Added networking, Scripting

This commit is contained in:
Tschipp 2022-11-29 00:49:57 +01:00
parent cf6a14f5d9
commit 375eb8dcc3
62 changed files with 2558 additions and 211 deletions

View File

@ -4,7 +4,7 @@ plugins {
id 'maven-publish'
}
archivesBaseName = "${mod_name}-common-${minecraft_version}"
archivesBaseName = "${mod_id}-common-${minecraft_version}"
minecraft {
version(minecraft_version)

View File

@ -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<CommandSourceStack> dispatcher)
{
CommandCarryOn.register(dispatcher);
}
}

View File

@ -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);
}
}
}
}

View File

@ -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");
}

View File

@ -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;
}
}

View File

@ -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<KeyMapping> 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));
}
}

View File

@ -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<EntityType<?>> type = EntityType.byString(entityname);
if (type.isPresent())
newEntity = type.get().create(level);
if (newEntity != null)
{
CompoundTag nbttag = carryOverride.getRenderNBT();
if (nbttag != null)
newEntity.deserializeNBT(nbttag);
entity = newEntity;
entity.setPos(playerpos.x, playerpos.y, playerpos.z);
entity.xRotO = 0.0f;
entity.yRotO = 0.0f;
entity.setYHeadRot(0.0f);
}
}
}
*/
if (entity instanceof LivingEntity)
((LivingEntity) entity).hurtTime = 0;
manager.render(entity, 0, 0, 0, 0f, 0, matrix, buffer, light);
manager.setRenderShadow(true);
Optional<CarryOnScript> 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<CarryOnScript> 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<CarryOnScript> 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();
}
}

View File

@ -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;
}
}

View File

@ -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<CarryOnScript> 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<Tag> 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<CarryOnScript> 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
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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<CarryOnScript> 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<CarryOnScript> 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);
}
}
}
}

View File

@ -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<Vec3, Entity, Boolean> 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<Entity> 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<Entity> pass = entity.getPassengers();
if (!pass.isEmpty())
{
entity = pass.get(0);
top = entity;
}
}
return top;
}
}

View File

@ -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<CommandSourceStack> dispatcher)
{
LiteralArgumentBuilder<CommandSourceStack> 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<ServerPlayer> 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);
}
}

View File

@ -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",

View File

@ -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<CarryOnScript> 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<ScriptObject> 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<ResourceKey<Block>> 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<ScriptObjectBlock> 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<ResourceKey<EntityType<?>>> 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<ScriptObjectEntity> 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<ScriptConditions> 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<ResourceKey<Block>> renderNameBlock,
Optional<ResourceKey<EntityType<?>>> renderNameEntity,
Optional<CompoundTag> 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<ScriptRender> 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<ScriptEffects> 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)
);
}
}

View File

@ -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<T>
{
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<Number>
{
public static final Codec<NumberBoundCondition> 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<Material>
{
public static final Codec<MaterialCondition> 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<ServerPlayer>
{
public static final Codec<AdvancementCondition> 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<ServerPlayer>
{
public static final Codec<GamestageCondition> 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<ServerPlayer>
{
public static final Codec<ScoreboardCondition> 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<Objective, Score> 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<ServerPlayer>
{
public static final Codec<PositionCondition> 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<ServerPlayer>
{
public static final Codec<EffectsCondition> 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<MobEffectInstance> fx = player.getActiveEffects();
String[] potions = effects.split(",");
List<String> names = new ArrayList<>();
List<Integer> 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<CompoundTag>
{
public static final Codec<NBTCondition> 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<OptionalVec3> 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);
}
}
}

View File

@ -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<CarryOnScript> SCRIPTS = new ArrayList<>();
public static Optional<CarryOnScript> 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<CarryOnScript> 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;
}
}

View File

@ -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<ResourceLocation, JsonElement> objects, ResourceManager manager, ProfilerFiller profiler)
{
ScriptManager.SCRIPTS.clear();
try {
objects.forEach((path, jsonElem) -> {
DataResult<CarryOnScript> 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<Tag> 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);
}
}
}

View File

@ -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<Vec3> 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());
}
}

View File

@ -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;
}
}

View File

@ -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<ItemStack> items;
@Redirect(method = "getFreeSlot()I", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/core/NonNullList;get(I)Ljava/lang/Object;"))
private <E> E getFreeSlotEmptyCheck(NonNullList<E> 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();
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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<List<CarryOnScript>> res = Codec.list(CarryOnScript.CODEC).parse(NbtOps.INSTANCE, serialized);
List<CarryOnScript> scripts = res.getOrThrow(false, (s) -> {throw new RuntimeException("Failed deserializing carry on scripts on the client: " + s);});
ScriptManager.SCRIPTS.clear();
ScriptManager.SCRIPTS.addAll(scripts);
}
}

View File

@ -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);
}
}

View File

@ -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);
<T extends PacketBase> void registerServerboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler);
<T extends PacketBase> void registerClientboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler);
void sendPacketToServer(ResourceLocation id, PacketBase packet);
void sendPacketToPlayer(ResourceLocation id, PacketBase packet, ServerPlayer player);
}

View File

@ -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 ʎɹɹɐƆ"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -4,12 +4,13 @@
"package": "tschipp.carryon.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"EntityMixin",
"InventoryMixin",
"PlayerMixin"
],
"client": [
"MinecraftMixin",
"HumanoidModelMixin"
"HumanoidModelMixin",
"MinecraftMixin"
],
"server": [
],

View File

@ -0,0 +1,5 @@
{
"replace": false,
"values": [
]
}

View File

@ -0,0 +1,5 @@
{
"replace": false,
"values": [
]
}

View File

@ -0,0 +1,5 @@
{
"replace": false,
"values": [
]
}

View File

@ -0,0 +1,5 @@
{
"replace": false,
"values": [
]
}

View File

@ -0,0 +1,5 @@
{
"replace": false,
"values": [
]
}

View File

@ -0,0 +1,5 @@
{
"replace": false,
"values": [
]
}

View File

@ -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}"

View File

@ -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 <T extends PacketBase> void registerClientboundPacket(ResourceLocation id, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler)
{
ClientPlayNetworking.registerGlobalReceiver(id, (client, packetHandler, buf, responseSender) -> {
T packet = reader.apply(buf);
client.execute(() -> {
handler.accept(packet, client.player);
});
});
}
}

View File

@ -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();
}
}

View File

@ -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();
});
}
}

View File

@ -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);
});
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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 <T extends PacketBase> void registerServerboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler)
{
ServerPlayNetworking.registerGlobalReceiver(id, (server, player, packetHandler, buf, responseSender) -> {
T packet = reader.apply(buf);
server.execute(() -> {
handler.accept(packet, player);
});
});
}
@Override
public <T extends PacketBase> void registerClientboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> 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);
}
}

View File

@ -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");
}
}

View File

@ -6,6 +6,9 @@
"mixins": [
],
"client": [
"ItemInHandRendererMixin",
"LevelRendererMixin",
"ScreenMixin"
],
"injectors": {
"defaultRequire": 1

View File

@ -20,6 +20,9 @@
"entrypoints": {
"main": [
"tschipp.carryon.CarryOnFabricMod"
],
"client": [
"tschipp.carryon.CarryOnFabricClientMod"
]
},
"mixins": [

View File

@ -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.

View File

@ -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();
}
}

View File

@ -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();
}
}
}

View File

@ -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<IMCMessage> 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);
}
}

View File

@ -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);
}
}

View File

@ -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 <T extends PacketBase> void registerServerboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler)
{
BiConsumer<T, Supplier<Context>> 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 <T extends PacketBase> void registerClientboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler)
{
BiConsumer<T, Supplier<Context>> 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);
}
}

View File

@ -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

View File

@ -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())