diff --git a/Common/build.gradle b/Common/build.gradle index ea3a28a..416cdb9 100644 --- a/Common/build.gradle +++ b/Common/build.gradle @@ -4,7 +4,7 @@ plugins { id 'maven-publish' } -archivesBaseName = "${mod_name}-common-${minecraft_version}" +archivesBaseName = "${mod_id}-common-${minecraft_version}" minecraft { version(minecraft_version) diff --git a/Common/src/main/java/tschipp/carryon/CarryOnCommon.java b/Common/src/main/java/tschipp/carryon/CarryOnCommon.java new file mode 100644 index 0000000..d453ef0 --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/CarryOnCommon.java @@ -0,0 +1,58 @@ +package tschipp.carryon; + +import com.mojang.brigadier.CommandDispatcher; +import net.minecraft.commands.CommandSourceStack; +import tschipp.carryon.common.command.CommandCarryOn; +import tschipp.carryon.config.ConfigLoader; +import tschipp.carryon.networking.clientbound.ClientboundStartRidingPacket; +import tschipp.carryon.networking.clientbound.ClientboundSyncScriptsPacket; +import tschipp.carryon.networking.serverbound.ServerboundCarryKeyPressedPacket; +import tschipp.carryon.platform.Services; + +public class CarryOnCommon +{ + public static void registerServerPackets() + { + Services.PLATFORM.registerServerboundPacket( + Constants.PACKET_ID_KEY_PRESSED, + 0, + ServerboundCarryKeyPressedPacket.class, + ServerboundCarryKeyPressedPacket::toBytes, + ServerboundCarryKeyPressedPacket::new, + ServerboundCarryKeyPressedPacket::handle + ); + } + + public static void registerClientPackets() + { + Services.PLATFORM.registerClientboundPacket( + Constants.PACKET_ID_START_RIDING, + 1, + ClientboundStartRidingPacket.class, + ClientboundStartRidingPacket::toBytes, + ClientboundStartRidingPacket::new, + ClientboundStartRidingPacket::handle + ); + + Services.PLATFORM.registerClientboundPacket( + Constants.PACKET_ID_SYNC_SCRIPTS, + 2, + ClientboundSyncScriptsPacket.class, + ClientboundSyncScriptsPacket::toBytes, + ClientboundSyncScriptsPacket::new, + ClientboundSyncScriptsPacket::handle + ); + } + + public static void registerConfig() + { + ConfigLoader.registerConfig(Constants.COMMON_CONFIG); + ConfigLoader.registerConfig(Constants.CLIENT_CONFIG); + } + + public static void registerCommands(CommandDispatcher dispatcher) + { + CommandCarryOn.register(dispatcher); + } + +} diff --git a/Common/src/main/java/tschipp/carryon/CarryOnCommonClient.java b/Common/src/main/java/tschipp/carryon/CarryOnCommonClient.java new file mode 100644 index 0000000..db6202d --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/CarryOnCommonClient.java @@ -0,0 +1,28 @@ +package tschipp.carryon; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.player.Player; +import tschipp.carryon.client.keybinds.CarryOnKeybinds; +import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.CarryOnDataManager; + +public class CarryOnCommonClient +{ + public static void checkForKeybinds() + { + Player player = Minecraft.getInstance().player; + if(player != null) { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + if (CarryOnKeybinds.carryKey.isDown() && !carry.isKeyPressed()) { + CarryOnKeybinds.onCarryKey(true); + carry.setKeyPressed(true); + CarryOnDataManager.setCarryData(player, carry); + } else if (!CarryOnKeybinds.carryKey.isDown() && carry.isKeyPressed()) { + CarryOnKeybinds.onCarryKey(false); + carry.setKeyPressed(false); + CarryOnDataManager.setCarryData(player, carry); + } + } + } + +} diff --git a/Common/src/main/java/tschipp/carryon/Constants.java b/Common/src/main/java/tschipp/carryon/Constants.java index 4410baa..eaafb4e 100644 --- a/Common/src/main/java/tschipp/carryon/Constants.java +++ b/Common/src/main/java/tschipp/carryon/Constants.java @@ -1,9 +1,9 @@ package tschipp.carryon; +import net.minecraft.resources.ResourceLocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import tschipp.carryon.common.config.CarryConfig; -import tschipp.carryon.config.ConfigLoader; public class Constants { @@ -14,8 +14,8 @@ public class Constants { 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); - } + public static final ResourceLocation PACKET_ID_KEY_PRESSED = new ResourceLocation(Constants.MOD_ID, "key_pressed"); + public static final ResourceLocation PACKET_ID_START_RIDING = new ResourceLocation(Constants.MOD_ID, "start_riding"); + public static final ResourceLocation PACKET_ID_SYNC_SCRIPTS = new ResourceLocation(Constants.MOD_ID, "sync_scripts"); + } \ No newline at end of file diff --git a/Common/src/main/java/tschipp/carryon/client/CarryOnClient.java b/Common/src/main/java/tschipp/carryon/client/CarryOnClient.java new file mode 100644 index 0000000..63289d9 --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/client/CarryOnClient.java @@ -0,0 +1,12 @@ +package tschipp.carryon.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.player.Player; + +public class CarryOnClient +{ + public static Player getPlayer() + { + return Minecraft.getInstance().player; + } +} diff --git a/Common/src/main/java/tschipp/carryon/client/keybinds/CarryOnKeybinds.java b/Common/src/main/java/tschipp/carryon/client/keybinds/CarryOnKeybinds.java new file mode 100644 index 0000000..d118e19 --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/client/keybinds/CarryOnKeybinds.java @@ -0,0 +1,25 @@ +package tschipp.carryon.client.keybinds; + +import net.minecraft.client.KeyMapping; +import tschipp.carryon.Constants; +import tschipp.carryon.networking.serverbound.ServerboundCarryKeyPressedPacket; +import tschipp.carryon.platform.Services; + +import java.util.function.Consumer; + +public class CarryOnKeybinds +{ + public static KeyMapping carryKey; + + public static void registerKeybinds(Consumer registrar) + { + carryKey = new KeyMapping("key.carry.desc", 340, "key.carry.category"); + registrar.accept(carryKey); + } + + public static void onCarryKey(boolean pressed) + { + Services.PLATFORM.sendPacketToServer(Constants.PACKET_ID_KEY_PRESSED, new ServerboundCarryKeyPressedPacket(pressed)); + } + +} diff --git a/Common/src/main/java/tschipp/carryon/client/render/CarriedObjectRender.java b/Common/src/main/java/tschipp/carryon/client/render/CarriedObjectRender.java index 1cfeacd..d4709bc 100644 --- a/Common/src/main/java/tschipp/carryon/client/render/CarriedObjectRender.java +++ b/Common/src/main/java/tschipp/carryon/client/render/CarriedObjectRender.java @@ -2,26 +2,28 @@ package tschipp.carryon.client.render; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.math.Vector3f; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.MultiBufferSource.BufferSource; 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.HumanoidArm; 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.Level; 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 tschipp.carryon.common.scripting.CarryOnScript; +import tschipp.carryon.common.scripting.CarryOnScript.ScriptRender; import java.util.Optional; @@ -32,9 +34,19 @@ public class CarriedObjectRender { CarryOnData carry = CarryOnDataManager.getCarryData(player); if(carry.isCarrying(CarryType.BLOCK)) - drawFirstPersonBlock(player, buffer, matrix, light, carry.getBlock()); + drawFirstPersonBlock(player, buffer, matrix, light, CarryRenderHelper.getRenderState(player)); else if (carry.isCarrying(CarryType.ENTITY)) - drawFirstPersonEntity(player, buffer, matrix, light, carry.getEntity(player.level), partialTicks); + drawFirstPersonEntity(player, buffer, matrix, light, partialTicks); + + if(carry.getActiveScript().isPresent()) + { + ScriptRender render = carry.getActiveScript().get().scriptRender(); + if(!render.renderLeftArm() && player.getMainArm() == HumanoidArm.LEFT) + return false; + + if(!render.renderRightArm() && player.getMainArm() == HumanoidArm.RIGHT) + return false; + } return carry.isCarrying(); } @@ -46,44 +58,34 @@ public class CarriedObjectRender matrix.translate(0, -0.5, -1); RenderSystem.enableBlend(); RenderSystem.disableCull(); - int perspective = CarryRenderHelper.getPerspective(); - if (Constants.CLIENT_CONFIG.facePlayer && isChest(state.getBlock())) { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + + if (!Constants.CLIENT_CONFIG.facePlayer && CarryRenderHelper.isChest(state.getBlock())) { matrix.mulPose(Vector3f.YP.rotationDegrees(180)); matrix.mulPose(Vector3f.XN.rotationDegrees(8)); } else { matrix.mulPose(Vector3f.XP.rotationDegrees(8)); } -// -// CarryOnOverride carryOverride = ScriptChecker.getOverride(player); -// if (carryOverride != null) { -// CarryRenderHelper.performOverrideTransformation(matrix, carryOverride); -// -// if (!carryOverride.getRenderNameBlock().isEmpty()) { -// Block b = StringParser.getBlock(carryOverride.getRenderNameBlock()); -// if (b != null) { -// ItemStack s = new ItemStack(b, 1); -// s.setTag(carryOverride.getRenderNBT()); -// model = Minecraft.getInstance().getItemRenderer().getModel(s, level, player, 0); -// } -// } -// } + if(carry.getActiveScript().isPresent()) + CarryRenderHelper.performScriptTransformation(matrix, carry.getActiveScript().get()); RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); ItemStack stack = new ItemStack(state.getBlock().asItem()); - //TODO: Model overrides - BakedModel model = Minecraft.getInstance().getItemRenderer().getModel(stack, player.level, player, 0); - CarryRenderHelper.renderItem(state, null, stack, matrix, buffer, light, model); + BakedModel model = CarryRenderHelper.getRenderBlock(player); + CarryRenderHelper.renderBakedModel(stack, matrix, buffer, light, model); RenderSystem.enableCull(); RenderSystem.disableBlend(); matrix.popPose(); } - private static void drawFirstPersonEntity(Player player, MultiBufferSource buffer, PoseStack matrix, int light, Entity entity, float partialTicks) { + private static void drawFirstPersonEntity(Player player, MultiBufferSource buffer, PoseStack matrix, int light, float partialTicks) { EntityRenderDispatcher manager = Minecraft.getInstance().getEntityRenderDispatcher(); + Entity entity = CarryRenderHelper.getRenderEntity(player); + CarryOnData carry = CarryOnDataManager.getCarryData(player); if (entity != null) { @@ -102,58 +104,121 @@ public class CarriedObjectRender matrix.mulPose(Vector3f.YP.rotationDegrees(180)); matrix.translate(0.0, -height - .1, width + 0.1); - // RenderSystem.enableAlphaTest(); + manager.setRenderShadow(false); - // 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> 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); + Optional res = carry.getActiveScript(); + if(res.isPresent()) + { + CarryOnScript script = res.get(); + CarryRenderHelper.performScriptTransformation(matrix, script); } - // RenderSystem.disableAlphaTest(); - matrix.popPose(); + 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(); } + /** + * Draws the third person view of entities and blocks + * @param partialticks + * @param matrix + */ + public static void drawThirdPerson(float partialticks, PoseStack matrix) { + Minecraft mc = Minecraft.getInstance(); + Level level = mc.level; + BufferSource buffer = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); + int light = 0; + int perspective = CarryRenderHelper.getPerspective(); + EntityRenderDispatcher manager = mc.getEntityRenderDispatcher(); - private static boolean isChest(Block block) - { - return block == Blocks.CHEST || block == Blocks.ENDER_CHEST || block == Blocks.TRAPPED_CHEST; + RenderSystem.enableBlend(); + RenderSystem.disableCull(); + RenderSystem.disableDepthTest(); + + for (Player player : level.players()) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + + if (perspective == 0 && player == mc.player) + continue; + + light = manager.getPackedLightCoords(player, partialticks); + + if (carry.isCarrying(CarryType.BLOCK)) + { + BlockState state = CarryRenderHelper.getRenderState(player); + + CarryRenderHelper.applyBlockTransformations(player, partialticks, matrix, state.getBlock()); + + ItemStack tileItem = new ItemStack(state.getBlock().asItem()); + BakedModel model = CarryRenderHelper.getRenderBlock(player); + + //ModelOverridesHandler.hasCustomOverrideModel(state, tag) ? ModelOverridesHandler.getCustomOverrideModel(state, tag, level, player) : tileItem.isEmpty() ? mc.getBlockRenderer().getBlockModel(state) : mc.getItemRenderer().getModel(tileItem, level, player, 0); +// + Optional res = carry.getActiveScript(); + if(res.isPresent()) + { + CarryOnScript script = res.get(); + CarryRenderHelper.performScriptTransformation(matrix, script); + } + + RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); + RenderSystem.enableCull(); + + PoseStack.Pose p = matrix.last(); + PoseStack copy = new PoseStack(); + copy.mulPoseMatrix(p.pose()); + matrix.popPose(); + + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + + CarryRenderHelper.renderBakedModel(tileItem, copy, buffer, light, model); + buffer.endBatch(); + + matrix.popPose(); + } + else if (carry.isCarrying(CarryType.ENTITY)) + { + Entity entity = CarryRenderHelper.getRenderEntity(player); + + if (entity != null) + { + CarryRenderHelper.applyEntityTransformations(player, partialticks, matrix, entity); + + manager.setRenderShadow(false); + + Optional res = carry.getActiveScript(); + if(res.isPresent()) + { + CarryOnScript script = res.get(); + CarryRenderHelper.performScriptTransformation(matrix, script); + } + + if (entity instanceof LivingEntity le) + le.hurtTime = 0; + + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + + manager.render(entity, 0, 0, 0, 0f, 0, matrix, buffer, light); + buffer.endBatch(); + + matrix.popPose(); + manager.setRenderShadow(true); + matrix.popPose(); + } + } + + } + RenderSystem.enableDepthTest(); + RenderSystem.enableCull(); + RenderSystem.disableBlend(); } + } diff --git a/Common/src/main/java/tschipp/carryon/client/render/CarryRenderHelper.java b/Common/src/main/java/tschipp/carryon/client/render/CarryRenderHelper.java index 0dab93c..6be830e 100644 --- a/Common/src/main/java/tschipp/carryon/client/render/CarryRenderHelper.java +++ b/Common/src/main/java/tschipp/carryon/client/render/CarryRenderHelper.java @@ -9,15 +9,26 @@ import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; 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.core.Registry; import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; 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.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.VoxelShape; +import tschipp.carryon.Constants; +import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.CarryOnData.CarryType; +import tschipp.carryon.common.carry.CarryOnDataManager; +import tschipp.carryon.common.scripting.CarryOnScript; +import tschipp.carryon.common.scripting.CarryOnScript.ScriptRender; public class CarryRenderHelper { @@ -28,8 +39,11 @@ public class CarryRenderHelper public static float getExactBodyRotationDegrees(LivingEntity entity, float partialticks) { - if (entity.getVehicle() != null && entity.getVehicle() instanceof LivingEntity) - return -(entity.yHeadRotO + (entity.yHeadRot - entity.yHeadRotO) * partialticks); + if (entity.getVehicle() != null && entity.getVehicle() instanceof LivingEntity vehicle) + if(vehicle instanceof Player player) + return -(player.yBodyRotO + (player.yBodyRot - player.yBodyRotO) * partialticks); + else + return -(entity.yHeadRotO + (entity.yHeadRot - entity.yHeadRotO) * partialticks); else return -(entity.yBodyRotO + (entity.yBodyRot - entity.yBodyRotO) * partialticks); } @@ -99,14 +113,14 @@ public class CarryRenderHelper 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(); + Vec3 viewVector = player.getViewVector(partialticks); + Vec3 deltaMovement = player.getDeltaMovement(); + double d0 = deltaMovement.horizontalDistanceSqr(); + double d1 = deltaMovement.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; + double d2 = (deltaMovement.x * viewVector.x + deltaMovement.z * viewVector.z) / (Math.sqrt(d0) * Math.sqrt(d1)); + double d3 = deltaMovement.x * viewVector.z - deltaMovement.z * viewVector.x; matrix.mulPose(Vector3f.YP.rotation((float) (Math.signum(d3) * Math.acos(d2)))); } @@ -119,43 +133,182 @@ public class CarryRenderHelper matrix.translate(0, 1.6, 0.65); } + public static void applyBlockTransformations(Player player, float partialticks, PoseStack matrix, Block block) + { + int perspective = CarryRenderHelper.getPerspective(); - //TODO: Scripting -// public static void performOverrideTransformation(PoseStack matrix, CarryOnOverride override) -// { -// int perspective = getPerspective(); -// -// float[] translation = ScriptParseHelper.getXYZArray(override.getRenderTranslation()); -// float[] rotation = ScriptParseHelper.getXYZArray(override.getRenderRotation()); -// float[] scaled = ScriptParseHelper.getScaled(override.getRenderScaled()); -// -// Quaternion rot = Vector3f.XP.rotationDegrees(rotation[0]); -// rot.mul(Vector3f.YP.rotationDegrees(rotation[1])); -// rot.mul(Vector3f.ZP.rotationDegrees(rotation[2])); -// matrix.mulPose(rot); -// -// matrix.translate(translation[0], translation[1], perspective == 1 && override.isBlock() ? -translation[2] : translation[2]); -// -// matrix.scale(scaled[0], scaled[1], scaled[2]); -// } + applyGeneralTransformations(player, partialticks, matrix); - public static void renderItem(BlockState state, CompoundTag tag, ItemStack stack, PoseStack matrix, MultiBufferSource buffer, int light, BakedModel model) + if (!Constants.CLIENT_CONFIG.facePlayer && isChest(block)) + { + //if ((ModList.get().isLoaded("realrender") || ModList.get().isLoaded("rfpr")) && perspective == 0) + // matrix.translate(0, 0, -0.4); + matrix.mulPose(Vector3f.YP.rotationDegrees(180)); + } + //else if ((ModList.get().isLoaded("realrender") || ModList.get().isLoaded("rfpr")) && perspective == 0) + // matrix.translate(0, 0, 0.4); + //matrix.mulPose(Vector3f.YP.rotationDegrees(180)); + + float height = getRenderHeight(player); + float offset = (height - 1f) / 1.2f; + matrix.translate(0, -offset, 0); + } + + public static void applyEntityTransformations(Player player, float partialticks, PoseStack matrix, Entity entity) + { + int perspective = CarryRenderHelper.getPerspective(); + Pose pose = player.getPose(); + + applyGeneralTransformations(player, partialticks, matrix); + + if (perspective == 2) + matrix.translate(0, -1.6, 0.65); + else + matrix.translate(0, -1.6, -0.65); + matrix.scale(1.666f, 1.666f, 1.666f); + + float height = entity.getBbHeight(); + float width = entity.getBbWidth(); + float multiplier = height * width; + entity.yo = 0.0f; + entity.yRotO = 0.0f; + entity.setYHeadRot(0.0f); + entity.xo = 0.0f; + entity.xRotO = 0.0f; + + if (perspective == 2) + matrix.mulPose(Vector3f.YP.rotationDegrees(180)); + + matrix.scale((10 - multiplier) * 0.08f, (10 - multiplier) * 0.08f, (10 - multiplier) * 0.08f); + matrix.translate(0.0, height / 2 + -(height / 2) + 1, width - 0.1 < 0.7 ? width - 0.1 + (0.7 - (width - 0.1)) : width - 0.1); + + if (pose == Pose.SWIMMING || pose == Pose.FALL_FLYING) + { + matrix.mulPose(Vector3f.XN.rotationDegrees(90)); + matrix.translate(0, -0.2 * height, 0); + + if (pose == Pose.FALL_FLYING) + matrix.translate(0, 0, 0.2); + } + + } + + + public static void performScriptTransformation(PoseStack matrix, CarryOnScript script) + { + int perspective = getPerspective(); + + ScriptRender render = script.scriptRender(); + + Vec3 translation = render.renderTranslation().getVec(); + Vec3 rotation = render.renderRotation().getVec(); + Vec3 scale = render.renderscale().getVec(1); + + Quaternion rot = Vector3f.XP.rotationDegrees((float) rotation.x); + rot.mul(Vector3f.YP.rotationDegrees((float) rotation.y)); + rot.mul(Vector3f.ZP.rotationDegrees((float) rotation.z)); + matrix.mulPose(rot); + + matrix.translate(translation.x, translation.y, perspective == 1 && script.isBlock() ? -translation.z : translation.z); + + matrix.scale((float) scale.x, (float) scale.y, (float) scale.z); + } + + + + public static void renderBakedModel(ItemStack stack, PoseStack matrix, MultiBufferSource buffer, int light, BakedModel model) { ItemRenderer renderer = Minecraft.getInstance().getItemRenderer(); -// if (ModelOverridesHandler.hasCustomOverrideModel(state, tag)) -// { -// Object override = ModelOverridesHandler.getOverrideObject(state, tag); - -// if (override instanceof ItemStack) -// { -// renderer.render((ItemStack) override, TransformType.NONE, false, matrix, buffer, light, OverlayTexture.NO_OVERLAY, model); -// return; -//// } -// } - renderer.render(stack, TransformType.NONE, false, matrix, buffer, light, OverlayTexture.NO_OVERLAY, model); } + public static BlockState getRenderState(Player player) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + BlockState state = carry.getBlock().getBlock().defaultBlockState(); + if(carry.getActiveScript().isPresent()) + { + ScriptRender render = carry.getActiveScript().get().scriptRender(); + if(render.renderNameBlock().isPresent()) + state = Registry.BLOCK.get(render.renderNameBlock().get()).defaultBlockState(); + } + return state; + } + + public static BakedModel getRenderBlock(Player player) + { + BlockState state = getRenderState(player); + + BakedModel model = Minecraft.getInstance().getBlockRenderer().getBlockModel(state); + + if(state.getRenderShape() != RenderShape.MODEL || model.isCustomRenderer() || model.getQuads(state, null, RandomSource.create()).size() <= 0) { + ItemStack stack = new ItemStack(state.getBlock()); + model = Minecraft.getInstance().getItemRenderer().getModel(stack, player.level, player, 0); + } + + return model; + } + + public static Entity getRenderEntity(Player player) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + Entity entity = carry.getEntity(player.level); + + if(carry.getActiveScript().isPresent()) + { + CarryOnScript script = carry.getActiveScript().get(); + ScriptRender render = script.scriptRender(); + if(render.renderNameEntity().isPresent()) + entity = Registry.ENTITY_TYPE.get(render.renderNameEntity().get()).create(player.level); + + if(render.renderNBT().isPresent()) + entity.load(render.renderNBT().get()); + } + + return entity; + } + + public static float getRenderWidth(Player player) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + if(carry.isCarrying(CarryType.BLOCK)) + { + VoxelShape shape = getRenderState(player).getShape(player.level, player.blockPosition()); + if(shape == null) + return 1f; + float width = (float)Math.abs(shape.bounds().maxX - shape.bounds().minX); + return width; + } + else if(carry.isCarrying(CarryType.ENTITY)) + { + Entity entity = getRenderEntity(player); + return entity.getBbWidth(); + } + else + return 1f; + } + + public static float getRenderHeight(Player player) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + if(carry.isCarrying(CarryType.BLOCK)) + { + VoxelShape shape = getRenderState(player).getShape(player.level, player.blockPosition()); + if(shape == null) + return 1f; + float height = (float)Math.abs(shape.bounds().maxY - shape.bounds().minY); + return height; + } + else if(carry.isCarrying(CarryType.ENTITY)) + { + Entity entity = getRenderEntity(player); + return entity.getBbHeight(); + } + else + return 1f; + } + + @SuppressWarnings("resource") public static int getPerspective() { @@ -176,4 +329,10 @@ public class CarryRenderHelper return player.isShiftKeyDown() || player.isCrouching(); } + + public static boolean isChest(Block block) + { + return block == Blocks.CHEST || block == Blocks.ENDER_CHEST || block == Blocks.TRAPPED_CHEST; + } + } diff --git a/Common/src/main/java/tschipp/carryon/common/carry/CarryOnData.java b/Common/src/main/java/tschipp/carryon/common/carry/CarryOnData.java index f4bb35b..4f9781a 100644 --- a/Common/src/main/java/tschipp/carryon/common/carry/CarryOnData.java +++ b/Common/src/main/java/tschipp/carryon/common/carry/CarryOnData.java @@ -1,21 +1,28 @@ package tschipp.carryon.common.carry; +import com.mojang.serialization.DataResult; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; 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.level.block.state.properties.BlockStateProperties; +import tschipp.carryon.common.scripting.CarryOnScript; import javax.annotation.Nullable; +import java.util.Optional; public class CarryOnData { private CarryType type; private CompoundTag nbt; + private boolean keyPressed = false; + private CarryOnScript activeScript; public CarryOnData(CompoundTag data) { @@ -25,11 +32,27 @@ public class CarryOnData { this.type = CarryType.INVALID; this.nbt = data; + + if(data.contains("keyPressed")) + this.keyPressed = data.getBoolean("keyPressed"); + + if(data.contains("activeScript")) + { + DataResult res = CarryOnScript.CODEC.parse(NbtOps.INSTANCE, data.get("activeScript")); + this.activeScript = res.getOrThrow(false, (s) -> {throw new RuntimeException("Failed to decode activeScript during CarryOnData serialization: " + s);}); + } } public CompoundTag getNbt() { nbt.putString("type", type.toString()); + nbt.putBoolean("keyPressed", keyPressed); + if(activeScript != null) + { + DataResult res = CarryOnScript.CODEC.encodeStart(NbtOps.INSTANCE, activeScript); + Tag tag = res.getOrThrow(false, (s) -> {throw new RuntimeException("Failed to encode activeScript during CarryOnData serialization: " + s);}); + nbt.put("activeScript", tag); + } return nbt; } @@ -83,7 +106,23 @@ public class CarryOnData { if(this.type != CarryType.ENTITY) throw new IllegalStateException("Called getEntity on data that contained " + this.type); - return EntityType.create(nbt.getCompound("entity"), level).orElseThrow(); + return EntityType.create(nbt.getCompound("entity"), level).orElseThrow(() -> new IllegalStateException("Called EntityType#create even though no entity data was present. Data: " + nbt.toString())); + } + + public Optional getActiveScript() + { + if(activeScript == null) + return Optional.empty(); + return Optional.of(activeScript); + } + + public void setActiveScript(CarryOnScript script) + { + this.activeScript = script; + } + + public void setCarryingPlayer() { + this.type = CarryType.PLAYER; } public boolean isCarrying() @@ -96,10 +135,18 @@ public class CarryOnData { return this.type == type; } + public boolean isKeyPressed() {return this.keyPressed;} + + public void setKeyPressed(boolean val) { + this.keyPressed = val; + this.nbt.putBoolean("keyPressed", val); + } + public void clear() { this.type = CarryType.INVALID; this.nbt = new CompoundTag(); + this.activeScript = null; } public int getTick() @@ -112,6 +159,7 @@ public class CarryOnData { public enum CarryType { BLOCK, ENTITY, + PLAYER, INVALID } } diff --git a/Common/src/main/java/tschipp/carryon/common/carry/CarryOnDataManager.java b/Common/src/main/java/tschipp/carryon/common/carry/CarryOnDataManager.java index 1e50f99..cb3b127 100644 --- a/Common/src/main/java/tschipp/carryon/common/carry/CarryOnDataManager.java +++ b/Common/src/main/java/tschipp/carryon/common/carry/CarryOnDataManager.java @@ -5,7 +5,6 @@ import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.world.entity.player.Player; -import org.apache.commons.lang3.ObjectUtils; public class CarryOnDataManager { @@ -22,10 +21,7 @@ public class CarryOnDataManager { { CompoundTag nbt = data.getNbt(); nbt.putInt("tick", player.tickCount); - System.out.println(player.getEntityData().isDirty()); - System.out.println("Old: " + player.getEntityData().get(CARRY_DATA_KEY) + ", New: " + nbt + ", NotEqual: " + ObjectUtils.notEqual(player.getEntityData().get(CARRY_DATA_KEY), nbt)); player.getEntityData().set(CARRY_DATA_KEY, nbt); - System.out.println(player.getEntityData().isDirty()); } } diff --git a/Common/src/main/java/tschipp/carryon/common/carry/ListHandler.java b/Common/src/main/java/tschipp/carryon/common/carry/ListHandler.java index 7773f47..f12ff4a 100644 --- a/Common/src/main/java/tschipp/carryon/common/carry/ListHandler.java +++ b/Common/src/main/java/tschipp/carryon/common/carry/ListHandler.java @@ -191,4 +191,34 @@ public class ListHandler { return containsAll; } + public static void addForbiddenTiles(String toAdd) + { + FORBIDDEN_TILES.add(toAdd); + } + + public static void addForbiddenEntities(String toAdd) + { + FORBIDDEN_ENTITIES.add(toAdd); + } + + public static void addForbiddenStacking(String toAdd) + { + FORBIDDEN_STACKING.add(toAdd); + } + + public static void addAllowedTiles(String toAdd) + { + ALLOWED_TILES.add(toAdd); + } + + public static void addAllowedEntities(String toAdd) + { + ALLOWED_ENTITIES.add(toAdd); + } + + public static void addAllowedStacking(String toAdd) + { + ALLOWED_ENTITIES.add(toAdd); + } + } diff --git a/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java b/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java index e7c185c..a9fec15 100644 --- a/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java +++ b/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java @@ -19,17 +19,18 @@ 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 tschipp.carryon.common.scripting.CarryOnScript; +import tschipp.carryon.common.scripting.ScriptManager; +import tschipp.carryon.networking.clientbound.ClientboundStartRidingPacket; +import tschipp.carryon.platform.Services; +import java.util.Optional; import java.util.UUID; public class PickupHandler { public static boolean canCarryGeneral(ServerPlayer player, Vec3 pos) { - //TODO: Check carry key - if(!player.isShiftKeyDown()) - return false; - if(!player.getMainHandItem().isEmpty() || !player.getOffhandItem().isEmpty()) return false; @@ -40,6 +41,9 @@ public class PickupHandler { if(carry.isCarrying()) return false; + if(!carry.isKeyPressed()) + return false; + //Needed so that we don't pick up and place in the same tick if(player.tickCount == carry.getTick()) return false; @@ -61,6 +65,9 @@ public class PickupHandler { CarryOnData carry = CarryOnDataManager.getCarryData(player); BlockEntity blockEntity = level.getBlockEntity(pos); BlockState state = level.getBlockState(pos); + CompoundTag nbt = null; + if(blockEntity != null) + nbt = blockEntity.saveWithId(); if(!ListHandler.isPermitted(state.getBlock())) return false; @@ -74,17 +81,28 @@ public class PickupHandler { //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 + Optional result = ScriptManager.inspectBlock(state, level, pos, nbt); + if(result.isPresent()) + { + CarryOnScript script = result.get(); + if(!script.fulfillsConditions(player)) + return false; + + carry.setActiveScript(script); + + String cmd = script.scriptEffects().commandInit(); + if(!cmd.isEmpty()) + player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd); + } + carry.setBlock(state, blockEntity); level.removeBlockEntity(pos); @@ -106,9 +124,6 @@ public class PickupHandler { if (entity.invulnerableTime != 0) return false; - if (entity instanceof Player) - return false; - if (entity instanceof TamableAnimal tame) { UUID owner = tame.getOwnerUUID(); @@ -130,21 +145,65 @@ public class PickupHandler { 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()) + 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); + Optional result = ScriptManager.inspectEntity(entity); + if(result.isPresent()) + { + CarryOnScript script = result.get(); + if(!script.fulfillsConditions(player)) + return false; + + carry.setActiveScript(script); + } + + if (entity instanceof Player otherPlayer) { + if (!Constants.COMMON_CONFIG.settings.pickupPlayers) + return false; + + if (!player.isCreative() && otherPlayer.isCreative()) + return false; + + otherPlayer.ejectPassengers(); + otherPlayer.stopRiding(); + + if (result.isPresent()) { + String cmd = result.get().scriptEffects().commandInit(); + if (!cmd.isEmpty()) + player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd); + } + + otherPlayer.startRiding(player); + Services.PLATFORM.sendPacketToPlayer(Constants.PACKET_ID_START_RIDING, new ClientboundStartRidingPacket(otherPlayer.getId(), true), player); + carry.setCarryingPlayer(); + player.swing(InteractionHand.MAIN_HAND, true); + player.level.playSound(null, player.getOnPos(), SoundEvents.ARMOR_EQUIP_GENERIC, SoundSource.AMBIENT, 1.0f, 0.5f); + CarryOnDataManager.setCarryData(player, carry); + return true; + + } + entity.ejectPassengers(); - if (entity instanceof Animal animal) + entity.stopRiding(); + if (entity instanceof Animal animal) { animal.dropLeash(true, true); + } + + if(result.isPresent()) + { + String cmd = result.get().scriptEffects().commandInit(); + if(!cmd.isEmpty()) + player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd); + } carry.setEntity(entity); entity.remove(RemovalReason.UNLOADED_WITH_PLAYER); @@ -155,4 +214,18 @@ public class PickupHandler { return true; } + public static void onCarryTick(ServerPlayer player) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + if(carry.isCarrying()) + { + if(carry.getActiveScript().isPresent()) + { + String cmd = carry.getActiveScript().get().scriptEffects().commandLoop(); + if(!cmd.isEmpty()) + player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd); + } + } + } + } diff --git a/Common/src/main/java/tschipp/carryon/common/carry/PlacementHandler.java b/Common/src/main/java/tschipp/carryon/common/carry/PlacementHandler.java index dccc4c8..5a51b78 100644 --- a/Common/src/main/java/tschipp/carryon/common/carry/PlacementHandler.java +++ b/Common/src/main/java/tschipp/carryon/common/carry/PlacementHandler.java @@ -3,10 +3,12 @@ package tschipp.carryon.common.carry; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; 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.Entity; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.animal.horse.Horse; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.Level; @@ -19,9 +21,12 @@ import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; +import tschipp.carryon.Constants; import tschipp.carryon.common.carry.CarryOnData.CarryType; +import tschipp.carryon.common.scripting.CarryOnScript.ScriptEffects; import javax.annotation.Nullable; +import java.util.List; import java.util.function.BiFunction; public class PlacementHandler @@ -50,7 +55,10 @@ public class PlacementHandler boolean canPlace = state.canSurvive(level, pos) && level.mayInteract(player, pos) && level.getBlockState(pos).canBeReplaced(context) && level.isUnobstructed(state, pos, CollisionContext.of(player)); if (!canPlace) + { + level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.LAVA_POP, SoundSource.PLAYERS, 0.5F, 0.5F); return false; + } state = getPlacementState(state, player, context, pos); boolean doPlace = placementCallback == null || placementCallback.apply(pos, state); @@ -58,6 +66,14 @@ public class PlacementHandler if (!doPlace) return false; + if(carry.getActiveScript().isPresent()) + { + ScriptEffects effects = carry.getActiveScript().get().scriptEffects(); + String cmd = effects.commandPlace(); + if(!cmd.isEmpty()) + player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd); + } + level.setBlock(pos, state, 3); if (blockEntity != null) level.setBlockEntity(blockEntity); @@ -72,7 +88,6 @@ public class PlacementHandler private static BlockState getPlacementState(BlockState state, ServerPlayer player, BlockPlaceContext context, BlockPos pos) { BlockState placementState = state.getBlock().getStateForPlacement(context); - System.out.println(placementState); for (var prop : placementState.getProperties()) { if (prop instanceof DirectionProperty) { @@ -88,8 +103,6 @@ public class PlacementHandler } } - System.out.println(state); - state = Block.updateFromNeighbourShapes(state, player.level, pos); if (placementState.hasProperty(BlockStateProperties.WATERLOGGED)) @@ -107,7 +120,8 @@ public class PlacementHandler public static boolean tryPlaceEntity(ServerPlayer player, BlockPos pos, Direction facing, @Nullable BiFunction placementCallback) { CarryOnData carry = CarryOnDataManager.getCarryData(player); - if (!carry.isCarrying(CarryType.ENTITY)) + + if (!carry.isCarrying(CarryType.ENTITY) && !carry.isCarrying(CarryType.PLAYER)) return false; if (player.tickCount == carry.getTick()) @@ -121,6 +135,18 @@ public class PlacementHandler Vec3 placementPos = Vec3.atBottomCenterOf(pos); + if(carry.isCarrying(CarryType.PLAYER)) + { + Entity otherPlayer = player.getFirstPassenger(); + player.ejectPassengers(); + carry.clear(); + CarryOnDataManager.setCarryData(player, carry); + if(otherPlayer == null) + return true; + otherPlayer.teleportTo(placementPos.x, placementPos.y, placementPos.z); + player.swing(InteractionHand.MAIN_HAND, true); + return true; + } Entity entity = carry.getEntity(level); entity.setPos(placementPos); @@ -129,6 +155,14 @@ public class PlacementHandler if (!doPlace) return false; + if(carry.getActiveScript().isPresent()) + { + ScriptEffects effects = carry.getActiveScript().get().scriptEffects(); + String cmd = effects.commandPlace(); + if(!cmd.isEmpty()) + player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd); + } + level.addFreshEntity(entity); if(entity instanceof Mob mob) mob.playAmbientSound(); @@ -139,4 +173,115 @@ public class PlacementHandler return true; } + public static void tryStackEntity(ServerPlayer player, Entity entityClicked) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + if(!carry.isCarrying(CarryType.ENTITY) && !carry.isCarrying(CarryType.PLAYER)) + return; + + Level level = player.level; + Entity entityHeld; + if(carry.isCarrying(CarryType.ENTITY)) + entityHeld = carry.getEntity(level); + else + entityHeld = player.getFirstPassenger(); + + + double sizeHeldEntity = entityHeld.getBbHeight() * entityHeld.getBbWidth(); + double distance = entityClicked.blockPosition().distSqr(player.blockPosition()); + Entity lowestEntity = entityClicked.getRootVehicle(); + int numPassengers = getPassengerCount(lowestEntity); + if (numPassengers < Constants.COMMON_CONFIG.settings.maxEntityStackLimit - 1) + { + Entity topEntity = getTopPassenger(lowestEntity); + + if(topEntity == entityHeld) + return; + + if (ListHandler.isStackingPermitted(topEntity)) + { + double sizeEntity = topEntity.getBbHeight() * topEntity.getBbWidth(); + if (Constants.COMMON_CONFIG.settings.entitySizeMattersStacking && sizeHeldEntity <= sizeEntity || !Constants.COMMON_CONFIG.settings.entitySizeMattersStacking) + { + if (topEntity instanceof Horse horse) + horse.setTamed(true); + + if (distance < 6) + { + double tempX = entityClicked.getX(); + double tempY = entityClicked.getY(); + double tempZ = entityClicked.getZ(); + if(carry.isCarrying(CarryType.ENTITY)) { + entityHeld.setPos(tempX, tempY + 2.6, tempZ); + level.addFreshEntity(entityHeld); + entityHeld.teleportTo(tempX, tempY, tempZ); + } + entityHeld.startRiding(topEntity, false); + } + else + { + if(carry.isCarrying(CarryType.ENTITY)) { + entityHeld.setPos(entityClicked.getX(), entityClicked.getY(), entityClicked.getZ()); + level.addFreshEntity(entityHeld); + } + entityHeld.startRiding(topEntity, false); + } + + if(carry.getActiveScript().isPresent()) + { + ScriptEffects effects = carry.getActiveScript().get().scriptEffects(); + String cmd = effects.commandPlace(); + if(!cmd.isEmpty()) + player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd); + } + + player.swing(InteractionHand.MAIN_HAND, true); + carry.clear(); + CarryOnDataManager.setCarryData(player, carry); + level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.HORSE_SADDLE, SoundSource.PLAYERS, 0.5F, 1.5F); + } + else + { + level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.LAVA_POP, SoundSource.PLAYERS, 0.5F, 0.5F); + } + } + } + else + { + level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.LAVA_POP, SoundSource.PLAYERS, 0.5F, 0.5F); + } + } + + private static int getPassengerCount(Entity entity) + { + int passengers = 0; + while (entity.isVehicle()) + { + List pass = entity.getPassengers(); + if (!pass.isEmpty()) + { + entity = pass.get(0); + passengers++; + } + } + + return passengers; + } + + private static Entity getTopPassenger(Entity entity) + { + Entity top = entity; + while (entity.isVehicle()) + { + List pass = entity.getPassengers(); + if (!pass.isEmpty()) + { + entity = pass.get(0); + top = entity; + } + } + + return top; + } + } diff --git a/Common/src/main/java/tschipp/carryon/common/command/CommandCarryOn.java b/Common/src/main/java/tschipp/carryon/common/command/CommandCarryOn.java new file mode 100644 index 0000000..3f55cc7 --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/common/command/CommandCarryOn.java @@ -0,0 +1,112 @@ +package tschipp.carryon.common.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.commands.arguments.EntityArgument; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +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.Collection; +import java.util.Collections; + +public class CommandCarryOn +{ + public static void register(CommandDispatcher dispatcher) + { + LiteralArgumentBuilder builder = Commands.literal("carryon") + + .then(Commands.literal("debug").executes(cmd -> handleDebug(cmd.getSource()))) + + .then(Commands.literal("clear").executes(cmd -> handleClear(cmd.getSource(), Collections.singleton(cmd.getSource().getPlayerOrException())))) + + .then(Commands.literal("clear").then(Commands.argument("target", EntityArgument.players()).requires(src -> src.hasPermission(2)).executes(cmd -> handleClear(cmd.getSource(), EntityArgument.getPlayers(cmd, "target"))))) + + ; + + dispatcher.register(builder); + + } + + private static int handleDebug(CommandSourceStack source) + { + try + { + if (source.getEntityOrException() != null) + { + ServerPlayer player = source.getPlayerOrException(); + + CarryOnData carry = CarryOnDataManager.getCarryData(player); + if (carry.isCarrying(CarryType.BLOCK)) + { + log(source,"Block: " + carry.getBlock().getBlock()); + log(source,"BlockState: " + carry.getBlock()); + log(source,"NBT: " + carry.getNbt()); + + //TODO +// if (ModelOverridesHandler.hasCustomOverrideModel(ItemCarryonBlock.getBlockState(main), ItemCarryonBlock.getTileData(main))) +// source.sendSuccess(Component.literal("Override Model: " + ModelOverridesHandler.getOverrideObject(ItemCarryonBlock.getBlockState(main), ItemCarryonBlock.getTileData(main))), true); + +// if (CustomPickupOverrideHandler.hasSpecialPickupConditions(ItemCarryonBlock.getBlockState(main))) +// source.sendSuccess(Component.literal("Custom Pickup Condition: " + CustomPickupOverrideHandler.getPickupCondition(ItemCarryonBlock.getBlockState(main))), true); + + return 1; + } + else if (carry.isCarrying(CarryType.ENTITY)) + { + log(source,"Entity: " + carry.getEntity(player.level)); + log(source,"Entity Name: " + carry.getEntity(player.level).getType()); + log(source,"NBT: " + carry.getNbt()); + +// if (CustomPickupOverrideHandler.hasSpecialPickupConditions(ItemCarryonEntity.getEntity(main, player.level))) +// source.sendSuccess(Component.literal("Custom Pickup Condition: " + CustomPickupOverrideHandler.getPickupCondition(ItemCarryonEntity.getEntity(main, player.level))), true); + + return 1; + } + else if(carry.isCarrying(CarryType.PLAYER)) + { + log(source, "Carrying Player."); + } + } + + } + catch (CommandSyntaxException e) + { + } + + return 0; + } + + private static int handleClear(CommandSourceStack source, Collection players) + { + int cleared = 0; + for (ServerPlayer player : players) + { + + CarryOnData carry = CarryOnDataManager.getCarryData(player); + carry.clear(); + CarryOnDataManager.setCarryData(player, carry); + + cleared++; + } + + if (cleared != 1) + source.sendSuccess(Component.literal("Cleared " + cleared + " Items!"), true); + else + source.sendSuccess(Component.literal("Cleared " + cleared + " Item!"), true); + + return 1; + } + + private static void log(CommandSourceStack source, String toLog) + { + source.sendSuccess(Component.literal(toLog), true); + Constants.LOG.info(toLog); + } +} diff --git a/Common/src/main/java/tschipp/carryon/common/config/CarryConfig.java b/Common/src/main/java/tschipp/carryon/common/config/CarryConfig.java index 1fff280..37daaea 100644 --- a/Common/src/main/java/tschipp/carryon/common/config/CarryConfig.java +++ b/Common/src/main/java/tschipp/carryon/common/config/CarryConfig.java @@ -153,6 +153,12 @@ public class CarryConfig { public String[] placementStateExceptions = { "minecraft:chest[type]" }; + + @Property( + type = PropertyType.BOOLEAN, + description = "Whether Players can be picked up. Creative players can't be picked up in Survival Mode" + ) + public boolean pickupPlayers = true; } @Property( @@ -196,7 +202,7 @@ public class CarryConfig { description = "Blocks that cannot be picked up" ) public String[] forbiddenTiles = { - "#forge:immovable", "#forge:relocation_not_supported", "minecraft:end_portal", + "#forge:immovable", "#forge:relocation_not_supported", "minecraft:end_portal", "minecraft:piston_head", "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", diff --git a/Common/src/main/java/tschipp/carryon/common/scripting/CarryOnScript.java b/Common/src/main/java/tschipp/carryon/common/scripting/CarryOnScript.java new file mode 100644 index 0000000..72ce807 --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/common/scripting/CarryOnScript.java @@ -0,0 +1,185 @@ +package tschipp.carryon.common.scripting; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.Registry; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.Block; +import tschipp.carryon.common.scripting.CarryOnScript.ScriptObject.ScriptObjectBlock; +import tschipp.carryon.common.scripting.CarryOnScript.ScriptObject.ScriptObjectEntity; +import tschipp.carryon.common.scripting.Matchables.*; + +import java.util.Optional; + +public record CarryOnScript( + long priority, + ScriptObject scriptObject, + ScriptConditions scriptConditions, + ScriptRender scriptRender, + ScriptEffects scriptEffects) +{ + + public boolean isValid() + { + return (isBlock() ^ isEntity()) && (scriptConditions != ScriptConditions.EMPTY || scriptRender != ScriptRender.EMPTY || scriptEffects != ScriptEffects.EMPTY); + } + + public boolean isBlock() + { + return scriptObject.block() != ScriptObjectBlock.EMPTY; + } + + public boolean isEntity() + { + return scriptObject.entity() != ScriptObjectEntity.EMPTY; + } + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> // Given an instance + instance.group( + Codec.LONG.optionalFieldOf("priority", 0L).forGetter(CarryOnScript::priority), + ScriptObject.CODEC.fieldOf("object").forGetter(CarryOnScript::scriptObject), + ScriptConditions.CODEC.optionalFieldOf("conditions", ScriptConditions.EMPTY).forGetter(CarryOnScript::scriptConditions), + ScriptRender.CODEC.optionalFieldOf("render", ScriptRender.EMPTY).forGetter(CarryOnScript::scriptRender), + ScriptEffects.CODEC.optionalFieldOf("effects", ScriptEffects.EMPTY).forGetter(CarryOnScript::scriptEffects) + ).apply(instance, CarryOnScript::new) + ); + + public boolean fulfillsConditions(ServerPlayer player) + { + ScriptConditions cond = this.scriptConditions(); + + boolean achievement = cond.conditionAchievement.matches(player); + boolean gamemode = cond.conditionGamemode.matches(player.gameMode.getGameModeForPlayer().getId()); + boolean gamestage = cond.conditionGamestage.matches(player); + boolean position = cond.conditionPosition.matches(player); + boolean xp = cond.conditionXp.matches(player.experienceLevel); + boolean scoreboard = cond.conditionScoreboard.matches(player); + boolean effects = cond.conditionEffects.matches(player); + + return achievement && gamemode && gamestage && position && xp && scoreboard && effects; + } + + + public record ScriptObject(ScriptObjectBlock block, ScriptObjectEntity entity) + { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + ScriptObjectBlock.CODEC.optionalFieldOf("block", ScriptObjectBlock.EMPTY).forGetter(ScriptObject::block), + ScriptObjectEntity.CODEC.optionalFieldOf("entity", ScriptObjectEntity.EMPTY).forGetter(ScriptObject::entity) + ).apply(instance, ScriptObject::new) + ); + + public record ScriptObjectBlock( + Optional> typeNameBlock, + MaterialCondition typeMaterial, + NumberBoundCondition typeHardness, + NumberBoundCondition typeResistance, + NBTCondition typeBlockTag + ){ + public static final ScriptObjectBlock EMPTY = new ScriptObjectBlock(Optional.empty(), MaterialCondition.NONE, NumberBoundCondition.NONE, NumberBoundCondition.NONE, NBTCondition.NONE); + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + ResourceKey.codec(Registry.BLOCK_REGISTRY).optionalFieldOf("name").forGetter(ScriptObjectBlock::typeNameBlock), + MaterialCondition.CODEC.optionalFieldOf("material", MaterialCondition.NONE).forGetter(ScriptObjectBlock::typeMaterial), + NumberBoundCondition.CODEC.optionalFieldOf("hardness", NumberBoundCondition.NONE).forGetter(ScriptObjectBlock::typeHardness), + NumberBoundCondition.CODEC.optionalFieldOf("resistance", NumberBoundCondition.NONE).forGetter(ScriptObjectBlock::typeResistance), + NBTCondition.CODEC.optionalFieldOf("nbt", NBTCondition.NONE).forGetter(ScriptObjectBlock::typeBlockTag) + ).apply(instance, ScriptObjectBlock::new) + ); + } + + public record ScriptObjectEntity( + Optional>> typeNameEntity, + NumberBoundCondition typeHealth, + NumberBoundCondition typeHeight, + NumberBoundCondition typeWidth, + NBTCondition typeEntityTag + ){ + public static final ScriptObjectEntity EMPTY = new ScriptObjectEntity(Optional.empty(), NumberBoundCondition.NONE, NumberBoundCondition.NONE, NumberBoundCondition.NONE, NBTCondition.NONE); + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + ResourceKey.codec(Registry.ENTITY_TYPE_REGISTRY).optionalFieldOf("name").forGetter(ScriptObjectEntity::typeNameEntity), + NumberBoundCondition.CODEC.optionalFieldOf("health", NumberBoundCondition.NONE).forGetter(ScriptObjectEntity::typeHealth), + NumberBoundCondition.CODEC.optionalFieldOf("height", NumberBoundCondition.NONE).forGetter(ScriptObjectEntity::typeHeight), + NumberBoundCondition.CODEC.optionalFieldOf("width", NumberBoundCondition.NONE).forGetter(ScriptObjectEntity::typeWidth), + NBTCondition.CODEC.optionalFieldOf("nbt", NBTCondition.NONE).forGetter(ScriptObjectEntity::typeEntityTag) + ).apply(instance, ScriptObjectEntity::new) + ); + } + } + + public record ScriptConditions( + GamestageCondition conditionGamestage, + AdvancementCondition conditionAchievement, + NumberBoundCondition conditionXp, + NumberBoundCondition conditionGamemode, + ScoreboardCondition conditionScoreboard, + PositionCondition conditionPosition, + EffectsCondition conditionEffects + ){ + public static final ScriptConditions EMPTY = new ScriptConditions(GamestageCondition.NONE, AdvancementCondition.NONE, NumberBoundCondition.NONE, NumberBoundCondition.NONE, ScoreboardCondition.NONE, PositionCondition.NONE, EffectsCondition.NONE); + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + GamestageCondition.CODEC.optionalFieldOf("gamestage", GamestageCondition.NONE).forGetter(ScriptConditions::conditionGamestage), + AdvancementCondition.CODEC.optionalFieldOf("advancement", AdvancementCondition.NONE).forGetter(ScriptConditions::conditionAchievement), + NumberBoundCondition.CODEC.optionalFieldOf("xp", NumberBoundCondition.NONE).forGetter(ScriptConditions::conditionXp), + NumberBoundCondition.CODEC.optionalFieldOf("gamemode", NumberBoundCondition.NONE).forGetter(ScriptConditions::conditionGamemode), + ScoreboardCondition.CODEC.optionalFieldOf("scoreboard", ScoreboardCondition.NONE).forGetter(ScriptConditions::conditionScoreboard), + PositionCondition.CODEC.optionalFieldOf("position", PositionCondition.NONE).forGetter(ScriptConditions::conditionPosition), + EffectsCondition.CODEC.optionalFieldOf("effects", EffectsCondition.NONE).forGetter(ScriptConditions::conditionEffects) + ).apply(instance, ScriptConditions::new) + ); + } + + public record ScriptRender( + Optional> renderNameBlock, + Optional>> renderNameEntity, + Optional renderNBT, + OptionalVec3 renderTranslation, + OptionalVec3 renderRotation, + OptionalVec3 renderscale, + OptionalVec3 renderRotationLeftArm, + OptionalVec3 renderRotationRightArm, + boolean renderLeftArm, + boolean renderRightArm + ){ + public static final ScriptRender EMPTY = new ScriptRender(Optional.empty(), Optional.empty(), Optional.empty(), OptionalVec3.NONE, OptionalVec3.NONE, OptionalVec3.NONE, OptionalVec3.NONE, OptionalVec3.NONE, true, true); + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + ResourceKey.codec(Registry.BLOCK_REGISTRY).optionalFieldOf("name_block").forGetter(ScriptRender::renderNameBlock), + ResourceKey.codec(Registry.ENTITY_TYPE_REGISTRY).optionalFieldOf("name_entity").forGetter(ScriptRender::renderNameEntity), + CompoundTag.CODEC.optionalFieldOf("nbt").forGetter(ScriptRender::renderNBT), + OptionalVec3.CODEC.optionalFieldOf("translation", OptionalVec3.NONE).forGetter(ScriptRender::renderTranslation), + OptionalVec3.CODEC.optionalFieldOf("rotation", OptionalVec3.NONE).forGetter(ScriptRender::renderRotation), + OptionalVec3.CODEC.optionalFieldOf("scale", OptionalVec3.NONE).forGetter(ScriptRender::renderscale), + OptionalVec3.CODEC.optionalFieldOf("rotation_left_arm", OptionalVec3.NONE).forGetter(ScriptRender::renderRotationLeftArm), + OptionalVec3.CODEC.optionalFieldOf("rotation_right_arm", OptionalVec3.NONE).forGetter(ScriptRender::renderRotationRightArm), + Codec.BOOL.optionalFieldOf("render_left_arm", true).forGetter(ScriptRender::renderLeftArm), + Codec.BOOL.optionalFieldOf("render_right_arm", true).forGetter(ScriptRender::renderRightArm) + ).apply(instance, ScriptRender::new) + ); + } + + public record ScriptEffects( + String commandInit, + String commandLoop, + String commandPlace + ){ + public static final ScriptEffects EMPTY = new ScriptEffects("", "", ""); + + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + Codec.STRING.optionalFieldOf("commandPickup", "").forGetter(ScriptEffects::commandInit), + Codec.STRING.optionalFieldOf("commandLoop", "").forGetter(ScriptEffects::commandLoop), + Codec.STRING.optionalFieldOf("commandPlace", "").forGetter(ScriptEffects::commandPlace) + ).apply(instance, ScriptEffects::new) + ); + } +} diff --git a/Common/src/main/java/tschipp/carryon/common/scripting/Matchables.java b/Common/src/main/java/tschipp/carryon/common/scripting/Matchables.java new file mode 100644 index 0000000..2632f0d --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/common/scripting/Matchables.java @@ -0,0 +1,402 @@ +package tschipp.carryon.common.scripting; + +import com.mojang.serialization.Codec; +import net.minecraft.advancements.Advancement; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.ServerAdvancementManager; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.scores.Objective; +import net.minecraft.world.scores.Score; +import net.minecraft.world.scores.Scoreboard; +import tschipp.carryon.platform.Services; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public final class Matchables +{ + public interface Matchable + { + boolean matches(T elem); + } + + private static float getValueFromString(String toGetFrom, String key, float defaultValue) + { + if (toGetFrom == null || toGetFrom.isEmpty()) + return defaultValue; + + String[] s = toGetFrom.split(","); + for (String string : s) + { + if (string.contains(key) && string.contains("=")) + { + float numb = 0; + string = string.replace(key + "=", ""); + + try + { + numb = Float.parseFloat(string); + } + catch (Exception e) + { + } + + return numb; + } + } + + return defaultValue; + } + + public record NumberBoundCondition(String bounds) implements Matchable + { + public static final Codec CODEC = Codec.STRING.xmap(NumberBoundCondition::new, NumberBoundCondition::bounds); + + public static final NumberBoundCondition NONE = new NumberBoundCondition(""); + + @Override + public boolean matches(Number num) + { + double number = num.doubleValue(); + + if (bounds == null || bounds.isEmpty()) + return true; + + try + { + if (bounds.contains("<=")) + return number <= Double.parseDouble(bounds.replace("<=", "")); + if (bounds.contains(">=")) + return number >= Double.parseDouble(bounds.replace(">=", "")); + if (bounds.contains("<")) + return number < Double.parseDouble(bounds.replace("<", "")); + if (bounds.contains(">")) + return number > Double.parseDouble(bounds.replace(">", "")); + if (bounds.contains("=")) + return number == Double.parseDouble(bounds.replace("=", "")); + else + return number == Double.parseDouble(bounds); + + } + catch (Exception e) + { + throw new RuntimeException("Error while parsing Number bound for string: "+ bounds + ". Error: " + e.getMessage()); + } + } + } + + public record MaterialCondition(String material) implements Matchable + { + public static final Codec CODEC = Codec.STRING.xmap(MaterialCondition::new, MaterialCondition::material); + + public static final MaterialCondition NONE = new MaterialCondition(""); + + @Override + public boolean matches(Material material) + { + if (this.material == null || this.material.isEmpty()) + return true; + + switch (this.material) { + case "air": + return material == Material.AIR; + case "anvil": + return material == Material.HEAVY_METAL; + case "barrier": + return material == Material.BARRIER; + case "cactus": + return material == Material.CACTUS; + case "cake": + return material == Material.CAKE; + case "carpet": + return material == Material.CLOTH_DECORATION; + case "clay": + return material == Material.CLAY; + case "cloth": + return material == Material.WOOL; + case "dragon_egg": + return material == Material.EGG; + case "fire": + return material == Material.FIRE; + case "glass": + return material == Material.GLASS; + case "gourd": + return material == Material.VEGETABLE; + case "grass": + return material == Material.GRASS; + case "ground": + return material == Material.GRASS; + case "ice": + return material == Material.ICE; + case "iron": + return material == Material.METAL; + case "lava": + return material == Material.LAVA; + case "leaves": + return material == Material.LEAVES; + case "packed_ice": + return material == Material.ICE_SOLID; + case "piston": + return material == Material.PISTON; + case "plants": + return material == Material.PLANT; + case "portal": + return material == Material.PORTAL; + case "redstone_light": + return material == Material.BUILDABLE_GLASS; + case "rock": + return material == Material.STONE; + case "sand": + return material == Material.SAND; + case "snow": + return material == Material.TOP_SNOW; + case "sponge": + return material == Material.SPONGE; + case "structure_void": + return material == Material.STRUCTURAL_AIR; + case "tnt": + return material == Material.EXPLOSIVE; + case "vine": + return material == Material.PLANT; + case "water": + return material == Material.WATER; + case "web": + return material == Material.WEB; + case "wood": + return material == Material.WOOD; + default: + return false; + } + } + } + + public record AdvancementCondition(String advancement) implements Matchable + { + public static final Codec CODEC = Codec.STRING.xmap(AdvancementCondition::new, AdvancementCondition::advancement); + + public static final AdvancementCondition NONE = new AdvancementCondition(""); + + @Override + public boolean matches(ServerPlayer player) + { + ServerAdvancementManager manager = player.server.getAdvancements(); + Advancement adv = manager.getAdvancement(new ResourceLocation(advancement.isEmpty() ? "" : advancement)); + + boolean achievement = adv == null ? true : player.getAdvancements().getOrStartProgress(adv).isDone(); + return achievement; + } + } + + public record GamestageCondition(String gamestage) implements Matchable + { + public static final Codec CODEC = Codec.STRING.xmap(GamestageCondition::new, GamestageCondition::gamestage); + + public static final GamestageCondition NONE = new GamestageCondition(""); + + @Override + public boolean matches(ServerPlayer elem) + { + if(!Services.PLATFORM.isModLoaded("gamestages")) + return true; + + //TODO: Gamestages + + return true; + } + } + + public record ScoreboardCondition(String cond) implements Matchable + { + public static final Codec CODEC = Codec.STRING.xmap(ScoreboardCondition::new, ScoreboardCondition::cond); + + public static final ScoreboardCondition NONE = new ScoreboardCondition(""); + + + @Override + public boolean matches(ServerPlayer player) + { + if (cond == null || cond.isEmpty()) + return true; + + Scoreboard score = player.getScoreboard(); + String numb; + String scorename; + int iE = cond.indexOf("="); + int iG = cond.indexOf(">"); + int iL = cond.indexOf("<"); + + if (iG == -1 ? true : iE < iG && iL == -1 ? true : iE < iL && iE != -1) + numb = cond.substring(iE); + else if (iE == -1 ? true : iG < iE && iL == -1 ? true : iG < iL && iG != -1) + numb = cond.substring(iG); + else + numb = cond.substring(iL); + + scorename = cond.replace(numb, ""); + Map o = score.getPlayerScores(player.getGameProfile().getName()); + if (o != null) + { + Score sc = o.get(score.getObjective(scorename)); + if (sc != null) + { + int points = sc.getScore(); + + return new NumberBoundCondition(numb).matches(points); + } + } + + return false; + } + } + + public record PositionCondition(String cond) implements Matchable + { + public static final Codec CODEC = Codec.STRING.xmap(PositionCondition::new, PositionCondition::cond); + + public static final PositionCondition NONE = new PositionCondition(""); + + + @Override + public boolean matches(ServerPlayer elem) + { + if (cond == null || cond.isEmpty()) + return true; + + BlockPos blockpos = new BlockPos(getValueFromString(cond, "x", 0), getValueFromString(cond, "y", 0), getValueFromString(cond, "z", 0)); + BlockPos expand = new BlockPos(getValueFromString(cond, "dx", 0), getValueFromString(cond, "dy", 0), getValueFromString(cond, "dz", 0)); + BlockPos expanded = blockpos.offset(expand); + BlockPos pos = elem.blockPosition(); + + boolean x = pos.getX() >= blockpos.getX() && pos.getX() <= expanded.getX() || blockpos.getX() == 0; + boolean y = pos.getY() >= blockpos.getY() && pos.getY() <= expanded.getY() || blockpos.getY() == 0; + boolean z = pos.getZ() >= blockpos.getZ() && pos.getZ() <= expanded.getZ() || blockpos.getZ() == 0; + + return x && y && z; + } + } + + public record EffectsCondition(String effects) implements Matchable + { + public static final Codec CODEC = Codec.STRING.xmap(EffectsCondition::new, EffectsCondition::effects); + + public static final EffectsCondition NONE = new EffectsCondition(""); + + @Override + public boolean matches(ServerPlayer player) + { + if (effects == null || effects.isEmpty()) + return true; + + Collection fx = player.getActiveEffects(); + String[] potions = effects.split(","); + + List names = new ArrayList<>(); + List levels = new ArrayList<>(); + + for (String pot : potions) + { + if (pot.contains("#")) + { + String level = pot.substring(pot.indexOf("#")); + String name = pot.substring(0, pot.indexOf("#")); + level = level.replace("#", ""); + int lev = 0; + try + { + lev = Integer.parseInt(level); + } + catch (Exception e) + { + } + + levels.add(lev); + names.add(name); + } + else + { + levels.add(0); + names.add(pot); + } + } + + int matches = 0; + for (MobEffectInstance effect : fx) + { + int amp = effect.getAmplifier(); + String name = Registry.MOB_EFFECT.getKey(effect.getEffect()).toString(); + + if (names.contains(name)) + { + int idx = names.indexOf(name); + int lev = levels.get(idx); + + if (lev == amp) + matches++; + } + } + + return matches == potions.length; + } + } + + public record NBTCondition(CompoundTag tag) implements Matchable + { + public static final Codec CODEC = CompoundTag.CODEC.xmap(NBTCondition::new, NBTCondition::tag); + + public static final NBTCondition NONE = new NBTCondition(new CompoundTag()); + + @Override + public boolean matches(CompoundTag other) + { + if(other == null) + return true; + return NbtUtils.compareNbt(tag, other, true); + } + } + + public static class OptionalVec3 { + + public static final Codec CODEC = Codec.STRING.xmap(OptionalVec3::new, OptionalVec3::source); + + public static final OptionalVec3 NONE = new OptionalVec3(""); + + String source; + Vec3 vec; + + public OptionalVec3(String source) + { + this.source = source; + double x = getValueFromString(source, "x", 0); + double y = getValueFromString(source, "y", 0); + double z = getValueFromString(source, "z", 0); + vec = new Vec3(x, y, z); + } + + private String source() + { + return source; + } + + public Vec3 getVec() + { + return vec; + } + + public Vec3 getVec(double defaultValue) + { + double x = vec.x == 0f ? defaultValue : vec.x; + double y = vec.y == 0f ? defaultValue : vec.y; + double z = vec.z == 0f ? defaultValue : vec.z; + return new Vec3(x, y, z); + } + } +} diff --git a/Common/src/main/java/tschipp/carryon/common/scripting/ScriptManager.java b/Common/src/main/java/tschipp/carryon/common/scripting/ScriptManager.java new file mode 100644 index 0000000..89914aa --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/common/scripting/ScriptManager.java @@ -0,0 +1,93 @@ +package tschipp.carryon.common.scripting; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Material; +import tschipp.carryon.Constants; +import tschipp.carryon.common.scripting.CarryOnScript.ScriptObject.ScriptObjectBlock; +import tschipp.carryon.common.scripting.CarryOnScript.ScriptObject.ScriptObjectEntity; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class ScriptManager +{ + public static final List SCRIPTS = new ArrayList<>(); + + public static Optional inspectBlock(BlockState state, Level level, BlockPos pos, @Nullable CompoundTag tag) + { + if (!Constants.COMMON_CONFIG.settings.useScripts) + return Optional.empty(); + + Block block = state.getBlock(); + Material material = state.getMaterial(); + float hardness = state.getDestroySpeed(level, pos); + float resistance = block.getExplosionResistance(); + + for (CarryOnScript script : SCRIPTS) + { + if (script.isBlock() && matchesAll(script, block, material, hardness, resistance, tag)) + return Optional.of(script); + } + + return Optional.empty(); + } + + public static Optional inspectEntity(Entity entity) + { + if (!Constants.COMMON_CONFIG.settings.useScripts) + return Optional.empty(); + + float height = entity.getBbHeight(); + float width = entity.getBbWidth(); + float health = entity instanceof LivingEntity ? ((LivingEntity) entity).getHealth() : 0.0f; + CompoundTag tag = new CompoundTag(); + entity.save(tag); + + for (CarryOnScript script : SCRIPTS) + { + if (script.isEntity() && matchesAll(script, entity, height, width, health, tag)) + return Optional.of(script); + } + + return Optional.empty(); + } + + private static boolean matchesAll(CarryOnScript script, Entity entity, float height, float width, float health, CompoundTag tag) + { + ScriptObjectEntity scEntity = script.scriptObject().entity(); + + boolean matchname = true; + if(scEntity.typeNameEntity().isPresent()) + matchname = entity.getType().equals(Registry.ENTITY_TYPE.get(scEntity.typeNameEntity().get())); + boolean matchheight = scEntity.typeHeight().matches(height); + boolean matchwidth = scEntity.typeWidth().matches(width); + boolean matchhealth = scEntity.typeHealth().matches(health); + boolean matchnbt = scEntity.typeEntityTag().matches(tag); + + return matchname && matchheight && matchwidth && matchhealth && matchnbt; + } + + private static boolean matchesAll(CarryOnScript script, Block block, Material material, float hardness, float resistance, CompoundTag nbt) + { + ScriptObjectBlock scBlock = script.scriptObject().block(); + + boolean matchblock = true; + if(scBlock.typeNameBlock().isPresent()) + matchblock = block == Registry.BLOCK.get(scBlock.typeNameBlock().get()); + boolean matchnbt = scBlock.typeBlockTag().matches(nbt); + boolean matchmaterial = scBlock.typeMaterial().matches(material); + boolean matchhardness = scBlock.typeHardness().matches(hardness); + boolean matchresistance = scBlock.typeResistance().matches(resistance); + + return matchnbt && matchblock && matchmaterial && matchhardness && matchresistance; + } +} diff --git a/Common/src/main/java/tschipp/carryon/common/scripting/ScriptReloadListener.java b/Common/src/main/java/tschipp/carryon/common/scripting/ScriptReloadListener.java new file mode 100644 index 0000000..258ce6d --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/common/scripting/ScriptReloadListener.java @@ -0,0 +1,65 @@ +package tschipp.carryon.common.scripting; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.JsonOps; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; +import tschipp.carryon.Constants; +import tschipp.carryon.networking.clientbound.ClientboundSyncScriptsPacket; +import tschipp.carryon.platform.Services; + +import java.util.Collections; +import java.util.Map; + +public class ScriptReloadListener extends SimpleJsonResourceReloadListener +{ + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + + public ScriptReloadListener() + { + super(GSON, "carryon/scripts"); + } + + @Override + protected void apply(Map objects, ResourceManager manager, ProfilerFiller profiler) + { + ScriptManager.SCRIPTS.clear(); + + try { + objects.forEach((path, jsonElem) -> { + DataResult res = CarryOnScript.CODEC.parse(JsonOps.INSTANCE, jsonElem); + CarryOnScript script = res.getOrThrow(false, (s) -> {throw new RuntimeException(s);}); + + if (script.isValid()) + ScriptManager.SCRIPTS.add(script); + }); + } + catch (Exception e) + { + e.printStackTrace(); + } + + Collections.sort(ScriptManager.SCRIPTS, (s1, s2) -> Long.compare(s2.priority(), s1.priority())); + } + + public static void syncScriptsWithClient(ServerPlayer player) + { + if (player != null) + { + DataResult result = Codec.list(CarryOnScript.CODEC).encodeStart(NbtOps.INSTANCE, ScriptManager.SCRIPTS); + Tag tag = result.getOrThrow(false, s -> {throw new RuntimeException("Error while synching Carry On Scripts: " + s);}); + + Services.PLATFORM.sendPacketToPlayer(Constants.PACKET_ID_SYNC_SCRIPTS, new ClientboundSyncScriptsPacket(tag), player); + } + } +} + diff --git a/Common/src/main/java/tschipp/carryon/mixin/EntityMixin.java b/Common/src/main/java/tschipp/carryon/mixin/EntityMixin.java new file mode 100644 index 0000000..cbf77a7 --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/mixin/EntityMixin.java @@ -0,0 +1,87 @@ +package tschipp.carryon.mixin; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Entity.MoveFunction; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import tschipp.carryon.Constants; +import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.CarryOnData.CarryType; +import tschipp.carryon.common.carry.CarryOnDataManager; +import tschipp.carryon.networking.clientbound.ClientboundStartRidingPacket; +import tschipp.carryon.platform.Services; + +@Mixin(Entity.class) +public abstract class EntityMixin +{ + @Shadow + public boolean hasPassenger(Entity pEntity) {throw new IllegalStateException("EntityMixin application failed");} + + @Shadow public abstract void onPassengerTurned(Entity $$0); + + @Inject(method = "positionRider(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity$MoveFunction;)V", at = @At("HEAD"), cancellable = true) + private void onPositionPassenger(Entity entity, MoveFunction move, CallbackInfo ci) + { + if((Object)this instanceof Player thisPlayer && entity instanceof Player otherPlayer) + { + if(hasPassenger(otherPlayer) && CarryOnDataManager.getCarryData(thisPlayer).isCarrying(CarryType.PLAYER)) + { + Vec3 forward = new Vec3(0, 0, 0.6); + Vec3 otherPos = thisPlayer.position().add(forward.yRot((float) Math.toRadians(-thisPlayer.yBodyRot))); + otherPos = otherPos.add(0, 0.4,0); + move.accept(otherPlayer, otherPos.x, otherPos.y, otherPos.z); + ((Entity)((Object)this)).onPassengerTurned(otherPlayer); + ci.cancel(); + } + } + + } + + @Inject(method = "getDismountLocationForPassenger(Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/phys/Vec3;", at = @At("HEAD")) + private void onDismountPassenger(LivingEntity living, CallbackInfoReturnable cir) + { + if((Object)this instanceof Player thisPlayer && living instanceof Player otherPlayer) + { + CarryOnData carry = CarryOnDataManager.getCarryData(thisPlayer); + if(carry.isCarrying(CarryType.PLAYER)) + { + carry.clear(); + CarryOnDataManager.setCarryData(thisPlayer, carry); + Services.PLATFORM.sendPacketToPlayer(Constants.PACKET_ID_START_RIDING, new ClientboundStartRidingPacket(otherPlayer.getId(), false), (ServerPlayer) thisPlayer); + } + } + } + + @Inject(method = "onPassengerTurned(Lnet/minecraft/world/entity/Entity;)V", at = @At("HEAD")) + private void onPassengerTurned(Entity toUpdate, CallbackInfo ci) + { + if((Object)this instanceof Player thisPlayer && toUpdate instanceof Player otherPlayer) + { + CarryOnData carry = CarryOnDataManager.getCarryData(thisPlayer); + if(carry.isCarrying(CarryType.PLAYER)) { + this.clampRotation(toUpdate); + } + } + } + + @Unique + private void clampRotation(Entity pEntityToUpdate) { + Entity thisEntity = (Entity)((Object)this); + pEntityToUpdate.setYBodyRot(thisEntity.getYRot()); + float f = Mth.wrapDegrees(pEntityToUpdate.getYRot() - thisEntity.getYRot()); + float f1 = Mth.clamp(f, -30.0F, 30.0F); + pEntityToUpdate.yRotO += f1 - f; + pEntityToUpdate.setYRot(pEntityToUpdate.getYRot() + f1 - f); + pEntityToUpdate.setYHeadRot(pEntityToUpdate.getYRot()); + } +} diff --git a/Common/src/main/java/tschipp/carryon/mixin/HumanoidModelMixin.java b/Common/src/main/java/tschipp/carryon/mixin/HumanoidModelMixin.java index 0df344f..587bd38 100644 --- a/Common/src/main/java/tschipp/carryon/mixin/HumanoidModelMixin.java +++ b/Common/src/main/java/tschipp/carryon/mixin/HumanoidModelMixin.java @@ -4,13 +4,17 @@ 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 net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; 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.client.render.CarryRenderHelper; import tschipp.carryon.common.carry.CarryOnData; import tschipp.carryon.common.carry.CarryOnDataManager; +import tschipp.carryon.common.scripting.CarryOnScript.ScriptRender; @Mixin(HumanoidModel.class) public class HumanoidModelMixin { @@ -24,32 +28,50 @@ public class HumanoidModelMixin { @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; + float x = 1.0f + (sneaking ? 0.2f : 0.0f) + (carry.isCarrying(CarryOnData.CarryType.BLOCK) ? 0.0f : 0.3f); + float z = 0.05f; - rightArm.yRot = 0; - leftArm.yRot = 0; + float width = CarryRenderHelper.getRenderWidth(player); + float offset = Math.min((width - 1) / 1.5f, 0.2f); - rightArm.xRot = -x; - leftArm.xRot = -x; + if(carry.getActiveScript().isPresent()) + { + ScriptRender render = carry.getActiveScript().get().scriptRender(); + boolean renderLeft = render.renderLeftArm(); + boolean renderRight = render.renderRightArm(); + + Vec3 rotLeft = render.renderRotationLeftArm().getVec(); + Vec3 rotRight = render.renderRotationRightArm().getVec(); + + if(renderLeft) + changeRotation(leftArm, (float) rotLeft.x, (float) rotLeft.y, (float) rotLeft.z); + + if(renderRight) + changeRotation(rightArm, (float) rotRight.x, (float) rotRight.y, (float) rotRight.z); + } + else { + changeRotation(rightArm, -x, offset, -z); + changeRotation(leftArm, -x, -offset, z); + } - rightArm.zRot = z; - leftArm.zRot = -z; } } } + @Unique + private void changeRotation(ModelPart part, float x, float y, float z) + { + part.xRot = x; + part.yRot = y; + part.zRot = z; + } + } diff --git a/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java b/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java index 22159ea..576649b 100644 --- a/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java +++ b/Common/src/main/java/tschipp/carryon/mixin/InventoryMixin.java @@ -1,11 +1,15 @@ package tschipp.carryon.mixin; +import net.minecraft.core.NonNullList; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; 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.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import tschipp.carryon.common.carry.CarryOnDataManager; @@ -15,16 +19,26 @@ public class InventoryMixin @Shadow public Player player; -// @Redirect(method = "selected:I", at = @At()) -// private void setSelected(Inventory inv, int value) -// { -// -// } + @Shadow + public int selected; + + @Shadow + public NonNullList items; + + @Redirect(method = "getFreeSlot()I", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/core/NonNullList;get(I)Ljava/lang/Object;")) + private E getFreeSlotEmptyCheck(NonNullList instance, int i) + { + if(i == selected && CarryOnDataManager.getCarryData(player).isCarrying()) + { + return (E) new ItemStack(Blocks.STONE, 1); + } + else + return instance.get(i); + } @Inject(method = "setPickedItem(Lnet/minecraft/world/item/ItemStack;)V", at = @At("HEAD"), cancellable = true) private void onPickBlock(CallbackInfo info) { - System.out.println("onPickBlock"); if(CarryOnDataManager.getCarryData(player).isCarrying()) info.cancel(); } @@ -32,7 +46,6 @@ public class InventoryMixin @Inject(method = "pickSlot(I)V", at = @At("HEAD"), cancellable = true) private void onPickSlot(int slot, CallbackInfo info) { - System.out.println("onPickSlot"); if(CarryOnDataManager.getCarryData(player).isCarrying()) info.cancel(); } @@ -40,9 +53,6 @@ public class InventoryMixin @Inject(method = "swapPaint(D)V", at = @At("HEAD"), cancellable = true) private void onSwapPaint(double direction, CallbackInfo info) { - System.out.println(player); - System.out.println(CarryOnDataManager.getCarryData(player).getNbt()); - System.out.println("onSwapPaint"); if(CarryOnDataManager.getCarryData(player).isCarrying()) info.cancel(); } diff --git a/Common/src/main/java/tschipp/carryon/mixin/PlayerMixin.java b/Common/src/main/java/tschipp/carryon/mixin/PlayerMixin.java index 9e31831..567b461 100644 --- a/Common/src/main/java/tschipp/carryon/mixin/PlayerMixin.java +++ b/Common/src/main/java/tschipp/carryon/mixin/PlayerMixin.java @@ -36,10 +36,9 @@ public abstract class PlayerMixin extends LivingEntity { @Inject(method = "readAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V", at = @At("RETURN")) private void onReadAdditionalSaveData(CompoundTag tag, CallbackInfo info) { - if(tag.contains("CarryOnData")) - { + if (tag.contains("CarryOnData")) { CarryOnData data = new CarryOnData(tag.getCompound("CarryOnData")); - CarryOnDataManager.setCarryData((Player)(Object)this, data); + CarryOnDataManager.setCarryData((Player) (Object) this, data); } } diff --git a/Common/src/main/java/tschipp/carryon/networking/PacketBase.java b/Common/src/main/java/tschipp/carryon/networking/PacketBase.java new file mode 100644 index 0000000..115f8cf --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/networking/PacketBase.java @@ -0,0 +1,11 @@ +package tschipp.carryon.networking; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Player; + +public abstract class PacketBase +{ + public abstract void toBytes(FriendlyByteBuf buf); + + public abstract void handle(Player player); +} diff --git a/Common/src/main/java/tschipp/carryon/networking/clientbound/ClientboundStartRidingPacket.java b/Common/src/main/java/tschipp/carryon/networking/clientbound/ClientboundStartRidingPacket.java new file mode 100644 index 0000000..57434a6 --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/networking/clientbound/ClientboundStartRidingPacket.java @@ -0,0 +1,42 @@ +package tschipp.carryon.networking.clientbound; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import tschipp.carryon.networking.PacketBase; + +public class ClientboundStartRidingPacket extends PacketBase +{ + int entityId; + boolean ride; + + public ClientboundStartRidingPacket(FriendlyByteBuf buf) + { + this.entityId = buf.readInt(); + this.ride = buf.readBoolean(); + } + + public ClientboundStartRidingPacket(int id, boolean ride) + { + this.entityId = id; + this.ride = ride; + } + + @Override + public void toBytes(FriendlyByteBuf buf) + { + buf.writeInt(entityId); + buf.writeBoolean(ride); + } + + @Override + public void handle(Player player) + { + Entity otherPlayer = player.level.getEntity(this.entityId); + if(otherPlayer != null) + if(ride) + otherPlayer.startRiding(player); + else + otherPlayer.stopRiding(); + } +} diff --git a/Common/src/main/java/tschipp/carryon/networking/clientbound/ClientboundSyncScriptsPacket.java b/Common/src/main/java/tschipp/carryon/networking/clientbound/ClientboundSyncScriptsPacket.java new file mode 100644 index 0000000..6a44e02 --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/networking/clientbound/ClientboundSyncScriptsPacket.java @@ -0,0 +1,46 @@ +package tschipp.carryon.networking.clientbound; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Player; +import tschipp.carryon.common.scripting.CarryOnScript; +import tschipp.carryon.common.scripting.ScriptManager; +import tschipp.carryon.networking.PacketBase; + +import java.util.List; + +public class ClientboundSyncScriptsPacket extends PacketBase +{ + private Tag serialized; + + public ClientboundSyncScriptsPacket(FriendlyByteBuf buf) + { + this.serialized = buf.readNbt().get("data"); + } + + public ClientboundSyncScriptsPacket(Tag serialized) + { + this.serialized = serialized; + } + + @Override + public void toBytes(FriendlyByteBuf buf) + { + CompoundTag tag = new CompoundTag(); + tag.put("data", serialized); + buf.writeNbt(tag); + } + + @Override + public void handle(Player player) + { + DataResult> res = Codec.list(CarryOnScript.CODEC).parse(NbtOps.INSTANCE, serialized); + List scripts = res.getOrThrow(false, (s) -> {throw new RuntimeException("Failed deserializing carry on scripts on the client: " + s);}); + ScriptManager.SCRIPTS.clear(); + ScriptManager.SCRIPTS.addAll(scripts); + } +} diff --git a/Common/src/main/java/tschipp/carryon/networking/serverbound/ServerboundCarryKeyPressedPacket.java b/Common/src/main/java/tschipp/carryon/networking/serverbound/ServerboundCarryKeyPressedPacket.java new file mode 100644 index 0000000..9ba406e --- /dev/null +++ b/Common/src/main/java/tschipp/carryon/networking/serverbound/ServerboundCarryKeyPressedPacket.java @@ -0,0 +1,37 @@ +package tschipp.carryon.networking.serverbound; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.CarryOnDataManager; +import tschipp.carryon.networking.PacketBase; + +public class ServerboundCarryKeyPressedPacket extends PacketBase +{ + boolean pressed; + + public ServerboundCarryKeyPressedPacket(FriendlyByteBuf buf) + { + this.pressed = buf.readBoolean(); + } + + public ServerboundCarryKeyPressedPacket(boolean pressed) + { + this.pressed = pressed; + } + + @Override + public void toBytes(FriendlyByteBuf buf) + { + buf.writeBoolean(pressed); + } + + @Override + public void handle(Player player) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + carry.setKeyPressed(this.pressed); + CarryOnDataManager.setCarryData(player, carry); + } +} diff --git a/Common/src/main/java/tschipp/carryon/platform/services/IPlatformHelper.java b/Common/src/main/java/tschipp/carryon/platform/services/IPlatformHelper.java index ce27a98..e8b4fa4 100644 --- a/Common/src/main/java/tschipp/carryon/platform/services/IPlatformHelper.java +++ b/Common/src/main/java/tschipp/carryon/platform/services/IPlatformHelper.java @@ -1,6 +1,14 @@ package tschipp.carryon.platform.services; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; import tschipp.carryon.config.BuiltConfig; +import tschipp.carryon.networking.PacketBase; + +import java.util.function.BiConsumer; +import java.util.function.Function; public interface IPlatformHelper { @@ -27,4 +35,13 @@ public interface IPlatformHelper { boolean isDevelopmentEnvironment(); void registerConfig(BuiltConfig cfg); + + void registerServerboundPacket(ResourceLocation id, int numericalId, Class clazz, BiConsumer writer, Function reader, BiConsumer handler); + + void registerClientboundPacket(ResourceLocation id, int numericalId, Class clazz, BiConsumer writer, Function reader, BiConsumer handler); + + void sendPacketToServer(ResourceLocation id, PacketBase packet); + + void sendPacketToPlayer(ResourceLocation id, PacketBase packet, ServerPlayer player); + } diff --git a/Common/src/main/resources/assets/carryon/lang/en_ud.json b/Common/src/main/resources/assets/carryon/lang/en_ud.json new file mode 100644 index 0000000..77a6461 --- /dev/null +++ b/Common/src/main/resources/assets/carryon/lang/en_ud.json @@ -0,0 +1,16 @@ +{ + "carryon.category.settings": "sᵷuᴉʇʇǝS", + "carryon.category.blacklist": "ʇsᴉꞁʞɔɐꞁᗺ", + "carryon.category.modeloverrides": "(pǝɔuɐʌpⱯ) sǝpᴉɹɹǝʌO ꞁǝpoW", + "carryon.category.custompickupconditions": "(pǝɔuɐʌpⱯ) suoᴉʇᴉpuoƆ dnʞɔᴉԀ ɯoʇsnƆ", + "carryon.category.whitelist": "ʇsᴉꞁǝʇᴉɥM", + + "carryon.general.modeloverrides.modeloverrides": "sǝpᴉɹɹǝʌO ꞁǝpoW", + "carryon.general.blacklist.forbiddenentities": "dn ʞɔᴉd ʇouuɐɔ ɹǝʎɐꞁԀ ǝɥʇ ʇɐɥʇ sǝᴉʇᴉʇuƎ", + "carryon.general.blacklist.forbiddentiles": "dn ʞɔᴉd ʇouuɐɔ ɹǝʎɐꞁԀ ǝɥʇ ʇɐɥʇ sʞɔoꞁᗺ", + "carryon.category.custompickupconditions.custompickupconditionsblocks": "suoᴉʇᴉpuoƆ dnʞɔᴉԀ ʞɔoꞁᗺ ɯoʇsnƆ", + "carryon.category.custompickupconditions.custompickupconditionsentities": "suoᴉʇᴉpuoƆ dnʞɔᴉԀ ʎʇᴉʇuƎ ɯoʇsnƆ", + + "key.carry.desc": "ʎɹɹɐƆ", + "key.carry.category": "uO ʎɹɹɐƆ" +} \ No newline at end of file diff --git a/Common/src/main/resources/assets/carryon/lang/en_us.json b/Common/src/main/resources/assets/carryon/lang/en_us.json new file mode 100644 index 0000000..8cea73d --- /dev/null +++ b/Common/src/main/resources/assets/carryon/lang/en_us.json @@ -0,0 +1,16 @@ +{ + "carryon.category.settings": "Settings", + "carryon.category.blacklist": "Blacklist", + "carryon.category.modeloverrides": "Model Overrides (Advanced)", + "carryon.category.custompickupconditions": "Custom Pickup Conditions (Advanced)", + "carryon.category.whitelist": "Whitelist", + + "carryon.general.modeloverrides.modeloverrides": "Model Overrides", + "carryon.general.blacklist.forbiddenentities": "Entities that the Player cannot pick up", + "carryon.general.blacklist.forbiddentiles": "Blocks that the Player cannot pick up", + "carryon.category.custompickupconditions.custompickupconditionsblocks": "Custom Block Pickup Conditions", + "carryon.category.custompickupconditions.custompickupconditionsentities": "Custom Entity Pickup Conditions", + + "key.carry.desc": "Carry", + "key.carry.category": "Carry On" +} \ No newline at end of file diff --git a/Common/src/main/resources/assets/carryon/lang/es_es.json b/Common/src/main/resources/assets/carryon/lang/es_es.json new file mode 100644 index 0000000..b652a9f --- /dev/null +++ b/Common/src/main/resources/assets/carryon/lang/es_es.json @@ -0,0 +1,16 @@ +{ + "carryon.category.settings": "Configuración", + "carryon.category.blacklist": "Lista negra", + "carryon.category.modeloverrides": "Reescribir modelo (Avanzado)", + "carryon.category.custompickupconditions": "Customizar condiciones de recoger (Avanzado)", + "carryon.category.whitelist": "Lista blanca", + + "carryon.general.modeloverrides.modeloverrides": "Reescribir modelo", + "carryon.general.blacklist.forbiddenentities": "Entidades que el jugador no puede recoger", + "carryon.general.blacklist.forbiddentiles": "Bloques que el jugador no puede recoger", + "carryon.category.custompickupconditions.custompickupconditionsblocks": "Customizar condiciones para recoger bloques", + "carryon.category.custompickupconditions.custompickupconditionsentities": "Customizar condiciones para recoger entidades", + + "key.carry.desc": "Agarrar", + "key.carry.category": "Carry On" +} \ No newline at end of file diff --git a/Common/src/main/resources/assets/carryon/lang/it_it.json b/Common/src/main/resources/assets/carryon/lang/it_it.json new file mode 100644 index 0000000..5402e38 --- /dev/null +++ b/Common/src/main/resources/assets/carryon/lang/it_it.json @@ -0,0 +1,16 @@ +{ + "carryon.category.settings": "Inpostazioni", + "carryon.category.blacklist": "Blacklist", + "carryon.category.modeloverrides": "Sostituzioni modello (avanzate)", + "carryon.category.custompickupconditions": "Condizioni di prelievo personalizzate (avanzate)", + "carryon.category.whitelist": "Whitelist", + + "carryon.general.modeloverrides.modeloverrides": "Sostituzioni modello", + "carryon.general.blacklist.forbiddenentities": "Entità che il giocatore non può raccogliere", + "carryon.general.blacklist.forbiddentiles": "Blocchi che il giocatore non può raccogliere", + "carryon.category.custompickupconditions.custompickupconditionsblocks": "Condizioni di prelievo blocco personalizzate", + "carryon.category.custompickupconditions.custompickupconditionsentities": "Condizioni di prelievo entità personalizzate", + + "key.carry.desc": "Afferra", + "key.carry.category": "Carry On Mod" +} \ No newline at end of file diff --git a/Common/src/main/resources/assets/carryon/lang/ko_kr.json b/Common/src/main/resources/assets/carryon/lang/ko_kr.json new file mode 100644 index 0000000..90f8d90 --- /dev/null +++ b/Common/src/main/resources/assets/carryon/lang/ko_kr.json @@ -0,0 +1,16 @@ +{ + "carryon.category.settings": "설정", + "carryon.category.blacklist": "블랙리스트", + "carryon.category.modeloverrides": "모델 오버라이딩 (고급)", + "carryon.category.custompickupconditions": "커스텀 들기 컨디션 (고급)", + "carryon.category.whitelist": "화이트리스트", + + "carryon.general.modeloverrides.modeloverrides": "모델 오버라이딩", + "carryon.general.blacklist.forbiddenentities": "플레이어가 들 수 없는 엔티티", + "carryon.general.blacklist.forbiddentiles": "플레이어가 들 수 없는 블록", + "carryon.category.custompickupconditions.custompickupconditionsblocks": "커스텀 블록 들기 컨디션", + "carryon.category.custompickupconditions.custompickupconditionsentities": "커스텀 엔티티 들기 컨디션", + + "key.carry.desc": "들고 나르기", + "key.carry.category": "Carry On" +} \ No newline at end of file diff --git a/Common/src/main/resources/assets/carryon/lang/ru_ru.json b/Common/src/main/resources/assets/carryon/lang/ru_ru.json new file mode 100644 index 0000000..36257f0 --- /dev/null +++ b/Common/src/main/resources/assets/carryon/lang/ru_ru.json @@ -0,0 +1,16 @@ +{ + "carryon.category.settings": "Настройки", + "carryon.category.blacklist": "Чёрный список", + "carryon.category.modeloverrides": "Переопределения модели (Улучшенное)", + "carryon.category.custompickupconditions": "Индивидуальные условия поднятия (Улучшенное)", + "carryon.category.whitelist": "Белый список", + + "carryon.general.modeloverrides.modeloverrides": "Переопределения модели", + "carryon.general.blacklist.forbiddenentities": "Сущности, которых игрок не может поднять", + "carryon.general.blacklist.forbiddentiles": "Блоки, которые игрок не может поднять", + "carryon.category.custompickupconditions.custompickupconditionsblocks": "Пользовательские условия поднятия блока", + "carryon.category.custompickupconditions.custompickupconditionsentities": "Пользовательские условия поднятия сущности", + + "key.carry.desc": "Поднять", + "key.carry.category": "Carry On" +} \ No newline at end of file diff --git a/Common/src/main/resources/carryon.mixins.json b/Common/src/main/resources/carryon.mixins.json index ec19c7d..cf60e4a 100644 --- a/Common/src/main/resources/carryon.mixins.json +++ b/Common/src/main/resources/carryon.mixins.json @@ -4,12 +4,13 @@ "package": "tschipp.carryon.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "EntityMixin", "InventoryMixin", "PlayerMixin" ], "client": [ - "MinecraftMixin", - "HumanoidModelMixin" + "HumanoidModelMixin", + "MinecraftMixin" ], "server": [ ], diff --git a/Common/src/main/resources/data/carryon/tags/blocks/block_blacklist.json b/Common/src/main/resources/data/carryon/tags/blocks/block_blacklist.json new file mode 100644 index 0000000..a22514f --- /dev/null +++ b/Common/src/main/resources/data/carryon/tags/blocks/block_blacklist.json @@ -0,0 +1,5 @@ +{ + "replace": false, + "values": [ + ] +} \ No newline at end of file diff --git a/Common/src/main/resources/data/carryon/tags/blocks/block_whitelist.json b/Common/src/main/resources/data/carryon/tags/blocks/block_whitelist.json new file mode 100644 index 0000000..a22514f --- /dev/null +++ b/Common/src/main/resources/data/carryon/tags/blocks/block_whitelist.json @@ -0,0 +1,5 @@ +{ + "replace": false, + "values": [ + ] +} \ No newline at end of file diff --git a/Common/src/main/resources/data/carryon/tags/entity_types/entity_blacklist.json b/Common/src/main/resources/data/carryon/tags/entity_types/entity_blacklist.json new file mode 100644 index 0000000..a22514f --- /dev/null +++ b/Common/src/main/resources/data/carryon/tags/entity_types/entity_blacklist.json @@ -0,0 +1,5 @@ +{ + "replace": false, + "values": [ + ] +} \ No newline at end of file diff --git a/Common/src/main/resources/data/carryon/tags/entity_types/entity_whitelist.json b/Common/src/main/resources/data/carryon/tags/entity_types/entity_whitelist.json new file mode 100644 index 0000000..a22514f --- /dev/null +++ b/Common/src/main/resources/data/carryon/tags/entity_types/entity_whitelist.json @@ -0,0 +1,5 @@ +{ + "replace": false, + "values": [ + ] +} \ No newline at end of file diff --git a/Common/src/main/resources/data/carryon/tags/entity_types/stacking_blacklist.json b/Common/src/main/resources/data/carryon/tags/entity_types/stacking_blacklist.json new file mode 100644 index 0000000..a22514f --- /dev/null +++ b/Common/src/main/resources/data/carryon/tags/entity_types/stacking_blacklist.json @@ -0,0 +1,5 @@ +{ + "replace": false, + "values": [ + ] +} \ No newline at end of file diff --git a/Common/src/main/resources/data/carryon/tags/entity_types/stacking_whitelist.json b/Common/src/main/resources/data/carryon/tags/entity_types/stacking_whitelist.json new file mode 100644 index 0000000..a22514f --- /dev/null +++ b/Common/src/main/resources/data/carryon/tags/entity_types/stacking_whitelist.json @@ -0,0 +1,5 @@ +{ + "replace": false, + "values": [ + ] +} \ No newline at end of file diff --git a/Fabric/build.gradle b/Fabric/build.gradle index 337a4a2..3da1d98 100644 --- a/Fabric/build.gradle +++ b/Fabric/build.gradle @@ -4,7 +4,7 @@ plugins { id 'idea' } -archivesBaseName = "${mod_name}-fabric-${minecraft_version}" +archivesBaseName = "${mod_id}-fabric-${minecraft_version}" dependencies { minecraft "com.mojang:minecraft:${minecraft_version}" diff --git a/Fabric/src/main/java/tschipp/carryon/CarryOnFabricClientMod.java b/Fabric/src/main/java/tschipp/carryon/CarryOnFabricClientMod.java new file mode 100644 index 0000000..b3295c1 --- /dev/null +++ b/Fabric/src/main/java/tschipp/carryon/CarryOnFabricClientMod.java @@ -0,0 +1,43 @@ +package tschipp.carryon; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import tschipp.carryon.client.keybinds.CarryOnKeybinds; +import tschipp.carryon.events.ClientEvents; +import tschipp.carryon.networking.PacketBase; + +import java.util.function.BiConsumer; +import java.util.function.Function; + +public class CarryOnFabricClientMod implements ClientModInitializer +{ + @Override + public void onInitializeClient() + { + CarryOnKeybinds.registerKeybinds(KeyBindingHelper::registerKeyBinding); + ClientEvents.registerEvents(); + CarryOnCommon.registerClientPackets(); + } + + public static void sendPacketToServer(ResourceLocation id, PacketBase packet) + { + FriendlyByteBuf buf = PacketByteBufs.create(); + packet.toBytes(buf); + ClientPlayNetworking.send(id, buf); + } + + public static void registerClientboundPacket(ResourceLocation id, Function reader, BiConsumer handler) + { + ClientPlayNetworking.registerGlobalReceiver(id, (client, packetHandler, buf, responseSender) -> { + T packet = reader.apply(buf); + client.execute(() -> { + handler.accept(packet, client.player); + }); + }); + } +} diff --git a/Fabric/src/main/java/tschipp/carryon/CarryOnFabricMod.java b/Fabric/src/main/java/tschipp/carryon/CarryOnFabricMod.java index 9bc2e24..89e58cb 100644 --- a/Fabric/src/main/java/tschipp/carryon/CarryOnFabricMod.java +++ b/Fabric/src/main/java/tschipp/carryon/CarryOnFabricMod.java @@ -14,9 +14,9 @@ public class CarryOnFabricMod implements ModInitializer { // This method is invoked by the Fabric mod loader when it is ready // to load your mod. You can access Fabric and Common code in this // project. + CarryOnCommon.registerConfig(); + - // Use Fabric to bootstrap the Common mod. - Constants.LOG.info("Hello Fabric world!"); try { ConfigLoaderImpl.initialize(); } catch (IOException e) { @@ -24,7 +24,7 @@ public class CarryOnFabricMod implements ModInitializer { } CommonEvents.registerEvents(); - + CarryOnCommon.registerServerPackets(); } } diff --git a/Fabric/src/main/java/tschipp/carryon/events/ClientEvents.java b/Fabric/src/main/java/tschipp/carryon/events/ClientEvents.java index 0efba9a..7c3a7d2 100644 --- a/Fabric/src/main/java/tschipp/carryon/events/ClientEvents.java +++ b/Fabric/src/main/java/tschipp/carryon/events/ClientEvents.java @@ -1,4 +1,15 @@ package tschipp.carryon.events; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import tschipp.carryon.CarryOnCommonClient; + public class ClientEvents { + + public static void registerEvents() + { + ClientTickEvents.END_CLIENT_TICK.register(mc -> { + CarryOnCommonClient.checkForKeybinds(); + }); + } + } diff --git a/Fabric/src/main/java/tschipp/carryon/events/CommonEvents.java b/Fabric/src/main/java/tschipp/carryon/events/CommonEvents.java index 5cd490c..874f05b 100644 --- a/Fabric/src/main/java/tschipp/carryon/events/CommonEvents.java +++ b/Fabric/src/main/java/tschipp/carryon/events/CommonEvents.java @@ -1,15 +1,24 @@ package tschipp.carryon.events; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.event.player.UseEntityCallback; +import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.packs.PackType; import net.minecraft.world.InteractionResult; +import tschipp.carryon.CarryOnCommon; import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.CarryOnData.CarryType; import tschipp.carryon.common.carry.CarryOnDataManager; import tschipp.carryon.common.carry.PickupHandler; import tschipp.carryon.common.carry.PlacementHandler; +import tschipp.carryon.common.scripting.ScriptReloadListener; +import tschipp.carryon.scripting.IdentifiableScriptReloadListener; public class CommonEvents { @@ -62,14 +71,32 @@ public class CommonEvents { return InteractionResult.SUCCESS; } } - else if(carry.isCarrying(CarryOnData.CarryType.ENTITY)) + else if(carry.isCarrying(CarryOnData.CarryType.ENTITY) || carry.isCarrying(CarryType.PLAYER)) { - //TODO: Stacking + PlacementHandler.tryStackEntity((ServerPlayer) player, entity); } return InteractionResult.PASS; }); + + CommandRegistrationCallback.EVENT.register(((dispatcher, registryAccess, environment) -> { + CarryOnCommon.registerCommands(dispatcher); + })); + + + ResourceManagerHelper.get(PackType.SERVER_DATA).registerReloadListener(new IdentifiableScriptReloadListener()); + + + ServerLifecycleEvents.SYNC_DATA_PACK_CONTENTS.register((player, joined) -> { + ScriptReloadListener.syncScriptsWithClient(player); + }); + + ServerTickEvents.END_SERVER_TICK.register(server -> { + for(ServerPlayer player : server.getPlayerList().getPlayers()) + PickupHandler.onCarryTick(player); + }); + } } diff --git a/Fabric/src/main/java/tschipp/carryon/mixin/ExampleMixin.java b/Fabric/src/main/java/tschipp/carryon/mixin/ExampleMixin.java deleted file mode 100644 index 0137cbd..0000000 --- a/Fabric/src/main/java/tschipp/carryon/mixin/ExampleMixin.java +++ /dev/null @@ -1,21 +0,0 @@ -package tschipp.carryon.mixin; - -import tschipp.carryon.Constants; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.TitleScreen; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(TitleScreen.class) -public class ExampleMixin { - - @Inject(at = @At("HEAD"), method = "init()V") - private void init(CallbackInfo info) { - - Constants.LOG.info("This line is printed by an example mod mixin from Fabric!"); - Constants.LOG.info("MC Version: {}", Minecraft.getInstance().getVersionType()); - Constants.LOG.info("Classloader: {}", this.getClass().getClassLoader()); - } -} \ No newline at end of file diff --git a/Fabric/src/main/java/tschipp/carryon/mixin/ItemInHandRendererMixin.java b/Fabric/src/main/java/tschipp/carryon/mixin/ItemInHandRendererMixin.java new file mode 100644 index 0000000..12e1c3e --- /dev/null +++ b/Fabric/src/main/java/tschipp/carryon/mixin/ItemInHandRendererMixin.java @@ -0,0 +1,31 @@ +package tschipp.carryon.mixin; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.ItemInHandRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +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.Redirect; +import tschipp.carryon.client.render.CarriedObjectRender; +import tschipp.carryon.client.render.CarryRenderHelper; + +@Mixin(ItemInHandRenderer.class) +public class ItemInHandRendererMixin +{ + + @Shadow + private void renderArmWithItem(AbstractClientPlayer player, float partialTicks, float f2, InteractionHand hand, float f3, ItemStack stack, float f4, PoseStack poseStack, MultiBufferSource source, int light) {throw new RuntimeException("CarryOn InHandRendererMixin failed");} + + + @Redirect(at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderArmWithItem(Lnet/minecraft/client/player/AbstractClientPlayer;FFLnet/minecraft/world/InteractionHand;FLnet/minecraft/world/item/ItemStack;FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V"), method = "renderHandsWithItems(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/player/LocalPlayer;I)V") + private void onRenderHand(ItemInHandRenderer instance, AbstractClientPlayer player, float partialTicks, float f2, InteractionHand hand, float f3, ItemStack stack, float f4, PoseStack poseStack, MultiBufferSource source, int light) + { + if(!CarriedObjectRender.drawFirstPerson(player, source, poseStack, light, partialTicks) && CarryRenderHelper.getPerspective() == 0) + renderArmWithItem(player, partialTicks, f2, hand, f3, stack, f4, poseStack, source, light); + } + +} diff --git a/Fabric/src/main/java/tschipp/carryon/mixin/LevelRendererMixin.java b/Fabric/src/main/java/tschipp/carryon/mixin/LevelRendererMixin.java new file mode 100644 index 0000000..f8e0195 --- /dev/null +++ b/Fabric/src/main/java/tschipp/carryon/mixin/LevelRendererMixin.java @@ -0,0 +1,23 @@ +package tschipp.carryon.mixin; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix4f; +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.LightTexture; +import org.spongepowered.asm.mixin.Mixin; +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.client.render.CarriedObjectRender; + +@Mixin(LevelRenderer.class) +public class LevelRendererMixin +{ + @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;F)V"), method = "renderLevel(Lcom/mojang/blaze3d/vertex/PoseStack;FJZLnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/GameRenderer;Lnet/minecraft/client/renderer/LightTexture;Lcom/mojang/math/Matrix4f;)V") + private void onRenderLevel(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, CallbackInfo ci) + { + CarriedObjectRender.drawThirdPerson(gameRenderer.getMinecraft().getFrameTime(), poseStack); + } +} diff --git a/Fabric/src/main/java/tschipp/carryon/mixin/ScreenMixin.java b/Fabric/src/main/java/tschipp/carryon/mixin/ScreenMixin.java new file mode 100644 index 0000000..fb169e7 --- /dev/null +++ b/Fabric/src/main/java/tschipp/carryon/mixin/ScreenMixin.java @@ -0,0 +1,28 @@ +package tschipp.carryon.mixin; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.world.entity.player.Player; +import org.spongepowered.asm.mixin.Mixin; +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(Screen.class) +public class ScreenMixin +{ + @Inject(at = @At(value = "TAIL"), method = "init(Lnet/minecraft/client/Minecraft;II)V") + private void onInit(Minecraft mc, int i, int j, CallbackInfo ci) + { + Player player = mc.player; + if((Object)this instanceof AbstractContainerScreen && player != null) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + if(carry.isCarrying()) + mc.setScreen((Screen)null); + } + } +} diff --git a/Fabric/src/main/java/tschipp/carryon/platform/FabricPlatformHelper.java b/Fabric/src/main/java/tschipp/carryon/platform/FabricPlatformHelper.java index 93e37a3..4081884 100644 --- a/Fabric/src/main/java/tschipp/carryon/platform/FabricPlatformHelper.java +++ b/Fabric/src/main/java/tschipp/carryon/platform/FabricPlatformHelper.java @@ -1,9 +1,20 @@ package tschipp.carryon.platform; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import tschipp.carryon.CarryOnFabricClientMod; import tschipp.carryon.config.BuiltConfig; import tschipp.carryon.config.fabric.ConfigLoaderImpl; +import tschipp.carryon.networking.PacketBase; import tschipp.carryon.platform.services.IPlatformHelper; -import net.fabricmc.loader.api.FabricLoader; + +import java.util.function.BiConsumer; +import java.util.function.Function; public class FabricPlatformHelper implements IPlatformHelper { @@ -28,4 +39,35 @@ public class FabricPlatformHelper implements IPlatformHelper { public void registerConfig(BuiltConfig cfg) { ConfigLoaderImpl.registerConfig(cfg); } + + @Override + public void registerServerboundPacket(ResourceLocation id, int numericalId, Class clazz, BiConsumer writer, Function reader, BiConsumer handler) + { + ServerPlayNetworking.registerGlobalReceiver(id, (server, player, packetHandler, buf, responseSender) -> { + T packet = reader.apply(buf); + server.execute(() -> { + handler.accept(packet, player); + }); + }); + } + + @Override + public void registerClientboundPacket(ResourceLocation id, int numericalId, Class clazz, BiConsumer writer, Function reader, BiConsumer handler) + { + CarryOnFabricClientMod.registerClientboundPacket(id, reader, handler); + } + + @Override + public void sendPacketToServer(ResourceLocation id, PacketBase packet) + { + CarryOnFabricClientMod.sendPacketToServer(id, packet); + } + + @Override + public void sendPacketToPlayer(ResourceLocation id, PacketBase packet, ServerPlayer player) + { + FriendlyByteBuf buf = PacketByteBufs.create(); + packet.toBytes(buf); + ServerPlayNetworking.send(player, id, buf); + } } diff --git a/Fabric/src/main/java/tschipp/carryon/scripting/IdentifiableScriptReloadListener.java b/Fabric/src/main/java/tschipp/carryon/scripting/IdentifiableScriptReloadListener.java new file mode 100644 index 0000000..3b08ee4 --- /dev/null +++ b/Fabric/src/main/java/tschipp/carryon/scripting/IdentifiableScriptReloadListener.java @@ -0,0 +1,15 @@ +package tschipp.carryon.scripting; + +import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; +import net.minecraft.resources.ResourceLocation; +import tschipp.carryon.Constants; +import tschipp.carryon.common.scripting.ScriptReloadListener; + +public class IdentifiableScriptReloadListener extends ScriptReloadListener implements IdentifiableResourceReloadListener +{ + @Override + public ResourceLocation getFabricId() + { + return new ResourceLocation(Constants.MOD_ID, "carryon_scripts"); + } +} diff --git a/Fabric/src/main/resources/carryon.fabric.mixins.json b/Fabric/src/main/resources/carryon.fabric.mixins.json index caf1cd6..562850c 100644 --- a/Fabric/src/main/resources/carryon.fabric.mixins.json +++ b/Fabric/src/main/resources/carryon.fabric.mixins.json @@ -6,6 +6,9 @@ "mixins": [ ], "client": [ + "ItemInHandRendererMixin", + "LevelRendererMixin", + "ScreenMixin" ], "injectors": { "defaultRequire": 1 diff --git a/Fabric/src/main/resources/fabric.mod.json b/Fabric/src/main/resources/fabric.mod.json index 098c01b..3e1988d 100644 --- a/Fabric/src/main/resources/fabric.mod.json +++ b/Fabric/src/main/resources/fabric.mod.json @@ -20,6 +20,9 @@ "entrypoints": { "main": [ "tschipp.carryon.CarryOnFabricMod" + ], + "client": [ + "tschipp.carryon.CarryOnFabricClientMod" ] }, "mixins": [ diff --git a/Forge/build.gradle b/Forge/build.gradle index f8ae222..d099e22 100644 --- a/Forge/build.gradle +++ b/Forge/build.gradle @@ -2,11 +2,13 @@ buildscript { repositories { maven { url = 'https://maven.minecraftforge.net' } maven { url = 'https://repo.spongepowered.org/repository/maven-public/' } + maven { url = 'https://maven.parchmentmc.org' } mavenCentral() } dependencies { classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT' + classpath 'org.parchmentmc:librarian:1.+' } } apply plugin: 'java' @@ -14,8 +16,9 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'org.spongepowered.mixin' apply plugin: 'maven-publish' +apply plugin: 'org.parchmentmc.librarian.forgegradle' -archivesBaseName = "${mod_name}-forge-${minecraft_version}" +archivesBaseName = "${mod_id}-forge-${minecraft_version}" mixin { add sourceSets.main, "${mod_id}.refmap.json" @@ -25,7 +28,7 @@ mixin { } minecraft { - mappings channel: 'official', version: minecraft_version + mappings channel: 'parchment', version: "${parchment_mappings}" if (project.hasProperty('forge_ats_enabled') && project.findProperty('forge_ats_enabled').toBoolean()) { // This location is hardcoded in Forge and can not be changed. diff --git a/Forge/src/main/java/tschipp/carryon/CarryOnForge.java b/Forge/src/main/java/tschipp/carryon/CarryOnForge.java index 1684936..19635f9 100644 --- a/Forge/src/main/java/tschipp/carryon/CarryOnForge.java +++ b/Forge/src/main/java/tschipp/carryon/CarryOnForge.java @@ -1,11 +1,20 @@ package tschipp.carryon; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; import tschipp.carryon.config.forge.ConfigLoaderImpl; @Mod(Constants.MOD_ID) +@EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) public class CarryOnForge { - + + public static SimpleChannel network; + public CarryOnForge() { // This method is invoked by the Forge mod loader when it is ready @@ -13,9 +22,19 @@ public class CarryOnForge { // project. // Use Forge to bootstrap the Common mod. - Constants.LOG.info("Hello Forge world!"); + CarryOnCommon.registerConfig(); + + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); ConfigLoaderImpl.initialize(); } + private void setup(final FMLCommonSetupEvent event) + { + network = NetworkRegistry.newSimpleChannel(new ResourceLocation(Constants.MOD_ID, "carryonpackets"), () -> "1.0", "1.0"::equals, "1.0"::equals); + + CarryOnCommon.registerServerPackets(); + CarryOnCommon.registerClientPackets(); + } + } \ No newline at end of file diff --git a/Forge/src/main/java/tschipp/carryon/events/ClientEvents.java b/Forge/src/main/java/tschipp/carryon/events/ClientEvents.java index 05d6ec0..207cc39 100644 --- a/Forge/src/main/java/tschipp/carryon/events/ClientEvents.java +++ b/Forge/src/main/java/tschipp/carryon/events/ClientEvents.java @@ -2,16 +2,25 @@ package tschipp.carryon.events; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.world.entity.player.Player; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.event.RenderHandEvent; +import net.minecraftforge.client.event.RenderLevelStageEvent; +import net.minecraftforge.client.event.RenderLevelStageEvent.Stage; +import net.minecraftforge.client.event.ScreenEvent; +import net.minecraftforge.event.TickEvent.ClientTickEvent; +import net.minecraftforge.event.TickEvent.Phase; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; +import tschipp.carryon.CarryOnCommonClient; import tschipp.carryon.Constants; import tschipp.carryon.client.render.CarriedObjectRender; import tschipp.carryon.client.render.CarryRenderHelper; +import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.CarryOnDataManager; @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE, modid = Constants.MOD_ID, value = Dist.CLIENT) public class ClientEvents { @@ -29,4 +38,47 @@ public class ClientEvents { if(CarriedObjectRender.drawFirstPerson(player, buffer, matrix, light, partialTicks) && CarryRenderHelper.getPerspective() == 0) event.setCanceled(true); } + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public static void onRenderLevel(RenderLevelStageEvent event) + { + if(event.getStage() == Stage.AFTER_PARTICLES) + CarriedObjectRender.drawThirdPerson(event.getPartialTick(), event.getPoseStack()); + } + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public static void onGuiInit(ScreenEvent.Init.Pre event) + { + if (event.getScreen() != null) + { + boolean inventory = event.getScreen() instanceof AbstractContainerScreen; + Minecraft mc = Minecraft.getInstance(); + Player player = mc.player; + + if (player != null && inventory) + { + CarryOnData carry = CarryOnDataManager.getCarryData(player); + if (carry.isCarrying()) + { + mc.player.closeContainer(); + mc.screen = null; + mc.mouseHandler.grabMouse(); + event.setCanceled(true); + } + } + } + } + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public static void onClientTick(ClientTickEvent event) + { + if(event.phase == Phase.END) + { + CarryOnCommonClient.checkForKeybinds(); + } + + } } diff --git a/Forge/src/main/java/tschipp/carryon/events/CommonEvents.java b/Forge/src/main/java/tschipp/carryon/events/CommonEvents.java index 8c9961f..f31824f 100644 --- a/Forge/src/main/java/tschipp/carryon/events/CommonEvents.java +++ b/Forge/src/main/java/tschipp/carryon/events/CommonEvents.java @@ -8,19 +8,28 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.BlockSnapshot; +import net.minecraftforge.event.AddReloadListenerEvent; +import net.minecraftforge.event.OnDatapackSyncEvent; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.TickEvent.Phase; +import net.minecraftforge.event.TickEvent.ServerTickEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.level.BlockEvent.EntityPlaceEvent; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.Event.Result; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.InterModComms; +import net.minecraftforge.fml.InterModComms.IMCMessage; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLDedicatedServerSetupEvent; +import tschipp.carryon.CarryOnCommon; import tschipp.carryon.Constants; -import tschipp.carryon.common.carry.CarryOnData; +import tschipp.carryon.common.carry.*; import tschipp.carryon.common.carry.CarryOnData.CarryType; -import tschipp.carryon.common.carry.CarryOnDataManager; -import tschipp.carryon.common.carry.PickupHandler; -import tschipp.carryon.common.carry.PlacementHandler; +import tschipp.carryon.common.scripting.ScriptReloadListener; + +import java.util.stream.Stream; @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE, modid = Constants.MOD_ID) public class CommonEvents @@ -95,10 +104,86 @@ public class CommonEvents return; } } - else if(carry.isCarrying(CarryType.ENTITY)) + else if(carry.isCarrying(CarryType.ENTITY) || carry.isCarrying(CarryType.PLAYER)) { - //TODO: Stacking + PlacementHandler.tryStackEntity((ServerPlayer)player, target); } } + @SubscribeEvent + public static void onRegisterCommands(RegisterCommandsEvent event) + { + CarryOnCommon.registerCommands(event.getDispatcher()); + } + + @SubscribeEvent(priority = EventPriority.LOW) + public void serverLoad(FMLDedicatedServerSetupEvent event) + { + Stream messages = InterModComms.getMessages(Constants.MOD_ID); + + messages.forEach(msg -> { + + String method = msg.method(); + Object obj = msg.messageSupplier().get(); + + if (!(obj instanceof String str)) + return; + + switch (method) + { + case "blacklistBlock": + ListHandler.addForbiddenTiles(str); + break; + case "blacklistEntity": + ListHandler.addForbiddenEntities(str); + break; + case "whitelistBlock": + ListHandler.addAllowedTiles(str); + break; + case "whitelistEntity": + ListHandler.addAllowedEntities(str); + break; + case "blacklistStacking": + ListHandler.addForbiddenStacking(str); + break; + case "whitelistStacking": + ListHandler.addAllowedStacking(str); + break; + //TODO +// case "addModelOverride": +// ModelOverridesHandler.parseOverride(str, 0); +// break; + } + + }); + + } + + @SubscribeEvent + public static void onDatapackRegister(AddReloadListenerEvent event) + { + event.addListener(new ScriptReloadListener()); + } + + @SubscribeEvent + public static void onDatapackSync(OnDatapackSyncEvent event) + { + ServerPlayer player = event.getPlayer(); + if(player == null) + { + for(ServerPlayer p : event.getPlayerList().getPlayers()) + ScriptReloadListener.syncScriptsWithClient(p); + } + else + ScriptReloadListener.syncScriptsWithClient(player); + } + + @SubscribeEvent + public static void onServerTick(ServerTickEvent event) + { + if(event.phase == Phase.END) + for(ServerPlayer player : event.getServer().getPlayerList().getPlayers()) + PickupHandler.onCarryTick(player); + } + } diff --git a/Forge/src/main/java/tschipp/carryon/events/ModClientEvents.java b/Forge/src/main/java/tschipp/carryon/events/ModClientEvents.java new file mode 100644 index 0000000..0e4c650 --- /dev/null +++ b/Forge/src/main/java/tschipp/carryon/events/ModClientEvents.java @@ -0,0 +1,21 @@ +package tschipp.carryon.events; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.RegisterKeyMappingsEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; +import tschipp.carryon.Constants; +import tschipp.carryon.client.keybinds.CarryOnKeybinds; + +@Mod.EventBusSubscriber(bus = Bus.MOD, modid = Constants.MOD_ID, value = Dist.CLIENT) +public class ModClientEvents +{ + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public static void registerKeybinds(RegisterKeyMappingsEvent event) + { + CarryOnKeybinds.registerKeybinds(event::register); + } +} diff --git a/Forge/src/main/java/tschipp/carryon/platform/ForgePlatformHelper.java b/Forge/src/main/java/tschipp/carryon/platform/ForgePlatformHelper.java index 12f42ae..ea0f35c 100644 --- a/Forge/src/main/java/tschipp/carryon/platform/ForgePlatformHelper.java +++ b/Forge/src/main/java/tschipp/carryon/platform/ForgePlatformHelper.java @@ -1,10 +1,25 @@ package tschipp.carryon.platform; -import tschipp.carryon.config.BuiltConfig; -import tschipp.carryon.config.forge.ConfigLoaderImpl; -import tschipp.carryon.platform.services.IPlatformHelper; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.loading.FMLLoader; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent.Context; +import net.minecraftforge.network.PacketDistributor; +import tschipp.carryon.CarryOnForge; +import tschipp.carryon.client.CarryOnClient; +import tschipp.carryon.config.BuiltConfig; +import tschipp.carryon.config.forge.ConfigLoaderImpl; +import tschipp.carryon.networking.PacketBase; +import tschipp.carryon.platform.services.IPlatformHelper; + +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; public class ForgePlatformHelper implements IPlatformHelper { @@ -30,4 +45,49 @@ public class ForgePlatformHelper implements IPlatformHelper { public void registerConfig(BuiltConfig cfg) { ConfigLoaderImpl.registerConfig(cfg); } + + @Override + public void registerServerboundPacket(ResourceLocation id, int numericalId, Class clazz, BiConsumer writer, Function reader, BiConsumer handler) + { + BiConsumer> serverHandler = (packet, ctx) -> { + if(ctx.get().getDirection().getReceptionSide().isServer()) + { + ctx.get().setPacketHandled(true); + ctx.get().enqueueWork(() -> { + handler.accept(packet, ctx.get().getSender()); + }); + } + }; + + CarryOnForge.network.registerMessage(numericalId, clazz, writer, reader, serverHandler, Optional.of(NetworkDirection.PLAY_TO_SERVER)); + } + + @Override + public void registerClientboundPacket(ResourceLocation id, int numericalId, Class clazz, BiConsumer writer, Function reader, BiConsumer handler) + { + BiConsumer> clientHandler = (packet, ctx) -> { + if(ctx.get().getDirection().getReceptionSide().isClient()) + { + ctx.get().setPacketHandled(true); + ctx.get().enqueueWork(() -> { + handler.accept(packet, CarryOnClient.getPlayer()); + }); + } + }; + + CarryOnForge.network.registerMessage(numericalId, clazz, writer, reader, clientHandler, Optional.of(NetworkDirection.PLAY_TO_CLIENT)); + } + + + @Override + public void sendPacketToServer(ResourceLocation id, PacketBase packet) + { + CarryOnForge.network.sendToServer(packet); + } + + @Override + public void sendPacketToPlayer(ResourceLocation id, PacketBase packet, ServerPlayer player) + { + CarryOnForge.network.send(PacketDistributor.PLAYER.with(() -> player), packet); + } } diff --git a/gradle.properties b/gradle.properties index 3bcb89e..5279e46 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,13 +4,13 @@ group=tschipp.carryon # Common minecraft_version=1.19.2 -parchment_mappings=2022.09.18 common_runs_enabled=false common_client_run_name=Common Client common_server_run_name=Common Server # Forge forge_version=43.1.30 +parchment_mappings=2022.11.20-1.19.2 //forge_ats_enabled=true # Fabric diff --git a/old/src/main/java/tschipp/carryon/common/helper/ScriptParseHelper.java b/old/src/main/java/tschipp/carryon/common/helper/ScriptParseHelper.java index b73eef1..f08f2ad 100644 --- a/old/src/main/java/tschipp/carryon/common/helper/ScriptParseHelper.java +++ b/old/src/main/java/tschipp/carryon/common/helper/ScriptParseHelper.java @@ -20,6 +20,8 @@ import net.minecraftforge.registries.ForgeRegistries; public class ScriptParseHelper { + + public static boolean matches(double number, String cond) { if (cond == null || cond.isEmpty())