Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
at develop 912 lines 34 kB view raw
1package org.bukkit.craftbukkit; 2 3import java.util.ArrayList; 4import java.util.List; 5import java.util.Random; 6import java.util.UUID; 7 8import org.bukkit.BlockChangeDelegate; 9import org.bukkit.Bukkit; 10import org.bukkit.Chunk; 11import org.bukkit.ChunkSnapshot; 12import org.bukkit.Effect; 13import org.bukkit.Location; 14import org.bukkit.TreeType; 15import org.bukkit.World; 16import org.bukkit.block.Biome; 17import org.bukkit.block.Block; 18import org.bukkit.craftbukkit.entity.CraftEntity; 19import org.bukkit.craftbukkit.entity.CraftItem; 20import org.bukkit.craftbukkit.entity.CraftLightningStrike; 21import org.bukkit.craftbukkit.entity.CraftMinecart; 22import org.bukkit.craftbukkit.entity.CraftPlayer; 23import org.bukkit.entity.Arrow; 24import org.bukkit.entity.Boat; 25import org.bukkit.entity.Chicken; 26import org.bukkit.entity.Cow; 27import org.bukkit.entity.CreatureType; 28import org.bukkit.entity.Creeper; 29import org.bukkit.entity.Egg; 30import org.bukkit.entity.Entity; 31import org.bukkit.entity.FallingSand; 32import org.bukkit.entity.Fireball; 33import org.bukkit.entity.Fish; 34import org.bukkit.entity.Ghast; 35import org.bukkit.entity.LightningStrike; 36import org.bukkit.entity.LivingEntity; 37import org.bukkit.entity.Minecart; 38import org.bukkit.entity.Painting; 39import org.bukkit.entity.Pig; 40import org.bukkit.entity.PigZombie; 41import org.bukkit.entity.Player; 42import org.bukkit.entity.PoweredMinecart; 43import org.bukkit.entity.Sheep; 44import org.bukkit.entity.Skeleton; 45import org.bukkit.entity.Slime; 46import org.bukkit.entity.Snowball; 47import org.bukkit.entity.Spider; 48import org.bukkit.entity.Squid; 49import org.bukkit.entity.StorageMinecart; 50import org.bukkit.entity.TNTPrimed; 51import org.bukkit.entity.Weather; 52import org.bukkit.entity.Wolf; 53import org.bukkit.entity.Zombie; 54import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; 55import org.bukkit.event.entity.EntityDamageEvent; 56import org.bukkit.event.weather.ThunderChangeEvent; 57import org.bukkit.event.weather.WeatherChangeEvent; 58import org.bukkit.event.world.SpawnChangeEvent; 59import org.bukkit.generator.BlockPopulator; 60import org.bukkit.generator.ChunkGenerator; 61import org.bukkit.inventory.ItemStack; 62import org.bukkit.util.Vector; 63 64import net.minecraft.server.BiomeBase; 65import net.minecraft.server.ChunkCoordinates; 66import net.minecraft.server.EntityArrow; 67import net.minecraft.server.EntityBoat; 68import net.minecraft.server.EntityChicken; 69import net.minecraft.server.EntityCow; 70import net.minecraft.server.EntityCreeper; 71import net.minecraft.server.EntityEgg; 72import net.minecraft.server.EntityFallingSand; 73import net.minecraft.server.EntityFireball; 74import net.minecraft.server.EntityFish; 75import net.minecraft.server.EntityGhast; 76import net.minecraft.server.EntityItem; 77import net.minecraft.server.EntityLiving; 78import net.minecraft.server.EntityMinecart; 79import net.minecraft.server.EntityPig; 80import net.minecraft.server.EntityPigZombie; 81import net.minecraft.server.EntitySheep; 82import net.minecraft.server.EntitySkeleton; 83import net.minecraft.server.EntitySlime; 84import net.minecraft.server.EntitySnowball; 85import net.minecraft.server.EntitySpider; 86import net.minecraft.server.EntitySquid; 87import net.minecraft.server.EntityTNTPrimed; 88import net.minecraft.server.EntityTypes; 89import net.minecraft.server.EntityWeatherStorm; 90import net.minecraft.server.EntityWolf; 91import net.minecraft.server.EntityZombie; 92import net.minecraft.server.Packet4UpdateTime; 93import net.minecraft.server.Packet61; 94import net.minecraft.server.TileEntity; 95import net.minecraft.server.WorldGenBigTree; 96import net.minecraft.server.WorldGenForest; 97import net.minecraft.server.WorldGenTaiga1; 98import net.minecraft.server.WorldGenTaiga2; 99import net.minecraft.server.WorldGenTrees; 100import net.minecraft.server.WorldProvider; 101import net.minecraft.server.WorldServer; 102import uk.betacraft.uberbukkit.Uberbukkit; 103 104public class CraftWorld implements World { 105 private final WorldServer world; 106 private Environment environment; 107 private final CraftServer server = (CraftServer) Bukkit.getServer(); 108 // private ConcurrentMap<Integer, CraftChunk> unloadedChunks = new MapMaker().weakValues().makeMap(); 109 private final ChunkGenerator generator; 110 private final List<BlockPopulator> populators = new ArrayList<BlockPopulator>(); 111 112 private static final Random rand = new Random(); 113 114 public CraftWorld(WorldServer world, ChunkGenerator gen, Environment env) { 115 this.world = world; 116 this.generator = gen; 117 118 environment = env; 119 } 120 121// public void preserveChunk(CraftChunk chunk) { 122// chunk.breakLink(); 123// unloadedChunks.put((chunk.getX() << 16) + chunk.getZ(), chunk); 124// } 125// 126// public Chunk popPreservedChunk(int x, int z) { 127// return unloadedChunks.remove((x << 16) + z); 128// } 129 130 public Block getBlockAt(int x, int y, int z) { 131 return getChunkAt(x >> 4, z >> 4).getBlock(x & 0xF, y & 0x7F, z & 0xF); 132 } 133 134 public int getBlockTypeIdAt(int x, int y, int z) { 135 return world.getTypeId(x, y, z); 136 } 137 138 public int getHighestBlockYAt(int x, int z) { 139 return world.getHighestBlockYAt(x, z); 140 } 141 142 public Location getSpawnLocation() { 143 ChunkCoordinates spawn = world.getSpawn(); 144 return new Location(this, spawn.x, spawn.y, spawn.z); 145 } 146 147 public boolean setSpawnLocation(int x, int y, int z) { 148 try { 149 Location previousLocation = getSpawnLocation(); 150 world.worldData.setSpawn(x, y, z); 151 152 // Notify anyone who's listening. 153 SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); 154 server.getPluginManager().callEvent(event); 155 156 return true; 157 } catch (Exception e) { 158 return false; 159 } 160 } 161 162 public Chunk getChunkAt(int x, int z) { 163 return this.world.chunkProviderServer.getChunkAt(x, z).bukkitChunk; 164 } 165 166 public Chunk getChunkAt(Block block) { 167 return getChunkAt(block.getX() >> 4, block.getZ() >> 4); 168 } 169 170 public boolean isChunkLoaded(int x, int z) { 171 return world.chunkProviderServer.isChunkLoaded(x, z); 172 } 173 174 public Chunk[] getLoadedChunks() { 175 Object[] chunks = world.chunkProviderServer.chunks.values().toArray(); 176 org.bukkit.Chunk[] craftChunks = new CraftChunk[chunks.length]; 177 178 for (int i = 0; i < chunks.length; i++) { 179 net.minecraft.server.Chunk chunk = (net.minecraft.server.Chunk) chunks[i]; 180 craftChunks[i] = chunk.bukkitChunk; 181 } 182 183 return craftChunks; 184 } 185 186 public void loadChunk(int x, int z) { 187 loadChunk(x, z, true); 188 } 189 190 public boolean unloadChunk(Chunk chunk) { 191 return unloadChunk(chunk.getX(), chunk.getZ()); 192 } 193 194 public boolean unloadChunk(int x, int z) { 195 return unloadChunk(x, z, true); 196 } 197 198 public boolean unloadChunk(int x, int z, boolean save) { 199 return unloadChunk(x, z, save, false); 200 } 201 202 public boolean unloadChunkRequest(int x, int z) { 203 return unloadChunkRequest(x, z, true); 204 } 205 206 public boolean unloadChunkRequest(int x, int z, boolean safe) { 207 if (safe && isChunkInUse(x, z)) { 208 return false; 209 } 210 211 world.chunkProviderServer.queueUnload(x, z); 212 213 return true; 214 } 215 216 public boolean unloadChunk(int x, int z, boolean save, boolean safe) { 217 if (safe && isChunkInUse(x, z)) { 218 return false; 219 } 220 221 net.minecraft.server.Chunk chunk = world.chunkProviderServer.getOrCreateChunk(x, z); 222 223 if (save && !chunk.isEmpty()) { 224 chunk.removeEntities(); 225 world.chunkProviderServer.saveChunk(chunk); 226 world.chunkProviderServer.saveChunkNOP(chunk); 227 } 228 229// preserveChunk((CraftChunk) chunk.bukkitChunk); 230 world.chunkProviderServer.unloadQueue.remove(x, z); 231 world.chunkProviderServer.chunks.remove(x, z); 232 world.chunkProviderServer.chunkList.remove(chunk); 233 234 return true; 235 } 236 237 public boolean regenerateChunk(int x, int z) { 238 unloadChunk(x, z, false, false); 239 240 world.chunkProviderServer.unloadQueue.remove(x, z); 241 242 net.minecraft.server.Chunk chunk = null; 243 244 if (world.chunkProviderServer.chunkProvider == null) { 245 chunk = world.chunkProviderServer.emptyChunk; 246 } else { 247 chunk = world.chunkProviderServer.chunkProvider.getOrCreateChunk(x, z); 248 } 249 250 chunkLoadPostProcess(chunk, x, z); 251 252 refreshChunk(x, z); 253 254 return chunk != null; 255 } 256 257 public boolean refreshChunk(int x, int z) { 258 if (!isChunkLoaded(x, z)) { 259 return false; 260 } 261 262 int px = x << 4; 263 int pz = z << 4; 264 265 // If there are more than 10 updates to a chunk at once, it carries out the update as a cuboid 266 // This flags 16 blocks in a line along the bottom for update and then flags a block at the opposite corner at the top 267 // The cuboid that contains these 17 blocks covers the entire chunk 268 // The server will compress the chunk and send it to all clients 269 270 for (int xx = px; xx < (px + 16); xx++) { 271 world.notify(xx, 0, pz); 272 } 273 world.notify(px, 127, pz + 15); 274 275 return true; 276 } 277 278 279 public boolean isChunkInUse(int x, int z) { 280 Player[] players = server.getOnlinePlayers(); 281 282 for (Player player : players) { 283 Location loc = player.getLocation(); 284 if (loc.getWorld() != world.chunkProviderServer.world.getWorld()) { 285 continue; 286 } 287 288 // If the chunk is within 256 blocks of a player, refuse to accept the unload request 289 // This is larger than the distance of loaded chunks that actually surround a player 290 // The player is the center of a 21x21 chunk grid, so the edge is 10 chunks (160 blocks) away from the player 291 if (Math.abs(loc.getBlockX() - (x << 4)) <= 256 && Math.abs(loc.getBlockZ() - (z << 4)) <= 256) { 292 return true; 293 } 294 } 295 return false; 296 } 297 298 public boolean loadChunk(int x, int z, boolean generate) { 299 if (generate) { 300 // Use the default variant of loadChunk when generate == true. 301 return world.chunkProviderServer.getChunkAt(x, z) != null; 302 } 303 304 world.chunkProviderServer.unloadQueue.remove(x, z); 305 net.minecraft.server.Chunk chunk = (net.minecraft.server.Chunk) world.chunkProviderServer.chunks.get(x, z); 306 307 if (chunk == null) { 308 chunk = world.chunkProviderServer.loadChunk(x, z); 309 310 chunkLoadPostProcess(chunk, x, z); 311 } 312 return chunk != null; 313 } 314 315 @SuppressWarnings("unchecked") 316 private void chunkLoadPostProcess(net.minecraft.server.Chunk chunk, int x, int z) { 317 if (chunk != null) { 318 world.chunkProviderServer.chunks.put(x, z, chunk); 319 world.chunkProviderServer.chunkList.add(chunk); 320 321 chunk.loadNOP(); 322 chunk.addEntities(); 323 324 if (!chunk.done && world.chunkProviderServer.isChunkLoaded(x + 1, z + 1) && world.chunkProviderServer.isChunkLoaded(x, z + 1) && world.chunkProviderServer.isChunkLoaded(x + 1, z)) { 325 world.chunkProviderServer.getChunkAt(world.chunkProviderServer, x, z); 326 } 327 328 if (world.chunkProviderServer.isChunkLoaded(x - 1, z) && !world.chunkProviderServer.getOrCreateChunk(x - 1, z).done && world.chunkProviderServer.isChunkLoaded(x - 1, z + 1) && world.chunkProviderServer.isChunkLoaded(x, z + 1) && world.chunkProviderServer.isChunkLoaded(x - 1, z)) { 329 world.chunkProviderServer.getChunkAt(world.chunkProviderServer, x - 1, z); 330 } 331 332 if (world.chunkProviderServer.isChunkLoaded(x, z - 1) && !world.chunkProviderServer.getOrCreateChunk(x, z - 1).done && world.chunkProviderServer.isChunkLoaded(x + 1, z - 1) && world.chunkProviderServer.isChunkLoaded(x, z - 1) && world.chunkProviderServer.isChunkLoaded(x + 1, z)) { 333 world.chunkProviderServer.getChunkAt(world.chunkProviderServer, x, z - 1); 334 } 335 336 if (world.chunkProviderServer.isChunkLoaded(x - 1, z - 1) && !world.chunkProviderServer.getOrCreateChunk(x - 1, z - 1).done && world.chunkProviderServer.isChunkLoaded(x - 1, z - 1) && world.chunkProviderServer.isChunkLoaded(x, z - 1) && world.chunkProviderServer.isChunkLoaded(x - 1, z)) { 337 world.chunkProviderServer.getChunkAt(world.chunkProviderServer, x - 1, z - 1); 338 } 339 } 340 } 341 342 public boolean isChunkLoaded(Chunk chunk) { 343 return isChunkLoaded(chunk.getX(), chunk.getZ()); 344 } 345 346 public void loadChunk(Chunk chunk) { 347 loadChunk(chunk.getX(), chunk.getZ()); 348 ((CraftChunk) getChunkAt(chunk.getX(), chunk.getZ())).getHandle().bukkitChunk = chunk; 349 } 350 351 public WorldServer getHandle() { 352 return world; 353 } 354 355 public org.bukkit.entity.Item dropItem(Location loc, ItemStack item) { 356 // uberbukkit 357 if (!Uberbukkit.getProtocolHandler().canReceiveBlockItem(item.getTypeId())) { 358 return null; 359 } 360 361 net.minecraft.server.ItemStack stack = new net.minecraft.server.ItemStack(item.getTypeId(), item.getAmount(), item.getDurability()); 362 EntityItem entity = new EntityItem(world, loc.getX(), loc.getY(), loc.getZ(), stack); 363 entity.pickupDelay = 10; 364 world.addEntity(entity); 365 // TODO this is inconsistent with how Entity.getBukkitEntity() works. 366 // However, this entity is not at the moment backed by a server entity class so it may be left. 367 return new CraftItem(world.getServer(), entity); 368 } 369 370 public org.bukkit.entity.Item dropItemNaturally(Location loc, ItemStack item) { 371 double xs = world.random.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D; 372 double ys = world.random.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D; 373 double zs = world.random.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D; 374 loc = loc.clone(); 375 loc.setX(loc.getX() + xs); 376 loc.setY(loc.getY() + ys); 377 loc.setZ(loc.getZ() + zs); 378 return dropItem(loc, item); 379 } 380 381 public Arrow spawnArrow(Location loc, Vector velocity, float speed, float spread) { 382 EntityArrow arrow = new EntityArrow(world); 383 arrow.setPositionRotation(loc.getX(), loc.getY(), loc.getZ(), 0, 0); 384 world.addEntity(arrow); 385 arrow.a(velocity.getX(), velocity.getY(), velocity.getZ(), speed, spread); 386 return (Arrow) arrow.getBukkitEntity(); 387 } 388 389 public LivingEntity spawnCreature(Location loc, CreatureType creatureType) { 390 LivingEntity creature; 391 try { 392 EntityLiving entityCreature = (EntityLiving) EntityTypes.a(creatureType.getName(), world); 393 entityCreature.setPosition(loc.getX(), loc.getY(), loc.getZ()); 394 creature = (LivingEntity) CraftEntity.getEntity(server, entityCreature); 395 396 // uberbukkit 397 if (!Uberbukkit.getProtocolHandler().canSeeMob(creature.getClass())) { 398 entityCreature.die(); 399 return null; 400 } 401 402 world.addEntity(entityCreature, SpawnReason.CUSTOM); 403 } catch (Exception e) { 404 // if we fail, for any reason, return null. 405 creature = null; 406 } 407 return creature; 408 } 409 410 public LightningStrike strikeLightning(Location loc) { 411 EntityWeatherStorm lightning = new EntityWeatherStorm(world, loc.getX(), loc.getY(), loc.getZ()); 412 world.strikeLightning(lightning); 413 return new CraftLightningStrike(server, lightning); 414 } 415 416 public LightningStrike strikeLightningEffect(Location loc) { 417 EntityWeatherStorm lightning = new EntityWeatherStorm(world, loc.getX(), loc.getY(), loc.getZ(), true); 418 world.strikeLightning(lightning); 419 return new CraftLightningStrike(server, lightning); 420 } 421 422 public boolean generateTree(Location loc, TreeType type) { 423 return generateTree(loc, type, world); 424 } 425 426 public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) { 427 switch (type) { 428 case BIG_TREE: 429 return new WorldGenBigTree().generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); 430 case BIRCH: 431 return new WorldGenForest().generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); 432 case REDWOOD: 433 return new WorldGenTaiga2().generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); 434 case TALL_REDWOOD: 435 return new WorldGenTaiga1().generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); 436 case TREE: 437 default: 438 return new WorldGenTrees().generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); 439 } 440 } 441 442 public TileEntity getTileEntityAt(final int x, final int y, final int z) { 443 return world.getTileEntity(x, y, z); 444 } 445 446 public String getName() { 447 return world.worldData.name; 448 } 449 450 @Deprecated 451 public long getId() { 452 return world.worldData.getSeed(); 453 } 454 455 public UUID getUID() { 456 return world.getUUID(); 457 } 458 459 @Override 460 public String toString() { 461 return "CraftWorld{name=" + getName() + '}'; 462 } 463 464 public long getTime() { 465 long time = getFullTime() % 24000; 466 if (time < 0) time += 24000; 467 return time; 468 } 469 470 public void setTime(long time) { 471 long margin = (time - getFullTime()) % 24000; 472 if (margin < 0) margin += 24000; 473 setFullTime(getFullTime() + margin); 474 } 475 476 public long getFullTime() { 477 return world.getTime(); 478 } 479 480 public void setFullTime(long time) { 481 world.setTime(time); 482 483 // Forces the client to update to the new time immediately 484 for (Player p : getPlayers()) { 485 CraftPlayer cp = (CraftPlayer) p; 486 cp.getHandle().netServerHandler.sendPacket(new Packet4UpdateTime(cp.getHandle().getPlayerTime())); 487 } 488 } 489 490 public boolean createExplosion(double x, double y, double z, float power) { 491 return createExplosion(x, y, z, power, false); 492 } 493 494 public boolean createExplosion(double x, double y, double z, float power, boolean setFire) { 495 return createExplosion(x, y, z, power, setFire, EntityDamageEvent.DamageCause.PLUGIN_EXPLOSION); 496 } 497 498 public boolean createExplosion(double x, double y, double z, float power, boolean setFire, EntityDamageEvent.DamageCause customDamageCause) { 499 return world.createExplosion(null, x, y, z, power, setFire, customDamageCause).wasCanceled ? false : true; 500 } 501 502 public boolean createExplosion(Location loc, float power) { 503 return createExplosion(loc, power, false); 504 } 505 506 public boolean createExplosion(Location loc, float power, boolean setFire) { 507 return createExplosion(loc.getX(), loc.getY(), loc.getZ(), power, setFire); 508 } 509 510 public boolean createExplosion(Location loc, float power, boolean setFire, EntityDamageEvent.DamageCause customDamageCause) { 511 return createExplosion(loc.getX(), loc.getY(), loc.getZ(), power, setFire, customDamageCause); 512 } 513 514 public Environment getEnvironment() { 515 return environment; 516 } 517 518 public void setEnvironment(Environment env) { 519 if (environment != env) { 520 environment = env; 521 world.worldProvider = WorldProvider.byDimension(environment.getId()); 522 } 523 } 524 525 public Block getBlockAt(Location location) { 526 return getBlockAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); 527 } 528 529 public int getBlockTypeIdAt(Location location) { 530 return getBlockTypeIdAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); 531 } 532 533 public int getHighestBlockYAt(Location location) { 534 return getHighestBlockYAt(location.getBlockX(), location.getBlockZ()); 535 } 536 537 public Chunk getChunkAt(Location location) { 538 return getChunkAt(location.getBlockX() >> 4, location.getBlockZ() >> 4); 539 } 540 541 public ChunkGenerator getGenerator() { 542 return generator; 543 } 544 545 public List<BlockPopulator> getPopulators() { 546 return populators; 547 } 548 549 public Block getHighestBlockAt(int x, int z) { 550 return getBlockAt(x, getHighestBlockYAt(x, z), z); 551 } 552 553 public Block getHighestBlockAt(Location location) { 554 return getHighestBlockAt(location.getBlockX(), location.getBlockZ()); 555 } 556 557 public Biome getBiome(int x, int z) { 558 BiomeBase base = getHandle().getWorldChunkManager().getBiome(x, z); 559 560 if (base == BiomeBase.RAINFOREST) { 561 return Biome.RAINFOREST; 562 } else if (base == BiomeBase.SWAMPLAND) { 563 return Biome.SWAMPLAND; 564 } else if (base == BiomeBase.SEASONAL_FOREST) { 565 return Biome.SEASONAL_FOREST; 566 } else if (base == BiomeBase.FOREST) { 567 return Biome.FOREST; 568 } else if (base == BiomeBase.SAVANNA) { 569 return Biome.SAVANNA; 570 } else if (base == BiomeBase.SHRUBLAND) { 571 return Biome.SHRUBLAND; 572 } else if (base == BiomeBase.TAIGA) { 573 return Biome.TAIGA; 574 } else if (base == BiomeBase.DESERT) { 575 return Biome.DESERT; 576 } else if (base == BiomeBase.PLAINS) { 577 return Biome.PLAINS; 578 } else if (base == BiomeBase.ICE_DESERT) { 579 return Biome.ICE_DESERT; 580 } else if (base == BiomeBase.TUNDRA) { 581 return Biome.TUNDRA; 582 } else if (base == BiomeBase.HELL) { 583 return Biome.HELL; 584 } else if (base == BiomeBase.SKY) { 585 return Biome.SKY; 586 } 587 588 return null; 589 } 590 591 public double getTemperature(int x, int z) { 592 return getHandle().getWorldChunkManager().a((double[]) null, x, z, 1, 1)[0]; 593 } 594 595 public double getHumidity(int x, int z) { 596 return getHandle().getWorldChunkManager().getHumidity(x, z); 597 } 598 599 public List<Entity> getEntities() { 600 List<Entity> list = new ArrayList<Entity>(); 601 602 for (Object o : world.entityList) { 603 if (o instanceof net.minecraft.server.Entity) { 604 net.minecraft.server.Entity mcEnt = (net.minecraft.server.Entity) o; 605 Entity bukkitEntity = mcEnt.getBukkitEntity(); 606 607 // Assuming that bukkitEntity isn't null 608 if (bukkitEntity != null) { 609 list.add(bukkitEntity); 610 } 611 } 612 } 613 614 return list; 615 } 616 617 public List<LivingEntity> getLivingEntities() { 618 List<LivingEntity> list = new ArrayList<LivingEntity>(); 619 620 for (Object o : world.entityList) { 621 if (o instanceof net.minecraft.server.Entity) { 622 net.minecraft.server.Entity mcEnt = (net.minecraft.server.Entity) o; 623 Entity bukkitEntity = mcEnt.getBukkitEntity(); 624 625 // Assuming that bukkitEntity isn't null 626 if (bukkitEntity != null && bukkitEntity instanceof LivingEntity) { 627 list.add((LivingEntity) bukkitEntity); 628 } 629 } 630 } 631 632 return list; 633 } 634 635 public List<Player> getPlayers() { 636 List<Player> list = new ArrayList<Player>(); 637 638 for (Object o : world.entityList) { 639 if (o instanceof net.minecraft.server.Entity) { 640 net.minecraft.server.Entity mcEnt = (net.minecraft.server.Entity) o; 641 Entity bukkitEntity = mcEnt.getBukkitEntity(); 642 643 if ((bukkitEntity != null) && (bukkitEntity instanceof Player)) { 644 list.add((Player) bukkitEntity); 645 } 646 } 647 } 648 649 return list; 650 } 651 652 public void save() { 653 boolean oldSave = world.canSave; 654 655 world.canSave = false; 656 world.save(true, null); 657 658 world.canSave = oldSave; 659 } 660 661 public boolean isAutoSave() { 662 return !world.canSave; 663 } 664 665 public void setAutoSave(boolean value) { 666 world.canSave = !value; 667 } 668 669 public boolean hasStorm() { 670 return world.worldData.hasStorm(); 671 } 672 673 public void setStorm(boolean hasStorm) { 674 CraftServer server = world.getServer(); 675 676 WeatherChangeEvent weather = new WeatherChangeEvent((org.bukkit.World) this, hasStorm); 677 server.getPluginManager().callEvent(weather); 678 if (!weather.isCancelled()) { 679 world.worldData.setStorm(hasStorm); 680 681 // These numbers are from Minecraft 682 if (hasStorm) { 683 setWeatherDuration(rand.nextInt(12000) + 12000); 684 } else { 685 setWeatherDuration(rand.nextInt(168000) + 12000); 686 } 687 } 688 } 689 690 public int getWeatherDuration() { 691 return world.worldData.getWeatherDuration(); 692 } 693 694 public void setWeatherDuration(int duration) { 695 world.worldData.setWeatherDuration(duration); 696 } 697 698 public boolean isThundering() { 699 return world.worldData.isThundering(); 700 } 701 702 public void setThundering(boolean thundering) { 703 CraftServer server = world.getServer(); 704 705 ThunderChangeEvent thunder = new ThunderChangeEvent((org.bukkit.World) this, thundering); 706 server.getPluginManager().callEvent(thunder); 707 if (!thunder.isCancelled()) { 708 world.worldData.setThundering(thundering); 709 710 // These numbers are from Minecraft 711 if (thundering) { 712 setThunderDuration(rand.nextInt(12000) + 3600); 713 } else { 714 setThunderDuration(rand.nextInt(168000) + 12000); 715 } 716 } 717 } 718 719 public int getThunderDuration() { 720 return world.worldData.getThunderDuration(); 721 } 722 723 public void setThunderDuration(int duration) { 724 world.worldData.setThunderDuration(duration); 725 } 726 727 public long getSeed() { 728 return world.worldData.getSeed(); 729 } 730 731 public boolean getPVP() { 732 return world.pvpMode; 733 } 734 735 public void setPVP(boolean pvp) { 736 world.pvpMode = pvp; 737 } 738 739 public void playEffect(Player player, Effect effect, int data) { 740 playEffect(player.getLocation(), effect, data, 0); 741 } 742 743 public void playEffect(Location location, Effect effect, int data) { 744 playEffect(location, effect, data, 64); 745 } 746 747 public void playEffect(Location location, Effect effect, int data, int radius) { 748 749 int packetData = effect.getId(); 750 Packet61 packet = new Packet61(packetData, location.getBlockX(), location.getBlockY(), location.getBlockZ(), data); 751 int distance; 752 for (Player player : getPlayers()) { 753 distance = (int) player.getLocation().distance(location); 754 if (distance <= radius) { 755 ((CraftPlayer) player).getHandle().netServerHandler.sendPacket(packet); 756 } 757 } 758 } 759 760 @SuppressWarnings("unchecked") 761 public <T extends Entity> T spawn(Location location, Class<T> clazz) throws IllegalArgumentException { 762 if (location == null || clazz == null) { 763 throw new IllegalArgumentException("Location or entity class cannot be null"); 764 } 765 766 // uberbukkit 767 if (!Uberbukkit.getProtocolHandler().canSeeMob(clazz)) { 768 return null; 769 } 770 771 net.minecraft.server.Entity entity = null; 772 773 double x = location.getX(); 774 double y = location.getY(); 775 double z = location.getZ(); 776 float pitch = location.getPitch(); 777 float yaw = location.getYaw(); 778 779 // order is important for some of these 780 if (Boat.class.isAssignableFrom(clazz)) { 781 entity = new EntityBoat(world, x, y, z); 782 } else if (Egg.class.isAssignableFrom(clazz)) { 783 entity = new EntityEgg(world, x, y, z); 784 } else if (FallingSand.class.isAssignableFrom(clazz)) { 785 entity = new EntityFallingSand(world, x, y, z, 0); 786 } else if (Fireball.class.isAssignableFrom(clazz)) { 787 entity = new EntityFireball(world); 788 ((EntityFireball) entity).setPositionRotation(x, y, z, yaw, pitch); 789 Vector direction = location.getDirection().multiply(10); 790 ((EntityFireball) entity).setDirection(direction.getX(), direction.getY(), direction.getZ()); 791 } else if (Snowball.class.isAssignableFrom(clazz)) { 792 entity = new EntitySnowball(world, x, y, z); 793 } else if (Minecart.class.isAssignableFrom(clazz)) { 794 795 if (PoweredMinecart.class.isAssignableFrom(clazz)) { 796 entity = new EntityMinecart(world, x, y, z, CraftMinecart.Type.PoweredMinecart.getId()); 797 } else if (StorageMinecart.class.isAssignableFrom(clazz)) { 798 entity = new EntityMinecart(world, x, y, z, CraftMinecart.Type.StorageMinecart.getId()); 799 } else { 800 entity = new EntityMinecart(world, x, y, z, CraftMinecart.Type.Minecart.getId()); 801 } 802 803 } else if (Arrow.class.isAssignableFrom(clazz)) { 804 entity = new EntityArrow(world); 805 entity.setPositionRotation(x, y, z, 0, 0); 806 } else if (LivingEntity.class.isAssignableFrom(clazz)) { 807 808 if (Chicken.class.isAssignableFrom(clazz)) { 809 entity = new EntityChicken(world); 810 } else if (Cow.class.isAssignableFrom(clazz)) { 811 entity = new EntityCow(world); 812 } else if (Creeper.class.isAssignableFrom(clazz)) { 813 entity = new EntityCreeper(world); 814 } else if (Ghast.class.isAssignableFrom(clazz)) { 815 entity = new EntityGhast(world); 816 } else if (Pig.class.isAssignableFrom(clazz)) { 817 entity = new EntityPig(world); 818 } else if (Player.class.isAssignableFrom(clazz)) { 819 // need a net server handler for this one 820 } else if (Sheep.class.isAssignableFrom(clazz)) { 821 entity = new EntitySheep(world); 822 } else if (Skeleton.class.isAssignableFrom(clazz)) { 823 entity = new EntitySkeleton(world); 824 } else if (Slime.class.isAssignableFrom(clazz)) { 825 entity = new EntitySlime(world); 826 } else if (Spider.class.isAssignableFrom(clazz)) { 827 entity = new EntitySpider(world); 828 } else if (Squid.class.isAssignableFrom(clazz)) { 829 entity = new EntitySquid(world); 830 } else if (Wolf.class.isAssignableFrom(clazz)) { 831 entity = new EntityWolf(world); 832 } else if (PigZombie.class.isAssignableFrom(clazz)) { 833 entity = new EntityPigZombie(world); 834 } else if (Zombie.class.isAssignableFrom(clazz)) { 835 entity = new EntityZombie(world); 836 } 837 838 if (entity != null) { 839 entity.setLocation(x, y, z, pitch, yaw); 840 } 841 842 } else if (Painting.class.isAssignableFrom(clazz)) { 843 // negative 844 } else if (TNTPrimed.class.isAssignableFrom(clazz)) { 845 entity = new EntityTNTPrimed(world, x, y, z); 846 } else if (Weather.class.isAssignableFrom(clazz)) { 847 // not sure what this can do 848 entity = new EntityWeatherStorm(world, x, y, z); 849 } else if (LightningStrike.class.isAssignableFrom(clazz)) { 850 // what is this, I don't even 851 } else if (Fish.class.isAssignableFrom(clazz)) { 852 // this is not a fish, it's a bobber, and it's probably useless 853 entity = new EntityFish(world); 854 entity.setLocation(x, y, z, pitch, yaw); 855 } 856 857 if (entity != null) { 858 world.addEntity(entity); 859 return (T) entity.getBukkitEntity(); 860 } 861 862 throw new IllegalArgumentException("Cannot spawn an entity for " + clazz.getName()); 863 } 864 865 public ChunkSnapshot getEmptyChunkSnapshot(int x, int z, boolean includeBiome, boolean includeBiomeTempRain) { 866 return CraftChunk.getEmptyChunkSnapshot(x, z, this, includeBiome, includeBiomeTempRain); 867 } 868 869 public void setSpawnFlags(boolean allowMonsters, boolean allowAnimals) { 870 world.setSpawnFlags(allowMonsters, allowAnimals); 871 } 872 873 public boolean getAllowAnimals() { 874 return world.allowAnimals; 875 } 876 877 public boolean getAllowMonsters() { 878 return world.allowMonsters; 879 } 880 881 public int getMaxHeight() { 882 return 128; 883 } 884 885 public boolean getKeepSpawnInMemory() { 886 return world.keepSpawnInMemory; 887 } 888 889 public void setKeepSpawnInMemory(boolean keepLoaded) { 890 world.keepSpawnInMemory = keepLoaded; 891 // Grab the worlds spawn chunk 892 ChunkCoordinates chunkcoordinates = this.world.getSpawn(); 893 int chunkCoordX = chunkcoordinates.x >> 4; 894 int chunkCoordZ = chunkcoordinates.z >> 4; 895 // Cycle through the 25x25 Chunks around it to load/unload the chunks. 896 for (int x = -12; x <= 12; x++) { 897 for (int z = -12; z <= 12; z++) { 898 if (keepLoaded) { 899 loadChunk(chunkCoordX + x, chunkCoordZ + z); 900 } else { 901 if (isChunkLoaded(chunkCoordX + x, chunkCoordZ + z)) { 902 if (this.getHandle().getChunkAt(chunkCoordX + x, chunkCoordZ + z).isEmpty()) { 903 unloadChunk(chunkCoordX + x, chunkCoordZ + z, false); 904 } else { 905 unloadChunk(chunkCoordX + x, chunkCoordZ + z); 906 } 907 } 908 } 909 } 910 } 911 } 912}