diff --git a/build.gradle b/build.gradle index c2e83fa1..1b589aa2 100644 --- a/build.gradle +++ b/build.gradle @@ -53,7 +53,22 @@ repositories { } fabricApi { - configureDataGeneration() + configureDataGeneration { + modId = "timeless" + } +} + +sourceSets { + main { + resources { + srcDirs += "src/main/generated" + } + } +} + +processResources { + exclude ".cache/**" + duplicatesStrategy = DuplicatesStrategy.INCLUDE } dependencies { @@ -124,3 +139,5 @@ publishing { // retrieving dependencies. } } + + diff --git a/src/main/java/mc/duzo/timeless/client/keybind/DoubleTapJumpFlight.java b/src/main/java/mc/duzo/timeless/client/keybind/DoubleTapJumpFlight.java new file mode 100644 index 00000000..9adeb0a0 --- /dev/null +++ b/src/main/java/mc/duzo/timeless/client/keybind/DoubleTapJumpFlight.java @@ -0,0 +1,58 @@ +package mc.duzo.timeless.client.keybind; + +import java.util.Optional; + +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; + +import net.minecraft.client.network.ClientPlayerEntity; + +import mc.duzo.timeless.network.c2s.UsePowerC2SPacket; +import mc.duzo.timeless.power.Power; +import mc.duzo.timeless.power.PowerList; +import mc.duzo.timeless.power.impl.FlightPower; +import mc.duzo.timeless.suit.Suit; + +public class DoubleTapJumpFlight { + private static final long DOUBLE_TAP_WINDOW_MS = 300; + private static long lastPressTime = 0; + private static boolean wasJumping = false; + + public static void tick(ClientPlayerEntity player) { + boolean isJumping = player.input.jumping; + boolean justPressed = isJumping && !wasJumping; + wasJumping = isJumping; + + if (!justPressed) return; + + long now = System.currentTimeMillis(); + if (lastPressTime != 0 && now - lastPressTime <= DOUBLE_TAP_WINDOW_MS) { + tryActivateFlight(player); + lastPressTime = 0; + } else { + lastPressTime = now; + } + } + + private static void tryActivateFlight(ClientPlayerEntity player) { + if (FlightPower.hasFlight(player)) return; + + Optional maybeSuit = Suit.findSuit(player); + if (maybeSuit.isEmpty()) return; + + Suit suit = maybeSuit.get(); + if (!suit.getSet().isWearing(player)) return; + + PowerList powers = suit.getPowers(); + int flightIndex = -1; + for (int i = 0; i < powers.size(); i++) { + Power p = powers.get(i); + if (p instanceof FlightPower) { + flightIndex = i; + break; + } + } + if (flightIndex < 0) return; + + ClientPlayNetworking.send(new UsePowerC2SPacket(flightIndex + 1)); + } +} diff --git a/src/main/java/mc/duzo/timeless/client/keybind/TimelessKeybinds.java b/src/main/java/mc/duzo/timeless/client/keybind/TimelessKeybinds.java index 977f2336..ce2a355d 100644 --- a/src/main/java/mc/duzo/timeless/client/keybind/TimelessKeybinds.java +++ b/src/main/java/mc/duzo/timeless/client/keybind/TimelessKeybinds.java @@ -34,5 +34,6 @@ private static void tick(MinecraftClient client) { binds.forEach(bind -> bind.tick(player)); KeybindSync.tick(player); + DoubleTapJumpFlight.tick(player); } } diff --git a/src/main/java/mc/duzo/timeless/mixin/client/PlayerEntityRendererMixin.java b/src/main/java/mc/duzo/timeless/mixin/client/PlayerEntityRendererMixin.java index 3033245d..f13e2fd4 100644 --- a/src/main/java/mc/duzo/timeless/mixin/client/PlayerEntityRendererMixin.java +++ b/src/main/java/mc/duzo/timeless/mixin/client/PlayerEntityRendererMixin.java @@ -41,7 +41,7 @@ public PlayerEntityRendererMixin(EntityRendererFactory.Context ctx, PlayerEntity this.addFeature(new SuitFeature<>(renderer, ctx.getModelLoader())); } - @Inject(method = "renderArm" , at = @At("HEAD"), cancellable = true) + @Inject(method = "renderArm", at = @At("TAIL")) private void timeless$renderArm(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, AbstractClientPlayerEntity player, ModelPart arm, ModelPart sleeve, CallbackInfo ci){ Suit suit = Suit.findSuit(player, EquipmentSlot.CHEST).orElse(null); if (suit == null) return; @@ -56,6 +56,5 @@ public PlayerEntityRendererMixin(EntityRendererFactory.Context ctx, PlayerEntity boolean isRight = player.getMainArm() == Arm.RIGHT; this.timeless$cachedArmModel.renderArm(isRight, player, 0, matrices, vertexConsumers.getBuffer(RenderLayer.getEntityTranslucent(clientSuit.texture())), light, 1, 1, 1, 1); - ci.cancel(); } } \ No newline at end of file diff --git a/src/main/java/mc/duzo/timeless/power/PowerRegistry.java b/src/main/java/mc/duzo/timeless/power/PowerRegistry.java index dd96e931..e6970f5f 100644 --- a/src/main/java/mc/duzo/timeless/power/PowerRegistry.java +++ b/src/main/java/mc/duzo/timeless/power/PowerRegistry.java @@ -54,6 +54,12 @@ public static T register(T entry) { }) .build().register(); public static Power SWIFT_SNEAK = Power.Builder.create(new Identifier(Timeless.MOD_ID, "swift_sneak")).build().register(); + public static Power INVULNERABILITY = Power.Builder.create(new Identifier(Timeless.MOD_ID, "invulnerability")) + .tick(player -> { + if (player.getServer().getTicks() % 20 != 0) return; + player.addStatusEffect(new StatusEffectInstance(StatusEffects.RESISTANCE, 22, 2, false, false)); + }) + .build().register(); public static void init() {} } diff --git a/src/main/java/mc/duzo/timeless/suit/client/render/SuitFeature.java b/src/main/java/mc/duzo/timeless/suit/client/render/SuitFeature.java index 93ce2ddb..624dc64f 100644 --- a/src/main/java/mc/duzo/timeless/suit/client/render/SuitFeature.java +++ b/src/main/java/mc/duzo/timeless/suit/client/render/SuitFeature.java @@ -52,6 +52,7 @@ private void renderPart(MatrixStack matrixStack, VertexConsumerProvider vertexCo model.setVisibilityForSlot(slot); model.copyFrom(context); model.setAngles(livingEntity, f, g, j, k, l); + model.copyTo(context); model.getCape().ifPresent(cape -> { cape.visible = false; diff --git a/src/main/java/mc/duzo/timeless/suit/client/render/SuitModel.java b/src/main/java/mc/duzo/timeless/suit/client/render/SuitModel.java index 21f05faf..c7ccdb0a 100644 --- a/src/main/java/mc/duzo/timeless/suit/client/render/SuitModel.java +++ b/src/main/java/mc/duzo/timeless/suit/client/render/SuitModel.java @@ -44,6 +44,19 @@ public void render(MatrixStack matrices, VertexConsumer vertices, int light, int public void setAngles(LivingEntity entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) { if (!(entity instanceof AbstractClientPlayerEntity player)) return; this.runAnimations(player, animationProgress); + + SuitAnimationHolder anim = this.getAnimation(player).orElse(null); + if (anim == null || anim.getInfo().transform() == AnimationInfo.Transform.TARGETED) { + this.rotateParts(player); + } + } + + /** + * Override to apply per-frame procedural rotations (e.g. flight tilt). + * Runs from setAngles, before SuitFeature copies the suit pose back to the player biped, + * so any rotations applied here propagate to the player model too. + */ + protected void rotateParts(AbstractClientPlayerEntity player) { } protected void runAnimations(AbstractClientPlayerEntity player, float animationProgress) { diff --git a/src/main/java/mc/duzo/timeless/suit/client/render/generic/AlexSuitModel.java b/src/main/java/mc/duzo/timeless/suit/client/render/generic/AlexSuitModel.java index d1b1af60..9abb8b39 100644 --- a/src/main/java/mc/duzo/timeless/suit/client/render/generic/AlexSuitModel.java +++ b/src/main/java/mc/duzo/timeless/suit/client/render/generic/AlexSuitModel.java @@ -46,23 +46,23 @@ public AlexSuitModel(ClientSuit suit) { public static TexturedModelData getTexturedModelData() { ModelData modelData = new ModelData(); ModelPartData modelPartData = modelData.getRoot(); - ModelPartData head = modelPartData.addChild("head", ModelPartBuilder.create().uv(0, 0).cuboid(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new Dilation(0.0F)) + ModelPartData head = modelPartData.addChild("head", ModelPartBuilder.create().uv(0, 0).cuboid(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new Dilation(0.25F)) .uv(32, 0).cuboid(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new Dilation(0.5F)), ModelTransform.pivot(0.0F, 0.0F, 0.0F)); - ModelPartData body = modelPartData.addChild("body", ModelPartBuilder.create().uv(16, 16).cuboid(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(16, 32).cuboid(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(0.0F, 0.0F, 0.0F)); + ModelPartData body = modelPartData.addChild("body", ModelPartBuilder.create().uv(16, 16).cuboid(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(16, 32).cuboid(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(0.0F, 0.0F, 0.0F)); - ModelPartData right_arm = modelPartData.addChild("right_arm", ModelPartBuilder.create().uv(40, 16).cuboid(-2.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(40, 32).cuboid(-2.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(-5.0F, 2.0F, 0.0F)); + ModelPartData right_arm = modelPartData.addChild("right_arm", ModelPartBuilder.create().uv(40, 16).cuboid(-2.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(40, 32).cuboid(-2.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(-5.0F, 2.0F, 0.0F)); - ModelPartData left_arm = modelPartData.addChild("left_arm", ModelPartBuilder.create().uv(32, 48).cuboid(-1.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(48, 48).cuboid(-1.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(5.0F, 2.0F, 0.0F)); + ModelPartData left_arm = modelPartData.addChild("left_arm", ModelPartBuilder.create().uv(32, 48).cuboid(-1.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(48, 48).cuboid(-1.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(5.0F, 2.0F, 0.0F)); - ModelPartData right_leg = modelPartData.addChild("right_leg", ModelPartBuilder.create().uv(0, 16).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(0, 32).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(-1.9F, 12.0F, 0.0F)); + ModelPartData right_leg = modelPartData.addChild("right_leg", ModelPartBuilder.create().uv(0, 16).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(0, 32).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(-1.9F, 12.0F, 0.0F)); - ModelPartData left_leg = modelPartData.addChild("left_leg", ModelPartBuilder.create().uv(16, 48).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(0, 48).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(1.9F, 12.0F, 0.0F)); + ModelPartData left_leg = modelPartData.addChild("left_leg", ModelPartBuilder.create().uv(16, 48).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(0, 48).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(1.9F, 12.0F, 0.0F)); return TexturedModelData.of(modelData, 64, 64); } @@ -73,13 +73,6 @@ public void render(LivingEntity entity, float tickDelta, MatrixStack matrices, V matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180f)); } - if (entity instanceof AbstractClientPlayerEntity player) { - SuitAnimationHolder anim = this.getAnimation(player).orElse(null); - if (anim == null || anim.getInfo().transform() == AnimationInfo.Transform.TARGETED) { - this.rotateParts(player); - } - } - this.getPart().render(matrices, vertexConsumers, light, OverlayTexture.DEFAULT_UV, r, g, b, alpha); matrices.pop(); } @@ -109,7 +102,8 @@ private void renderLeftArm(AbstractClientPlayerEntity player, int i, MatrixStack matrices.pop(); } - private void rotateParts(AbstractClientPlayerEntity entity) { + @Override + protected void rotateParts(AbstractClientPlayerEntity entity) { if (!FlightPower.isFlying(entity)) return; Vec3d velocity = entity.getVelocity().rotateY(((float) Math.toRadians(entity.getYaw()))); diff --git a/src/main/java/mc/duzo/timeless/suit/client/render/generic/SteveSuitModel.java b/src/main/java/mc/duzo/timeless/suit/client/render/generic/SteveSuitModel.java index 8c54ade4..82113bdf 100644 --- a/src/main/java/mc/duzo/timeless/suit/client/render/generic/SteveSuitModel.java +++ b/src/main/java/mc/duzo/timeless/suit/client/render/generic/SteveSuitModel.java @@ -46,23 +46,23 @@ public SteveSuitModel(ClientSuit suit) { public static TexturedModelData getTexturedModelData() { ModelData modelData = new ModelData(); ModelPartData modelPartData = modelData.getRoot(); - ModelPartData head = modelPartData.addChild("head", ModelPartBuilder.create().uv(0, 0).cuboid(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new Dilation(0.0F)) + ModelPartData head = modelPartData.addChild("head", ModelPartBuilder.create().uv(0, 0).cuboid(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new Dilation(0.25F)) .uv(32, 0).cuboid(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new Dilation(0.5F)), ModelTransform.pivot(0.0F, 0.0F, 0.0F)); - ModelPartData body = modelPartData.addChild("body", ModelPartBuilder.create().uv(16, 16).cuboid(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(16, 32).cuboid(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(0.0F, 0.0F, 0.0F)); + ModelPartData body = modelPartData.addChild("body", ModelPartBuilder.create().uv(16, 16).cuboid(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(16, 32).cuboid(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(0.0F, 0.0F, 0.0F)); - ModelPartData right_arm = modelPartData.addChild("right_arm", ModelPartBuilder.create().uv(40, 16).cuboid(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(40, 32).cuboid(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(-5.0F, 2.0F, 0.0F)); + ModelPartData right_arm = modelPartData.addChild("right_arm", ModelPartBuilder.create().uv(40, 16).cuboid(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(40, 32).cuboid(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(-5.0F, 2.0F, 0.0F)); - ModelPartData left_arm = modelPartData.addChild("left_arm", ModelPartBuilder.create().uv(32, 48).cuboid(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(48, 48).cuboid(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(5.0F, 2.0F, 0.0F)); + ModelPartData left_arm = modelPartData.addChild("left_arm", ModelPartBuilder.create().uv(32, 48).cuboid(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(48, 48).cuboid(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(5.0F, 2.0F, 0.0F)); - ModelPartData right_leg = modelPartData.addChild("right_leg", ModelPartBuilder.create().uv(0, 16).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(0, 32).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(-1.9F, 12.0F, 0.0F)); + ModelPartData right_leg = modelPartData.addChild("right_leg", ModelPartBuilder.create().uv(0, 16).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(0, 32).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(-1.9F, 12.0F, 0.0F)); - ModelPartData left_leg = modelPartData.addChild("left_leg", ModelPartBuilder.create().uv(16, 48).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.0F)) - .uv(0, 48).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)), ModelTransform.pivot(1.9F, 12.0F, 0.0F)); + ModelPartData left_leg = modelPartData.addChild("left_leg", ModelPartBuilder.create().uv(16, 48).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.25F)) + .uv(0, 48).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new Dilation(0.5F)), ModelTransform.pivot(1.9F, 12.0F, 0.0F)); return TexturedModelData.of(modelData, 64, 64); } @@ -73,13 +73,6 @@ public void render(LivingEntity entity, float tickDelta, MatrixStack matrices, V matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180f)); } - if (entity instanceof AbstractClientPlayerEntity player) { - SuitAnimationHolder anim = this.getAnimation(player).orElse(null); - if (anim == null || anim.getInfo().transform() == AnimationInfo.Transform.TARGETED) { - this.rotateParts(player); - } - } - this.getPart().render(matrices, vertexConsumers, light, OverlayTexture.DEFAULT_UV, r, g, b, alpha); matrices.pop(); } @@ -109,7 +102,8 @@ private void renderLeftArm(AbstractClientPlayerEntity player, int i, MatrixStack matrices.pop(); } - private void rotateParts(AbstractClientPlayerEntity entity) { + @Override + protected void rotateParts(AbstractClientPlayerEntity entity) { if (!FlightPower.isFlying(entity)) return; Vec3d velocity = entity.getVelocity().rotateY(((float) Math.toRadians(entity.getYaw()))); diff --git a/src/main/java/mc/duzo/timeless/suit/ironman/client/GenericIronManModel.java b/src/main/java/mc/duzo/timeless/suit/ironman/client/GenericIronManModel.java index c45337bc..de2be618 100644 --- a/src/main/java/mc/duzo/timeless/suit/ironman/client/GenericIronManModel.java +++ b/src/main/java/mc/duzo/timeless/suit/ironman/client/GenericIronManModel.java @@ -302,12 +302,7 @@ public void render(LivingEntity entity, float tickDelta, MatrixStack matrices, V float pivotFix = -22F; - if (entity instanceof AbstractClientPlayerEntity player) { - SuitAnimationHolder anim = this.getAnimation(player).orElse(null); - if (anim == null || anim.getInfo().transform() == AnimationInfo.Transform.TARGETED) { - this.rotateParts(player); - } - + if (entity instanceof AbstractClientPlayerEntity) { pivotFix = 2F; matrices.translate(0f, -1.5125f, 0f); matrices.scale(1.01f, 1.01f, 1.01f); @@ -322,7 +317,8 @@ public void render(LivingEntity entity, float tickDelta, MatrixStack matrices, V matrices.pop(); } - private void rotateParts(AbstractClientPlayerEntity entity) { + @Override + protected void rotateParts(AbstractClientPlayerEntity entity) { if (!FlightPower.isFlying(entity)) return; Vec3d velocity = entity.getVelocity().rotateY(((float) Math.toRadians(entity.getYaw()))); diff --git a/src/main/java/mc/duzo/timeless/suit/ironman/mk5/client/MarkFiveModel.java b/src/main/java/mc/duzo/timeless/suit/ironman/mk5/client/MarkFiveModel.java index 7205639f..fd0bd5da 100644 --- a/src/main/java/mc/duzo/timeless/suit/ironman/mk5/client/MarkFiveModel.java +++ b/src/main/java/mc/duzo/timeless/suit/ironman/mk5/client/MarkFiveModel.java @@ -294,7 +294,6 @@ public void render(LivingEntity entity, float tickDelta, MatrixStack matrices, V if (entity instanceof AbstractClientPlayerEntity player) { SuitAnimationHolder anim = this.getAnimation(player).orElse(null); if (anim == null || anim.getInfo().transform() == AnimationInfo.Transform.TARGETED) { - this.rotateParts(player); matrices.translate(0f, -0.2f, 0f); } } @@ -306,7 +305,8 @@ public void render(LivingEntity entity, float tickDelta, MatrixStack matrices, V matrices.pop(); } - private void rotateParts(AbstractClientPlayerEntity entity) { + @Override + protected void rotateParts(AbstractClientPlayerEntity entity) { if (!FlightPower.isFlying(entity)) return; Vec3d velocity = entity.getVelocity().rotateY(((float) Math.toRadians(entity.getYaw()))); diff --git a/src/main/java/mc/duzo/timeless/suit/set/SetRegistry.java b/src/main/java/mc/duzo/timeless/suit/set/SetRegistry.java index dfea107e..831d1e84 100644 --- a/src/main/java/mc/duzo/timeless/suit/set/SetRegistry.java +++ b/src/main/java/mc/duzo/timeless/suit/set/SetRegistry.java @@ -4,6 +4,8 @@ import mc.duzo.timeless.suit.moonknight.jake.JakeSuit; import mc.duzo.timeless.suit.moonknight.marc.MarcSuit; import mc.duzo.timeless.suit.moonknight.steven.StevenSuit; +import mc.duzo.timeless.suit.superman.generic.GenericSupermanSuit; +import mc.duzo.timeless.suit.superman.item.SupermanSuitItem; import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder; import net.minecraft.registry.Registry; @@ -32,6 +34,7 @@ public static T register(T suit) { public static SuitSet MARK_THREE; public static SuitSet MARK_TWO; public static SuitSet BATMAN_66; + public static SuitSet SUPERMAN; public static SuitSet MOON_KNIGHT_MARC; public static SuitSet MOON_KNIGHT_JAKE; public static SuitSet MOON_KNIGHT_STEVEN; @@ -45,6 +48,9 @@ public static void init() { // Batman BATMAN_66 = register(new RegisteringSuitSet(new Batman66Suit(), BatmanSuitItem::new)); + + // Superman + SUPERMAN = register(new RegisteringSuitSet(new GenericSupermanSuit(), SupermanSuitItem::new)); MOON_KNIGHT_MARC = register(new RegisteringSuitSet(new MarcSuit(), MoonKnightSuitItem::new)); MOON_KNIGHT_JAKE = register(new RegisteringSuitSet(new JakeSuit(), MoonKnightSuitItem::new)); MOON_KNIGHT_STEVEN = register(new RegisteringSuitSet(new StevenSuit(), MoonKnightSuitItem::new)); diff --git a/src/main/java/mc/duzo/timeless/suit/superman/SupermanSuit.java b/src/main/java/mc/duzo/timeless/suit/superman/SupermanSuit.java new file mode 100644 index 00000000..290f49c2 --- /dev/null +++ b/src/main/java/mc/duzo/timeless/suit/superman/SupermanSuit.java @@ -0,0 +1,52 @@ +package mc.duzo.timeless.suit.superman; + +import mc.duzo.timeless.Timeless; +import mc.duzo.timeless.datagen.provider.lang.AutomaticSuitEnglish; +import mc.duzo.timeless.power.PowerList; +import mc.duzo.timeless.suit.Suit; +import mc.duzo.timeless.suit.api.FlightSuit; +import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.Identifier; + +public abstract class SupermanSuit extends Suit implements AutomaticSuitEnglish, FlightSuit { + private final Identifier id; + protected final PowerList powers; + + protected SupermanSuit(Identifier id, PowerList powers) { + this.id = id; + this.powers = powers; + } + + protected SupermanSuit(String mark, String modid, PowerList powers) { + this(new Identifier(modid, "superman_" + mark), powers); + } + + /** + * For Timeless heroes ONLY + * Addon mods should use other constructor + */ + protected SupermanSuit(String mark, PowerList powers) { + this(mark, Timeless.MOD_ID, powers); + } + + @Override + public PowerList getPowers() { + return powers; + } + + @Override + public boolean isBinding() { + return false; + } + + @Override + public Identifier id() { + return this.id; + } + + @Override + public SoundEvent getStepSound() { + return SoundEvents.BLOCK_WOOL_STEP; + } +} diff --git a/src/main/java/mc/duzo/timeless/suit/superman/generic/GenericSupermanSuit.java b/src/main/java/mc/duzo/timeless/suit/superman/generic/GenericSupermanSuit.java new file mode 100644 index 00000000..5872e604 --- /dev/null +++ b/src/main/java/mc/duzo/timeless/suit/superman/generic/GenericSupermanSuit.java @@ -0,0 +1,50 @@ +package mc.duzo.timeless.suit.superman.generic; + +import mc.duzo.animation.generic.VisiblePart; +import mc.duzo.timeless.power.PowerList; +import mc.duzo.timeless.power.PowerRegistry; +import mc.duzo.timeless.suit.client.ClientSuit; +import mc.duzo.timeless.suit.client.render.SuitModel; +import mc.duzo.timeless.suit.client.render.generic.SteveSuitModel; +import mc.duzo.timeless.suit.set.SetRegistry; +import mc.duzo.timeless.suit.set.SuitSet; +import mc.duzo.timeless.suit.superman.SupermanSuit; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.entity.LivingEntity; + +import java.util.List; +import java.util.function.Supplier; + +public class GenericSupermanSuit extends SupermanSuit { + + public GenericSupermanSuit() { + super("generic", PowerList.of(PowerRegistry.BOOSTED_FLIGHT, PowerRegistry.SUPER_STRENGTH, PowerRegistry.SUPER_JUMP, PowerRegistry.SWIFT_SNEAK, PowerRegistry.INVULNERABILITY)); + } + + @Override + public SuitSet getSet() { + return SetRegistry.SUPERMAN; + } + + @Override + @Environment(EnvType.CLIENT) + protected ClientSuit createClient() { + return new ClientSuit(this) { + @Override + public Supplier model() { + return () -> new SteveSuitModel(this); + } + + @Override + public List getVisibleParts(LivingEntity entity) { + return List.of(VisiblePart.HEAD, VisiblePart.LEFT_ARM, VisiblePart.LEFT_SLEEVE, VisiblePart.RIGHT_ARM, VisiblePart.RIGHT_SLEEVE); + } + }; + } + + @Override + public int getFlightSpeed(boolean hasBoost) { + return 50; + } +} diff --git a/src/main/java/mc/duzo/timeless/suit/superman/item/SupermanSuitItem.java b/src/main/java/mc/duzo/timeless/suit/superman/item/SupermanSuitItem.java new file mode 100644 index 00000000..2a117ebd --- /dev/null +++ b/src/main/java/mc/duzo/timeless/suit/superman/item/SupermanSuitItem.java @@ -0,0 +1,39 @@ +package mc.duzo.timeless.suit.superman.item; + +import mc.duzo.timeless.core.items.SuitItem; +import mc.duzo.timeless.core.items.SuitMaterial; +import mc.duzo.timeless.datagen.provider.lang.AutomaticSuitEnglish; +import mc.duzo.timeless.datagen.provider.model.AutomaticModel; +import mc.duzo.timeless.suit.Suit; +import net.fabricmc.fabric.api.item.v1.FabricItemSettings; +import net.minecraft.item.ArmorItem; +import net.minecraft.item.Item; +import net.minecraft.item.Items; +import net.minecraft.recipe.Ingredient; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.Util; + +import java.util.EnumMap; + +public class SupermanSuitItem extends SuitItem implements AutomaticModel, AutomaticSuitEnglish { + public SupermanSuitItem(Suit suit, Type type) { + super(suit, SupermanMaterial.INSTANCE, type, new FabricItemSettings().maxCount(1)); + } + + private static class SupermanMaterial extends SuitMaterial { + public SupermanMaterial(Item repair) { + super("superman", 33, Util.make(new EnumMap(ArmorItem.Type.class), map -> { + map.put(ArmorItem.Type.BOOTS, 3); + map.put(ArmorItem.Type.LEGGINGS, 6); + map.put(ArmorItem.Type.CHESTPLATE, 8); + map.put(ArmorItem.Type.HELMET, 3); + }), 10, SoundEvents.ITEM_ARMOR_EQUIP_LEATHER, 2.0F, 0.0F, () -> Ingredient.ofItems(repair)); + } + + public SupermanMaterial() { + this(Items.LEATHER); // todo + } + + public static SupermanMaterial INSTANCE = new SupermanMaterial(); + } +} diff --git a/src/main/resources/assets/timeless/textures/suit/superman_generic.png b/src/main/resources/assets/timeless/textures/suit/superman_generic.png new file mode 100644 index 00000000..39899487 Binary files /dev/null and b/src/main/resources/assets/timeless/textures/suit/superman_generic.png differ