From 1b05bf2ed1b1c041079f602dc0d8da8194823c98 Mon Sep 17 00:00:00 2001 From: pietru Date: Sun, 16 Mar 2025 17:43:27 +0100 Subject: [PATCH] add experimental npcs --- .../pietru/cookie_utils/api/TextCommands.java | 83 +++++++++++ .../cookie_utils/mixins/LoginPacketMixin.java | 7 + .../net/pietru/cookie_utils/npcs/NpcDef.java | 140 ++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 src/main/java/net/pietru/cookie_utils/npcs/NpcDef.java diff --git a/src/main/java/net/pietru/cookie_utils/api/TextCommands.java b/src/main/java/net/pietru/cookie_utils/api/TextCommands.java index 8e9f72d..b15eba2 100644 --- a/src/main/java/net/pietru/cookie_utils/api/TextCommands.java +++ b/src/main/java/net/pietru/cookie_utils/api/TextCommands.java @@ -21,6 +21,7 @@ import finalforeach.cosmicreach.world.IZoneLoader; import finalforeach.cosmicreach.world.Zone; import finalforeach.cosmicreach.worldgen.ZoneGenerator; import io.netty.channel.ChannelHandlerContext; +import net.pietru.cookie_utils.npcs.NpcDef; import net.pietru.cookie_utils.permissions.GroupPerms; import net.pietru.cookie_utils.permissions.Permissions; import net.pietru.cookie_utils.setups.Setup; @@ -246,6 +247,88 @@ public class TextCommands { packet.setupAndSend(channelHandlerContext); }); + commands.put("npc",(args, networkIdentity, channelHandlerContext) -> { + Player plr = networkIdentity.getPlayer(); + MessagePacket packet = new MessagePacket("[Server] Usage :npc action id values(optional)"); + if (args.length>=4) { + String arg2 = args[2]; + String arg3 = args[3]; + switch (args[1]) { + case "name": + try { + NpcDef.registered_npc_list.get(Integer.parseInt(arg2)).change_zone(plr.getZone()).setName(arg3); + packet.message="[Server] Changed npc with ID: %s, NAME: %s".formatted(arg2,arg3); + } catch (Exception ignored){ + packet.message="[Server] Failed to modify npc ID: %s".formatted(arg2); + } + break; + case "rot": + try { + String[] ps = arg3.split(":"); + NpcDef.registered_npc_list.get(Integer.parseInt(arg2)) + .change_view_dir(new Vector3( + Float.parseFloat(ps[0]), + Float.parseFloat(ps[1]), + Float.parseFloat(ps[2]) + )).send_update(); + packet.message="[Server] Rotated npc with ID: %s".formatted(arg2); + } catch (Exception ignored){ + packet.message="[Server] Failed to modify npc ID: %s".formatted(arg2); + } + break; + } + } else if (args.length==3) { + String arg2 = args[2]; + switch (args[1]) { + case "add": + new NpcDef(arg2, plr.getPosition(), plr.getZone()).register().show_npc(); + packet.message="[Server] Added npc with ID: %s".formatted(NpcDef.registered_npc_list.size()-1); + break; + case "tphere": + try { + NpcDef.registered_npc_list.get(Integer.parseInt(arg2)) + .change_zone(plr.getZone()) + .change_position(plr.getPosition()) + .send_update(); + packet.message="[Server] Moved npc with ID: %s".formatted(arg2); + } catch (Exception ignored){ + packet.message="[Server] Failed to parse npc ID: %s".formatted(arg2); + } + break; + case "myrot": + try { + NpcDef.registered_npc_list.get(Integer.parseInt(arg2)) + .change_view_dir(plr.getEntity().viewDirection) + .send_update(); + packet.message="[Server] Rotated npc with ID: %s".formatted(arg2); + } catch (Exception ignored){ + packet.message="[Server] Failed to parse npc ID: %s".formatted(arg2); + } + break; + case "remove", "del": + try { + NpcDef.registered_npc_list.get(Integer.parseInt(arg2)).unregister(); + packet.message="[Server] Removed npc with ID: %s".formatted(arg2); + } catch (Exception ignored){ + packet.message="[Server] Failed to parse npc ID: %s".formatted(arg2); + } + break; + } + } else if (args.length == 2) { + switch (args[1]) { + case "list": + StringBuilder msg = new StringBuilder("[Server] NPC List:\n"); + for (int i = 0; i < NpcDef.registered_npc_list.size(); i++) { + msg.append(" - ID: %d | Name: %s \n".formatted(i, NpcDef.registered_npc_list.get(i).getName())); + } + packet.message=msg.toString(); + break; + } + } + + packet.setupAndSend(channelHandlerContext); + }); + commands.put("make_zone",(args, networkIdentity, channelHandlerContext) -> { boolean created = false; ArrayList zones; diff --git a/src/main/java/net/pietru/cookie_utils/mixins/LoginPacketMixin.java b/src/main/java/net/pietru/cookie_utils/mixins/LoginPacketMixin.java index 61ab3ae..4f6ae9f 100644 --- a/src/main/java/net/pietru/cookie_utils/mixins/LoginPacketMixin.java +++ b/src/main/java/net/pietru/cookie_utils/mixins/LoginPacketMixin.java @@ -3,8 +3,11 @@ package net.pietru.cookie_utils.mixins; import com.llamalad7.mixinextras.sugar.Local; import finalforeach.cosmicreach.accounts.Account; import finalforeach.cosmicreach.networking.NetworkIdentity; +import finalforeach.cosmicreach.networking.packets.entities.PlayerPacket; import finalforeach.cosmicreach.networking.packets.meta.LoginPacket; +import finalforeach.cosmicreach.networking.server.ServerSingletons; import io.netty.channel.ChannelHandlerContext; +import net.pietru.cookie_utils.npcs.NpcDef; import net.pietru.cookie_utils.utils.player_utils; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -24,6 +27,10 @@ public class LoginPacketMixin { if (is_plr_valid(account.getUniqueId())){ player_utils.usernames_to_ids.put(account.getUsername(), account.getUniqueId()); player_utils.plr_last_area.put(account.getUniqueId(),""); + + for (NpcDef def : NpcDef.registered_npc_list){ + def.send_to(ctx); + } } } } diff --git a/src/main/java/net/pietru/cookie_utils/npcs/NpcDef.java b/src/main/java/net/pietru/cookie_utils/npcs/NpcDef.java new file mode 100644 index 0000000..cfba85c --- /dev/null +++ b/src/main/java/net/pietru/cookie_utils/npcs/NpcDef.java @@ -0,0 +1,140 @@ +package net.pietru.cookie_utils.npcs; + +import com.badlogic.gdx.math.Vector3; +import finalforeach.cosmicreach.accounts.AccountOffline; +import finalforeach.cosmicreach.entities.Entity; +import finalforeach.cosmicreach.entities.player.Player; +import finalforeach.cosmicreach.entities.player.PlayerEntity; +import finalforeach.cosmicreach.networking.packets.entities.PlayerPacket; +import finalforeach.cosmicreach.networking.packets.entities.PlayerPositionPacket; +import finalforeach.cosmicreach.networking.packets.meta.RemovedPlayerPacket; +import finalforeach.cosmicreach.networking.server.ServerSingletons; +import finalforeach.cosmicreach.world.Zone; +import io.netty.channel.ChannelHandlerContext; + +import java.util.ArrayList; + +public class NpcDef { + public final static ArrayList registered_npc_list = new ArrayList<>(); + + + AccountOffline account; + Player player; + PlayerEntity playerEntity; + Zone zone; + + boolean added = false; + + public NpcDef(String npc_name, Vector3 position, Zone zone){ + this.zone=zone; + + account = new AccountOffline(); + account.setDisplayName(npc_name); + + player=new Player(); + + playerEntity=new PlayerEntity(player); + player.setEntity(playerEntity); + + playerEntity.setPosition(position); + playerEntity.gravityModifier=0F; + //playerEntity.setNoClip(true); + } + + public String getName(){ + return account.getDisplayName(); + } + + public NpcDef setName(String npc_name){ + account.setDisplayName(npc_name); + if (added) { + hide_npc(); + show_npc(); + } + return this; + } + + public NpcDef register(){ + if (!registered_npc_list.contains(this)) + registered_npc_list.add(this); + return this; + } + + public NpcDef unregister(){ + registered_npc_list.remove(this); + hide_npc(); + return this; + } + + public NpcDef change_position(Vector3 position){ + playerEntity.setPosition(position); + return this; + } + + public NpcDef change_view_dir(Vector3 dir){ + playerEntity.viewDirection=dir; + return this; + } + + public NpcDef send_update(){ + PlayerPositionPacket packet = new PlayerPositionPacket(player); + + packet.playerUniqueId = account.getUniqueId(); + Entity e = player.getEntity(); + packet.position.set(e.getPosition()); + packet.viewDir.set(e.viewDirection); + packet.viewDirOff.set(e.viewPositionOffset); + packet.zoneId = player.zoneId; + packet.playerFlags = 0; + addFlag(packet, PlayerPositionPacket.PLAYER_FLAG_SNEAKING, e.isSneaking()); + addFlag(packet, PlayerPositionPacket.PLAYER_FLAG_SPRINTING, player.isSprinting); + + ServerSingletons.SERVER.broadcastToAll(packet); + return this; + } + + private void addFlag(PlayerPositionPacket packet, int flagMask, boolean flagValue) { + if (flagValue) { + packet.playerFlags |= flagMask; + } else { + packet.playerFlags &= ~flagMask; + } + } + + public NpcDef change_zone(Zone zone){ + if (zone.equals(this.zone) || !added) { + this.zone = zone; + return this; + } + player.zoneId=zone.zoneId; + this.zone.removeEntity(playerEntity); + this.zone=zone; + zone.addEntity(playerEntity); + return this; + } + + public NpcDef send_to(ChannelHandlerContext ctx){ + if (added){ + PlayerPacket packet = new PlayerPacket(account,player,false); + packet.setupAndSend(ctx); + } + return this; + } + + public NpcDef show_npc(){ + player.zoneId=zone.zoneId; + PlayerPacket packet = new PlayerPacket(account,player,false); + ServerSingletons.SERVER.broadcastToAll(packet); + zone.addEntity(playerEntity); + added=true; + return this; + } + + public NpcDef hide_npc(){ + RemovedPlayerPacket packet = new RemovedPlayerPacket(account); + ServerSingletons.SERVER.broadcastToAll(packet); + added=false; + zone.removeEntity(playerEntity); + return this; + } +}