Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
at develop 280 lines 10 kB view raw
1package net.minecraft.server; 2 3import com.legacyminecraft.poseidon.PoseidonConfig; 4import org.bukkit.craftbukkit.CraftChunk; 5import org.bukkit.craftbukkit.util.LongHashset; 6import org.bukkit.craftbukkit.util.LongHashtable; 7import org.bukkit.event.world.ChunkLoadEvent; 8import org.bukkit.event.world.ChunkPopulateEvent; 9import org.bukkit.event.world.ChunkUnloadEvent; 10import org.bukkit.generator.BlockPopulator; 11 12import java.util.ArrayList; 13import java.util.List; 14import java.util.Random; 15 16// CraftBukkit start 17// CraftBukkit end 18 19public class ChunkProviderServer implements IChunkProvider { 20 21 // CraftBukkit start 22 public LongHashset unloadQueue = new LongHashset(); 23 public Chunk emptyChunk; 24 public IChunkProvider chunkProvider; // CraftBukkit 25 private IChunkLoader e; 26 public boolean forceChunkLoad = false; 27 public LongHashtable<Chunk> chunks = new LongHashtable<Chunk>(); 28 public List chunkList = new ArrayList(); 29 public WorldServer world; 30 // CraftBukkit end 31 32 public ChunkProviderServer(WorldServer worldserver, IChunkLoader ichunkloader, IChunkProvider ichunkprovider) { 33 this.emptyChunk = new EmptyChunk(worldserver, new byte['\u8000'], 0, 0); 34 this.world = worldserver; 35 this.e = ichunkloader; 36 this.chunkProvider = ichunkprovider; 37 } 38 39 public boolean isChunkLoaded(int i, int j) { 40 return this.chunks.containsKey(i, j); // CraftBukkit 41 } 42 43 public void queueUnload(int i, int j) { 44 ChunkCoordinates chunkcoordinates = this.world.getSpawn(); 45 int k = i * 16 + 8 - chunkcoordinates.x; 46 int l = j * 16 + 8 - chunkcoordinates.z; 47 short short1 = 128; 48 49 if (k < -short1 || k > short1 || l < -short1 || l > short1 || !(this.world.keepSpawnInMemory)) { // CraftBukkit - added 'this.world.keepSpawnInMemory' 50 this.unloadQueue.add(i, j); // CraftBukkit 51 } 52 } 53 54 public Chunk getChunkAt(int i, int j) { 55 // CraftBukkit start 56 this.unloadQueue.remove(i, j); 57 Chunk chunk = (Chunk) this.chunks.get(i, j); 58 boolean newChunk = false; 59 // CraftBukkit end 60 61 if (chunk == null) { 62 chunk = this.loadChunk(i, j); 63 if (chunk == null) { 64 if (this.chunkProvider == null) { 65 chunk = this.emptyChunk; 66 } else { 67 chunk = this.chunkProvider.getOrCreateChunk(i, j); 68 } 69 newChunk = true; // CraftBukkit 70 } 71 72 this.chunks.put(i, j, chunk); // CraftBukkit 73 this.chunkList.add(chunk); 74 if (chunk != null) { 75 chunk.loadNOP(); 76 chunk.addEntities(); 77 } 78 79 // CraftBukkit start 80 org.bukkit.Server server = this.world.getServer(); 81 if (server != null) { 82 /* 83 * If it's a new world, the first few chunks are generated inside 84 * the World constructor. We can't reliably alter that, so we have 85 * no way of creating a CraftWorld/CraftServer at that point. 86 */ 87 server.getPluginManager().callEvent(new ChunkLoadEvent(chunk.bukkitChunk, newChunk)); 88 } 89 // CraftBukkit end 90 91 if (!chunk.done && this.isChunkLoaded(i + 1, j + 1) && this.isChunkLoaded(i, j + 1) && this.isChunkLoaded(i + 1, j)) { 92 this.getChunkAt(this, i, j); 93 } 94 95 if (this.isChunkLoaded(i - 1, j) && !this.getOrCreateChunk(i - 1, j).done && this.isChunkLoaded(i - 1, j + 1) && this.isChunkLoaded(i, j + 1) && this.isChunkLoaded(i - 1, j)) { 96 this.getChunkAt(this, i - 1, j); 97 } 98 99 if (this.isChunkLoaded(i, j - 1) && !this.getOrCreateChunk(i, j - 1).done && this.isChunkLoaded(i + 1, j - 1) && this.isChunkLoaded(i, j - 1) && this.isChunkLoaded(i + 1, j)) { 100 this.getChunkAt(this, i, j - 1); 101 } 102 103 if (this.isChunkLoaded(i - 1, j - 1) && !this.getOrCreateChunk(i - 1, j - 1).done && this.isChunkLoaded(i - 1, j - 1) && this.isChunkLoaded(i, j - 1) && this.isChunkLoaded(i - 1, j)) { 104 this.getChunkAt(this, i - 1, j - 1); 105 } 106 } 107 108 return chunk; 109 } 110 111 public Chunk getOrCreateChunk(int i, int j) { 112 // CraftBukkit start 113 Chunk chunk = (Chunk) this.chunks.get(i, j); 114 115 //Poseidon chunk regenerate 116 try { 117 chunk = chunk == null ? (!this.world.isLoading && !this.forceChunkLoad ? this.emptyChunk : this.getChunkAt(i, j)) : chunk; 118 } catch (Exception e) { 119 //Poseidon chunk regenerate 120 if (PoseidonConfig.getInstance().getConfigBoolean("emergency.debug.regenerate-corrupt-chunks.enable")) { 121 System.out.println("Poseidon ran into a critical error when attempting to load a chunk (" + i + "," + j + "+. Regenerating chunk..."); 122 chunk = this.emptyChunk; 123 } else { 124 System.out.println("Poseidon ran into a critical error when attempting to load a chunk (" + i + "," + j + "+. The server will now likely hang. Enabling \"emergency.debug.regenerate-corrupt-chunks.enable\" in the Poseidon.yml may help."); 125 e.printStackTrace(); 126 } 127 e.printStackTrace(); 128 } 129 130 131 if (chunk == this.emptyChunk) return chunk; 132 if (i != chunk.x || j != chunk.z) { 133 MinecraftServer.log.info("Chunk (" + chunk.x + ", " + chunk.z + ") stored at (" + i + ", " + j + ")"); 134 MinecraftServer.log.info(chunk.getClass().getName()); 135 Throwable ex = new Throwable(); 136 ex.fillInStackTrace(); 137 ex.printStackTrace(); 138 } 139 return chunk; 140 // CraftBukkit end 141 } 142 143 public Chunk loadChunk(int i, int j) { // CraftBukkit - private -> public 144 if (this.e == null) { 145 return null; 146 } else { 147 try { 148 Chunk chunk = this.e.a(this.world, i, j); 149 150 if (chunk != null) { 151 chunk.r = this.world.getTime(); 152 } 153 154 return chunk; 155 } catch (Exception exception) { 156 exception.printStackTrace(); 157 return null; 158 } 159 } 160 } 161 162 public void saveChunkNOP(Chunk chunk) { // CraftBukkit - private -> public 163 if (this.e != null) { 164 try { 165 this.e.b(this.world, chunk); 166 } catch (Exception exception) { 167 exception.printStackTrace(); 168 } 169 } 170 } 171 172 public void saveChunk(Chunk chunk) { // CraftBukkit - private -> public 173 if (this.e != null) { 174 try { 175 chunk.r = this.world.getTime(); 176 this.e.a(this.world, chunk); 177 } catch (Exception ioexception) { // CraftBukkit - IOException -> Exception 178 ioexception.printStackTrace(); 179 } 180 } 181 } 182 183 public void getChunkAt(IChunkProvider ichunkprovider, int i, int j) { 184 Chunk chunk = this.getOrCreateChunk(i, j); 185 186 if (!chunk.done) { 187 chunk.done = true; 188 if (this.chunkProvider != null) { 189 this.chunkProvider.getChunkAt(ichunkprovider, i, j); 190 191 // CraftBukkit start 192 BlockSand.instaFall = true; 193 Random random = new Random(); 194 random.setSeed(world.getSeed()); 195 long xRand = random.nextLong() / 2L * 2L + 1L; 196 long zRand = random.nextLong() / 2L * 2L + 1L; 197 random.setSeed((long) i * xRand + (long) j * zRand ^ world.getSeed()); 198 199 org.bukkit.World world = this.world.getWorld(); 200 if (world != null) { 201 for (BlockPopulator populator : world.getPopulators()) { 202 populator.populate(world, random, chunk.bukkitChunk); 203 } 204 } 205 BlockSand.instaFall = false; 206 this.world.getServer().getPluginManager().callEvent(new ChunkPopulateEvent(chunk.bukkitChunk)); 207 // CraftBukkit end 208 209 chunk.f(); 210 } 211 } 212 } 213 214 public boolean saveChunks(boolean flag, IProgressUpdate iprogressupdate) { 215 int i = 0; 216 217 for (int j = 0; j < this.chunkList.size(); ++j) { 218 Chunk chunk = (Chunk) this.chunkList.get(j); 219 220 if (flag && !chunk.p) { 221 this.saveChunkNOP(chunk); 222 } 223 224 if (chunk.a(flag)) { 225 this.saveChunk(chunk); 226 chunk.o = false; 227 ++i; 228 if (i == 24 && !flag) { 229 return false; 230 } 231 } 232 } 233 234 if (flag) { 235 if (this.e == null) { 236 return true; 237 } 238 239 this.e.b(); 240 } 241 242 return true; 243 } 244 245 public boolean unloadChunks() { 246 if (!this.world.canSave) { 247 // CraftBukkit start 248 org.bukkit.Server server = this.world.getServer(); 249 for (int i = 0; i < 50 && !this.unloadQueue.isEmpty(); i++) { 250 long chunkcoordinates = this.unloadQueue.popFirst(); 251 Chunk chunk = this.chunks.get(chunkcoordinates); 252 if (chunk == null) continue; 253 254 ChunkUnloadEvent event = new ChunkUnloadEvent(chunk.bukkitChunk); 255 server.getPluginManager().callEvent(event); 256 if (!event.isCancelled()) { 257// this.world.getWorld().preserveChunk((CraftChunk) chunk.bukkitChunk); 258 259 chunk.removeEntities(); 260 this.saveChunk(chunk); 261 this.saveChunkNOP(chunk); 262 // this.unloadQueue.remove(integer); 263 this.chunks.remove(chunkcoordinates); // CraftBukkit 264 this.chunkList.remove(chunk); 265 } 266 } 267 // CraftBukkit end 268 269 if (this.e != null) { 270 this.e.a(); 271 } 272 } 273 274 return this.chunkProvider.unloadChunks(); 275 } 276 277 public boolean canSave() { 278 return !this.world.canSave; 279 } 280}