]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blobdiff - src/main/java/com/irtimaled/bbor/common/CommonProxy.java
Move Mob Spawner processing to client side
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / common / CommonProxy.java
index 68e338b60fbf55885fe433bfcc757547d25e4650..9606d02f0efc6017cea3fd3c132d2f7fc5b99fdf 100644 (file)
 package com.irtimaled.bbor.common;
 
 import com.irtimaled.bbor.Logger;
-import com.irtimaled.bbor.ReflectionHelper;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.world.DimensionType;
-import net.minecraft.world.World;
-import net.minecraft.world.chunk.Chunk;
-import net.minecraft.world.chunk.IChunkProvider;
-import net.minecraft.world.gen.ChunkProviderServer;
-import net.minecraft.world.gen.IChunkGenerator;
+import com.irtimaled.bbor.common.events.*;
+import com.irtimaled.bbor.common.messages.AddBoundingBox;
+import com.irtimaled.bbor.common.messages.InitializeClient;
+import com.irtimaled.bbor.common.messages.PayloadBuilder;
+import com.irtimaled.bbor.common.messages.RemoveBoundingBox;
+import com.irtimaled.bbor.common.models.AbstractBoundingBox;
+import com.irtimaled.bbor.common.models.ServerPlayer;
 
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 public class CommonProxy {
-    protected DimensionCache dimensionCache;
-    protected Set<VillageProcessor> villageProcessors = new HashSet<>();
-
-    private IVillageEventHandler eventHandler = null;
-
-    public void worldLoaded(World world) {
-        IChunkProvider chunkProvider = world.getChunkProvider();
-        if (chunkProvider instanceof ChunkProviderServer) {
-            IChunkGenerator chunkGenerator = ReflectionHelper.getPrivateValue(ChunkProviderServer.class, (ChunkProviderServer) chunkProvider, IChunkGenerator.class);
-            dimensionCache.setWorldData(world.getSeed(), world.getWorldInfo().getSpawnX(), world.getWorldInfo().getSpawnZ());
-            DimensionType dimensionType = world.provider.getDimensionType();
-            Logger.info("create world dimension: %s, %s (chunkprovider: %s) (seed: %d)", dimensionType, world.getClass().toString(), chunkGenerator.getClass().toString(), world.getSeed());
-            DimensionProcessor boundingBoxCache = new DimensionProcessor(dimensionType, chunkGenerator);
-            dimensionCache.put(dimensionType, boundingBoxCache);
-            if (ConfigManager.drawVillages.getBoolean()) {
-                villageProcessors.add(new VillageProcessor(world, dimensionType, eventHandler, boundingBoxCache));
+    private final Map<Integer, ServerPlayer> players = new ConcurrentHashMap<>();
+    private final Map<Integer, Set<AbstractBoundingBox>> playerBoundingBoxesCache = new HashMap<>();
+    private final Map<Integer, VillageProcessor> villageProcessors = new HashMap<>();
+    private final Map<Integer, ChunkProcessor> chunkProcessors = new HashMap<>();
+    private final Map<Integer, BoundingBoxCache> dimensionCache = new ConcurrentHashMap<>();
+    private Long seed = null;
+    private Integer spawnX = null;
+    private Integer spawnZ = null;
+
+    public void init() {
+        EventBus.subscribe(WorldLoaded.class, this::worldLoaded);
+        EventBus.subscribe(ChunkLoaded.class, this::chunkLoaded);
+        EventBus.subscribe(PlayerLoggedIn.class, this::playerLoggedIn);
+        EventBus.subscribe(PlayerLoggedOut.class, this::playerLoggedOut);
+        EventBus.subscribe(PlayerSubscribed.class, this::onPlayerSubscribed);
+        EventBus.subscribe(ServerWorldTick.class, this::serverWorldTick);
+        EventBus.subscribe(ServerTick.class, e -> serverTick());
+        EventBus.subscribe(VillageRemoved.class, this::onVillageRemoved);
+    }
+
+    protected void setSeed(long seed) {
+        this.seed = seed;
+    }
+
+    protected void setWorldSpawn(int spawnX, int spawnZ) {
+        this.spawnX = spawnX;
+        this.spawnZ = spawnZ;
+    }
+
+    private void worldLoaded(WorldLoaded event) {
+        int dimensionId = event.getDimensionId();
+        long seed = event.getSeed();
+        if (dimensionId == Dimensions.OVERWORLD) {
+            setSeed(seed);
+            setWorldSpawn(event.getSpawnX(), event.getSpawnZ());
+        }
+        Logger.info("create world dimension: %s (seed: %d)", dimensionId, seed);
+        BoundingBoxCache boundingBoxCache = getOrCreateCache(dimensionId);
+        chunkProcessors.put(dimensionId, new ChunkProcessor(boundingBoxCache));
+        villageProcessors.put(dimensionId, new VillageProcessor(dimensionId, boundingBoxCache));
+    }
+
+    private void chunkLoaded(ChunkLoaded event) {
+        ChunkProcessor chunkProcessor = chunkProcessors.get(event.getDimensionId());
+        if (chunkProcessor == null) return;
+
+        chunkProcessor.process(event.getChunk());
+    }
+
+    private void playerLoggedIn(PlayerLoggedIn event) {
+        if (seed == null || spawnX == null || spawnZ == null) {
+            return;
+        }
+        ServerPlayer player = event.getPlayer();
+        player.sendPacket(InitializeClient.getPayload(seed, spawnX, spawnZ));
+    }
+
+    private void playerLoggedOut(PlayerLoggedOut event) {
+        int playerId = event.getPlayerId();
+        players.remove(playerId);
+        playerBoundingBoxesCache.remove(playerId);
+    }
+
+    private void onVillageRemoved(VillageRemoved event) {
+        sendRemoveBoundingBox(event.getDimensionId(), event.getVillage());
+    }
+
+    private void sendRemoveBoundingBox(int dimensionId, AbstractBoundingBox boundingBox) {
+        PayloadBuilder payload = RemoveBoundingBox.getPayload(dimensionId, boundingBox);
+        if (payload == null) return;
+
+        for (Map.Entry<Integer, ServerPlayer> playerEntry : players.entrySet()) {
+            int playerId = playerEntry.getKey();
+            ServerPlayer player = playerEntry.getValue();
+            if (player.getDimensionId() == dimensionId) {
+                player.sendPacket(payload);
+
+                if (playerBoundingBoxesCache.containsKey(playerId)) {
+                    playerBoundingBoxesCache.get(playerId).remove(boundingBox);
+                }
             }
         }
     }
 
-    public void chunkLoaded(Chunk chunk) {
-        DimensionType dimensionType = chunk.getWorld().provider.getDimensionType();
-        dimensionCache.refresh(dimensionType);
+    private void onPlayerSubscribed(PlayerSubscribed event) {
+        int playerId = event.getPlayerId();
+        ServerPlayer player = event.getPlayer();
+        players.put(playerId, player);
+        sendToPlayer(playerId, player);
     }
 
-    public void tick() {
-        villageProcessors.forEach(VillageProcessor::process);
+    private void sendToPlayer(int playerId, ServerPlayer player) {
+        for (Map.Entry<Integer, BoundingBoxCache> entry : dimensionCache.entrySet()) {
+            int dimensionId = entry.getKey();
+            BoundingBoxCache boundingBoxCache = entry.getValue();
+            if (boundingBoxCache == null) return;
+
+            Set<AbstractBoundingBox> playerBoundingBoxes = playerBoundingBoxesCache.computeIfAbsent(playerId, k -> new HashSet<>());
+
+            Map<AbstractBoundingBox, Set<AbstractBoundingBox>> boundingBoxMap = boundingBoxCache.getBoundingBoxes();
+            for (AbstractBoundingBox key : boundingBoxMap.keySet()) {
+                if (playerBoundingBoxes.contains(key)) {
+                    continue;
+                }
+
+                Set<AbstractBoundingBox> boundingBoxes = boundingBoxMap.get(key);
+                PayloadBuilder payload = AddBoundingBox.getPayload(dimensionId, key, boundingBoxes);
+                if (payload != null)
+                    player.sendPacket(payload);
+
+                playerBoundingBoxes.add(key);
+            }
+        }
     }
 
-    public void init() {
-        dimensionCache = new DimensionCache();
+    protected void removeBoundingBox(int dimensionId, AbstractBoundingBox key) {
+        BoundingBoxCache cache = getCache(dimensionId);
+        if (cache == null) return;
+
+        cache.removeBoundingBox(key);
     }
 
-    public void setEventHandler(IVillageEventHandler eventHandler) {
-        this.eventHandler = eventHandler;
+    private void serverTick() {
+        for (Map.Entry<Integer, ServerPlayer> playerEntry : players.entrySet()) {
+            int playerId = playerEntry.getKey();
+            ServerPlayer player = playerEntry.getValue();
+
+            sendToPlayer(playerId, player);
+        }
+    }
+
+    private void serverWorldTick(ServerWorldTick event) {
+        VillageProcessor villageProcessor = villageProcessors.get(event.getDimensionId());
+        if (villageProcessor == null) return;
+
+        villageProcessor.process(event.getWorld());
+    }
+
+    protected BoundingBoxCache getCache(int dimensionId) {
+        return dimensionCache.get(dimensionId);
+    }
+
+    protected BoundingBoxCache getOrCreateCache(int dimensionId) {
+        return dimensionCache.computeIfAbsent(dimensionId, dt -> new BoundingBoxCache());
     }
 
-    public DimensionCache getDimensionCache() {
-        return dimensionCache;
+    protected void clearCaches() {
+        for (VillageProcessor villageProcessor : villageProcessors.values()) {
+            villageProcessor.clear();
+        }
+        villageProcessors.clear();
+        for (BoundingBoxCache cache : dimensionCache.values()) {
+            cache.clear();
+        }
+        dimensionCache.clear();
     }
 }