From 6bcfdf5ca9e56faa17df77f204221268df8b02cf Mon Sep 17 00:00:00 2001 From: TGdoesCode Date: Thu, 5 Feb 2026 08:59:06 +0100 Subject: [PATCH] shit --- .../szar/client/HitterEntityRenderer.java | 27 ++ .../szar/client/PlaneAnimationResolver.java | 23 ++ .../szar/client/PlaneEntityAnimations.java | 207 +++++++++++ .../szar/client/PlaneEntityModel.java | 124 +++++++ .../szar/client/PlaneEntityRenderer.java | 60 ++++ .../dev/tggamesyt/szar/client/SzarClient.java | 52 +++ .../java/dev/tggamesyt/szar/HitterEntity.java | 69 ++++ .../java/dev/tggamesyt/szar/NaziEntity.java | 65 ++++ .../dev/tggamesyt/szar/PlaneAnimation.java | 17 + .../java/dev/tggamesyt/szar/PlaneEntity.java | 324 ++++++++++++++++++ src/main/java/dev/tggamesyt/szar/Szar.java | 141 +++++++- .../resources/assets/szar/lang/en_us.json | 5 +- .../szar/models/item/hitler_spawn_egg.json | 3 + .../assets/szar/textures/entity/hitter.png | Bin 0 -> 2086 bytes .../assets/szar/textures/entity/plane.png | Bin 0 -> 1247 bytes src/main/resources/szar.accesswidener | 3 +- 16 files changed, 1117 insertions(+), 3 deletions(-) create mode 100644 src/client/java/dev/tggamesyt/szar/client/HitterEntityRenderer.java create mode 100644 src/client/java/dev/tggamesyt/szar/client/PlaneAnimationResolver.java create mode 100644 src/client/java/dev/tggamesyt/szar/client/PlaneEntityAnimations.java create mode 100644 src/client/java/dev/tggamesyt/szar/client/PlaneEntityModel.java create mode 100644 src/client/java/dev/tggamesyt/szar/client/PlaneEntityRenderer.java create mode 100644 src/main/java/dev/tggamesyt/szar/HitterEntity.java create mode 100644 src/main/java/dev/tggamesyt/szar/NaziEntity.java create mode 100644 src/main/java/dev/tggamesyt/szar/PlaneAnimation.java create mode 100644 src/main/java/dev/tggamesyt/szar/PlaneEntity.java create mode 100644 src/main/resources/assets/szar/models/item/hitler_spawn_egg.json create mode 100644 src/main/resources/assets/szar/textures/entity/hitter.png create mode 100644 src/main/resources/assets/szar/textures/entity/plane.png diff --git a/src/client/java/dev/tggamesyt/szar/client/HitterEntityRenderer.java b/src/client/java/dev/tggamesyt/szar/client/HitterEntityRenderer.java new file mode 100644 index 0000000..729359a --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/HitterEntityRenderer.java @@ -0,0 +1,27 @@ +package dev.tggamesyt.szar.client; + +import dev.tggamesyt.szar.HitterEntity; +import dev.tggamesyt.szar.NiggerEntity; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.render.entity.MobEntityRenderer; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.client.render.entity.model.EntityModelLayers; +import net.minecraft.util.Identifier; + +public class HitterEntityRenderer + extends MobEntityRenderer> { + + public HitterEntityRenderer(EntityRendererFactory.Context context) { + super( + context, + new BipedEntityModel<>(context.getPart(EntityModelLayers.PLAYER)), + 0.5F + ); + } + + @Override + public Identifier getTexture(HitterEntity entity) { + return new Identifier("szar", "textures/entity/hitter.png"); + } +} + diff --git a/src/client/java/dev/tggamesyt/szar/client/PlaneAnimationResolver.java b/src/client/java/dev/tggamesyt/szar/client/PlaneAnimationResolver.java new file mode 100644 index 0000000..f23141b --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/PlaneAnimationResolver.java @@ -0,0 +1,23 @@ +package dev.tggamesyt.szar.client; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.entity.animation.Animation; + +import static dev.tggamesyt.szar.PlaneAnimation.*; +import dev.tggamesyt.szar.PlaneAnimation; + +@Environment(EnvType.CLIENT) +public class PlaneAnimationResolver { + + public static Animation resolve(PlaneAnimation anim) { + return switch (anim) { + case START_ENGINE -> PlaneEntityAnimations.start_engine; + case STOP_ENGINE -> PlaneEntityAnimations.stop_engine; + case FLYING -> PlaneEntityAnimations.flying; + case LANDING -> PlaneEntityAnimations.landing; + case LAND_STARTED -> PlaneEntityAnimations.land_started; + case LIFT_UP -> PlaneEntityAnimations.lift_up; + }; + } +} \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/PlaneEntityAnimations.java b/src/client/java/dev/tggamesyt/szar/client/PlaneEntityAnimations.java new file mode 100644 index 0000000..e42c112 --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/PlaneEntityAnimations.java @@ -0,0 +1,207 @@ +package dev.tggamesyt.szar.client;// Save this class in your mod and generate all required imports + +import net.minecraft.client.render.entity.animation.Animation; +import net.minecraft.client.render.entity.animation.AnimationHelper; +import net.minecraft.client.render.entity.animation.Keyframe; +import net.minecraft.client.render.entity.animation.Transformation; + +/** + * Made with Blockbench 5.0.7 + * Exported for Minecraft version 1.19 or later with Yarn mappings + * @author Author + */ +public class PlaneEntityAnimations { + public static final Animation start_engine = Animation.Builder.create(2.2917F) + .addBoneAnimation("rotor", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 360.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 180.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 90.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.7917F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -180.0F), Transformation.Interpolations.LINEAR), + new Keyframe(2.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -900.0F), Transformation.Interpolations.LINEAR), + new Keyframe(2.2917F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -2520.0F), Transformation.Interpolations.LINEAR) + )) + .build(); + + public static final Animation stop_engine = Animation.Builder.create(2.0F) + .addBoneAnimation("rotor", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -2070.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -1440.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -1980.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -2250.0F), Transformation.Interpolations.LINEAR), + new Keyframe(2.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -2520.0F), Transformation.Interpolations.LINEAR) + )) + .build(); + + public static final Animation land_started = Animation.Builder.create(0.25F).looping() + .addBoneAnimation("rotor", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 2520.0F), Transformation.Interpolations.LINEAR) + )) + .build(); + + public static final Animation flying = Animation.Builder.create(0.25F).looping() + .addBoneAnimation("rotor", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 2520.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("right_wheel", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -107.5F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("right_wheel", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("left_wheel", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 107.5F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("left_wheel", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .build(); + + public static final Animation landing = Animation.Builder.create(2.0F) + .addBoneAnimation("base", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.75F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(2.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("rotor", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 2520.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 1800.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.75F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 720.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -360.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -1800.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -3240.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.75F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -4320.0F), Transformation.Interpolations.LINEAR), + new Keyframe(2.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -5760.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("rotor", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.75F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(2.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("back_wing", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.75F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(2.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("right_wing", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.75F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(2.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("left_wing", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.75F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(2.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("right_wheel", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -107.5F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -107.5F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("right_wheel", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("left_wheel", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 107.5F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 107.5F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("left_wheel", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .build(); + + public static final Animation lift_up = Animation.Builder.create(1.5F) + .addBoneAnimation("base", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("base", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("rotor", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 2520.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 1800.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.75F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -2160.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -3600.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -4680.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -6120.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("rotor", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("back_wing", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("right_wing", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("left_wing", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, -1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.25F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.5F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("right_wheel", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, -107.5F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("right_wheel", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("left_wheel", new Transformation(Transformation.Targets.ROTATE, + new Keyframe(0.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(1.0F, AnimationHelper.createRotationalVector(0.0F, 0.0F, 107.5F), Transformation.Interpolations.LINEAR) + )) + .addBoneAnimation("left_wheel", new Transformation(Transformation.Targets.TRANSLATE, + new Keyframe(0.0F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.25F, AnimationHelper.createTranslationalVector(0.0F, 0.0F, 0.0F), Transformation.Interpolations.LINEAR), + new Keyframe(0.5F, AnimationHelper.createTranslationalVector(0.0F, 1.0F, 0.0F), Transformation.Interpolations.LINEAR) + )) + .build(); +} \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/PlaneEntityModel.java b/src/client/java/dev/tggamesyt/szar/client/PlaneEntityModel.java new file mode 100644 index 0000000..0456f4a --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/PlaneEntityModel.java @@ -0,0 +1,124 @@ +package dev.tggamesyt.szar.client; + +import dev.tggamesyt.szar.PlaneEntity; +import dev.tggamesyt.szar.PlaneAnimation; +import net.minecraft.client.model.*; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.entity.animation.Animation; +import net.minecraft.client.render.entity.animation.AnimationHelper; +import net.minecraft.client.render.entity.model.SinglePartEntityModel; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.AnimationState; +import net.minecraft.entity.Entity; +import org.joml.Vector3f; + +// Made with Blockbench 5.0.7 +// Exported for Minecraft version 1.17+ for Yarn +// Paste this class into your mod and generate all required imports +public class PlaneEntityModel extends SinglePartEntityModel { + private final Vector3f tempVec = new Vector3f(); + private final ModelPart root; + private final ModelPart right_wheel; + private final ModelPart base; + private final ModelPart left_wheel; + private final ModelPart left_wing; + private final ModelPart right_wing; + private final ModelPart back_wing; + private final ModelPart rotor; + public PlaneEntityModel(ModelPart root) { + this.root = root; + this.right_wheel = root.getChild("right_wheel"); + this.base = root.getChild("base"); + this.left_wheel = root.getChild("left_wheel"); + this.left_wing = root.getChild("left_wing"); + this.right_wing = root.getChild("right_wing"); + this.back_wing = root.getChild("back_wing"); + this.rotor = root.getChild("rotor"); + } + public final AnimationState engineStart = new AnimationState(); + public final AnimationState flying = new AnimationState(); + public final AnimationState engineStop = new AnimationState(); + + public static TexturedModelData getTexturedModelData() { + ModelData modelData = new ModelData(); + ModelPartData modelPartData = modelData.getRoot(); + ModelPartData right_wheel = modelPartData.addChild("right_wheel", ModelPartBuilder.create().uv(24, 58).cuboid(-2.0F, 3.0F, -1.0F, 2.0F, 2.0F, 2.0F, new Dilation(0.0F)), ModelTransform.pivot(-3.0F, 19.0F, 0.0F)); + + ModelPartData cube_r1 = right_wheel.addChild("cube_r1", ModelPartBuilder.create().uv(32, 58).cuboid(0.0F, -3.0F, -1.0F, 1.0F, 3.0F, 2.0F, new Dilation(0.0F)), ModelTransform.of(-1.0F, 3.0F, 0.0F, 0.0F, 0.0F, 0.3927F)); + + ModelPartData base = modelPartData.addChild("base", ModelPartBuilder.create().uv(24, 55).cuboid(-3.0F, 0.0F, -1.0F, 6.0F, 1.0F, 2.0F, new Dilation(0.0F)) + .uv(0, 24).cuboid(-2.0F, -1.0F, -11.0F, 4.0F, 1.0F, 18.0F, new Dilation(0.0F)) + .uv(44, 24).cuboid(2.0F, -3.0F, -8.0F, 1.0F, 2.0F, 15.0F, new Dilation(0.0F)) + .uv(44, 24).cuboid(-3.0F, -3.0F, -8.0F, 1.0F, 2.0F, 15.0F, new Dilation(0.0F)) + .uv(0, 0).cuboid(-2.0F, -3.0F, -12.0F, 4.0F, 2.0F, 22.0F, new Dilation(0.0F)) + .uv(44, 41).cuboid(-1.0F, -5.0F, -8.0F, 2.0F, 2.0F, 12.0F, new Dilation(0.0F)) + .uv(52, 12).cuboid(-1.0F, -10.0F, 13.0F, 2.0F, 7.0F, 4.0F, new Dilation(0.0F)) + .uv(24, 62).cuboid(-1.0F, -3.0F, -13.0F, 2.0F, 1.0F, 1.0F, new Dilation(0.0F)) + .uv(0, 55).cuboid(1.0F, -5.0F, -7.0F, 1.0F, 2.0F, 11.0F, new Dilation(0.0F)) + .uv(0, 55).cuboid(-2.0F, -5.0F, -7.0F, 1.0F, 2.0F, 11.0F, new Dilation(0.0F)) + .uv(34, 51).cuboid(-1.0F, -4.0F, 4.0F, 2.0F, 1.0F, 3.0F, new Dilation(0.0F)) + .uv(60, 61).cuboid(1.0F, -4.0F, 4.0F, 1.0F, 1.0F, 2.0F, new Dilation(0.0F)) + .uv(60, 61).cuboid(-2.0F, -4.0F, 4.0F, 1.0F, 1.0F, 2.0F, new Dilation(0.0F)) + .uv(52, 0).cuboid(-1.0F, -6.0F, -7.0F, 2.0F, 1.0F, 11.0F, new Dilation(0.0F)) + .uv(52, 61).cuboid(-1.0F, -5.0F, 4.0F, 2.0F, 1.0F, 2.0F, new Dilation(0.0F)) + .uv(38, 62).cuboid(-1.0F, -4.0F, -9.0F, 2.0F, 1.0F, 1.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 19.0F, 0.0F)); + + ModelPartData cube_r2 = base.addChild("cube_r2", ModelPartBuilder.create().uv(40, 55).cuboid(-1.0F, -2.0F, -1.0F, 2.0F, 3.0F, 4.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, -2.0F, 11.0F, 0.3927F, 0.0F, 0.0F)); + + ModelPartData left_wheel = modelPartData.addChild("left_wheel", ModelPartBuilder.create().uv(24, 58).cuboid(0.0F, 3.0F, -1.0F, 2.0F, 2.0F, 2.0F, new Dilation(0.0F)), ModelTransform.pivot(3.0F, 19.0F, 0.0F)); + + ModelPartData cube_r3 = left_wheel.addChild("cube_r3", ModelPartBuilder.create().uv(32, 58).cuboid(-1.0F, -3.0F, -1.0F, 1.0F, 3.0F, 2.0F, new Dilation(0.0F)), ModelTransform.of(1.0F, 3.0F, 0.0F, 0.0F, 0.0F, -0.3927F)); + + ModelPartData left_wing = modelPartData.addChild("left_wing", ModelPartBuilder.create(), ModelTransform.pivot(2.0F, 18.0F, -5.0F)); + + ModelPartData cube_r4 = left_wing.addChild("cube_r4", ModelPartBuilder.create().uv(0, 43).cuboid(0.0F, 0.0F, 0.0F, 15.0F, 1.0F, 7.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, 0.0F, -0.3927F, 0.0F)); + + ModelPartData right_wing = modelPartData.addChild("right_wing", ModelPartBuilder.create(), ModelTransform.pivot(-2.0F, 18.0F, -5.0F)); + + ModelPartData cube_r5 = right_wing.addChild("cube_r5", ModelPartBuilder.create().uv(0, 43).cuboid(-15.0F, 0.0F, 0.0F, 15.0F, 1.0F, 7.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, 0.0F, 0.3927F, 0.0F)); + + ModelPartData back_wing = modelPartData.addChild("back_wing", ModelPartBuilder.create(), ModelTransform.pivot(0.0F, 16.0F, 14.0F)); + + ModelPartData cube_r6 = back_wing.addChild("cube_r6", ModelPartBuilder.create().uv(0, 51).cuboid(-7.0F, -1.0F, 0.0F, 14.0F, 1.0F, 3.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, 0.3927F, 0.0F, 0.0F)); + + ModelPartData rotor = modelPartData.addChild("rotor", ModelPartBuilder.create().uv(52, 55).cuboid(-3.0F, -3.0F, 0.0F, 6.0F, 6.0F, 0.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 16.0F, -13.0F)); + return TexturedModelData.of(modelData, 128, 128); + } + + @Override + public void render(MatrixStack matrices, VertexConsumer vertexConsumer, int light, int overlay, float red, float green, float blue, float alpha) { + right_wheel.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha); + base.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha); + left_wheel.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha); + left_wing.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha); + right_wing.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha); + back_wing.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha); + rotor.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha); + } + + @Override + public ModelPart getPart() { + return this.root; + } + + @Override + public void setAngles(Entity entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) { + // Reset transforms + this.root.traverse().forEach(ModelPart::resetTransform); + if (entity instanceof PlaneEntity planeEntity) { + PlaneAnimation anim = planeEntity.getCurrentAnimation(); + + if (anim != null) { + AnimationHelper.animate( + this, + PlaneAnimationResolver.resolve(anim), + planeEntity.age, + 1.0F, + tempVec + ); + } else { + this.root.traverse().forEach(ModelPart::resetTransform); + } + } + } +} \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/PlaneEntityRenderer.java b/src/client/java/dev/tggamesyt/szar/client/PlaneEntityRenderer.java new file mode 100644 index 0000000..d7de19d --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/PlaneEntityRenderer.java @@ -0,0 +1,60 @@ +package dev.tggamesyt.szar.client; + +import dev.tggamesyt.szar.PlaneEntity; + +import net.minecraft.client.render.*; +import net.minecraft.client.render.entity.*; +import net.minecraft.client.render.entity.model.EntityModelLayer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Identifier; + +public class PlaneEntityRenderer extends EntityRenderer { + + public static final EntityModelLayer MODEL_LAYER = + new EntityModelLayer(new Identifier("szar", "plane"), "main"); + + private final PlaneEntityModel model; + + public PlaneEntityRenderer(EntityRendererFactory.Context ctx) { + super(ctx); + this.model = new PlaneEntityModel(ctx.getPart(MODEL_LAYER)); + } + + @Override + public Identifier getTexture(PlaneEntity entity) { + return new Identifier("szar", "textures/entity/plane.png"); + } + + @Override + public void render( + PlaneEntity entity, + float yaw, + float tickDelta, + MatrixStack matrices, + VertexConsumerProvider vertices, + int light + ) { + matrices.push(); + matrices.scale(4.0F, 4.0F, 4.0F); + matrices.translate(0.0, 1.5, 0.0); + matrices.scale(-1.0F, -1.0F, 1.0F); + + model.setAngles( + entity, + 0, + 0, + entity.age + tickDelta, + 0, + 0 + ); + + VertexConsumer consumer = + vertices.getBuffer(RenderLayer.getEntityCutout(getTexture(entity))); + + model.render(matrices, consumer, light, OverlayTexture.DEFAULT_UV, + 1.0F, 1.0F, 1.0F, 1.0F); + + matrices.pop(); + super.render(entity, yaw, tickDelta, matrices, vertices, light); + } +} diff --git a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java index 208b7e2..a14b602 100644 --- a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java +++ b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java @@ -1,18 +1,24 @@ package dev.tggamesyt.szar.client; import com.mojang.blaze3d.systems.RenderSystem; +import dev.tggamesyt.szar.PlaneEntity; import dev.tggamesyt.szar.Szar; +import dev.tggamesyt.szar.PlaneAnimation; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry; import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry; import net.minecraft.client.MinecraftClient; import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.render.entity.animation.Animation; +import net.minecraft.client.render.entity.model.EntityModelLayer; import net.minecraft.client.util.InputUtil; import net.minecraft.client.render.*; +import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; @@ -20,11 +26,45 @@ import net.minecraft.util.math.random.Random; import java.util.HashMap; import java.util.Map; +import java.util.UUID; + +import static dev.tggamesyt.szar.Szar.HitterEntityType; +import static dev.tggamesyt.szar.Szar.PLANE_ANIM_PACKET; +import static javax.swing.text.html.HTML.Attribute.ID; public class SzarClient implements ClientModInitializer { private static final Map activeScramble = new HashMap<>(); + public static final EntityModelLayer PLANE = + new EntityModelLayer( + new Identifier("szar", "plane"), + "main" + ); + @Override public void onInitializeClient() { + ClientPlayNetworking.registerGlobalReceiver( + PLANE_ANIM_PACKET, + (client, handler, buf, sender) -> { + + int entityId = buf.readInt(); + PlaneAnimation anim = buf.readEnumConstant(PlaneAnimation.class); + + client.execute(() -> { + if (client.world == null) return; + + Entity e = client.world.getEntityById(entityId); + if (!(e instanceof PlaneEntity plane)) return; + + if (anim == null) { + plane.stopAnimation(); + return; + } + + plane.playAnimation(anim, anim.looping); + }); + } + ); + ClientPlayNetworking.registerGlobalReceiver( Szar.TOTEMPACKET, (client, handler, buf, responseSender) -> { @@ -41,6 +81,10 @@ public class SzarClient implements ClientModInitializer { Szar.NiggerEntityType, NiggerEntityRenderer::new ); + EntityRendererRegistry.register( + Szar.HitterEntityType, + HitterEntityRenderer::new + ); EntityRendererRegistry.register( Szar.PoliceEntityType, PoliceEntityRenderer::new @@ -49,6 +93,14 @@ public class SzarClient implements ClientModInitializer { Szar.TERRORIST_ENTITY_TYPE, TerroristEntityRenderer::new ); + EntityRendererRegistry.register( + Szar.PLANE_ENTITY_TYPE, + PlaneEntityRenderer::new + ); + EntityModelLayerRegistry.registerModelLayer( + PLANE, + PlaneEntityModel::getTexturedModelData + ); EntityRendererRegistry.register( Szar.GYPSY_ENTITY_TYPE, diff --git a/src/main/java/dev/tggamesyt/szar/HitterEntity.java b/src/main/java/dev/tggamesyt/szar/HitterEntity.java new file mode 100644 index 0000000..7d3a505 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/HitterEntity.java @@ -0,0 +1,69 @@ +package dev.tggamesyt.szar; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.ai.goal.LookAroundGoal; +import net.minecraft.entity.ai.goal.MeleeAttackGoal; +import net.minecraft.entity.ai.goal.WanderAroundFarGoal; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.mob.PathAwareEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.*; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.List; + +public class HitterEntity extends PathAwareEntity implements Arrestable{ + + public static boolean arrestable = true; + + public HitterEntity(EntityType type, World world) { + super(type, world); + } + + @Override + protected void initGoals() { + this.goalSelector.add(0, new MeleeAttackGoal(this, 1.2D, true)); + this.goalSelector.add(2, new WanderAroundFarGoal(this, 1.0D)); + this.goalSelector.add(3, new LookAroundGoal(this)); + + this.targetSelector.add(1, new AggroOnHitRevengeGoal(this)); + } + + + public static DefaultAttributeContainer.Builder createAttributes() { + return MobEntity.createMobAttributes() + .add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0) + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25) + .add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 2); + } + + @Override + protected void dropLoot(DamageSource source, boolean causedByPlayer) { + ItemStack book = new ItemStack(Items.WRITTEN_BOOK); + + NbtCompound nbt = book.getOrCreateNbt(); + nbt.putString("title", "Hitler's will"); + nbt.putString("author", "Hitler"); + + // Pages need to be JSON text components + NbtList pages = new NbtList(); + pages.add(NbtString.of("{\"text\":\"Hitler's will\\n - Kill all jews\\n - Kill all players\"}")); + pages.add(NbtString.of("{\"text\":\"die\"}")); + + nbt.put("pages", pages); + + this.dropStack(book); + } + + + + @Override + public boolean isArrestable() { + return arrestable; + } +} diff --git a/src/main/java/dev/tggamesyt/szar/NaziEntity.java b/src/main/java/dev/tggamesyt/szar/NaziEntity.java new file mode 100644 index 0000000..3c609ac --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/NaziEntity.java @@ -0,0 +1,65 @@ +package dev.tggamesyt.szar; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.ai.goal.LookAroundGoal; +import net.minecraft.entity.ai.goal.MeleeAttackGoal; +import net.minecraft.entity.ai.goal.WanderAroundFarGoal; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.mob.PathAwareEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.world.World; + +public class NaziEntity extends PathAwareEntity implements Arrestable{ + + public static boolean arrestable = true; + + public NaziEntity(EntityType type, World world) { + super(type, world); + } + + @Override + protected void initGoals() { + this.goalSelector.add(0, new MeleeAttackGoal(this, 1.2D, true)); + this.goalSelector.add(2, new WanderAroundFarGoal(this, 1.0D)); + this.goalSelector.add(3, new LookAroundGoal(this)); + + this.targetSelector.add(1, new AggroOnHitRevengeGoal(this)); + } + + + public static DefaultAttributeContainer.Builder createAttributes() { + return MobEntity.createMobAttributes() + .add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0) + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25) + .add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 2); + } + + @Override + protected void dropLoot(DamageSource source, boolean causedByPlayer) { + ItemStack book = new ItemStack(Items.WRITTEN_BOOK); + + NbtCompound nbt = book.getOrCreateNbt(); + nbt.putString("title", "Nazi's message"); + nbt.putString("author", "Nazi"); + + // Pages need to be JSON text components + NbtList pages = new NbtList(); + pages.add(NbtString.of("{\"text\":\"Hail Hitler\"}")); + + nbt.put("pages", pages); + + this.dropStack(book); + } + + @Override + public boolean isArrestable() { + return arrestable; + } +} diff --git a/src/main/java/dev/tggamesyt/szar/PlaneAnimation.java b/src/main/java/dev/tggamesyt/szar/PlaneAnimation.java new file mode 100644 index 0000000..a1274f5 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/PlaneAnimation.java @@ -0,0 +1,17 @@ +package dev.tggamesyt.szar; + +public enum PlaneAnimation { + START_ENGINE(false), + STOP_ENGINE(false), + FLYING(true), + LANDING(false), + LAND_STARTED(true), + LIFT_UP(false); + + public final boolean looping; + + PlaneAnimation(boolean looping) { + this.looping = looping; + } +} + diff --git a/src/main/java/dev/tggamesyt/szar/PlaneEntity.java b/src/main/java/dev/tggamesyt/szar/PlaneEntity.java new file mode 100644 index 0000000..d895f7a --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/PlaneEntity.java @@ -0,0 +1,324 @@ +package dev.tggamesyt.szar; + +import dev.tggamesyt.szar.PlaneAnimation; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.PlayerLookup; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.entity.*; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.data.DataTracker; +import net.minecraft.entity.data.TrackedData; +import net.minecraft.entity.data.TrackedDataHandlerRegistry; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +import static dev.tggamesyt.szar.Szar.ANIMATION_TIMINGS; +import static dev.tggamesyt.szar.Szar.ANIMATION_TIMINGS_SECONDS; + +public class PlaneEntity extends Entity { + + /* -------- DATA TRACKER -------- */ + + private static final TrackedData ENGINE_ON = + DataTracker.registerData(PlaneEntity.class, TrackedDataHandlerRegistry.BOOLEAN); + + private static final TrackedData IS_FLYING = + DataTracker.registerData(PlaneEntity.class, TrackedDataHandlerRegistry.BOOLEAN); + // PlaneEntity.java (CLIENT SIDE ONLY FIELDS) + @Environment(EnvType.CLIENT) + private PlaneAnimation currentAnimation; + + @Environment(EnvType.CLIENT) + private long animationStartTick; + + @Environment(EnvType.CLIENT) + private boolean looping; + + // --- SERVER STATE --- + private PlaneAnimation currentServerAnimation = null; + private int animationTick = 0; + private boolean hadPassengerLastTick = false; + private boolean wasFlyingLastTick = false; + + private void playServerAnimation(PlaneAnimation anim) { + if (this.currentServerAnimation == anim) return; + + this.currentServerAnimation = anim; + Szar.playPlaneAnimation(anim, this.getId()); + } + private boolean isAboveGround(double distance) { + return !this.getWorld().isSpaceEmpty( + this, + this.getBoundingBox().offset(0, -distance, 0) + ); + } + + + public PlaneEntity(EntityType type, World world) { + super(type, world); + this.noClip = false; + } + + /* -------- DATA -------- */ + + @Override + protected void initDataTracker() { + this.dataTracker.startTracking(ENGINE_ON, false); + this.dataTracker.startTracking(IS_FLYING, false); + } + + public boolean isEngineOn() { + return dataTracker.get(ENGINE_ON); + } + + public void setEngineOn(boolean value) { + dataTracker.set(ENGINE_ON, value); + } + + public boolean isFlying() { + return dataTracker.get(IS_FLYING); + } + + public void setFlying(boolean value) { + dataTracker.set(IS_FLYING, value); + } + @Environment(EnvType.CLIENT) + public void playAnimation(PlaneAnimation anim, boolean looping) { + this.currentAnimation = anim; + this.looping = looping; + this.animationStartTick = this.age; + } + + @Environment(EnvType.CLIENT) + public void stopAnimation() { + this.currentAnimation = null; + this.looping = false; + } + + @Environment(EnvType.CLIENT) + @Nullable + public PlaneAnimation getCurrentAnimation() { + return currentAnimation; + } + + @Environment(EnvType.CLIENT) + public float getAnimationTime(float tickDelta) { + if (currentAnimation == null) return 0; + + float time = (this.age + tickDelta) - animationStartTick; + + if (looping) { + return time % ANIMATION_TIMINGS_SECONDS.getOrDefault(currentAnimation, -1f); + } + + return Math.min(time, ANIMATION_TIMINGS_SECONDS.getOrDefault(currentAnimation, -1f)); + } + + + /* -------- SAVE / LOAD -------- */ + + @Override + protected void readCustomDataFromNbt(NbtCompound nbt) { + setEngineOn(nbt.getBoolean("EngineOn")); + setFlying(nbt.getBoolean("IsFlying")); + } + + @Override + protected void writeCustomDataToNbt(NbtCompound nbt) { + nbt.putBoolean("EngineOn", isEngineOn()); + nbt.putBoolean("IsFlying", isFlying()); + } + + /* -------- TICK -------- */ + + @Override + public void tick() { + super.tick(); + + if (getWorld().isClient) return; + + PlayerEntity player = getControllingPassenger(); + boolean hasPassenger = player != null; + + // Tick the current animation + if (currentServerAnimation != null) { + animationTick++; + + int duration = ANIMATION_TIMINGS.getOrDefault(currentServerAnimation, -1); + + // If it's a non-looping animation and finished, clear it + if (duration != -1 && animationTick >= duration) { + currentServerAnimation = null; + animationTick = 0; + } + } + + /* -------------------------------- + LANDING / GRAVITY CHECK + -------------------------------- */ + + boolean nearGround = isAboveGround(1.5); + + if (!nearGround && isFlying()) { + setFlying(false); + setNoGravity(false); + playServerAnimation(PlaneAnimation.LANDING); + } + + /* -------------------------------- + PASSENGER STATE CHANGES + -------------------------------- */ + + if (!hadPassengerLastTick && hasPassenger) { + setEngineOn(true); + playServerAnimation(PlaneAnimation.START_ENGINE); + } + + if (hadPassengerLastTick && !hasPassenger) { + setEngineOn(false); + setFlying(false); + setNoGravity(false); + playServerAnimation(PlaneAnimation.STOP_ENGINE); + currentServerAnimation = null; // allow full stop + } + + hadPassengerLastTick = hasPassenger; + + /* -------------------------------- + IDLE (NO PASSENGER) + -------------------------------- */ + + if (!hasPassenger) { + setVelocity(getVelocity().multiply(0.9)); + move(MovementType.SELF, getVelocity()); + return; + } + + /* -------------------------------- + ENGINE RUNNING (ON GROUND) + -------------------------------- */ + + if (isEngineOn() && !isFlying()) { + playServerAnimation(PlaneAnimation.LAND_STARTED); + } + + /* -------------------------------- + FLIGHT TAKEOFF +-------------------------------- */ + boolean nearGroundForTakeoff = isAboveGround(1.5); + boolean wantsTakeoff = player.jumping; + + if (!isFlying()) { + if (wantsTakeoff && nearGroundForTakeoff) { + // Start engine if not on yet + if (!isEngineOn()) { + setEngineOn(true); + playServerAnimation(PlaneAnimation.START_ENGINE); + } + // Play lift up if not already lifting + if (currentServerAnimation != PlaneAnimation.LIFT_UP) { + playServerAnimation(PlaneAnimation.LIFT_UP); + animationTick = 0; + } + } + + // If lift-up animation finished, start flying + if (currentServerAnimation == PlaneAnimation.LIFT_UP) { + int liftUpDuration = ANIMATION_TIMINGS.getOrDefault(PlaneAnimation.LIFT_UP, 10); + if (animationTick >= liftUpDuration) { + setFlying(true); + setNoGravity(true); + playServerAnimation(PlaneAnimation.FLYING); + } + } + } else { + // Already flying, handle in-air movement + setNoGravity(true); + playServerAnimation(PlaneAnimation.FLYING); // ensure looping + } + + /* -------------------------------- + FLIGHT PHYSICS + -------------------------------- */ + + setYaw(player.getYaw()); + setPitch(player.getPitch()); + prevYaw = getYaw(); + + float forward = player.forwardSpeed; + float sideways = player.sidewaysSpeed; + float speed = isFlying() ? 0.4f : 0.15f; + + Vec3d forwardDir = Vec3d.fromPolar(0, getYaw()); + Vec3d velocity = forwardDir.multiply(forward * speed); + setYaw(getYaw() + sideways * 3.0f); + + if (isFlying() && player.isSneaking()) { + velocity = velocity.add(0, -0.06, 0); + } + + setVelocity(getVelocity().add(velocity).multiply(0.98)); + move(MovementType.SELF, getVelocity()); + + wasFlyingLastTick = isFlying(); + } + + + @Override + public ActionResult interact(PlayerEntity player, Hand hand) { + player.startRiding(this); + return ActionResult.SUCCESS; + } + @Override + protected boolean canAddPassenger(Entity passenger) { + return passenger instanceof PlayerEntity && this.getPassengerList().isEmpty(); + } + @Override + public void updatePassengerPosition(Entity passenger, PositionUpdater positionUpdater) { + if (this.hasPassenger(passenger)) { + passenger.setPosition( + this.getX(), + this.getY() + 0.8, // seat height + this.getZ() - 1.0 + ); + } + } + @Nullable + public PlayerEntity getControllingPassenger() { + Entity passenger = this.getFirstPassenger(); + return passenger instanceof PlayerEntity player ? player : null; + } + + @Override + public void updateTrackedPosition(double x, double y, double z) { + super.updateTrackedPosition(x, y, z); + this.prevYaw = this.getYaw(); + } + public static DefaultAttributeContainer.Builder createAttributes() { + return MobEntity.createMobAttributes() + .add(EntityAttributes.GENERIC_MAX_HEALTH, 1.0) + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 1.0) + .add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 1.0); + } + + @Override + public boolean canHit() { + return true; + } + + @Override + public boolean isPushable() { + return true; + } +} diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index 47d419a..68f7ffe 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -1,15 +1,20 @@ package dev.tggamesyt.szar; import com.google.common.collect.ImmutableSet; +import dev.tggamesyt.szar.PlaneAnimation; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.biome.v1.BiomeModifications; import net.fabricmc.fabric.api.biome.v1.BiomeSelectors; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.player.AttackEntityCallback; import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback; import net.fabricmc.fabric.api.item.v1.FabricItemSettings; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; import net.fabricmc.fabric.api.message.v1.ServerMessageDecoratorEvent; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.PlayerLookup; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder; @@ -25,9 +30,12 @@ import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.*; +import net.minecraft.network.PacketByteBuf; import net.minecraft.registry.*; import net.minecraft.registry.tag.BiomeTags; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundEvents; import net.minecraft.structure.StructurePieceType; import net.minecraft.text.Text; @@ -63,6 +71,9 @@ public class Szar implements ModInitializer { public static final String MOD_ID = "szar"; public static final Logger LOGGER = LogManager.getLogger(MOD_ID); + public static MinecraftServer SERVER; + public static final Identifier PLANE_ANIM_PACKET = + new Identifier("szar", "plane_anim"); public static final Block SZAR_BLOCK = new SzarBlock(); public static final TrackedData LAST_CRIME_TICK = @@ -100,6 +111,24 @@ public class Szar implements ModInitializer { .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized .build() ); + public static final EntityType HitterEntityType = + Registry.register( + Registries.ENTITY_TYPE, + new Identifier(MOD_ID, "hitler"), + FabricEntityTypeBuilder + .create(SpawnGroup.CREATURE, HitterEntity::new) + .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized + .build() + ); + public static final EntityType NaziEntityType = + Registry.register( + Registries.ENTITY_TYPE, + new Identifier(MOD_ID, "nazi"), + FabricEntityTypeBuilder + .create(SpawnGroup.CREATURE, NaziEntity::new) + .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized + .build() + ); public static final EntityType PoliceEntityType = Registry.register( Registries.ENTITY_TYPE, @@ -118,6 +147,15 @@ public class Szar implements ModInitializer { .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized .build() ); + public static final EntityType PLANE_ENTITY_TYPE = + Registry.register( + Registries.ENTITY_TYPE, + new Identifier(MOD_ID, "plane"), + FabricEntityTypeBuilder + .create(SpawnGroup.CREATURE, PlaneEntity::new) + .dimensions(EntityDimensions.fixed(5.0F, 2.0F)) + .build() + ); public static final EntityType TERRORIST_ENTITY_TYPE = Registry.register( Registries.ENTITY_TYPE, @@ -163,6 +201,13 @@ public class Szar implements ModInitializer { ); @Override public void onInitialize() { + ServerLifecycleEvents.SERVER_STARTED.register(server -> { + SERVER = server; + }); + + ServerLifecycleEvents.SERVER_STOPPED.register(server -> { + SERVER = null; + }); // register block Registry.register( @@ -301,9 +346,13 @@ public class Szar implements ModInitializer { NiggerEntityType, NiggerEntity.createAttributes() ); + FabricDefaultAttributeRegistry.register( + HitterEntityType, + HitterEntity.createAttributes() + ); FabricDefaultAttributeRegistry.register( PoliceEntityType, - NiggerEntity.createAttributes() + PoliceEntity.createAttributes() ); FabricDefaultAttributeRegistry.register( GYPSY_ENTITY_TYPE, @@ -345,6 +394,46 @@ public class Szar implements ModInitializer { 1, // min group size 2 // max group size ); + // 1. Allow entity A to spawn naturally in your biomes + BiomeModifications.addSpawn( + BiomeSelectors.includeByKey(BiomeKeys.FOREST, BiomeKeys.FLOWER_FOREST), + SpawnGroup.MONSTER, + HitterEntityType, + 5, 1, 1 + ); + + ServerTickEvents.END_WORLD_TICK.register(world -> { + if (world.isClient) return; + + if (world.random.nextInt(200) != 0) return; + + world.getEntitiesByClass( + HitterEntity.class, // <-- your A entity class + entityA -> entityA.isAlive() && !entityA.hasTag("b_group_spawned") + ).forEach(entityA -> { + if (entityA.isAlive() && !entityA.getCommandTags().contains("b_group_spawned")) return; + entityA.addCommandTag("b_group_spawned"); + + int groupSize = 2 + world.random.nextInt(9); // 2–10 Bs + for (int i = 0; i < groupSize; i++) { + Entity entityB = NaziEntityType.create(world); + if (entityB != null) { + double offsetX = (world.random.nextDouble() - 0.5) * 4; + double offsetZ = (world.random.nextDouble() - 0.5) * 4; + entityB.refreshPositionAndAngles( + entityA.getX() + offsetX, + entityA.getY(), + entityA.getZ() + offsetZ, + world.random.nextFloat() * 360, + 0 + ); + world.spawnEntity(entityB); + } + } + }); + }); + + BiomeModifications.addSpawn( BiomeSelectors.includeByKey( BiomeKeys.JUNGLE, @@ -589,6 +678,26 @@ public class Szar implements ModInitializer { new Item.Settings() ) ); + public static final Item HITTER_SPAWNEGG = Registry.register( + Registries.ITEM, + new Identifier(MOD_ID, "hitler_spawn_egg"), + new SpawnEggItem( + HitterEntityType, + 0x000000, + 0xFF0000, + new Item.Settings() + ) + ); + public static final Item NAZI_SPAWNEGG = Registry.register( + Registries.ITEM, + new Identifier(MOD_ID, "hitler_spawn_egg"), + new SpawnEggItem( + NaziEntityType, + 0x000000, + 0xFF0000, + new Item.Settings() + ) + ); public static final Item POLICE_SPAWNEGG = Registry.register( Registries.ITEM, new Identifier(MOD_ID, "police_spawn_egg"), @@ -678,4 +787,34 @@ public class Szar implements ModInitializer { .getProgress(advancement) .isDone(); } + public static void playPlaneAnimation(PlaneAnimation animation, int entityId) { + for (ServerWorld world : SERVER.getWorlds()) { + for (ServerPlayerEntity player : world.getPlayers()) { + PacketByteBuf buf = PacketByteBufs.create(); + buf.writeInt(entityId); // <-- important change + buf.writeEnumConstant(animation); // PlaneAnimation + ServerPlayNetworking.send(player, PLANE_ANIM_PACKET, buf); + } + } + } + public static final Map ANIMATION_TIMINGS = new HashMap<>(); + + static { + ANIMATION_TIMINGS.put(PlaneAnimation.START_ENGINE, 46); // 2.2917s * 20 ticks + ANIMATION_TIMINGS.put(PlaneAnimation.STOP_ENGINE, 40); // 2.0s * 20 ticks + ANIMATION_TIMINGS.put(PlaneAnimation.FLYING, -1); // looping + ANIMATION_TIMINGS.put(PlaneAnimation.LANDING, 40); // 2.0s * 20 ticks + ANIMATION_TIMINGS.put(PlaneAnimation.LAND_STARTED, -1); // looping + ANIMATION_TIMINGS.put(PlaneAnimation.LIFT_UP, 30); // 1.5s * 20 ticks + } + public static final Map ANIMATION_TIMINGS_SECONDS = new HashMap<>(); + + static { + ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.START_ENGINE, 2.2917f); // 2.2917s * 20 ticks + ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.STOP_ENGINE, 20f); // 2.0s * 20 ticks + ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.FLYING, -1f); // looping + ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.LANDING, 2f); // 2.0s * 20 ticks + ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.LAND_STARTED, -1f); // looping + ANIMATION_TIMINGS_SECONDS.put(PlaneAnimation.LIFT_UP, 1.5f); // 1.5s * 20 ticks + } } diff --git a/src/main/resources/assets/szar/lang/en_us.json b/src/main/resources/assets/szar/lang/en_us.json index 59839e1..ae81f3c 100644 --- a/src/main/resources/assets/szar/lang/en_us.json +++ b/src/main/resources/assets/szar/lang/en_us.json @@ -32,5 +32,8 @@ "effect.szar.arrested": "Arrested", "item.szar.police_key": "Police Key", "item.szar.police_handcuff": "Police Handcuff", - "entity.szar.gypsy": "Cigány" + "entity.szar.gypsy": "Cigány", + "entity.szar.plane": "Plane", + "entity.szar.hitler": "Hitler", + "item.szar.hitler_spawn_egg":"Hitler Spawn Egg" } diff --git a/src/main/resources/assets/szar/models/item/hitler_spawn_egg.json b/src/main/resources/assets/szar/models/item/hitler_spawn_egg.json new file mode 100644 index 0000000..ddd1559 --- /dev/null +++ b/src/main/resources/assets/szar/models/item/hitler_spawn_egg.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +} diff --git a/src/main/resources/assets/szar/textures/entity/hitter.png b/src/main/resources/assets/szar/textures/entity/hitter.png new file mode 100644 index 0000000000000000000000000000000000000000..63004598de7a604982bf457cf6afe60ad9a9212d GIT binary patch literal 2086 zcmV+>2-)|EP)&k2Z#`-ttwg1@} z;5C9{-9I}6#`-ttwf~#}uD`R18d$P%KinYxiRw?Jmnz~PZf#R1p04#X0AdsWXxaA( zOvJa$jK*x6e7ak43_#1i%`)f^01G!dIuyuL_uXf2A(J1rp@9sy9~FS1MiKRyyLKnu zZk;bOO8~`R>$s+PebT<9T9zuMFA?jP$@WzM*eC(mxY4Nx#!H7?v2gcnEiSI^WiZ8E&ffT3uli(9d^0ZvFq{r-FlCcM^} zkpRqFuwYofoMgj{k`NT-`4GYQq01u)S4WeK1mIFj3(NtNr_8YjDGH17B>)-)<5Kh< zZtmMuR$#ANoM*3|lV_7>12pRn1kv$N5NlrQ$7?hC6E_rKKRqQ+T%HA?8iZ!P1%I705qZXkpe1YRsIHi3Z(HfN zKQ5bKuV0vNuV0*RZ(3GhSFS9yt5+APpNsCkAa4KLkM_U&asJfz=)Ba3!-o&yeA8*r z-UQoqL)vEmC*`&emZ&zndwM{ypk?HpVB0b_LMsP@nu|}x1*VT!mOPz{DHF$`D9Ots z`AlP}@AHsN;#Mpu-K%cC=2rFrxu@^48CIZ+_^jbPa;jutIK7%MM;5CLkY{g*Y9S z6?P62CmSvE?P}`9-sS*~wgy1H>cj&@walc{(~dIoRrL>aJyBHO#qUlnRdOAK>c)Om zb~;&>^p;RxNtkysq>Ofo%1QIWMji3wQAU7jE=HD8ao2ets!l_J{H}8r_Wn8!r#o}e zcJ(ICbkD%Swp`@oj#r?*>L(in`MS$N)LaZ=N8>|Op6ElRJV;eH^`qv(AnJY(if<0~ zwu}R9=|hmG>|k3?*nU7Rvmoj&1yNZaP<7Qb51{Thhf6DFbe;ncQ(xMP4SP1g4X1Xl zfr&F;eFPJUI^;P3d`ymq7kr%{;^`^puZ0^D4Iq&|k)8pt#3%xJ#)pX_zaJ({Tk=O+ z1D1(bi^szae8zEuSr_@(HNBY&ATNDD`^_#AMPu!i!sWyOxTqgZ<&+Dc?9pnA_VQ=* z0X}5&0oi;&HXjhWG4OGjchpcxowNA>6^8JM0SdG6NZNk|HfQqzKsFyB^Nmk;%monH zd_XoI09mau^C43s*@F+~v?b-z)`XH%L1s8CE36BX;TA&@AJ_F<-^+8i$^&@K2Z+D* zzs?89!pY9&1BPapXU;7bK%JQjAaCXZ$S3N6=jQ;f>EnU903x2Aa{gMlA<+P0^{JK_ z0NyGhFmnOqWlE=%58zLp38uzO$h{^ie-K-KM&1>gFyH-i4?ygCf62!EmI>wvOnmd{ z>*_xRn#Kl*0f?22XxZy}KUM!x7XZH0jI8(bQtw`>{;9W+;rUS{@BEAOdS7U&&86xe zwLgIS1h^-Fdjr@oJHkByyjgLd0Qt)DLbZ>8w%jWq_X)LMK;8i=nyUZ$Mfp-+zFisK zXTW#FQx5GrL^_srqK*)}@&P(8K*~IUtnF2f zK%Upt9s(t+kKR8(8SS-=rj#e+58bIqM}<+H6$Pmjp{e3|G9YF~31FG_8jufpA?l!B zF`<)7$U_F1KJ%S^?S&w!n+DXoe!lbPyMOKh;9dakJs?jRb$sW~cmH}nfmi<#4*=Kj zCb-6T1K0Q_OkeVDzSNn%l<; QcK`qY07*qoM6N<$f?l5c&j0`b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/szar/textures/entity/plane.png b/src/main/resources/assets/szar/textures/entity/plane.png new file mode 100644 index 0000000000000000000000000000000000000000..e6a678668ea572db3a2950666326dbc09d8d498d GIT binary patch literal 1247 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEiDV{ElAr*7p+&x=(%Ynfm zagL|{%7(n6-fpjT@7zR}NU4|U^w%FyIG&*U{w~rrZ&Wf|WZ(4W#^>UL#)lZT+ z4$M3&{OV=PP4mimetU|g9@>5~+?Ny4TB&sR?_BxyZ-Yx)zMn7(W6&It_rQ|rb85)#vo9(i{VUlYIRb?+H&>> z|2lr}3$FF&n<6Wf?$0~_xEMHr{nKY?Ki8=*%RcAoZsvsde2+J?LPBelq+tkbum_e- m|Nr*~*~|tq*g)kIGef7unrHQQuj~hkFnGH9xvX