diff --git a/src/main/java/com/minelittlepony/api/pony/IPonyData.java b/src/main/java/com/minelittlepony/api/pony/IPonyData.java index f4307fc9..3137aed0 100644 --- a/src/main/java/com/minelittlepony/api/pony/IPonyData.java +++ b/src/main/java/com/minelittlepony/api/pony/IPonyData.java @@ -3,11 +3,7 @@ package com.minelittlepony.api.pony; import org.jetbrains.annotations.Nullable; import com.google.common.collect.ComparisonChain; -import com.minelittlepony.api.pony.meta.Gender; -import com.minelittlepony.api.pony.meta.Race; -import com.minelittlepony.api.pony.meta.Size; -import com.minelittlepony.api.pony.meta.TailLength; -import com.minelittlepony.api.pony.meta.Wearable; +import com.minelittlepony.api.pony.meta.*; import com.minelittlepony.common.util.animation.Interpolator; import java.util.Arrays; @@ -26,7 +22,12 @@ public interface IPonyData extends Comparable { /** * Gets the length of the pony's tail. */ - TailLength getTail(); + TailLength getTailLength(); + + /** + * Gets the shape of the pony's tail. + */ + TailShape getTailShape(); /** * Get the pony's gender (usually female). @@ -79,7 +80,7 @@ public interface IPonyData extends Comparable { default int compareTo(@Nullable IPonyData o) { return o == this ? 0 : o == null ? 1 : ComparisonChain.start() .compare(getRace(), o.getRace()) - .compare(getTail(), o.getTail()) + .compare(getTailLength(), o.getTailLength()) .compare(getGender(), o.getGender()) .compare(getSize().ordinal(), o.getSize().ordinal()) .compare(getGlowColor(), o.getGlowColor()) diff --git a/src/main/java/com/minelittlepony/api/pony/meta/TailShape.java b/src/main/java/com/minelittlepony/api/pony/meta/TailShape.java new file mode 100644 index 00000000..5636a200 --- /dev/null +++ b/src/main/java/com/minelittlepony/api/pony/meta/TailShape.java @@ -0,0 +1,21 @@ +package com.minelittlepony.api.pony.meta; + +import com.minelittlepony.api.pony.TriggerPixelType; + +public enum TailShape implements TriggerPixelType { + STRAIGHT(0), + BUMPY (0xfc539f), + SWIRLY (0x3eff22), + SPIKY (0x3308c7); + + private int triggerValue; + + TailShape(int pixel) { + triggerValue = pixel; + } + + @Override + public int getColorCode() { + return triggerValue; + } +} diff --git a/src/main/java/com/minelittlepony/api/pony/meta/TriggerPixel.java b/src/main/java/com/minelittlepony/api/pony/meta/TriggerPixel.java index 42c27c70..4c71ab2a 100644 --- a/src/main/java/com/minelittlepony/api/pony/meta/TriggerPixel.java +++ b/src/main/java/com/minelittlepony/api/pony/meta/TriggerPixel.java @@ -20,7 +20,8 @@ public enum TriggerPixel { GENDER(Gender.MARE, Channel.ALL, 2, 0), SIZE(Sizes.NORMAL, Channel.ALL, 3, 0), GLOW(null, Channel.RAW, 0, 1), - WEARABLES(Wearable.NONE, Channel.RAW, 1, 1); + WEARABLES(Wearable.NONE, Channel.RAW, 1, 1), + TAIL_SHAPE(TailShape.STRAIGHT, Channel.ALL, 2, 1); private int x; private int y; diff --git a/src/main/java/com/minelittlepony/api/pony/network/MsgPonyData.java b/src/main/java/com/minelittlepony/api/pony/network/MsgPonyData.java index 3fba7b8f..24af15e4 100644 --- a/src/main/java/com/minelittlepony/api/pony/network/MsgPonyData.java +++ b/src/main/java/com/minelittlepony/api/pony/network/MsgPonyData.java @@ -3,14 +3,11 @@ package com.minelittlepony.api.pony.network; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Util; +import com.google.common.base.MoreObjects; import com.google.common.base.Suppliers; import com.minelittlepony.api.pony.IPonyData; import com.minelittlepony.api.pony.TriggerPixelType; -import com.minelittlepony.api.pony.meta.Gender; -import com.minelittlepony.api.pony.meta.Race; -import com.minelittlepony.api.pony.meta.Size; -import com.minelittlepony.api.pony.meta.TailLength; -import com.minelittlepony.api.pony.meta.Wearable; +import com.minelittlepony.api.pony.meta.*; import com.minelittlepony.common.util.animation.Interpolator; import java.util.Map; @@ -22,6 +19,7 @@ public class MsgPonyData implements IPonyData { private final Race race; private final TailLength tailLength; + private final TailShape tailShape; private final Gender gender; private final Size size; private final int glowColor; @@ -36,7 +34,8 @@ public class MsgPonyData implements IPonyData { private final Supplier>> triggerPixels = Suppliers.memoize(() -> Util.make(new TreeMap<>(), this::initTriggerPixels)); private void initTriggerPixels(Map> map) { map.put("race", race); - map.put("tail", tailLength); + map.put("tailLength", tailLength); + map.put("tailShape", tailShape); map.put("gender", gender); map.put("size", size); map.put("magic", TriggerPixelType.of(glowColor)); @@ -44,9 +43,10 @@ public class MsgPonyData implements IPonyData { } public MsgPonyData(PacketByteBuf buffer) { - race = Race.values()[buffer.readInt()]; - tailLength = TailLength.values()[buffer.readInt()]; - gender = Gender.values()[buffer.readInt()]; + race = buffer.readEnumConstant(Race.class); + tailLength = buffer.readEnumConstant(TailLength.class); + tailShape = buffer.readEnumConstant(TailShape.class); + gender = buffer.readEnumConstant(Gender.class); size = new MsgSize(buffer); glowColor = buffer.readInt(); hasHorn = buffer.readBoolean(); @@ -63,7 +63,8 @@ public class MsgPonyData implements IPonyData { public MsgPonyData(IPonyData data, boolean noSkin) { race = data.getRace(); - tailLength = data.getTail(); + tailLength = data.getTailLength(); + tailShape = data.getTailShape(); gender = data.getGender(); size = data.getSize(); glowColor = data.getGlowColor(); @@ -75,9 +76,10 @@ public class MsgPonyData implements IPonyData { } public PacketByteBuf toBuffer(PacketByteBuf buffer) { - buffer.writeInt(race.ordinal()); - buffer.writeInt(tailLength.ordinal()); - buffer.writeInt(gender.ordinal()); + buffer.writeEnumConstant(race); + buffer.writeEnumConstant(tailLength); + buffer.writeEnumConstant(tailShape); + buffer.writeEnumConstant(gender); new MsgSize(size).toBuffer(buffer); buffer.writeInt(glowColor); buffer.writeBoolean(hasHorn); @@ -103,10 +105,15 @@ public class MsgPonyData implements IPonyData { } @Override - public TailLength getTail() { + public TailLength getTailLength() { return tailLength; } + @Override + public TailShape getTailShape() { + return tailShape; + } + @Override public Gender getGender() { return gender; @@ -152,6 +159,19 @@ public class MsgPonyData implements IPonyData { return triggerPixels.get(); } + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("race", race) + .add("tailLength", tailLength) + .add("tailShape", tailShape) + .add("gender", gender) + .add("size", size) + .add("wearables", getGear()) + .add("glowColor", TriggerPixelType.toHex(glowColor)) + .toString(); + } + private static final class MsgSize implements Size { private final int ordinal; diff --git a/src/main/java/com/minelittlepony/client/model/part/PonyTail.java b/src/main/java/com/minelittlepony/client/model/part/PonyTail.java index 20c7c69b..073262cc 100644 --- a/src/main/java/com/minelittlepony/client/model/part/PonyTail.java +++ b/src/main/java/com/minelittlepony/client/model/part/PonyTail.java @@ -6,6 +6,7 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.MathHelper; import com.minelittlepony.api.model.IPart; +import com.minelittlepony.api.pony.meta.TailShape; import com.minelittlepony.client.model.AbstractPonyModel; import com.minelittlepony.mson.api.ModelContext; import com.minelittlepony.mson.api.MsonModel; @@ -18,9 +19,10 @@ import java.util.concurrent.ExecutionException; public class PonyTail implements IPart, MsonModel { private ModelPart tail; - private AbstractPonyModel theModel; + private AbstractPonyModel model; private int tailStop = 0; + private TailShape shape = TailShape.STRAIGHT; private final List segments = new ArrayList<>(); @@ -30,7 +32,7 @@ public class PonyTail implements IPart, MsonModel { @Override public void init(ModelContext context) { - theModel = context.getModel(); + model = context.getModel(); try { int segments = context.getLocals().getLocal("segments").get().intValue(); @@ -54,9 +56,9 @@ public class PonyTail implements IPart, MsonModel { tail.roll = rainboom ? 0 : MathHelper.cos(move * 0.8F) * 0.2f * swing; tail.yaw = bodySwing; - if (theModel.getAttributes().isCrouching && !rainboom) { + if (model.getAttributes().isCrouching && !rainboom) { rotateSneak(); - } else if (theModel.isRiding()) { + } else if (model.isRiding()) { tail.pivotZ = TAIL_RP_Z_RIDING; tail.pivotY = TAIL_RP_Y_RIDING; tail.pitch = PI / 5; @@ -91,7 +93,8 @@ public class PonyTail implements IPart, MsonModel { @Override public void setVisible(boolean visible) { tail.visible = visible; - tailStop = theModel.getMetadata().getTail().ordinal(); + tailStop = model.getMetadata().getTailLength().ordinal(); + shape = model.getMetadata().getTailShape(); } @Override @@ -116,9 +119,42 @@ public class PonyTail implements IPart, MsonModel { } public void render(MatrixStack stack, VertexConsumer renderContext, int overlayUv, int lightUv, float red, float green, float blue, float alpha) { - if (index < tail.tailStop) { - tree.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha); + if (index >= tail.tailStop) { + return; } + + if (tail.shape == TailShape.STRAIGHT) { + tree.yaw = 0; + tree.pivotZ = 0; + tree.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha); + return; + } + + stack.push(); + if (tail.shape == TailShape.BUMPY) { + stack.translate(0, 0, -9/16F); + float scale = 1 + MathHelper.cos(index + 5) / 2F; + stack.scale(scale, 1, scale); + stack.translate(1 / 16F * scale - 0.1F, 0, -2 / 16F * scale); + tree.pivotZ = 9; + } + if (tail.shape == TailShape.SWIRLY) { + stack.translate(0, 0, -6/16F); + float scale = 1 + MathHelper.cos(index + 10) / 5F; + stack.scale(1, 1, scale); + stack.translate(0, 0, -2 / 16F * scale); + tree.pivotZ = 9; + } + if (tail.shape == TailShape.SPIKY) { + stack.translate(0, 0, -6/16F); + float scale = 1 + MathHelper.cos(index + 10) / 5F; + stack.scale(1, 1, scale); + stack.translate(0, 0, -2 / 16F * scale); + tree.yaw = 0.2F * (index % 2 - 1); + tree.pivotZ = 9; + } + tree.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha); + stack.pop(); } } } diff --git a/src/main/java/com/minelittlepony/client/pony/NativePonyData.java b/src/main/java/com/minelittlepony/client/pony/NativePonyData.java index 27c9ec35..8ee0faa7 100644 --- a/src/main/java/com/minelittlepony/client/pony/NativePonyData.java +++ b/src/main/java/com/minelittlepony/client/pony/NativePonyData.java @@ -7,13 +7,7 @@ import com.minelittlepony.api.pony.IPonyData; import com.minelittlepony.api.pony.TriggerPixelSet; import com.minelittlepony.api.pony.TriggerPixelType; import com.minelittlepony.api.pony.TriggerPixelValue; -import com.minelittlepony.api.pony.meta.Gender; -import com.minelittlepony.api.pony.meta.Race; -import com.minelittlepony.api.pony.meta.Size; -import com.minelittlepony.api.pony.meta.Sizes; -import com.minelittlepony.api.pony.meta.TailLength; -import com.minelittlepony.api.pony.meta.TriggerPixel; -import com.minelittlepony.api.pony.meta.Wearable; +import com.minelittlepony.api.pony.meta.*; import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.common.util.animation.Interpolator; import com.minelittlepony.settings.PonyConfig; @@ -30,7 +24,8 @@ import org.jetbrains.annotations.Unmodifiable; @Unmodifiable class NativePonyData implements IPonyData { private final TriggerPixelValue race; - private final TriggerPixelValue tailSize; + private final TriggerPixelValue tailLength; + private final TriggerPixelValue tailShape; private final TriggerPixelValue gender; private final TriggerPixelValue size; private final int glowColor; @@ -41,14 +36,16 @@ class NativePonyData implements IPonyData { NativePonyData(NativeImage image) { race = TriggerPixel.RACE.readValue(image); - tailSize = TriggerPixel.TAIL.readValue(image); + tailLength = TriggerPixel.TAIL.readValue(image); + tailShape = TriggerPixel.TAIL_SHAPE.readValue(image); size = TriggerPixel.SIZE.readValue(image); gender = TriggerPixel.GENDER.readValue(image); glowColor = TriggerPixel.GLOW.readColor(image); wearables = TriggerPixel.WEARABLES.readFlags(image); attributes.put("race", race); - attributes.put("tail", tailSize); + attributes.put("tailLength", tailLength); + attributes.put("tailShape", tailShape); attributes.put("gender", gender); attributes.put("size", size); attributes.put("magic", TriggerPixelType.of(glowColor)); @@ -61,8 +58,13 @@ class NativePonyData implements IPonyData { } @Override - public TailLength getTail() { - return tailSize.getValue(); + public TailLength getTailLength() { + return tailLength.getValue(); + } + + @Override + public TailShape getTailShape() { + return tailShape.getValue(); } @Override @@ -110,6 +112,7 @@ class NativePonyData implements IPonyData { return Interpolator.linear(interpolatorId); } + @Override public Map> getTriggerPixels() { return attributes; } @@ -118,7 +121,8 @@ class NativePonyData implements IPonyData { public String toString() { return MoreObjects.toStringHelper(this) .add("race", race.getValue()) - .add("tailSize", tailSize.getValue()) + .add("tailLength", tailLength.getValue()) + .add("tailShape", tailShape.getValue()) .add("gender", gender.getValue()) .add("size", size.getValue()) .add("wearables", getGear()) diff --git a/src/main/java/com/minelittlepony/client/pony/PonyData.java b/src/main/java/com/minelittlepony/client/pony/PonyData.java index 224ad9d1..755146fb 100644 --- a/src/main/java/com/minelittlepony/client/pony/PonyData.java +++ b/src/main/java/com/minelittlepony/client/pony/PonyData.java @@ -6,11 +6,7 @@ import com.google.common.base.MoreObjects; import com.google.gson.annotations.Expose; import com.minelittlepony.api.pony.IPonyData; import com.minelittlepony.api.pony.TriggerPixelType; -import com.minelittlepony.api.pony.meta.Gender; -import com.minelittlepony.api.pony.meta.Race; -import com.minelittlepony.api.pony.meta.Sizes; -import com.minelittlepony.api.pony.meta.TailLength; -import com.minelittlepony.api.pony.meta.Wearable; +import com.minelittlepony.api.pony.meta.*; import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.util.render.NativeUtil; import com.minelittlepony.common.util.animation.Interpolator; @@ -65,32 +61,30 @@ public class PonyData implements IPonyData { private final Race race; @Expose - private final TailLength tailSize; + private final TailLength tailLength = TailLength.FULL; @Expose - private final Gender gender; + private final TailShape tailShape = TailShape.STRAIGHT; @Expose - private final Sizes size; + private final Gender gender = Gender.MARE; @Expose - private final int glowColor; + private final Sizes size = Sizes.NORMAL; @Expose - private final boolean[] wearables; + private final int glowColor = 0x4444aa; + + @Expose + private final boolean[] wearables = new boolean[Wearable.values().length]; private final Map> attributes = new TreeMap<>(); public PonyData(Race race) { this.race = race; - tailSize = TailLength.FULL; - gender = Gender.MARE; - size = Sizes.NORMAL; - glowColor = 0x4444aa; - wearables = new boolean[Wearable.values().length]; - attributes.put("race", race); - attributes.put("tail", tailSize); + attributes.put("tailLength", tailLength); + attributes.put("tailShape", tailShape); attributes.put("gender", gender); attributes.put("size", size); attributes.put("magic", TriggerPixelType.of(glowColor)); @@ -103,8 +97,14 @@ public class PonyData implements IPonyData { } @Override - public TailLength getTail() { - return tailSize; + public TailLength getTailLength() { + return tailLength; + } + + + @Override + public TailShape getTailShape() { + return tailShape; } @Override @@ -160,7 +160,8 @@ public class PonyData implements IPonyData { public String toString() { return MoreObjects.toStringHelper(this) .add("race", race) - .add("tailSize", tailSize) + .add("tailLength", tailLength) + .add("tailShape", tailShape) .add("gender", gender) .add("size", size) .add("wearables", getGear())