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