]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - java/com/irtimaled/bbor/CommonProxy.java
Fix #4
[BoundingBoxOutlineReloaded.git] / java / com / irtimaled / bbor / CommonProxy.java
1 package com.irtimaled.bbor;
2
3 import com.irtimaled.bbor.messages.*;
4 import net.minecraft.entity.player.EntityPlayer;
5 import net.minecraft.entity.player.EntityPlayerMP;
6 import net.minecraft.server.MinecraftServer;
7 import net.minecraft.world.chunk.IChunkProvider;
8 import net.minecraft.world.gen.ChunkProviderServer;
9 import net.minecraftforge.event.world.ChunkEvent;
10 import net.minecraftforge.event.world.WorldEvent;
11 import net.minecraftforge.fml.common.FMLLog;
12 import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
13 import net.minecraftforge.fml.common.gameevent.PlayerEvent;
14 import net.minecraftforge.fml.common.gameevent.TickEvent;
15 import net.minecraftforge.fml.common.network.NetworkRegistry;
16 import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
17 import net.minecraftforge.fml.relauncher.Side;
18
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.concurrent.ConcurrentHashMap;
24
25 public class CommonProxy {
26
27     public Map<Integer, BoundingBoxCache> boundingBoxCacheMap = new ConcurrentHashMap<Integer, BoundingBoxCache>();
28     public Map<EntityPlayerMP, Integer> playerDimensions = new ConcurrentHashMap<EntityPlayerMP, Integer>();
29     private Map<EntityPlayerMP, Set<BoundingBox>> playerBoundingBoxesCache = new HashMap<EntityPlayerMP, Set<BoundingBox>>();
30
31     public ConfigManager configManager;
32     protected SimpleNetworkWrapper network;
33     protected long seed;
34     protected int spawnX;
35     protected int spawnZ;
36     protected boolean initialized;
37
38     public void init() {
39         network = NetworkRegistry.INSTANCE.newSimpleChannel("bbor");
40         network.registerMessage(AddBoundingBoxMessageHandler.class, AddBoundingBoxMessage.class, 0, Side.CLIENT);
41         network.registerMessage(RemoveBoundingBoxMessageHandler.class, RemoveBoundingBoxMessage.class, 1, Side.CLIENT);
42         network.registerMessage(InitializeClientMessageHandler.class, InitializeClientMessage.class, 2, Side.CLIENT);
43     }
44
45     @SubscribeEvent
46     public void worldEvent(WorldEvent.Load event) {
47         IChunkProvider chunkProvider = event.world.getChunkProvider();
48         if (chunkProvider instanceof ChunkProviderServer) {
49             chunkProvider = ((ChunkProviderServer) chunkProvider).serverChunkGenerator;
50             setWorldData(event.world.getSeed(), event.world.getWorldInfo().getSpawnX(), event.world.getWorldInfo().getSpawnZ());
51             int dimensionId = event.world.provider.getDimensionId();
52             FMLLog.info("create world dimension: %d, %s (chunkprovider: %s) (seed: %d)", dimensionId, event.world.getClass().toString(), chunkProvider.getClass().toString(), seed);
53             boundingBoxCacheMap.put(dimensionId, new DimensionProcessor(configManager, event.world, dimensionId, chunkProvider));
54         }
55     }
56
57     @SubscribeEvent
58     public void chunkEvent(ChunkEvent.Load event) {
59         int dimensionId = event.world.provider.getDimensionId();
60         if (boundingBoxCacheMap.containsKey(dimensionId)) {
61             boundingBoxCacheMap.get(dimensionId).refresh();
62         }
63     }
64
65     @SubscribeEvent
66     public void playerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent evt) {
67         if (playerDimensions.containsKey(evt.player)) {
68             EntityPlayerMP player = (EntityPlayerMP) evt.player;
69             int dimension = player.dimension;
70             playerDimensions.put(player, dimension);
71
72             sendToPlayer(player, boundingBoxCacheMap.get(dimension));
73         }
74     }
75
76     protected boolean isRemotePlayer(EntityPlayer player) {
77         return true;
78     }
79
80     @SubscribeEvent
81     public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent evt) {
82         if (evt.player instanceof EntityPlayerMP &&
83                 isRemotePlayer(evt.player)) {
84             EntityPlayerMP player = (EntityPlayerMP) evt.player;
85             initializeClient(player);
86             int dimension = player.dimension;
87             playerDimensions.put(player, dimension);
88             sendToPlayer(player, boundingBoxCacheMap.get(dimension));
89         }
90     }
91
92     @SubscribeEvent
93     public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent evt) {
94         if (playerDimensions.containsKey(evt.player)) {
95             playerDimensions.remove(evt.player);
96             playerBoundingBoxesCache.remove(evt.player);
97         }
98     }
99
100     @SubscribeEvent
101     public void tickEvent(TickEvent event) {
102         for (EntityPlayerMP player : playerDimensions.keySet()) {
103
104             MinecraftServer mc = MinecraftServer.getServer();
105             if (!mc.getConfigurationManager().playerEntityList.contains(player)) {
106                 playerDimensions.remove(player);
107             } else {
108                 int dimension = playerDimensions.get(player);
109                 if (boundingBoxCacheMap.containsKey(dimension)) {
110                     sendToPlayer(player, boundingBoxCacheMap.get(dimension));
111                 }
112             }
113         }
114     }
115
116     private void initializeClient(EntityPlayerMP player) {
117         network.sendTo(InitializeClientMessage.from(seed, spawnX, spawnZ), player);
118     }
119
120     private void sendToPlayer(EntityPlayerMP player, BoundingBoxCache boundingBoxCache) {
121         Map<BoundingBox, Set<BoundingBox>> cacheSubset = getBoundingBoxMap(player, boundingBoxCache.getBoundingBoxes());
122
123         int dimension = player.dimension;
124         if (cacheSubset.keySet().size() > 0) {
125             FMLLog.info("send %d entries to %s (%d)", cacheSubset.keySet().size(), player.getDisplayNameString(), dimension);
126         }
127
128         for (BoundingBox key : cacheSubset.keySet()) {
129             Set<BoundingBox> boundingBoxes = cacheSubset.get(key);
130             network.sendTo(AddBoundingBoxMessage.from(dimension, key, boundingBoxes), player);
131
132             if (!playerBoundingBoxesCache.containsKey(player)) {
133                 playerBoundingBoxesCache.put(player, new HashSet<BoundingBox>());
134             }
135             playerBoundingBoxesCache.get(player).add(key);
136         }
137     }
138
139     private Map<BoundingBox, Set<BoundingBox>> getBoundingBoxMap(EntityPlayerMP player, Map<BoundingBox, Set<BoundingBox>> boundingBoxMap) {
140         Map<BoundingBox, Set<BoundingBox>> cacheSubset = new HashMap<BoundingBox, Set<BoundingBox>>();
141         for (BoundingBox key : boundingBoxMap.keySet()) {
142             if (!playerBoundingBoxesCache.containsKey(player) || !playerBoundingBoxesCache.get(player).contains(key)) {
143                 cacheSubset.put(key, boundingBoxMap.get(key));
144             }
145         }
146         return cacheSubset;
147     }
148
149     public void boundingBoxRemoved(BoundingBox bb) {
150         // the only bounding boxes that can change are spawn or villages - both of these are in overworld so I guess
151         // hard coding dimension 0 is okay.
152         RemoveBoundingBoxMessage message = RemoveBoundingBoxMessage.from(0, bb);
153         for (EntityPlayerMP player : playerDimensions.keySet()) {
154             if (player.dimension == 0) {
155                 FMLLog.info("remove 1 entry from %s (0)", player.getDisplayNameString());
156                 network.sendTo(message, player);
157
158                 if (playerBoundingBoxesCache.containsKey(player) &&
159                         playerBoundingBoxesCache.get(player).contains(bb)) {
160                     playerBoundingBoxesCache.get(player).remove(bb);
161                 }
162             }
163         }
164     }
165
166     public void setWorldData(long seed, int spawnX, int spawnZ) {
167         this.seed = seed;
168         this.spawnX = spawnX;
169         this.spawnZ = spawnZ;
170         this.initialized = true;
171     }
172
173     public void setWorldData(IWorldData worldData) {
174         setWorldData(worldData.getSeed(), worldData.getSpawnX(), worldData.getSpawnZ());
175     }
176 }