]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/common/CommonProxy.java
b39613757230eceebc55cb616c8ef59baf9d9931
[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.events.*;
5 import com.irtimaled.bbor.common.messages.AddBoundingBox;
6 import com.irtimaled.bbor.common.messages.InitializeClient;
7 import com.irtimaled.bbor.common.messages.PayloadBuilder;
8 import com.irtimaled.bbor.common.models.AbstractBoundingBox;
9 import com.irtimaled.bbor.common.models.ServerPlayer;
10
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.Map;
14 import java.util.Set;
15 import java.util.concurrent.ConcurrentHashMap;
16
17 public class CommonProxy {
18     private final Map<Integer, ServerPlayer> players = new ConcurrentHashMap<>();
19     private final Map<Integer, Set<AbstractBoundingBox>> playerBoundingBoxesCache = new HashMap<>();
20     private final Map<Integer, StructureProcessor> structureProcessors = new HashMap<>();
21     private final Map<Integer, BoundingBoxCache> dimensionCache = new ConcurrentHashMap<>();
22     private Long seed = null;
23     private Integer spawnX = null;
24     private Integer spawnZ = null;
25
26     public void init() {
27         BoundingBoxType.registerTypes();
28         EventBus.subscribe(WorldLoaded.class, this::worldLoaded);
29         EventBus.subscribe(StructuresLoaded.class, this::structuresLoaded);
30         EventBus.subscribe(PlayerLoggedIn.class, this::playerLoggedIn);
31         EventBus.subscribe(PlayerLoggedOut.class, this::playerLoggedOut);
32         EventBus.subscribe(PlayerSubscribed.class, this::onPlayerSubscribed);
33         EventBus.subscribe(ServerTick.class, e -> serverTick());
34     }
35
36     protected void setSeed(long seed) {
37         this.seed = seed;
38     }
39
40     protected void setWorldSpawn(int spawnX, int spawnZ) {
41         this.spawnX = spawnX;
42         this.spawnZ = spawnZ;
43     }
44
45     private void worldLoaded(WorldLoaded event) {
46         int dimensionId = event.getDimensionId();
47         long seed = event.getSeed();
48         if (dimensionId == Dimensions.OVERWORLD) {
49             setSeed(seed);
50             setWorldSpawn(event.getSpawnX(), event.getSpawnZ());
51         }
52         Logger.info("create world dimension: %s (seed: %d)", dimensionId, seed);
53     }
54
55     private void structuresLoaded(StructuresLoaded event) {
56         int dimensionId = event.getDimensionId();
57         StructureProcessor structureProcessor = getStructureProcessor(dimensionId);
58         structureProcessor.process(event.getStructures());
59     }
60
61     private StructureProcessor getStructureProcessor(int dimensionId) {
62         StructureProcessor structureProcessor = structureProcessors.get(dimensionId);
63         if (structureProcessor == null) {
64             structureProcessor = new StructureProcessor(getOrCreateCache(dimensionId));
65             structureProcessors.put(dimensionId, structureProcessor);
66         }
67         return structureProcessor;
68     }
69
70     private void playerLoggedIn(PlayerLoggedIn event) {
71         if (seed == null || spawnX == null || spawnZ == null) {
72             return;
73         }
74         ServerPlayer player = event.getPlayer();
75         player.sendPacket(InitializeClient.getPayload(seed, spawnX, spawnZ));
76     }
77
78     private void playerLoggedOut(PlayerLoggedOut event) {
79         int playerId = event.getPlayerId();
80         players.remove(playerId);
81         playerBoundingBoxesCache.remove(playerId);
82     }
83
84     private void onPlayerSubscribed(PlayerSubscribed event) {
85         int playerId = event.getPlayerId();
86         ServerPlayer player = event.getPlayer();
87         players.put(playerId, player);
88         sendToPlayer(playerId, player);
89     }
90
91     private void sendToPlayer(int playerId, ServerPlayer player) {
92         for (Map.Entry<Integer, BoundingBoxCache> entry : dimensionCache.entrySet()) {
93             int dimensionId = entry.getKey();
94             BoundingBoxCache boundingBoxCache = entry.getValue();
95             if (boundingBoxCache == null) return;
96
97             Set<AbstractBoundingBox> playerBoundingBoxes = playerBoundingBoxesCache.computeIfAbsent(playerId, k -> new HashSet<>());
98
99             Map<AbstractBoundingBox, Set<AbstractBoundingBox>> boundingBoxMap = boundingBoxCache.getBoundingBoxes();
100             for (AbstractBoundingBox key : boundingBoxMap.keySet()) {
101                 if (playerBoundingBoxes.contains(key)) {
102                     continue;
103                 }
104
105                 Set<AbstractBoundingBox> boundingBoxes = boundingBoxMap.get(key);
106                 PayloadBuilder payload = AddBoundingBox.getPayload(dimensionId, key, boundingBoxes);
107                 if (payload != null)
108                     player.sendPacket(payload);
109
110                 playerBoundingBoxes.add(key);
111             }
112         }
113     }
114
115     private void serverTick() {
116         for (Map.Entry<Integer, ServerPlayer> playerEntry : players.entrySet()) {
117             int playerId = playerEntry.getKey();
118             ServerPlayer player = playerEntry.getValue();
119
120             sendToPlayer(playerId, player);
121         }
122     }
123
124     protected BoundingBoxCache getCache(int dimensionId) {
125         return dimensionCache.get(dimensionId);
126     }
127
128     protected BoundingBoxCache getOrCreateCache(int dimensionId) {
129         return dimensionCache.computeIfAbsent(dimensionId, dt -> new BoundingBoxCache());
130     }
131
132     protected void clearCaches() {
133         structureProcessors.clear();
134         for (BoundingBoxCache cache : dimensionCache.values()) {
135             cache.clear();
136         }
137         dimensionCache.clear();
138     }
139 }