]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/common/CommonProxy.java
Cleanup code
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / common / CommonProxy.java
1 package com.irtimaled.bbor.common;
2
3 import com.irtimaled.bbor.Logger;
4 import com.irtimaled.bbor.common.chunkProcessors.ChunkProcessor;
5 import com.irtimaled.bbor.common.chunkProcessors.EndChunkProcessor;
6 import com.irtimaled.bbor.common.chunkProcessors.NetherChunkProcessor;
7 import com.irtimaled.bbor.common.chunkProcessors.OverworldChunkProcessor;
8 import com.irtimaled.bbor.common.events.*;
9 import com.irtimaled.bbor.common.messages.AddBoundingBox;
10 import com.irtimaled.bbor.common.messages.InitializeClient;
11 import com.irtimaled.bbor.common.messages.PayloadBuilder;
12 import com.irtimaled.bbor.common.messages.RemoveBoundingBox;
13 import com.irtimaled.bbor.common.models.*;
14 import net.minecraft.world.WorldServer;
15 import net.minecraft.world.chunk.Chunk;
16
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.Map;
20 import java.util.Set;
21 import java.util.concurrent.ConcurrentHashMap;
22
23 public class CommonProxy {
24     private Set<ServerPlayer> players = new HashSet<>();
25     private Map<ServerPlayer, Set<BoundingBox>> playerBoundingBoxesCache = new HashMap<>();
26     private Map<Integer, VillageProcessor> villageProcessors = new HashMap<>();
27     private Map<Integer, ChunkProcessor> chunkProcessors = new HashMap<>();
28     private WorldData worldData = null;
29     private final Map<Integer, BoundingBoxCache> dimensionCache = new ConcurrentHashMap<>();
30
31     public void init() {
32         EventBus.subscribe(WorldLoaded.class, e -> worldLoaded(e.getWorld()));
33         EventBus.subscribe(ChunkLoaded.class, e -> chunkLoaded(e.getChunk()));
34         EventBus.subscribe(MobSpawnerBroken.class, e -> mobSpawnerBroken(e.getDimensionId(), e.getPos()));
35         EventBus.subscribe(PlayerLoggedIn.class, e -> playerLoggedIn(e.getPlayer()));
36         EventBus.subscribe(PlayerLoggedOut.class, e -> playerLoggedOut(e.getPlayer()));
37         EventBus.subscribe(PlayerSubscribed.class, e -> sendBoundingBoxes(e.getPlayer()));
38         EventBus.subscribe(ServerWorldTick.class, e -> serverWorldTick(e.getWorld()));
39         EventBus.subscribe(ServerTick.class, e -> serverTick());
40         EventBus.subscribe(VillageRemoved.class, e -> sendRemoveBoundingBox(e.getDimensionId(), e.getVillage()));
41     }
42
43     protected void setWorldData(long seed, int spawnX, int spawnZ) {
44         worldData = new WorldData(seed, spawnX, spawnZ);
45     }
46
47     private void worldLoaded(WorldServer world) {
48         int dimensionId = world.dimension.getType().getId();
49         BoundingBoxCache boundingBoxCache = getOrCreateCache(dimensionId);
50         ChunkProcessor chunkProcessor = null;
51         if (dimensionId == Dimensions.OVERWORLD) {
52             setWorldData(world.getSeed(), world.getWorldInfo().getSpawnX(), world.getWorldInfo().getSpawnZ());
53             chunkProcessor = new OverworldChunkProcessor(boundingBoxCache);
54         }
55         if (dimensionId == Dimensions.NETHER) {
56             chunkProcessor = new NetherChunkProcessor(boundingBoxCache);
57         }
58         if (dimensionId == Dimensions.THE_END) {
59             chunkProcessor = new EndChunkProcessor(boundingBoxCache);
60         }
61         Logger.info("create world dimension: %s, %s (seed: %d)", dimensionId, world.getClass().toString(), world.getSeed());
62         chunkProcessors.put(dimensionId, chunkProcessor);
63         villageProcessors.put(dimensionId, new VillageProcessor(dimensionId, boundingBoxCache));
64     }
65
66     private void chunkLoaded(Chunk chunk) {
67         int dimensionId = chunk.getWorld().dimension.getType().getId();
68         ChunkProcessor chunkProcessor = chunkProcessors.get(dimensionId);
69         if (chunkProcessor != null) {
70             chunkProcessor.process(chunk);
71         }
72     }
73
74     private void playerLoggedIn(ServerPlayer player) {
75         player.sendPacket(InitializeClient.getPayload(worldData));
76     }
77
78     private void playerLoggedOut(ServerPlayer player) {
79         players.remove(player);
80         playerBoundingBoxesCache.remove(player);
81     }
82
83     private void sendRemoveBoundingBox(int dimensionId, BoundingBox boundingBox) {
84         PayloadBuilder payload = RemoveBoundingBox.getPayload(dimensionId, boundingBox);
85         if (payload == null) return;
86
87         for (ServerPlayer player : players) {
88             if (player.getDimensionId() == dimensionId) {
89                 player.sendPacket(payload);
90
91                 if (playerBoundingBoxesCache.containsKey(player)) {
92                     playerBoundingBoxesCache.get(player).remove(boundingBox);
93                 }
94             }
95         }
96     }
97
98     private void sendBoundingBoxes(ServerPlayer player) {
99         players.add(player);
100         sendToPlayer(player, getCache(player.getDimensionId()));
101     }
102
103     private void sendToPlayer(ServerPlayer player, BoundingBoxCache boundingBoxCache) {
104         if (boundingBoxCache == null) return;
105
106         Map<BoundingBox, Set<BoundingBox>> cacheSubset = getBoundingBoxMap(player, boundingBoxCache.getBoundingBoxes());
107
108         for (BoundingBox key : cacheSubset.keySet()) {
109             Set<BoundingBox> boundingBoxes = cacheSubset.get(key);
110             PayloadBuilder payload = AddBoundingBox.getPayload(player.getDimensionId(), key, boundingBoxes);
111             if (payload != null)
112                 player.sendPacket(payload);
113
114             if (!playerBoundingBoxesCache.containsKey(player)) {
115                 playerBoundingBoxesCache.put(player, new HashSet<>());
116             }
117             playerBoundingBoxesCache.get(player).add(key);
118         }
119     }
120
121     private Map<BoundingBox, Set<BoundingBox>> getBoundingBoxMap(ServerPlayer player, Map<BoundingBox, Set<BoundingBox>> boundingBoxMap) {
122         Map<BoundingBox, Set<BoundingBox>> cacheSubset = new HashMap<>();
123         for (BoundingBox key : boundingBoxMap.keySet()) {
124             if (!playerBoundingBoxesCache.containsKey(player) || !playerBoundingBoxesCache.get(player).contains(key)) {
125                 cacheSubset.put(key, boundingBoxMap.get(key));
126             }
127         }
128         return cacheSubset;
129     }
130
131     protected void addBoundingBox(int dimensionId, BoundingBox key, Set<BoundingBox> boundingBoxes) {
132         BoundingBoxCache cache = getCache(dimensionId);
133         if (cache == null) return;
134
135         cache.addBoundingBoxes(key, boundingBoxes);
136     }
137
138     protected void removeBoundingBox(int dimensionId, BoundingBox key) {
139         BoundingBoxCache cache = getCache(dimensionId);
140         if (cache == null) return;
141
142         cache.removeBoundingBox(key);
143     }
144
145     private void mobSpawnerBroken(int dimensionId, Coords pos) {
146         BoundingBox boundingBox = BoundingBoxMobSpawner.from(pos);
147         removeBoundingBox(dimensionId, boundingBox);
148         sendRemoveBoundingBox(dimensionId, boundingBox);
149     }
150
151     private void serverTick() {
152         for (ServerPlayer player : players) {
153             sendToPlayer(player, getCache(player.getDimensionId()));
154         }
155     }
156
157     private void serverWorldTick(WorldServer world) {
158         int dimensionId = world.dimension.getType().getId();
159         VillageProcessor villageProcessor = villageProcessors.get(dimensionId);
160         if (villageProcessor == null) return;
161
162         villageProcessor.process(world.getVillageCollection());
163     }
164
165     protected BoundingBoxCache getCache(int dimensionId) {
166         return dimensionCache.get(dimensionId);
167     }
168
169     protected BoundingBoxCache getOrCreateCache(int dimensionId) {
170         return dimensionCache.computeIfAbsent(dimensionId, dt -> new BoundingBoxCache());
171     }
172
173     protected void clearCaches() {
174         for (VillageProcessor villageProcessor : villageProcessors.values()) {
175             villageProcessor.clear();
176         }
177         villageProcessors.clear();
178         for (BoundingBoxCache cache : dimensionCache.values()) {
179             cache.clear();
180         }
181         dimensionCache.clear();
182     }
183 }