From 674e8feed211c41ea8cefa31aa3ec70e85fa3781 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sun, 13 Jun 2021 16:30:37 +0800 Subject: [PATCH 01/51] BodyPart: Hold down the Alt/Option key to lock the space transformed while switching limbs --- .../mchorse/metamorph/bodypart/BodyPart.java | 103 ++++++++++++++++-- .../metamorph/bodypart/GuiBodyPartEditor.java | 3 +- 2 files changed, 93 insertions(+), 13 deletions(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java index 7ba4fbfe..20c0e66a 100644 --- a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java +++ b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java @@ -1,25 +1,32 @@ package mchorse.metamorph.bodypart; +import javax.vecmath.Matrix3f; +import javax.vecmath.Matrix4f; +import javax.vecmath.Vector3f; + +import org.lwjgl.opengl.GL11; + import com.google.common.base.Objects; + import mchorse.mclib.client.Draw; import mchorse.mclib.client.gui.framework.elements.GuiModelRenderer; +import mchorse.mclib.utils.DummyEntity; import mchorse.mclib.utils.Interpolation; import mchorse.mclib.utils.MatrixUtils; +import mchorse.mclib.utils.MatrixUtils.Transformation; +import mchorse.mclib.utils.MatrixUtils.Transformation.RotationOrder; +import mchorse.mclib.utils.NBTUtils; import mchorse.metamorph.Metamorph; +import mchorse.metamorph.api.Morph; import mchorse.metamorph.api.MorphUtils; +import mchorse.metamorph.api.morphs.AbstractMorph; import mchorse.metamorph.api.morphs.utils.Animation; import mchorse.metamorph.api.morphs.utils.IAnimationProvider; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; -import org.lwjgl.opengl.GL11; - -import mchorse.mclib.utils.DummyEntity; -import mchorse.mclib.utils.NBTUtils; -import mchorse.metamorph.api.Morph; -import mchorse.metamorph.api.morphs.AbstractMorph; -import mchorse.metamorph.capabilities.morphing.IMorphing; -import net.minecraft.client.Minecraft; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -27,10 +34,6 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import javax.vecmath.Matrix3f; -import javax.vecmath.Matrix4f; -import javax.vecmath.Vector3f; - /** * Morph body part */ @@ -39,6 +42,7 @@ public class BodyPart public static Vector3f cachedTranslation = new Vector3f(); public static Vector3f cachedAngularVelocity = new Vector3f(); public static Matrix4f modelViewMatrix = new Matrix4f(); + public static boolean recording = false; public Morph morph = new Morph(); public ItemStack[] slots = new ItemStack[] {ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY}; @@ -56,6 +60,8 @@ public class BodyPart private Vector3f lastScale; private Vector3f lastRotate; private Vector3f previousRotation = new Vector3f(); + + public Matrix4f lastMatrix = null; @SideOnly(Side.CLIENT) public void init() @@ -85,6 +91,12 @@ public void updateEntity() @SideOnly(Side.CLIENT) public void render(AbstractMorph parent, EntityLivingBase entity, float partialTicks) { + if (recording) + { + this.lastMatrix = MatrixUtils.readModelView(new Matrix4f()); + return; + } + entity = this.useTarget ? entity : this.entity; if (this.morph.get() == null || entity == null || !this.enabled) @@ -430,4 +442,71 @@ public void toNBT(NBTTagCompound tag) if (!this.animate) tag.setBoolean("Animate", this.animate); if (!this.limb.isEmpty()) tag.setString("Limb", this.limb); } + + @SideOnly(Side.CLIENT) + public void setLimb(AbstractMorph parent, String limb, boolean convertTransform) + { + if (this.limb.equals(limb)) + { + return; + } + + if (this.limb.isEmpty() || !convertTransform) + { + this.limb = limb; + return; + } + + recording = true; + EntityPlayer player = Minecraft.getMinecraft().player; + + int lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE); + GL11.glMatrixMode(GL11.GL_MODELVIEW); + + GL11.glPushMatrix(); + GL11.glLoadIdentity(); + MorphUtils.render(parent, player, 0, 0, 0, 0, 0); + GL11.glPopMatrix(); + Matrix4f last = this.lastMatrix; + Matrix4f transform = new Matrix4f(); + transform.setIdentity(); + transform.setTranslation(this.translate); + last.mul(transform); + transform.rotZ((float) Math.toRadians(this.rotate.z)); + last.mul(transform); + transform.rotY((float) Math.toRadians(this.rotate.y)); + last.mul(transform); + transform.rotX((float) Math.toRadians(this.rotate.x)); + last.mul(transform); + transform.setIdentity(); + transform.m00 = this.scale.x; + transform.m11 = this.scale.y; + transform.m22 = this.scale.z; + last.mul(transform); + + this.limb = limb; + + GL11.glPushMatrix(); + GL11.glLoadIdentity(); + MorphUtils.render(parent, player, 0, 0, 0, 0, 0); + GL11.glPopMatrix(); + Matrix4f current = this.lastMatrix; + + Transformation extract = MatrixUtils.extractTransformations(current, last); + + if (extract.getCreationException() == null) + { + Vector3f rotate = extract.getRotation(RotationOrder.XYZ); + if (rotate != null) + { + this.translate.set(extract.getTranslation3f()); + this.rotate.set(rotate); + this.scale.set(extract.getScale()); + } + } + + GL11.glMatrixMode(lastMatrixMode); + + recording = false; + } } \ No newline at end of file diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index 86c3aede..cef606e3 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -390,7 +390,8 @@ protected void setPart(BodyPart part) protected void pickLimb(String str) { - this.part.limb = str; + this.part.setLimb(this.morph, str, GuiScreen.isAltKeyDown()); + this.fillBodyPart(this.part); } public void fillBodyPart(BodyPart part) From 482d9a43ba2543fffc7555e42280943982c27755 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sun, 27 Jun 2021 15:34:08 +0800 Subject: [PATCH 02/51] Added option to disable shadow mapping of morph --- .../mchorse/metamorph/api/MorphSettings.java | 22 +++++++++++++- .../mchorse/metamorph/api/MorphUtils.java | 29 +++++++++++++++++++ .../api/json/MorphSettingsAdapter.java | 5 ++++ .../client/gui/editor/GuiSettingsPanel.java | 13 +++++++++ .../assets/metamorph/lang/en_US.lang | 1 + .../assets/metamorph/lang/zh_CN.lang | 1 + .../assets/metamorph/lang/zh_TW.lang | 1 + 7 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/api/MorphSettings.java b/src/main/java/mchorse/metamorph/api/MorphSettings.java index 18b5bf60..306528da 100644 --- a/src/main/java/mchorse/metamorph/api/MorphSettings.java +++ b/src/main/java/mchorse/metamorph/api/MorphSettings.java @@ -67,6 +67,11 @@ public class MorphSettings * Does this morph updates itself */ public boolean updates = true; + + /** + * Whether to render this morph in shadow pass + */ + public boolean shadowMapping = true; @Override public boolean equals(Object obj) @@ -81,7 +86,8 @@ public boolean equals(Object obj) this.health == settings.health && this.speed == settings.speed && this.hostile == settings.hostile && - this.updates == settings.updates; + this.updates == settings.updates && + this.shadowMapping == settings.shadowMapping; } return super.equals(obj); @@ -112,6 +118,8 @@ public void copy(MorphSettings setting) this.hostile = setting.hostile; this.hands = setting.hands; this.updates = setting.updates; + + this.shadowMapping = setting.shadowMapping; } /** @@ -150,6 +158,7 @@ public void toBytes(ByteBuf buf) buf.writeBoolean(this.hostile); buf.writeBoolean(this.hands); buf.writeBoolean(this.updates); + buf.writeBoolean(this.shadowMapping); } /** @@ -188,6 +197,7 @@ public void fromBytes(ByteBuf buf) this.hostile = buf.readBoolean(); this.hands = buf.readBoolean(); this.updates = buf.readBoolean(); + this.shadowMapping = buf.readBoolean(); } /** @@ -241,6 +251,11 @@ public void toNBT(NBTTagCompound tag) { tag.setBoolean("Updates", this.updates); } + + if (!this.shadowMapping) + { + tag.setBoolean("ShadowMapping", this.shadowMapping); + } } /** @@ -299,6 +314,11 @@ public void fromNBT(NBTTagCompound tag) { this.updates = tag.getBoolean("Updates"); } + + if (tag.hasKey("ShadowMapping")) + { + this.shadowMapping = tag.getBoolean("ShadowMapping"); + } } /** diff --git a/src/main/java/mchorse/metamorph/api/MorphUtils.java b/src/main/java/mchorse/metamorph/api/MorphUtils.java index 94247ea1..2c3a6f5c 100644 --- a/src/main/java/mchorse/metamorph/api/MorphUtils.java +++ b/src/main/java/mchorse/metamorph/api/MorphUtils.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; +import java.lang.reflect.Field; import java.util.Map; import java.util.Set; @@ -24,6 +25,21 @@ public class MorphUtils { + + public static final Field isShadowPass; + + static { + Field field = null; + try + { + Class clazz = Class.forName("net.optifine.shaders.Shaders"); + field = clazz.getField("isShadowPass"); + } + catch (Exception e) + {} + isShadowPass = field; + } + /** * Generate an empty file */ @@ -86,6 +102,19 @@ public static boolean render(AbstractMorph morph, EntityLivingBase entity, doubl { return false; } + + if (isShadowPass != null && !morph.settings.shadowMapping) + { + try + { + if (isShadowPass.getBoolean(null)) + { + return false; + } + } + catch (Exception e) + {} + } try { diff --git a/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java b/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java index ad1bc452..23ad5e18 100644 --- a/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java +++ b/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java @@ -83,6 +83,11 @@ public MorphSettings deserialize(JsonElement json, Type typeOfT, JsonDeserializa { morph.updates = object.get("updates").getAsBoolean(); } + + if (object.has("shadowmapping") && object.get("shadowmapping").isJsonPrimitive()) + { + morph.shadowMapping = object.get("shadowmapping").getAsBoolean(); + } return morph; } diff --git a/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java b/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java index ac9c358e..ccc7ae4b 100644 --- a/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java +++ b/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java @@ -43,6 +43,8 @@ public class GuiSettingsPanel extends GuiMorphPanel this.morph.settings.shadowMapping = b.isToggled()); + try + { + Class.forName("net.optifine.shaders.Shaders"); + this.right.add(Elements.label(IKey.str("Optifine")).marginTop(8), this.shadowMapping); + } + catch (ClassNotFoundException e) + {} this.add(this.left, this.right, this.data); } @@ -184,6 +195,8 @@ public void fillData(AbstractMorph morph) this.hitboxHeight.setValue(morph.hitbox.height); this.hitboxSneakingHeight.setValue(morph.hitbox.sneakingHeight); this.hitboxEyePosition.setValue(morph.hitbox.eye); + + this.shadowMapping.toggled(morph.settings.shadowMapping); } public void updateNBT() diff --git a/src/main/resources/assets/metamorph/lang/en_US.lang b/src/main/resources/assets/metamorph/lang/en_US.lang index e5517b8b..bb54beeb 100644 --- a/src/main/resources/assets/metamorph/lang/en_US.lang +++ b/src/main/resources/assets/metamorph/lang/en_US.lang @@ -111,6 +111,7 @@ metamorph.gui.editor.texture=Pick a texture... metamorph.gui.editor.texture_tooltip=This feature won't work for all mobs, because some mobs can have custom rendering implementation metamorph.gui.editor.keys.category=Morph editor keybinds metamorph.gui.editor.keys.cycle=Cycle between morph panels +metamorph.gui.editor.shadowmapping=Shadow Mapping metamorph.gui.editor.hitbox.enabled=Custom hitbox metamorph.gui.editor.hitbox.size=Size diff --git a/src/main/resources/assets/metamorph/lang/zh_CN.lang b/src/main/resources/assets/metamorph/lang/zh_CN.lang index 3a17e74c..05e92d50 100644 --- a/src/main/resources/assets/metamorph/lang/zh_CN.lang +++ b/src/main/resources/assets/metamorph/lang/zh_CN.lang @@ -111,6 +111,7 @@ metamorph.gui.editor.texture=选取材质贴图... metamorph.gui.editor.texture_tooltip=该功能不一定适用于所有生物,因为部分生物拥有非常规的渲染实现。 metamorph.gui.editor.keys.category=伪装编辑器快捷键 metamorph.gui.editor.keys.cycle=在伪装面板间循环切换 +metamorph.gui.editor.shadowmapping=阴影映射 metamorph.gui.editor.hitbox.enabled=自定义碰撞箱 metamorph.gui.editor.hitbox.size=大小 diff --git a/src/main/resources/assets/metamorph/lang/zh_TW.lang b/src/main/resources/assets/metamorph/lang/zh_TW.lang index c4c6fb34..f9816405 100644 --- a/src/main/resources/assets/metamorph/lang/zh_TW.lang +++ b/src/main/resources/assets/metamorph/lang/zh_TW.lang @@ -111,6 +111,7 @@ metamorph.gui.editor.texture=選取材質貼圖... metamorph.gui.editor.texture_tooltip=該功能不一定適用於所有生物,因為部分生物擁有非常規的渲染實現。 metamorph.gui.editor.keys.category=偽裝編輯器快捷鍵 metamorph.gui.editor.keys.cycle=在偽裝面板間循環切換 +metamorph.gui.editor.shadowmapping=陰影映射 metamorph.gui.editor.hitbox.enabled=自定義碰撞箱 metamorph.gui.editor.hitbox.size=大小 From 25832bb85d2f9345b6a97a35ee4cd08c1bb05aa3 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sat, 10 Jul 2021 20:27:10 +0800 Subject: [PATCH 03/51] Add ISyncableMorph.resume() --- .../mchorse/metamorph/api/MorphUtils.java | 28 ++++++++++++++++++ .../api/morphs/utils/ISyncableMorph.java | 29 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/main/java/mchorse/metamorph/api/MorphUtils.java b/src/main/java/mchorse/metamorph/api/MorphUtils.java index 2c3a6f5c..b9eb8d88 100644 --- a/src/main/java/mchorse/metamorph/api/MorphUtils.java +++ b/src/main/java/mchorse/metamorph/api/MorphUtils.java @@ -14,6 +14,7 @@ import mchorse.metamorph.api.events.RegisterSettingsEvent; import mchorse.metamorph.api.morphs.AbstractMorph; import mchorse.metamorph.api.morphs.utils.ISyncableMorph; +import mchorse.metamorph.bodypart.BodyPart; import mchorse.metamorph.bodypart.IBodyPartProvider; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -183,6 +184,33 @@ else if (morph instanceof IBodyPartProvider) return false; } + + /** + * Resume given morph from pause. + */ + public static boolean resume(AbstractMorph morph) + { + if (morph instanceof ISyncableMorph) + { + ((ISyncableMorph) morph).resume(); + + return true; + } + else if (morph instanceof IBodyPartProvider) + { + for (BodyPart part : ((IBodyPartProvider) morph).getBodyPart().parts) + { + if (!part.morph.isEmpty() && part.morph.get() instanceof ISyncableMorph) + { + ((ISyncableMorph) part.morph.get()).resume(); + } + } + + return true; + } + + return false; + } /** * Morph to NBT diff --git a/src/main/java/mchorse/metamorph/api/morphs/utils/ISyncableMorph.java b/src/main/java/mchorse/metamorph/api/morphs/utils/ISyncableMorph.java index d5ab3e24..b3fc1e82 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/utils/ISyncableMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/utils/ISyncableMorph.java @@ -1,10 +1,39 @@ package mchorse.metamorph.api.morphs.utils; +import mchorse.metamorph.api.models.IMorphProvider; import mchorse.metamorph.api.morphs.AbstractMorph; +import mchorse.metamorph.bodypart.BodyPart; +import mchorse.metamorph.bodypart.IBodyPartProvider; public interface ISyncableMorph { public void pause(AbstractMorph previous, int offset); public boolean isPaused(); + + default public void resume() + { + Object morph = this; + + if (morph instanceof IMorphProvider) + { + morph = ((IMorphProvider) morph).getMorph(); + } + + if (morph instanceof IAnimationProvider) + { + ((IAnimationProvider) morph).getAnimation().paused = false; + } + + if (morph instanceof IBodyPartProvider) + { + for (BodyPart part : ((IBodyPartProvider) morph).getBodyPart().parts) + { + if (!part.morph.isEmpty() && part.morph.get() instanceof ISyncableMorph) + { + ((ISyncableMorph) part.morph.get()).resume(); + } + } + } + } } \ No newline at end of file From 95db68effe446d6eb7451643186672ffd3918728 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sat, 24 Jul 2021 10:25:10 +0800 Subject: [PATCH 04/51] Fix crash when text have non-english character --- .../java/mchorse/vanilla_pack/morphs/LabelMorph.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/mchorse/vanilla_pack/morphs/LabelMorph.java b/src/main/java/mchorse/vanilla_pack/morphs/LabelMorph.java index 7355666b..ad75c644 100644 --- a/src/main/java/mchorse/vanilla_pack/morphs/LabelMorph.java +++ b/src/main/java/mchorse/vanilla_pack/morphs/LabelMorph.java @@ -146,7 +146,14 @@ private void renderString() } else { - int max = MathUtils.clamp(this.max, 6, Integer.MAX_VALUE); + int min = 6; + + for (int i = 0; i < text.length(); i++) + { + min = Math.max(font.getCharWidth(text.charAt(i)), min); + } + + int max = MathUtils.clamp(this.max, min, Integer.MAX_VALUE); List labels = font.listFormattedStringToWidth(text, max); int h = MathUtils.clamp(labels.size() - 1, 0, 100) * 12 + font.FONT_HEIGHT; int y = -(int) (h * this.anchorY); From 6b50b2bb57b19b94a2427c5fb32a96e616360130 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sat, 24 Jul 2021 23:38:20 +0800 Subject: [PATCH 05/51] Add IMorphGenerator --- .../api/morphs/utils/IMorphGenerator.java | 10 +++++ .../mchorse/metamorph/bodypart/BodyPart.java | 39 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/main/java/mchorse/metamorph/api/morphs/utils/IMorphGenerator.java diff --git a/src/main/java/mchorse/metamorph/api/morphs/utils/IMorphGenerator.java b/src/main/java/mchorse/metamorph/api/morphs/utils/IMorphGenerator.java new file mode 100644 index 00000000..de8c1c7c --- /dev/null +++ b/src/main/java/mchorse/metamorph/api/morphs/utils/IMorphGenerator.java @@ -0,0 +1,10 @@ +package mchorse.metamorph.api.morphs.utils; + +import mchorse.metamorph.api.morphs.AbstractMorph; + +public interface IMorphGenerator +{ + public boolean canGenerate(); + + public AbstractMorph genCurrentMorph(float partialTicks); +} diff --git a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java index 20c0e66a..05f54dc8 100644 --- a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java +++ b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java @@ -22,6 +22,7 @@ import mchorse.metamorph.api.morphs.AbstractMorph; import mchorse.metamorph.api.morphs.utils.Animation; import mchorse.metamorph.api.morphs.utils.IAnimationProvider; +import mchorse.metamorph.api.morphs.utils.IMorphGenerator; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; @@ -308,6 +309,44 @@ public void pause(BodyPart previous, int offset) MorphUtils.pause(this.morph.get(), previous == null ? null : previous.morph.get(), offset); } + public BodyPart genCurrentBodyPart(AbstractMorph morph, float partialTicks) + { + BodyPart part = this.copy(); + + if (morph instanceof IAnimationProvider) + { + Animation animation = ((IAnimationProvider) morph).getAnimation(); + + if (animation.isInProgress() && this.lastTranslate != null && this.animate) + { + Interpolation inter = animation.interp; + float factor = animation.getFactor(partialTicks); + + part.translate.x = inter.interpolate(this.lastTranslate.x, this.translate.x, factor); + part.translate.y = inter.interpolate(this.lastTranslate.y, this.translate.y, factor); + part.translate.z = inter.interpolate(this.lastTranslate.z, this.translate.z, factor); + part.scale.x = inter.interpolate(this.lastScale.x, this.scale.x, factor); + part.scale.y = inter.interpolate(this.lastScale.y, this.scale.y, factor); + part.scale.z = inter.interpolate(this.lastScale.z, this.scale.z, factor); + part.rotate.x = inter.interpolate(this.lastRotate.x, this.rotate.x, factor); + part.rotate.y = inter.interpolate(this.lastRotate.y, this.rotate.y, factor); + part.rotate.z = inter.interpolate(this.lastRotate.z, this.rotate.z, factor); + } + } + + if (this.morph.get() instanceof IMorphGenerator) + { + IMorphGenerator generator = (IMorphGenerator) this.morph.get(); + + if (generator.canGenerate()) + { + part.morph.setDirect(generator.genCurrentMorph(partialTicks)); + } + } + + return part; + } + @Override public boolean equals(Object obj) { From 7aee506462e76c44b4176936621baccc88068ea4 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sat, 31 Jul 2021 01:20:24 +0800 Subject: [PATCH 06/51] Add some functions for creative morph list --- .../gui/creative/GuiCreativeMorphsList.java | 65 ++++++++++++++++++- .../client/gui/editor/GuiAbstractMorph.java | 22 +++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java index faeda1f7..3acf4a0b 100644 --- a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java +++ b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java @@ -3,6 +3,7 @@ import mchorse.mclib.client.gui.framework.GuiBase; import mchorse.mclib.client.gui.framework.elements.GuiDelegateElement; import mchorse.mclib.client.gui.framework.elements.GuiElement; +import mchorse.mclib.client.gui.framework.elements.GuiModelRenderer; import mchorse.mclib.client.gui.framework.elements.buttons.GuiButtonElement; import mchorse.mclib.client.gui.framework.elements.context.GuiSimpleContextMenu; import mchorse.mclib.client.gui.framework.elements.input.GuiTextElement; @@ -29,6 +30,8 @@ import java.util.Stack; import java.util.function.Consumer; +import javax.vecmath.Vector3f; + /** * Scroll list of available morphs * @@ -66,6 +69,13 @@ public class GuiCreativeMorphsList extends GuiElement protected Keybind exitKey; + protected boolean keepViewport; + + protected Vector3f lastPos = new Vector3f(); + protected float lastYaw; + protected float lastPitch; + protected float lastScale; + /** * Initiate this GUI. * @@ -221,8 +231,19 @@ public boolean isNested() public void nestEdit(AbstractMorph selected, boolean editing, Consumer callback) { - NestedEdit edit = new NestedEdit(this.morphs.filter, this.editor.delegate.morph, this.editor.delegate.toNBT(), this.callback, this.morphs.selected, editing); + this.nestEdit(selected, editing, false, callback); + } + + public void nestEdit(AbstractMorph selected, boolean editing, boolean keepViewport, Consumer callback) + { + NestedEdit edit = new NestedEdit(this.morphs.filter, this.editor.delegate.morph, this.editor.delegate.toNBT(), this.callback, this.morphs.selected, editing, this.keepViewport); this.callback = callback; + this.keepViewport = keepViewport; + + if (keepViewport) + { + this.saveViewport(); + } if (editing) { @@ -259,6 +280,13 @@ public void restoreEdit() this.enterEditMorph(edit.editMorph); this.editor.delegate.fromNBT(edit.data); + + if (this.keepViewport) + { + this.loadViewport(); + } + + this.keepViewport = edit.keepViewport; } /* Edit mode */ @@ -300,6 +328,11 @@ public void enterEditMorph(AbstractMorph morph) if (editor != null) { this.setEditor(editor); + + if (this.keepViewport) + { + this.loadViewport(); + } } } @@ -310,6 +343,11 @@ public void exitEditMorph(boolean add, boolean ignore) return; } + if (this.keepViewport) + { + this.saveViewport(); + } + AbstractMorph edited = this.editor.delegate.morph; if (!this.nestedEdits.isEmpty() && !ignore) @@ -353,6 +391,8 @@ public void finish() { this.pickMorph(MorphUtils.copy(this.getSelected())); } + + this.keepViewport = false; } private GuiAbstractMorph getMorphEditor(AbstractMorph morph) @@ -377,6 +417,25 @@ private GuiAbstractMorph getMorphEditor(AbstractMorph morph) return null; } + private void saveViewport() + { + GuiModelRenderer renderer = this.editor.delegate.renderer; + + this.lastPos.set(renderer.pos); + this.lastPitch = renderer.pitch; + this.lastYaw = renderer.yaw; + this.lastScale = renderer.scale; + } + + private void loadViewport() + { + GuiModelRenderer renderer = this.editor.delegate.renderer; + + renderer.setPosition(this.lastPos.x, this.lastPos.y, this.lastPos.z); + renderer.setRotation(this.lastYaw, this.lastPitch); + renderer.setScale(this.lastScale); + } + /* Morph selection and filtering */ /** @@ -518,14 +577,16 @@ public static class NestedEdit public AbstractMorph selectedMorph; public AbstractMorph editMorph; public boolean editing; + public boolean keepViewport; - public NestedEdit(String filter, AbstractMorph editMorph, NBTTagCompound data, Consumer callback, GuiMorphSection selected, boolean editing) + public NestedEdit(String filter, AbstractMorph editMorph, NBTTagCompound data, Consumer callback, GuiMorphSection selected, boolean editing, boolean keepViewport) { this.filter = filter; this.data = data; this.editMorph = editMorph; this.callback = callback; this.editing = editing; + this.keepViewport = keepViewport; this.selected = selected; this.selectedCategory = selected == null ? null : selected.category; diff --git a/src/main/java/mchorse/metamorph/client/gui/editor/GuiAbstractMorph.java b/src/main/java/mchorse/metamorph/client/gui/editor/GuiAbstractMorph.java index e8e09c7f..28c46b7d 100644 --- a/src/main/java/mchorse/metamorph/client/gui/editor/GuiAbstractMorph.java +++ b/src/main/java/mchorse/metamorph/client/gui/editor/GuiAbstractMorph.java @@ -14,6 +14,8 @@ import mchorse.mclib.client.gui.utils.keys.IKey; import mchorse.mclib.utils.MathUtils; import mchorse.metamorph.api.morphs.AbstractMorph; +import mchorse.metamorph.api.morphs.utils.Animation; +import mchorse.metamorph.api.morphs.utils.IAnimationProvider; import mchorse.metamorph.bodypart.GuiBodyPartEditor; import mchorse.metamorph.client.gui.creative.GuiCreativeMorphsList; import mchorse.metamorph.client.gui.creative.GuiMorphRenderer; @@ -192,6 +194,26 @@ public List getFields(Minecraft mc, GuiCreativeMorphsList morphs, T return elements; } + /** + * Get current tick for preview + */ + public int getCurrentTick() + { + int tick = 0; + + if (this.morph instanceof IAnimationProvider) + { + Animation animation = ((IAnimationProvider) this.morph).getAnimation(); + + if (animation.animates) + { + tick = animation.duration; + } + } + + return tick; + } + @Override public GuiIconElement registerPanel(GuiMorphPanel panel, IKey tooltip, Icon icon) { From 86ef4e4133ab8ab6eb50ccc38a24af6f7018547c Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sat, 31 Jul 2021 10:12:04 +0800 Subject: [PATCH 07/51] Add option to render shadows only --- .../mchorse/metamorph/api/MorphSettings.java | 18 +++++------ .../mchorse/metamorph/api/MorphUtils.java | 32 ++++--------------- .../api/json/MorphSettingsAdapter.java | 4 +-- .../client/gui/editor/GuiSettingsPanel.java | 23 +++++++++---- .../assets/metamorph/lang/en_US.lang | 4 ++- .../assets/metamorph/lang/zh_CN.lang | 4 ++- .../assets/metamorph/lang/zh_TW.lang | 4 ++- 7 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/main/java/mchorse/metamorph/api/MorphSettings.java b/src/main/java/mchorse/metamorph/api/MorphSettings.java index 306528da..684fa643 100644 --- a/src/main/java/mchorse/metamorph/api/MorphSettings.java +++ b/src/main/java/mchorse/metamorph/api/MorphSettings.java @@ -71,7 +71,7 @@ public class MorphSettings /** * Whether to render this morph in shadow pass */ - public boolean shadowMapping = true; + public int shadowOption = 0; @Override public boolean equals(Object obj) @@ -87,7 +87,7 @@ public boolean equals(Object obj) this.speed == settings.speed && this.hostile == settings.hostile && this.updates == settings.updates && - this.shadowMapping == settings.shadowMapping; + this.shadowOption == settings.shadowOption; } return super.equals(obj); @@ -119,7 +119,7 @@ public void copy(MorphSettings setting) this.hands = setting.hands; this.updates = setting.updates; - this.shadowMapping = setting.shadowMapping; + this.shadowOption = setting.shadowOption; } /** @@ -158,7 +158,7 @@ public void toBytes(ByteBuf buf) buf.writeBoolean(this.hostile); buf.writeBoolean(this.hands); buf.writeBoolean(this.updates); - buf.writeBoolean(this.shadowMapping); + buf.writeInt(this.shadowOption); } /** @@ -197,7 +197,7 @@ public void fromBytes(ByteBuf buf) this.hostile = buf.readBoolean(); this.hands = buf.readBoolean(); this.updates = buf.readBoolean(); - this.shadowMapping = buf.readBoolean(); + this.shadowOption = buf.readInt(); } /** @@ -252,9 +252,9 @@ public void toNBT(NBTTagCompound tag) tag.setBoolean("Updates", this.updates); } - if (!this.shadowMapping) + if (this.shadowOption != 0) { - tag.setBoolean("ShadowMapping", this.shadowMapping); + tag.setInteger("ShadowOption", this.shadowOption); } } @@ -315,9 +315,9 @@ public void fromNBT(NBTTagCompound tag) this.updates = tag.getBoolean("Updates"); } - if (tag.hasKey("ShadowMapping")) + if (tag.hasKey("ShadowOption")) { - this.shadowMapping = tag.getBoolean("ShadowMapping"); + this.shadowOption = tag.getInteger("ShadowOption"); } } diff --git a/src/main/java/mchorse/metamorph/api/MorphUtils.java b/src/main/java/mchorse/metamorph/api/MorphUtils.java index b9eb8d88..3950bfa6 100644 --- a/src/main/java/mchorse/metamorph/api/MorphUtils.java +++ b/src/main/java/mchorse/metamorph/api/MorphUtils.java @@ -9,6 +9,7 @@ import io.netty.buffer.ByteBuf; import mchorse.mclib.utils.NBTUtils; +import mchorse.mclib.utils.ReflectionUtils; import mchorse.metamorph.api.events.RegisterBlacklistEvent; import mchorse.metamorph.api.events.RegisterRemapEvent; import mchorse.metamorph.api.events.RegisterSettingsEvent; @@ -26,21 +27,6 @@ public class MorphUtils { - - public static final Field isShadowPass; - - static { - Field field = null; - try - { - Class clazz = Class.forName("net.optifine.shaders.Shaders"); - field = clazz.getField("isShadowPass"); - } - catch (Exception e) - {} - isShadowPass = field; - } - /** * Generate an empty file */ @@ -103,18 +89,12 @@ public static boolean render(AbstractMorph morph, EntityLivingBase entity, doubl { return false; } - - if (isShadowPass != null && !morph.settings.shadowMapping) + + boolean isShadowPass = ReflectionUtils.isOptifineShadowPass(); + + if (isShadowPass && morph.settings.shadowOption == 1 || !isShadowPass && morph.settings.shadowOption == 2) { - try - { - if (isShadowPass.getBoolean(null)) - { - return false; - } - } - catch (Exception e) - {} + return false; } try diff --git a/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java b/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java index 23ad5e18..3010ad2c 100644 --- a/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java +++ b/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java @@ -84,9 +84,9 @@ public MorphSettings deserialize(JsonElement json, Type typeOfT, JsonDeserializa morph.updates = object.get("updates").getAsBoolean(); } - if (object.has("shadowmapping") && object.get("shadowmapping").isJsonPrimitive()) + if (object.has("shadow_option") && object.get("shadow_option").isJsonPrimitive()) { - morph.shadowMapping = object.get("shadowmapping").getAsBoolean(); + morph.shadowOption = object.get("shadow_option").getAsInt(); } return morph; diff --git a/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java b/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java index ccc7ae4b..12ef2295 100644 --- a/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java +++ b/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java @@ -2,6 +2,7 @@ import mchorse.mclib.client.gui.framework.elements.GuiScrollElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiButtonElement; +import mchorse.mclib.client.gui.framework.elements.buttons.GuiCirculateElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiToggleElement; import mchorse.mclib.client.gui.framework.elements.input.GuiKeybindElement; import mchorse.mclib.client.gui.framework.elements.input.GuiTextElement; @@ -44,7 +45,7 @@ public class GuiSettingsPanel extends GuiMorphPanel this.morph.settings.shadowMapping = b.isToggled()); + + this.shadowOption = new GuiCirculateElement(mc, (element) -> this.morph.settings.shadowOption = element.getValue()); + for (OptifineShadowOption option : OptifineShadowOption.values()) + { + this.shadowOption.addLabel(IKey.lang("metamorph.gui.editor.shadow." + option.name().toLowerCase())); + } + try { Class.forName("net.optifine.shaders.Shaders"); - this.right.add(Elements.label(IKey.str("Optifine")).marginTop(8), this.shadowMapping); + this.right.add(Elements.label(IKey.str("Optifine")).marginTop(8), this.shadowOption); } catch (ClassNotFoundException e) {} @@ -195,8 +201,8 @@ public void fillData(AbstractMorph morph) this.hitboxHeight.setValue(morph.hitbox.height); this.hitboxSneakingHeight.setValue(morph.hitbox.sneakingHeight); this.hitboxEyePosition.setValue(morph.hitbox.eye); - - this.shadowMapping.toggled(morph.settings.shadowMapping); + + this.shadowOption.setValue(morph.settings.shadowOption); } public void updateNBT() @@ -265,4 +271,9 @@ public void draw(GuiContext context) this.font.drawStringWithShadow(I18n.format("metamorph.gui.panels.nbt_data"), this.data.area.x, this.data.area.y - 12, this.error ? 0xffff3355 : 0xffffff); } } + + public enum OptifineShadowOption + { + ALL, NOSHADOW, ONLYSHADOW + } } \ No newline at end of file diff --git a/src/main/resources/assets/metamorph/lang/en_US.lang b/src/main/resources/assets/metamorph/lang/en_US.lang index bb54beeb..ad3959f7 100644 --- a/src/main/resources/assets/metamorph/lang/en_US.lang +++ b/src/main/resources/assets/metamorph/lang/en_US.lang @@ -111,7 +111,9 @@ metamorph.gui.editor.texture=Pick a texture... metamorph.gui.editor.texture_tooltip=This feature won't work for all mobs, because some mobs can have custom rendering implementation metamorph.gui.editor.keys.category=Morph editor keybinds metamorph.gui.editor.keys.cycle=Cycle between morph panels -metamorph.gui.editor.shadowmapping=Shadow Mapping +metamorph.gui.editor.shadow.all=Render all +metamorph.gui.editor.shadow.noshadow=No shadow +metamorph.gui.editor.shadow.onlyshadow=Only shaodws metamorph.gui.editor.hitbox.enabled=Custom hitbox metamorph.gui.editor.hitbox.size=Size diff --git a/src/main/resources/assets/metamorph/lang/zh_CN.lang b/src/main/resources/assets/metamorph/lang/zh_CN.lang index 05e92d50..789d0296 100644 --- a/src/main/resources/assets/metamorph/lang/zh_CN.lang +++ b/src/main/resources/assets/metamorph/lang/zh_CN.lang @@ -111,7 +111,9 @@ metamorph.gui.editor.texture=选取材质贴图... metamorph.gui.editor.texture_tooltip=该功能不一定适用于所有生物,因为部分生物拥有非常规的渲染实现。 metamorph.gui.editor.keys.category=伪装编辑器快捷键 metamorph.gui.editor.keys.cycle=在伪装面板间循环切换 -metamorph.gui.editor.shadowmapping=阴影映射 +metamorph.gui.editor.shadow.all=渲染全部 +metamorph.gui.editor.shadow.noshadow=不渲染阴影 +metamorph.gui.editor.shadow.onlyshadow=只渲染阴影 metamorph.gui.editor.hitbox.enabled=自定义碰撞箱 metamorph.gui.editor.hitbox.size=大小 diff --git a/src/main/resources/assets/metamorph/lang/zh_TW.lang b/src/main/resources/assets/metamorph/lang/zh_TW.lang index f9816405..45342808 100644 --- a/src/main/resources/assets/metamorph/lang/zh_TW.lang +++ b/src/main/resources/assets/metamorph/lang/zh_TW.lang @@ -111,7 +111,9 @@ metamorph.gui.editor.texture=選取材質貼圖... metamorph.gui.editor.texture_tooltip=該功能不一定適用於所有生物,因為部分生物擁有非常規的渲染實現。 metamorph.gui.editor.keys.category=偽裝編輯器快捷鍵 metamorph.gui.editor.keys.cycle=在偽裝面板間循環切換 -metamorph.gui.editor.shadowmapping=陰影映射 +metamorph.gui.editor.shadow.all=渲染全部 +metamorph.gui.editor.shadow.noshadow=不渲染陰影 +metamorph.gui.editor.shadow.onlyshadow=只渲染陰影 metamorph.gui.editor.hitbox.enabled=自定義碰撞箱 metamorph.gui.editor.hitbox.size=大小 From 1fb020e78f2358d829e079ab547b290142378f8f Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Thu, 5 Aug 2021 01:29:22 +0800 Subject: [PATCH 08/51] print exception for morph rendering --- .../mchorse/metamorph/api/MorphUtils.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/mchorse/metamorph/api/MorphUtils.java b/src/main/java/mchorse/metamorph/api/MorphUtils.java index 3950bfa6..1631e370 100644 --- a/src/main/java/mchorse/metamorph/api/MorphUtils.java +++ b/src/main/java/mchorse/metamorph/api/MorphUtils.java @@ -17,6 +17,8 @@ import mchorse.metamorph.api.morphs.utils.ISyncableMorph; import mchorse.metamorph.bodypart.BodyPart; import mchorse.metamorph.bodypart.IBodyPartProvider; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; @@ -105,8 +107,19 @@ public static boolean render(AbstractMorph morph, EntityLivingBase entity, doubl } catch (Exception e) { + e.printStackTrace(); morph.errorRendering = true; } + finally + { + try + { + Tessellator.getInstance().getBuffer().finishDrawing(); + System.err.println("Unfinished builder comes from class: " + morph.getClass().getName()); + } + catch (IllegalStateException ex) + {} + } return false; } @@ -130,8 +143,19 @@ public static boolean renderOnScreen(AbstractMorph morph, EntityPlayer player, i } catch (Exception e) { + e.printStackTrace(); morph.errorRendering = true; } + finally + { + try + { + Tessellator.getInstance().getBuffer().finishDrawing(); + System.err.println("Unfinished builder comes from class: " + morph.getClass().getName()); + } + catch (IllegalStateException ex) + {} + } return false; } From 53778eee0aea12311e5ce240563de3599e55c374 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Thu, 5 Aug 2021 13:07:57 +0800 Subject: [PATCH 09/51] Onionskin interfaces --- .../gui/creative/GuiCreativeMorphsList.java | 164 +++++++++++++++++- .../assets/metamorph/lang/en_US.lang | 1 + .../assets/metamorph/lang/zh_CN.lang | 1 + .../assets/metamorph/lang/zh_TW.lang | 1 + .../assets/metamorph/shaders/onionskin.frag | 11 ++ .../assets/metamorph/shaders/onionskin.vert | 14 ++ 6 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 src/main/resources/assets/metamorph/shaders/onionskin.frag create mode 100644 src/main/resources/assets/metamorph/shaders/onionskin.vert diff --git a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java index 3acf4a0b..6a2b0e3c 100644 --- a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java +++ b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java @@ -12,7 +12,10 @@ import mchorse.mclib.client.gui.utils.Area; import mchorse.mclib.client.gui.utils.Keybind; import mchorse.mclib.client.gui.utils.keys.IKey; +import mchorse.mclib.utils.Color; +import mchorse.mclib.utils.DummyEntity; import mchorse.mclib.utils.Timer; +import mchorse.mclib.utils.shaders.Shader; import mchorse.metamorph.api.MorphManager; import mchorse.metamorph.api.MorphUtils; import mchorse.metamorph.api.creative.categories.MorphCategory; @@ -21,15 +24,21 @@ import mchorse.metamorph.client.gui.editor.GuiAbstractMorph; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; import net.minecraft.nbt.NBTTagCompound; + +import org.apache.commons.io.IOUtils; import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL20; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.Stack; import java.util.function.Consumer; +import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; /** @@ -41,6 +50,9 @@ */ public class GuiCreativeMorphsList extends GuiElement { + public static Shader shader; + public static int skinColor = -1; + /** * Morph consumer */ @@ -64,6 +76,9 @@ public class GuiCreativeMorphsList extends GuiElement public GuiQuickEditor quickEditor; public GuiCreativeMorphs morphs; + public List onionSkins = new ArrayList(); + public List lastOnionSkins; + private Timer timer = new Timer(100); private Stack nestedEdits = new Stack(); @@ -76,6 +91,10 @@ public class GuiCreativeMorphsList extends GuiElement protected float lastPitch; protected float lastScale; + protected boolean doRenderOnionSkin; + + private DummyEntity entity; + /** * Initiate this GUI. * @@ -114,6 +133,30 @@ public GuiCreativeMorphsList(Minecraft mc, Consumer callback) this.screen.add(this.morphs, this.bar, this.quickEditor); this.add(this.screen, new GuiDrawable(this::drawOverlay), this.editor); + /* Onion skin */ + this.doRenderOnionSkin = true; + this.entity = new DummyEntity(mc.world); + + if (shader == null) + { + try + { + String vert = IOUtils.toString(this.getClass().getResourceAsStream("/assets/metamorph/shaders/onionskin.vert"), Charset.defaultCharset()); + String frag = IOUtils.toString(this.getClass().getResourceAsStream("/assets/metamorph/shaders/onionskin.frag"), Charset.defaultCharset()); + + shader = new Shader(); + shader.compile(vert, frag, true); + + GL20.glUniform1i(GL20.glGetUniformLocation(shader.programId, "texture"), 0); + + skinColor = GL20.glGetUniformLocation(shader.programId, "onionskin"); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + /* Morph editor keybinds */ IKey category = IKey.lang("metamorph.gui.creative.keys.category"); @@ -124,6 +167,8 @@ public GuiCreativeMorphsList(Minecraft mc, Consumer callback) this.morphs.keys().register(IKey.lang("metamorph.gui.creative.keys.edit"), Keyboard.KEY_E, this::enterEditMorph).category(category); this.morphs.keys().register(IKey.lang("metamorph.gui.creative.keys.quick"), Keyboard.KEY_Q, this::toggleQuickEdit).category(category); this.morphs.keys().register(IKey.lang("metamorph.gui.creative.keys.focus"), Keyboard.KEY_F, () -> GuiBase.getCurrent().focus(this.search, true)).held(Keyboard.KEY_LCONTROL).category(category); + + this.keys().register(IKey.lang("metamorph.gui.creative.keys.onionskin"), Keyboard.KEY_Q, () -> this.doRenderOnionSkin = !this.doRenderOnionSkin).active(() -> this.isEditMode() && this.haveOnionSkin()).category(category); } public void reload() @@ -236,15 +281,25 @@ public void nestEdit(AbstractMorph selected, boolean editing, Consumer callback) { - NestedEdit edit = new NestedEdit(this.morphs.filter, this.editor.delegate.morph, this.editor.delegate.toNBT(), this.callback, this.morphs.selected, editing, this.keepViewport); + NestedEdit edit = new NestedEdit(this.morphs.filter, this.editor.delegate.morph, this.editor.delegate.toNBT(), this.callback, this.morphs.selected, editing, this.keepViewport, this.lastOnionSkins); this.callback = callback; this.keepViewport = keepViewport; if (keepViewport) { this.saveViewport(); + + this.lastOnionSkins = this.lastOnionSkins == null ? new ArrayList() : new ArrayList(this.lastOnionSkins); + this.lastOnionSkins.addAll(this.onionSkins); + } + else + { + this.lastOnionSkins = null; } + this.nestedEdits.add(edit); + this.updateExitKey(); + if (editing) { this.enterEditMorph(selected); @@ -255,9 +310,6 @@ public void nestEdit(AbstractMorph selected, boolean editing, boolean keepViewpo this.morphs.setFilter(""); this.setSelected(selected); } - - this.nestedEdits.add(edit); - this.updateExitKey(); } public void restoreEdit() @@ -287,6 +339,7 @@ public void restoreEdit() } this.keepViewport = edit.keepViewport; + this.lastOnionSkins = edit.lastOnionSkins; } /* Edit mode */ @@ -323,6 +376,8 @@ public void enterEditMorph(AbstractMorph morph) this.disableDirty(); + this.onionSkins.clear(); + GuiAbstractMorph editor = this.getMorphEditor(morph); if (editor != null) @@ -333,6 +388,8 @@ public void enterEditMorph(AbstractMorph morph) { this.loadViewport(); } + + editor.renderer.afterRender = this::renderOnionSkin; } } @@ -343,6 +400,8 @@ public void exitEditMorph(boolean add, boolean ignore) return; } + this.editor.delegate.renderer.afterRender = null; + if (this.keepViewport) { this.saveViewport(); @@ -393,6 +452,7 @@ public void finish() } this.keepViewport = false; + this.lastOnionSkins = null; } private GuiAbstractMorph getMorphEditor(AbstractMorph morph) @@ -436,6 +496,59 @@ private void loadViewport() renderer.setScale(this.lastScale); } + /* Onion skin */ + + public boolean haveOnionSkin() + { + return !this.onionSkins.isEmpty() || this.lastOnionSkins != null && !this.lastOnionSkins.isEmpty(); + } + + private void renderOnionSkin(GuiContext context) + { + if (!this.doRenderOnionSkin) + { + return; + } + + this.entity.ticksExisted = this.editor.delegate.renderer.getEntity().ticksExisted; + + shader.bind(); + GuiModelRenderer.disableRenderingFlag(); + + if (this.lastOnionSkins != null) + { + for (OnionSkin skin : this.lastOnionSkins) + { + renderSingleOnionSkin(skin, context.partialTicks); + } + } + + for (OnionSkin skin : this.onionSkins) + { + renderSingleOnionSkin(skin, context.partialTicks); + } + + shader.unbind(); + } + + private void renderSingleOnionSkin(OnionSkin skin, float partialTicks) + { + if (skin.morph == null) + { + return; + } + + GL20.glUniform4f(skinColor, skin.color.r, skin.color.g, skin.color.b, skin.color.a); + + entity.prevRotationPitch = entity.rotationPitch = skin.pitch; + entity.prevRenderYawOffset = entity.renderYawOffset = skin.yawBody; + entity.prevRotationYawHead = entity.rotationYawHead = skin.yawHead; + + GlStateManager.pushMatrix(); + MorphUtils.render(skin.morph, entity, skin.offset.x, skin.offset.y, skin.offset.z, 0, partialTicks); + GlStateManager.popMatrix(); + } + /* Morph selection and filtering */ /** @@ -578,8 +691,9 @@ public static class NestedEdit public AbstractMorph editMorph; public boolean editing; public boolean keepViewport; + public List lastOnionSkins; - public NestedEdit(String filter, AbstractMorph editMorph, NBTTagCompound data, Consumer callback, GuiMorphSection selected, boolean editing, boolean keepViewport) + public NestedEdit(String filter, AbstractMorph editMorph, NBTTagCompound data, Consumer callback, GuiMorphSection selected, boolean editing, boolean keepViewport, List lastOnionSkins) { this.filter = filter; this.data = data; @@ -587,10 +701,50 @@ public NestedEdit(String filter, AbstractMorph editMorph, NBTTagCompound data, C this.callback = callback; this.editing = editing; this.keepViewport = keepViewport; + this.lastOnionSkins = lastOnionSkins; this.selected = selected; this.selectedCategory = selected == null ? null : selected.category; this.selectedMorph = selected == null ? null : selected.morph; } } + + /** + * Onion skin data + */ + public static class OnionSkin + { + public Color color = new Color(); + + public AbstractMorph morph; + + public Vector3d offset = new Vector3d(0, 0, 0); + + public float pitch = 0f; + + public float yawHead = 0f; + + public float yawBody = 0f; + + public OnionSkin color(float r, float g, float b, float a) + { + this.color.set(r, g, b, a); + return this; + } + + public OnionSkin morph(AbstractMorph morph) + { + this.morph = morph; + return this; + } + + public OnionSkin offset(double x, double y, double z, float pitch, float yawHead, float yawBody) + { + this.offset.set(x, y, z); + this.pitch = pitch; + this.yawHead = yawHead; + this.yawBody = yawBody; + return this; + } + } } \ No newline at end of file diff --git a/src/main/resources/assets/metamorph/lang/en_US.lang b/src/main/resources/assets/metamorph/lang/en_US.lang index ad3959f7..81cf63c8 100644 --- a/src/main/resources/assets/metamorph/lang/en_US.lang +++ b/src/main/resources/assets/metamorph/lang/en_US.lang @@ -111,6 +111,7 @@ metamorph.gui.editor.texture=Pick a texture... metamorph.gui.editor.texture_tooltip=This feature won't work for all mobs, because some mobs can have custom rendering implementation metamorph.gui.editor.keys.category=Morph editor keybinds metamorph.gui.editor.keys.cycle=Cycle between morph panels +metamorph.gui.creative.keys.onionskin=Toggle onion skins metamorph.gui.editor.shadow.all=Render all metamorph.gui.editor.shadow.noshadow=No shadow metamorph.gui.editor.shadow.onlyshadow=Only shaodws diff --git a/src/main/resources/assets/metamorph/lang/zh_CN.lang b/src/main/resources/assets/metamorph/lang/zh_CN.lang index 789d0296..bf1a392c 100644 --- a/src/main/resources/assets/metamorph/lang/zh_CN.lang +++ b/src/main/resources/assets/metamorph/lang/zh_CN.lang @@ -111,6 +111,7 @@ metamorph.gui.editor.texture=选取材质贴图... metamorph.gui.editor.texture_tooltip=该功能不一定适用于所有生物,因为部分生物拥有非常规的渲染实现。 metamorph.gui.editor.keys.category=伪装编辑器快捷键 metamorph.gui.editor.keys.cycle=在伪装面板间循环切换 +metamorph.gui.creative.keys.onionskin=切换洋葱皮开关 metamorph.gui.editor.shadow.all=渲染全部 metamorph.gui.editor.shadow.noshadow=不渲染阴影 metamorph.gui.editor.shadow.onlyshadow=只渲染阴影 diff --git a/src/main/resources/assets/metamorph/lang/zh_TW.lang b/src/main/resources/assets/metamorph/lang/zh_TW.lang index 45342808..f63694d5 100644 --- a/src/main/resources/assets/metamorph/lang/zh_TW.lang +++ b/src/main/resources/assets/metamorph/lang/zh_TW.lang @@ -111,6 +111,7 @@ metamorph.gui.editor.texture=選取材質貼圖... metamorph.gui.editor.texture_tooltip=該功能不一定適用於所有生物,因為部分生物擁有非常規的渲染實現。 metamorph.gui.editor.keys.category=偽裝編輯器快捷鍵 metamorph.gui.editor.keys.cycle=在偽裝面板間循環切換 +metamorph.gui.creative.keys.onionskin=切換洋葱皮開關 metamorph.gui.editor.shadow.all=渲染全部 metamorph.gui.editor.shadow.noshadow=不渲染陰影 metamorph.gui.editor.shadow.onlyshadow=只渲染陰影 diff --git a/src/main/resources/assets/metamorph/shaders/onionskin.frag b/src/main/resources/assets/metamorph/shaders/onionskin.frag new file mode 100644 index 00000000..8e51ff89 --- /dev/null +++ b/src/main/resources/assets/metamorph/shaders/onionskin.frag @@ -0,0 +1,11 @@ +#version 120 + +uniform sampler2D texture; + +varying vec4 color; +varying vec4 texcoord; + +void main() +{ + gl_FragColor = texture2D(texture, texcoord.st) * color; +} \ No newline at end of file diff --git a/src/main/resources/assets/metamorph/shaders/onionskin.vert b/src/main/resources/assets/metamorph/shaders/onionskin.vert new file mode 100644 index 00000000..aafb4cbd --- /dev/null +++ b/src/main/resources/assets/metamorph/shaders/onionskin.vert @@ -0,0 +1,14 @@ +#version 120 + +uniform vec4 onionskin; + +varying vec4 color; +varying vec4 texcoord; + +void main() +{ + gl_Position = ftransform(); + + color = gl_Color * onionskin; + texcoord = gl_TextureMatrix[0] * gl_MultiTexCoord0; +} \ No newline at end of file From 16d2c96541a8d05c404a8897ee375f2626ecb691 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sun, 8 Aug 2021 05:08:02 +0800 Subject: [PATCH 10/51] UTF-8 --- .../metamorph/api/creative/sections/UserSection.java | 6 +++--- .../java/mchorse/metamorph/client/EntityModelHandler.java | 6 +++--- .../client/gui/creative/GuiCreativeMorphsList.java | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/mchorse/metamorph/api/creative/sections/UserSection.java b/src/main/java/mchorse/metamorph/api/creative/sections/UserSection.java index 516110ce..6fe20ae1 100644 --- a/src/main/java/mchorse/metamorph/api/creative/sections/UserSection.java +++ b/src/main/java/mchorse/metamorph/api/creative/sections/UserSection.java @@ -25,7 +25,7 @@ import org.apache.commons.io.FileUtils; import java.io.File; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -137,7 +137,7 @@ public void load() try { List categories = new ArrayList(); - String content = FileUtils.readFileToString(file, Charset.defaultCharset()); + String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8); JsonArray object = new JsonParser().parse(content).getAsJsonArray(); int i = 0; @@ -220,7 +220,7 @@ public void save() try { - FileUtils.writeStringToFile(Metamorph.proxy.list, JsonUtils.jsonToPretty(array), Charset.defaultCharset()); + FileUtils.writeStringToFile(Metamorph.proxy.list, JsonUtils.jsonToPretty(array), StandardCharsets.UTF_8); } catch (Exception e) { diff --git a/src/main/java/mchorse/metamorph/client/EntityModelHandler.java b/src/main/java/mchorse/metamorph/client/EntityModelHandler.java index 65c9720c..1621852a 100644 --- a/src/main/java/mchorse/metamorph/client/EntityModelHandler.java +++ b/src/main/java/mchorse/metamorph/client/EntityModelHandler.java @@ -24,7 +24,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Type; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -98,7 +98,7 @@ public void loadSelectors() try { Type token = (new TypeToken>() {}).getType(); - List selectors = this.entitySelector.fromJson(FileUtils.readFileToString(selectorsFile, Charset.defaultCharset()), token); + List selectors = this.entitySelector.fromJson(FileUtils.readFileToString(selectorsFile, StandardCharsets.UTF_8), token); EntityModelHandler.selectors.clear(); EntityModelHandler.selectors.addAll(selectors); @@ -116,7 +116,7 @@ public void saveSelectors() { JsonElement element = this.entitySelector.toJsonTree(selectors); - FileUtils.writeStringToFile(Metamorph.proxy.selectors, JsonUtils.jsonToPretty(element), Charset.defaultCharset()); + FileUtils.writeStringToFile(Metamorph.proxy.selectors, JsonUtils.jsonToPretty(element), StandardCharsets.UTF_8); } catch (IOException e) { diff --git a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java index 6a2b0e3c..b75d10a9 100644 --- a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java +++ b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java @@ -32,7 +32,7 @@ import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL20; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Stack; @@ -141,8 +141,8 @@ public GuiCreativeMorphsList(Minecraft mc, Consumer callback) { try { - String vert = IOUtils.toString(this.getClass().getResourceAsStream("/assets/metamorph/shaders/onionskin.vert"), Charset.defaultCharset()); - String frag = IOUtils.toString(this.getClass().getResourceAsStream("/assets/metamorph/shaders/onionskin.frag"), Charset.defaultCharset()); + String vert = IOUtils.toString(this.getClass().getResourceAsStream("/assets/metamorph/shaders/onionskin.vert"), StandardCharsets.UTF_8); + String frag = IOUtils.toString(this.getClass().getResourceAsStream("/assets/metamorph/shaders/onionskin.frag"), StandardCharsets.UTF_8); shader = new Shader(); shader.compile(vert, frag, true); From de84b7f16d8e7f8df708bb11e22e9158284e5e3c Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sun, 8 Aug 2021 06:26:03 +0800 Subject: [PATCH 11/51] Fix crash when player is in specator mode --- .../mchorse/metamorph/api/MorphUtils.java | 15 ++++++++++- .../mchorse/metamorph/bodypart/BodyPart.java | 26 ++++++++++++++++--- .../metamorph/bodypart/GuiBodyPartEditor.java | 3 ++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/main/java/mchorse/metamorph/api/MorphUtils.java b/src/main/java/mchorse/metamorph/api/MorphUtils.java index 1631e370..4d66e97f 100644 --- a/src/main/java/mchorse/metamorph/api/MorphUtils.java +++ b/src/main/java/mchorse/metamorph/api/MorphUtils.java @@ -8,6 +8,7 @@ import java.util.Set; import io.netty.buffer.ByteBuf; +import mchorse.mclib.client.gui.framework.elements.GuiModelRenderer; import mchorse.mclib.utils.NBTUtils; import mchorse.mclib.utils.ReflectionUtils; import mchorse.metamorph.api.events.RegisterBlacklistEvent; @@ -94,7 +95,19 @@ public static boolean render(AbstractMorph morph, EntityLivingBase entity, doubl boolean isShadowPass = ReflectionUtils.isOptifineShadowPass(); - if (isShadowPass && morph.settings.shadowOption == 1 || !isShadowPass && morph.settings.shadowOption == 2) + if (!GuiModelRenderer.isRendering() && (isShadowPass && morph.settings.shadowOption == 1 || !isShadowPass && morph.settings.shadowOption == 2)) + { + return false; + } + + return renderDirect(morph, entity, x, y, z, yaw, partialTick); + } + + /* Without shadow pass check */ + @SideOnly(Side.CLIENT) + public static boolean renderDirect(AbstractMorph morph, EntityLivingBase entity, double x, double y, double z, float yaw, float partialTick) + { + if (morph == null || morph.errorRendering) { return false; } diff --git a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java index 05f54dc8..044c354e 100644 --- a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java +++ b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java @@ -483,7 +483,7 @@ public void toNBT(NBTTagCompound tag) } @SideOnly(Side.CLIENT) - public void setLimb(AbstractMorph parent, String limb, boolean convertTransform) + public void setLimb(AbstractMorph parent, String limb, boolean convertTransform, EntityLivingBase entity, float partialTicks) { if (this.limb.equals(limb)) { @@ -497,16 +497,25 @@ public void setLimb(AbstractMorph parent, String limb, boolean convertTransform) } recording = true; - EntityPlayer player = Minecraft.getMinecraft().player; int lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE); GL11.glMatrixMode(GL11.GL_MODELVIEW); + this.lastMatrix = null; GL11.glPushMatrix(); GL11.glLoadIdentity(); - MorphUtils.render(parent, player, 0, 0, 0, 0, 0); + MorphUtils.renderDirect(parent, entity, 0, 0, 0, 0, partialTicks); GL11.glPopMatrix(); Matrix4f last = this.lastMatrix; + + if (last == null) + { + GL11.glMatrixMode(lastMatrixMode); + recording = false; + + return; + } + Matrix4f transform = new Matrix4f(); transform.setIdentity(); transform.setTranslation(this.translate); @@ -525,12 +534,21 @@ public void setLimb(AbstractMorph parent, String limb, boolean convertTransform) this.limb = limb; + this.lastMatrix = null; GL11.glPushMatrix(); GL11.glLoadIdentity(); - MorphUtils.render(parent, player, 0, 0, 0, 0, 0); + MorphUtils.renderDirect(parent, entity, 0, 0, 0, 0, partialTicks); GL11.glPopMatrix(); Matrix4f current = this.lastMatrix; + if (current == null) + { + GL11.glMatrixMode(lastMatrixMode); + recording = false; + + return; + } + Transformation extract = MatrixUtils.extractTransformations(current, last); if (extract.getCreationException() == null) diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index cef606e3..0091f110 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -1,5 +1,6 @@ package mchorse.metamorph.bodypart; +import mchorse.mclib.client.gui.framework.GuiBase; import mchorse.mclib.client.gui.framework.elements.GuiElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiIconElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiSlotElement; @@ -390,7 +391,7 @@ protected void setPart(BodyPart part) protected void pickLimb(String str) { - this.part.setLimb(this.morph, str, GuiScreen.isAltKeyDown()); + this.part.setLimb(this.morph, str, GuiScreen.isAltKeyDown(), this.editor.renderer.getEntity(), GuiBase.getCurrent().partialTicks); this.fillBodyPart(this.part); } From db2a76beba9a52a15943794c8ed33c89cad7e390 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Mon, 9 Aug 2021 00:15:45 +0800 Subject: [PATCH 12/51] resize GuiTransformations --- src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index 0091f110..26a9222a 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -121,7 +121,7 @@ public GuiBodyPartEditor(Minecraft mc, GuiAbstractMorph editor) this.bottomEditor.flex().column(5).vertical().stretch(); this.bottomEditor.add(this.enabled, this.animate, this.useTarget); - this.transformations.flex().relative(this.area).x(0.5F, -95).y(1, -10).wh(190, 70).anchorY(1F); + this.transformations.flex().relative(this.area).x(0.5F, -128).y(1, -10).wh(256, 70).anchorY(1F); this.limbs.flex().relative(this).set(0, 50, width, 90).x(1, -115).hTo(this.bottomEditor.area, -5); this.pickMorph.flex().relative(this).set(0, 10, width, 20).x(1, -115); this.bodyParts.flex().relative(this).set(10, 22, width, 0).hTo(this.transformations.flex(), 1F, -20); From fc6deb2d8a44f68b6c247376af665c4f0b853ff3 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Thu, 12 Aug 2021 18:15:37 +0800 Subject: [PATCH 13/51] Show onion skin of parent morph when editing a bodypart --- .../mchorse/metamorph/bodypart/BodyPart.java | 106 ++------- .../metamorph/bodypart/GuiBodyPartEditor.java | 202 +++++++++++++++++- 2 files changed, 217 insertions(+), 91 deletions(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java index 044c354e..cff1f1bb 100644 --- a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java +++ b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java @@ -13,8 +13,6 @@ import mchorse.mclib.utils.DummyEntity; import mchorse.mclib.utils.Interpolation; import mchorse.mclib.utils.MatrixUtils; -import mchorse.mclib.utils.MatrixUtils.Transformation; -import mchorse.mclib.utils.MatrixUtils.Transformation.RotationOrder; import mchorse.mclib.utils.NBTUtils; import mchorse.metamorph.Metamorph; import mchorse.metamorph.api.Morph; @@ -27,7 +25,6 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -45,6 +42,24 @@ public class BodyPart public static Matrix4f modelViewMatrix = new Matrix4f(); public static boolean recording = false; + @SideOnly(Side.CLIENT) + public static void recordMatrix(AbstractMorph parent, EntityLivingBase entity, float partialTicks) + { + recording = true; + + int lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE); + GL11.glMatrixMode(GL11.GL_MODELVIEW); + + GL11.glPushMatrix(); + GL11.glLoadIdentity(); + MorphUtils.renderDirect(parent, entity, 0, 0, 0, 0, partialTicks); + GL11.glPopMatrix(); + + GL11.glMatrixMode(lastMatrixMode); + + recording = false; + } + public Morph morph = new Morph(); public ItemStack[] slots = new ItemStack[] {ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY}; public Vector3f translate = new Vector3f(); @@ -481,89 +496,4 @@ public void toNBT(NBTTagCompound tag) if (!this.animate) tag.setBoolean("Animate", this.animate); if (!this.limb.isEmpty()) tag.setString("Limb", this.limb); } - - @SideOnly(Side.CLIENT) - public void setLimb(AbstractMorph parent, String limb, boolean convertTransform, EntityLivingBase entity, float partialTicks) - { - if (this.limb.equals(limb)) - { - return; - } - - if (this.limb.isEmpty() || !convertTransform) - { - this.limb = limb; - return; - } - - recording = true; - - int lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE); - GL11.glMatrixMode(GL11.GL_MODELVIEW); - - this.lastMatrix = null; - GL11.glPushMatrix(); - GL11.glLoadIdentity(); - MorphUtils.renderDirect(parent, entity, 0, 0, 0, 0, partialTicks); - GL11.glPopMatrix(); - Matrix4f last = this.lastMatrix; - - if (last == null) - { - GL11.glMatrixMode(lastMatrixMode); - recording = false; - - return; - } - - Matrix4f transform = new Matrix4f(); - transform.setIdentity(); - transform.setTranslation(this.translate); - last.mul(transform); - transform.rotZ((float) Math.toRadians(this.rotate.z)); - last.mul(transform); - transform.rotY((float) Math.toRadians(this.rotate.y)); - last.mul(transform); - transform.rotX((float) Math.toRadians(this.rotate.x)); - last.mul(transform); - transform.setIdentity(); - transform.m00 = this.scale.x; - transform.m11 = this.scale.y; - transform.m22 = this.scale.z; - last.mul(transform); - - this.limb = limb; - - this.lastMatrix = null; - GL11.glPushMatrix(); - GL11.glLoadIdentity(); - MorphUtils.renderDirect(parent, entity, 0, 0, 0, 0, partialTicks); - GL11.glPopMatrix(); - Matrix4f current = this.lastMatrix; - - if (current == null) - { - GL11.glMatrixMode(lastMatrixMode); - recording = false; - - return; - } - - Transformation extract = MatrixUtils.extractTransformations(current, last); - - if (extract.getCreationException() == null) - { - Vector3f rotate = extract.getRotation(RotationOrder.XYZ); - if (rotate != null) - { - this.translate.set(extract.getTranslation3f()); - this.rotate.set(rotate); - this.scale.set(extract.getScale()); - } - } - - GL11.glMatrixMode(lastMatrixMode); - - recording = false; - } } \ No newline at end of file diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index 26a9222a..d4e21381 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -14,15 +14,23 @@ import mchorse.mclib.client.gui.utils.keys.IKey; import mchorse.mclib.utils.Direction; import mchorse.mclib.utils.MathUtils; +import mchorse.mclib.utils.MatrixUtils; +import mchorse.mclib.utils.MatrixUtils.Transformation; +import mchorse.mclib.utils.MatrixUtils.Transformation.RotationOrder; import mchorse.metamorph.api.MorphUtils; import mchorse.metamorph.api.morphs.AbstractMorph; import mchorse.metamorph.api.morphs.utils.IAnimationProvider; +import mchorse.metamorph.client.gui.creative.GuiCreativeMorphsList; +import mchorse.metamorph.client.gui.creative.GuiCreativeMorphsList.OnionSkin; import mchorse.metamorph.client.gui.creative.GuiNestedEdit; import mchorse.metamorph.client.gui.editor.GuiAbstractMorph; import mchorse.metamorph.client.gui.editor.GuiMorphPanel; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.JsonToNBT; import net.minecraft.nbt.NBTTagCompound; @@ -34,6 +42,11 @@ import java.util.Collection; import java.util.List; +import javax.vecmath.Matrix4f; +import javax.vecmath.Vector3f; + +import com.google.common.collect.ImmutableList; + @SideOnly(Side.CLIENT) public class GuiBodyPartEditor extends GuiMorphPanel { @@ -77,8 +90,9 @@ public GuiBodyPartEditor(Minecraft mc, GuiAbstractMorph editor) this.pickMorph = new GuiNestedEdit(mc, (editing) -> { BodyPart part = this.part; + GuiCreativeMorphsList morphs = this.editor.morphs; - this.editor.morphs.nestEdit(part.morph.get(), editing, (morph) -> + morphs.nestEdit(part.morph.get(), editing, (morph) -> { if (part != null) { @@ -88,6 +102,72 @@ public GuiBodyPartEditor(Minecraft mc, GuiAbstractMorph editor) this.applyUseTarget(part, copy); } }); + + EntityLivingBase entity = this.editor.renderer.getEntity(); + + entity.prevRotationPitch = entity.rotationPitch = 0; + entity.prevRotationYawHead = entity.rotationYawHead = 0; + entity.prevRenderYawOffset = entity.renderYawOffset = 0; + + part.lastMatrix = null; + BodyPart.recordMatrix(morph, entity, 0F); + Matrix4f last = part.lastMatrix; + + if (last != null) + { + Matrix4f transform = new Matrix4f(); + + transform.setIdentity(); + transform.setTranslation(part.translate); + last.mul(transform); + transform.rotZ((float) Math.toRadians(part.rotate.z)); + last.mul(transform); + transform.rotY((float) Math.toRadians(part.rotate.y)); + last.mul(transform); + transform.rotX((float) Math.toRadians(part.rotate.x)); + last.mul(transform); + transform.setIdentity(); + transform.m00 = part.scale.x; + transform.m11 = part.scale.y; + transform.m22 = part.scale.z; + last.mul(transform); + + transform.setIdentity(); + Transformation extract = MatrixUtils.extractTransformations(last, transform); + + if (extract.getCreationException() == null) + { + Vector3f rotate = extract.getRotation(RotationOrder.XYZ); + + if (rotate != null) + { + TransformedOnionSkinMorph morph = new TransformedOnionSkinMorph(); + + Vector3f vec = extract.getTranslation3f(); + morph.translate[0] = vec.x; + morph.translate[1] = vec.y; + morph.translate[2] = vec.z; + + vec = rotate; + morph.rotate[0] = vec.x; + morph.rotate[1] = vec.y; + morph.rotate[2] = vec.z; + + vec = extract.getScale(); + morph.scale[0] = vec.x; + morph.scale[1] = vec.y; + morph.scale[2] = vec.z; + + boolean enabled = part.enabled; + part.enabled = false; + morph.morph = this.morph.copy(); + part.enabled = enabled; + + OnionSkin skin = new OnionSkin().morph(morph).color(1F, 1F, 1F, 1F); + morphs.lastOnionSkins = ImmutableList.of(skin); + } + } + } }); this.add = new GuiIconElement(mc, Icons.ADD, this::addPart); @@ -391,8 +471,72 @@ protected void setPart(BodyPart part) protected void pickLimb(String str) { - this.part.setLimb(this.morph, str, GuiScreen.isAltKeyDown(), this.editor.renderer.getEntity(), GuiBase.getCurrent().partialTicks); - this.fillBodyPart(this.part); + BodyPart part = this.part; + boolean convert = GuiScreen.isAltKeyDown(); + + if (part.limb.equals(str)) + { + return; + } + + if (part.limb.isEmpty() || !convert) + { + part.limb = str; + return; + } + + part.lastMatrix = null; + BodyPart.recordMatrix(this.morph, this.editor.renderer.getEntity(), GuiBase.getCurrent().partialTicks); + Matrix4f last = part.lastMatrix; + + if (last == null) + { + part.limb = str; + return; + } + + Matrix4f transform = new Matrix4f(); + transform.setIdentity(); + transform.setTranslation(part.translate); + last.mul(transform); + transform.rotZ((float) Math.toRadians(part.rotate.z)); + last.mul(transform); + transform.rotY((float) Math.toRadians(part.rotate.y)); + last.mul(transform); + transform.rotX((float) Math.toRadians(part.rotate.x)); + last.mul(transform); + transform.setIdentity(); + transform.m00 = part.scale.x; + transform.m11 = part.scale.y; + transform.m22 = part.scale.z; + last.mul(transform); + + part.limb = str; + + part.lastMatrix = null; + BodyPart.recordMatrix(this.morph, this.editor.renderer.getEntity(), GuiBase.getCurrent().partialTicks); + Matrix4f current = part.lastMatrix; + + if (current == null) + { + return; + } + + Transformation extract = MatrixUtils.extractTransformations(current, last); + + if (extract.getCreationException() == null) + { + Vector3f rotate = extract.getRotation(RotationOrder.XYZ); + + if (rotate != null) + { + part.translate.set(extract.getTranslation3f()); + part.rotate.set(rotate); + part.scale.set(extract.getScale()); + } + } + + this.fillBodyPart(part); } public void fillBodyPart(BodyPart part) @@ -545,4 +689,56 @@ public void setR(double x, double y, double z) this.part.rotate.z = (float) z; } } + + public static class TransformedOnionSkinMorph extends AbstractMorph + { + public float[] translate = new float[3]; + public float[] rotate = new float[3]; + public float[] scale = new float[3]; + public AbstractMorph morph = null; + + @Override + public void renderOnScreen(EntityPlayer player, int x, int y, float scale, float alpha) + {} + + @Override + public void render(EntityLivingBase entity, double x, double y, double z, float entityYaw, float partialTicks) + { + if (this.morph == null) + { + return; + } + + GlStateManager.pushMatrix(); + + GlStateManager.translate(this.translate[0], this.translate[1], this.translate[2]); + GlStateManager.rotate(this.rotate[2], 0, 0, 1); + GlStateManager.rotate(this.rotate[1], 0, 1, 0); + GlStateManager.rotate(this.rotate[0], 1, 0, 0); + GlStateManager.scale(this.scale[0], this.scale[1], this.scale[2]); + + MorphUtils.renderDirect(morph, entity, x, y, z, entityYaw, partialTicks); + + GlStateManager.popMatrix(); + } + + @Override + public AbstractMorph create() + { + return null; + } + + @Override + public float getWidth(EntityLivingBase target) + { + return 0; + } + + @Override + public float getHeight(EntityLivingBase target) + { + return 0; + } + + } } \ No newline at end of file From 0d9903069880788ef2420f1c4e63f1d2ad099d41 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sat, 14 Aug 2021 18:49:12 +0800 Subject: [PATCH 14/51] Onion skin optimization --- .../metamorph/bodypart/GuiBodyPartEditor.java | 136 ++++++++++-------- .../gui/creative/GuiCreativeMorphsList.java | 12 +- 2 files changed, 84 insertions(+), 64 deletions(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index d4e21381..2dfab881 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -91,6 +91,7 @@ public GuiBodyPartEditor(Minecraft mc, GuiAbstractMorph editor) { BodyPart part = this.part; GuiCreativeMorphsList morphs = this.editor.morphs; + OnionSkin skin = this.generateOnionSkin(part); morphs.nestEdit(part.morph.get(), editing, (morph) -> { @@ -103,70 +104,9 @@ public GuiBodyPartEditor(Minecraft mc, GuiAbstractMorph editor) } }); - EntityLivingBase entity = this.editor.renderer.getEntity(); - - entity.prevRotationPitch = entity.rotationPitch = 0; - entity.prevRotationYawHead = entity.rotationYawHead = 0; - entity.prevRenderYawOffset = entity.renderYawOffset = 0; - - part.lastMatrix = null; - BodyPart.recordMatrix(morph, entity, 0F); - Matrix4f last = part.lastMatrix; - - if (last != null) + if (skin != null) { - Matrix4f transform = new Matrix4f(); - - transform.setIdentity(); - transform.setTranslation(part.translate); - last.mul(transform); - transform.rotZ((float) Math.toRadians(part.rotate.z)); - last.mul(transform); - transform.rotY((float) Math.toRadians(part.rotate.y)); - last.mul(transform); - transform.rotX((float) Math.toRadians(part.rotate.x)); - last.mul(transform); - transform.setIdentity(); - transform.m00 = part.scale.x; - transform.m11 = part.scale.y; - transform.m22 = part.scale.z; - last.mul(transform); - - transform.setIdentity(); - Transformation extract = MatrixUtils.extractTransformations(last, transform); - - if (extract.getCreationException() == null) - { - Vector3f rotate = extract.getRotation(RotationOrder.XYZ); - - if (rotate != null) - { - TransformedOnionSkinMorph morph = new TransformedOnionSkinMorph(); - - Vector3f vec = extract.getTranslation3f(); - morph.translate[0] = vec.x; - morph.translate[1] = vec.y; - morph.translate[2] = vec.z; - - vec = rotate; - morph.rotate[0] = vec.x; - morph.rotate[1] = vec.y; - morph.rotate[2] = vec.z; - - vec = extract.getScale(); - morph.scale[0] = vec.x; - morph.scale[1] = vec.y; - morph.scale[2] = vec.z; - - boolean enabled = part.enabled; - part.enabled = false; - morph.morph = this.morph.copy(); - part.enabled = enabled; - - OnionSkin skin = new OnionSkin().morph(morph).color(1F, 1F, 1F, 1F); - morphs.lastOnionSkins = ImmutableList.of(skin); - } - } + morphs.lastOnionSkins = ImmutableList.of(skin); } }); @@ -279,6 +219,76 @@ private GuiContextMenu bodyPartContextMenu() return menu.actions.getList().isEmpty() ? null : menu; } + private OnionSkin generateOnionSkin(BodyPart part) + { + EntityLivingBase entity = this.editor.renderer.getEntity(); + + entity.prevRotationPitch = entity.rotationPitch = 0; + entity.prevRotationYawHead = entity.rotationYawHead = 0; + entity.prevRenderYawOffset = entity.renderYawOffset = 0; + + part.lastMatrix = null; + BodyPart.recordMatrix(this.morph, entity, 0F); + Matrix4f last = part.lastMatrix; + + if (last != null) + { + Matrix4f transform = new Matrix4f(); + + transform.setIdentity(); + transform.setTranslation(part.translate); + last.mul(transform); + transform.rotZ((float) Math.toRadians(part.rotate.z)); + last.mul(transform); + transform.rotY((float) Math.toRadians(part.rotate.y)); + last.mul(transform); + transform.rotX((float) Math.toRadians(part.rotate.x)); + last.mul(transform); + transform.setIdentity(); + transform.m00 = part.scale.x; + transform.m11 = part.scale.y; + transform.m22 = part.scale.z; + last.mul(transform); + + transform.setIdentity(); + Transformation extract = MatrixUtils.extractTransformations(last, transform); + + if (extract.getCreationException() == null) + { + Vector3f rotate = extract.getRotation(RotationOrder.XYZ); + + if (rotate != null) + { + TransformedOnionSkinMorph morph = new TransformedOnionSkinMorph(); + + Vector3f vec = extract.getTranslation3f(); + morph.translate[0] = vec.x; + morph.translate[1] = vec.y; + morph.translate[2] = vec.z; + + vec = rotate; + morph.rotate[0] = vec.x; + morph.rotate[1] = vec.y; + morph.rotate[2] = vec.z; + + vec = extract.getScale(); + morph.scale[0] = vec.x; + morph.scale[1] = vec.y; + morph.scale[2] = vec.z; + + boolean enabled = part.enabled; + part.enabled = false; + morph.morph = this.morph.copy(); + part.enabled = enabled; + + return new OnionSkin().morph(morph).color(0.5F, 0.5F, 0.5F, 0.5F); + } + } + } + + return null; + } + protected void addPart(GuiIconElement b) { BodyPart part = new BodyPart(); diff --git a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java index b75d10a9..b5272cea 100644 --- a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java +++ b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java @@ -389,7 +389,8 @@ public void enterEditMorph(AbstractMorph morph) this.loadViewport(); } - editor.renderer.afterRender = this::renderOnionSkin; + editor.renderer.beforeRender = this::beforeRenderModel; + editor.renderer.afterRender = this::afterRenderModel; } } @@ -400,6 +401,7 @@ public void exitEditMorph(boolean add, boolean ignore) return; } + this.editor.delegate.renderer.beforeRender = null; this.editor.delegate.renderer.afterRender = null; if (this.keepViewport) @@ -496,6 +498,14 @@ private void loadViewport() renderer.setScale(this.lastScale); } + protected void beforeRenderModel(GuiContext context) + {} + + protected void afterRenderModel(GuiContext context) + { + this.renderOnionSkin(context); + } + /* Onion skin */ public boolean haveOnionSkin() From 2afe4c9b53ad21e65f57bd8cff6c2bd1674d7246 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Sat, 21 Aug 2021 08:38:46 +0800 Subject: [PATCH 15/51] Fix bug that the shadow option may modify default morph settings --- .../metamorph/client/gui/editor/GuiSettingsPanel.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java b/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java index 12ef2295..8cf56493 100644 --- a/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java +++ b/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java @@ -156,7 +156,11 @@ public GuiSettingsPanel(Minecraft mc, GuiAbstractMorph editor) this.right.add(Elements.label(IKey.lang("metamorph.gui.editor.hitbox.size")).marginTop(8), this.hitboxWidth, this.hitboxHeight, this.hitboxSneakingHeight); this.right.add(Elements.label(IKey.lang("metamorph.gui.editor.hitbox.eye")).marginTop(8), this.hitboxEyePosition); - this.shadowOption = new GuiCirculateElement(mc, (element) -> this.morph.settings.shadowOption = element.getValue()); + this.shadowOption = new GuiCirculateElement(mc, (element) -> + { + this.ensureCustomSettings(); + this.morph.settings.shadowOption = element.getValue(); + }); for (OptifineShadowOption option : OptifineShadowOption.values()) { this.shadowOption.addLabel(IKey.lang("metamorph.gui.editor.shadow." + option.name().toLowerCase())); From b17a3fa5839ef0d70da9fcbb398940c569e6b5ab Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Thu, 26 Aug 2021 01:21:13 +0800 Subject: [PATCH 16/51] Fix the compatibility of bodypart onion skin with emoticons --- .../metamorph/bodypart/GuiBodyPartEditor.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index 2dfab881..fcc41b43 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -277,8 +277,18 @@ private OnionSkin generateOnionSkin(BodyPart part) morph.scale[2] = vec.z; boolean enabled = part.enabled; + part.enabled = false; - morph.morph = this.morph.copy(); + + AbstractMorph copy = this.morph.copy(); + + if (copy instanceof IAnimationProvider) + { + ((IAnimationProvider) copy).getAnimation().animates = false; + } + + morph.morph = copy; + part.enabled = enabled; return new OnionSkin().morph(morph).color(0.5F, 0.5F, 0.5F, 0.5F); From 531788283890bf792011f21a57cc2adca992c768 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Fri, 29 Oct 2021 23:11:41 +0800 Subject: [PATCH 17/51] Add isRenderingOnScreen flag --- src/main/java/mchorse/metamorph/api/MorphUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/mchorse/metamorph/api/MorphUtils.java b/src/main/java/mchorse/metamorph/api/MorphUtils.java index 4d66e97f..87d7ccd3 100644 --- a/src/main/java/mchorse/metamorph/api/MorphUtils.java +++ b/src/main/java/mchorse/metamorph/api/MorphUtils.java @@ -30,6 +30,8 @@ public class MorphUtils { + public static boolean isRenderingOnScreen = false; + /** * Generate an empty file */ @@ -150,6 +152,7 @@ public static boolean renderOnScreen(AbstractMorph morph, EntityPlayer player, i try { + isRenderingOnScreen = true; morph.renderOnScreen(player, x, y, scale, alpha); return true; @@ -161,6 +164,7 @@ public static boolean renderOnScreen(AbstractMorph morph, EntityPlayer player, i } finally { + isRenderingOnScreen = false; try { Tessellator.getInstance().getBuffer().finishDrawing(); From 3a61bf865430be71c3e448a21f6018da114f4416 Mon Sep 17 00:00:00 2001 From: NyaNLI Date: Thu, 4 Nov 2021 19:57:15 +0800 Subject: [PATCH 18/51] Try to compatible with CEM of Optifine --- src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java index d05b5eaa..8c1a4c67 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java @@ -354,11 +354,11 @@ public void render(EntityLivingBase entity, double x, double y, double z, float { GlStateManager.rotate(180, 0.0F, 1.0F, 0.0F); - render.doRender(this.entity, 0, 0, 0, entityYaw, partialTicks); + Minecraft.getMinecraft().getRenderManager().renderEntity(this.entity, 0, 0, 0, entityYaw, partialTicks, false); } else { - render.doRender(this.entity, 0, 0, 0, entityYaw, partialTicks); + Minecraft.getMinecraft().getRenderManager().renderEntity(this.entity, 0, 0, 0, entityYaw, partialTicks, false); } GlStateManager.popMatrix(); From 8844b6cdc6bf250e06123baae87a22a1d26b82c6 Mon Sep 17 00:00:00 2001 From: MiaoNLI Date: Mon, 28 Feb 2022 01:25:44 +0800 Subject: [PATCH 19/51] Set the speed of morph on the server side only --- src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java index 650105da..534a2059 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java @@ -158,7 +158,7 @@ public void update(EntityLivingBase target) { this.updateHitbox(target); - if (this.settings.speed != 0.1F) + if (target.isServerWorld()) { target.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(this.settings.speed); } From 87b1b19116137c92b84d56a9888097dbd49207aa Mon Sep 17 00:00:00 2001 From: MiaoNLI Date: Tue, 5 Apr 2022 23:30:35 +0800 Subject: [PATCH 20/51] Call finishEdit before restoreEdit --- .../metamorph/client/gui/creative/GuiCreativeMorphsList.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java index b5272cea..c46dab54 100644 --- a/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java +++ b/src/main/java/mchorse/metamorph/client/gui/creative/GuiCreativeMorphsList.java @@ -409,6 +409,8 @@ public void exitEditMorph(boolean add, boolean ignore) this.saveViewport(); } + this.editor.delegate.finishEdit(); + AbstractMorph edited = this.editor.delegate.morph; if (!this.nestedEdits.isEmpty() && !ignore) @@ -419,7 +421,6 @@ public void exitEditMorph(boolean add, boolean ignore) return; } - this.editor.delegate.finishEdit(); this.morphs.syncSelected(); if (add && edited != null && !this.isSelectedMorphIsEditable()) From 4a4da689afeb8341b49eabd7e20ca4b3b90ee674 Mon Sep 17 00:00:00 2001 From: Andriy <41327680+Andruxioid@users.noreply.github.com> Date: Sun, 20 Feb 2022 08:25:44 +0200 Subject: [PATCH 21/51] RU lang Strings 2.4.1 --- .../assets/metamorph/lang/ru_RU.lang | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/main/resources/assets/metamorph/lang/ru_RU.lang b/src/main/resources/assets/metamorph/lang/ru_RU.lang index cb08bcbe..6dab09a1 100644 --- a/src/main/resources/assets/metamorph/lang/ru_RU.lang +++ b/src/main/resources/assets/metamorph/lang/ru_RU.lang @@ -5,8 +5,8 @@ entity.metamorph.Morph.name=Морф # Keyboard bindings strings key.metamorph=Метаморф key.metamorph.action=Использовать действие -key.metamorph.creative_menu=Открыть меню превращения креатива -key.metamorph.selector_menu=Открыть меню селекторов существ +key.metamorph.creative_menu=Открыть меню превращения творчества +key.metamorph.selector_menu=Открыть меню селекторов сущностей key.metamorph.survival_menu=Открыть меню превращения выживания key.metamorph.demorph=Сбросить морф (обратно стать игроком) @@ -24,6 +24,8 @@ metamorph.gui.body_parts.dupe_tooltip=Клонировать выбранную metamorph.gui.body_parts.remove_tooltip=Удалить выбранную часть тела... metamorph.gui.body_parts.copy_tooltip=Скопировать все части тела... metamorph.gui.body_parts.paste_tooltip=Вставить скопированные части тела... +metamorph.gui.body_parts.keys.select_prev=Выбрать предыдущую часть тела +metamorph.gui.body_parts.keys.select_next=Выбрать следующую часть тела metamorph.gui.body_parts.context.copy=Скопировать часть тела metamorph.gui.body_parts.context.paste=Вставить скопированную часть тела @@ -59,7 +61,7 @@ metamorph.gui.creative.pick=Выбрать metamorph.gui.creative.quick=Быстрое редактирование metamorph.gui.creative.presets=Предустановки metamorph.gui.creative.random=Случайная предустановка -metamorph.gui.creative.keys.category=Меню превращения креатива +metamorph.gui.creative.keys.category=Меню превращения творчества metamorph.gui.creative.keys.exit=Выйти из редактора морфов metamorph.gui.creative.keys.edit=Редактировать выбранный морф metamorph.gui.creative.keys.focus=Панель поиска @@ -72,7 +74,7 @@ metamorph.gui.creative.context.add_category=Добавить новую кате metamorph.gui.creative.context.rename_category=Переименовать категорию metamorph.gui.creative.context.rename_category_modal=Дайте новое имя выбранной категории... metamorph.gui.creative.context.remove_category=Удалить категорию -metamorph.gui.creative.context.remove_morph_modal=Are you sure you want to remove this morph? It will be gone forever... +metamorph.gui.creative.context.remove_morph_modal=Уверенны, что хотите удалить этот морф? Он пропадёт навсегда... metamorph.gui.creative.context.remove_category_modal=Вы уверены, что хотите удалить эту категорию морфов? Она пропадёт навсегда... metamorph.gui.creative.context.clear_category=Удалить все морфы metamorph.gui.creative.context.clear_category_modal=Вы уверены, что хотите удалить все морфы из этой категории? Они пропадут оттуда навсегда... @@ -91,7 +93,7 @@ metamorph.gui.survival.keys.category=Меню превращения выжив metamorph.gui.survival.keys.toggle_favorites=Включить избранные морфы metamorph.gui.survival.keys.focus_keybind=Клавиша -metamorph.gui.editor.entity=Entity properties +metamorph.gui.editor.entity=Свойства сущности metamorph.gui.editor.settings=Параметры морфа metamorph.gui.editor.keybind=Комбинация клавиш metamorph.gui.editor.keybind_tooltip=Привязка морфа к клавише позволит вам превращаться в этот морф посредством нажатия назначенной клавиши либо при игре, либо в меню превращения выживания @@ -104,9 +106,9 @@ metamorph.gui.editor.attack=Атака metamorph.gui.editor.action=Действие metamorph.gui.editor.reset=Сбросить metamorph.gui.editor.item_morph=Предмет -metamorph.gui.editor.scale=Entity scale -metamorph.gui.editor.texture=Pick a texture... -metamorph.gui.editor.texture_tooltip=This feature won't work for all mobs, because some mobs can have custom rendering implementation +metamorph.gui.editor.scale=Размер сущности +metamorph.gui.editor.texture=Выбрать текстуру... +metamorph.gui.editor.texture_tooltip=Эта опция работает не для всех мобов, так как у некоторых присутствует свой собственный метод рендера metamorph.gui.editor.keys.category=Клавиши редактора морфов metamorph.gui.editor.keys.cycle=Зацикливание между панелями морфов @@ -126,9 +128,9 @@ metamorph.gui.label.shadow=Тень metamorph.gui.label.shadow_offset=Смещение тени metamorph.gui.label.shadow_color=Цвет тени metamorph.gui.label.lighting=Свечение -metamorph.gui.label.lighting_tooltip=Если отключить этот параметр, то карта свечения из Майнкрафта не будет применена, то есть морф применения будет светиться в темноте. Шейдерпаки у которых есть опция блума (bloom), will make this morph look like neon sign -metamorph.gui.label.background=Background -metamorph.gui.label.billboard=Look at player +metamorph.gui.label.lighting_tooltip=Если отключить этот параметр, то карта свечения из Майнкрафта не будет примененятся на морф, то есть морф применения будет светиться в темноте. С шейдерами, у которых есть опция блума (bloom), отключение этой настройки у морфа даст результат в виде "неонового" свечения +metamorph.gui.label.background=Фон +metamorph.gui.label.billboard=Смотреть на игрока metamorph.gui.edit=Редактировать metamorph.gui.panels.nbt_data=NBT-данные @@ -158,7 +160,7 @@ metamorph.config.comments.acquiring.acquire_immediately=Приобретать metamorph.config.morphs.title=Морфы metamorph.config.morphs.tooltip=Все параметры, касающиеся морфов и их настроек -metamorph.config.morphs.keep_morphs=Сохранять приобретённые морфов после смерти +metamorph.config.morphs.keep_morphs=Сохранять приобретённые морфы после смерти metamorph.config.comments.morphs.keep_morphs=Сохранять приобретённые морфы после смерти игрока metamorph.config.morphs.disable_pov=Отключить поле зрения metamorph.config.comments.morphs.disable_pov=Отключить изменение значения поля зрения. Опцию запросили из-за проблем с модом MorePlayerModels (поставьте на true если у вас дёргается экран) @@ -167,40 +169,40 @@ metamorph.config.comments.morphs.disable_health=Отключить измене metamorph.config.morphs.disable_morph_animation=Отключить анимацию превращения metamorph.config.comments.morphs.disable_morph_animation=Отключает анимацию превращения (частицы и так далее) metamorph.config.morphs.disable_morph_disguise=Отключить враждебность морфов -metamorph.config.comments.morphs.disable_morph_disguise=Отключить способности морфов с пометкой "враждебные" для того, чтобы не быть атакованным враждебными мобами +metamorph.config.comments.morphs.disable_morph_disguise=Отключает способности морфов с пометкой "враждебные" дабы не быть атакованным враждебными мобами metamorph.config.morphs.disable_first_person_hand=Отключить руку в режиме от первого лица metamorph.config.comments.morphs.disable_first_person_hand=Полностью отключить отображение руки в режиме от первого лица metamorph.config.morphs.morph_in_tight_spaces=Разрешить превращение в узких пространствах -metamorph.config.comments.morphs.morph_in_tight_spaces=Разрешает превращение даже при возможности удушья, а также разрешает прохождение сквозь стены +metamorph.config.comments.morphs.morph_in_tight_spaces=Разрешает превращение даже при возможности удушья, а также разрешает проходить сквозь стены metamorph.config.morphs.show_morph_idle_sounds=Проигрывать звуки бездействия морфов metamorph.config.comments.morphs.show_morph_idle_sounds=Проигрываются ли звуки бездействия морфа, в который превратился игрок metamorph.config.morphs.pause_gui_in_sp=Остановка интерфейса превращения -metamorph.config.comments.morphs.pause_gui_in_sp=Происходит ли остановка времени при открытии интерфейса превращения выживания и креатива в одиночной игре +metamorph.config.comments.morphs.pause_gui_in_sp=Происходит ли остановка времени при открытии интерфейса превращения режимов выживания и творчества в одиночной игре metamorph.config.morphs.max_recent_morphs=Максимальное количество недавних морфов -metamorph.config.comments.morphs.max_recent_morphs=Максиально возможное количество недавних морфов, которые добавляются в меню морфов перед удалением +metamorph.config.comments.morphs.max_recent_morphs=Максимально возможное количество недавних морфов, которые добавляются в меню морфов перед удалением metamorph.config.morphs.allow_morphing_into_category_morphs=Позволить превращение в категории морфов -metamorph.config.comments.morphs.allow_morphing_into_category_morphs=Если включена, эта опция позволит превращаться в недавние морфы и морфы из пользовательских категорий во время нахождения в режиме выживания. This option also allows to open creative morph menu in survival +metamorph.config.comments.morphs.allow_morphing_into_category_morphs=Если включена, эта опция позволит превращаться в недавние морфы и морфы из пользовательских категорий во время нахождения в режиме выживания. Эта опция также позволяет открывать меню метаморфа из режима творчества в режиме выживания metamorph.config.morphs.load_entity_morphs=Загрузить морфы существ -metamorph.config.comments.morphs.load_entity_morphs=Должны ли морфы существ быть загруженными в меню превращения креатива -metamorph.config.morphs.render_bodypart_axis=Render Axis for body parts -metamorph.config.comments.morphs.render_bodypart_axis=When enabled, body part axes are displayed in the body part editor GUI +metamorph.config.comments.morphs.load_entity_morphs=Должны ли морфы существ быть загруженными в меню превращения творчества +metamorph.config.morphs.render_bodypart_axis=Отображать оси частей тела +metamorph.config.comments.morphs.render_bodypart_axis=Если включена, опция будет показывать оси частей тела в интерфейса редактора # OP access config -op_access.config.metamorph.title=Metamorph -op_access.config.metamorph.tooltip=Metamorph's OP access options +op_access.config.metamorph.title=Метаморф +op_access.config.metamorph.tooltip=Настройки ОП-доступа к Метаморфу -op_access.config.metamorph.entity_selectors=Entity selectors -op_access.config.comments.metamorph.entity_selectors=Can non-OP players edit entity selectors? +op_access.config.metamorph.entity_selectors=Селекторы сущностей +op_access.config.comments.metamorph.entity_selectors=Может ли игрок, не являющийся оператором, редактировать селекторы сущностей? # Commands metamorph.commands.morph=Команда превращения. Эта команда отвечает за превращение игрока в какой-либо конкретный морф.\n\n/morph [morph_name] [data_tag] metamorph.commands.acquire_morph=Команда приобретения морфа. Эта команда отвечает за добавление морфа в список морфов приобретённых игроком.\n\n/morph [data_tag] metamorph.commands.metamorph=Серверная команда Метаморфа. Эта команда позволяет вам управлять серверными параметрами Метаморфа.\n\n/metamorph reload - перезагрузить черный список Метаморфа или конфигурацию морфа -metamorph.error.morph.not_player=Существо %s не является игроком! +metamorph.error.morph.not_player=Сущность %s не является игроком! metamorph.error.morph.nbt=Произошла ошибка во время синтаксического анализа (парсинга) дата-тэга:\n%s metamorph.error.morph.factory=Невозможно превратиться в морф %2$s с заданным тэгом данных -metamorph.error.acquire=Невозможно приобрестие морф с именем %s! +metamorph.error.acquire=Невозможно приобрести морф с названием %s! metamorph.success.morph=Игрок с никнеймом %s успешно превратился в морф %s! metamorph.success.demorph=Игрок с никнеймом %s успешно сбросил морф! metamorph.success.acquire=Игрок с никнеймом %s успешно приобрёл морф %s! @@ -214,6 +216,6 @@ morph.category.hostile=Враждебные морфы morph.category.modded=Морфы из %s morph.category.recent=Последние морфы -# Morph sections and categories -morph.section.entity=Морфы существ (Метаморфа) -morph.section.user=Пользовательские морфы \ No newline at end of file +# Секции и категории морфов +morph.section.entity=Морфы сущностей (Метаморфа) +morph.section.user=Пользовательские морфы From 9a96ac7d79a6ea17cae6529e40317c9aab8cb1e5 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Mon, 2 May 2022 00:06:58 +0200 Subject: [PATCH 22/51] Bump versions (1.3) --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index a7a2af4f..d9dbc8c3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Metamorph gradle properties -version=1.2.13 -mclib=2.3.6 +version=1.3 +mclib=2.4 mc_version=1.12.2 forge_version=14.23.5.2799 From 88ac40d9178685630308cc9ba9bf5853c1b3b658 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Mon, 2 May 2022 22:10:15 +0200 Subject: [PATCH 23/51] Update CHANGELOG --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index beafdd79..c7ac1d05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## Metamorph 1.3 + +This update was made by MiaoNLI. + +* GUI + * Add Onion Skin (Toggled by Q) + * Adjust the width of GuiTransformations +* BodyPart + * Hold down the Alt/Option key to lock the space transformed while switching limbs + * Show onion skin while editing a morph +* Morph + * Add option to enable/disable/only rendering shadow of Optifine shaderpack + * Label Morph + * Fix crash when text has non-English character + * Entity Morph + * Compatible with CEM of Optifine (suggested by MichaelCreeper_) +* File Encoding + * UTF-8 file encoding is used by default + ## Metamorph 1.2.13 This update fixed rotation yaw wasn't synchronized with body parts with use target. From b81ac4a62a27cf8c509a557a7657a6b67f0a7702 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Mon, 2 May 2022 22:10:23 +0200 Subject: [PATCH 24/51] Update version.json --- version.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/version.json b/version.json index cf13f5b7..169dac02 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,7 @@ { "homepage": "https://www.curseforge.com/minecraft/mc-mods/metamorph", "1.12.2": { + "1.3": "This update was made by MiaoNLI.", "1.2.13": "This patch fixed rotation yaw wasn't synchronized with body parts with use target.", "1.2.12": "This update adds a couple of QoL tweaks.", "1.2.11": "This update was made by Chryfi. The only change is making Use target option enabled by default for Blockbuster's tracker morphs.", @@ -36,8 +37,8 @@ "1.1.5": "This is a small, quick and dirty patch that provides several bugfixes (mainly for Blockbuster's update)." }, "promos": { - "1.12.2-latest":"1.2.13", - "1.12.2-recommended":"1.2.13", + "1.12.2-latest":"1.3", + "1.12.2-recommended":"1.3", "1.11.2-latest":"1.1.10", "1.11.2-recommended":"1.1.10", "1.10.2-latest":"1.1.10", From 97f1418ea66f9ddb3e3f271dc27010e78a79cc9b Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Mon, 2 May 2022 22:38:59 +0200 Subject: [PATCH 25/51] Added missing compatible sentence to CHANGELOG --- CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7ac1d05..272fed69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,18 @@ This update was made by MiaoNLI. +**Compatible** with McLib `2.4`. It doesn't mean that future versions of McLib would be incompatible, but older versions are most likely incompatible. + * GUI - * Add Onion Skin (Toggled by Q) - * Adjust the width of GuiTransformations + * Added Onion Skin (Toggled by Q) + * Adjusted the width of GuiTransformations * BodyPart * Hold down the Alt/Option key to lock the space transformed while switching limbs * Show onion skin while editing a morph * Morph - * Add option to enable/disable/only rendering shadow of Optifine shaderpack + * Added option to enable/disable/only rendering shadow of Optifine shaderpack * Label Morph - * Fix crash when text has non-English character + * Fixed crash when text has non-English character * Entity Morph * Compatible with CEM of Optifine (suggested by MichaelCreeper_) * File Encoding From 5468e5a2e92f805745fc6e47ead5c6c50a668202 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Mon, 2 May 2022 23:55:54 +0200 Subject: [PATCH 26/51] Update README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bfb367b7..a3766ab1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -**ATTENTION**: This mod is **no longer being developed nor maintained by McHorse**. If you wish to continue the mod, feel free to check out the [source code](https://github.com/mchorse/metamorph). +**ATTENTION**: This mod is **no longer being maintained by McHorse. It is now maintained by Chryfi.** + There are **still going to be official updates by Chryfi and other contributors** and there have been task forces that are investigating on porting it. **If you also want to contribute to official updates**, or to the porting effort, please **join the official [McHorse's Discord server](https://discord.gg/qfxrqUF), so we can communicate with you.** Check out the [source code](https://github.com/mchorse/metamorph). ![Metamorph](http://i.imgur.com/gbHB5iQ.png) From 330ac0cc65a9d4a826f5a769ee033c3f5a5a29bf Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Tue, 12 Jul 2022 14:05:38 +0200 Subject: [PATCH 27/51] Add local translation --- .../mchorse/metamorph/bodypart/BodyPart.java | 80 ++++++++++++++----- .../metamorph/bodypart/GuiBodyPartEditor.java | 10 ++- 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java index cff1f1bb..4fb88d1c 100644 --- a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java +++ b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java @@ -3,7 +3,9 @@ import javax.vecmath.Matrix3f; import javax.vecmath.Matrix4f; import javax.vecmath.Vector3f; +import javax.vecmath.Vector4f; +import mchorse.mclib.client.gui.framework.elements.input.GuiTransformations; import org.lwjgl.opengl.GL11; import com.google.common.base.Objects; @@ -42,24 +44,6 @@ public class BodyPart public static Matrix4f modelViewMatrix = new Matrix4f(); public static boolean recording = false; - @SideOnly(Side.CLIENT) - public static void recordMatrix(AbstractMorph parent, EntityLivingBase entity, float partialTicks) - { - recording = true; - - int lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE); - GL11.glMatrixMode(GL11.GL_MODELVIEW); - - GL11.glPushMatrix(); - GL11.glLoadIdentity(); - MorphUtils.renderDirect(parent, entity, 0, 0, 0, 0, partialTicks); - GL11.glPopMatrix(); - - GL11.glMatrixMode(lastMatrixMode); - - recording = false; - } - public Morph morph = new Morph(); public ItemStack[] slots = new ItemStack[] {ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY}; public Vector3f translate = new Vector3f(); @@ -79,6 +63,24 @@ public static void recordMatrix(AbstractMorph parent, EntityLivingBase entity, f public Matrix4f lastMatrix = null; + @SideOnly(Side.CLIENT) + public static void recordMatrix(AbstractMorph parent, EntityLivingBase entity, float partialTicks) + { + recording = true; + + int lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE); + GL11.glMatrixMode(GL11.GL_MODELVIEW); + + GL11.glPushMatrix(); + GL11.glLoadIdentity(); + MorphUtils.renderDirect(parent, entity, 0, 0, 0, 0, partialTicks); + GL11.glPopMatrix(); + + GL11.glMatrixMode(lastMatrixMode); + + recording = false; + } + @SideOnly(Side.CLIENT) public void init() { @@ -104,6 +106,29 @@ public void updateEntity() } } + public void addTranslation(float x, float y, float z, GuiTransformations.TransformOrientation orientation) + { + Vector4f trans = new Vector4f(x, y, z, 1); + + if (orientation == GuiTransformations.TransformOrientation.LOCAL) + { + Matrix4f mat = new Matrix4f(); + mat.setIdentity(); + Matrix4f rot = new Matrix4f(); + + rot.rotZ((float) Math.toRadians(this.rotate.z)); + mat.mul(rot); + rot.rotY((float) Math.toRadians(this.rotate.y)); + mat.mul(rot); + rot.rotX((float) Math.toRadians(this.rotate.x)); + mat.mul(rot); + + mat.transform(trans); + } + + this.translate.add(new Vector3f(trans.x, trans.y, trans.z)); + } + @SideOnly(Side.CLIENT) public void render(AbstractMorph parent, EntityLivingBase entity, float partialTicks) { @@ -186,12 +211,22 @@ public void render(AbstractMorph parent, EntityLivingBase entity, float partialT GL11.glPushMatrix(); GL11.glTranslatef(tx, ty, tz); + if (GuiTransformations.GuiStaticTransformOrientation.getOrientation() == GuiTransformations.TransformOrientation.GLOBAL) + { + this.drawAxis(); + } + GL11.glRotatef(rz, 0, 0, 1); GL11.glRotatef(ry, 0, 1, 0); GL11.glRotatef(rx, 1, 0, 0); GL11.glScalef(sx, sy, sz); + if (GuiTransformations.GuiStaticTransformOrientation.getOrientation() == GuiTransformations.TransformOrientation.LOCAL) + { + this.drawAxis(); + } + float yaw = entity.rotationYaw; float prevYaw = entity.prevRotationYaw; float rotationYaw = entity.renderYawOffset; @@ -214,6 +249,11 @@ public void render(AbstractMorph parent, EntityLivingBase entity, float partialT entity.rotationYawHead = rotationYawHead; entity.prevRotationYawHead = prevRotationYawHead; + GL11.glPopMatrix(); + } + + protected void drawAxis() + { /* Draw axis point for body part renderer */ if (GuiModelRenderer.isRendering()) { @@ -229,7 +269,7 @@ public void render(AbstractMorph parent, EntityLivingBase entity, float partialT if (Metamorph.renderBodyPartAxis.get()) { - Draw.axis(0.1F); + Draw.axis(0.25F); } GlStateManager.enableLighting(); @@ -240,8 +280,6 @@ public void render(AbstractMorph parent, EntityLivingBase entity, float partialT GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); GlStateManager.enableTexture2D(); } - - GL11.glPopMatrix(); } public void update(AbstractMorph parent, EntityLivingBase entity) diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index fcc41b43..af5caecb 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -16,7 +16,7 @@ import mchorse.mclib.utils.MathUtils; import mchorse.mclib.utils.MatrixUtils; import mchorse.mclib.utils.MatrixUtils.Transformation; -import mchorse.mclib.utils.MatrixUtils.Transformation.RotationOrder; +import mchorse.mclib.utils.MatrixUtils.RotationOrder; import mchorse.metamorph.api.MorphUtils; import mchorse.metamorph.api.morphs.AbstractMorph; import mchorse.metamorph.api.morphs.utils.IAnimationProvider; @@ -673,6 +673,14 @@ public GuiBodyPartTransformations(Minecraft mc) super(mc); } + @Override + public void localTranslate(double x, double y, double z) + { + this.part.addTranslation((float) x, (float) y, (float) z, GuiStaticTransformOrientation.getOrientation()); + + this.fillT(this.part.translate.x, this.part.translate.y, this.part.translate.z); + } + public void setBodyPart(BodyPart part) { this.part = part; From 3fb019ba8833e85f22e5870bf0f47b3fddb3d0d6 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Fri, 15 Jul 2022 14:51:43 +0200 Subject: [PATCH 28/51] Refactor addTranslation method to use getRotationMatrix of McLib --- .../mchorse/metamorph/bodypart/BodyPart.java | 25 ++++++++----------- .../metamorph/bodypart/GuiBodyPartEditor.java | 2 +- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java index 4fb88d1c..e0cc4f95 100644 --- a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java +++ b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java @@ -6,6 +6,7 @@ import javax.vecmath.Vector4f; import mchorse.mclib.client.gui.framework.elements.input.GuiTransformations; +import mchorse.mclib.utils.ITransformationObject; import org.lwjgl.opengl.GL11; import com.google.common.base.Objects; @@ -37,7 +38,7 @@ /** * Morph body part */ -public class BodyPart +public class BodyPart implements ITransformationObject { public static Vector3f cachedTranslation = new Vector3f(); public static Vector3f cachedAngularVelocity = new Vector3f(); @@ -106,24 +107,18 @@ public void updateEntity() } } - public void addTranslation(float x, float y, float z, GuiTransformations.TransformOrientation orientation) + @Override + public void addTranslation(double x, double y, double z, GuiTransformations.TransformOrientation orientation) { - Vector4f trans = new Vector4f(x, y, z, 1); + Vector4f trans = new Vector4f((float) x,(float) y,(float) z, 1); if (orientation == GuiTransformations.TransformOrientation.LOCAL) { - Matrix4f mat = new Matrix4f(); - mat.setIdentity(); - Matrix4f rot = new Matrix4f(); - - rot.rotZ((float) Math.toRadians(this.rotate.z)); - mat.mul(rot); - rot.rotY((float) Math.toRadians(this.rotate.y)); - mat.mul(rot); - rot.rotX((float) Math.toRadians(this.rotate.x)); - mat.mul(rot); - - mat.transform(trans); + float rotX = (float) Math.toRadians(this.rotate.x); + float rotY = (float) Math.toRadians(this.rotate.y); + float rotZ = (float) Math.toRadians(this.rotate.z); + + MatrixUtils.getRotationMatrix(rotX, rotY, rotZ, MatrixUtils.RotationOrder.XYZ).transform(trans); } this.translate.add(new Vector3f(trans.x, trans.y, trans.z)); diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index af5caecb..f2f596da 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -676,7 +676,7 @@ public GuiBodyPartTransformations(Minecraft mc) @Override public void localTranslate(double x, double y, double z) { - this.part.addTranslation((float) x, (float) y, (float) z, GuiStaticTransformOrientation.getOrientation()); + this.part.addTranslation(x, y, z, GuiStaticTransformOrientation.getOrientation()); this.fillT(this.part.translate.x, this.part.translate.y, this.part.translate.z); } From 65729e7a1c1d954e4596a3d046266941bebc2046 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Sat, 16 Jul 2022 15:51:07 +0200 Subject: [PATCH 29/51] Fix NPE issue with attachCapability with other mods entities --- .../java/mchorse/metamorph/capabilities/CapabilityHandler.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/mchorse/metamorph/capabilities/CapabilityHandler.java b/src/main/java/mchorse/metamorph/capabilities/CapabilityHandler.java index e0aa1e0c..5fca6e5f 100644 --- a/src/main/java/mchorse/metamorph/capabilities/CapabilityHandler.java +++ b/src/main/java/mchorse/metamorph/capabilities/CapabilityHandler.java @@ -67,6 +67,8 @@ private static boolean isMohist() @SubscribeEvent public void attachCapability(AttachCapabilitiesEvent event) { + if (event == null) return; + if (event.getObject() instanceof EntityLivingBase && event.getObject().world.isRemote) { event.addCapability(MODEL_CAP, new ModelProvider()); From f1639849ad7a1a92b3fe3528a77c569335246ad1 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Sun, 17 Jul 2022 21:38:47 +0200 Subject: [PATCH 30/51] Only draw bodypart axis of the selected bodypart --- src/main/java/mchorse/metamorph/bodypart/BodyPart.java | 9 +++++++-- .../mchorse/metamorph/bodypart/GuiBodyPartEditor.java | 9 +++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java index e0cc4f95..f994ba8f 100644 --- a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java +++ b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java @@ -5,6 +5,7 @@ import javax.vecmath.Vector3f; import javax.vecmath.Vector4f; +import mchorse.mclib.client.gui.framework.GuiBase; import mchorse.mclib.client.gui.framework.elements.input.GuiTransformations; import mchorse.mclib.utils.ITransformationObject; import org.lwjgl.opengl.GL11; @@ -35,6 +36,8 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.List; + /** * Morph body part */ @@ -249,8 +252,10 @@ public void render(AbstractMorph parent, EntityLivingBase entity, float partialT protected void drawAxis() { + List childList = GuiBase.getCurrentChildren(GuiBodyPartEditor.class); + /* Draw axis point for body part renderer */ - if (GuiModelRenderer.isRendering()) + if (GuiModelRenderer.isRendering() && childList != null && childList.get(0).isSelected(this)) { GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); GlStateManager.disableTexture2D(); @@ -264,7 +269,7 @@ protected void drawAxis() if (Metamorph.renderBodyPartAxis.get()) { - Draw.axis(0.25F); + Draw.axis(0.2F); } GlStateManager.enableLighting(); diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index f2f596da..5e64acc1 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -168,6 +168,15 @@ public GuiBodyPartEditor(Minecraft mc, GuiAbstractMorph editor) this.bodyParts.keys().register(IKey.lang("metamorph.gui.body_parts.keys.select_next"), Keyboard.KEY_S, () -> this.moveIndex(1)).category(GuiAbstractMorph.KEY_CATEGORY); } + /** + * @param part + * @return true if the provided instance reference matches the current selected bodypart + */ + public boolean isSelected(BodyPart part) + { + return part == this.part; + } + private void applyUseTarget(BodyPart part, AbstractMorph copy) { if (copy == null) From f23d61960878020d43cdb0c68fb6a4587ea1b24e Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Wed, 10 Aug 2022 16:02:59 +0200 Subject: [PATCH 31/51] Prevent NPE with attachCapability method, again... --- .../java/mchorse/metamorph/capabilities/CapabilityHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/capabilities/CapabilityHandler.java b/src/main/java/mchorse/metamorph/capabilities/CapabilityHandler.java index 5fca6e5f..cda41b24 100644 --- a/src/main/java/mchorse/metamorph/capabilities/CapabilityHandler.java +++ b/src/main/java/mchorse/metamorph/capabilities/CapabilityHandler.java @@ -69,7 +69,7 @@ public void attachCapability(AttachCapabilitiesEvent event) { if (event == null) return; - if (event.getObject() instanceof EntityLivingBase && event.getObject().world.isRemote) + if (event.getObject() instanceof EntityLivingBase && event.getObject().world != null && event.getObject().world.isRemote) { event.addCapability(MODEL_CAP, new ModelProvider()); } From f8942799b35b93ce7a6fde96843f74e949a4459a Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Wed, 10 Aug 2022 16:23:26 +0200 Subject: [PATCH 32/51] Fix bodypart axis being drawn behind models --- .../mchorse/metamorph/bodypart/BodyPart.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java index f994ba8f..1e3407af 100644 --- a/src/main/java/mchorse/metamorph/bodypart/BodyPart.java +++ b/src/main/java/mchorse/metamorph/bodypart/BodyPart.java @@ -2,12 +2,14 @@ import javax.vecmath.Matrix3f; import javax.vecmath.Matrix4f; +import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; import javax.vecmath.Vector4f; import mchorse.mclib.client.gui.framework.GuiBase; import mchorse.mclib.client.gui.framework.elements.input.GuiTransformations; import mchorse.mclib.utils.ITransformationObject; +import mchorse.mclib.utils.RenderingUtils; import org.lwjgl.opengl.GL11; import com.google.common.base.Objects; @@ -209,22 +211,12 @@ public void render(AbstractMorph parent, EntityLivingBase entity, float partialT GL11.glPushMatrix(); GL11.glTranslatef(tx, ty, tz); - if (GuiTransformations.GuiStaticTransformOrientation.getOrientation() == GuiTransformations.TransformOrientation.GLOBAL) - { - this.drawAxis(); - } - GL11.glRotatef(rz, 0, 0, 1); GL11.glRotatef(ry, 0, 1, 0); GL11.glRotatef(rx, 1, 0, 0); GL11.glScalef(sx, sy, sz); - if (GuiTransformations.GuiStaticTransformOrientation.getOrientation() == GuiTransformations.TransformOrientation.LOCAL) - { - this.drawAxis(); - } - float yaw = entity.rotationYaw; float prevYaw = entity.prevRotationYaw; float rotationYaw = entity.renderYawOffset; @@ -240,6 +232,8 @@ public void render(AbstractMorph parent, EntityLivingBase entity, float partialT MorphUtils.render(this.morph.get(), entity, 0, 0, 0, 0, partialTicks); + this.drawAxis(); + entity.rotationYaw = yaw; entity.prevRotationYaw = prevYaw; entity.renderYawOffset = rotationYaw; @@ -257,6 +251,15 @@ protected void drawAxis() /* Draw axis point for body part renderer */ if (GuiModelRenderer.isRendering() && childList != null && childList.get(0).isSelected(this)) { + GlStateManager.pushMatrix(); + + if (GuiTransformations.GuiStaticTransformOrientation.getOrientation() == GuiTransformations.TransformOrientation.GLOBAL) + { + Vector3d rot = new Vector3d(Math.toRadians(this.rotate.x), Math.toRadians(this.rotate.y), Math.toRadians(this.rotate.z)); + + RenderingUtils.glRevertRotationScale(rot, new Vector3d(this.scale), MatrixUtils.RotationOrder.XYZ); + } + GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); GlStateManager.disableTexture2D(); GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); @@ -272,6 +275,8 @@ protected void drawAxis() Draw.axis(0.2F); } + GlStateManager.popMatrix(); + GlStateManager.enableLighting(); GlStateManager.enableDepth(); From bc590c65bdbddfa369a17693bc940e989cc589e3 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Wed, 10 Aug 2022 16:24:01 +0200 Subject: [PATCH 33/51] Remove W and S for bodypart Cycling - use Arrow keys now W and S collided with immersive editor left click movement WASD --- .../metamorph/bodypart/GuiBodyPartEditor.java | 31 ++----------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index 5e64acc1..79006fb8 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -164,8 +164,8 @@ public GuiBodyPartEditor(Minecraft mc, GuiAbstractMorph editor) this.elements.add(this.stacks); - this.bodyParts.keys().register(IKey.lang("metamorph.gui.body_parts.keys.select_prev"), Keyboard.KEY_W, () -> this.moveIndex(-1)).category(GuiAbstractMorph.KEY_CATEGORY); - this.bodyParts.keys().register(IKey.lang("metamorph.gui.body_parts.keys.select_next"), Keyboard.KEY_S, () -> this.moveIndex(1)).category(GuiAbstractMorph.KEY_CATEGORY); + this.bodyParts.keys().register(IKey.lang("metamorph.gui.body_parts.keys.select_prev"), Keyboard.KEY_UP, () -> this.moveIndex(-1)).category(GuiAbstractMorph.KEY_CATEGORY); + this.bodyParts.keys().register(IKey.lang("metamorph.gui.body_parts.keys.select_next"), Keyboard.KEY_DOWN, () -> this.moveIndex(1)).category(GuiAbstractMorph.KEY_CATEGORY); } /** @@ -597,19 +597,6 @@ public void fillBodyPart(BodyPart part) } } - @Override - public boolean keyTyped(GuiContext context) - { - if (super.keyTyped(context)) - { - return true; - } - - this.moveIndex(this.getMoveIndex(context.keyCode)); - - return false; - } - private void moveIndex(int index) { if (index != 0) @@ -621,20 +608,6 @@ private void moveIndex(int index) } } - private int getMoveIndex(int keyCode) - { - if (keyCode == Keyboard.KEY_UP) - { - return -1; - } - else if (keyCode == Keyboard.KEY_DOWN) - { - return 1; - } - - return 0; - } - @Override public void draw(GuiContext context) { From b90392b919fdb3c01ae27f939f4ca180e7a2bdd6 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Fri, 12 Aug 2022 13:38:16 +0200 Subject: [PATCH 34/51] Add anyMatch method to MorphUtils to traverse a morph --- .../mchorse/metamorph/api/MorphUtils.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/main/java/mchorse/metamorph/api/MorphUtils.java b/src/main/java/mchorse/metamorph/api/MorphUtils.java index 87d7ccd3..9624eb4c 100644 --- a/src/main/java/mchorse/metamorph/api/MorphUtils.java +++ b/src/main/java/mchorse/metamorph/api/MorphUtils.java @@ -6,6 +6,10 @@ import java.lang.reflect.Field; import java.util.Map; import java.util.Set; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; import io.netty.buffer.ByteBuf; import mchorse.mclib.client.gui.framework.elements.GuiModelRenderer; @@ -14,9 +18,11 @@ import mchorse.metamorph.api.events.RegisterBlacklistEvent; import mchorse.metamorph.api.events.RegisterRemapEvent; import mchorse.metamorph.api.events.RegisterSettingsEvent; +import mchorse.metamorph.api.models.IMorphProvider; import mchorse.metamorph.api.morphs.AbstractMorph; import mchorse.metamorph.api.morphs.utils.ISyncableMorph; import mchorse.metamorph.bodypart.BodyPart; +import mchorse.metamorph.bodypart.BodyPartManager; import mchorse.metamorph.bodypart.IBodyPartProvider; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.Tessellator; @@ -273,4 +279,47 @@ public static AbstractMorph morphFromBuf(ByteBuf buffer) { return MorphManager.INSTANCE.morphFromNBT(NBTUtils.readInfiniteTag(buffer)); } + + /** + * Traverses the morph and its bodyparts to find a morph that matches the provided predicate. + * @param morph + * @param condition the predicate to apply on the morphs and children + * @return true if any of the morph and children match the provided predicate, otherwise false. + */ + public static boolean anyMatch(AbstractMorph morph, Predicate condition) + { + while (true) + { + if (condition.test(morph)) + { + return true; + } + + if (morph instanceof IBodyPartProvider) + { + BodyPartManager mgr = ((IBodyPartProvider) morph).getBodyPart(); + for (BodyPart part : mgr.parts) + { + if (part.enabled) + { + if (anyMatch(part.morph.get(), condition)) + { + return true; + } + } + } + } + + if (morph instanceof IMorphProvider) + { + morph = ((IMorphProvider) morph).getMorph(); + } + else + { + break; + } + } + + return false; + } } \ No newline at end of file From 45ee82009879bb70a9f4337842201f4818d58542 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Sat, 13 Aug 2022 13:52:04 +0200 Subject: [PATCH 35/51] Added useTargetDefault method to use for bodypart gui --- .../java/mchorse/metamorph/api/morphs/AbstractMorph.java | 9 +++++++++ .../mchorse/metamorph/bodypart/GuiBodyPartEditor.java | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java index 534a2059..b2235846 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java @@ -428,6 +428,15 @@ public boolean canMerge(AbstractMorph morph) public void afterMerge(AbstractMorph morph) {} + /** + * Whether to activate the use target option in GUIs like BodyPart GUI by default + * @return false by default + */ + public boolean useTargetDefault() + { + return false; + } + /** * This method should be used by any morphs that support merging to copy essential * whenever they merge diff --git a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java index 79006fb8..1703493a 100644 --- a/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java +++ b/src/main/java/mchorse/metamorph/bodypart/GuiBodyPartEditor.java @@ -184,7 +184,7 @@ private void applyUseTarget(BodyPart part, AbstractMorph copy) return; } - if (copy.name.equals("snowstorm") || copy.name.equals("particle") || copy.name.equals("tracker")) + if (copy.useTargetDefault()) { part.useTarget = true; this.useTarget.toggled(part.useTarget); From b9a2f4507d21e62b43eb6ecf3abfd6cc6e865ce2 Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Fri, 14 Oct 2022 19:42:57 +0200 Subject: [PATCH 36/51] Update version.json (1.3.1) --- version.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/version.json b/version.json index 169dac02..f26ed4fc 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,7 @@ { "homepage": "https://www.curseforge.com/minecraft/mc-mods/metamorph", "1.12.2": { + "1.3.1": "This update was made by Chryfi and it fixes some issues.", "1.3": "This update was made by MiaoNLI.", "1.2.13": "This patch fixed rotation yaw wasn't synchronized with body parts with use target.", "1.2.12": "This update adds a couple of QoL tweaks.", @@ -37,8 +38,8 @@ "1.1.5": "This is a small, quick and dirty patch that provides several bugfixes (mainly for Blockbuster's update)." }, "promos": { - "1.12.2-latest":"1.3", - "1.12.2-recommended":"1.3", + "1.12.2-latest":"1.3.1", + "1.12.2-recommended":"1.3.1", "1.11.2-latest":"1.1.10", "1.11.2-recommended":"1.1.10", "1.10.2-latest":"1.1.10", From d017785f26195cfc0a55294445e93506094e000f Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Fri, 14 Oct 2022 19:43:06 +0200 Subject: [PATCH 37/51] Update changelog (1.3.1) --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 272fed69..0e702ebe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## Metamorph 1.3.1 + +This update was made by Chryfi. + +**Compatible** with McLib `2.4`. It doesn't mean that future versions of McLib would be incompatible, but older versions are most likely incompatible. + +* Added local / global translation mode +* Added useTargetDefault method to AbstractMorph to get rid of bad name checks in bodypart menu code +* Fixed bodypart axis drawing at non selected bodyparts +* Fixed NPE crash with Metamorph capabilities +* Removed W and S key for bodypart cycling - use the arrow keys now + ## Metamorph 1.3 This update was made by MiaoNLI. From 75eff59ce95ffe4e9f64a149d1b7504f39f3705c Mon Sep 17 00:00:00 2001 From: Chryfi <71967555+Chryfi@users.noreply.github.com> Date: Fri, 14 Oct 2022 19:43:17 +0200 Subject: [PATCH 38/51] Bump versions (1.3.1) --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index d9dbc8c3..0a19787c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Metamorph gradle properties -version=1.3 -mclib=2.4 +version=1.3.1 +mclib=2.4.1 mc_version=1.12.2 forge_version=14.23.5.2799 From c5b32fcbc9612601fea5d1e3f10754f52075eec9 Mon Sep 17 00:00:00 2001 From: McHorse Date: Wed, 28 Jun 2023 12:54:38 +0100 Subject: [PATCH 39/51] Add item transform option to item morph --- .../vanilla_pack/editors/GuiItemMorph.java | 9 ++- .../editors/panels/GuiItemPanel.java | 62 +++++++++++++++++++ .../editors/panels/GuiItemStackPanel.java | 2 + .../vanilla_pack/morphs/ItemMorph.java | 60 ++++++++++++++++-- .../assets/metamorph/lang/en_US.lang | 10 +++ 5 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java diff --git a/src/main/java/mchorse/vanilla_pack/editors/GuiItemMorph.java b/src/main/java/mchorse/vanilla_pack/editors/GuiItemMorph.java index c8094194..60738d2e 100644 --- a/src/main/java/mchorse/vanilla_pack/editors/GuiItemMorph.java +++ b/src/main/java/mchorse/vanilla_pack/editors/GuiItemMorph.java @@ -4,24 +4,23 @@ import mchorse.metamorph.api.morphs.AbstractMorph; import mchorse.metamorph.client.gui.editor.GuiAbstractMorph; import mchorse.metamorph.util.MMIcons; -import mchorse.vanilla_pack.editors.panels.GuiItemStackPanel; +import mchorse.vanilla_pack.editors.panels.GuiItemPanel; import mchorse.vanilla_pack.morphs.ItemMorph; import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) public class GuiItemMorph extends GuiAbstractMorph { - public GuiItemStackPanel block; + public GuiItemPanel item; public GuiItemMorph(Minecraft mc) { super(mc); - this.defaultPanel = this.block = new GuiItemStackPanel(mc, this); - this.registerPanel(this.block, IKey.lang("metamorph.gui.editor.item_morph"), MMIcons.ITEM); + this.defaultPanel = this.item = new GuiItemPanel(mc, this); + this.registerPanel(this.item, IKey.lang("metamorph.gui.editor.item_morph"), MMIcons.ITEM); } @Override diff --git a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java new file mode 100644 index 00000000..1484d6bf --- /dev/null +++ b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java @@ -0,0 +1,62 @@ +package mchorse.vanilla_pack.editors.panels; + +import mchorse.mclib.client.gui.framework.elements.buttons.GuiCirculateElement; +import mchorse.mclib.client.gui.framework.elements.buttons.GuiSlotElement; +import mchorse.mclib.client.gui.framework.elements.buttons.GuiToggleElement; +import mchorse.mclib.client.gui.utils.keys.IKey; +import mchorse.metamorph.client.gui.editor.GuiAbstractMorph; +import mchorse.metamorph.client.gui.editor.GuiMorphPanel; +import mchorse.vanilla_pack.morphs.ItemMorph; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class GuiItemPanel extends GuiMorphPanel> +{ + public GuiSlotElement slot; + public GuiToggleElement lighting; + public GuiCirculateElement transform; + + public GuiItemPanel(Minecraft mc, GuiAbstractMorph editor) + { + super(mc, editor); + + this.slot = new GuiSlotElement(mc, 0, (stack) -> this.morph.setStack(stack)); + this.lighting = new GuiToggleElement(mc, IKey.lang("metamorph.gui.label.lighting"), (b) -> this.morph.lighting = b.isToggled()); + + this.slot.flex().relative(this).x(0.5F, 0).y(1, -10).wh(32, 32).anchor(0.5F, 1); + this.lighting.flex().relative(this).xy(10, 10).w(110); + + this.transform = new GuiCirculateElement(mc, (b) -> + { + ItemCameraTransforms.TransformType type = ItemCameraTransforms.TransformType.values()[b.getValue()]; + + this.morph.transform = ItemMorph.getTransformTypes().inverse().get(type); + }); + + this.transform.flex().relative(this.lighting).y(1F, 5).w(1F); + + for (ItemCameraTransforms.TransformType transform : ItemCameraTransforms.TransformType.values()) + { + String key = ItemMorph.getTransformTypes().inverse().get(transform); + + this.transform.addLabel(IKey.lang("metamorph.gui.item.transform." + key)); + } + + this.add(this.slot, this.lighting, this.transform); + } + + @Override + public void fillData(ItemMorph morph) + { + super.fillData(morph); + + ItemCameraTransforms.TransformType type = morph.getTransformType(); + + this.slot.setStack(morph.getStack()); + this.lighting.toggled(morph.lighting); + this.transform.setValue(type.ordinal()); + } +} \ No newline at end of file diff --git a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemStackPanel.java b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemStackPanel.java index 470e4762..f7d725ee 100644 --- a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemStackPanel.java +++ b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemStackPanel.java @@ -1,5 +1,6 @@ package mchorse.vanilla_pack.editors.panels; +import mchorse.mclib.client.gui.framework.elements.buttons.GuiCirculateElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiSlotElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiToggleElement; import mchorse.mclib.client.gui.utils.keys.IKey; @@ -15,6 +16,7 @@ public class GuiItemStackPanel extends GuiMorphPanel editor) { diff --git a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java index 354be3fe..5604ca12 100644 --- a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java +++ b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java @@ -1,29 +1,54 @@ package mchorse.vanilla_pack.morphs; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import mchorse.mclib.client.gui.framework.elements.utils.GuiInventoryElement; -import mchorse.mclib.utils.MathUtils; import mchorse.metamorph.api.morphs.AbstractMorph; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.RenderItem; import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import java.util.Objects; - public class ItemMorph extends ItemStackMorph { + @SideOnly(Side.CLIENT) + private static BiMap transformTypes; + public ItemStack stack = new ItemStack(Items.DIAMOND_HOE, 1); + public String transform = ""; + + @SideOnly(Side.CLIENT) + public static BiMap getTransformTypes() + { + if (transformTypes == null) + { + transformTypes = HashBiMap.create(); + + transformTypes.put("none", ItemCameraTransforms.TransformType.NONE); + transformTypes.put("third_person_left_hand", ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND); + transformTypes.put("third_person_right_hand", ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND); + transformTypes.put("first_person_left_hand", ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND); + transformTypes.put("first_person_right_hand", ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND); + transformTypes.put("head", ItemCameraTransforms.TransformType.HEAD); + transformTypes.put("gui", ItemCameraTransforms.TransformType.GUI); + transformTypes.put("ground", ItemCameraTransforms.TransformType.GROUND); + transformTypes.put("fixed", ItemCameraTransforms.TransformType.FIXED); + } + + return transformTypes; + } public ItemMorph() { @@ -42,6 +67,14 @@ public ItemStack getStack() return this.stack; } + @SideOnly(Side.CLIENT) + public ItemCameraTransforms.TransformType getTransformType() + { + ItemCameraTransforms.TransformType transformType = transformTypes.get(this.transform); + + return transformType == null ? ItemCameraTransforms.TransformType.NONE : transformType; + } + @Override @SideOnly(Side.CLIENT) public void renderOnScreen(EntityPlayer player, int x, int y, float scale, float alpha) @@ -86,7 +119,14 @@ public void render(EntityLivingBase entity, double x, double y, double z, float Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); RenderItem render = Minecraft.getMinecraft().getRenderItem(); - IBakedModel model = render.getItemModelWithOverrides(stack, entity.world, entity); + IBakedModel model = render.getItemModelWithOverrides(this.stack, entity.world, entity); + + ItemCameraTransforms.TransformType transform = this.getTransformType(); + + if (transform != ItemCameraTransforms.TransformType.NONE) + { + model = ForgeHooksClient.handleCameraTransforms(model, transform, false); + } render.renderItem(this.stack, model); @@ -108,6 +148,7 @@ public boolean equals(Object obj) ItemMorph item = (ItemMorph) obj; result = result && ItemStack.areItemStacksEqualUsingNBTShareTag(this.stack, item.stack); + result = result && this.transform != item.transform; } return result; @@ -126,7 +167,10 @@ public void copy(AbstractMorph from) if (from instanceof ItemMorph) { - this.stack = ((ItemMorph) from).stack.copy(); + ItemMorph item = (ItemMorph) from; + + this.stack = item.stack.copy(); + this.transform = item.transform; } } @@ -151,6 +195,8 @@ public void toNBT(NBTTagCompound tag) { tag.setTag("Stack", this.stack.serializeNBT()); } + + tag.setString("Transform", this.transform); } @Override @@ -162,5 +208,7 @@ public void fromNBT(NBTTagCompound tag) { this.stack = new ItemStack(tag.getCompoundTag("Stack")); } + + this.transform = tag.getString("Transform"); } } \ No newline at end of file diff --git a/src/main/resources/assets/metamorph/lang/en_US.lang b/src/main/resources/assets/metamorph/lang/en_US.lang index 81cf63c8..803865e9 100644 --- a/src/main/resources/assets/metamorph/lang/en_US.lang +++ b/src/main/resources/assets/metamorph/lang/en_US.lang @@ -136,6 +136,16 @@ metamorph.gui.label.lighting_tooltip=When disabled, Minecraft's lightmap won't b metamorph.gui.label.background=Background metamorph.gui.label.billboard=Look at player +metamorph.gui.item.transform.none=None +metamorph.gui.item.transform.third_person_left_hand=Left hand (3rd) +metamorph.gui.item.transform.third_person_right_hand=Right hand (3rd) +metamorph.gui.item.transform.first_person_left_hand=Left hand (1st) +metamorph.gui.item.transform.first_person_right_hand=Right hand (1st) +metamorph.gui.item.transform.head=On head +metamorph.gui.item.transform.gui=Inventory +metamorph.gui.item.transform.ground=On ground +metamorph.gui.item.transform.fixed=Item frame + metamorph.gui.edit=Edit metamorph.gui.panels.nbt_data=NBT data metamorph.gui.panels.username=Username From 0eaddb0f260e04c0e27147d4ae6bade544702f1f Mon Sep 17 00:00:00 2001 From: McHorse Date: Wed, 28 Jun 2023 14:35:54 +0100 Subject: [PATCH 40/51] Add extruded 3D item texture morph --- .../editors/panels/GuiItemPanel.java | 28 ++- .../editors/panels/GuiItemStackPanel.java | 2 - .../vanilla_pack/morphs/ItemMorph.java | 64 +++++- .../vanilla_pack/render/CachedExtrusion.java | 84 ++++++++ .../vanilla_pack/render/ItemExtruder.java | 185 ++++++++++++++++++ 5 files changed, 350 insertions(+), 13 deletions(-) create mode 100644 src/main/java/mchorse/vanilla_pack/render/CachedExtrusion.java create mode 100644 src/main/java/mchorse/vanilla_pack/render/ItemExtruder.java diff --git a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java index 1484d6bf..bad94405 100644 --- a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java +++ b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java @@ -1,9 +1,15 @@ package mchorse.vanilla_pack.editors.panels; +import mchorse.mclib.client.gui.framework.elements.GuiElement; +import mchorse.mclib.client.gui.framework.elements.buttons.GuiButtonElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiCirculateElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiSlotElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiToggleElement; +import mchorse.mclib.client.gui.framework.elements.input.GuiTexturePicker; +import mchorse.mclib.client.gui.utils.Elements; import mchorse.mclib.client.gui.utils.keys.IKey; +import mchorse.mclib.utils.Direction; +import mchorse.mclib.utils.resources.RLUtils; import mchorse.metamorph.client.gui.editor.GuiAbstractMorph; import mchorse.metamorph.client.gui.editor.GuiMorphPanel; import mchorse.vanilla_pack.morphs.ItemMorph; @@ -18,6 +24,9 @@ public class GuiItemPanel extends GuiMorphPanel editor) { @@ -27,7 +36,6 @@ public GuiItemPanel(Minecraft mc, GuiAbstractMorph editor) this.lighting = new GuiToggleElement(mc, IKey.lang("metamorph.gui.label.lighting"), (b) -> this.morph.lighting = b.isToggled()); this.slot.flex().relative(this).x(0.5F, 0).y(1, -10).wh(32, 32).anchor(0.5F, 1); - this.lighting.flex().relative(this).xy(10, 10).w(110); this.transform = new GuiCirculateElement(mc, (b) -> { @@ -36,8 +44,6 @@ public GuiItemPanel(Minecraft mc, GuiAbstractMorph editor) this.morph.transform = ItemMorph.getTransformTypes().inverse().get(type); }); - this.transform.flex().relative(this.lighting).y(1F, 5).w(1F); - for (ItemCameraTransforms.TransformType transform : ItemCameraTransforms.TransformType.values()) { String key = ItemMorph.getTransformTypes().inverse().get(transform); @@ -45,7 +51,21 @@ public GuiItemPanel(Minecraft mc, GuiAbstractMorph editor) this.transform.addLabel(IKey.lang("metamorph.gui.item.transform." + key)); } - this.add(this.slot, this.lighting, this.transform); + this.texture = new GuiButtonElement(mc, IKey.lang("metamorph.gui.editor.texture"), (b) -> + { + this.picker.refresh(); + this.picker.fill(this.morph.texture); + this.add(this.picker); + this.picker.resize(); + }); + this.picker = new GuiTexturePicker(mc, (rl) -> this.morph.texture = RLUtils.clone(rl)); + this.picker.flex().relative(this).wh(1F, 1F); + + GuiElement column = Elements.column(mc, 5, this.lighting, this.transform, this.texture); + + column.flex().relative(this).xy(10, 10).w(110); + + this.add(this.slot, column); } @Override diff --git a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemStackPanel.java b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemStackPanel.java index f7d725ee..470e4762 100644 --- a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemStackPanel.java +++ b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemStackPanel.java @@ -1,6 +1,5 @@ package mchorse.vanilla_pack.editors.panels; -import mchorse.mclib.client.gui.framework.elements.buttons.GuiCirculateElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiSlotElement; import mchorse.mclib.client.gui.framework.elements.buttons.GuiToggleElement; import mchorse.mclib.client.gui.utils.keys.IKey; @@ -16,7 +15,6 @@ public class GuiItemStackPanel extends GuiMorphPanel editor) { diff --git a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java index 5604ca12..c55ff2ed 100644 --- a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java +++ b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java @@ -3,7 +3,10 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import mchorse.mclib.client.gui.framework.elements.utils.GuiInventoryElement; +import mchorse.mclib.utils.resources.RLUtils; import mchorse.metamorph.api.morphs.AbstractMorph; +import mchorse.vanilla_pack.render.CachedExtrusion; +import mchorse.vanilla_pack.render.ItemExtruder; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; @@ -17,9 +20,13 @@ import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.OpenGLException; + +import java.util.Objects; public class ItemMorph extends ItemStackMorph { @@ -28,6 +35,7 @@ public class ItemMorph extends ItemStackMorph public ItemStack stack = new ItemStack(Items.DIAMOND_HOE, 1); public String transform = ""; + public ResourceLocation texture; @SideOnly(Side.CLIENT) public static BiMap getTransformTypes() @@ -81,19 +89,37 @@ public void renderOnScreen(EntityPlayer player, int x, int y, float scale, float { GlStateManager.disableCull(); GlStateManager.enableDepth(); - RenderHelper.enableGUIStandardItemLighting(); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240.0F, 240.0F); scale = scale / 16F; GlStateManager.pushMatrix(); GlStateManager.translate(x, y - 12, 0); - GlStateManager.scale(scale, scale, scale); - GuiInventoryElement.drawItemStack(this.stack, -8, -8, 0, null); - GlStateManager.popMatrix(); + if (this.texture != null) + { + GlStateManager.color(1, 1, 1); + GlStateManager.scale(scale * 16F, -scale * 16F, scale * 16F); + + CachedExtrusion extrusion = ItemExtruder.extrude(this.texture); + + if (extrusion != null) + { + extrusion.render(); + } + } + else + { + GlStateManager.scale(scale, scale, scale); + + RenderHelper.enableGUIStandardItemLighting(); + + GuiInventoryElement.drawItemStack(this.stack, -8, -8, 0, null); - RenderHelper.disableStandardItemLighting(); + RenderHelper.disableStandardItemLighting(); + } + + GlStateManager.popMatrix(); GlStateManager.enableCull(); GlStateManager.disableDepth(); } @@ -128,7 +154,19 @@ public void render(EntityLivingBase entity, double x, double y, double z, float model = ForgeHooksClient.handleCameraTransforms(model, transform, false); } - render.renderItem(this.stack, model); + if (this.texture != null) + { + CachedExtrusion extrusion = ItemExtruder.extrude(this.texture); + + if (extrusion != null) + { + extrusion.render(); + } + } + else + { + render.renderItem(this.stack, model); + } GlStateManager.popMatrix(); @@ -148,7 +186,8 @@ public boolean equals(Object obj) ItemMorph item = (ItemMorph) obj; result = result && ItemStack.areItemStacksEqualUsingNBTShareTag(this.stack, item.stack); - result = result && this.transform != item.transform; + result = result && this.transform.equals(item.transform); + result = result && Objects.equals(this.texture, item.texture); } return result; @@ -171,6 +210,7 @@ public void copy(AbstractMorph from) this.stack = item.stack.copy(); this.transform = item.transform; + this.texture = item.texture; } } @@ -197,6 +237,11 @@ public void toNBT(NBTTagCompound tag) } tag.setString("Transform", this.transform); + + if (this.texture != null) + { + tag.setString("Texture", this.texture.toString()); + } } @Override @@ -210,5 +255,10 @@ public void fromNBT(NBTTagCompound tag) } this.transform = tag.getString("Transform"); + + if (tag.hasKey("Texture")) + { + this.texture = RLUtils.create(tag.getString("Texture")); + } } } \ No newline at end of file diff --git a/src/main/java/mchorse/vanilla_pack/render/CachedExtrusion.java b/src/main/java/mchorse/vanilla_pack/render/CachedExtrusion.java new file mode 100644 index 00000000..3709d15f --- /dev/null +++ b/src/main/java/mchorse/vanilla_pack/render/CachedExtrusion.java @@ -0,0 +1,84 @@ +package mchorse.vanilla_pack.render; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL15; + +import java.nio.ByteBuffer; + +public class CachedExtrusion +{ + /* 6 vertices * (3f vertex + 3f normal + 2f uv) */ + private static final int BYTES_PER_VERTEX = (3 * 4 + 3 * 4 + 2 * 4); + private static final int BYTES_PER_QUAD = 6 * BYTES_PER_VERTEX; + + private ResourceLocation texture; + private int vertices; + private int vbo; + private ByteBuffer buffer; + + public CachedExtrusion(ResourceLocation texture, int w, int h) + { + this.texture = texture; + this.buffer = BufferUtils.createByteBuffer(w * h * BYTES_PER_QUAD); + + this.vbo = GL15.glGenBuffers(); + } + + public void addVertex(float x, float y, float z, float nx, float ny, float nz, float u, float v) + { + this.buffer.putFloat(x); + this.buffer.putFloat(y); + this.buffer.putFloat(z); + + this.buffer.putFloat(nx); + this.buffer.putFloat(ny); + this.buffer.putFloat(nz); + + this.buffer.putFloat(u); + this.buffer.putFloat(v); + + this.vertices += 1; + } + + public void flush() + { + this.buffer.flip(); + + GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vbo); + GL15.glBufferData(GL15.GL_ARRAY_BUFFER, this.buffer, GL15.GL_DYNAMIC_DRAW); + } + + public void render() + { + GlStateManager.disableCull(); + + Minecraft.getMinecraft().renderEngine.bindTexture(this.texture); + + GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vbo); + GL11.glVertexPointer(3, GL11.GL_FLOAT, BYTES_PER_VERTEX, 0); + GL11.glNormalPointer(GL11.GL_FLOAT, BYTES_PER_VERTEX, 3 * 4); + GL11.glTexCoordPointer(2, GL11.GL_FLOAT, BYTES_PER_VERTEX, 6 * 4); + + GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY); + GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY); + GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + + /* Render with index buffer */ + GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, this.vertices); + + /* Unbind the buffer. REQUIRED to avoid OpenGL crash */ + GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); + GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); + + GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY); + GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY); + GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + + GlStateManager.enableCull(); + } +} \ No newline at end of file diff --git a/src/main/java/mchorse/vanilla_pack/render/ItemExtruder.java b/src/main/java/mchorse/vanilla_pack/render/ItemExtruder.java new file mode 100644 index 00000000..1070d8fd --- /dev/null +++ b/src/main/java/mchorse/vanilla_pack/render/ItemExtruder.java @@ -0,0 +1,185 @@ +package mchorse.vanilla_pack.render; + +import mchorse.mclib.utils.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Map; + +@SideOnly(Side.CLIENT) +public class ItemExtruder +{ + private static Map cache = new HashMap(); + + public static CachedExtrusion extrude(ResourceLocation texture) + { + CachedExtrusion extrusion = cache.get(texture); + + if (extrusion != null) + { + return extrusion; + } + + BufferedImage pixels = null; + + try + { + pixels = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(texture).getInputStream()); + } + catch (Exception e) + { + cache.put(texture, null); + + return null; + } + + int w = pixels.getWidth(); + int h = pixels.getHeight(); + extrusion = new CachedExtrusion(texture, w, h); + + int uv_x = 0; + int uv_y = 0; + + float p = 0.5F; + float n = -0.5F; + float u1 = uv_x / (float) w; + float v1 = uv_y / (float) h; + float u2 = (uv_x + w) / (float) w; + float v2 = (uv_y + h) / (float) h; + float d = 0.5F / 16F; + + fillTexturedNormalQuad(extrusion, + p, n, d, + n, n, d, + n, p, d, + p, p, d, + u1, v1, u2, v2, + 0F, 0F, 1F + ); + + fillTexturedNormalQuad(extrusion, + n, n, -d, + p, n, -d, + p, p, -d, + n, p, -d, + u2, v1, u1, v2, + 0F, 0F, -1F + ); + + for (int i = 0; i < w; i++) + { + for (int j = 0; j < h; j++) + { + int x = uv_x + i; + int y = uv_y + j; + + if (hasPixel(pixels, x, y)) + { + generateNeighbors(pixels, extrusion, i, j, x, y, d, w, h); + } + } + } + + extrusion.flush(); + + cache.put(texture, extrusion); + + return extrusion; + } + + private static void generateNeighbors(BufferedImage pixels, CachedExtrusion extrusion, int i, int j, int x, int y, float d, float w, float h) + { + float u = (x + 0.5F) / w; + float v = (y + 0.5F) / h; + + if (!hasPixel(pixels, x - 1, y) || i == 0) + { + fillTexturedNormalQuad(extrusion, + i / w - 0.5F, -(j + 1) / h + 0.5F, -d, + i / w - 0.5F, -j / h + 0.5F, -d, + i / w - 0.5F, -j / h + 0.5F, d, + i / w - 0.5F, -(j + 1) / h + 0.5F, d, + u, v, u, v, + -1F, 0F, 0F + ); + } + + if (!hasPixel(pixels, x + 1, y) || i == 15) + { + fillTexturedNormalQuad(extrusion, + (i + 1) / w - 0.5F, -(j + 1) / h + 0.5F, d, + (i + 1) / w - 0.5F, -j / h + 0.5F, d, + (i + 1) / w - 0.5F, -j / h + 0.5F, -d, + (i + 1) / w - 0.5F, -(j + 1) / h + 0.5F, -d, + u, v, u, v, + 1F, 0F, 0F + ); + } + + if (!hasPixel(pixels, x, y - 1) || j == 0) + { + fillTexturedNormalQuad(extrusion, + (i + 1) / w - 0.5F, -j / h + 0.5F, d, + i / w - 0.5F, -j / h + 0.5F, d, + i / w - 0.5F, -j / h + 0.5F, -d, + (i + 1) / w - 0.5F, -j / h + 0.5F, -d, + u, v, u, v, + 0F, 1F, 0F + ); + } + + if (!hasPixel(pixels, x, y + 1) || j == 15) + { + fillTexturedNormalQuad(extrusion, + (i + 1) / w - 0.5F, -(j + 1) / h + 0.5F, -d, + i / w - 0.5F, -(j + 1) / h + 0.5F, -d, + i / w - 0.5F, -(j + 1) / h + 0.5F, d, + (i + 1) / w - 0.5F, -(j + 1) / h + 0.5F, d, + u, v, u, v, + 0F, -1F, 0F + ); + } + } + + private static boolean hasPixel(BufferedImage pixels, int x, int y) + { + if (x < 0 || x >= pixels.getWidth() || y < 0 || y >= pixels.getHeight()) + { + return false; + } + + Color pixel = new Color().set(pixels.getRGB(x, y)); + + return pixel != null && pixel.a >= 1; + } + + /** + * Fill a quad for vertex-normal-uv-rgba. Points should + * be supplied in this order: + * + * 3 -------> 4 + * ^ + * | + * | + * 2 <------- 1 + * + * I.e. bottom left, bottom right, top left, top right, where left is -X and right is +X, + * in case of a quad on fixed on Z axis. + */ + public static void fillTexturedNormalQuad(CachedExtrusion extrusion, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4, float u1, float v1, float u2, float v2, float nx, float ny, float nz) + { + /* 1 - BL, 2 - BR, 3 - TR, 4 - TL */ + extrusion.addVertex(x2, y2, z2, nx, ny, nz, u1, v2); + extrusion.addVertex(x1, y1, z1, nx, ny, nz, u2, v2); + extrusion.addVertex(x4, y4, z4, nx, ny, nz, u2, v1); + + extrusion.addVertex(x2, y2, z2, nx, ny, nz, u1, v2); + extrusion.addVertex(x4, y4, z4, nx, ny, nz, u2, v1); + extrusion.addVertex(x3, y3, z3, nx, ny, nz, u1, v1); + } +} \ No newline at end of file From c18b3af10bb168cbc9ae25f77ba0cf6669a4698c Mon Sep 17 00:00:00 2001 From: McHorse Date: Fri, 30 Jun 2023 16:02:18 +0100 Subject: [PATCH 41/51] Ported @OtakuGamer's dropped item animation option --- .../editors/panels/GuiItemPanel.java | 7 +++-- .../vanilla_pack/morphs/ItemMorph.java | 26 +++++++++++++++++-- .../assets/metamorph/lang/en_US.lang | 1 + 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java index bad94405..78b11bea 100644 --- a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java +++ b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java @@ -8,7 +8,6 @@ import mchorse.mclib.client.gui.framework.elements.input.GuiTexturePicker; import mchorse.mclib.client.gui.utils.Elements; import mchorse.mclib.client.gui.utils.keys.IKey; -import mchorse.mclib.utils.Direction; import mchorse.mclib.utils.resources.RLUtils; import mchorse.metamorph.client.gui.editor.GuiAbstractMorph; import mchorse.metamorph.client.gui.editor.GuiMorphPanel; @@ -22,9 +21,11 @@ public class GuiItemPanel extends GuiMorphPanel> { public GuiSlotElement slot; + public GuiToggleElement lighting; public GuiCirculateElement transform; public GuiButtonElement texture; + public GuiToggleElement animation; public GuiTexturePicker picker; @@ -34,6 +35,7 @@ public GuiItemPanel(Minecraft mc, GuiAbstractMorph editor) this.slot = new GuiSlotElement(mc, 0, (stack) -> this.morph.setStack(stack)); this.lighting = new GuiToggleElement(mc, IKey.lang("metamorph.gui.label.lighting"), (b) -> this.morph.lighting = b.isToggled()); + this.animation = new GuiToggleElement(mc, IKey.lang("metamorph.gui.item.animation"), (b) -> this.morph.animation = b.isToggled()); this.slot.flex().relative(this).x(0.5F, 0).y(1, -10).wh(32, 32).anchor(0.5F, 1); @@ -61,7 +63,7 @@ public GuiItemPanel(Minecraft mc, GuiAbstractMorph editor) this.picker = new GuiTexturePicker(mc, (rl) -> this.morph.texture = RLUtils.clone(rl)); this.picker.flex().relative(this).wh(1F, 1F); - GuiElement column = Elements.column(mc, 5, this.lighting, this.transform, this.texture); + GuiElement column = Elements.column(mc, 5, this.lighting, this.transform, this.texture, this.animation); column.flex().relative(this).xy(10, 10).w(110); @@ -78,5 +80,6 @@ public void fillData(ItemMorph morph) this.slot.setStack(morph.getStack()); this.lighting.toggled(morph.lighting); this.transform.setValue(type.ordinal()); + this.animation.toggled(morph.animation); } } \ No newline at end of file diff --git a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java index c55ff2ed..765d2fe5 100644 --- a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java +++ b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java @@ -21,10 +21,10 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import org.lwjgl.opengl.OpenGLException; import java.util.Objects; @@ -36,6 +36,7 @@ public class ItemMorph extends ItemStackMorph public ItemStack stack = new ItemStack(Items.DIAMOND_HOE, 1); public String transform = ""; public ResourceLocation texture; + public boolean animation; @SideOnly(Side.CLIENT) public static BiMap getTransformTypes() @@ -78,7 +79,7 @@ public ItemStack getStack() @SideOnly(Side.CLIENT) public ItemCameraTransforms.TransformType getTransformType() { - ItemCameraTransforms.TransformType transformType = transformTypes.get(this.transform); + ItemCameraTransforms.TransformType transformType = getTransformTypes().get(this.transform); return transformType == null ? ItemCameraTransforms.TransformType.NONE : transformType; } @@ -154,6 +155,15 @@ public void render(EntityLivingBase entity, double x, double y, double z, float model = ForgeHooksClient.handleCameraTransforms(model, transform, false); } + if (this.animation) + { + long ticks = entity.world.getTotalWorldTime(); + float bobbing = MathHelper.sin((ticks + partialTicks) / 10F) * 0.1F + 0.1F; + + GlStateManager.translate(0F, bobbing, 0F); + GlStateManager.rotate((entity.ticksExisted + partialTicks) * 2F, 0F, 1F, 0F); + } + if (this.texture != null) { CachedExtrusion extrusion = ItemExtruder.extrude(this.texture); @@ -188,6 +198,7 @@ public boolean equals(Object obj) result = result && ItemStack.areItemStacksEqualUsingNBTShareTag(this.stack, item.stack); result = result && this.transform.equals(item.transform); result = result && Objects.equals(this.texture, item.texture); + result = result && this.animation == item.animation; } return result; @@ -211,6 +222,7 @@ public void copy(AbstractMorph from) this.stack = item.stack.copy(); this.transform = item.transform; this.texture = item.texture; + this.animation = item.animation; } } @@ -242,6 +254,11 @@ public void toNBT(NBTTagCompound tag) { tag.setString("Texture", this.texture.toString()); } + + if (this.animation) + { + tag.setBoolean("Animation", this.animation); + } } @Override @@ -260,5 +277,10 @@ public void fromNBT(NBTTagCompound tag) { this.texture = RLUtils.create(tag.getString("Texture")); } + + if (tag.hasKey("Animation")) + { + this.animation = tag.getBoolean("Animation"); + } } } \ No newline at end of file diff --git a/src/main/resources/assets/metamorph/lang/en_US.lang b/src/main/resources/assets/metamorph/lang/en_US.lang index 803865e9..977edfeb 100644 --- a/src/main/resources/assets/metamorph/lang/en_US.lang +++ b/src/main/resources/assets/metamorph/lang/en_US.lang @@ -136,6 +136,7 @@ metamorph.gui.label.lighting_tooltip=When disabled, Minecraft's lightmap won't b metamorph.gui.label.background=Background metamorph.gui.label.billboard=Look at player +metamorph.gui.item.animation=Animation metamorph.gui.item.transform.none=None metamorph.gui.item.transform.third_person_left_hand=Left hand (3rd) metamorph.gui.item.transform.third_person_right_hand=Right hand (3rd) From 15d1bd9aa99139cc48d7fc4311f550a60a75a0a4 Mon Sep 17 00:00:00 2001 From: McHorse Date: Fri, 30 Jun 2023 20:53:38 +0100 Subject: [PATCH 42/51] Implement equipment slot feature for item morph --- .../editors/panels/GuiItemPanel.java | 21 +++++++--- .../vanilla_pack/morphs/ItemMorph.java | 42 ++++++++++++++++++- .../assets/metamorph/lang/en_US.lang | 7 ++++ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java index 78b11bea..03827f0f 100644 --- a/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java +++ b/src/main/java/mchorse/vanilla_pack/editors/panels/GuiItemPanel.java @@ -14,6 +14,7 @@ import mchorse.vanilla_pack.morphs.ItemMorph; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -26,6 +27,8 @@ public class GuiItemPanel extends GuiMorphPanel editor) this.slot = new GuiSlotElement(mc, 0, (stack) -> this.morph.setStack(stack)); this.lighting = new GuiToggleElement(mc, IKey.lang("metamorph.gui.label.lighting"), (b) -> this.morph.lighting = b.isToggled()); - this.animation = new GuiToggleElement(mc, IKey.lang("metamorph.gui.item.animation"), (b) -> this.morph.animation = b.isToggled()); - - this.slot.flex().relative(this).x(0.5F, 0).y(1, -10).wh(32, 32).anchor(0.5F, 1); - this.transform = new GuiCirculateElement(mc, (b) -> { ItemCameraTransforms.TransformType type = ItemCameraTransforms.TransformType.values()[b.getValue()]; this.morph.transform = ItemMorph.getTransformTypes().inverse().get(type); }); + this.animation = new GuiToggleElement(mc, IKey.lang("metamorph.gui.item.animation"), (b) -> this.morph.animation = b.isToggled()); + this.itemFromEquipment = new GuiToggleElement(mc, IKey.lang("metamorph.gui.item.item_from_equipment"), (b) -> this.morph.itemFromEquipment = b.isToggled()); + this.equipmentSlot = new GuiCirculateElement(mc, (b) -> this.morph.equipmentSlot = EntityEquipmentSlot.values()[b.getValue()]); + + this.slot.flex().relative(this).x(0.5F, 0).y(1, -10).wh(32, 32).anchor(0.5F, 1); for (ItemCameraTransforms.TransformType transform : ItemCameraTransforms.TransformType.values()) { @@ -53,6 +57,11 @@ public GuiItemPanel(Minecraft mc, GuiAbstractMorph editor) this.transform.addLabel(IKey.lang("metamorph.gui.item.transform." + key)); } + for (EntityEquipmentSlot slot : EntityEquipmentSlot.values()) + { + this.equipmentSlot.addLabel(IKey.lang("metamorph.gui.item.equipment_slot." + slot.getName())); + } + this.texture = new GuiButtonElement(mc, IKey.lang("metamorph.gui.editor.texture"), (b) -> { this.picker.refresh(); @@ -63,7 +72,7 @@ public GuiItemPanel(Minecraft mc, GuiAbstractMorph editor) this.picker = new GuiTexturePicker(mc, (rl) -> this.morph.texture = RLUtils.clone(rl)); this.picker.flex().relative(this).wh(1F, 1F); - GuiElement column = Elements.column(mc, 5, this.lighting, this.transform, this.texture, this.animation); + GuiElement column = Elements.column(mc, 5, this.lighting, this.transform, this.texture, this.animation, this.itemFromEquipment.marginTop(12), this.equipmentSlot); column.flex().relative(this).xy(10, 10).w(110); @@ -81,5 +90,7 @@ public void fillData(ItemMorph morph) this.lighting.toggled(morph.lighting); this.transform.setValue(type.ordinal()); this.animation.toggled(morph.animation); + this.itemFromEquipment.toggled(morph.itemFromEquipment); + this.equipmentSlot.setValue(morph.equipmentSlot.ordinal()); } } \ No newline at end of file diff --git a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java index 765d2fe5..10ef001d 100644 --- a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java +++ b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java @@ -18,6 +18,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; +import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; @@ -37,6 +38,8 @@ public class ItemMorph extends ItemStackMorph public String transform = ""; public ResourceLocation texture; public boolean animation; + public boolean itemFromEquipment; + public EntityEquipmentSlot equipmentSlot = EntityEquipmentSlot.MAINHAND; @SideOnly(Side.CLIENT) public static BiMap getTransformTypes() @@ -64,6 +67,16 @@ public ItemMorph() this.name = "item"; } + private ItemStack getStackForRender(EntityLivingBase entity) + { + if (this.itemFromEquipment) + { + return entity.getItemStackFromSlot(this.equipmentSlot); + } + + return this.stack; + } + @Override public void setStack(ItemStack stack) { @@ -146,7 +159,8 @@ public void render(EntityLivingBase entity, double x, double y, double z, float Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); RenderItem render = Minecraft.getMinecraft().getRenderItem(); - IBakedModel model = render.getItemModelWithOverrides(this.stack, entity.world, entity); + ItemStack stack = this.getStackForRender(entity); + IBakedModel model = render.getItemModelWithOverrides(stack, entity.world, entity); ItemCameraTransforms.TransformType transform = this.getTransformType(); @@ -175,7 +189,7 @@ public void render(EntityLivingBase entity, double x, double y, double z, float } else { - render.renderItem(this.stack, model); + render.renderItem(stack, model); } GlStateManager.popMatrix(); @@ -199,6 +213,8 @@ public boolean equals(Object obj) result = result && this.transform.equals(item.transform); result = result && Objects.equals(this.texture, item.texture); result = result && this.animation == item.animation; + result = result && this.itemFromEquipment == item.itemFromEquipment; + result = result && this.equipmentSlot == item.equipmentSlot; } return result; @@ -223,6 +239,8 @@ public void copy(AbstractMorph from) this.transform = item.transform; this.texture = item.texture; this.animation = item.animation; + this.itemFromEquipment = item.itemFromEquipment; + this.equipmentSlot = item.equipmentSlot; } } @@ -259,6 +277,16 @@ public void toNBT(NBTTagCompound tag) { tag.setBoolean("Animation", this.animation); } + + if (this.itemFromEquipment) + { + tag.setBoolean("ItemFromEquipment", this.itemFromEquipment); + } + + if (this.equipmentSlot != EntityEquipmentSlot.MAINHAND) + { + tag.setString("EquipmentSlot", this.equipmentSlot.getName()); + } } @Override @@ -282,5 +310,15 @@ public void fromNBT(NBTTagCompound tag) { this.animation = tag.getBoolean("Animation"); } + + if (tag.hasKey("ItemFromEquipment")) + { + this.itemFromEquipment = tag.getBoolean("ItemFromEquipment"); + } + + if (tag.hasKey("EquipmentSlot")) + { + this.equipmentSlot = EntityEquipmentSlot.fromString(tag.getString("EquipmentSlot")); + } } } \ No newline at end of file diff --git a/src/main/resources/assets/metamorph/lang/en_US.lang b/src/main/resources/assets/metamorph/lang/en_US.lang index 977edfeb..1336bded 100644 --- a/src/main/resources/assets/metamorph/lang/en_US.lang +++ b/src/main/resources/assets/metamorph/lang/en_US.lang @@ -137,6 +137,7 @@ metamorph.gui.label.background=Background metamorph.gui.label.billboard=Look at player metamorph.gui.item.animation=Animation +metamorph.gui.item.item_from_equipment=From equipment metamorph.gui.item.transform.none=None metamorph.gui.item.transform.third_person_left_hand=Left hand (3rd) metamorph.gui.item.transform.third_person_right_hand=Right hand (3rd) @@ -146,6 +147,12 @@ metamorph.gui.item.transform.head=On head metamorph.gui.item.transform.gui=Inventory metamorph.gui.item.transform.ground=On ground metamorph.gui.item.transform.fixed=Item frame +metamorph.gui.item.equipment_slot.mainhand=Main hand +metamorph.gui.item.equipment_slot.offhand=Off hand +metamorph.gui.item.equipment_slot.feet=Feet +metamorph.gui.item.equipment_slot.legs=Legs +metamorph.gui.item.equipment_slot.chest=Chest +metamorph.gui.item.equipment_slot.head=Head metamorph.gui.edit=Edit metamorph.gui.panels.nbt_data=NBT data From 5311d8003a19c257649495b94fb526e8b7c10e76 Mon Sep 17 00:00:00 2001 From: McHorse Date: Sat, 1 Jul 2023 09:11:06 +0100 Subject: [PATCH 43/51] Use player's equipment when previewing item morph's equipment item stack --- src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java index 10ef001d..74fefb1e 100644 --- a/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java +++ b/src/main/java/mchorse/vanilla_pack/morphs/ItemMorph.java @@ -2,6 +2,7 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; +import mchorse.mclib.client.gui.framework.elements.GuiModelRenderer; import mchorse.mclib.client.gui.framework.elements.utils.GuiInventoryElement; import mchorse.mclib.utils.resources.RLUtils; import mchorse.metamorph.api.morphs.AbstractMorph; @@ -67,10 +68,16 @@ public ItemMorph() this.name = "item"; } + @SideOnly(Side.CLIENT) private ItemStack getStackForRender(EntityLivingBase entity) { if (this.itemFromEquipment) { + if (GuiModelRenderer.isRendering()) + { + entity = Minecraft.getMinecraft().player; + } + return entity.getItemStackFromSlot(this.equipmentSlot); } From 5a6b272a0bdfb1e0491dbef9af46f7e916000591 Mon Sep 17 00:00:00 2001 From: asanetargoss Date: Sat, 29 Aug 2020 17:18:57 -0700 Subject: [PATCH 44/51] Implement sparse morph settings, compute health/speed when not provided --- .../mchorse/metamorph/api/MorphHandler.java | 2 +- .../mchorse/metamorph/api/MorphManager.java | 14 +- .../mchorse/metamorph/api/MorphSettings.java | 339 +++++++++++++----- .../api/json/MorphSettingsAdapter.java | 27 +- .../metamorph/api/morphs/AbstractMorph.java | 142 +++++++- .../metamorph/api/morphs/EntityMorph.java | 78 +++- .../capabilities/morphing/Morphing.java | 4 +- .../metamorph/client/NetworkHandler.java | 2 +- .../server/survival/ServerHandlerAction.java | 2 +- 9 files changed, 473 insertions(+), 137 deletions(-) diff --git a/src/main/java/mchorse/metamorph/api/MorphHandler.java b/src/main/java/mchorse/metamorph/api/MorphHandler.java index 0c7eb641..c9e30cb0 100644 --- a/src/main/java/mchorse/metamorph/api/MorphHandler.java +++ b/src/main/java/mchorse/metamorph/api/MorphHandler.java @@ -301,7 +301,7 @@ public void onLivingSetAttackTarget(LivingSetAttackTargetEvent event) AbstractMorph currentMorph = morphing.getCurrentMorph(); - if (morphing.getCurrentMorph().settings.hostile && source.getAttackingEntity() != target && + if (morphing.getCurrentMorph().getSettings().hostile && source.getAttackingEntity() != target && !(currentMorph instanceof mchorse.metamorph.api.morphs.EntityMorph && ((mchorse.metamorph.api.morphs.EntityMorph) currentMorph).getEntity() == source.getAttackingEntity())) { if (source instanceof EntityLiving) diff --git a/src/main/java/mchorse/metamorph/api/MorphManager.java b/src/main/java/mchorse/metamorph/api/MorphManager.java index 0f7bb7f7..a1d7387a 100644 --- a/src/main/java/mchorse/metamorph/api/MorphManager.java +++ b/src/main/java/mchorse/metamorph/api/MorphManager.java @@ -56,7 +56,7 @@ public class MorphManager public List factories = new ArrayList(); /** - * Active morph settings + * Active morph settings from JSON config */ public Map activeSettings = new HashMap(); @@ -228,7 +228,7 @@ public AbstractMorph morphFromNBT(NBTTagCompound tag) if (morph != null) { this.applySettings(morph); - + return morph; } } @@ -242,15 +242,7 @@ public AbstractMorph morphFromNBT(NBTTagCompound tag) */ public void applySettings(AbstractMorph morph) { - if (morph.settings != MorphSettings.DEFAULT) - { - return; - } - - if (this.activeSettings.containsKey(morph.name)) - { - morph.settings = this.activeSettings.get(morph.name); - } + morph.setActiveSettings(this.activeSettings.get(morph.name)); } /** diff --git a/src/main/java/mchorse/metamorph/api/MorphSettings.java b/src/main/java/mchorse/metamorph/api/MorphSettings.java index 684fa643..e361c21c 100644 --- a/src/main/java/mchorse/metamorph/api/MorphSettings.java +++ b/src/main/java/mchorse/metamorph/api/MorphSettings.java @@ -20,58 +20,81 @@ * * An instance of this class is responsible for storing information about * morph's configurable settings. + * + * For well-defined defaults, use {@link #DEFAULT_MORPHED} or {@link #DEFAULT}. */ public class MorphSettings { /** - * Empty morph settings which doesn't have any attributes + * "Safe" settings, equivalent to not being morphed */ public static final MorphSettings DEFAULT = new MorphSettings(); + + static + { + DEFAULT.hostile = false; + DEFAULT.hands = true; + DEFAULT.updates = false; + } + + /** + * Default settings to fall back on for most morphs. + */ + public static final MorphSettings DEFAULT_MORPHED = new MorphSettings(); /** * Abilities that are going to be applied on a morph */ public List abilities = new ArrayList(); + public boolean hasAbilities = true; /** * Attack that is going to be used on a morph */ - public IAttackAbility attack; + public IAttackAbility attack = null; + public boolean hasAttack = true; /** * Action that is going to be used on a morph */ - public IAction action; + public IAction action = null; + public boolean hasAction = true; /** * Health units which are going to be applied */ public int health = 20; + public boolean hasHealth = true; /** * Speed which is going to be applied */ public float speed = 0.1F; + public boolean hasSpeed = true; /** * Hostile flag which is going to be applied */ - public boolean hostile; + public boolean hostile = true; + public boolean hasHostile = true; /** * Does client tries render hands for this morph */ - public boolean hands; + public boolean hands = false; + public boolean hasHands = true; /** * Does this morph updates itself */ public boolean updates = true; - + public boolean hasUpdates = true; + /** * Whether to render this morph in shadow pass */ public int shadowOption = 0; + public boolean hasShadowOption = true; @Override public boolean equals(Object obj) @@ -80,14 +103,14 @@ public boolean equals(Object obj) { MorphSettings settings = (MorphSettings) obj; - return this.abilities.equals(settings.abilities) && - Objects.equals(this.action, settings.action) && - Objects.equals(this.attack, settings.attack) && - this.health == settings.health && - this.speed == settings.speed && - this.hostile == settings.hostile && - this.updates == settings.updates && - this.shadowOption == settings.shadowOption; + return (this.hasAbilities == settings.hasAbilities && (this.abilities.equals(settings.abilities) || this.hasAbilities == false)) && + (this.hasAction == settings.hasAction && (Objects.equals(this.action, settings.action) || this.hasAction == false)) && + (this.hasAttack == settings.hasAttack && (Objects.equals(this.attack, settings.attack) || this.hasAttack == false)) && + (this.hasHealth == settings.hasHealth && (this.health == settings.health || this.hasHealth == false)) && + (this.hasSpeed == settings.hasSpeed && (this.speed == settings.speed || this.hasSpeed == false)) && + (this.hasHostile == settings.hasHostile && (this.hostile == settings.hostile || this.hasHostile == false)) && + (this.hasUpdates == settings.hasUpdates && (this.updates == settings.updates || this.hasUpdates == false)) && + (this.hasUpdates == settings.hasShadowOption && (this.shadowOption == settings.shadowOption || this.hasShadowOption == false)); } return super.equals(obj); @@ -109,56 +132,147 @@ public void copy(MorphSettings setting) { this.abilities.clear(); this.abilities.addAll(setting.abilities); + this.hasAbilities = setting.hasAbilities; this.action = setting.action; + this.hasAction = setting.hasAction; this.attack = setting.attack; + this.hasAttack = setting.hasAttack; this.health = setting.health; + this.hasHealth = setting.hasHealth; this.speed = setting.speed; + this.hasSpeed = setting.hasSpeed; this.hostile = setting.hostile; + this.hasHostile = setting.hasHostile; this.hands = setting.hands; + this.hasHands = setting.hasHands; this.updates = setting.updates; + this.hasUpdates = setting.hasUpdates; - this.shadowOption = setting.shadowOption; + this.shadowOption = setting.shadowOption; + this.hasShadowOption = setting.hasShadowOption; } /** - * Write morph settings to the network buffer + * Apply any additional settings to this one as long as they are not null/empty */ - public void toBytes(ByteBuf buf) + public void applyOverrides(MorphSettings setting) { - buf.writeInt(this.abilities.size()); - - for (IAbility ability : this.abilities) + if (setting.hasAbilities) { - String string = getKey(MorphManager.INSTANCE.abilities, ability); - - ByteBufUtils.writeUTF8String(buf, string == null ? "" : string); + this.abilities.clear(); + this.abilities.addAll(setting.abilities); + this.hasAbilities = true; } - String action = getKey(MorphManager.INSTANCE.actions, this.action); - String attack = getKey(MorphManager.INSTANCE.attacks, this.attack); - - buf.writeBoolean(action != null); + if (setting.hasAction) + { + this.action = setting.action; + this.hasAction = true; + } + if (setting.hasAttack) + { + this.attack = setting.attack; + this.hasAttack = true; + } - if (action != null) + if (setting.hasHealth) + { + this.health = setting.health; + this.hasHealth = true; + } + if (setting.hasSpeed) + { + this.speed = setting.speed; + this.hasSpeed = true; + } + if (setting.hasHostile) + { + this.hostile = setting.hostile; + this.hasHostile = true; + } + if (setting.hasHands) { - ByteBufUtils.writeUTF8String(buf, action); + this.hands = setting.hands; + this.hasHands = true; } + if (setting.hasUpdates) + { + this.updates = setting.updates; + this.hasUpdates = true; + } + } - buf.writeBoolean(attack != null); + /** + * Write morph settings to the network buffer + */ + public void toBytes(ByteBuf buf) + { + buf.writeBoolean(this.hasAbilities); + if (this.hasAbilities) + { + buf.writeInt(this.abilities.size()); + + for (IAbility ability : this.abilities) + { + String string = getKey(MorphManager.INSTANCE.abilities, ability); + + ByteBufUtils.writeUTF8String(buf, string == null ? "" : string); + } + } - if (attack != null) + buf.writeBoolean(this.hasAction); + if (this.hasAction) { - ByteBufUtils.writeUTF8String(buf, attack); + String action = getKey(MorphManager.INSTANCE.actions, this.action); + buf.writeBoolean(action != null); + if (action != null) + { + ByteBufUtils.writeUTF8String(buf, action); + } } - buf.writeInt(this.health); - buf.writeFloat(this.speed); - buf.writeBoolean(this.hostile); - buf.writeBoolean(this.hands); - buf.writeBoolean(this.updates); - buf.writeInt(this.shadowOption); + buf.writeBoolean(this.hasAttack); + if (this.hasAttack) { + String attack = getKey(MorphManager.INSTANCE.attacks, this.attack); + buf.writeBoolean(attack != null); + if (attack != null) + { + ByteBufUtils.writeUTF8String(buf, attack); + } + } + + buf.writeBoolean(this.hasHealth); + if (this.hasHealth) + { + buf.writeInt(this.health); + } + buf.writeBoolean(this.hasSpeed); + if (this.hasSpeed) + { + buf.writeFloat(this.speed); + } + buf.writeBoolean(this.hasHostile); + if (this.hasHostile) + { + buf.writeBoolean(this.hostile); + } + buf.writeBoolean(this.hasHands); + if (this.hasHands) + { + buf.writeBoolean(this.hands); + } + buf.writeBoolean(this.hasUpdates); + if (this.hasUpdates) + { + buf.writeBoolean(this.updates); + } + buf.writeBoolean(this.hasShadowOption); + if (this.hasShadowOption) + { + buf.writeInt(this.shadowOption); + } } /** @@ -166,38 +280,86 @@ public void toBytes(ByteBuf buf) */ public void fromBytes(ByteBuf buf) { - this.abilities.clear(); - - for (int i = 0, c = buf.readInt(); i < c; i++) + this.hasAbilities = buf.readBoolean(); + if (this.hasAbilities) { - IAbility ability = MorphManager.INSTANCE.abilities.get(ByteBufUtils.readUTF8String(buf)); - - if (ability != null) + List abilities = new ArrayList(); + for (int i = 0, c = buf.readInt(); i < c; i++) { - this.abilities.add(ability); + IAbility ability = MorphManager.INSTANCE.abilities.get(ByteBufUtils.readUTF8String(buf)); + + if (ability != null) + { + abilities.add(ability); + } } + this.abilities = abilities; } - if (buf.readBoolean()) + this.hasAction = buf.readBoolean(); + if (this.hasAction) { - String action = ByteBufUtils.readUTF8String(buf); - - this.action = MorphManager.INSTANCE.actions.get(action); + if (buf.readBoolean()) + { + String action = ByteBufUtils.readUTF8String(buf); + this.action = MorphManager.INSTANCE.actions.get(action); + } + else + { + this.action = null; + } } - if (buf.readBoolean()) + this.hasAttack = buf.readBoolean(); + if (this.hasAttack) { - String attack = ByteBufUtils.readUTF8String(buf); - - this.attack = MorphManager.INSTANCE.attacks.get(attack); + if (buf.readBoolean()) + { + String attack = ByteBufUtils.readUTF8String(buf); + this.attack = MorphManager.INSTANCE.attacks.get(attack); + } + else + { + this.attack = null; + } + } + + this.hasHealth = buf.readBoolean(); + if (this.hasHealth) + { + this.health = buf.readInt(); + } + + this.hasSpeed = buf.readBoolean(); + if (this.hasSpeed) + { + this.speed = buf.readFloat(); + } + + this.hasHostile = buf.readBoolean(); + if (this.hasHostile) + { + this.hostile = buf.readBoolean(); + } + + this.hasHands = buf.readBoolean(); + if (this.hasHands) + { + this.hands = buf.readBoolean(); + } + + this.hasUpdates = buf.readBoolean(); + if (this.hasUpdates) + { + this.updates = buf.readBoolean(); + } + + this.hasShadowOption = buf.readBoolean(); + if (this.hasShadowOption) + { + this.shadowOption = buf.readInt(); } - this.health = buf.readInt(); - this.speed = buf.readFloat(); - this.hostile = buf.readBoolean(); - this.hands = buf.readBoolean(); - this.updates = buf.readBoolean(); - this.shadowOption = buf.readInt(); } /** @@ -205,7 +367,7 @@ public void fromBytes(ByteBuf buf) */ public void toNBT(NBTTagCompound tag) { - if (!this.abilities.isEmpty()) + if (this.hasAbilities) { NBTTagList list = new NBTTagList(); @@ -217,42 +379,46 @@ public void toNBT(NBTTagCompound tag) tag.setTag("Abilities", list); } - if (this.attack != null) + if (this.hasAttack) { - tag.setString("Attack", getKey(MorphManager.INSTANCE.attacks, this.attack)); + String attackKey = getKey(MorphManager.INSTANCE.attacks, this.attack); + if (attackKey == null) { attackKey = "null"; } + tag.setString("Attack", attackKey); } - if (this.action != null) + if (this.hasAction) { - tag.setString("Action", getKey(MorphManager.INSTANCE.actions, this.action)); + String actionKey = getKey(MorphManager.INSTANCE.actions, this.action); + if (actionKey == null) { actionKey = "null"; } + tag.setString("Action", actionKey); } - if (this.health != 20) + if (this.hasHealth) { tag.setInteger("HP", this.health); } - if (this.speed != 0.1F) + if (this.hasSpeed) { tag.setFloat("Speed", this.speed); } - if (this.hostile) + if (this.hasHostile) { tag.setBoolean("Hostile", this.hostile); } - if (this.hands) + if (this.hasHands) { tag.setBoolean("Hands", this.hands); } - if (!this.updates) + if (this.hasUpdates) { tag.setBoolean("Updates", this.updates); } - - if (this.shadowOption != 0) + + if (this.hasShadowOption) { tag.setInteger("ShadowOption", this.shadowOption); } @@ -263,9 +429,10 @@ public void toNBT(NBTTagCompound tag) */ public void fromNBT(NBTTagCompound tag) { - if (tag.hasKey("Abilities")) + this.hasAbilities = tag.hasKey("Abilities"); + if (this.hasAbilities) { - NBTTagList list = tag.getTagList("Abilities", Constants.NBT.TAG_STRING); + NBTTagList list = tag.getTagList("Abilities", Constants.NBT.TAG_STRING); this.abilities.clear(); @@ -280,42 +447,50 @@ public void fromNBT(NBTTagCompound tag) } } - if (tag.hasKey("Attack")) + this.hasAttack = tag.hasKey("Attack"); + if (this.hasAttack) { this.attack = MorphManager.INSTANCE.attacks.get(tag.getString("Attack")); } - if (tag.hasKey("Action")) + this.hasAction = tag.hasKey("Action"); + if (this.hasAction) { this.action = MorphManager.INSTANCE.actions.get(tag.getString("Action")); } - if (tag.hasKey("HP")) + this.hasHealth = tag.hasKey("HP"); + if (this.hasHealth) { this.health = tag.getInteger("HP"); } - if (tag.hasKey("Speed")) + this.hasSpeed = tag.hasKey("Speed"); + if (this.hasSpeed) { this.speed = tag.getFloat("Speed"); } - if (tag.hasKey("Hostile")) + this.hasHostile = tag.hasKey("Hostile"); + if (this.hasHostile) { this.hostile = tag.getBoolean("Hostile"); } - if (tag.hasKey("Hands")) + this.hasHands = tag.hasKey("Hands"); + if (this.hasHands) { this.hands = tag.getBoolean("Hands"); } - if (tag.hasKey("Updates")) + this.hasUpdates = tag.hasKey("Updates"); + if (this.hasUpdates) { this.updates = tag.getBoolean("Updates"); } - - if (tag.hasKey("ShadowOption")) + + this.hasShadowOption = tag.hasKey("ShadowOption"); + if (this.hasShadowOption) { this.shadowOption = tag.getInteger("ShadowOption"); } diff --git a/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java b/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java index 3010ad2c..255e203d 100644 --- a/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java +++ b/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java @@ -29,27 +29,32 @@ public MorphSettings deserialize(JsonElement json, Type typeOfT, JsonDeserializa MorphSettings morph = new MorphSettings(); MorphManager manager = MorphManager.INSTANCE; - if (object.has("health") && object.get("health").isJsonPrimitive()) + morph.hasHealth = object.has("health") && object.get("health").isJsonPrimitive(); + if (morph.hasHealth) { morph.health = object.get("health").getAsInt(); } - if (object.has("speed") && object.get("speed").isJsonPrimitive()) + morph.hasSpeed = object.has("speed") && object.get("speed").isJsonPrimitive(); + if (morph.hasSpeed) { morph.speed = object.get("speed").getAsFloat(); } - if (object.has("hostile") && object.get("hostile").isJsonPrimitive()) + morph.hasHostile = object.has("hostile") && object.get("hostile").isJsonPrimitive(); + if (morph.hasHostile) { morph.hostile = object.get("hostile").getAsBoolean(); } - if (object.has("hands") && object.get("hands").isJsonPrimitive()) + morph.hasHands = object.has("hands") && object.get("hands").isJsonPrimitive(); + if (morph.hasHands) { morph.hands = object.get("hands").getAsBoolean(); } - if (object.has("abilities") && object.get("abilities").isJsonArray()) + morph.hasAbilities = object.has("abilities") && object.get("abilities").isJsonArray(); + if (morph.hasAbilities) { morph.abilities.clear(); @@ -69,22 +74,26 @@ public MorphSettings deserialize(JsonElement json, Type typeOfT, JsonDeserializa } } - if (object.has("action") && object.get("action").isJsonPrimitive()) + morph.hasAction = object.has("action") && object.get("action").isJsonPrimitive(); + if (morph.hasAction) { morph.action = manager.actions.get(object.get("action").getAsString()); } - if (object.has("attack") && object.get("attack").isJsonPrimitive()) + morph.hasAttack = object.has("attack") && object.get("attack").isJsonPrimitive(); + if (morph.hasAttack) { morph.attack = manager.attacks.get(object.get("attack").getAsString()); } - if (object.has("updates") && object.get("updates").isJsonPrimitive()) + morph.hasUpdates = object.has("updates") && object.get("updates").isJsonPrimitive(); + if (morph.hasUpdates) { morph.updates = object.get("updates").getAsBoolean(); } - if (object.has("shadow_option") && object.get("shadow_option").isJsonPrimitive()) + morph.hasShadowOption = object.has("shadow_option") && object.get("shadow_option").isJsonPrimitive(); + if (morph.hasShadowOption) { morph.shadowOption = object.get("shadow_option").getAsInt(); } diff --git a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java index b2235846..99cefcd3 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java @@ -67,12 +67,100 @@ public abstract class AbstractMorph */ public int keybind = -1; - /* Abilities */ + /* Morph Settings */ /** - * Morph settings + * The authoritative settings for the morph. */ - public MorphSettings settings = MorphSettings.DEFAULT; + @Deprecated + public MorphSettings settings = MorphSettings.DEFAULT.copy(); + + /** + * If this is false, {@link #settings} will be initialized + * as needed. If this is true, {@link #settings} will remain + * at whatever value it was set to in {@link #forceSettings(MorphSettings)} + */ + protected boolean forcedSettings = false; + + protected boolean needSettingsUpdate = false; + + /** + * The highest priority settings, defined through + * configuration. + */ + protected MorphSettings activeSettings = null; + + /** + * This is called to initialize settings for morphs, if + * settings are out-of-date. + */ + public void initializeSettings() + { + if (!this.needSettingsUpdate) + { + return; + } + + this.settings = MorphSettings.DEFAULT_MORPHED.copy(); + + if (this.activeSettings != null) + { + this.settings.applyOverrides(this.activeSettings); + } + + finishInitializingSettings(); + } + + protected void finishInitializingSettings() + { + this.needSettingsUpdate = false; + this.forcedSettings = false; + } + + /** + * This sets the active settings for the morph, usually defined + * by the user through JSON configuration. These settings usually + * have the highest priority. + */ + public void setActiveSettings(MorphSettings activeSettings) + { + this.activeSettings = activeSettings; + this.needSettingsUpdate = true; + } + + /** + * This forces a morph to use the given settings. These settings + * will not be overridden and must be complete settings + * (no null fields allowed). + */ + public void forceSettings(MorphSettings settings) + { + this.settings = settings; + this.forcedSettings = true; + } + + /** + * Undoes the effects of {@link #forceSettings} + */ + public void clearForcedSettings() + { + this.settings = null; + this.forcedSettings = false; + this.needSettingsUpdate = true; + } + + /** + * Gets the morph settings or initializes them if + * not defined. + */ + public MorphSettings getSettings() + { + if (!this.forcedSettings) + { + initializeSettings(); + } + return this.settings; + } /** * Custom hitbox setting @@ -158,12 +246,13 @@ public void update(EntityLivingBase target) { this.updateHitbox(target); - if (target.isServerWorld()) + MorphSettings settings = this.getSettings(); + if (settings.speed != 0.1F) { - target.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(this.settings.speed); + target.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(settings.speed); } - for (IAbility ability : this.settings.abilities) + for (IAbility ability : settings.abilities) { ability.update(target); } @@ -181,7 +270,7 @@ public void update(EntityLivingBase target) */ public void morph(EntityLivingBase target) { - for (IAbility ability : this.settings.abilities) + for (IAbility ability : this.getSettings().abilities) { ability.onMorph(target); } @@ -195,7 +284,7 @@ public void morph(EntityLivingBase target) */ public void demorph(EntityLivingBase target) { - for (IAbility ability : this.settings.abilities) + for (IAbility ability : this.getSettings().abilities) { ability.onDemorph(target); } @@ -276,9 +365,9 @@ public static void updateSizeDefault(EntityLivingBase target, float width, float */ public void action(EntityLivingBase target) { - if (this.settings.action != null) + if (this.getSettings().action != null) { - this.settings.action.execute(target, this); + this.getSettings().action.execute(target, this); } } @@ -287,33 +376,54 @@ public void action(EntityLivingBase target) */ public void attack(Entity target, EntityLivingBase source) { - if (this.settings.attack != null) + if (this.getSettings().attack != null) { - this.settings.attack.attack(target, source); + this.getSettings().attack.attack(target, source); } } + /** + *

Used when copying morphs

+ * + *

+ * IMPORTANT: When you subclass other morphs, don't forget to override + * their method with your own. + *

+ */ + public abstract AbstractMorph create(); + /** * Clone a morph */ public final AbstractMorph copy() { AbstractMorph morph = this.create(); + // If this fails, then modder forgot to override copy() + assert(this.getClass().isInstance(morph)); morph.copy(this); return morph; } - public abstract AbstractMorph create(); - + /** + *

Copy this {@link AbstractMorph}

+ * + *

+ * IMPORTANT: If you subclass other morphs, and your morph contains new + * data, don't for get to override their method with your own. + *

+ */ public void copy(AbstractMorph from) { this.name = from.name; this.displayName = from.displayName; this.favorite = from.favorite; + this.settings = from.settings != null ? from.settings.copy() : null; + this.activeSettings = from.activeSettings != null ? from.activeSettings.copy() : null; + this.forcedSettings = from.forcedSettings; + this.needSettingsUpdate = from.needSettingsUpdate; this.keybind = from.keybind; - this.settings = this.hasCustomSettings() ? from.settings.copy() : from.settings; this.hitbox.copy(from.hitbox); } @@ -453,6 +563,8 @@ protected void mergeBasic(AbstractMorph morph) */ public void reset() { + setActiveSettings(null); + clearForcedSettings(); this.hitbox.reset(); } diff --git a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java index 8c1a4c67..60fd6ea3 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java @@ -31,6 +31,8 @@ import net.minecraft.entity.EntityList; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.IAttributeInstance; import net.minecraft.entity.boss.EntityDragon; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.passive.EntityAnimal; @@ -219,7 +221,7 @@ else if (this.name.equals("minecraft:guardian") && entity.height > 1.8) @SuppressWarnings("rawtypes") public boolean renderHand(EntityPlayer player, EnumHand hand) { - if (!this.settings.hands) + if (!getSettings().hands) { return true; } @@ -373,6 +375,42 @@ public void render(EntityLivingBase entity, double x, double y, double z, float renderEntity = null; } } + + /* Entity morph settings */ + + /** + * These are settings that are defined from the morph entity. + * They have lower priority than activeSettings. + */ + protected MorphSettings entitySettings = null; + + protected void setEntitySettings(MorphSettings entitySettings) { + this.entitySettings = entitySettings; + this.needSettingsUpdate = true; + } + + @Override + public void initializeSettings() + { + if (!this.needSettingsUpdate) + { + return; + } + + this.settings = MorphSettings.DEFAULT_MORPHED.copy(); + + if (this.entitySettings != null) + { + this.settings.applyOverrides(this.entitySettings); + } + + if (this.activeSettings != null) + { + this.settings.applyOverrides(this.activeSettings); + } + + finishInitializingSettings(); + } @SideOnly(Side.CLIENT) protected void setupBodyPart() @@ -493,18 +531,22 @@ public void setEntity(EntityLivingBase entity) entity.noClip = true; entity.setAlwaysRenderNameTag(true); - if (this.settings == MorphSettings.DEFAULT) + if (entity instanceof EntityLiving) { - this.customSettings = true; - this.settings = new MorphSettings(); - - if (this.settings.health == 20) - { - this.settings.health = (int) entity.getMaxHealth(); - } + ((EntityLiving) entity).setLeftHanded(false); + } - this.settings.hostile = entity instanceof EntityMob || entity instanceof EntityAnimal; + MorphSettings entitySettings = new MorphSettings(); + entitySettings.health = (int)entity.getMaxHealth(); + entitySettings.hostile = entity instanceof EntityMob || entity instanceof EntityAnimal; + IAttributeInstance speedAttribute = entity.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED); + if (speedAttribute != null) + { + // By vanilla convention, mob movement speeds tend to be 2.5x + // what the equivalent player speed would be. + entitySettings.speed = 0.4F * (float)speedAttribute.getBaseValue(); } + setEntitySettings(entitySettings); if (entity instanceof EntityLiving && !(entity instanceof EntityDragon)) { @@ -715,7 +757,7 @@ else if (!targetRiding && entityRiding) protected void updateEntity(EntityLivingBase target) { - if (this.settings.updates) + if (getSettings().updates) { if (!Metamorph.showMorphIdleSounds.get()) { @@ -801,9 +843,13 @@ protected void setupRenderer() this.renderer = (RenderLivingBase) renderer; ModelBase model = this.renderer.getMainModel(); - if (this.customSettings && model instanceof ModelBiped || model instanceof ModelQuadruped) + if (this.entity != null && model instanceof ModelBiped || model instanceof ModelQuadruped) { - this.settings.hands = true; + // Entity settings should have been defined when setEntity(...) was called + assert(this.entitySettings != null); + MorphSettings entitySettings = this.entitySettings != null ? this.entitySettings : new MorphSettings(); + entitySettings.hands = true; + setEntitySettings(entitySettings); } if (bodyPartMap == null) @@ -1019,6 +1065,7 @@ public void resetEntity() } this.entity = null; + setEntitySettings(null); } } @@ -1036,8 +1083,9 @@ public void copy(AbstractMorph from) if (from instanceof EntityMorph) { EntityMorph morph = (EntityMorph) from; - - this.entityData = morph.entityData == null ? null : morph.entityData.copy(); + + this.entitySettings = this.entitySettings != null ? this.entitySettings.copy() : null; + this.entityData = morph.entityData != null ? morph.entityData.copy() : null; this.parts.copy(morph.parts); this.scale = morph.scale; this.userTexture = RLUtils.clone(morph.userTexture); diff --git a/src/main/java/mchorse/metamorph/capabilities/morphing/Morphing.java b/src/main/java/mchorse/metamorph/capabilities/morphing/Morphing.java index 33183034..74a3c338 100644 --- a/src/main/java/mchorse/metamorph/capabilities/morphing/Morphing.java +++ b/src/main/java/mchorse/metamorph/capabilities/morphing/Morphing.java @@ -277,7 +277,7 @@ public boolean setCurrentMorph(AbstractMorph morph, EntityPlayer player, boolean { AbstractMorph current = this.morph.get(); - this.setHealth(player, current.settings.health); + this.setHealth(player, current.getSettings().health); current.morph(player); } @@ -454,7 +454,7 @@ public void update(EntityPlayer player) if (!Metamorph.disableHealth.get()) { - this.setMaxHealth(player, morph.settings.health); + this.setMaxHealth(player, morph.getSettings().health); } morph.update(player); diff --git a/src/main/java/mchorse/metamorph/client/NetworkHandler.java b/src/main/java/mchorse/metamorph/client/NetworkHandler.java index dd41821d..f647f826 100644 --- a/src/main/java/mchorse/metamorph/client/NetworkHandler.java +++ b/src/main/java/mchorse/metamorph/client/NetworkHandler.java @@ -116,7 +116,7 @@ private void morph(NBTTagCompound tag, EntityPlayer player) if (morph != null) { /* No fancy stuff or actions */ - morph.settings = MorphSettings.DEFAULT; + morph.forceSettings(MorphSettings.DEFAULT); Morphing.get(player).setCurrentMorph(morph, player, true); } diff --git a/src/main/java/mchorse/metamorph/network/server/survival/ServerHandlerAction.java b/src/main/java/mchorse/metamorph/network/server/survival/ServerHandlerAction.java index 3ed346d7..df688e7b 100644 --- a/src/main/java/mchorse/metamorph/network/server/survival/ServerHandlerAction.java +++ b/src/main/java/mchorse/metamorph/network/server/survival/ServerHandlerAction.java @@ -21,7 +21,7 @@ public void run(EntityPlayerMP player, PacketAction message) AbstractMorph morph = capability.getCurrentMorph(); morph.action(player); - MinecraftForge.EVENT_BUS.post(new MorphActionEvent(player, morph.settings.action, morph)); + MinecraftForge.EVENT_BUS.post(new MorphActionEvent(player, morph.getSettings().action, morph)); } } } \ No newline at end of file From af579b8eed9610fea32403fbe0ca5cb87a328588 Mon Sep 17 00:00:00 2001 From: asanetargoss Date: Sat, 17 Oct 2020 17:19:48 -0700 Subject: [PATCH 45/51] Remove settings from entity equality check --- src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java index 99cefcd3..213a09ea 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java @@ -516,7 +516,6 @@ public boolean equals(Object obj) return Objects.equals(this.name, morph.name) && Objects.equals(this.displayName, morph.displayName) && - Objects.equals(this.settings, morph.settings) && Objects.equals(this.hitbox, morph.hitbox); } From a9287f2c8cc54cc6e8eb5feda329f2a4fea835db Mon Sep 17 00:00:00 2001 From: asanetargoss Date: Sun, 1 May 2022 17:01:39 -0700 Subject: [PATCH 46/51] Fix squid morphs moving too fast, and player morphs too slow --- .../metamorph/api/morphs/EntityMorph.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java index 60fd6ea3..3f326696 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java @@ -39,6 +39,7 @@ import net.minecraft.entity.passive.EntityHorse; import net.minecraft.entity.passive.EntityPig; import net.minecraft.entity.passive.EntityRabbit; +import net.minecraft.entity.passive.EntityWaterMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -544,7 +545,21 @@ public void setEntity(EntityLivingBase entity) { // By vanilla convention, mob movement speeds tend to be 2.5x // what the equivalent player speed would be. - entitySettings.speed = 0.4F * (float)speedAttribute.getBaseValue(); + // Squids and players being the major exceptions. + if ((entity instanceof EntityWaterMob)) + { + // Check for EntityWaterMob rather than EntitySquid, + // as EntityWaterMob would be deleted in an entity class refactor. + entitySettings.speed = 0.1F; + } + else if (entity instanceof EntityPlayer) + { + entitySettings.speed = (float)speedAttribute.getBaseValue(); + } + else + { + entitySettings.speed = 0.4F * (float)speedAttribute.getBaseValue(); + } } setEntitySettings(entitySettings); From eb3de038d7bdc21d0572ebfec241c33ecc677287 Mon Sep 17 00:00:00 2001 From: asanetargoss Date: Fri, 18 Nov 2022 21:12:27 -0800 Subject: [PATCH 47/51] Fix paragraphs --- .../mchorse/metamorph/api/MorphSettings.java | 44 ++++++++++++++++++- .../api/json/MorphSettingsAdapter.java | 11 ++++- .../metamorph/api/morphs/AbstractMorph.java | 4 +- .../metamorph/api/morphs/EntityMorph.java | 6 ++- 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/main/java/mchorse/metamorph/api/MorphSettings.java b/src/main/java/mchorse/metamorph/api/MorphSettings.java index e361c21c..3f78f050 100644 --- a/src/main/java/mchorse/metamorph/api/MorphSettings.java +++ b/src/main/java/mchorse/metamorph/api/MorphSettings.java @@ -171,6 +171,7 @@ public void applyOverrides(MorphSettings setting) this.action = setting.action; this.hasAction = true; } + if (setting.hasAttack) { this.attack = setting.attack; @@ -182,21 +183,25 @@ public void applyOverrides(MorphSettings setting) this.health = setting.health; this.hasHealth = true; } + if (setting.hasSpeed) { this.speed = setting.speed; this.hasSpeed = true; } + if (setting.hasHostile) { this.hostile = setting.hostile; this.hasHostile = true; } + if (setting.hasHands) { this.hands = setting.hands; this.hasHands = true; } + if (setting.hasUpdates) { this.updates = setting.updates; @@ -210,6 +215,7 @@ public void applyOverrides(MorphSettings setting) public void toBytes(ByteBuf buf) { buf.writeBoolean(this.hasAbilities); + if (this.hasAbilities) { buf.writeInt(this.abilities.size()); @@ -223,10 +229,12 @@ public void toBytes(ByteBuf buf) } buf.writeBoolean(this.hasAction); + if (this.hasAction) { String action = getKey(MorphManager.INSTANCE.actions, this.action); buf.writeBoolean(action != null); + if (action != null) { ByteBufUtils.writeUTF8String(buf, action); @@ -234,9 +242,11 @@ public void toBytes(ByteBuf buf) } buf.writeBoolean(this.hasAttack); + if (this.hasAttack) { String attack = getKey(MorphManager.INSTANCE.attacks, this.attack); buf.writeBoolean(attack != null); + if (attack != null) { ByteBufUtils.writeUTF8String(buf, attack); @@ -244,31 +254,42 @@ public void toBytes(ByteBuf buf) } buf.writeBoolean(this.hasHealth); + if (this.hasHealth) { buf.writeInt(this.health); } + buf.writeBoolean(this.hasSpeed); + if (this.hasSpeed) { buf.writeFloat(this.speed); } + buf.writeBoolean(this.hasHostile); + if (this.hasHostile) { buf.writeBoolean(this.hostile); } + buf.writeBoolean(this.hasHands); + if (this.hasHands) { buf.writeBoolean(this.hands); } + buf.writeBoolean(this.hasUpdates); + if (this.hasUpdates) { buf.writeBoolean(this.updates); } + buf.writeBoolean(this.hasShadowOption); + if (this.hasShadowOption) { buf.writeInt(this.shadowOption); @@ -281,6 +302,7 @@ public void toBytes(ByteBuf buf) public void fromBytes(ByteBuf buf) { this.hasAbilities = buf.readBoolean(); + if (this.hasAbilities) { List abilities = new ArrayList(); @@ -293,10 +315,12 @@ public void fromBytes(ByteBuf buf) abilities.add(ability); } } + this.abilities = abilities; } this.hasAction = buf.readBoolean(); + if (this.hasAction) { if (buf.readBoolean()) @@ -311,6 +335,7 @@ public void fromBytes(ByteBuf buf) } this.hasAttack = buf.readBoolean(); + if (this.hasAttack) { if (buf.readBoolean()) @@ -325,36 +350,42 @@ public void fromBytes(ByteBuf buf) } this.hasHealth = buf.readBoolean(); + if (this.hasHealth) { this.health = buf.readInt(); } this.hasSpeed = buf.readBoolean(); + if (this.hasSpeed) { this.speed = buf.readFloat(); } this.hasHostile = buf.readBoolean(); + if (this.hasHostile) { this.hostile = buf.readBoolean(); } this.hasHands = buf.readBoolean(); + if (this.hasHands) { this.hands = buf.readBoolean(); } this.hasUpdates = buf.readBoolean(); + if (this.hasUpdates) { this.updates = buf.readBoolean(); } this.hasShadowOption = buf.readBoolean(); + if (this.hasShadowOption) { this.shadowOption = buf.readInt(); @@ -389,7 +420,9 @@ public void toNBT(NBTTagCompound tag) if (this.hasAction) { String actionKey = getKey(MorphManager.INSTANCE.actions, this.action); + if (actionKey == null) { actionKey = "null"; } + tag.setString("Action", actionKey); } @@ -430,6 +463,7 @@ public void toNBT(NBTTagCompound tag) public void fromNBT(NBTTagCompound tag) { this.hasAbilities = tag.hasKey("Abilities"); + if (this.hasAbilities) { NBTTagList list = tag.getTagList("Abilities", Constants.NBT.TAG_STRING); @@ -448,48 +482,56 @@ public void fromNBT(NBTTagCompound tag) } this.hasAttack = tag.hasKey("Attack"); + if (this.hasAttack) { this.attack = MorphManager.INSTANCE.attacks.get(tag.getString("Attack")); } this.hasAction = tag.hasKey("Action"); + if (this.hasAction) { this.action = MorphManager.INSTANCE.actions.get(tag.getString("Action")); } this.hasHealth = tag.hasKey("HP"); + if (this.hasHealth) { this.health = tag.getInteger("HP"); } this.hasSpeed = tag.hasKey("Speed"); + if (this.hasSpeed) { this.speed = tag.getFloat("Speed"); } this.hasHostile = tag.hasKey("Hostile"); + if (this.hasHostile) { this.hostile = tag.getBoolean("Hostile"); } this.hasHands = tag.hasKey("Hands"); + if (this.hasHands) { this.hands = tag.getBoolean("Hands"); } this.hasUpdates = tag.hasKey("Updates"); + if (this.hasUpdates) { this.updates = tag.getBoolean("Updates"); } this.hasShadowOption = tag.hasKey("ShadowOption"); + if (this.hasShadowOption) { this.shadowOption = tag.getInteger("ShadowOption"); @@ -516,4 +558,4 @@ public static String getKey(Map map, T value) return null; } -} \ No newline at end of file +} diff --git a/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java b/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java index 255e203d..14594f25 100644 --- a/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java +++ b/src/main/java/mchorse/metamorph/api/json/MorphSettingsAdapter.java @@ -30,30 +30,35 @@ public MorphSettings deserialize(JsonElement json, Type typeOfT, JsonDeserializa MorphManager manager = MorphManager.INSTANCE; morph.hasHealth = object.has("health") && object.get("health").isJsonPrimitive(); + if (morph.hasHealth) { morph.health = object.get("health").getAsInt(); } morph.hasSpeed = object.has("speed") && object.get("speed").isJsonPrimitive(); + if (morph.hasSpeed) { morph.speed = object.get("speed").getAsFloat(); } morph.hasHostile = object.has("hostile") && object.get("hostile").isJsonPrimitive(); + if (morph.hasHostile) { morph.hostile = object.get("hostile").getAsBoolean(); } morph.hasHands = object.has("hands") && object.get("hands").isJsonPrimitive(); + if (morph.hasHands) { morph.hands = object.get("hands").getAsBoolean(); } morph.hasAbilities = object.has("abilities") && object.get("abilities").isJsonArray(); + if (morph.hasAbilities) { morph.abilities.clear(); @@ -75,24 +80,28 @@ public MorphSettings deserialize(JsonElement json, Type typeOfT, JsonDeserializa } morph.hasAction = object.has("action") && object.get("action").isJsonPrimitive(); + if (morph.hasAction) { morph.action = manager.actions.get(object.get("action").getAsString()); } morph.hasAttack = object.has("attack") && object.get("attack").isJsonPrimitive(); + if (morph.hasAttack) { morph.attack = manager.attacks.get(object.get("attack").getAsString()); } morph.hasUpdates = object.has("updates") && object.get("updates").isJsonPrimitive(); + if (morph.hasUpdates) { morph.updates = object.get("updates").getAsBoolean(); } morph.hasShadowOption = object.has("shadow_option") && object.get("shadow_option").isJsonPrimitive(); + if (morph.hasShadowOption) { morph.shadowOption = object.get("shadow_option").getAsInt(); @@ -100,4 +109,4 @@ public MorphSettings deserialize(JsonElement json, Type typeOfT, JsonDeserializa return morph; } -} \ No newline at end of file +} diff --git a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java index 213a09ea..1231cadb 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java @@ -159,6 +159,7 @@ public MorphSettings getSettings() { initializeSettings(); } + return this.settings; } @@ -247,6 +248,7 @@ public void update(EntityLivingBase target) this.updateHitbox(target); MorphSettings settings = this.getSettings(); + if (settings.speed != 0.1F) { target.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(settings.speed); @@ -653,4 +655,4 @@ public void fromNBT(NBTTagCompound tag) this.hitbox.fromNBT(tag.getCompoundTag("Hitbox")); } } -} \ No newline at end of file +} diff --git a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java index 3f326696..da09d017 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java @@ -541,11 +541,13 @@ public void setEntity(EntityLivingBase entity) entitySettings.health = (int)entity.getMaxHealth(); entitySettings.hostile = entity instanceof EntityMob || entity instanceof EntityAnimal; IAttributeInstance speedAttribute = entity.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED); + if (speedAttribute != null) { // By vanilla convention, mob movement speeds tend to be 2.5x // what the equivalent player speed would be. // Squids and players being the major exceptions. + if ((entity instanceof EntityWaterMob)) { // Check for EntityWaterMob rather than EntitySquid, @@ -561,6 +563,7 @@ else if (entity instanceof EntityPlayer) entitySettings.speed = 0.4F * (float)speedAttribute.getBaseValue(); } } + setEntitySettings(entitySettings); if (entity instanceof EntityLiving && !(entity instanceof EntityDragon)) @@ -778,6 +781,7 @@ protected void updateEntity(EntityLivingBase target) { this.entity.setSilent(true); } + this.entity.onUpdate(); this.entity.setSilent(false); } @@ -1280,4 +1284,4 @@ public boolean shouldCombineTextures() return false; } } -} \ No newline at end of file +} From e99431853d7ab0bfdc623d7c9cc58e79dd1d5a25 Mon Sep 17 00:00:00 2001 From: asanetargoss Date: Sat, 13 May 2023 22:18:42 -0700 Subject: [PATCH 48/51] Better NPE handling: If user is a player, do a temporary fix. If user is a developer, explain better why the error occurred --- .../metamorph/api/morphs/AbstractMorph.java | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java index 1231cadb..b2f9693e 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java @@ -16,6 +16,7 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraftforge.classloading.FMLForgePlugin; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -98,6 +99,19 @@ public void initializeSettings() { if (!this.needSettingsUpdate) { + if (this.settings == null) + { + if (FMLForgePlugin.RUNTIME_DEOBF) + { + this.settings = MorphSettings.DEFAULT_MORPHED.copy(); + } + else + { + // Developer mode + throw new NullPointerException("needSettingsUpdate was not set to true when changing morph settings, or the settings was set to null directly when it shouldn't be"); + } + } + return; } @@ -133,9 +147,22 @@ public void setActiveSettings(MorphSettings activeSettings) * will not be overridden and must be complete settings * (no null fields allowed). */ - public void forceSettings(MorphSettings settings) - { - this.settings = settings; + public void forceSettings(MorphSettings settingsToForce) + { + if (settingsToForce == null) + { + if (FMLForgePlugin.RUNTIME_DEOBF) + { + settingsToForce = MorphSettings.DEFAULT_MORPHED.copy(); + } + else + { + // Developer mode + throw new NullPointerException("Forced settings should never be null (are you trying to call clearForcedSettings()?)"); + } + } + + this.settings = settingsToForce; this.forcedSettings = true; } From f5a03039420ea0f2064cf9d1364aeba37a31c565 Mon Sep 17 00:00:00 2001 From: asanetargoss Date: Sun, 14 May 2023 10:06:11 -0700 Subject: [PATCH 49/51] Fix creative morph settings edits --- .../mchorse/metamorph/api/MorphSettings.java | 18 +++-- .../mchorse/metamorph/api/MorphUtils.java | 2 +- .../metamorph/api/morphs/AbstractMorph.java | 52 +++++++++---- .../metamorph/api/morphs/EntityMorph.java | 7 +- .../client/gui/editor/GuiSettingsPanel.java | 75 ++++++++++--------- 5 files changed, 93 insertions(+), 61 deletions(-) diff --git a/src/main/java/mchorse/metamorph/api/MorphSettings.java b/src/main/java/mchorse/metamorph/api/MorphSettings.java index 3f78f050..70c2a3de 100644 --- a/src/main/java/mchorse/metamorph/api/MorphSettings.java +++ b/src/main/java/mchorse/metamorph/api/MorphSettings.java @@ -1,5 +1,10 @@ package mchorse.metamorph.api; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + import io.netty.buffer.ByteBuf; import mchorse.metamorph.api.abilities.IAbility; import mchorse.metamorph.api.abilities.IAction; @@ -10,11 +15,6 @@ import net.minecraftforge.common.util.Constants; import net.minecraftforge.fml.common.network.ByteBufUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; - /** * Morph settings * @@ -95,6 +95,14 @@ public class MorphSettings */ public int shadowOption = 0; public boolean hasShadowOption = true; + + /** + * Morph settings applier lambda + */ + public static interface Edit + { + void apply(MorphSettings settings); + } @Override public boolean equals(Object obj) diff --git a/src/main/java/mchorse/metamorph/api/MorphUtils.java b/src/main/java/mchorse/metamorph/api/MorphUtils.java index 9624eb4c..1488f694 100644 --- a/src/main/java/mchorse/metamorph/api/MorphUtils.java +++ b/src/main/java/mchorse/metamorph/api/MorphUtils.java @@ -103,7 +103,7 @@ public static boolean render(AbstractMorph morph, EntityLivingBase entity, doubl boolean isShadowPass = ReflectionUtils.isOptifineShadowPass(); - if (!GuiModelRenderer.isRendering() && (isShadowPass && morph.settings.shadowOption == 1 || !isShadowPass && morph.settings.shadowOption == 2)) + if (!GuiModelRenderer.isRendering() && (isShadowPass && morph.getSettings().shadowOption == 1 || !isShadowPass && morph.getSettings().shadowOption == 2)) { return false; } diff --git a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java index b2f9693e..cc8c98c5 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/AbstractMorph.java @@ -165,6 +165,21 @@ public void forceSettings(MorphSettings settingsToForce) this.settings = settingsToForce; this.forcedSettings = true; } + + /** + * This forces a morph to use the updated settings. These settings + * will not be overridden and must be complete settings + * (no null fields allowed). + * If the settings have not been forced yet, the morph's existing + * settings will be copied and used as the basis for the new forced + * settings. + */ + public void forceEditSettings(MorphSettings.Edit edit) + { + MorphSettings settingsCopy = this.getSettings().copy(); + edit.apply(settingsCopy); + forceSettings(settingsCopy); + } /** * Undoes the effects of {@link #forceSettings} @@ -226,19 +241,20 @@ public boolean hasCustomName() return this.displayName != null && !this.displayName.isEmpty(); } + @Deprecated public boolean hasCustomSettings() { - if (this.settings == MorphSettings.DEFAULT) - { - return false; - } - - if (this.settings == MorphManager.INSTANCE.activeSettings.get(this.name)) - { - return false; - } - - return true; + if (this.settings != MorphSettings.DEFAULT) + { + return true; + } + + if (this.settings != MorphManager.INSTANCE.activeSettings.get(this.name)) + { + return true; + } + + return forcedSettings; } /* Render methods */ @@ -614,17 +630,19 @@ public void toNBT(NBTTagCompound tag) { tag.setString("Name", this.name); - if (this.hasCustomSettings()) + if (this.forcedSettings) { NBTTagCompound settings = new NBTTagCompound(); - this.settings.toNBT(settings); + this.getSettings().toNBT(settings); if (!settings.hasNoTags()) { tag.setTag("Settings", settings); } } + + tag.setBoolean("ForcedSettings", this.forcedSettings); if (this.displayName != null && !this.displayName.isEmpty()) { @@ -655,11 +673,19 @@ public void fromNBT(NBTTagCompound tag) this.reset(); this.name = tag.getString("Name"); + + boolean hasForcedSettings = tag.hasKey("ForcedSettings"); + this.forcedSettings = tag.getBoolean("ForcedSettings"); if (tag.hasKey("Settings")) { this.settings = new MorphSettings(); this.settings.fromNBT(tag.getCompoundTag("Settings")); + + if (!hasForcedSettings) + { + this.forcedSettings = true; + } } if (tag.hasKey("DisplayName")) diff --git a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java index da09d017..e32863b8 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java @@ -101,6 +101,7 @@ public class EntityMorph extends AbstractMorph implements IBodyPartProvider /** * Custom settings were generated by this morph */ + @Deprecated protected boolean customSettings; /** @@ -1066,11 +1067,7 @@ public void reset() this.scale = 1F; this.userTexture = null; - if (this.customSettings) - { - this.settings = MorphSettings.DEFAULT; - this.customSettings = false; - } + super.reset(); } public void resetEntity() diff --git a/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java b/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java index 8cf56493..b0a0fd4e 100644 --- a/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java +++ b/src/main/java/mchorse/metamorph/client/gui/editor/GuiSettingsPanel.java @@ -74,7 +74,7 @@ public GuiSettingsPanel(Minecraft mc, GuiAbstractMorph editor) this.keybind.tooltip(IKey.lang("metamorph.gui.editor.keybind_tooltip")); this.reset = new GuiButtonElement(mc, IKey.lang("metamorph.gui.editor.reset"), (button) -> { - this.morph.settings = MorphSettings.DEFAULT; + this.morph.clearForcedSettings(); MorphManager.INSTANCE.applySettings(this.morph); this.editor.setPanel(this.editor.defaultPanel); @@ -82,42 +82,52 @@ public GuiSettingsPanel(Minecraft mc, GuiAbstractMorph editor) this.displayName = new GuiTextElement(mc, (string) -> this.morph.displayName = string); this.abilities = new GuiStringListElement(mc, (values) -> { - this.ensureCustomSettings(); - this.morph.settings.abilities.clear(); + this.morph.forceEditSettings((settings) -> + { + settings.abilities.clear(); - for (String value : values) - { - IAbility ability = MorphManager.INSTANCE.abilities.get(value); - - if (ability != null) + for (String value : values) { - this.morph.settings.abilities.add(ability); + IAbility ability = MorphManager.INSTANCE.abilities.get(value); + + if (ability != null) + { + settings.abilities.add(ability); + } } - } + }); }); this.abilities.multi().background().tooltip(IKey.lang("metamorph.gui.editor.abilities_tooltip")); this.attack = new GuiStringListElement(mc, (values) -> { - this.ensureCustomSettings(); - this.morph.settings.attack = MorphManager.INSTANCE.attacks.get(values.get(0)); + this.morph.forceEditSettings((settings) -> + { + settings.attack = MorphManager.INSTANCE.attacks.get(values.get(0)); + }); }); this.attack.background(); this.action = new GuiStringListElement(mc, (values) -> { - this.ensureCustomSettings(); - this.morph.settings.action = MorphManager.INSTANCE.actions.get(values.get(0)); + this.morph.forceEditSettings((settings) -> + { + settings.action = MorphManager.INSTANCE.actions.get(values.get(0)); + }); }); this.action.background(); this.health = new GuiTrackpadElement(mc, (value) -> { - this.ensureCustomSettings(); - this.morph.settings.health = value.intValue(); + this.morph.forceEditSettings((settings) -> + { + settings.health = value.intValue(); + }); }) .limit(0, Float.POSITIVE_INFINITY, true); this.speed = new GuiTrackpadElement(mc, (value) -> { - this.ensureCustomSettings(); - this.morph.settings.speed = value.floatValue(); + this.morph.forceEditSettings((settings) -> + { + settings.speed = value.floatValue(); + }); }) .limit(0, Float.POSITIVE_INFINITY) .values(0.05F, 0.01F, 0.1F) @@ -158,8 +168,10 @@ public GuiSettingsPanel(Minecraft mc, GuiAbstractMorph editor) this.shadowOption = new GuiCirculateElement(mc, (element) -> { - this.ensureCustomSettings(); - this.morph.settings.shadowOption = element.getValue(); + this.morph.forceEditSettings((settings) -> + { + settings.shadowOption = element.getValue(); + }); }); for (OptifineShadowOption option : OptifineShadowOption.values()) { @@ -177,17 +189,6 @@ public GuiSettingsPanel(Minecraft mc, GuiAbstractMorph editor) this.add(this.left, this.right, this.data); } - private void ensureCustomSettings() - { - if (!this.morph.hasCustomSettings()) - { - MorphSettings old = this.morph.settings; - - this.morph.settings = new MorphSettings(); - this.morph.settings.copy(old); - } - } - @Override public void fillData(AbstractMorph morph) { @@ -206,7 +207,7 @@ public void fillData(AbstractMorph morph) this.hitboxSneakingHeight.setValue(morph.hitbox.sneakingHeight); this.hitboxEyePosition.setValue(morph.hitbox.eye); - this.shadowOption.setValue(morph.settings.shadowOption); + this.shadowOption.setValue(morph.getSettings().shadowOption); } public void updateNBT() @@ -241,12 +242,12 @@ public void startEditing() this.keybind.setKeybind(morph.keybind); this.displayName.setText(morph.displayName); - this.health.setValue(morph.settings.health); - this.speed.setValue(morph.settings.speed); + this.health.setValue(morph.getSettings().health); + this.speed.setValue(morph.getSettings().speed); List abilities = new ArrayList(); - for (IAbility ability : morph.settings.abilities) + for (IAbility ability : morph.getSettings().abilities) { String key = MorphSettings.getKey(MorphManager.INSTANCE.abilities, ability); @@ -261,8 +262,8 @@ public void startEditing() this.action.sort(); this.abilities.setCurrent(abilities); - this.attack.setCurrent(MorphSettings.getKey(MorphManager.INSTANCE.attacks, morph.settings.attack)); - this.action.setCurrent(MorphSettings.getKey(MorphManager.INSTANCE.actions, morph.settings.action)); + this.attack.setCurrent(MorphSettings.getKey(MorphManager.INSTANCE.attacks, morph.getSettings().attack)); + this.action.setCurrent(MorphSettings.getKey(MorphManager.INSTANCE.actions, morph.getSettings().action)); } @Override From c86ef137d1ee9f870380e23da3dadd91ecde442c Mon Sep 17 00:00:00 2001 From: asanetargoss Date: Sat, 10 Feb 2024 20:56:48 -0800 Subject: [PATCH 50/51] Update mclib dependency to 2.4.2 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 0a19787c..f89ec62c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Metamorph gradle properties version=1.3.1 -mclib=2.4.1 +mclib=2.4.2 mc_version=1.12.2 forge_version=14.23.5.2799 -snapshot=snapshot_20171003 \ No newline at end of file +snapshot=snapshot_20171003 From b83f8e951429d85e69dccf440e3d264c4017ad12 Mon Sep 17 00:00:00 2001 From: asanetargoss Date: Sat, 10 Feb 2024 21:33:33 -0800 Subject: [PATCH 51/51] Fix 1.12->1.11 backport errors --- src/main/java/mchorse/metamorph/api/MorphUtils.java | 1 - src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/mchorse/metamorph/api/MorphUtils.java b/src/main/java/mchorse/metamorph/api/MorphUtils.java index 1488f694..37ebd33d 100644 --- a/src/main/java/mchorse/metamorph/api/MorphUtils.java +++ b/src/main/java/mchorse/metamorph/api/MorphUtils.java @@ -24,7 +24,6 @@ import mchorse.metamorph.bodypart.BodyPart; import mchorse.metamorph.bodypart.BodyPartManager; import mchorse.metamorph.bodypart.IBodyPartProvider; -import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.Tessellator; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java index 209e7590..1144301c 100644 --- a/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java +++ b/src/main/java/mchorse/metamorph/api/morphs/EntityMorph.java @@ -358,11 +358,11 @@ public void render(EntityLivingBase entity, double x, double y, double z, float { GlStateManager.rotate(180, 0.0F, 1.0F, 0.0F); - Minecraft.getMinecraft().getRenderManager().renderEntity(this.entity, 0, 0, 0, entityYaw, partialTicks, false); + Minecraft.getMinecraft().getRenderManager().doRenderEntity(this.entity, 0, 0, 0, entityYaw, partialTicks, false); } else { - Minecraft.getMinecraft().getRenderManager().renderEntity(this.entity, 0, 0, 0, entityYaw, partialTicks, false); + Minecraft.getMinecraft().getRenderManager().doRenderEntity(this.entity, 0, 0, 0, entityYaw, partialTicks, false); } GlStateManager.popMatrix();