More updates to joint fabric-forge build
This commit is contained in:
parent
e6ace77c39
commit
cf6a14f5d9
|
|
@ -1,3 +0,0 @@
|
|||
<component name="DependencyValidationManager">
|
||||
<scope name="Fabric sources" pattern="!ext[Gradle: cpw.mods:*:*]:*/&&!ext[Gradle: mezz.jei:*:*:*]:*/&&!ext[Gradle: net.jodah:typetools:*]:*/&&!ext[Gradle: net.minecraft:client:extra:*]:*/&&!ext[Gradle: net.minecraft:joined*:*]:*/&&!ext[Gradle: net.minecraft:mappings_official:zip:*]:*/&&!ext[Gradle: net.minecraftforge:*:*]:*/" />
|
||||
</component>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<component name="DependencyValidationManager">
|
||||
<scope name="Forge sources" pattern="!ext[Gradle: loom_mappings_*:*:*]:*/&&!ext[Gradle: net.fabricmc:*:*]:*/&&!ext[Gradle: net.minecraft:joined*:*]:*/&&!ext[Gradle: net.minecraft:mappings_official:zip:*]:*/&&!ext[Gradle: net.minecraft:minecraft-project-*:*]:*/" />
|
||||
</component>
|
||||
|
|
@ -2,10 +2,20 @@ package tschipp.carryon;
|
|||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import tschipp.carryon.common.config.CarryConfig;
|
||||
import tschipp.carryon.config.ConfigLoader;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String MOD_ID = "carryon";
|
||||
public static final String MOD_NAME = "Carry On";
|
||||
public static final Logger LOG = LoggerFactory.getLogger(MOD_NAME);
|
||||
|
||||
public static final CarryConfig.Common COMMON_CONFIG = new CarryConfig.Common();
|
||||
public static final CarryConfig.Client CLIENT_CONFIG = new CarryConfig.Client();
|
||||
|
||||
static {
|
||||
ConfigLoader.registerConfig(COMMON_CONFIG);
|
||||
ConfigLoader.registerConfig(CLIENT_CONFIG);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,27 +5,36 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
|||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import tschipp.carryon.Constants;
|
||||
import tschipp.carryon.common.carry.CarryOnData;
|
||||
import tschipp.carryon.common.carry.CarryOnData.CarryType;
|
||||
import tschipp.carryon.common.carry.CarryOnDataManager;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class CarriedObjectRender
|
||||
{
|
||||
|
||||
public static boolean drawFirstPerson(Player player, MultiBufferSource buffer, PoseStack matrix, int light)
|
||||
public static boolean drawFirstPerson(Player player, MultiBufferSource buffer, PoseStack matrix, int light, float partialTicks)
|
||||
{
|
||||
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
||||
if(carry.isCarrying(CarryType.BLOCK))
|
||||
drawFirstPersonBlock(player, buffer, matrix, light, carry.getBlock());
|
||||
else
|
||||
;
|
||||
else if (carry.isCarrying(CarryType.ENTITY))
|
||||
drawFirstPersonEntity(player, buffer, matrix, light, carry.getEntity(player.level), partialTicks);
|
||||
|
||||
return carry.isCarrying();
|
||||
}
|
||||
|
|
@ -39,8 +48,7 @@ public class CarriedObjectRender
|
|||
RenderSystem.disableCull();
|
||||
int perspective = CarryRenderHelper.getPerspective();
|
||||
|
||||
//TODO: FacePlayer config
|
||||
if (isChest(state.getBlock())) {
|
||||
if (Constants.CLIENT_CONFIG.facePlayer && isChest(state.getBlock())) {
|
||||
matrix.mulPose(Vector3f.YP.rotationDegrees(180));
|
||||
matrix.mulPose(Vector3f.XN.rotationDegrees(8));
|
||||
} else {
|
||||
|
|
@ -74,8 +82,76 @@ public class CarriedObjectRender
|
|||
matrix.popPose();
|
||||
}
|
||||
|
||||
private static void drawFirstPersonEntity(Player player, MultiBufferSource buffer, PoseStack matrix, int light, Entity entity, float partialTicks) {
|
||||
EntityRenderDispatcher manager = Minecraft.getInstance().getEntityRenderDispatcher();
|
||||
|
||||
public static boolean isChest(Block block)
|
||||
if (entity != null)
|
||||
{
|
||||
Vec3 playerpos = CarryRenderHelper.getExactPos(player, partialTicks);
|
||||
|
||||
entity.setPos(playerpos.x, playerpos.y, playerpos.z);
|
||||
entity.xRotO = 0.0f;
|
||||
entity.yRotO = 0.0f;
|
||||
entity.setYHeadRot(0.0f);
|
||||
|
||||
float height = entity.getBbHeight();
|
||||
float width = entity.getBbWidth();
|
||||
|
||||
matrix.pushPose();
|
||||
matrix.scale(0.8f, 0.8f, 0.8f);
|
||||
matrix.mulPose(Vector3f.YP.rotationDegrees(180));
|
||||
matrix.translate(0.0, -height - .1, width + 0.1);
|
||||
|
||||
// RenderSystem.enableAlphaTest();
|
||||
|
||||
// Lighting.en
|
||||
manager.setRenderShadow(false);
|
||||
|
||||
//TODO: Scripts
|
||||
/*
|
||||
CarryOnOverride carryOverride = ScriptChecker.getOverride(player);
|
||||
if (carryOverride != null)
|
||||
{
|
||||
CarryRenderHelper.performOverrideTransformation(matrix, carryOverride);
|
||||
|
||||
String entityname = carryOverride.getRenderNameEntity();
|
||||
if (entityname != null)
|
||||
{
|
||||
Entity newEntity = null;
|
||||
|
||||
Optional<EntityType<?>> type = EntityType.byString(entityname);
|
||||
if (type.isPresent())
|
||||
newEntity = type.get().create(level);
|
||||
|
||||
if (newEntity != null)
|
||||
{
|
||||
CompoundTag nbttag = carryOverride.getRenderNBT();
|
||||
if (nbttag != null)
|
||||
newEntity.deserializeNBT(nbttag);
|
||||
entity = newEntity;
|
||||
entity.setPos(playerpos.x, playerpos.y, playerpos.z);
|
||||
entity.xRotO = 0.0f;
|
||||
entity.yRotO = 0.0f;
|
||||
entity.setYHeadRot(0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if (entity instanceof LivingEntity)
|
||||
((LivingEntity) entity).hurtTime = 0;
|
||||
|
||||
manager.render(entity, 0, 0, 0, 0f, 0, matrix, buffer, light);
|
||||
manager.setRenderShadow(true);
|
||||
}
|
||||
|
||||
// RenderSystem.disableAlphaTest();
|
||||
matrix.popPose();
|
||||
}
|
||||
|
||||
|
||||
private static boolean isChest(Block block)
|
||||
{
|
||||
return block == Blocks.CHEST || block == Blocks.ENDER_CHEST || block == Blocks.TRAPPED_CHEST;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@ import net.minecraft.client.renderer.entity.ItemRenderer;
|
|||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Pose;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
|
@ -36,6 +39,87 @@ public class CarryRenderHelper
|
|||
return Vector3f.YP.rotationDegrees(getExactBodyRotationDegrees(entity, partialticks));
|
||||
}
|
||||
|
||||
public static void applyGeneralTransformations(Player player, float partialticks, PoseStack matrix)
|
||||
{
|
||||
int perspective = CarryRenderHelper.getPerspective();
|
||||
Quaternion playerrot = CarryRenderHelper.getExactBodyRotation(player, partialticks);
|
||||
Vec3 playerpos = CarryRenderHelper.getExactPos(player, partialticks);
|
||||
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
|
||||
Vec3 offset = playerpos.subtract(cameraPos);
|
||||
Pose pose = player.getPose();
|
||||
|
||||
matrix.pushPose();
|
||||
matrix.translate(offset.x, offset.y, offset.z);
|
||||
|
||||
if (perspective == 2)
|
||||
playerrot.mul(Vector3f.YP.rotationDegrees(180));
|
||||
matrix.mulPose(playerrot);
|
||||
|
||||
matrix.pushPose();
|
||||
matrix.scale(0.6f, 0.6f, 0.6f);
|
||||
|
||||
if (perspective == 2)
|
||||
matrix.translate(0, 0, -1.35);
|
||||
|
||||
if (doSneakCheck(player))
|
||||
{
|
||||
matrix.translate(0, -0.4, 0);
|
||||
}
|
||||
|
||||
if (pose == Pose.SWIMMING)
|
||||
{
|
||||
float f = player.getSwimAmount(partialticks);
|
||||
float f3 = player.isInWater() ? -90.0F - player.xRotO : -90.0F;
|
||||
float f4 = Mth.lerp(f, 0.0F, f3);
|
||||
if (perspective == 2)
|
||||
{
|
||||
matrix.translate(0, 0, 1.35);
|
||||
matrix.mulPose(Vector3f.XP.rotationDegrees(f4));
|
||||
}
|
||||
else
|
||||
matrix.mulPose(Vector3f.XN.rotationDegrees(f4));
|
||||
|
||||
matrix.translate(0, -1.5, -1.848);
|
||||
if (perspective == 2)
|
||||
matrix.translate(0, 0, 2.38);
|
||||
}
|
||||
|
||||
if (pose == Pose.FALL_FLYING)
|
||||
{
|
||||
float f1 = player.getFallFlyingTicks() + partialticks;
|
||||
float f2 = Mth.clamp(f1 * f1 / 100.0F, 0.0F, 1.0F);
|
||||
if (!player.isAutoSpinAttack())
|
||||
{
|
||||
if (perspective == 2)
|
||||
matrix.translate(0, 0, 1.35);
|
||||
|
||||
if (perspective == 2)
|
||||
matrix.mulPose(Vector3f.XP.rotationDegrees(f2 * (-90.0F - player.xRotO)));
|
||||
else
|
||||
matrix.mulPose(Vector3f.XN.rotationDegrees(f2 * (-90.0F - player.xRotO)));
|
||||
}
|
||||
|
||||
Vec3 Vector3d = player.getViewVector(partialticks);
|
||||
Vec3 Vector3d1 = player.getDeltaMovement();
|
||||
double d0 = Vector3d1.horizontalDistanceSqr();
|
||||
double d1 = Vector3d1.horizontalDistanceSqr();
|
||||
if (d0 > 0.0D && d1 > 0.0D)
|
||||
{
|
||||
double d2 = (Vector3d1.x * Vector3d.x + Vector3d1.z * Vector3d.z) / (Math.sqrt(d0) * Math.sqrt(d1));
|
||||
double d3 = Vector3d1.x * Vector3d.z - Vector3d1.z * Vector3d.x;
|
||||
|
||||
matrix.mulPose(Vector3f.YP.rotation((float) (Math.signum(d3) * Math.acos(d2))));
|
||||
}
|
||||
|
||||
if (perspective != 2)
|
||||
matrix.translate(0, 0, -1.35);
|
||||
matrix.translate(0, -0.2, 0);
|
||||
}
|
||||
|
||||
matrix.translate(0, 1.6, 0.65);
|
||||
}
|
||||
|
||||
|
||||
//TODO: Scripting
|
||||
// public static void performOverrideTransformation(PoseStack matrix, CarryOnOverride override)
|
||||
// {
|
||||
|
|
@ -84,4 +168,12 @@ public class CarryRenderHelper
|
|||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
public static boolean doSneakCheck(Player player)
|
||||
{
|
||||
if (player.getAbilities().flying)
|
||||
return false;
|
||||
|
||||
return player.isShiftKeyDown() || player.isCrouching();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,194 @@
|
|||
package tschipp.carryon.common.carry;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import tschipp.carryon.Constants;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ListHandler {
|
||||
|
||||
private static Set<String> FORBIDDEN_TILES = new HashSet<>();
|
||||
private static Set<String> FORBIDDEN_ENTITIES = new HashSet<>();
|
||||
private static Set<String> ALLOWED_ENTITIES = new HashSet<>();
|
||||
private static Set<String> ALLOWED_TILES = new HashSet<>();
|
||||
private static Set<String> FORBIDDEN_STACKING = new HashSet<>();
|
||||
private static Set<String> ALLOWED_STACKING = new HashSet<>();
|
||||
|
||||
private static List<TagKey<Block>> FORBIDDEN_TILES_TAGS = new ArrayList<>();
|
||||
private static List<TagKey<EntityType<?>>> FORBIDDEN_ENTITIES_TAGS = new ArrayList<>();
|
||||
private static List<TagKey<EntityType<?>>> ALLOWED_ENTITIES_TAGS = new ArrayList<>();
|
||||
private static List<TagKey<Block>> ALLOWED_TILES_TAGS = new ArrayList<>();
|
||||
private static List<TagKey<EntityType<?>>> FORBIDDEN_STACKING_TAGS = new ArrayList<>();
|
||||
private static List<TagKey<EntityType<?>>> ALLOWED_STACKING_TAGS = new ArrayList<>();
|
||||
|
||||
|
||||
private static Set<Class<?>> PROPERTY_EXCEPTION_CLASSES = new HashSet<>();
|
||||
|
||||
|
||||
public static boolean isPermitted(Block block)
|
||||
{
|
||||
if(Constants.COMMON_CONFIG.settings.useWhitelistBlocks)
|
||||
return doCheck(block, ALLOWED_TILES, ALLOWED_TILES_TAGS);
|
||||
else
|
||||
return !doCheck(block, FORBIDDEN_TILES, FORBIDDEN_TILES_TAGS);
|
||||
}
|
||||
|
||||
public static boolean isPermitted(Entity entity)
|
||||
{
|
||||
if(Constants.COMMON_CONFIG.settings.useWhitelistEntities)
|
||||
return doCheck(entity, ALLOWED_ENTITIES, ALLOWED_ENTITIES_TAGS);
|
||||
else
|
||||
return !doCheck(entity, FORBIDDEN_ENTITIES, FORBIDDEN_ENTITIES_TAGS);
|
||||
}
|
||||
|
||||
public static boolean isStackingPermitted(Entity entity)
|
||||
{
|
||||
if(Constants.COMMON_CONFIG.settings.useWhitelistStacking)
|
||||
return doCheck(entity, ALLOWED_STACKING, ALLOWED_STACKING_TAGS);
|
||||
else
|
||||
return !doCheck(entity, FORBIDDEN_STACKING, FORBIDDEN_STACKING_TAGS);
|
||||
}
|
||||
|
||||
public static boolean isPropertyException(Property<?> prop)
|
||||
{
|
||||
return PROPERTY_EXCEPTION_CLASSES.contains(prop.getValueClass());
|
||||
}
|
||||
|
||||
private static boolean doCheck(Block block, Set<String> regular, List<TagKey<Block>> tags)
|
||||
{
|
||||
String name = Registry.BLOCK.getKey(block).toString();
|
||||
if(regular.contains(name))
|
||||
return true;
|
||||
for(TagKey<Block> tag : tags)
|
||||
if(block.defaultBlockState().is(tag))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean doCheck(Entity entity, Set<String> regular, List<TagKey<EntityType<?>>> tags)
|
||||
{
|
||||
String name = Registry.ENTITY_TYPE.getKey(entity.getType()).toString();
|
||||
if(regular.contains(name))
|
||||
return true;
|
||||
for(TagKey<EntityType<?>> tag : tags)
|
||||
if(entity.getType().is(tag))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void initConfigLists()
|
||||
{
|
||||
FORBIDDEN_ENTITIES.clear();
|
||||
FORBIDDEN_ENTITIES_TAGS.clear();
|
||||
FORBIDDEN_STACKING.clear();
|
||||
FORBIDDEN_STACKING_TAGS.clear();
|
||||
FORBIDDEN_TILES.clear();
|
||||
FORBIDDEN_TILES_TAGS.clear();
|
||||
ALLOWED_ENTITIES.clear();
|
||||
ALLOWED_ENTITIES_TAGS.clear();
|
||||
ALLOWED_STACKING.clear();
|
||||
ALLOWED_STACKING_TAGS.clear();
|
||||
ALLOWED_TILES.clear();
|
||||
ALLOWED_TILES_TAGS.clear();
|
||||
PROPERTY_EXCEPTION_CLASSES.clear();
|
||||
|
||||
Map<ResourceLocation, TagKey<Block>> blocktags = Registry.BLOCK.getTagNames().collect(Collectors.toMap(t -> t.location(), t -> t));
|
||||
Map<ResourceLocation, TagKey<EntityType<?>>> entitytags = Registry.ENTITY_TYPE.getTagNames().collect(Collectors.toMap(t -> t.location(), t -> t));
|
||||
|
||||
List<String> forbidden = new ArrayList<>(List.of(Constants.COMMON_CONFIG.blacklist.forbiddenTiles));
|
||||
forbidden.add("#carryon:block_blacklist");
|
||||
addWithWildcards(forbidden, FORBIDDEN_TILES, Registry.BLOCK, blocktags, FORBIDDEN_TILES_TAGS);
|
||||
|
||||
List<String> forbiddenEntity = new ArrayList<>(List.of(Constants.COMMON_CONFIG.blacklist.forbiddenEntities));
|
||||
forbiddenEntity.add("#carryon:entity_blacklist");
|
||||
addWithWildcards(forbiddenEntity, FORBIDDEN_ENTITIES, Registry.ENTITY_TYPE, entitytags, FORBIDDEN_ENTITIES_TAGS);
|
||||
|
||||
List<String> allowedEntities = new ArrayList<>(List.of(Constants.COMMON_CONFIG.whitelist.allowedEntities));
|
||||
allowedEntities.add("#carryon:entity_whitelist");
|
||||
addWithWildcards(allowedEntities, ALLOWED_ENTITIES, Registry.ENTITY_TYPE, entitytags, ALLOWED_ENTITIES_TAGS);
|
||||
|
||||
List<String> allowedBlocks = new ArrayList<>(List.of(Constants.COMMON_CONFIG.whitelist.allowedBlocks));
|
||||
allowedBlocks.add("#carryon:block_whitelist");
|
||||
addWithWildcards(allowedBlocks, ALLOWED_TILES, Registry.BLOCK, blocktags, ALLOWED_TILES_TAGS);
|
||||
|
||||
List<String> forbiddenStacking = new ArrayList<>(List.of(Constants.COMMON_CONFIG.blacklist.forbiddenStacking));
|
||||
forbiddenStacking.add("#carryon:stacking_blacklist");
|
||||
addWithWildcards(forbiddenStacking, FORBIDDEN_STACKING, Registry.ENTITY_TYPE, entitytags, FORBIDDEN_STACKING_TAGS);
|
||||
|
||||
List<String> allowedStacking = new ArrayList<>(List.of(Constants.COMMON_CONFIG.whitelist.allowedStacking));
|
||||
allowedStacking.add("#carryon:stacking_whitelist");
|
||||
addWithWildcards(allowedStacking, ALLOWED_STACKING, Registry.ENTITY_TYPE, entitytags, ALLOWED_STACKING_TAGS);
|
||||
|
||||
for(String propString : Constants.COMMON_CONFIG.settings.placementStateExceptions)
|
||||
{
|
||||
if(!propString.contains("[") || !propString.contains("]"))
|
||||
continue;
|
||||
String name = propString.substring(0, propString.indexOf("["));
|
||||
String propName = propString.substring(propString.indexOf("[") + 1, propString.indexOf("]"));
|
||||
Block blk = Registry.BLOCK.get(new ResourceLocation(name));
|
||||
for(Property<?> prop : blk.defaultBlockState().getProperties())
|
||||
{
|
||||
if(prop.getName().equals(propName))
|
||||
PROPERTY_EXCEPTION_CLASSES.add(prop.getValueClass());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static <T> void addTag(String tag, Map<ResourceLocation, TagKey<T>> tagMap, List<TagKey<T>> tags) {
|
||||
String sub = tag.substring(1);
|
||||
TagKey<T> t = tagMap.get(new ResourceLocation(sub));
|
||||
if (t != null)
|
||||
tags.add(t);
|
||||
}
|
||||
|
||||
private static <T> void addWithWildcards(List<String> entries, Set<String> toAddTo, Registry<T> registry, Map<ResourceLocation, TagKey<T>> tags, List<TagKey<T>> toAddTags) {
|
||||
|
||||
ResourceLocation[] keys = registry.keySet().toArray(new ResourceLocation[0]);
|
||||
for (int i = 0; i < entries.size(); i++)
|
||||
{
|
||||
String curr = entries.get(i);
|
||||
if (!curr.startsWith("#"))
|
||||
{
|
||||
if (curr.contains("*"))
|
||||
{
|
||||
String[] filter = curr.replace("*", ",").split(",");
|
||||
|
||||
for (ResourceLocation key : keys)
|
||||
{
|
||||
if (containsAll(key.toString(), filter))
|
||||
{
|
||||
toAddTo.add(key.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
toAddTo.add(curr);
|
||||
}
|
||||
else
|
||||
addTag(curr, tags, toAddTags);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsAll(String str, String... strings)
|
||||
{
|
||||
boolean containsAll = true;
|
||||
|
||||
for (String s : strings)
|
||||
{
|
||||
if (!str.contains(s))
|
||||
containsAll = false;
|
||||
}
|
||||
|
||||
return containsAll;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
package tschipp.carryon.common.carry;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.AgeableMob;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.Entity.RemovalReason;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.entity.TamableAnimal;
|
||||
import net.minecraft.world.entity.animal.Animal;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
|
@ -15,15 +18,12 @@ import net.minecraft.world.level.Level;
|
|||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import tschipp.carryon.Constants;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PickupHandler {
|
||||
|
||||
//TODO: CONFIG
|
||||
private static final double range = 2.0;
|
||||
|
||||
|
||||
public static boolean canCarryGeneral(ServerPlayer player, Vec3 pos)
|
||||
{
|
||||
//TODO: Check carry key
|
||||
|
|
@ -33,13 +33,14 @@ public class PickupHandler {
|
|||
if(!player.getMainHandItem().isEmpty() || !player.getOffhandItem().isEmpty())
|
||||
return false;
|
||||
|
||||
if(player.position().distanceTo(pos) >= range)
|
||||
if(player.position().distanceTo(pos) > Constants.COMMON_CONFIG.settings.maxDistance)
|
||||
return false;
|
||||
|
||||
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
||||
if(carry.isCarrying())
|
||||
return false;
|
||||
|
||||
//Needed so that we don't pick up and place in the same tick
|
||||
if(player.tickCount == carry.getTick())
|
||||
return false;
|
||||
|
||||
|
|
@ -47,6 +48,7 @@ public class PickupHandler {
|
|||
return false;
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -56,12 +58,33 @@ public class PickupHandler {
|
|||
if(!canCarryGeneral(player, Vec3.atCenterOf(pos)))
|
||||
return false;
|
||||
|
||||
//TODO: Whitelist/Blacklist checks
|
||||
|
||||
|
||||
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
||||
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
BlockState state = level.getBlockState(pos);
|
||||
|
||||
if(!ListHandler.isPermitted(state.getBlock()))
|
||||
return false;
|
||||
|
||||
if(state.getDestroySpeed(level, pos) == -1 && !player.isCreative())
|
||||
return false;
|
||||
|
||||
if(blockEntity == null && !Constants.COMMON_CONFIG.settings.pickupAllBlocks)
|
||||
return false;
|
||||
|
||||
//Check if TE is locked
|
||||
if(blockEntity != null)
|
||||
{
|
||||
CompoundTag nbt = blockEntity.saveWithId();
|
||||
if(nbt.contains("Lock") && !nbt.getString("Lock").equals(""))
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: Script conditions
|
||||
|
||||
//TODO: Gamestages conditions check
|
||||
|
||||
//TODO: Protections
|
||||
|
||||
carry.setBlock(state, blockEntity);
|
||||
|
||||
level.removeBlockEntity(pos);
|
||||
|
|
@ -94,19 +117,37 @@ public class PickupHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (entity instanceof Animal)
|
||||
((Animal) entity).dropLeash(true, true);
|
||||
if(!ListHandler.isPermitted(entity))
|
||||
{
|
||||
//We can pick up baby animals even if the grown up animal is blacklisted.
|
||||
if(!(entity instanceof AgeableMob ageableMob && Constants.COMMON_CONFIG.settings.allowBabies && (ageableMob.getAge() < 0 || ageableMob.isBaby())))
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: White and blacklist
|
||||
//Non-Creative only guards
|
||||
if(!player.isCreative())
|
||||
{
|
||||
if(!Constants.COMMON_CONFIG.settings.pickupHostileMobs && entity.getType().getCategory() == MobCategory.MONSTER)
|
||||
return false;
|
||||
|
||||
if(Constants.COMMON_CONFIG.settings.maxEntityHeight > entity.getBbHeight() || Constants.COMMON_CONFIG.settings.maxEntityWidth > entity.getBbWidth())
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: Script conditions
|
||||
|
||||
//TODO: Gamestages conditions check
|
||||
|
||||
//TODO: Protections
|
||||
|
||||
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
||||
|
||||
|
||||
entity.ejectPassengers();
|
||||
if (entity instanceof Animal animal)
|
||||
animal.dropLeash(true, true);
|
||||
|
||||
carry.setEntity(entity);
|
||||
entity.remove(RemovalReason.DISCARDED);
|
||||
entity.remove(RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
|
||||
player.level.playSound(null, player.getOnPos(), SoundEvents.ARMOR_EQUIP_GENERIC, SoundSource.AMBIENT, 1.0f, 0.5f);
|
||||
CarryOnDataManager.setCarryData(player, carry);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package tschipp.carryon.common.carry;
|
|||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
|
|
@ -16,7 +15,6 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
|||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
|
@ -55,7 +53,7 @@ public class PlacementHandler
|
|||
return false;
|
||||
|
||||
state = getPlacementState(state, player, context, pos);
|
||||
boolean doPlace = placementCallback == null ? true : placementCallback.apply(pos, state);
|
||||
boolean doPlace = placementCallback == null || placementCallback.apply(pos, state);
|
||||
|
||||
if (!doPlace)
|
||||
return false;
|
||||
|
|
@ -80,12 +78,12 @@ public class PlacementHandler
|
|||
if (prop instanceof DirectionProperty) {
|
||||
state = updateProperty(state, placementState, prop);
|
||||
}
|
||||
if (prop instanceof EnumProperty<?>) {
|
||||
if (state.getValue(prop) instanceof Axis)
|
||||
state = updateProperty(state, placementState, prop);
|
||||
if (prop.getValueClass() == Direction.Axis.class) {
|
||||
state = updateProperty(state, placementState, prop);
|
||||
}
|
||||
//TODO: Add config for state variant names, which should be taken from the placementState
|
||||
if (prop.getName().equals("type")) {
|
||||
|
||||
//This is needed for certain blocks, otherwise we get problems like chests not connecting
|
||||
if (ListHandler.isPropertyException(prop)) {
|
||||
state = updateProperty(state, placementState, prop);
|
||||
}
|
||||
}
|
||||
|
|
@ -100,7 +98,7 @@ public class PlacementHandler
|
|||
return state;
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>, V extends T> BlockState updateProperty(BlockState state, BlockState otherState, Property<T> prop)
|
||||
private static <T extends Comparable<T>> BlockState updateProperty(BlockState state, BlockState otherState, Property<T> prop)
|
||||
{
|
||||
var val = otherState.getValue(prop);
|
||||
return state.setValue(prop, val);
|
||||
|
|
@ -127,7 +125,7 @@ public class PlacementHandler
|
|||
Entity entity = carry.getEntity(level);
|
||||
entity.setPos(placementPos);
|
||||
|
||||
boolean doPlace = placementCallback == null ? true : placementCallback.apply(placementPos, entity);
|
||||
boolean doPlace = placementCallback == null || placementCallback.apply(placementPos, entity);
|
||||
if (!doPlace)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,311 @@
|
|||
package tschipp.carryon.common.config;
|
||||
|
||||
import tschipp.carryon.config.PropertyType;
|
||||
import tschipp.carryon.config.annotations.Category;
|
||||
import tschipp.carryon.config.annotations.Config;
|
||||
import tschipp.carryon.config.annotations.Property;
|
||||
|
||||
public class CarryConfig {
|
||||
|
||||
@Config("carryon-common")
|
||||
public static class Common {
|
||||
//Settings
|
||||
@Property(
|
||||
type = PropertyType.CATEGORY,
|
||||
description = "General Settings"
|
||||
)
|
||||
public Settings settings = new Settings();
|
||||
|
||||
@Category("settings")
|
||||
public static class Settings {
|
||||
@Property(
|
||||
type = PropertyType.DOUBLE,
|
||||
description = "Maximum distance from where Blocks and Entities can be picked up",
|
||||
minD = 0
|
||||
)
|
||||
public double maxDistance = 2.5;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.DOUBLE,
|
||||
description = "Max width of entities that can be picked up in survival mode",
|
||||
minD = 0,
|
||||
maxD = 10
|
||||
)
|
||||
public double maxEntityWidth = 1.5;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.DOUBLE,
|
||||
description = "Max height of entities that can be picked up in survival mode",
|
||||
minD = 0,
|
||||
maxD = 10
|
||||
)
|
||||
public double maxEntityHeight = 2.5;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.DOUBLE,
|
||||
description = "Slowness multiplier for blocks",
|
||||
minD = 0
|
||||
)
|
||||
public double blockSlownessMultiplier = 1;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.DOUBLE,
|
||||
description = "Slowness multiplier for entities",
|
||||
minD = 0
|
||||
)
|
||||
public double entitySlownessMultiplier = 1;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.INT,
|
||||
description = "Maximum stack limit for entities",
|
||||
min = 1
|
||||
)
|
||||
public int maxEntityStackLimit = 10;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "More complex Tile Entities slow down the player more"
|
||||
)
|
||||
public boolean heavyTiles = true;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Allow all blocks to be picked up, not just Tile Entites. White/Blacklist will still be respected."
|
||||
)
|
||||
public boolean pickupAllBlocks = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Whether Blocks and Entities slow the creative player down when carried"
|
||||
)
|
||||
public boolean slownessInCreative = true;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Whether hostile mobs should be able to picked up in survival mode"
|
||||
)
|
||||
public boolean pickupHostileMobs = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Larger Entities slow down the player more"
|
||||
)
|
||||
public boolean heavyEntities = true;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Allow babies to be carried even when adult mob is blacklisted (or not whitelisted)"
|
||||
)
|
||||
public boolean allowBabies = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Use Whitelist instead of Blacklist for Blocks"
|
||||
)
|
||||
public boolean useWhitelistBlocks = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Use Whitelist instead of Blacklist for Entities"
|
||||
)
|
||||
public boolean useWhitelistEntities = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Use Whitelist instead of Blacklist for Stacking"
|
||||
)
|
||||
public boolean useWhitelistStacking = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Whether the player can hit blocks and entities while carrying or not"
|
||||
)
|
||||
public boolean hitWhileCarrying = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Whether the player drops the carried object when hit or not"
|
||||
)
|
||||
public boolean dropCarriedWhenHit = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Use custom Pickup Scripts. Having this set to false, will not allow you to run scripts, but will increase your performance"
|
||||
)
|
||||
public boolean useScripts = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Allows entities to be stacked on top of each other"
|
||||
)
|
||||
public boolean stackableEntities = true;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Whether entities' size matters when stacking or not. This means that larger entities cannot be stacked on smaller ones"
|
||||
)
|
||||
public boolean entitySizeMattersStacking = true;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Usually all the block state information is retained when placing a block that was picked up. But some information is changed to a modified property, like rotation or orientation. In this list, add additional properties that should NOT be saved and instead be updated when placed. Format: modid:block[propertyname]. Note: You don't need to add an entry for every subtype of a same block. For example, we only add an entry for one type of slab, but the change is applied to all slabs."
|
||||
)
|
||||
public String[] placementStateExceptions = {
|
||||
"minecraft:chest[type]"
|
||||
};
|
||||
}
|
||||
|
||||
@Property(
|
||||
type = PropertyType.CATEGORY,
|
||||
description = "Whitelist. Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Black---and-Whitelist-Config"
|
||||
)
|
||||
|
||||
//Whitelist
|
||||
public Whitelist whitelist = new Whitelist();
|
||||
@Category("whitelist")
|
||||
public static class Whitelist {
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Entities that CAN be picked up (useWhitelistEntities must be true)"
|
||||
)
|
||||
public String[] allowedEntities = {};
|
||||
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Blocks that CAN be picked up (useWhitelistBlocks must be true)"
|
||||
)
|
||||
public String[] allowedBlocks = {};
|
||||
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Entities that CAN have other entities stacked on top of them (useWhitelistStacking must be true)"
|
||||
)
|
||||
public String[] allowedStacking = {};
|
||||
}
|
||||
|
||||
//Blacklist
|
||||
@Property(
|
||||
type = PropertyType.CATEGORY,
|
||||
description = "Blacklist. Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Black---and-Whitelist-Config"
|
||||
)
|
||||
public Blacklist blacklist = new Blacklist();
|
||||
@Category("blacklist")
|
||||
public static class Blacklist {
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Blocks that cannot be picked up"
|
||||
)
|
||||
public String[] forbiddenTiles = {
|
||||
"#forge:immovable", "#forge:relocation_not_supported", "minecraft:end_portal",
|
||||
"minecraft:end_gateway", "minecraft:tall_grass", "minecraft:large_fern", "minecraft:peony",
|
||||
"minecraft:rose_bush", "minecraft:lilac", "minecraft:sunflower", "minecraft:*_bed",
|
||||
"minecraft:*_door", "minecraft:big_dripleaf_stem", "minecraft:waterlily", "minecraft:cake",
|
||||
"minecraft:nether_portal", "minecraft:tall_seagrass", "animania:block_trough",
|
||||
"animania:block_invisiblock", "colossalchests:*", "ic2:*", "bigreactors:*", "forestry:*",
|
||||
"tconstruct:*", "rustic:*", "botania:*", "astralsorcery:*", "quark:colored_bed_*",
|
||||
"immersiveengineering:*", "embers:block_furnace", "embers:ember_bore",
|
||||
"embers:ember_activator", "embers:mixer", "embers:heat_coil", "embers:large_tank",
|
||||
"embers:crystal_cell", "embers:alchemy_pedestal", "embers:boiler", "embers:combustor",
|
||||
"embers:catalzyer", "embers:field_chart", "embers:inferno_forge",
|
||||
"storagedrawers:framingtable", "skyresources:*", "lootbags:*", "exsartagine:*",
|
||||
"aquamunda:tank", "opencomputers:*", "malisisdoors:*", "industrialforegoing:*",
|
||||
"minecolonies:*", "thaumcraft:pillar*", "thaumcraft:infernal_furnace",
|
||||
"thaumcraft:placeholder*", "thaumcraft:infusion_matrix", "thaumcraft:golem_builder",
|
||||
"thaumcraft:thaumatorium*", "magneticraft:oil_heater", "magneticraft:solar_panel",
|
||||
"magneticraft:steam_engine", "magneticraft:shelving_unit", "magneticraft:grinder",
|
||||
"magneticraft:sieve", "magneticraft:solar_tower", "magneticraft:solar_mirror",
|
||||
"magneticraft:container", "magneticraft:pumpjack", "magneticraft:solar_panel",
|
||||
"magneticraft:refinery", "magneticraft:oil_heater", "magneticraft:hydraulic_press",
|
||||
"magneticraft:multiblock_gap", "refinedstorage:*", "mcmultipart:*", "enderstorage:*",
|
||||
"betterstorage:*", "practicallogistics2:*", "wearablebackpacks:*", "rftools:screen",
|
||||
"rftools:creative_screen", "create:*", "magic_doorknob:*", "iceandfire:*", "ftbquests:*",
|
||||
"waystones:*"
|
||||
};
|
||||
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Entities that cannot be picked up"
|
||||
)
|
||||
public String[] forbiddenEntities = {
|
||||
"minecraft:end_crystal", "minecraft:ender_dragon", "minecraft:ghast",
|
||||
"minecraft:shulker", "minecraft:leash_knot", "minecraft:armor_stand",
|
||||
"minecraft:item_frame", "minecraft:painting", "minecraft:shulker_bullet",
|
||||
"animania:hamster", "animania:ferret*", "animania:hedgehog*", "animania:cart",
|
||||
"animania:wagon", "mynko:*", "pixelmon:*", "mocreatures:*", "quark:totem", "vehicle:*"
|
||||
};
|
||||
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Entities that cannot have other entities stacked on top of them"
|
||||
)
|
||||
public String[] forbiddenStacking = {
|
||||
"minecraft:horse"
|
||||
};
|
||||
}
|
||||
|
||||
//Custom Pickup Conditions
|
||||
@Property(
|
||||
type = PropertyType.CATEGORY,
|
||||
description = "Custom Pickup Conditions. Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Custom-Pickup-Condition-Config"
|
||||
)
|
||||
public CustomPickupConditions customPickupConditions = new CustomPickupConditions();
|
||||
@Category("customPickupConditions")
|
||||
public static class CustomPickupConditions {
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Custom Pickup Conditions for Blocks"
|
||||
)
|
||||
public String[] customPickupConditionsBlocks = {};
|
||||
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Custom Pickup Conditions for Entities"
|
||||
)
|
||||
public String[] customPickupConditionsEntities = {};
|
||||
}
|
||||
}
|
||||
|
||||
@Config("carryon-client")
|
||||
public static class Client {
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "If the front of the Tile Entities should face the player or should face outward"
|
||||
)
|
||||
public boolean facePlayer = false;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.BOOLEAN,
|
||||
description = "Arms should render on sides when carrying. Set to false if you experience issues with mods that replace the player model (like MoBends, etc)"
|
||||
)
|
||||
public boolean renderArms = true;
|
||||
|
||||
@Property(
|
||||
type = PropertyType.STRING_ARRAY,
|
||||
description = "Model Overrides based on NBT or Meta. Advanced users only! Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Model-Override-Config"
|
||||
)
|
||||
public String[] modelOverrides = {
|
||||
"minecraft:hopper->(block)minecraft:hopper",
|
||||
"minecraft:comparator->(block)minecraft:comparator",
|
||||
"minecraft:repeater->(block)minecraft:repeater",
|
||||
"minecraft:cauldron->(block)minecraft:cauldron",
|
||||
"minecraft:brewing_stand->(item)minecraft:brewing_stand",
|
||||
"minecraft:flower_pot->(block)minecraft:flower_pot",
|
||||
"minecraft:sugar_cane->(block)minecraft:sugar_cane",
|
||||
"minecraft:redstone_wire->(item)minecraft:redstone",
|
||||
"animania:block_nest->(block)animania:block_nest",
|
||||
"animania:cheese_mold;0->(block)animania:cheese_mold;0",
|
||||
"animania:cheese_mold;1->(block)animania:cheese_mold;1",
|
||||
"animania:cheese_mold;2->(block)animania:cheese_mold;2",
|
||||
"animania:cheese_mold;3->(block)animania:cheese_mold;3",
|
||||
"animania:cheese_mold;4->(block)animania:cheese_mold;4",
|
||||
"animania:cheese_mold;5->(block)animania:cheese_mold;5",
|
||||
"animania:cheese_mold;6->(block)animania:cheese_mold;6",
|
||||
"animania:cheese_mold;7->(block)animania:cheese_mold;7",
|
||||
"animania:cheese_mold;8->(block)animania:cheese_mold;8",
|
||||
"animania:cheese_mold;9->(block)animania:cheese_mold;9",
|
||||
"animania:cheese_mold;10->(block)animania:cheese_mold;10"
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package tschipp.carryon.config;
|
||||
|
||||
|
||||
import tschipp.carryon.config.annotations.Property;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public record AnnotationData(
|
||||
PropertyType type,
|
||||
String description,
|
||||
int min, int max,
|
||||
double minD, double maxD
|
||||
) {
|
||||
|
||||
public static AnnotationData getData(Field field) {
|
||||
Property annotation = field.getAnnotation(Property.class);
|
||||
return new AnnotationData(
|
||||
annotation.type(),
|
||||
annotation.description(),
|
||||
annotation.min(), annotation.max(),
|
||||
annotation.minD(), annotation.maxD()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package tschipp.carryon.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class BuiltCategory {
|
||||
|
||||
public final List<PropertyData> properties = new ArrayList<>();
|
||||
public final List<BuiltCategory> categories = new ArrayList<>();
|
||||
|
||||
public final String categoryDesc;
|
||||
public final String category;
|
||||
|
||||
public BuiltCategory(String categoryDesc, String category) {
|
||||
this.categoryDesc = categoryDesc;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public Optional<PropertyData> getProperty(String id) {
|
||||
for (PropertyData property : properties) {
|
||||
if (property.getId().equals(id)) {
|
||||
return Optional.of(property);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public Optional<BuiltCategory> getCategory(String id) {
|
||||
for (BuiltCategory category : categories) {
|
||||
if (category.category.equals(id)) {
|
||||
return Optional.of(category);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
11
Common/src/main/java/tschipp/carryon/config/BuiltConfig.java
Normal file
11
Common/src/main/java/tschipp/carryon/config/BuiltConfig.java
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package tschipp.carryon.config;
|
||||
|
||||
public class BuiltConfig extends BuiltCategory {
|
||||
|
||||
public final String fileName;
|
||||
|
||||
public BuiltConfig(String fileName) {
|
||||
super(null, fileName);
|
||||
this.fileName = fileName;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package tschipp.carryon.config;
|
||||
|
||||
//Many Thanks to ThatGravyBoat for this template!
|
||||
|
||||
import tschipp.carryon.common.carry.ListHandler;
|
||||
import tschipp.carryon.config.annotations.Category;
|
||||
import tschipp.carryon.config.annotations.Config;
|
||||
import tschipp.carryon.config.annotations.Property;
|
||||
import tschipp.carryon.platform.Services;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class ConfigLoader {
|
||||
|
||||
public static void registerConfig(Object object) {
|
||||
BuiltCategory category;
|
||||
try {
|
||||
category = buildCategory(null, object);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
category = null;
|
||||
}
|
||||
if (category instanceof BuiltConfig config) {
|
||||
registerConfig(config);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Config supplied does not have a @Config annotation");
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerConfig(BuiltConfig config) {
|
||||
Services.PLATFORM.registerConfig(config);
|
||||
}
|
||||
|
||||
public static void onConfigLoaded() {
|
||||
ListHandler.initConfigLists();
|
||||
}
|
||||
|
||||
public static BuiltCategory buildCategory(String categoryDesc, Object object) throws IllegalAccessException {
|
||||
Class<?> configClass = object.getClass();
|
||||
BuiltCategory category;
|
||||
if (configClass.isAnnotationPresent(Config.class)) {
|
||||
category = new BuiltConfig(configClass.getAnnotation(Config.class).value());
|
||||
} else if (configClass.isAnnotationPresent(Category.class)) {
|
||||
category = new BuiltCategory(categoryDesc, configClass.getAnnotation(Category.class).value());
|
||||
} else {
|
||||
throw new IllegalStateException("Config does not contain any @Config annotation or @Category");
|
||||
}
|
||||
|
||||
for (Field field : configClass.getDeclaredFields()) {
|
||||
if (field.isAnnotationPresent(Property.class) && field.canAccess(object)) {
|
||||
PropertyType type = field.getAnnotation(Property.class).type();
|
||||
if (type.equals(PropertyType.CATEGORY)) {
|
||||
category.categories.add(buildCategory(field.getAnnotation(Property.class).description(), field.get(object)));
|
||||
} else {
|
||||
category.properties.add(new PropertyData(object, field, AnnotationData.getData(field)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package tschipp.carryon.config;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public record PropertyData(Object fieldClass, Field field, AnnotationData data) {
|
||||
|
||||
public String getId() {
|
||||
return field().getName();
|
||||
}
|
||||
|
||||
public boolean getBoolean() throws IllegalAccessException {
|
||||
return field().getBoolean(fieldClass());
|
||||
}
|
||||
|
||||
public void setBoolean(boolean _boolean) {
|
||||
try {
|
||||
field.setBoolean(fieldClass, _boolean);
|
||||
} catch (Exception e) {
|
||||
//Ignore
|
||||
}
|
||||
}
|
||||
|
||||
public int getInt() throws IllegalAccessException {
|
||||
return field().getInt(fieldClass());
|
||||
}
|
||||
|
||||
public void setInt(int _int) {
|
||||
try {
|
||||
field.setInt(fieldClass, _int);
|
||||
} catch (Exception e) {
|
||||
//Ignore
|
||||
}
|
||||
}
|
||||
|
||||
public double getDouble() throws IllegalAccessException {
|
||||
return field().getDouble(fieldClass());
|
||||
}
|
||||
|
||||
public void setDouble(double _double) {
|
||||
try {
|
||||
field.setDouble(fieldClass, _double);
|
||||
} catch (Exception e) {
|
||||
//Ignore
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getStringArray() throws IllegalAccessException {
|
||||
return (String[])field().get(fieldClass());
|
||||
}
|
||||
|
||||
public void setStringArray(String[] arr)
|
||||
{
|
||||
try {
|
||||
field.set(fieldClass, arr);
|
||||
} catch (Exception e) {
|
||||
//Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package tschipp.carryon.config;
|
||||
|
||||
public enum PropertyType {
|
||||
INT,
|
||||
DOUBLE,
|
||||
BOOLEAN,
|
||||
STRING_ARRAY,
|
||||
CATEGORY
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package tschipp.carryon.config.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Category {
|
||||
String value();
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package tschipp.carryon.config.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Config {
|
||||
String value();
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package tschipp.carryon.config.annotations;
|
||||
|
||||
import tschipp.carryon.config.PropertyType;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Property {
|
||||
|
||||
|
||||
|
||||
PropertyType type();
|
||||
String description();
|
||||
|
||||
int min() default Integer.MIN_VALUE;
|
||||
int max() default Integer.MAX_VALUE;
|
||||
|
||||
double minD() default Double.MIN_VALUE;
|
||||
double maxD() default Double.MAX_VALUE;
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package tschipp.carryon.mixin;
|
||||
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import tschipp.carryon.common.carry.CarryOnData;
|
||||
import tschipp.carryon.common.carry.CarryOnDataManager;
|
||||
|
||||
@Mixin(HumanoidModel.class)
|
||||
public class HumanoidModelMixin {
|
||||
|
||||
@Shadow
|
||||
public ModelPart rightArm;
|
||||
|
||||
@Shadow
|
||||
public ModelPart leftArm;
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V")
|
||||
private void onSetupAnimations(LivingEntity living, float f1, float f2, float f3, float f4, float f5, CallbackInfo ci)
|
||||
{
|
||||
System.out.println("Reached model injectiob");
|
||||
if(living instanceof Player player)
|
||||
{
|
||||
System.out.println("Model is player");
|
||||
|
||||
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
||||
if(carry.isCarrying() && !player.isVisuallySwimming() && !player.isFallFlying())
|
||||
{
|
||||
System.out.println("Player is carrying");
|
||||
|
||||
boolean sneaking = !player.getAbilities().flying && player.isShiftKeyDown() || player.isCrouching();
|
||||
|
||||
float x = 1.0f + (sneaking ? 0.2f : 0.0f) - (carry.isCarrying(CarryOnData.CarryType.BLOCK) ? 0.0f : 0.3f);
|
||||
float z = 0.15f;
|
||||
|
||||
rightArm.yRot = 0;
|
||||
leftArm.yRot = 0;
|
||||
|
||||
rightArm.xRot = -x;
|
||||
leftArm.xRot = -x;
|
||||
|
||||
rightArm.zRot = z;
|
||||
leftArm.zRot = -z;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ public abstract class PlayerMixin extends LivingEntity {
|
|||
@Inject(method = "defineSynchedData()V", at = @At("RETURN"))
|
||||
private void onDefineSynchedData(CallbackInfo info) {
|
||||
this.entityData.define(CarryOnDataManager.CARRY_DATA_KEY, new CompoundTag());
|
||||
System.out.println("Added Carry Data!");
|
||||
}
|
||||
|
||||
@Inject(method = "addAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V", at = @At("RETURN"))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package tschipp.carryon.platform.services;
|
||||
|
||||
import tschipp.carryon.config.BuiltConfig;
|
||||
|
||||
public interface IPlatformHelper {
|
||||
|
||||
/**
|
||||
|
|
@ -23,4 +25,6 @@ public interface IPlatformHelper {
|
|||
* @return True if in a development environment, false otherwise.
|
||||
*/
|
||||
boolean isDevelopmentEnvironment();
|
||||
|
||||
void registerConfig(BuiltConfig cfg);
|
||||
}
|
||||
|
|
|
|||
BIN
Common/src/main/resources/assets/carryon/logo.png
Normal file
BIN
Common/src/main/resources/assets/carryon/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 170 KiB |
|
|
@ -8,7 +8,8 @@
|
|||
"PlayerMixin"
|
||||
],
|
||||
"client": [
|
||||
"MinecraftMixin"
|
||||
"MinecraftMixin",
|
||||
"HumanoidModelMixin"
|
||||
],
|
||||
"server": [
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
package tschipp.carryon;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import tschipp.carryon.config.fabric.ConfigLoaderImpl;
|
||||
import tschipp.carryon.events.CommonEvents;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class CarryOnFabricMod implements ModInitializer {
|
||||
|
||||
|
|
@ -13,6 +17,14 @@ public class CarryOnFabricMod implements ModInitializer {
|
|||
|
||||
// Use Fabric to bootstrap the Common mod.
|
||||
Constants.LOG.info("Hello Fabric world!");
|
||||
try {
|
||||
ConfigLoaderImpl.initialize();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
CommonEvents.registerEvents();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
package tschipp.carryon.config.fabric;
|
||||
|
||||
import com.google.gson.*;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import tschipp.carryon.config.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConfigLoaderImpl {
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();
|
||||
|
||||
//Default JSON and config data.
|
||||
public static final Map<JsonObject, BuiltConfig> CONFIGS = new HashMap<>();
|
||||
|
||||
public static void initialize() throws IOException {
|
||||
Path cfgPath = FabricLoader.getInstance().getConfigDir();
|
||||
|
||||
for (Map.Entry<JsonObject, BuiltConfig> entry : CONFIGS.entrySet()) {
|
||||
File cfgFile = new File(cfgPath.toFile(), entry.getValue().fileName+".json");
|
||||
if (!cfgFile.exists()) {
|
||||
cfgPath.toFile().mkdirs();
|
||||
FileUtils.write(cfgFile, GSON.toJson(entry.getKey()), StandardCharsets.UTF_8);
|
||||
} else {
|
||||
JsonObject cfgJson = GSON.fromJson(FileUtils.readFileToString(cfgFile, StandardCharsets.UTF_8), JsonObject.class);
|
||||
FileUtils.write(cfgFile, GSON.toJson(loadConfig(entry.getValue(), cfgJson)), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static JsonObject loadConfig(BuiltCategory category, JsonObject config) {
|
||||
config.entrySet().forEach((entry) -> {
|
||||
String id = entry.getKey();
|
||||
if (!id.startsWith("//")) {
|
||||
JsonElement value = entry.getValue();
|
||||
if (value instanceof JsonPrimitive configValue) {
|
||||
category.getProperty(id).ifPresent(data -> {
|
||||
if (configValue.isBoolean() && data.data().type().equals(PropertyType.BOOLEAN))
|
||||
data.setBoolean(configValue.getAsBoolean());
|
||||
if (configValue.isNumber() && data.data().type().equals(PropertyType.INT)) {
|
||||
int configInt = configValue.getAsInt();
|
||||
if (configInt > data.data().max() || configInt < data.data().min()) {
|
||||
try {
|
||||
config.addProperty(id, data.getInt());
|
||||
} catch (IllegalAccessException ignored) {
|
||||
}
|
||||
} else {
|
||||
data.setInt(configInt);
|
||||
}
|
||||
}
|
||||
if (configValue.isNumber() && data.data().type().equals(PropertyType.DOUBLE)) {
|
||||
double configDouble = configValue.getAsDouble();
|
||||
if (configDouble > data.data().maxD() || configDouble < data.data().minD()) {
|
||||
try {
|
||||
config.addProperty(id, data.getDouble());
|
||||
} catch (IllegalAccessException ignored) {
|
||||
}
|
||||
} else {
|
||||
data.setDouble(configDouble);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (value instanceof JsonObject subConfig) {
|
||||
category.getCategory(id).ifPresent(cat -> loadConfig(cat, subConfig));
|
||||
} else if (value instanceof JsonArray list) {
|
||||
category.getProperty(id).ifPresent(data -> {
|
||||
if(data.data().type() == PropertyType.STRING_ARRAY)
|
||||
{
|
||||
List<String> ls = new ArrayList<>();
|
||||
for(JsonElement arrEle : list)
|
||||
{
|
||||
if(arrEle instanceof JsonPrimitive p && p.isString())
|
||||
{
|
||||
ls.add(p.getAsString());
|
||||
}
|
||||
}
|
||||
data.setStringArray(ls.toArray(new String[ls.size()]));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
ConfigLoader.onConfigLoaded();
|
||||
return config;
|
||||
}
|
||||
|
||||
public static void registerConfig(BuiltConfig config) {
|
||||
try {
|
||||
JsonObject configJson = new JsonObject();
|
||||
for (PropertyData property : config.properties) buildProperty(configJson, property);
|
||||
for (BuiltCategory category : config.categories) buildCategory(configJson, category);
|
||||
CONFIGS.put(configJson, config);
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildCategory(JsonObject builder, BuiltCategory category) throws IllegalAccessException {
|
||||
JsonObject categoryJson = new JsonObject();
|
||||
if (category.categoryDesc != null) categoryJson.addProperty("//"+category.category, category.categoryDesc);
|
||||
for (PropertyData property : category.properties) buildProperty(categoryJson, property);
|
||||
for (BuiltCategory builtCategory : category.categories) buildCategory(categoryJson, builtCategory);
|
||||
builder.add(category.category, categoryJson);
|
||||
}
|
||||
|
||||
private static void buildProperty(JsonObject builder, PropertyData data) throws IllegalAccessException {
|
||||
AnnotationData annotationData = data.data();
|
||||
builder.addProperty("//"+data.getId(), annotationData.description());
|
||||
|
||||
switch (annotationData.type()) {
|
||||
case BOOLEAN -> builder.addProperty(data.getId(), data.getBoolean());
|
||||
case INT -> builder.addProperty(data.getId(), data.getInt());
|
||||
case DOUBLE -> builder.addProperty(data.getId(), data.getDouble());
|
||||
case STRING_ARRAY -> {
|
||||
JsonArray arr = new JsonArray();
|
||||
for(String s : data.getStringArray())
|
||||
arr.add(s);
|
||||
builder.add(data.getId(), arr);
|
||||
}
|
||||
default -> throw new IllegalAccessException("Unknown property type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package tschipp.carryon.events;
|
||||
|
||||
public class ClientEvents {
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package tschipp.carryon.events;
|
||||
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import tschipp.carryon.common.carry.CarryOnData;
|
||||
import tschipp.carryon.common.carry.CarryOnDataManager;
|
||||
import tschipp.carryon.common.carry.PickupHandler;
|
||||
import tschipp.carryon.common.carry.PlacementHandler;
|
||||
|
||||
public class CommonEvents {
|
||||
|
||||
public static void registerEvents() {
|
||||
|
||||
UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> {
|
||||
|
||||
if(world.isClientSide)
|
||||
return InteractionResult.PASS;
|
||||
|
||||
BlockPos pos = hitResult.getBlockPos();
|
||||
Direction facing = hitResult.getDirection();
|
||||
|
||||
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
||||
if(!carry.isCarrying())
|
||||
{
|
||||
if (PickupHandler.tryPickUpBlock((ServerPlayer) player, pos, world))
|
||||
return InteractionResult.SUCCESS;
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(carry.isCarrying(CarryOnData.CarryType.BLOCK))
|
||||
{
|
||||
if(PlacementHandler.tryPlaceBlock((ServerPlayer) player, pos, facing, null))
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(PlacementHandler.tryPlaceEntity((ServerPlayer) player, pos, facing, null))
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
//Fail here, so that we don't interact with placed things
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
UseEntityCallback.EVENT.register((player, level, hand, entity, hitResult) -> {
|
||||
|
||||
if(level.isClientSide)
|
||||
return InteractionResult.PASS;
|
||||
|
||||
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
||||
if (!carry.isCarrying()) {
|
||||
if (PickupHandler.tryPickupEntity((ServerPlayer) player, entity)) {
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
else if(carry.isCarrying(CarryOnData.CarryType.ENTITY))
|
||||
{
|
||||
//TODO: Stacking
|
||||
}
|
||||
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package tschipp.carryon.platform;
|
||||
|
||||
import tschipp.carryon.config.BuiltConfig;
|
||||
import tschipp.carryon.config.fabric.ConfigLoaderImpl;
|
||||
import tschipp.carryon.platform.services.IPlatformHelper;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
|
|
@ -21,4 +23,9 @@ public class FabricPlatformHelper implements IPlatformHelper {
|
|||
|
||||
return FabricLoader.getInstance().isDevelopmentEnvironment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConfig(BuiltConfig cfg) {
|
||||
ConfigLoaderImpl.registerConfig(cfg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "modid",
|
||||
"id": "carryon",
|
||||
"version": "${version}",
|
||||
|
||||
"name": "Example Mod",
|
||||
"name": "Carry On",
|
||||
"description": "This is an example description! Tell everyone what your mod is about!",
|
||||
"authors": [
|
||||
"Me!"
|
||||
"Tschipp"
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "https://fabricmc.net/",
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
},
|
||||
|
||||
"license": "CC0-1.0",
|
||||
"icon": "assets/modid/icon.png",
|
||||
"icon": "assets/carryon/logo.png",
|
||||
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
|
|
@ -23,7 +23,8 @@
|
|||
]
|
||||
},
|
||||
"mixins": [
|
||||
"carryon.fabric.mixins.json"
|
||||
"carryon.fabric.mixins.json",
|
||||
"carryon.mixins.json"
|
||||
],
|
||||
|
||||
"depends": {
|
||||
|
|
@ -31,9 +32,6 @@
|
|||
"fabric": "*",
|
||||
"minecraft": "1.19.x",
|
||||
"java": ">=17"
|
||||
},
|
||||
"suggests": {
|
||||
"another-mod": "*"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package tschipp.carryon;
|
||||
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import tschipp.carryon.config.forge.ConfigLoaderImpl;
|
||||
|
||||
@Mod(Constants.MOD_ID)
|
||||
public class CarryOnForge {
|
||||
|
|
@ -13,6 +14,8 @@ public class CarryOnForge {
|
|||
|
||||
// Use Forge to bootstrap the Common mod.
|
||||
Constants.LOG.info("Hello Forge world!");
|
||||
|
||||
ConfigLoaderImpl.initialize();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package tschipp.carryon.config.forge;
|
||||
|
||||
import com.electronwill.nightconfig.core.AbstractConfig;
|
||||
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.config.IConfigSpec;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.event.config.ModConfigEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import tschipp.carryon.config.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConfigLoaderImpl {
|
||||
|
||||
public static final Map<ForgeConfigSpec, BuiltConfig> CONFIGS = new HashMap<>();
|
||||
|
||||
public static void initialize() {
|
||||
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
bus.addListener(ConfigLoaderImpl::onConfigLoad);
|
||||
bus.addListener(ConfigLoaderImpl::onConfigReload);
|
||||
|
||||
ConfigLoaderImpl.CONFIGS.forEach((spec, config) -> {
|
||||
if(config.fileName.contains("client"))
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, spec, config.fileName+".toml");
|
||||
else
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, spec, config.fileName+".toml");
|
||||
});
|
||||
}
|
||||
|
||||
public static void onConfigLoad(ModConfigEvent.Loading loading) {
|
||||
loadConfig(loading.getConfig().getSpec());
|
||||
ConfigLoader.onConfigLoaded();
|
||||
}
|
||||
|
||||
public static void onConfigReload(ModConfigEvent.Reloading loading) {
|
||||
loadConfig(loading.getConfig().getSpec());
|
||||
ConfigLoader.onConfigLoaded();
|
||||
}
|
||||
|
||||
private static void loadConfig(IConfigSpec<ForgeConfigSpec> spec) {
|
||||
BuiltConfig builtConfig = CONFIGS.get(spec.self());
|
||||
if (builtConfig == null) return;
|
||||
loadConfig(builtConfig, spec.self().getValues());
|
||||
}
|
||||
|
||||
private static void loadConfig(BuiltCategory category, UnmodifiableConfig config) {
|
||||
config.valueMap().forEach((id, value) -> {
|
||||
if (value instanceof ForgeConfigSpec.ConfigValue<?> configValue) {
|
||||
category.getProperty(id).ifPresent(data -> {
|
||||
if (configValue instanceof ForgeConfigSpec.BooleanValue booleanValue)
|
||||
data.setBoolean(booleanValue.get());
|
||||
if (configValue instanceof ForgeConfigSpec.IntValue intValue)
|
||||
data.setInt(intValue.get());
|
||||
if (configValue instanceof ForgeConfigSpec.DoubleValue doubleValue)
|
||||
data.setDouble(doubleValue.get());
|
||||
if(configValue.get() instanceof List<?> listVal)
|
||||
data.setStringArray(listVal.toArray(new String[listVal.size()]));
|
||||
});
|
||||
} else if (value instanceof AbstractConfig subConfig) {
|
||||
category.getCategory(id).ifPresent(cat -> loadConfig(cat, subConfig));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void registerConfig(BuiltConfig config) {
|
||||
try {
|
||||
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
||||
for (PropertyData property : config.properties) buildProperty(builder, property);
|
||||
for (BuiltCategory category : config.categories) buildCategory(builder, category);
|
||||
CONFIGS.put(builder.build(), config);
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildCategory(ForgeConfigSpec.Builder builder, BuiltCategory category) throws IllegalAccessException {
|
||||
builder.push(category.category);
|
||||
if (category.categoryDesc != null) builder.comment(category.categoryDesc);
|
||||
for (PropertyData property : category.properties) buildProperty(builder, property);
|
||||
for (BuiltCategory builtCategory : category.categories) buildCategory(builder, builtCategory);
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
private static void buildProperty(ForgeConfigSpec.Builder builder, PropertyData data) throws IllegalAccessException {
|
||||
AnnotationData annotationData = data.data();
|
||||
builder.comment(annotationData.description());
|
||||
|
||||
switch (annotationData.type()) {
|
||||
case BOOLEAN -> builder.define(data.getId(), data.getBoolean());
|
||||
case INT -> builder.defineInRange(data.getId(), data.getInt(), annotationData.min(), annotationData.max());
|
||||
case DOUBLE -> builder.defineInRange(data.getId(), data.getDouble(), annotationData.minD(), annotationData.maxD());
|
||||
case STRING_ARRAY -> builder.defineList(data.getId(), Arrays.asList(data.getStringArray()), obj -> obj instanceof String);
|
||||
default -> throw new IllegalAccessException("Unknown property type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,8 +24,9 @@ public class ClientEvents {
|
|||
MultiBufferSource buffer = event.getMultiBufferSource();
|
||||
PoseStack matrix = event.getPoseStack();
|
||||
int light = event.getPackedLight();
|
||||
float partialTicks = event.getPartialTick();
|
||||
|
||||
if(CarriedObjectRender.drawFirstPerson(player, buffer, matrix, light) && CarryRenderHelper.getPerspective() == 0)
|
||||
if(CarriedObjectRender.drawFirstPerson(player, buffer, matrix, light, partialTicks) && CarryRenderHelper.getPerspective() == 0)
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import tschipp.carryon.common.carry.PlacementHandler;
|
|||
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE, modid = Constants.MOD_ID)
|
||||
public class CommonEvents
|
||||
{
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void onBlockClick(PlayerInteractEvent.RightClickBlock event)
|
||||
{
|
||||
|
|
@ -39,12 +38,12 @@ public class CommonEvents
|
|||
if (level.isClientSide)
|
||||
return;
|
||||
|
||||
boolean cancel = false;
|
||||
boolean success = false;
|
||||
|
||||
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
||||
if (!carry.isCarrying()) {
|
||||
if (PickupHandler.tryPickUpBlock((ServerPlayer) player, pos, level)) {
|
||||
cancel = true;
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
if (carry.isCarrying(CarryType.BLOCK)) {
|
||||
|
|
@ -54,23 +53,23 @@ public class CommonEvents
|
|||
MinecraftForge.EVENT_BUS.post(event1);
|
||||
return !event1.isCanceled();
|
||||
})) {
|
||||
cancel = true;
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
//TODO: Entity place perms
|
||||
if (PlacementHandler.tryPlaceEntity((ServerPlayer) player,pos, event.getFace(), null))
|
||||
{
|
||||
cancel = true;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cancel)
|
||||
if(success)
|
||||
{
|
||||
event.setUseBlock(Event.Result.DENY);
|
||||
event.setUseItem(Event.Result.DENY);
|
||||
event.setCancellationResult(InteractionResult.SUCCESS);
|
||||
event.setCanceled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package tschipp.carryon.platform;
|
||||
|
||||
import tschipp.carryon.config.BuiltConfig;
|
||||
import tschipp.carryon.config.forge.ConfigLoaderImpl;
|
||||
import tschipp.carryon.platform.services.IPlatformHelper;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
|
|
@ -23,4 +25,9 @@ public class ForgePlatformHelper implements IPlatformHelper {
|
|||
|
||||
return !FMLLoader.isProduction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConfig(BuiltConfig cfg) {
|
||||
ConfigLoaderImpl.registerConfig(cfg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user