From 881d648aa28956a606cc307e7dca15c27878c61c Mon Sep 17 00:00:00 2001 From: Goldenfield192 <1437356849@qq.com> Date: Sat, 21 Mar 2026 23:03:04 +0800 Subject: [PATCH 1/3] feat: add roll axis --- src/main/java/cam72cam/mod/entity/Entity.java | 40 ++++++++++++++++++- .../cam72cam/mod/entity/ModdedEntity.java | 30 ++++++++++++++ .../cam72cam/mod/render/EntityRenderer.java | 6 ++- 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/main/java/cam72cam/mod/entity/Entity.java b/src/main/java/cam72cam/mod/entity/Entity.java index 9e6f460d..bbaabe58 100644 --- a/src/main/java/cam72cam/mod/entity/Entity.java +++ b/src/main/java/cam72cam/mod/entity/Entity.java @@ -7,9 +7,9 @@ import cam72cam.mod.world.World; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.passive.EntityVillager; -import net.minecraft.util.DamageSource; +import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.Explosion; import java.util.List; @@ -26,6 +26,8 @@ public class Entity { /** The wrapped MC construct. Do not use directly */ public net.minecraft.entity.Entity internal; + private float rotationRoll; + /** Wrap a MC entity in UMC entity. Do not use directly. */ public Entity(net.minecraft.entity.Entity entity) { this.internal = entity; @@ -101,6 +103,33 @@ public void setRotationPitch(float pitch) { internal.rotationPitch = pitch; } + public float getRotationRoll() { + if (internal instanceof ModdedEntity) { + return internal.getDataManager().get(ModdedEntity.ROLL); + } + return 0f; + } + + public void setRotationRoll(float roll) { + if (internal instanceof ModdedEntity) { + EntityDataManager dataManager = internal.getDataManager(); + dataManager.set(ModdedEntity.PREV_ROLL, dataManager.get(ModdedEntity.ROLL)); + dataManager.set(ModdedEntity.ROLL, roll); + } + } + + public float getRotationYaw(float partialTicks) { + return (float) MathHelper.clampedLerp(internal.prevRotationYaw, internal.rotationYaw, partialTicks); + } + + public float getRotationPitch(float partialTicks) { + return (float) MathHelper.clampedLerp(internal.prevRotationPitch, internal.rotationPitch, partialTicks); + } + + public float getRotationRoll(float partialTicks) { + return (float) MathHelper.clampedLerp(getPrevRotationRoll(), getRotationRoll(), partialTicks); + } + public float getPrevRotationYaw() { return internal.prevRotationYaw; } @@ -109,6 +138,13 @@ public float getPrevRotationPitch() { return internal.prevRotationPitch; } + public float getPrevRotationRoll() { + if (internal instanceof ModdedEntity) { + return internal.getDataManager().get(ModdedEntity.PREV_ROLL); + } + return 0f; + } + Vec3d eyeCache; public Vec3d getPositionEyes() { if (eyeCache == null || ( diff --git a/src/main/java/cam72cam/mod/entity/ModdedEntity.java b/src/main/java/cam72cam/mod/entity/ModdedEntity.java index dfda5742..f493efb4 100644 --- a/src/main/java/cam72cam/mod/entity/ModdedEntity.java +++ b/src/main/java/cam72cam/mod/entity/ModdedEntity.java @@ -15,6 +15,9 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; import net.minecraft.util.math.AxisAlignedBB; @@ -30,6 +33,9 @@ /** Internal class which extends MC's Entity. Do not use directly */ public class ModdedEntity extends Entity implements IEntityAdditionalSpawnData { + static final DataParameter PREV_ROLL = EntityDataManager.createKey(ModdedEntity.class, DataSerializers.FLOAT); + static final DataParameter ROLL = EntityDataManager.createKey(ModdedEntity.class, DataSerializers.FLOAT); + // Reference to the entity that this is representing private CustomEntity self; @@ -37,6 +43,11 @@ public class ModdedEntity extends Entity implements IEntityAdditionalSpawnData { @TagField(value = "passengers", mapper = PassengerMapper.class) private Map passengerPositions = new HashMap<>(); + @TagField + private float roll; + @TagField + private float prevRoll; + // All of the known seats attached to this entity private final List seats = new ArrayList<>(); @@ -70,6 +81,8 @@ public ModdedEntity(World world) { super(world); super.preventEntitySpawning = true; + this.dataManager.register(ROLL, 0f); + this.dataManager.register(PREV_ROLL, 0f); } @Override @@ -129,6 +142,11 @@ private void load(TagCompound data) { ModCore.catching(e, "Error during entity load: %s - %s", this, data); } + if (!this.world.isRemote) { + dataManager.set(ROLL, this.roll); + dataManager.set(PREV_ROLL, this.prevRoll); + } + TagCompound selfData = data.get("selfData"); if (selfData == null) { // Old style used to save everything in one giant NBT blob. New versions save self in a sub tag. @@ -162,6 +180,11 @@ protected final void writeEntityToNBT(NBTTagCompound compound) { */ private void save(TagCompound data) { data.setString("custom_mob_type", type); + if (!this.world.isRemote) { + this.roll = dataManager.get(ROLL); + this.prevRoll = dataManager.get(PREV_ROLL); + } + try { TagSerializer.serialize(data, this); } catch (SerializationException e) { @@ -226,6 +249,13 @@ public final void writeSpawnData(ByteBuf buffer) { @Override public final void onUpdate() { iTickable.onTick(); + + if (iTickable instanceof cam72cam.mod.entity.Entity) { + cam72cam.mod.entity.Entity moddedEntity = (cam72cam.mod.entity.Entity) iTickable; + moddedEntity.setRotationRoll(moddedEntity.getRotationRoll() + 10); + } + + this.dataManager.set(PREV_ROLL, this.dataManager.get(ROLL)); try { self.sync.send(); } catch (SerializationException e) { diff --git a/src/main/java/cam72cam/mod/render/EntityRenderer.java b/src/main/java/cam72cam/mod/render/EntityRenderer.java index 7ff9cc8c..03a2f6f2 100644 --- a/src/main/java/cam72cam/mod/render/EntityRenderer.java +++ b/src/main/java/cam72cam/mod/render/EntityRenderer.java @@ -102,7 +102,8 @@ public void doRender(ModdedEntity stock, double x, double y, double z, float ent RenderState state = new RenderState(); state.translate(x, y, z); state.rotate(180 - entityYaw, 0, 1, 0); - state.rotate(self.getRotationPitch(), 1, 0, 0); + state.rotate(self.getRotationPitch(partialTicks), 1, 0, 0); + state.rotate(self.getRotationRoll(partialTicks), 0, 0, 1); state.rotate(-90, 0, 1, 0); state.stage(RenderContext.Stage.ENTITY); renderers.get(self.getClass()).render(self, state, partialTicks); @@ -120,7 +121,8 @@ public void renderMultipass(ModdedEntity stock, double x, double y, double z, fl RenderState state = new RenderState(); state.translate(x, y, z); state.rotate(180 - entityYaw, 0, 1, 0); - state.rotate(self.getRotationPitch(), 1, 0, 0); + state.rotate(self.getRotationPitch(partialTicks), 1, 0, 0); + state.rotate(self.getRotationRoll(partialTicks), 0, 0, 1); state.rotate(-90, 0, 1, 0); state.stage(RenderContext.Stage.ENTITY); renderers.get(self.getClass()).postRender(self, state, partialTicks); From 8b2666cfe3820406a7deb62eda3ea77c3273acff Mon Sep 17 00:00:00 2001 From: Goldenfield192 <1437356849@qq.com> Date: Sun, 22 Mar 2026 14:08:07 +0800 Subject: [PATCH 2/3] remove testing code --- src/main/java/cam72cam/mod/entity/ModdedEntity.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/cam72cam/mod/entity/ModdedEntity.java b/src/main/java/cam72cam/mod/entity/ModdedEntity.java index f493efb4..f209c3f6 100644 --- a/src/main/java/cam72cam/mod/entity/ModdedEntity.java +++ b/src/main/java/cam72cam/mod/entity/ModdedEntity.java @@ -249,12 +249,6 @@ public final void writeSpawnData(ByteBuf buffer) { @Override public final void onUpdate() { iTickable.onTick(); - - if (iTickable instanceof cam72cam.mod.entity.Entity) { - cam72cam.mod.entity.Entity moddedEntity = (cam72cam.mod.entity.Entity) iTickable; - moddedEntity.setRotationRoll(moddedEntity.getRotationRoll() + 10); - } - this.dataManager.set(PREV_ROLL, this.dataManager.get(ROLL)); try { self.sync.send(); From a03a15c760c2df848ef977a4bf2ece6b7d2feb7d Mon Sep 17 00:00:00 2001 From: Goldenfield192 <1437356849@qq.com> Date: Sun, 22 Mar 2026 14:31:12 +0800 Subject: [PATCH 3/3] fix: restrict degrees range --- src/main/java/cam72cam/mod/entity/Entity.java | 32 ++++++++++++++----- .../cam72cam/mod/entity/ModdedEntity.java | 7 ++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/main/java/cam72cam/mod/entity/Entity.java b/src/main/java/cam72cam/mod/entity/Entity.java index bbaabe58..44bb6a97 100644 --- a/src/main/java/cam72cam/mod/entity/Entity.java +++ b/src/main/java/cam72cam/mod/entity/Entity.java @@ -81,17 +81,15 @@ public float getRotationYaw() { public void setRotationYaw(float yaw) { internal.prevRotationYaw = internal.rotationYaw; internal.rotationYaw = yaw; - double d0 = internal.prevRotationYaw - yaw; - if (d0 < -180.0D) - { - internal.prevRotationYaw += 360.0F; - } - if (d0 >= 180.0D) + while (internal.rotationYaw - internal.prevRotationYaw < -180.0F) { internal.prevRotationYaw -= 360.0F; } - + while (internal.rotationYaw - internal.prevRotationYaw >= 180.0F) + { + internal.prevRotationYaw += 360.0F; + } } public float getRotationPitch() { @@ -101,6 +99,15 @@ public float getRotationPitch() { public void setRotationPitch(float pitch) { internal.prevRotationPitch = internal.rotationPitch; internal.rotationPitch = pitch; + + while (internal.rotationPitch - internal.prevRotationPitch < -180.0F) + { + internal.prevRotationPitch -= 360.0F; + } + while (internal.rotationPitch - internal.prevRotationPitch >= 180.0F) + { + internal.prevRotationPitch += 360.0F; + } } public float getRotationRoll() { @@ -113,7 +120,16 @@ public float getRotationRoll() { public void setRotationRoll(float roll) { if (internal instanceof ModdedEntity) { EntityDataManager dataManager = internal.getDataManager(); - dataManager.set(ModdedEntity.PREV_ROLL, dataManager.get(ModdedEntity.ROLL)); + float prevRoll = dataManager.get(ModdedEntity.PREV_ROLL); + while (roll - prevRoll < -180.0F) + { + prevRoll -= 360.0F; + } + while (roll - prevRoll >= 180.0F) + { + prevRoll += 360.0F; + } + dataManager.set(ModdedEntity.PREV_ROLL, prevRoll); dataManager.set(ModdedEntity.ROLL, roll); } } diff --git a/src/main/java/cam72cam/mod/entity/ModdedEntity.java b/src/main/java/cam72cam/mod/entity/ModdedEntity.java index f209c3f6..82ec9d19 100644 --- a/src/main/java/cam72cam/mod/entity/ModdedEntity.java +++ b/src/main/java/cam72cam/mod/entity/ModdedEntity.java @@ -33,9 +33,6 @@ /** Internal class which extends MC's Entity. Do not use directly */ public class ModdedEntity extends Entity implements IEntityAdditionalSpawnData { - static final DataParameter PREV_ROLL = EntityDataManager.createKey(ModdedEntity.class, DataSerializers.FLOAT); - static final DataParameter ROLL = EntityDataManager.createKey(ModdedEntity.class, DataSerializers.FLOAT); - // Reference to the entity that this is representing private CustomEntity self; @@ -43,6 +40,10 @@ public class ModdedEntity extends Entity implements IEntityAdditionalSpawnData { @TagField(value = "passengers", mapper = PassengerMapper.class) private Map passengerPositions = new HashMap<>(); + //For data sync + static final DataParameter PREV_ROLL = EntityDataManager.createKey(ModdedEntity.class, DataSerializers.FLOAT); + static final DataParameter ROLL = EntityDataManager.createKey(ModdedEntity.class, DataSerializers.FLOAT); + //For data storage @TagField private float roll; @TagField