From 915db8d815a5b443b4e93f932764527ae88038d6 Mon Sep 17 00:00:00 2001 From: TGGamesYT Date: Tue, 24 Feb 2026 15:20:19 +0100 Subject: [PATCH] another kid update --- gradle.properties | 2 +- .../java/dev/tggamesyt/szar/KidEntity.java | 232 +++++++++++++++++- src/main/java/dev/tggamesyt/szar/Szar.java | 25 +- 3 files changed, 249 insertions(+), 10 deletions(-) diff --git a/gradle.properties b/gradle.properties index b5c6297..7d7dc70 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.2.23.1 +mod_version=26.2.24 maven_group=dev.tggamesyt archives_base_name=szar # Dependencies diff --git a/src/main/java/dev/tggamesyt/szar/KidEntity.java b/src/main/java/dev/tggamesyt/szar/KidEntity.java index 9053eee..fde2e91 100644 --- a/src/main/java/dev/tggamesyt/szar/KidEntity.java +++ b/src/main/java/dev/tggamesyt/szar/KidEntity.java @@ -1,7 +1,10 @@ package dev.tggamesyt.szar; import net.minecraft.block.Blocks; +import net.minecraft.entity.EntityDimensions; +import net.minecraft.entity.EntityPose; import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.goal.*; import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.attribute.EntityAttributes; @@ -13,7 +16,11 @@ import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import java.util.Optional; @@ -27,9 +34,11 @@ public class KidEntity extends PathAwareEntity { DataTracker.registerData(KidEntity.class, TrackedDataHandlerRegistry.OPTIONAL_UUID); private static final TrackedData> PARENT_B = DataTracker.registerData(KidEntity.class, TrackedDataHandlerRegistry.OPTIONAL_UUID); - + private static final TrackedData STAYING = + DataTracker.registerData(KidEntity.class, TrackedDataHandlerRegistry.BOOLEAN); public static final int MAX_AGE = 360000; // 30 days * 10h - + private BlockPos stayPos; + private BlockPos lastSeenParentPos; public KidEntity(EntityType type, World world) { super(type, world); } @@ -40,6 +49,7 @@ public class KidEntity extends PathAwareEntity { this.dataTracker.startTracking(AGE, 0); this.dataTracker.startTracking(PARENT_A, Optional.empty()); this.dataTracker.startTracking(PARENT_B, Optional.empty()); + this.dataTracker.startTracking(STAYING, false); } public float getAgeFraction() { @@ -49,12 +59,8 @@ public class KidEntity extends PathAwareEntity { @Override protected void initGoals() { this.goalSelector.add(0, new SwimGoal(this)); - this.goalSelector.add(1, new FleeEntityGoal<>(this, PlayerEntity.class, 6F, 1.2, 1.5)); - this.goalSelector.add(2, new WanderAroundFarGoal(this, 1.0)); - this.goalSelector.add(3, new LookAroundGoal(this)); - //this.goalSelector.add(4, new KidGoToBedGoal(this, 1.0)); - - this.targetSelector.add(1, new RevengeGoal(this)); + this.goalSelector.add(1, new KidParentBrainGoal(this, 1.3)); + this.goalSelector.add(2, new LookAroundGoal(this)); } @Override @@ -65,6 +71,9 @@ public class KidEntity extends PathAwareEntity { int age = dataTracker.get(AGE); age++; dataTracker.set(AGE, age); + EntityPose current = this.getPose(); + this.setPose(EntityPose.SITTING); + this.setPose(current); // Remove brutal killing; just let the kid “grow up” visually if (age > MAX_AGE) { @@ -114,6 +123,38 @@ public class KidEntity extends PathAwareEntity { this.dataTracker.set(PARENT_B, Optional.ofNullable(b)); } + public PlayerEntity getNearbyParent() { + if (this.getWorld().isClient) return null; + + ServerWorld world = (ServerWorld) this.getWorld(); + + UUID a = getParentA(); + UUID b = getParentB(); + + PlayerEntity parentA = a != null ? world.getPlayerByUuid(a) : null; + PlayerEntity parentB = b != null ? world.getPlayerByUuid(b) : null; + + PlayerEntity closest = null; + double closestDist = Double.MAX_VALUE; + + for (PlayerEntity p : new PlayerEntity[]{parentA, parentB}) { + if (p != null && p.isAlive() && !p.isSpectator()) { + double dist = this.squaredDistanceTo(p); + if (dist < closestDist) { + closest = p; + closestDist = dist; + } + } + } + + // Render distance check (32 blocks = 1024 sq) + if (closest != null && closestDist <= 1024) { + return closest; + } + + return null; + } + @Override public void writeCustomDataToNbt(NbtCompound nbt) { super.writeCustomDataToNbt(nbt); @@ -139,4 +180,179 @@ public class KidEntity extends PathAwareEntity { dataTracker.set(AGE, nbt.getInt("Age")); } + @Override + public ActionResult interactMob(PlayerEntity player, Hand hand) { + if (!this.getWorld().isClient && hand == Hand.MAIN_HAND) { + boolean staying = this.dataTracker.get(STAYING); + + if (!staying) { + player.sendMessage(Text.literal("Kid will now say here.")); + this.dataTracker.set(STAYING, true); + this.stayPos = this.getBlockPos(); + } else { + player.sendMessage(Text.literal("Kid will now follow parents.")); + this.dataTracker.set(STAYING, false); + } + } + + return ActionResult.success(this.getWorld().isClient); + } + @Override + public EntityDimensions getDimensions(EntityPose pose) { + float ageFraction = getAgeFraction(); + float bodyScale = 0.3f + (1.0f - 0.3f) * ageFraction; + + EntityDimensions base = super.getDimensions(pose); + + return EntityDimensions.changing( + base.width * bodyScale, + base.height * bodyScale + ); + } + static class KidParentBrainGoal extends Goal { + + private final KidEntity kid; + private final double speed; + + public KidParentBrainGoal(KidEntity kid, double speed) { + this.kid = kid; + this.speed = speed; + } + + @Override + public boolean canStart() { + return true; // Always active brain + } + + @Override + public void tick() { + + if (kid.dataTracker.get(KidEntity.STAYING)) { + handleStayMode(); + return; + } + + PlayerEntity parent = kid.getNearbyParent(); + + if (parent != null) { + kid.lastSeenParentPos = parent.getBlockPos(); + + double dist = kid.squaredDistanceTo(parent); + + if (dist > 120) { + // RUN to parent + kid.getNavigation().startMovingTo(parent, speed * 1.5); + } else if (dist < 36) { // 6 blocks + kid.getNavigation().stop(); + } else { + // Wander casually near parent + if (kid.getNavigation().isIdle() && kid.getRandom().nextInt(80) == 0) { + wanderNear(parent.getBlockPos(), 6); + } + } + + } else { + // No visible parent → panic mode + handlePanic(); + } + } + + private void handleStayMode() { + if (kid.stayPos == null) return; + + if (kid.getNavigation().isIdle() && kid.getRandom().nextInt(60) == 0) { + wanderNear(kid.stayPos, 5); + } + } + + private void handlePanic() { + + if (kid.lastSeenParentPos == null) return; + + ServerWorld world = (ServerWorld) kid.getWorld(); + + double dist = kid.squaredDistanceTo( + kid.lastSeenParentPos.getX(), + kid.lastSeenParentPos.getY(), + kid.lastSeenParentPos.getZ() + ); + + // ===== MOVEMENT ===== + + // If far from last seen location, run there fast + if (dist > 16) { // 4 blocks + kid.getNavigation().startMovingTo( + kid.lastSeenParentPos.getX(), + kid.lastSeenParentPos.getY(), + kid.lastSeenParentPos.getZ(), + speed * 1.2 + ); + } + // Once there → panic wander in 5 block radius + else if (kid.getNavigation().isIdle() && kid.getRandom().nextInt(20) == 0) { + + double panicX = kid.lastSeenParentPos.getX() + kid.getRandom().nextInt(11) - 5; + double panicZ = kid.lastSeenParentPos.getZ() + kid.getRandom().nextInt(11) - 5; + + kid.getNavigation().startMovingTo(panicX, + kid.lastSeenParentPos.getY(), + panicZ, + speed); + } + + // ===== CRYING PARTICLES ===== + + if (kid.getRandom().nextInt(2) == 0) { + + // Proper head height (accounts for body scaling) + double headY = kid.getY() + kid.getStandingEyeHeight(); + + // Face direction + float yawRad = (float) Math.toRadians(kid.getYaw()); + + // Offset to simulate left/right eyes + double eyeOffsetX = Math.cos(yawRad) * 0.15; + double eyeOffsetZ = Math.sin(yawRad) * 0.15; + + // Left eye + spawnTear(world, + kid.getX() - eyeOffsetZ, + headY, + kid.getZ() + eyeOffsetX); + + // Right eye + spawnTear(world, + kid.getX() + eyeOffsetZ, + headY, + kid.getZ() - eyeOffsetX); + } + } + private void spawnTear(ServerWorld world, double x, double y, double z) { + + // Downward falling motion + double velX = (kid.getRandom().nextDouble() - 0.5) * 0.02; + double velY = -0.12 - kid.getRandom().nextDouble() * 0.05; + double velZ = (kid.getRandom().nextDouble() - 0.5) * 0.02; + + world.spawnParticles( + net.minecraft.particle.ParticleTypes.FALLING_WATER, + x, + y, + z, + 1, + velX, + velY, + velZ, + 0.0 + ); + } + + private void wanderNear(BlockPos center, int radius) { + double x = center.getX() + kid.getRandom().nextInt(radius * 2) - radius; + double z = center.getZ() + kid.getRandom().nextInt(radius * 2) - radius; + double y = center.getY(); + + kid.getNavigation().startMovingTo(x, y, z, 1.0); + } + } } \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index a590b0c..f19d19f 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -1,9 +1,12 @@ package dev.tggamesyt.szar; import com.google.common.collect.ImmutableSet; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; 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.command.v2.CommandRegistrationCallback; 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; @@ -36,6 +39,7 @@ import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.tag.BiomeTags; import net.minecraft.registry.tag.BlockTags; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; @@ -64,11 +68,13 @@ import net.minecraft.world.gen.structure.StructureType; import net.minecraft.world.poi.PointOfInterestType; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.UnknownNullability; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.regex.Pattern; +import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; import static dev.tggamesyt.szar.ServerCosmetics.USERS; import static dev.tggamesyt.szar.ServerCosmetics.sync; @@ -157,7 +163,7 @@ public class Szar implements ModInitializer { new Identifier(MOD_ID, "kid"), FabricEntityTypeBuilder.create(SpawnGroup.CREATURE, KidEntity::new) // ✅ matches EntityType - .dimensions(EntityDimensions.fixed(0.6F, 1.8F)) + .dimensions(EntityDimensions.changing(0.6F, 1.8F)) .build() ); public static final EntityType EpsteinEntityType = @@ -622,6 +628,23 @@ public class Szar implements ModInitializer { } } }); + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { + dispatcher.register( + LiteralArgumentBuilder.literal("ny") + .requires(context -> context.hasPermissionLevel(2)) + .executes(context -> { + ServerCommandSource source = context.getSource(); + ServerWorld world = source.getWorld(); + + // Kill all KidEntity instances + int count = world.getEntitiesByType(NyanEntityType, e -> true).size(); + world.getEntitiesByType(NyanEntityType, e -> true).forEach(e -> e.kill()); + + source.sendMessage(Text.literal("Killed " + count + " nyan cats.")); + return count; + }) + ); + }); } public static final StructurePieceType TNT_OBELISK_PIECE = Registry.register(