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