diff --git a/modules/development/src/main/java/unnamed/mmo/server/dev/Main.java b/modules/development/src/main/java/unnamed/mmo/server/dev/Main.java index 0ee13fdd..d8cd91ab 100644 --- a/modules/development/src/main/java/unnamed/mmo/server/dev/Main.java +++ b/modules/development/src/main/java/unnamed/mmo/server/dev/Main.java @@ -5,13 +5,16 @@ import com.mattworzala.debug.DebugMessage; import com.mattworzala.debug.Layer; import com.mattworzala.debug.shape.Line; +import com.mattworzala.debug.shape.Text; import com.mojang.serialization.JsonOps; import net.kyori.adventure.audience.Audience; import net.minestom.server.MinecraftServer; import net.minestom.server.adventure.MinestomAdventure; +import net.minestom.server.command.builder.Command; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; import net.minestom.server.entity.GameMode; import net.minestom.server.entity.Player; import net.minestom.server.event.GlobalEventHandler; @@ -36,6 +39,7 @@ import unnamed.mmo.command.BaseCommandRegister; import unnamed.mmo.damage.DamageProcessor; import unnamed.mmo.data.number.NumberProvider; +import unnamed.mmo.entity.HeadRotationZombie; import unnamed.mmo.entity.UnnamedEntity; import unnamed.mmo.entity.brain.task.*; import unnamed.mmo.item.Item; @@ -120,24 +124,35 @@ public static void main(String[] args) { // } // } // }"""); - JsonElement json = JsonParser.parseString(""" - { - "type": "unnamed:sequence", - "children": [ - { - "type": "unnamed:wander_in_region" - }, - { - "type": "unnamed:idle", - "time": 20 - } - ] - }"""); - Task task = JsonOps.INSTANCE.withDecoder(Task.Spec.CODEC) - .apply(json).getOrThrow(false, System.err::println).getFirst().create(); - UnnamedEntity entity = new UnnamedEntity(task); - entity.setInstance(instance, new Pos(0, 40, 0)) - .thenAccept(unused -> System.out.println("Spawned")); +// JsonElement json = JsonParser.parseString(""" +// { +// "type": "unnamed:sequence", +// "children": [ +// { +// "type": "unnamed:wander_in_region" +// }, +// { +// "type": "unnamed:idle", +// "time": 20 +// } +// ] +// }"""); +// Task task = JsonOps.INSTANCE.withDecoder(Task.Spec.CODEC) +// .apply(json).getOrThrow(false, System.err::println).getFirst().create(); +// UnnamedEntity entity = new UnnamedEntity(task); +// entity.setInstance(instance, new Pos(0, 40, 0)) +// .thenAccept(unused -> System.out.println("Spawned")); + +// Entity entity = new Entity(EntityType.ZOMBIE) { +// @Override +// public void tick(long time) { +// super.tick(time); +// +// lookAt(player); +// } +// }; + Entity entity = new HeadRotationZombie(); + entity.setInstance(instance, new Pos(0, 40, 0)); }); eventHandler.addListener(PlayerPacketOutEvent.class, event -> { SendablePacket packet = event.getPacket(); @@ -154,28 +169,40 @@ public static void main(String[] args) { System.out.println(packet.getClass().getSimpleName()); if (packet instanceof EntityHeadLookPacket headLook) { - Vec dir = new Pos(0, 0, 0, headLook.yaw(), 0).direction(); - Pos entityPos = Entity.getEntity(headLook.entityId()).getPosition(); - DebugMessage.builder() - .set(NamespaceID.from(ThreadLocalRandom.current().nextDouble() + ""), new Line.Builder() - .point(entityPos.asVec()) - .point(dir.mul(2).add(entityPos.asVec())) - .layer(Layer.TOP) - .color(0xFFFFFF00) - .build()) - .build() - .sendTo(Audience.audience(MinecraftServer.getConnectionManager().getOnlinePlayers())); +// Vec dir = new Pos(0, 0, 0, headLook.yaw(), 0).direction(); +// Pos entityPos = Entity.getEntity(headLook.entityId()).getPosition(); +// DebugMessage.builder() +// .set(NamespaceID.from(ThreadLocalRandom.current().nextInt() + ""), new Line.Builder() +// .point(entityPos.asVec()) +// .point(dir.mul(2).add(entityPos.asVec())) +// .layer(Layer.TOP) +// .color(0xFFFFFF00) +// .build()) +//// .set(NamespaceID.from(ThreadLocalRandom.current().nextInt() + ""), new Text.Builder() +//// .content(System.currentTimeMillis() + "") +//// .position(dir.mul(2).add(entityPos.asVec())) +//// .layer(Layer.TOP) +//// .color(0xFFFFFF00) +//// .build()) +// .build() +// .sendTo(Audience.audience(MinecraftServer.getConnectionManager().getOnlinePlayers())); } if (packet instanceof EntityPositionAndRotationPacket posAndRot) { Vec dir = new Pos(0, 0, 0, posAndRot.yaw(), posAndRot.pitch()).direction(); Pos entityPos = Entity.getEntity(posAndRot.entityId()).getPosition(); DebugMessage.builder() - .set(NamespaceID.from(ThreadLocalRandom.current().nextDouble() + ""), new Line.Builder() + .set(NamespaceID.from(ThreadLocalRandom.current().nextInt() + ""), new Line.Builder() .point(entityPos.asVec()) .point(dir.mul(2).add(entityPos.asVec())) .layer(Layer.TOP) .color(0xFFFF00FF) .build()) +// .set(NamespaceID.from(ThreadLocalRandom.current().nextInt() + ""), new Text.Builder() +// .content(System.currentTimeMillis() + "") +// .position(dir.mul(2).add(entityPos.asVec().withY(y -> y + 0.5))) +// .layer(Layer.TOP) +// .color(0xFFFF00FF) +// .build()) .build() .sendTo(Audience.audience(MinecraftServer.getConnectionManager().getOnlinePlayers())); } @@ -184,6 +211,12 @@ public static void main(String[] args) { BaseCommandRegister.registerCommands(); + Command c = new Command("clear"); + c.setDefaultExecutor((sender, context) -> { + DebugMessage.builder().clear().build().sendTo(sender); + }); + MinecraftServer.getCommandManager().register(c); + // For now, manually register chat (with conn to mongo :/ need a config system) // MongoClient mongoClient = MongoClients.create(MongoClientSettings.builder() // .applyConnectionString(new ConnectionString("mongodb://localhost:27017")) diff --git a/modules/entity/src/main/java/unnamed/mmo/entity/HeadRotationZombie.java b/modules/entity/src/main/java/unnamed/mmo/entity/HeadRotationZombie.java new file mode 100644 index 00000000..f6704950 --- /dev/null +++ b/modules/entity/src/main/java/unnamed/mmo/entity/HeadRotationZombie.java @@ -0,0 +1,63 @@ +package unnamed.mmo.entity; + +import net.minestom.server.collision.CollisionUtils; +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.utils.position.PositionUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.ThreadLocalRandom; + +public class HeadRotationZombie extends LivingEntity { + private Point target; + + public HeadRotationZombie() { + super(EntityType.ZOMBIE); + } + + @Override + public void tick(long time) { + super.tick(time); + + if (target == null || getPosition().distance(target) < 0.8) { + selectTarget(); + } + + moveTowards(target, 0.2f); + + } + + private void selectTarget() { + target = new Vec( + ThreadLocalRandom.current().nextInt(-10, 10), + 40, + ThreadLocalRandom.current().nextInt(-10, 10) + ); + } + + private void moveTowards(@NotNull Point direction, double speed) { + final Pos position = getPosition(); + final double dx = direction.x() - position.x(); + final double dy = direction.y() - position.y(); + final double dz = direction.z() - position.z(); + // the purpose of these few lines is to slow down entities when they reach their destination + final double distSquared = dx * dx + dy * dy + dz * dz; + if (speed > distSquared) { + speed = distSquared; + } + final double radians = Math.atan2(dz, dx); + final double speedX = Math.cos(radians) * speed; + final double speedY = dy * speed; + final double speedZ = Math.sin(radians) * speed; + final float yaw = PositionUtils.getLookYaw(dx, dz); + final float pitch = PositionUtils.getLookPitch(dx, dy, dz); + + // Prevent ghosting + final var physicsResult = CollisionUtils.handlePhysics(this, new Vec(speedX, speedY, speedZ)); + refreshPosition(Pos.fromPoint(physicsResult.newPosition()).withView(yaw, pitch)); + } +} + diff --git a/modules/entity/src/main/java/unnamed/mmo/entity/motion/MotionNavigator.java b/modules/entity/src/main/java/unnamed/mmo/entity/motion/MotionNavigator.java index c32754b8..c23c3127 100644 --- a/modules/entity/src/main/java/unnamed/mmo/entity/motion/MotionNavigator.java +++ b/modules/entity/src/main/java/unnamed/mmo/entity/motion/MotionNavigator.java @@ -5,6 +5,7 @@ import com.mattworzala.debug.shape.Box; import com.mattworzala.debug.shape.Line; import com.mattworzala.debug.shape.OutlineBox; +import net.minestom.server.MinecraftServer; import net.minestom.server.attribute.Attribute; import net.minestom.server.collision.CollisionUtils; import net.minestom.server.coordinate.Point; @@ -14,7 +15,10 @@ import net.minestom.server.entity.LivingEntity; import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Instance; +import net.minestom.server.network.packet.server.play.EntityHeadLookPacket; +import net.minestom.server.network.packet.server.play.EntityRotationPacket; import net.minestom.server.utils.NamespaceID; +import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.position.PositionUtils; import net.minestom.server.utils.time.Cooldown; import net.minestom.server.utils.time.TimeUnit; @@ -177,6 +181,11 @@ private void sendDebugData() { .color(0xFFFFFFFF) .layer(Layer.TOP) .build()); + EntityHeadLookPacket headLook = new EntityHeadLookPacket(entity.getEntityId(), entity.getPosition().yaw()); + PacketUtils.sendGroupedPacket(entity.getViewers(), headLook); + EntityRotationPacket rotation = new EntityRotationPacket(entity.getEntityId(), entity.getPosition().yaw(), entity.getPosition().pitch(), true); + PacketUtils.sendGroupedPacket(entity.getViewers(), rotation); + builder.build() .sendTo(entity.getViewersAsAudience());