2010-12-27 03:13:03 +01:00
|
|
|
package org.bukkit.craftbukkit;
|
|
|
|
|
2011-01-15 22:40:18 +01:00
|
|
|
import org.bukkit.craftbukkit.block.CraftBlock;
|
2011-01-15 22:52:43 +01:00
|
|
|
import org.bukkit.craftbukkit.entity.*;
|
|
|
|
import org.bukkit.entity.*;
|
2011-01-26 21:03:54 +01:00
|
|
|
import org.bukkit.entity.Entity;
|
2011-01-17 09:26:47 +01:00
|
|
|
|
2011-01-26 21:03:54 +01:00
|
|
|
import java.util.ArrayList;
|
2010-12-27 03:13:03 +01:00
|
|
|
import java.util.HashMap;
|
2011-01-26 21:03:54 +01:00
|
|
|
import java.util.List;
|
2010-12-27 03:13:03 +01:00
|
|
|
import java.util.Map;
|
2011-01-03 03:01:17 +01:00
|
|
|
import java.util.Random;
|
2011-01-15 22:52:43 +01:00
|
|
|
import net.minecraft.server.*;
|
2011-01-15 22:21:05 +01:00
|
|
|
import org.bukkit.entity.Arrow;
|
2011-01-15 22:36:57 +01:00
|
|
|
import org.bukkit.block.Block;
|
2011-01-15 22:21:05 +01:00
|
|
|
import org.bukkit.entity.Boat;
|
2010-12-27 03:13:03 +01:00
|
|
|
import org.bukkit.Chunk;
|
2011-01-15 22:21:05 +01:00
|
|
|
import org.bukkit.entity.ItemDrop;
|
2011-01-15 22:27:29 +01:00
|
|
|
import org.bukkit.inventory.ItemStack;
|
2011-01-15 22:44:22 +01:00
|
|
|
import org.bukkit.util.Vector;
|
2011-01-02 09:40:27 +01:00
|
|
|
import org.bukkit.Location;
|
2010-12-27 03:13:03 +01:00
|
|
|
import org.bukkit.World;
|
|
|
|
|
|
|
|
public class CraftWorld implements World {
|
2011-01-04 16:54:41 +01:00
|
|
|
private final Map<ChunkCoordinate, CraftChunk> chunkCache = new HashMap<ChunkCoordinate, CraftChunk>();
|
|
|
|
private final Map<BlockCoordinate, CraftBlock> blockCache = new HashMap<BlockCoordinate, CraftBlock>();
|
2010-12-27 03:13:03 +01:00
|
|
|
private final WorldServer world;
|
2011-01-03 03:01:17 +01:00
|
|
|
|
|
|
|
private static final Random rand = new Random();
|
2010-12-27 03:13:03 +01:00
|
|
|
|
2010-12-30 05:37:32 +01:00
|
|
|
public CraftWorld(WorldServer world) {
|
2010-12-27 03:13:03 +01:00
|
|
|
this.world = world;
|
|
|
|
}
|
2011-01-01 14:06:04 +01:00
|
|
|
|
2010-12-27 03:13:03 +01:00
|
|
|
public Block getBlockAt(int x, int y, int z) {
|
|
|
|
BlockCoordinate loc = new BlockCoordinate(x, y, z);
|
2011-01-04 16:54:41 +01:00
|
|
|
CraftBlock block = blockCache.get(loc);
|
2010-12-27 03:13:03 +01:00
|
|
|
|
|
|
|
if (block == null) {
|
2011-01-29 22:50:29 +01:00
|
|
|
block = new CraftBlock(this, x, y, z, world.getTypeId(x, y, z), (byte)world.getData(x, y, z));
|
2010-12-27 03:13:03 +01:00
|
|
|
blockCache.put(loc, block);
|
2011-01-16 06:10:24 +01:00
|
|
|
} else {
|
|
|
|
block.update();
|
2010-12-27 03:13:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return block;
|
|
|
|
}
|
2011-01-15 21:01:49 +01:00
|
|
|
|
|
|
|
public int getBlockTypeIdAt(int x, int y, int z) {
|
2011-01-29 22:50:29 +01:00
|
|
|
return world.getTypeId(x, y, z);
|
2011-01-15 21:01:49 +01:00
|
|
|
}
|
|
|
|
|
2011-01-03 22:56:09 +01:00
|
|
|
public int getHighestBlockYAt(int x, int z) {
|
2011-01-10 09:30:34 +01:00
|
|
|
return world.d(x, z);
|
2011-01-03 22:56:09 +01:00
|
|
|
}
|
2011-01-16 00:00:01 +01:00
|
|
|
|
|
|
|
public Location getSpawnLocation() {
|
2011-01-29 22:50:29 +01:00
|
|
|
return new Location(this, world.spawnX, world.e(world.spawnX, world.spawnZ), world.spawnZ);
|
2011-01-16 00:00:01 +01:00
|
|
|
}
|
2010-12-27 03:13:03 +01:00
|
|
|
|
|
|
|
public Chunk getChunkAt(int x, int z) {
|
|
|
|
ChunkCoordinate loc = new ChunkCoordinate(x, z);
|
2011-01-04 16:54:41 +01:00
|
|
|
CraftChunk chunk = chunkCache.get(loc);
|
2010-12-27 03:13:03 +01:00
|
|
|
|
|
|
|
if (chunk == null) {
|
2011-01-04 15:17:05 +01:00
|
|
|
chunk = new CraftChunk(this, x, z);
|
2010-12-27 03:13:03 +01:00
|
|
|
chunkCache.put(loc, chunk);
|
|
|
|
}
|
|
|
|
|
|
|
|
return chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Chunk getChunkAt(Block block) {
|
2011-01-18 12:37:01 +01:00
|
|
|
return getChunkAt(block.getX() >> 4, block.getZ() >> 4);
|
2010-12-27 03:13:03 +01:00
|
|
|
}
|
|
|
|
|
2011-01-03 04:25:24 +01:00
|
|
|
public boolean isChunkLoaded(Chunk chunk) {
|
|
|
|
return world.A.a(chunk.getX(), chunk.getZ());
|
2010-12-27 03:13:03 +01:00
|
|
|
}
|
|
|
|
|
2011-01-20 21:57:33 +01:00
|
|
|
public void loadChunk(Chunk chunk) {
|
|
|
|
world.A.d(chunk.getX(), chunk.getZ());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-29 00:52:29 +01:00
|
|
|
public Block updateBlock(int x, int y, int z) {
|
|
|
|
BlockCoordinate loc = new BlockCoordinate(x, y, z);
|
|
|
|
CraftBlock block = (CraftBlock)blockCache.get(loc);
|
2011-01-29 22:50:29 +01:00
|
|
|
final int type = world.getTypeId(x, y, z);
|
|
|
|
final byte data = (byte)world.getData(x, y, z);
|
2010-12-29 00:52:29 +01:00
|
|
|
|
|
|
|
if (block == null) {
|
|
|
|
block = new CraftBlock(this, x, y, z, type, data);
|
|
|
|
blockCache.put(loc, block);
|
|
|
|
} else {
|
2011-01-15 22:52:43 +01:00
|
|
|
block.update();
|
2010-12-29 00:52:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return block;
|
|
|
|
}
|
|
|
|
|
2011-01-04 16:54:41 +01:00
|
|
|
public CraftChunk updateChunk(int x, int z) {
|
|
|
|
ChunkCoordinate loc = new ChunkCoordinate(x, z);
|
|
|
|
CraftChunk chunk = chunkCache.get(loc);
|
|
|
|
|
|
|
|
if (chunk == null) {
|
|
|
|
chunk = new CraftChunk(this, x, z);
|
|
|
|
chunkCache.put(loc, chunk);
|
|
|
|
} else {
|
|
|
|
// TODO: Chunk stuff
|
|
|
|
}
|
|
|
|
|
|
|
|
return chunk;
|
|
|
|
}
|
|
|
|
|
2010-12-29 02:07:57 +01:00
|
|
|
public WorldServer getHandle() {
|
|
|
|
return world;
|
|
|
|
}
|
2011-01-08 21:48:45 +01:00
|
|
|
|
|
|
|
public ItemDrop dropItem(Location loc, ItemStack item) {
|
2011-01-15 20:53:20 +01:00
|
|
|
net.minecraft.server.ItemStack stack = new net.minecraft.server.ItemStack(
|
|
|
|
item.getTypeId(),
|
|
|
|
item.getAmount(),
|
|
|
|
item.getDamage()
|
|
|
|
);
|
|
|
|
EntityItem entity = new EntityItem(world, loc.getX(), loc.getY(), loc.getZ(), stack);
|
2011-01-08 21:48:45 +01:00
|
|
|
entity.c = 10;
|
|
|
|
world.a(entity);
|
2011-01-17 09:26:47 +01:00
|
|
|
//TODO this is inconsistent with how Entity.getBukkitEntity() works.
|
|
|
|
// However, this entity is not at the moment backed by a server entity class so it may be left.
|
2011-01-08 21:48:45 +01:00
|
|
|
return new CraftItemDrop(world.getServer(), entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
public ItemDrop dropItemNaturally(Location loc, ItemStack item) {
|
|
|
|
double xs = world.l.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D;
|
|
|
|
double ys = world.l.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D;
|
|
|
|
double zs = world.l.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D;
|
|
|
|
loc = loc.clone();
|
|
|
|
loc.setX(loc.getX() + xs);
|
2011-01-15 22:45:48 +01:00
|
|
|
loc.setY(loc.getY() + ys);
|
|
|
|
loc.setZ(loc.getZ() + zs);
|
2011-01-08 21:48:45 +01:00
|
|
|
return dropItem(loc, item);
|
|
|
|
}
|
2010-12-29 02:07:57 +01:00
|
|
|
|
2011-01-15 20:53:20 +01:00
|
|
|
public Arrow spawnArrow(Location loc, Vector velocity, float speed, float spread) {
|
2011-01-02 09:40:27 +01:00
|
|
|
EntityArrow arrow = new EntityArrow(world);
|
2011-01-10 23:13:44 +01:00
|
|
|
arrow.c(loc.getX(), loc.getY(), loc.getZ(), 0, 0);
|
2011-01-02 09:40:27 +01:00
|
|
|
world.a(arrow);
|
|
|
|
arrow.a(velocity.getX(), velocity.getY(), velocity.getZ(), speed, spread);
|
2011-01-17 09:26:47 +01:00
|
|
|
return (Arrow) arrow.getBukkitEntity();
|
2011-01-02 09:40:27 +01:00
|
|
|
}
|
2011-01-03 03:01:17 +01:00
|
|
|
|
2011-01-03 06:41:57 +01:00
|
|
|
public Minecart spawnMinecart(Location loc) {
|
|
|
|
EntityMinecart minecart = new EntityMinecart(
|
2011-01-15 20:53:20 +01:00
|
|
|
world,
|
|
|
|
loc.getX(),
|
|
|
|
loc.getY(),
|
|
|
|
loc.getZ(),
|
|
|
|
CraftMinecart.Type.Minecart.getId()
|
|
|
|
);
|
2011-01-03 06:41:57 +01:00
|
|
|
world.a(minecart);
|
2011-01-23 13:23:13 +01:00
|
|
|
return (Minecart) minecart.getBukkitEntity();
|
2011-01-03 06:41:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public StorageMinecart spawnStorageMinecart(Location loc) {
|
|
|
|
EntityMinecart minecart = new EntityMinecart(
|
2011-01-15 20:53:20 +01:00
|
|
|
world,
|
|
|
|
loc.getX(),
|
|
|
|
loc.getY(),
|
|
|
|
loc.getZ(),
|
|
|
|
CraftMinecart.Type.StorageMinecart.getId()
|
|
|
|
);
|
2011-01-03 06:41:57 +01:00
|
|
|
world.a(minecart);
|
2011-01-23 13:23:13 +01:00
|
|
|
return (StorageMinecart) minecart.getBukkitEntity();
|
2011-01-03 06:41:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public PoweredMinecart spawnPoweredMinecart(Location loc) {
|
|
|
|
EntityMinecart minecart = new EntityMinecart(
|
2011-01-15 20:53:20 +01:00
|
|
|
world,
|
|
|
|
loc.getX(),
|
|
|
|
loc.getY(),
|
|
|
|
loc.getZ(),
|
|
|
|
CraftMinecart.Type.PoweredMinecart.getId()
|
|
|
|
);
|
2011-01-03 06:41:57 +01:00
|
|
|
world.a(minecart);
|
2011-01-17 09:26:47 +01:00
|
|
|
return (PoweredMinecart) minecart.getBukkitEntity();
|
2011-01-03 06:41:57 +01:00
|
|
|
}
|
|
|
|
|
2011-01-07 23:01:37 +01:00
|
|
|
public Boat spawnBoat(Location loc) {
|
2011-01-15 20:53:20 +01:00
|
|
|
EntityBoat boat = new EntityBoat(world, loc.getX(), loc.getY(), loc.getZ());
|
2011-01-07 23:01:37 +01:00
|
|
|
world.a(boat);
|
2011-01-17 09:26:47 +01:00
|
|
|
return (Boat) boat.getBukkitEntity();
|
2011-01-07 23:01:37 +01:00
|
|
|
}
|
|
|
|
|
2011-01-03 03:01:17 +01:00
|
|
|
public boolean generateTree(Location loc) {
|
|
|
|
WorldGenTrees treeGen = new WorldGenTrees();
|
2011-01-15 20:53:20 +01:00
|
|
|
return treeGen.a(world, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
2011-01-03 03:01:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean generateBigTree(Location loc) {
|
|
|
|
WorldGenBigTree treeGen = new WorldGenBigTree();
|
2011-01-15 20:53:20 +01:00
|
|
|
return treeGen.a(world, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
2011-01-03 03:01:17 +01:00
|
|
|
}
|
2011-01-07 21:00:44 +01:00
|
|
|
|
2011-01-08 02:22:17 +01:00
|
|
|
public TileEntity getTileEntityAt(final int x, final int y, final int z) {
|
2011-01-29 22:50:29 +01:00
|
|
|
return world.getTileEntity(x, y, z);
|
2011-01-08 02:22:17 +01:00
|
|
|
}
|
|
|
|
|
2011-01-08 03:29:57 +01:00
|
|
|
public String getName() {
|
|
|
|
return world.w;
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getId() {
|
|
|
|
return world.u;
|
|
|
|
}
|
|
|
|
|
2010-12-30 21:34:26 +01:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "CraftWorld";
|
|
|
|
}
|
|
|
|
|
2010-12-27 03:13:03 +01:00
|
|
|
private final class ChunkCoordinate {
|
|
|
|
public final int x;
|
|
|
|
public final int z;
|
2011-01-01 14:06:04 +01:00
|
|
|
|
2010-12-27 03:13:03 +01:00
|
|
|
public ChunkCoordinate(final int x, final int z) {
|
|
|
|
this.x = x;
|
|
|
|
this.z = z;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object obj) {
|
|
|
|
if (obj == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (getClass() != obj.getClass()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
final ChunkCoordinate other = (ChunkCoordinate) obj;
|
|
|
|
if (this.x != other.x) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (this.z != other.z) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
|
|
|
int hash = 5;
|
|
|
|
hash = 53 * hash + this.x;
|
|
|
|
hash = 53 * hash + this.z;
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private final class BlockCoordinate {
|
|
|
|
public final int x;
|
|
|
|
public final int y;
|
|
|
|
public final int z;
|
2011-01-01 14:06:04 +01:00
|
|
|
|
2010-12-27 03:13:03 +01:00
|
|
|
public BlockCoordinate(final int x, final int y, final int z) {
|
|
|
|
this.x = x;
|
|
|
|
this.y = y;
|
|
|
|
this.z = z;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object obj) {
|
|
|
|
if (obj == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (getClass() != obj.getClass()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
final BlockCoordinate other = (BlockCoordinate) obj;
|
|
|
|
if (this.x != other.x) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (this.y != other.y) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (this.z != other.z) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
|
|
|
int hash = 7;
|
|
|
|
hash = 37 * hash + this.x;
|
|
|
|
hash = 37 * hash + this.y;
|
|
|
|
hash = 37 * hash + this.z;
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
}
|
2011-01-26 21:03:54 +01:00
|
|
|
|
|
|
|
public List<Entity> getEntities() {
|
|
|
|
List<Entity> list = new ArrayList<Entity>();
|
|
|
|
|
|
|
|
for (Object o : world.b) {
|
|
|
|
if (o instanceof net.minecraft.server.Entity) {
|
|
|
|
net.minecraft.server.Entity mcEnt
|
|
|
|
= (net.minecraft.server.Entity)o;
|
|
|
|
|
|
|
|
Entity bukkitEntity = mcEnt.getBukkitEntity();
|
|
|
|
|
|
|
|
// Assuming that bukkitEntity isn't null
|
|
|
|
if (bukkitEntity != null) {
|
|
|
|
list.add(bukkitEntity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<LivingEntity> getLivingEntities() {
|
|
|
|
List<LivingEntity> list = new ArrayList<LivingEntity>();
|
|
|
|
|
|
|
|
for (Object o : world.b) {
|
|
|
|
if (o instanceof net.minecraft.server.Entity) {
|
|
|
|
net.minecraft.server.Entity mcEnt
|
|
|
|
= (net.minecraft.server.Entity)o;
|
|
|
|
|
|
|
|
Entity bukkitEntity = mcEnt.getBukkitEntity();
|
|
|
|
|
|
|
|
// Assuming that bukkitEntity isn't null
|
|
|
|
if (bukkitEntity != null && bukkitEntity instanceof LivingEntity) {
|
|
|
|
list.add((LivingEntity)bukkitEntity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
2010-12-27 03:13:03 +01:00
|
|
|
}
|