diff --git a/src/main/java/emu/grasscutter/game/GenshinPlayer.java b/src/main/java/emu/grasscutter/game/GenshinPlayer.java index 5e3e94f09..95edb99b6 100644 --- a/src/main/java/emu/grasscutter/game/GenshinPlayer.java +++ b/src/main/java/emu/grasscutter/game/GenshinPlayer.java @@ -695,10 +695,6 @@ public class GenshinPlayer { it.remove(); } } - // - if (this.getScene() != null && this.getSceneLoadState() == SceneLoadState.LOADED) { - this.getScene().checkSpawns(this); - } // Ping if (this.getWorld() != null) { // RTT notify - very important to send this often diff --git a/src/main/java/emu/grasscutter/game/GenshinScene.java b/src/main/java/emu/grasscutter/game/GenshinScene.java index 25e2f195a..43370ef84 100644 --- a/src/main/java/emu/grasscutter/game/GenshinScene.java +++ b/src/main/java/emu/grasscutter/game/GenshinScene.java @@ -315,32 +315,31 @@ public class GenshinScene { target.onDeath(attackerId); } - // TODO Do not use yet - public synchronized void onTick() { - for (GenshinPlayer player : this.getPlayers()) { - this.checkSpawns(player); - } + public void onTick() { + this.checkSpawns(); } // TODO - Test - public void checkSpawns(GenshinPlayer player) { + public void checkSpawns() { SpatialIndex list = GenshinDepot.getSpawnListById(this.getId()); Set visible = new HashSet<>(); - int RANGE = 100; - Collection entries = list.query( - new double[] {player.getPos().getX() - RANGE, player.getPos().getZ() - RANGE}, - new double[] {player.getPos().getX() + RANGE, player.getPos().getZ() + RANGE} - ); - - for (SpawnGroupEntry entry : entries) { - for (SpawnDataEntry spawnData : entry.getSpawns()) { - visible.add(spawnData); + for (GenshinPlayer player : this.getPlayers()) { + int RANGE = 100; + Collection entries = list.query( + new double[] {player.getPos().getX() - RANGE, player.getPos().getZ() - RANGE}, + new double[] {player.getPos().getX() + RANGE, player.getPos().getZ() + RANGE} + ); + + for (SpawnGroupEntry entry : entries) { + for (SpawnDataEntry spawnData : entry.getSpawns()) { + visible.add(spawnData); + } } } // World level - WorldLevelData worldLevelData = GenshinData.getWorldLevelDataMap().get(player.getWorldLevel()); + WorldLevelData worldLevelData = GenshinData.getWorldLevelDataMap().get(getWorld().getWorldLevel()); int worldLevelOverride = 0; if (worldLevelData != null) { diff --git a/src/main/java/emu/grasscutter/game/World.java b/src/main/java/emu/grasscutter/game/World.java index 25cbcd3e5..9dd6b6905 100644 --- a/src/main/java/emu/grasscutter/game/World.java +++ b/src/main/java/emu/grasscutter/game/World.java @@ -37,6 +37,7 @@ import emu.grasscutter.server.packet.send.PacketWorldPlayerInfoNotify; import emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify; import emu.grasscutter.utils.Position; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; public class World implements Iterable { @@ -58,11 +59,13 @@ public class World implements Iterable { public World(GenshinPlayer player, boolean isMultiplayer) { this.owner = player; this.players = Collections.synchronizedList(new ArrayList<>()); - this.scenes = new Int2ObjectOpenHashMap<>(); + this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>()); this.levelEntityId = getNextEntityId(EntityIdType.MPLEVEL); this.worldLevel = player.getWorldLevel(); this.isMultiplayer = isMultiplayer; + + this.owner.getServer().registerWorld(this); } public GenshinPlayer getHost() { @@ -273,6 +276,12 @@ public class World implements Iterable { } } + public void onTick() { + for (GenshinScene scene : this.getScenes().values()) { + scene.onTick(); + } + } + public void close() { } diff --git a/src/main/java/emu/grasscutter/server/game/GameServer.java b/src/main/java/emu/grasscutter/server/game/GameServer.java index 065344ee2..905317e9a 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServer.java +++ b/src/main/java/emu/grasscutter/server/game/GameServer.java @@ -10,6 +10,7 @@ import emu.grasscutter.command.CommandMap; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.Account; import emu.grasscutter.game.GenshinPlayer; +import emu.grasscutter.game.World; import emu.grasscutter.game.dungeons.DungeonManager; import emu.grasscutter.game.gacha.GachaManager; import emu.grasscutter.game.managers.ChatManager; @@ -26,6 +27,7 @@ public final class GameServer extends MihoyoKcpServer { private final GameServerPacketHandler packetHandler; private final Map players; + private final Set worlds; private final ChatManager chatManager; private final InventoryManager inventoryManager; @@ -50,6 +52,7 @@ public final class GameServer extends MihoyoKcpServer { this.address = address; this.packetHandler = new GameServerPacketHandler(PacketHandler.class); this.players = new ConcurrentHashMap<>(); + this.worlds = Collections.synchronizedSet(new HashSet<>()); this.chatManager = new ChatManager(this); this.inventoryManager = new InventoryManager(this); @@ -84,6 +87,10 @@ public final class GameServer extends MihoyoKcpServer { return players; } + public Set getWorlds() { + return worlds; + } + public ChatManager getChatManager() { return chatManager; } @@ -161,12 +168,32 @@ public final class GameServer extends MihoyoKcpServer { } public void onTick() throws Exception { + Iterator it = this.getWorlds().iterator(); + while (it.hasNext()) { + World world = it.next(); + + if (world.getPlayerCount() == 0) { + it.remove(); + } + + world.onTick(); + } + for (GenshinPlayer player : this.getPlayers().values()) { player.onTick(); } OnGameServerTick.post(new GameServerTickEvent()); } + + public void registerWorld(World world) { + this.getWorlds().add(world); + } + + public void deregisterWorld(World world) { + // TODO Auto-generated method stub + + } @Override public void onStartFinish() {