Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
at develop 226 lines 7.7 kB view raw
1package org.bukkit.craftbukkit; 2 3import com.google.common.collect.MapMaker; 4import net.minecraft.server.BiomeBase; 5import net.minecraft.server.ChunkPosition; 6import net.minecraft.server.WorldChunkManager; 7import net.minecraft.server.WorldServer; 8import org.bukkit.Chunk; 9import org.bukkit.ChunkSnapshot; 10import org.bukkit.World; 11import org.bukkit.block.Block; 12import org.bukkit.block.BlockState; 13import org.bukkit.craftbukkit.block.CraftBlock; 14import org.bukkit.entity.Entity; 15 16import java.lang.ref.WeakReference; 17import java.util.concurrent.ConcurrentMap; 18 19public class CraftChunk implements Chunk { 20 private WeakReference<net.minecraft.server.Chunk> weakChunk; 21 private final ConcurrentMap<Integer, Block> cache = new MapMaker().softValues().makeMap(); 22 private WorldServer worldServer; 23 private int x; 24 private int z; 25 26 public CraftChunk(net.minecraft.server.Chunk chunk) { 27 this.weakChunk = new WeakReference<net.minecraft.server.Chunk>(chunk); 28 worldServer = (WorldServer) getHandle().world; 29 x = getHandle().x; 30 z = getHandle().z; 31 } 32 33 public World getWorld() { 34 return worldServer.getWorld(); 35 } 36 37 public net.minecraft.server.Chunk getHandle() { 38 net.minecraft.server.Chunk c = weakChunk.get(); 39 if (c == null) { 40 c = worldServer.getChunkAt(x, z); 41 weakChunk = new WeakReference<net.minecraft.server.Chunk>(c); 42 } 43 return c; 44 } 45 46 void breakLink() { 47 weakChunk.clear(); 48 } 49 50 public int getX() { 51 return x; 52 } 53 54 public int getZ() { 55 return z; 56 } 57 58 @Override 59 public String toString() { 60 return "CraftChunk{" + "x=" + getX() + "z=" + getZ() + '}'; 61 } 62 63 public Block getBlock(int x, int y, int z) { 64 int pos = (x & 0xF) << 11 | (z & 0xF) << 7 | (y & 0x7F); 65 Block block = this.cache.get(pos); 66 if (block == null) { 67 Block newBlock = new CraftBlock(this, (getX() << 4) | (x & 0xF), y & 0x7F, (getZ() << 4) | (z & 0xF)); 68 Block oldBlock = this.cache.put(pos, newBlock); 69 if (oldBlock == null) { 70 block = newBlock; 71 } else { 72 block = oldBlock; 73 } 74 } 75 return block; 76 } 77 78 public Entity[] getEntities() { 79 int count = 0, index = 0; 80 net.minecraft.server.Chunk chunk = getHandle(); 81 for (int i = 0; i < 8; i++) { 82 count += chunk.entitySlices[i].size(); 83 } 84 85 Entity[] entities = new Entity[count]; 86 for (int i = 0; i < 8; i++) { 87 for (Object obj : chunk.entitySlices[i].toArray()) { 88 if (!(obj instanceof net.minecraft.server.Entity)) { 89 continue; 90 } 91 entities[index++] = ((net.minecraft.server.Entity) obj).getBukkitEntity(); 92 } 93 } 94 return entities; 95 } 96 97 public BlockState[] getTileEntities() { 98 int index = 0; 99 net.minecraft.server.Chunk chunk = getHandle(); 100 BlockState[] entities = new BlockState[chunk.tileEntities.size()]; 101 for (Object obj : chunk.tileEntities.keySet().toArray()) { 102 if (!(obj instanceof ChunkPosition)) { 103 continue; 104 } 105 ChunkPosition position = (ChunkPosition) obj; 106 entities[index++] = worldServer.getWorld().getBlockAt(position.x + (chunk.x << 4), position.y, position.z + (chunk.z << 4)).getState(); 107 } 108 return entities; 109 } 110 111 public boolean isLoaded() { 112 return getWorld().isChunkLoaded(this); 113 } 114 115 public boolean load() { 116 return getWorld().loadChunk(getX(), getZ(), true); 117 } 118 119 public boolean load(boolean generate) { 120 return getWorld().loadChunk(getX(), getZ(), generate); 121 } 122 123 public boolean unload() { 124 return getWorld().unloadChunk(getX(), getZ()); 125 } 126 127 public boolean unload(boolean save) { 128 return getWorld().unloadChunk(getX(), getZ(), save); 129 } 130 131 public boolean unload(boolean save, boolean safe) { 132 return getWorld().unloadChunk(getX(), getZ(), save, safe); 133 } 134 135 public ChunkSnapshot getChunkSnapshot() { 136 return getChunkSnapshot(true, false, false); 137 } 138 139 public ChunkSnapshot getChunkSnapshot(boolean includeMaxblocky, boolean includeBiome, boolean includeBiomeTempRain) { 140 net.minecraft.server.Chunk chunk = getHandle(); 141 byte[] buf = new byte[32768 + 16384 + 16384 + 16384]; // Get big enough buffer for whole chunk 142 chunk.getData(buf, 0, 0, 0, 16, 128, 16, 0); // Get whole chunk 143 byte[] hmap = null; 144 145 if (includeMaxblocky) { 146 hmap = new byte[256]; // Get copy of height map 147 System.arraycopy(chunk.heightMap, 0, hmap, 0, 256); 148 } 149 150 BiomeBase[] biome = null; 151 double[] biomeTemp = null; 152 double[] biomeRain = null; 153 154 if (includeBiome || includeBiomeTempRain) { 155 WorldChunkManager wcm = chunk.world.getWorldChunkManager(); 156 BiomeBase[] biomeBase = wcm.getBiomeData(getX() << 4, getZ() << 4, 16, 16); 157 158 if (includeBiome) { 159 biome = new BiomeBase[256]; 160 System.arraycopy(biomeBase, 0, biome, 0, biome.length); 161 } 162 163 if (includeBiomeTempRain) { 164 biomeTemp = new double[256]; 165 biomeRain = new double[256]; 166 System.arraycopy(wcm.temperature, 0, biomeTemp, 0, biomeTemp.length); 167 System.arraycopy(wcm.rain, 0, biomeRain, 0, biomeRain.length); 168 } 169 } 170 World world = getWorld(); 171 return new CraftChunkSnapshot(getX(), getZ(), world.getName(), world.getFullTime(), buf, hmap, biome, biomeTemp, biomeRain); 172 } 173 174 /** 175 * Empty chunk snapshot - nothing but air blocks, but can include valid biome data 176 */ 177 private static class EmptyChunkSnapshot extends CraftChunkSnapshot { 178 EmptyChunkSnapshot(int x, int z, String worldName, long time, BiomeBase[] biome, double[] biomeTemp, double[] biomeRain) { 179 super(x, z, worldName, time, null, null, biome, biomeTemp, biomeRain); 180 } 181 182 public final int getBlockTypeId(int x, int y, int z) { 183 return 0; 184 } 185 186 public final int getBlockData(int x, int y, int z) { 187 return 0; 188 } 189 190 public final int getBlockSkyLight(int x, int y, int z) { 191 return 15; 192 } 193 194 public final int getBlockEmittedLight(int x, int y, int z) { 195 return 0; 196 } 197 198 public final int getHighestBlockYAt(int x, int z) { 199 return 0; 200 } 201 } 202 203 public static ChunkSnapshot getEmptyChunkSnapshot(int x, int z, CraftWorld world, boolean includeBiome, boolean includeBiomeTempRain) { 204 BiomeBase[] biome = null; 205 double[] biomeTemp = null; 206 double[] biomeRain = null; 207 208 if (includeBiome || includeBiomeTempRain) { 209 WorldChunkManager wcm = world.getHandle().getWorldChunkManager(); 210 BiomeBase[] biomeBase = wcm.getBiomeData(x << 4, z << 4, 16, 16); 211 212 if (includeBiome) { 213 biome = new BiomeBase[256]; 214 System.arraycopy(biomeBase, 0, biome, 0, biome.length); 215 } 216 217 if (includeBiomeTempRain) { 218 biomeTemp = new double[256]; 219 biomeRain = new double[256]; 220 System.arraycopy(wcm.temperature, 0, biomeTemp, 0, biomeTemp.length); 221 System.arraycopy(wcm.rain, 0, biomeRain, 0, biomeRain.length); 222 } 223 } 224 return new EmptyChunkSnapshot(x, z, world.getName(), world.getFullTime(), biome, biomeTemp, biomeRain); 225 } 226}