2010-12-27 03:13:03 +01:00
|
|
|
package org.bukkit.craftbukkit;
|
|
|
|
|
2011-07-15 19:28:09 +02:00
|
|
|
import com.google.common.collect.MapMaker;
|
2011-11-25 04:47:12 +01:00
|
|
|
import java.io.File;
|
2012-01-13 09:52:26 +01:00
|
|
|
import java.util.Set;
|
2012-01-20 08:26:26 +01:00
|
|
|
import org.apache.commons.lang.Validate;
|
|
|
|
|
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;
|
2011-12-12 00:27:53 +01:00
|
|
|
import java.util.Collection;
|
2012-01-13 09:52:26 +01:00
|
|
|
import java.util.HashSet;
|
2011-07-15 19:28:09 +02:00
|
|
|
import java.util.concurrent.ConcurrentMap;
|
2011-01-26 21:03:54 +01:00
|
|
|
import java.util.List;
|
2011-01-03 03:01:17 +01:00
|
|
|
import java.util.Random;
|
2011-07-13 06:06:07 +02:00
|
|
|
import java.util.UUID;
|
|
|
|
|
2011-01-15 22:52:43 +01:00
|
|
|
import net.minecraft.server.*;
|
2011-02-17 06:25:03 +01:00
|
|
|
|
2011-01-15 22:21:05 +01:00
|
|
|
import org.bukkit.entity.Arrow;
|
2011-06-10 07:57:32 +02:00
|
|
|
import org.bukkit.Effect;
|
2011-06-21 22:20:11 +02:00
|
|
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
2011-04-26 01:47:25 +02:00
|
|
|
import org.bukkit.event.weather.WeatherChangeEvent;
|
|
|
|
import org.bukkit.event.weather.ThunderChangeEvent;
|
2011-03-29 11:04:42 +02:00
|
|
|
import org.bukkit.event.world.SpawnChangeEvent;
|
2011-01-15 22:36:57 +01:00
|
|
|
import org.bukkit.block.Block;
|
2011-10-01 19:31:28 +02:00
|
|
|
import org.bukkit.block.BlockFace;
|
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:27:29 +01:00
|
|
|
import org.bukkit.inventory.ItemStack;
|
2012-01-13 09:52:26 +01:00
|
|
|
import org.bukkit.plugin.Plugin;
|
2011-01-15 22:44:22 +01:00
|
|
|
import org.bukkit.util.Vector;
|
2011-01-30 22:53:57 +01:00
|
|
|
import org.bukkit.BlockChangeDelegate;
|
2011-06-17 04:06:45 +02:00
|
|
|
import org.bukkit.Bukkit;
|
2011-06-06 15:52:02 +02:00
|
|
|
import org.bukkit.generator.ChunkGenerator;
|
2011-06-17 15:23:19 +02:00
|
|
|
import org.bukkit.ChunkSnapshot;
|
2011-01-02 09:40:27 +01:00
|
|
|
import org.bukkit.Location;
|
2011-01-30 22:53:57 +01:00
|
|
|
import org.bukkit.TreeType;
|
2010-12-27 03:13:03 +01:00
|
|
|
import org.bukkit.World;
|
2011-07-13 07:52:40 +02:00
|
|
|
import org.bukkit.block.Biome;
|
2011-06-06 15:52:02 +02:00
|
|
|
import org.bukkit.generator.BlockPopulator;
|
2011-10-03 07:25:54 +02:00
|
|
|
import org.bukkit.Difficulty;
|
2011-11-22 22:21:33 +01:00
|
|
|
import org.bukkit.craftbukkit.block.CraftBlock;
|
2011-11-27 03:45:34 +01:00
|
|
|
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
2012-01-13 09:52:26 +01:00
|
|
|
import org.bukkit.plugin.messaging.StandardMessenger;
|
2010-12-27 03:13:03 +01:00
|
|
|
|
|
|
|
public class CraftWorld implements World {
|
|
|
|
private final WorldServer world;
|
2011-06-04 00:35:05 +02:00
|
|
|
private Environment environment;
|
2012-01-14 23:02:10 +01:00
|
|
|
private final CraftServer server = (CraftServer) Bukkit.getServer();
|
2011-07-16 03:55:54 +02:00
|
|
|
private ConcurrentMap<Integer, CraftChunk> unloadedChunks = new MapMaker().weakValues().makeMap();
|
2011-06-06 15:52:02 +02:00
|
|
|
private final ChunkGenerator generator;
|
|
|
|
private final List<BlockPopulator> populators = new ArrayList<BlockPopulator>();
|
2011-02-02 00:32:18 +01:00
|
|
|
|
2011-01-03 03:01:17 +01:00
|
|
|
private static final Random rand = new Random();
|
2010-12-27 03:13:03 +01:00
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
public CraftWorld(WorldServer world, ChunkGenerator gen, Environment env) {
|
2010-12-27 03:13:03 +01:00
|
|
|
this.world = world;
|
2011-06-06 15:52:02 +02:00
|
|
|
this.generator = gen;
|
2011-06-13 00:49:52 +02:00
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
environment = env;
|
2010-12-27 03:13:03 +01:00
|
|
|
}
|
2011-01-01 14:06:04 +01:00
|
|
|
|
2011-05-14 16:29:42 +02:00
|
|
|
public void preserveChunk(CraftChunk chunk) {
|
2011-03-11 20:39:09 +01:00
|
|
|
chunk.breakLink();
|
2011-05-14 16:29:42 +02:00
|
|
|
unloadedChunks.put((chunk.getX() << 16) + chunk.getZ(), chunk);
|
2011-02-20 17:09:02 +01:00
|
|
|
}
|
|
|
|
|
2011-05-14 16:29:42 +02:00
|
|
|
public Chunk popPreservedChunk(int x, int z) {
|
|
|
|
return unloadedChunks.remove((x << 16) + z);
|
2011-02-20 17:09:02 +01:00
|
|
|
}
|
|
|
|
|
2010-12-27 03:13:03 +01:00
|
|
|
public Block getBlockAt(int x, int y, int z) {
|
2011-02-01 23:49:28 +01:00
|
|
|
return getChunkAt(x >> 4, z >> 4).getBlock(x & 0xF, y & 0x7F, z & 0xF);
|
2010-12-27 03:13:03 +01:00
|
|
|
}
|
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) {
|
2012-01-14 23:02:10 +01:00
|
|
|
if (!isChunkLoaded(x >> 4, z >> 4)) {
|
2011-12-19 17:30:26 +01:00
|
|
|
loadChunk(x >> 4, z >> 4);
|
|
|
|
}
|
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
return world.getHighestBlockYAt(x, z);
|
2011-01-03 22:56:09 +01:00
|
|
|
}
|
2011-02-02 00:32:18 +01:00
|
|
|
|
2011-01-16 00:00:01 +01:00
|
|
|
public Location getSpawnLocation() {
|
2011-04-20 19:05:14 +02:00
|
|
|
ChunkCoordinates spawn = world.getSpawn();
|
|
|
|
return new Location(this, spawn.x, spawn.y, spawn.z);
|
2011-01-16 00:00:01 +01:00
|
|
|
}
|
2011-04-20 19:05:14 +02:00
|
|
|
|
2011-03-01 03:21:27 +01:00
|
|
|
public boolean setSpawnLocation(int x, int y, int z) {
|
|
|
|
try {
|
2011-03-29 11:04:42 +02:00
|
|
|
Location previousLocation = getSpawnLocation();
|
2011-04-20 19:05:14 +02:00
|
|
|
world.worldData.setSpawn(x, y, z);
|
2011-03-29 11:04:42 +02:00
|
|
|
|
|
|
|
// Notify anyone who's listening.
|
|
|
|
SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation);
|
|
|
|
server.getPluginManager().callEvent(event);
|
|
|
|
|
2011-03-01 03:21:27 +01:00
|
|
|
return true;
|
|
|
|
} catch (Exception e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2011-04-20 19:05:14 +02:00
|
|
|
|
2010-12-27 03:13:03 +01:00
|
|
|
public Chunk getChunkAt(int x, int z) {
|
2011-06-17 04:06:45 +02:00
|
|
|
return this.world.chunkProviderServer.getChunkAt(x, z).bukkitChunk;
|
2010-12-27 03:13:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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-02-01 23:49:28 +01:00
|
|
|
public boolean isChunkLoaded(int x, int z) {
|
2011-06-17 04:06:45 +02:00
|
|
|
return world.chunkProviderServer.isChunkLoaded(x, z);
|
2010-12-27 03:13:03 +01:00
|
|
|
}
|
|
|
|
|
2011-02-04 21:11:57 +01:00
|
|
|
public Chunk[] getLoadedChunks() {
|
2011-06-17 04:06:45 +02:00
|
|
|
Object[] chunks = world.chunkProviderServer.chunks.values().toArray();
|
2011-02-08 16:22:46 +01:00
|
|
|
org.bukkit.Chunk[] craftChunks = new CraftChunk[chunks.length];
|
|
|
|
|
|
|
|
for (int i = 0; i < chunks.length; i++) {
|
2011-06-12 01:12:43 +02:00
|
|
|
net.minecraft.server.Chunk chunk = (net.minecraft.server.Chunk) chunks[i];
|
2011-02-09 21:00:17 +01:00
|
|
|
craftChunks[i] = chunk.bukkitChunk;
|
2011-02-08 16:22:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return craftChunks;
|
2011-02-04 21:11:57 +01:00
|
|
|
}
|
|
|
|
|
2011-02-01 23:49:28 +01:00
|
|
|
public void loadChunk(int x, int z) {
|
2011-02-08 15:26:55 +01:00
|
|
|
loadChunk(x, z, true);
|
|
|
|
}
|
|
|
|
|
2011-07-28 06:32:58 +02:00
|
|
|
public boolean unloadChunk(Chunk chunk) {
|
|
|
|
return unloadChunk(chunk.getX(), chunk.getZ());
|
|
|
|
}
|
|
|
|
|
2011-02-08 15:26:55 +01:00
|
|
|
public boolean unloadChunk(int x, int z) {
|
|
|
|
return unloadChunk(x, z, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean unloadChunk(int x, int z, boolean save) {
|
|
|
|
return unloadChunk(x, z, save, false);
|
|
|
|
}
|
2011-04-26 01:47:25 +02:00
|
|
|
|
2011-02-08 15:26:55 +01:00
|
|
|
public boolean unloadChunkRequest(int x, int z) {
|
|
|
|
return unloadChunkRequest(x, z, true);
|
|
|
|
}
|
2011-04-26 01:47:25 +02:00
|
|
|
|
2011-02-08 15:26:55 +01:00
|
|
|
public boolean unloadChunkRequest(int x, int z, boolean safe) {
|
2011-02-08 16:22:46 +01:00
|
|
|
if (safe && isChunkInUse(x, z)) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-04-26 01:47:25 +02:00
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
world.chunkProviderServer.queueUnload(x, z);
|
2011-02-08 16:22:46 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean unloadChunk(int x, int z, boolean save, boolean safe) {
|
|
|
|
if (safe && isChunkInUse(x, z)) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-04-20 19:05:14 +02:00
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
net.minecraft.server.Chunk chunk = world.chunkProviderServer.getOrCreateChunk(x, z);
|
2011-04-20 19:05:14 +02:00
|
|
|
|
2011-09-15 02:23:52 +02:00
|
|
|
if (save && !(chunk instanceof EmptyChunk)) {
|
2011-04-20 19:05:14 +02:00
|
|
|
chunk.removeEntities();
|
2011-06-17 04:06:45 +02:00
|
|
|
world.chunkProviderServer.saveChunk(chunk);
|
|
|
|
world.chunkProviderServer.saveChunkNOP(chunk);
|
2011-02-08 16:22:46 +01:00
|
|
|
}
|
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
preserveChunk((CraftChunk) chunk.bukkitChunk);
|
2011-06-17 04:06:45 +02:00
|
|
|
world.chunkProviderServer.unloadQueue.remove(x, z);
|
|
|
|
world.chunkProviderServer.chunks.remove(x, z);
|
|
|
|
world.chunkProviderServer.chunkList.remove(chunk);
|
2011-04-20 19:05:14 +02:00
|
|
|
|
2011-02-08 16:22:46 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-03-02 21:27:44 +01:00
|
|
|
public boolean regenerateChunk(int x, int z) {
|
|
|
|
unloadChunk(x, z, false, false);
|
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
world.chunkProviderServer.unloadQueue.remove(x, z);
|
2011-03-02 21:27:44 +01:00
|
|
|
|
|
|
|
net.minecraft.server.Chunk chunk = null;
|
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
if (world.chunkProviderServer.chunkProvider == null) {
|
|
|
|
chunk = world.chunkProviderServer.emptyChunk;
|
2011-03-02 21:27:44 +01:00
|
|
|
} else {
|
2011-06-17 04:06:45 +02:00
|
|
|
chunk = world.chunkProviderServer.chunkProvider.getOrCreateChunk(x, z);
|
2011-03-02 21:27:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
chunkLoadPostProcess(chunk, x, z);
|
|
|
|
|
|
|
|
refreshChunk(x, z);
|
|
|
|
|
|
|
|
return chunk != null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean refreshChunk(int x, int z) {
|
2011-03-11 22:25:35 +01:00
|
|
|
if (!isChunkLoaded(x, z)) {
|
2011-03-02 21:27:44 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-06-12 01:12:43 +02:00
|
|
|
int px = x << 4;
|
|
|
|
int pz = z << 4;
|
2011-03-02 21:27:44 +01:00
|
|
|
|
|
|
|
// If there are more than 10 updates to a chunk at once, it carries out the update as a cuboid
|
|
|
|
// This flags 16 blocks in a line along the bottom for update and then flags a block at the opposite corner at the top
|
|
|
|
// The cuboid that contains these 17 blocks covers the entire chunk
|
|
|
|
// The server will compress the chunk and send it to all clients
|
|
|
|
|
2011-06-12 01:12:43 +02:00
|
|
|
for (int xx = px; xx < (px + 16); xx++) {
|
2011-04-20 19:05:14 +02:00
|
|
|
world.notify(xx, 0, pz);
|
2011-03-02 21:27:44 +01:00
|
|
|
}
|
2011-06-12 01:12:43 +02:00
|
|
|
world.notify(px, 127, pz + 15);
|
2011-03-02 21:27:44 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-02-08 16:22:46 +01:00
|
|
|
public boolean isChunkInUse(int x, int z) {
|
|
|
|
Player[] players = server.getOnlinePlayers();
|
2011-04-20 19:05:14 +02:00
|
|
|
|
2011-02-08 16:22:46 +01:00
|
|
|
for (Player player : players) {
|
|
|
|
Location loc = player.getLocation();
|
2011-06-17 04:06:45 +02:00
|
|
|
if (loc.getWorld() != world.chunkProviderServer.world.getWorld()) {
|
2011-02-08 16:22:46 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the chunk is within 256 blocks of a player, refuse to accept the unload request
|
|
|
|
// This is larger than the distance of loaded chunks that actually surround a player
|
|
|
|
// The player is the center of a 21x21 chunk grid, so the edge is 10 chunks (160 blocks) away from the player
|
|
|
|
if (Math.abs(loc.getBlockX() - (x << 4)) <= 256 && Math.abs(loc.getBlockZ() - (z << 4)) <= 256) {
|
2011-03-02 19:50:39 +01:00
|
|
|
return true;
|
2011-02-08 16:22:46 +01:00
|
|
|
}
|
|
|
|
}
|
2011-03-02 19:50:39 +01:00
|
|
|
return false;
|
2011-02-08 16:22:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean loadChunk(int x, int z, boolean generate) {
|
|
|
|
if (generate) {
|
|
|
|
// Use the default variant of loadChunk when generate == true.
|
2011-06-17 04:06:45 +02:00
|
|
|
return world.chunkProviderServer.getChunkAt(x, z) != null;
|
2011-02-08 16:22:46 +01:00
|
|
|
}
|
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
world.chunkProviderServer.unloadQueue.remove(x, z);
|
|
|
|
net.minecraft.server.Chunk chunk = (net.minecraft.server.Chunk) world.chunkProviderServer.chunks.get(x, z);
|
2011-02-08 16:22:46 +01:00
|
|
|
|
|
|
|
if (chunk == null) {
|
2011-06-17 04:06:45 +02:00
|
|
|
chunk = world.chunkProviderServer.loadChunk(x, z);
|
2011-02-08 16:22:46 +01:00
|
|
|
|
2011-03-02 21:27:44 +01:00
|
|
|
chunkLoadPostProcess(chunk, x, z);
|
|
|
|
}
|
|
|
|
return chunk != null;
|
|
|
|
}
|
2011-02-08 16:22:46 +01:00
|
|
|
|
2011-07-17 15:34:40 +02:00
|
|
|
@SuppressWarnings("unchecked")
|
2011-03-02 21:27:44 +01:00
|
|
|
private void chunkLoadPostProcess(net.minecraft.server.Chunk chunk, int x, int z) {
|
|
|
|
if (chunk != null) {
|
2011-06-17 04:06:45 +02:00
|
|
|
world.chunkProviderServer.chunks.put(x, z, chunk);
|
|
|
|
world.chunkProviderServer.chunkList.add(chunk);
|
2011-02-08 16:22:46 +01:00
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
chunk.loadNOP();
|
|
|
|
chunk.addEntities();
|
2011-02-08 16:22:46 +01:00
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
if (!chunk.done && world.chunkProviderServer.isChunkLoaded(x + 1, z + 1) && world.chunkProviderServer.isChunkLoaded(x, z + 1) && world.chunkProviderServer.isChunkLoaded(x + 1, z)) {
|
|
|
|
world.chunkProviderServer.getChunkAt(world.chunkProviderServer, x, z);
|
2011-03-02 21:27:44 +01:00
|
|
|
}
|
2011-02-08 16:22:46 +01:00
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
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)) {
|
|
|
|
world.chunkProviderServer.getChunkAt(world.chunkProviderServer, x - 1, z);
|
2011-03-02 21:27:44 +01:00
|
|
|
}
|
2011-02-08 16:22:46 +01:00
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
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)) {
|
|
|
|
world.chunkProviderServer.getChunkAt(world.chunkProviderServer, x, z - 1);
|
2011-03-02 21:27:44 +01:00
|
|
|
}
|
|
|
|
|
2011-06-17 04:06:45 +02:00
|
|
|
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)) {
|
|
|
|
world.chunkProviderServer.getChunkAt(world.chunkProviderServer, x - 1, z - 1);
|
2011-02-08 16:22:46 +01:00
|
|
|
}
|
|
|
|
}
|
2011-01-20 21:57:33 +01:00
|
|
|
}
|
|
|
|
|
2011-02-01 23:49:28 +01:00
|
|
|
public boolean isChunkLoaded(Chunk chunk) {
|
|
|
|
return isChunkLoaded(chunk.getX(), chunk.getZ());
|
2010-12-29 00:52:29 +01:00
|
|
|
}
|
|
|
|
|
2011-02-01 23:49:28 +01:00
|
|
|
public void loadChunk(Chunk chunk) {
|
|
|
|
loadChunk(chunk.getX(), chunk.getZ());
|
|
|
|
((CraftChunk) getChunkAt(chunk.getX(), chunk.getZ())).getHandle().bukkitChunk = chunk;
|
2011-01-04 16:54:41 +01:00
|
|
|
}
|
|
|
|
|
2010-12-29 02:07:57 +01:00
|
|
|
public WorldServer getHandle() {
|
|
|
|
return world;
|
|
|
|
}
|
2011-02-01 23:49:28 +01:00
|
|
|
|
2011-02-22 01:43:12 +01:00
|
|
|
public org.bukkit.entity.Item dropItem(Location loc, ItemStack item) {
|
2012-01-20 08:26:26 +01:00
|
|
|
Validate.notNull(item, "Cannot drop a Null item.");
|
|
|
|
Validate.isTrue(item.getTypeId() != 0, "Cannot drop AIR.");
|
2011-11-27 03:45:34 +01:00
|
|
|
CraftItemStack clone = new CraftItemStack(item);
|
|
|
|
EntityItem entity = new EntityItem(world, loc.getX(), loc.getY(), loc.getZ(), clone.getHandle());
|
2011-04-20 19:05:14 +02:00
|
|
|
entity.pickupDelay = 10;
|
|
|
|
world.addEntity(entity);
|
2011-05-14 16:29:42 +02:00
|
|
|
// TODO this is inconsistent with how Entity.getBukkitEntity() works.
|
2011-01-17 09:26:47 +01:00
|
|
|
// However, this entity is not at the moment backed by a server entity class so it may be left.
|
2011-02-22 01:43:12 +01:00
|
|
|
return new CraftItem(world.getServer(), entity);
|
2011-01-08 21:48:45 +01:00
|
|
|
}
|
2011-02-02 00:32:18 +01:00
|
|
|
|
2011-02-22 01:43:12 +01:00
|
|
|
public org.bukkit.entity.Item dropItemNaturally(Location loc, ItemStack item) {
|
2011-04-20 19:05:14 +02:00
|
|
|
double xs = world.random.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D;
|
|
|
|
double ys = world.random.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D;
|
|
|
|
double zs = world.random.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D;
|
2011-01-08 21:48:45 +01:00
|
|
|
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-04-20 19:05:14 +02:00
|
|
|
arrow.setPositionRotation(loc.getX(), loc.getY(), loc.getZ(), 0, 0);
|
|
|
|
world.addEntity(arrow);
|
2012-01-12 16:27:39 +01:00
|
|
|
arrow.shoot(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-02-02 00:32:18 +01:00
|
|
|
|
2012-02-06 06:19:23 +01:00
|
|
|
@Deprecated
|
2011-03-19 06:29:21 +01:00
|
|
|
public LivingEntity spawnCreature(Location loc, CreatureType creatureType) {
|
2012-02-06 06:19:23 +01:00
|
|
|
return spawnCreature(loc, creatureType.toEntityType());
|
|
|
|
}
|
|
|
|
|
|
|
|
public LivingEntity spawnCreature(Location loc, EntityType creatureType) {
|
2011-12-01 22:50:23 +01:00
|
|
|
Entity result = spawn(loc, creatureType.getEntityClass());
|
|
|
|
|
|
|
|
if (result == null) {
|
|
|
|
return null;
|
2011-02-17 06:25:03 +01:00
|
|
|
}
|
2011-12-01 22:50:23 +01:00
|
|
|
|
2012-01-14 23:02:10 +01:00
|
|
|
return (LivingEntity) result;
|
2011-02-17 06:25:03 +01:00
|
|
|
}
|
|
|
|
|
2011-04-22 10:25:55 +02:00
|
|
|
public LightningStrike strikeLightning(Location loc) {
|
2011-11-30 00:17:43 +01:00
|
|
|
EntityWeatherLighting lightning = new EntityWeatherLighting(world, loc.getX(), loc.getY(), loc.getZ());
|
2011-06-27 00:25:01 +02:00
|
|
|
world.strikeLightning(lightning);
|
2011-04-22 10:25:55 +02:00
|
|
|
return new CraftLightningStrike(server, lightning);
|
|
|
|
}
|
|
|
|
|
2011-05-07 04:25:44 +02:00
|
|
|
public LightningStrike strikeLightningEffect(Location loc) {
|
2011-11-30 00:17:43 +01:00
|
|
|
EntityWeatherLighting lightning = new EntityWeatherLighting(world, loc.getX(), loc.getY(), loc.getZ(), true);
|
2011-06-27 00:25:01 +02:00
|
|
|
world.strikeLightning(lightning);
|
2011-05-07 04:25:44 +02:00
|
|
|
return new CraftLightningStrike(server, lightning);
|
|
|
|
}
|
|
|
|
|
2011-01-30 22:53:57 +01:00
|
|
|
public boolean generateTree(Location loc, TreeType type) {
|
|
|
|
return generateTree(loc, type, world);
|
2011-01-03 03:01:17 +01:00
|
|
|
}
|
2011-01-30 22:53:57 +01:00
|
|
|
|
|
|
|
public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) {
|
|
|
|
switch (type) {
|
2012-01-14 23:02:10 +01:00
|
|
|
case BIG_TREE:
|
|
|
|
return new WorldGenBigTree(false).generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), null, null, null);
|
|
|
|
case BIRCH:
|
|
|
|
return new WorldGenForest(false).generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), null, null, null);
|
|
|
|
case REDWOOD:
|
|
|
|
return new WorldGenTaiga2(false).generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), null, null, null);
|
|
|
|
case TALL_REDWOOD:
|
|
|
|
return new WorldGenTaiga1().generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
|
|
|
case TREE:
|
|
|
|
default:
|
|
|
|
return new WorldGenTrees(false).generate(delegate, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), null, null, null);
|
2011-01-30 22:53:57 +01:00
|
|
|
}
|
2011-01-03 03:01:17 +01:00
|
|
|
}
|
2011-02-02 00:32:18 +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() {
|
2011-04-20 19:05:14 +02:00
|
|
|
return world.worldData.name;
|
2011-01-08 03:29:57 +01:00
|
|
|
}
|
|
|
|
|
2011-07-05 05:48:27 +02:00
|
|
|
@Deprecated
|
2011-01-08 03:29:57 +01:00
|
|
|
public long getId() {
|
2011-06-27 00:25:01 +02:00
|
|
|
return world.worldData.getSeed();
|
2011-01-08 03:29:57 +01:00
|
|
|
}
|
|
|
|
|
2011-07-13 06:06:07 +02:00
|
|
|
public UUID getUID() {
|
|
|
|
return world.getUUID();
|
2011-07-05 05:48:27 +02:00
|
|
|
}
|
|
|
|
|
2010-12-30 21:34:26 +01:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
2011-02-07 02:22:43 +01:00
|
|
|
return "CraftWorld{name=" + getName() + '}';
|
2010-12-30 21:34:26 +01:00
|
|
|
}
|
|
|
|
|
2011-02-01 15:53:39 +01:00
|
|
|
public long getTime() {
|
|
|
|
long time = getFullTime() % 24000;
|
|
|
|
if (time < 0) time += 24000;
|
|
|
|
return time;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTime(long time) {
|
|
|
|
long margin = (time - getFullTime()) % 24000;
|
|
|
|
if (margin < 0) margin += 24000;
|
|
|
|
setFullTime(getFullTime() + margin);
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getFullTime() {
|
2011-04-20 19:05:14 +02:00
|
|
|
return world.getTime();
|
2011-02-01 15:53:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setFullTime(long time) {
|
2011-04-20 19:05:14 +02:00
|
|
|
world.setTime(time);
|
2011-04-02 10:04:57 +02:00
|
|
|
|
2011-05-14 16:29:42 +02:00
|
|
|
// Forces the client to update to the new time immediately
|
2012-01-14 23:02:10 +01:00
|
|
|
for (Player p : getPlayers()) {
|
2011-04-02 10:04:57 +02:00
|
|
|
CraftPlayer cp = (CraftPlayer) p;
|
2011-06-17 08:29:16 +02:00
|
|
|
cp.getHandle().netServerHandler.sendPacket(new Packet4UpdateTime(cp.getHandle().getPlayerTime()));
|
2011-04-02 10:04:57 +02:00
|
|
|
}
|
2011-02-01 15:53:39 +01:00
|
|
|
}
|
|
|
|
|
2011-06-09 10:17:19 +02:00
|
|
|
public boolean createExplosion(double x, double y, double z, float power) {
|
2011-06-13 00:49:52 +02:00
|
|
|
return createExplosion(x, y, z, power, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean createExplosion(double x, double y, double z, float power, boolean setFire) {
|
|
|
|
return world.createExplosion(null, x, y, z, power, setFire).wasCanceled ? false : true;
|
2011-06-09 10:17:19 +02:00
|
|
|
}
|
|
|
|
|
2011-06-10 08:13:38 +02:00
|
|
|
public boolean createExplosion(Location loc, float power) {
|
2011-06-13 00:49:52 +02:00
|
|
|
return createExplosion(loc, power, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean createExplosion(Location loc, float power, boolean setFire) {
|
|
|
|
return createExplosion(loc.getX(), loc.getY(), loc.getZ(), power, setFire);
|
2011-06-10 08:13:38 +02:00
|
|
|
}
|
|
|
|
|
2011-02-06 21:50:57 +01:00
|
|
|
public Environment getEnvironment() {
|
|
|
|
return environment;
|
|
|
|
}
|
2011-06-13 00:49:52 +02:00
|
|
|
|
2011-06-04 00:35:05 +02:00
|
|
|
public void setEnvironment(Environment env) {
|
|
|
|
if (environment != env) {
|
|
|
|
environment = env;
|
2011-06-27 00:25:01 +02:00
|
|
|
world.worldProvider = WorldProvider.byDimension(environment.getId());
|
2011-06-04 00:35:05 +02:00
|
|
|
}
|
|
|
|
}
|
2011-02-06 21:50:57 +01:00
|
|
|
|
2011-02-18 17:35:05 +01:00
|
|
|
public Block getBlockAt(Location location) {
|
|
|
|
return getBlockAt(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getBlockTypeIdAt(Location location) {
|
|
|
|
return getBlockTypeIdAt(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getHighestBlockYAt(Location location) {
|
|
|
|
return getHighestBlockYAt(location.getBlockX(), location.getBlockZ());
|
|
|
|
}
|
|
|
|
|
|
|
|
public Chunk getChunkAt(Location location) {
|
|
|
|
return getChunkAt(location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
|
|
|
}
|
|
|
|
|
2011-06-06 15:52:02 +02:00
|
|
|
public ChunkGenerator getGenerator() {
|
|
|
|
return generator;
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<BlockPopulator> getPopulators() {
|
|
|
|
return populators;
|
|
|
|
}
|
|
|
|
|
2011-07-13 07:52:40 +02:00
|
|
|
public Block getHighestBlockAt(int x, int z) {
|
|
|
|
return getBlockAt(x, getHighestBlockYAt(x, z), z);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Block getHighestBlockAt(Location location) {
|
|
|
|
return getHighestBlockAt(location.getBlockX(), location.getBlockZ());
|
|
|
|
}
|
|
|
|
|
|
|
|
public Biome getBiome(int x, int z) {
|
|
|
|
BiomeBase base = getHandle().getWorldChunkManager().getBiome(x, z);
|
|
|
|
|
2011-11-22 22:21:33 +01:00
|
|
|
return CraftBlock.biomeBaseToBiome(base);
|
2011-07-13 07:52:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public double getTemperature(int x, int z) {
|
2011-09-15 02:23:52 +02:00
|
|
|
throw new UnsupportedOperationException("Not compatible with 1.8");
|
2011-07-13 07:52:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public double getHumidity(int x, int z) {
|
2011-09-15 02:23:52 +02:00
|
|
|
throw new UnsupportedOperationException("Not compatible with 1.8");
|
2011-07-13 07:52:40 +02:00
|
|
|
}
|
|
|
|
|
2011-01-26 21:03:54 +01:00
|
|
|
public List<Entity> getEntities() {
|
|
|
|
List<Entity> list = new ArrayList<Entity>();
|
2011-02-02 00:32:18 +01:00
|
|
|
|
2012-01-14 23:02:10 +01:00
|
|
|
for (Object o : world.entityList) {
|
2011-01-26 21:03:54 +01:00
|
|
|
if (o instanceof net.minecraft.server.Entity) {
|
2011-06-12 01:12:43 +02:00
|
|
|
net.minecraft.server.Entity mcEnt = (net.minecraft.server.Entity) o;
|
2011-01-26 21:03:54 +01:00
|
|
|
Entity bukkitEntity = mcEnt.getBukkitEntity();
|
|
|
|
|
|
|
|
// Assuming that bukkitEntity isn't null
|
|
|
|
if (bukkitEntity != null) {
|
|
|
|
list.add(bukkitEntity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-02-02 00:32:18 +01:00
|
|
|
|
2011-01-26 21:03:54 +01:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<LivingEntity> getLivingEntities() {
|
|
|
|
List<LivingEntity> list = new ArrayList<LivingEntity>();
|
2011-02-02 00:32:18 +01:00
|
|
|
|
2012-01-14 23:02:10 +01:00
|
|
|
for (Object o : world.entityList) {
|
2011-01-26 21:03:54 +01:00
|
|
|
if (o instanceof net.minecraft.server.Entity) {
|
2011-06-12 01:12:43 +02:00
|
|
|
net.minecraft.server.Entity mcEnt = (net.minecraft.server.Entity) o;
|
2011-01-26 21:03:54 +01:00
|
|
|
Entity bukkitEntity = mcEnt.getBukkitEntity();
|
2011-02-02 00:32:18 +01:00
|
|
|
|
2011-01-26 21:03:54 +01:00
|
|
|
// Assuming that bukkitEntity isn't null
|
|
|
|
if (bukkitEntity != null && bukkitEntity instanceof LivingEntity) {
|
2011-06-12 01:12:43 +02:00
|
|
|
list.add((LivingEntity) bukkitEntity);
|
2011-01-26 21:03:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-02-02 00:32:18 +01:00
|
|
|
|
2011-01-26 21:03:54 +01:00
|
|
|
return list;
|
|
|
|
}
|
2011-02-24 20:37:53 +01:00
|
|
|
|
2011-12-12 00:27:53 +01:00
|
|
|
@SuppressWarnings("unchecked")
|
2012-01-28 04:49:55 +01:00
|
|
|
@Deprecated
|
2011-12-12 00:27:53 +01:00
|
|
|
public <T extends Entity> Collection<T> getEntitiesByClass(Class<T>... classes) {
|
2012-01-28 04:49:55 +01:00
|
|
|
return (Collection<T>)getEntitiesByClasses(classes);
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public <T extends Entity> Collection<T> getEntitiesByClass(Class<T> clazz) {
|
2011-12-12 00:27:53 +01:00
|
|
|
Collection<T> list = new ArrayList<T>();
|
|
|
|
|
2012-01-28 04:49:55 +01:00
|
|
|
for (Object entity: world.entityList) {
|
|
|
|
if (entity instanceof net.minecraft.server.Entity) {
|
|
|
|
Entity bukkitEntity = ((net.minecraft.server.Entity) entity).getBukkitEntity();
|
|
|
|
|
|
|
|
if (bukkitEntity == null) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Class<?> bukkitClass = bukkitEntity.getClass();
|
|
|
|
|
|
|
|
if (clazz.isAssignableFrom(bukkitClass)) {
|
|
|
|
list.add((T) bukkitEntity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Collection<Entity> getEntitiesByClasses(Class<?>... classes) {
|
|
|
|
Collection<Entity> list = new ArrayList<Entity>();
|
|
|
|
|
2011-12-12 00:27:53 +01:00
|
|
|
for (Object entity: world.entityList) {
|
|
|
|
if (entity instanceof net.minecraft.server.Entity) {
|
|
|
|
Entity bukkitEntity = ((net.minecraft.server.Entity) entity).getBukkitEntity();
|
|
|
|
|
|
|
|
if (bukkitEntity == null) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Class<?> bukkitClass = bukkitEntity.getClass();
|
|
|
|
|
|
|
|
for (Class<?> clazz : classes) {
|
|
|
|
if (clazz.isAssignableFrom(bukkitClass)) {
|
2012-01-28 04:49:55 +01:00
|
|
|
list.add(bukkitEntity);
|
2011-12-12 00:27:53 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2011-02-24 20:37:53 +01:00
|
|
|
public List<Player> getPlayers() {
|
|
|
|
List<Player> list = new ArrayList<Player>();
|
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
for (Object o : world.entityList) {
|
2011-02-24 20:37:53 +01:00
|
|
|
if (o instanceof net.minecraft.server.Entity) {
|
2011-06-12 01:12:43 +02:00
|
|
|
net.minecraft.server.Entity mcEnt = (net.minecraft.server.Entity) o;
|
2011-02-24 20:37:53 +01:00
|
|
|
Entity bukkitEntity = mcEnt.getBukkitEntity();
|
2011-04-20 19:05:14 +02:00
|
|
|
|
2011-02-24 20:37:53 +01:00
|
|
|
if ((bukkitEntity != null) && (bukkitEntity instanceof Player)) {
|
2011-06-12 01:12:43 +02:00
|
|
|
list.add((Player) bukkitEntity);
|
2011-02-24 20:37:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
2011-02-26 03:29:42 +01:00
|
|
|
|
|
|
|
public void save() {
|
2011-09-24 23:03:31 +02:00
|
|
|
boolean oldSave = world.savingDisabled;
|
2011-02-26 03:29:42 +01:00
|
|
|
|
2011-09-24 23:03:31 +02:00
|
|
|
world.savingDisabled = false;
|
2011-09-02 21:46:26 +02:00
|
|
|
world.save(true, null);
|
|
|
|
|
2011-09-24 23:03:31 +02:00
|
|
|
world.savingDisabled = oldSave;
|
2011-09-02 21:46:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isAutoSave() {
|
2011-09-24 23:03:31 +02:00
|
|
|
return !world.savingDisabled;
|
2011-09-02 21:46:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setAutoSave(boolean value) {
|
2011-09-24 23:03:31 +02:00
|
|
|
world.savingDisabled = !value;
|
2011-02-26 03:29:42 +01:00
|
|
|
}
|
2011-04-22 11:18:13 +02:00
|
|
|
|
2011-10-03 07:25:54 +02:00
|
|
|
public void setDifficulty(Difficulty difficulty) {
|
|
|
|
this.getHandle().difficulty = difficulty.getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Difficulty getDifficulty() {
|
|
|
|
return Difficulty.getByValue(this.getHandle().difficulty);
|
|
|
|
}
|
|
|
|
|
2011-04-22 11:18:13 +02:00
|
|
|
public boolean hasStorm() {
|
2011-06-27 00:25:01 +02:00
|
|
|
return world.worldData.hasStorm();
|
2011-04-22 11:18:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setStorm(boolean hasStorm) {
|
2011-04-26 01:47:25 +02:00
|
|
|
CraftServer server = world.getServer();
|
|
|
|
|
|
|
|
WeatherChangeEvent weather = new WeatherChangeEvent((org.bukkit.World) this, hasStorm);
|
|
|
|
server.getPluginManager().callEvent(weather);
|
|
|
|
if (!weather.isCancelled()) {
|
2011-06-27 00:25:01 +02:00
|
|
|
world.worldData.setStorm(hasStorm);
|
2011-04-26 01:47:25 +02:00
|
|
|
|
|
|
|
// These numbers are from Minecraft
|
|
|
|
if (hasStorm) {
|
|
|
|
setWeatherDuration(rand.nextInt(12000) + 12000);
|
|
|
|
} else {
|
|
|
|
setWeatherDuration(rand.nextInt(168000) + 12000);
|
|
|
|
}
|
2011-04-22 11:18:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getWeatherDuration() {
|
2011-06-27 00:25:01 +02:00
|
|
|
return world.worldData.getWeatherDuration();
|
2011-04-22 11:18:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setWeatherDuration(int duration) {
|
2011-06-27 00:25:01 +02:00
|
|
|
world.worldData.setWeatherDuration(duration);
|
2011-04-22 11:18:13 +02:00
|
|
|
}
|
2011-04-22 12:13:21 +02:00
|
|
|
|
|
|
|
public boolean isThundering() {
|
2011-12-10 18:20:24 +01:00
|
|
|
return hasStorm() && world.worldData.isThundering();
|
2011-04-22 12:13:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setThundering(boolean thundering) {
|
2011-12-10 18:20:24 +01:00
|
|
|
if (thundering && !hasStorm()) setStorm(true);
|
2011-04-26 01:47:25 +02:00
|
|
|
CraftServer server = world.getServer();
|
|
|
|
|
|
|
|
ThunderChangeEvent thunder = new ThunderChangeEvent((org.bukkit.World) this, thundering);
|
|
|
|
server.getPluginManager().callEvent(thunder);
|
|
|
|
if (!thunder.isCancelled()) {
|
2011-06-27 00:25:01 +02:00
|
|
|
world.worldData.setThundering(thundering);
|
2011-04-26 01:47:25 +02:00
|
|
|
|
|
|
|
// These numbers are from Minecraft
|
|
|
|
if (thundering) {
|
|
|
|
setThunderDuration(rand.nextInt(12000) + 3600);
|
|
|
|
} else {
|
|
|
|
setThunderDuration(rand.nextInt(168000) + 12000);
|
|
|
|
}
|
2011-04-22 12:13:21 +02:00
|
|
|
}
|
|
|
|
}
|
2011-04-26 01:47:25 +02:00
|
|
|
|
2011-04-22 12:13:21 +02:00
|
|
|
public int getThunderDuration() {
|
2011-06-27 00:25:01 +02:00
|
|
|
return world.worldData.getThunderDuration();
|
2011-04-22 12:13:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setThunderDuration(int duration) {
|
2011-06-27 00:25:01 +02:00
|
|
|
world.worldData.setThunderDuration(duration);
|
2011-04-22 12:13:21 +02:00
|
|
|
}
|
2011-04-23 18:57:25 +02:00
|
|
|
|
|
|
|
public long getSeed() {
|
2011-06-27 00:25:01 +02:00
|
|
|
return world.worldData.getSeed();
|
2011-04-23 18:57:25 +02:00
|
|
|
}
|
2011-04-30 00:34:37 +02:00
|
|
|
|
|
|
|
public boolean getPVP() {
|
|
|
|
return world.pvpMode;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setPVP(boolean pvp) {
|
|
|
|
world.pvpMode = pvp;
|
2011-06-13 00:49:52 +02:00
|
|
|
}
|
|
|
|
|
2011-06-10 08:08:00 +02:00
|
|
|
public void playEffect(Player player, Effect effect, int data) {
|
|
|
|
playEffect(player.getLocation(), effect, data, 0);
|
2011-06-09 21:37:27 +02:00
|
|
|
}
|
|
|
|
|
2011-06-10 08:08:00 +02:00
|
|
|
public void playEffect(Location location, Effect effect, int data) {
|
|
|
|
playEffect(location, effect, data, 64);
|
2011-04-30 00:34:37 +02:00
|
|
|
}
|
2011-06-09 21:37:27 +02:00
|
|
|
|
2011-06-10 08:08:00 +02:00
|
|
|
public void playEffect(Location location, Effect effect, int data, int radius) {
|
|
|
|
int packetData = effect.getId();
|
2011-11-30 00:17:43 +01:00
|
|
|
Packet61WorldEvent packet = new Packet61WorldEvent(packetData, location.getBlockX(), location.getBlockY(), location.getBlockZ(), data);
|
2011-06-09 21:37:27 +02:00
|
|
|
int distance;
|
2012-01-15 11:42:40 +01:00
|
|
|
radius *= radius;
|
|
|
|
|
2011-06-09 21:37:27 +02:00
|
|
|
for (Player player : getPlayers()) {
|
2012-01-15 11:42:40 +01:00
|
|
|
distance = (int) player.getLocation().distanceSquared(location);
|
2011-06-09 21:37:27 +02:00
|
|
|
if (distance <= radius) {
|
|
|
|
((CraftPlayer) player).getHandle().netServerHandler.sendPacket(packet);
|
|
|
|
}
|
|
|
|
}
|
2011-06-13 00:49:52 +02:00
|
|
|
}
|
2011-06-09 00:47:27 +02:00
|
|
|
|
|
|
|
public <T extends Entity> T spawn(Location location, Class<T> clazz) throws IllegalArgumentException {
|
2011-11-20 09:01:14 +01:00
|
|
|
return spawn(location, clazz, SpawnReason.CUSTOM);
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public <T extends Entity> T spawn(Location location, Class<T> clazz, SpawnReason reason) throws IllegalArgumentException {
|
2011-06-09 00:47:27 +02:00
|
|
|
if (location == null || clazz == null) {
|
|
|
|
throw new IllegalArgumentException("Location or entity class cannot be null");
|
|
|
|
}
|
|
|
|
|
|
|
|
net.minecraft.server.Entity entity = null;
|
|
|
|
|
|
|
|
double x = location.getX();
|
|
|
|
double y = location.getY();
|
|
|
|
double z = location.getZ();
|
|
|
|
float pitch = location.getPitch();
|
|
|
|
float yaw = location.getYaw();
|
|
|
|
|
|
|
|
// order is important for some of these
|
2011-06-19 21:59:17 +02:00
|
|
|
if (Boat.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityBoat(world, x, y, z);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (FallingSand.class.isAssignableFrom(clazz)) {
|
2011-11-30 00:17:43 +01:00
|
|
|
entity = new EntityFallingBlock(world, x, y, z, 0, 0);
|
2011-11-20 09:01:14 +01:00
|
|
|
} else if (Projectile.class.isAssignableFrom(clazz)) {
|
|
|
|
if (Snowball.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntitySnowball(world, x, y, z);
|
|
|
|
} else if (Egg.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityEgg(world, x, y, z);
|
|
|
|
} else if (EnderPearl.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityEnderPearl(world, x, y, z);
|
2011-11-21 03:18:10 +01:00
|
|
|
} else if (Arrow.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityArrow(world);
|
|
|
|
entity.setPositionRotation(x, y, z, 0, 0);
|
|
|
|
} else if (Fireball.class.isAssignableFrom(clazz)) {
|
|
|
|
if (SmallFireball.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntitySmallFireball(world);
|
|
|
|
} else {
|
|
|
|
entity = new EntityFireball(world);
|
|
|
|
}
|
|
|
|
((EntityFireball) entity).setPositionRotation(x, y, z, yaw, pitch);
|
|
|
|
Vector direction = location.getDirection().multiply(10);
|
|
|
|
((EntityFireball) entity).setDirection(direction.getX(), direction.getY(), direction.getZ());
|
2011-11-20 09:01:14 +01:00
|
|
|
}
|
2011-06-09 00:47:27 +02:00
|
|
|
} else if (Minecart.class.isAssignableFrom(clazz)) {
|
2011-06-18 18:30:50 +02:00
|
|
|
if (PoweredMinecart.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityMinecart(world, x, y, z, CraftMinecart.Type.PoweredMinecart.getId());
|
2011-06-18 18:30:50 +02:00
|
|
|
} else if (StorageMinecart.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityMinecart(world, x, y, z, CraftMinecart.Type.StorageMinecart.getId());
|
|
|
|
} else {
|
|
|
|
entity = new EntityMinecart(world, x, y, z, CraftMinecart.Type.Minecart.getId());
|
|
|
|
}
|
2011-11-20 09:01:14 +01:00
|
|
|
} else if (EnderSignal.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityEnderSignal(world, x, y, z);
|
2011-11-21 23:39:33 +01:00
|
|
|
} else if (EnderCrystal.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityEnderCrystal(world);
|
|
|
|
entity.setPositionRotation(x, y, z, 0, 0);
|
2011-06-09 00:47:27 +02:00
|
|
|
} else if (LivingEntity.class.isAssignableFrom(clazz)) {
|
2011-06-19 21:59:17 +02:00
|
|
|
if (Chicken.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityChicken(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Cow.class.isAssignableFrom(clazz)) {
|
2011-11-20 09:01:14 +01:00
|
|
|
if (MushroomCow.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityMushroomCow(world);
|
|
|
|
} else {
|
|
|
|
entity = new EntityCow(world);
|
|
|
|
}
|
|
|
|
} else if (Snowman.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntitySnowman(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Creeper.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityCreeper(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Ghast.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityGhast(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Pig.class.isAssignableFrom(clazz)) {
|
2011-06-20 00:03:54 +02:00
|
|
|
entity = new EntityPig(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Player.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
// need a net server handler for this one
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Sheep.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntitySheep(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Skeleton.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntitySkeleton(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Slime.class.isAssignableFrom(clazz)) {
|
2011-11-28 06:08:28 +01:00
|
|
|
if (MagmaCube.class.isAssignableFrom(clazz)) {
|
2011-11-30 00:17:43 +01:00
|
|
|
entity = new EntityMagmaCube(world);
|
2011-11-28 06:08:28 +01:00
|
|
|
} else {
|
|
|
|
entity = new EntitySlime(world);
|
|
|
|
}
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Spider.class.isAssignableFrom(clazz)) {
|
2011-09-15 06:53:19 +02:00
|
|
|
if (CaveSpider.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityCaveSpider(world);
|
|
|
|
} else {
|
|
|
|
entity = new EntitySpider(world);
|
|
|
|
}
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Squid.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntitySquid(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Wolf.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityWolf(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (PigZombie.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityPigZombie(world);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Zombie.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityZombie(world);
|
2011-12-12 04:35:57 +01:00
|
|
|
} else if (Giant.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityGiantZombie(world);
|
2011-09-15 06:53:19 +02:00
|
|
|
} else if (Silverfish.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntitySilverfish(world);
|
|
|
|
} else if (Enderman.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityEnderman(world);
|
2011-11-20 09:01:14 +01:00
|
|
|
} else if (Blaze.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityBlaze(world);
|
|
|
|
} else if (Villager.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityVillager(world);
|
|
|
|
} else if (ComplexLivingEntity.class.isAssignableFrom(clazz)) {
|
|
|
|
if (EnderDragon.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityEnderDragon(world);
|
|
|
|
}
|
2011-06-09 00:47:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (entity != null) {
|
|
|
|
entity.setLocation(x, y, z, pitch, yaw);
|
|
|
|
}
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Painting.class.isAssignableFrom(clazz)) {
|
2011-10-01 19:31:28 +02:00
|
|
|
Block block = getBlockAt(location);
|
|
|
|
BlockFace face = BlockFace.SELF;
|
|
|
|
if (block.getRelative(BlockFace.EAST).getTypeId() == 0) {
|
|
|
|
face = BlockFace.EAST;
|
|
|
|
} else if (block.getRelative(BlockFace.NORTH).getTypeId() == 0) {
|
|
|
|
face = BlockFace.NORTH;
|
|
|
|
} else if (block.getRelative(BlockFace.WEST).getTypeId() == 0) {
|
|
|
|
face = BlockFace.WEST;
|
|
|
|
} else if (block.getRelative(BlockFace.SOUTH).getTypeId() == 0) {
|
|
|
|
face = BlockFace.SOUTH;
|
|
|
|
}
|
|
|
|
int dir;
|
2012-01-14 23:02:10 +01:00
|
|
|
switch (face) {
|
|
|
|
case EAST:
|
|
|
|
default:
|
|
|
|
dir = 0;
|
|
|
|
break;
|
|
|
|
case NORTH:
|
|
|
|
dir = 1;
|
|
|
|
break;
|
|
|
|
case WEST:
|
|
|
|
dir = 2;
|
|
|
|
break;
|
|
|
|
case SOUTH:
|
|
|
|
dir = 3;
|
|
|
|
;
|
|
|
|
break;
|
2011-10-01 19:31:28 +02:00
|
|
|
}
|
|
|
|
entity = new EntityPainting(world, (int) x, (int) y, (int) z, dir);
|
2012-01-12 16:27:39 +01:00
|
|
|
if (!((EntityPainting) entity).survives()) {
|
2011-10-01 19:31:28 +02:00
|
|
|
entity = null;
|
|
|
|
}
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (TNTPrimed.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
entity = new EntityTNTPrimed(world, x, y, z);
|
2011-09-15 06:53:19 +02:00
|
|
|
} else if (ExperienceOrb.class.isAssignableFrom(clazz)) {
|
|
|
|
entity = new EntityExperienceOrb(world, x, y, z, 0);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (Weather.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
// not sure what this can do
|
2011-11-30 00:17:43 +01:00
|
|
|
entity = new EntityWeatherLighting(world, x, y, z);
|
2011-06-19 21:59:17 +02:00
|
|
|
} else if (LightningStrike.class.isAssignableFrom(clazz)) {
|
2011-06-09 00:47:27 +02:00
|
|
|
// what is this, I don't even
|
2011-06-20 21:36:46 +02:00
|
|
|
} else if (Fish.class.isAssignableFrom(clazz)) {
|
|
|
|
// this is not a fish, it's a bobber, and it's probably useless
|
2011-09-24 23:03:31 +02:00
|
|
|
entity = new EntityFishingHook(world);
|
2011-06-20 21:36:46 +02:00
|
|
|
entity.setLocation(x, y, z, pitch, yaw);
|
2011-06-09 00:47:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (entity != null) {
|
2011-11-20 09:01:14 +01:00
|
|
|
world.addEntity(entity, reason);
|
2011-06-09 00:47:27 +02:00
|
|
|
return (T) entity.getBukkitEntity();
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new IllegalArgumentException("Cannot spawn an entity for " + clazz.getName());
|
|
|
|
}
|
2011-06-17 15:23:19 +02:00
|
|
|
|
|
|
|
public ChunkSnapshot getEmptyChunkSnapshot(int x, int z, boolean includeBiome, boolean includeBiomeTempRain) {
|
|
|
|
return CraftChunk.getEmptyChunkSnapshot(x, z, this, includeBiome, includeBiomeTempRain);
|
|
|
|
}
|
2011-06-19 12:09:05 +02:00
|
|
|
|
|
|
|
public void setSpawnFlags(boolean allowMonsters, boolean allowAnimals) {
|
|
|
|
world.setSpawnFlags(allowMonsters, allowAnimals);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean getAllowAnimals() {
|
|
|
|
return world.allowAnimals;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean getAllowMonsters() {
|
|
|
|
return world.allowMonsters;
|
|
|
|
}
|
2011-07-20 01:03:47 +02:00
|
|
|
|
|
|
|
public int getMaxHeight() {
|
2011-09-25 02:05:55 +02:00
|
|
|
return world.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getSeaLevel() {
|
|
|
|
return world.seaLevel;
|
2011-07-20 01:03:47 +02:00
|
|
|
}
|
2011-07-27 01:24:27 +02:00
|
|
|
|
|
|
|
public boolean getKeepSpawnInMemory() {
|
|
|
|
return world.keepSpawnInMemory;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setKeepSpawnInMemory(boolean keepLoaded) {
|
|
|
|
world.keepSpawnInMemory = keepLoaded;
|
|
|
|
// Grab the worlds spawn chunk
|
|
|
|
ChunkCoordinates chunkcoordinates = this.world.getSpawn();
|
|
|
|
int chunkCoordX = chunkcoordinates.x >> 4;
|
|
|
|
int chunkCoordZ = chunkcoordinates.z >> 4;
|
2012-01-14 23:02:10 +01:00
|
|
|
// Cycle through the 25x25 Chunks around it to load/unload the chunks.
|
2011-07-27 01:24:27 +02:00
|
|
|
for (int x = -12; x <= 12; x++) {
|
|
|
|
for (int z = -12; z <= 12; z++) {
|
|
|
|
if (keepLoaded) {
|
|
|
|
loadChunk(chunkCoordX + x, chunkCoordZ + z);
|
|
|
|
} else {
|
2011-08-11 11:29:39 +02:00
|
|
|
if (isChunkLoaded(chunkCoordX + x, chunkCoordZ + z)) {
|
2011-09-15 02:23:52 +02:00
|
|
|
if (this.getHandle().getChunkAt(chunkCoordX + x, chunkCoordZ + z) instanceof EmptyChunk) {
|
2011-08-11 11:29:39 +02:00
|
|
|
unloadChunk(chunkCoordX + x, chunkCoordZ + z, false);
|
|
|
|
} else {
|
|
|
|
unloadChunk(chunkCoordX + x, chunkCoordZ + z);
|
|
|
|
}
|
|
|
|
}
|
2011-07-27 01:24:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-10-10 23:45:52 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
|
|
|
return getUID().hashCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object obj) {
|
|
|
|
if (obj == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (getClass() != obj.getClass()) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-12-10 18:20:24 +01:00
|
|
|
|
2011-10-10 23:45:52 +02:00
|
|
|
final CraftWorld other = (CraftWorld) obj;
|
2011-12-10 18:20:24 +01:00
|
|
|
|
2011-10-10 23:45:52 +02:00
|
|
|
return this.getUID() == other.getUID();
|
|
|
|
}
|
2011-11-25 04:47:12 +01:00
|
|
|
|
|
|
|
public File getWorldFolder() {
|
2012-01-14 23:02:10 +01:00
|
|
|
return ((WorldNBTStorage) world.getDataManager()).getDirectory();
|
2011-11-25 04:47:12 +01:00
|
|
|
}
|
2011-12-07 14:23:06 +01:00
|
|
|
|
|
|
|
public void explodeBlock(Block block, float yield) {
|
|
|
|
// First of all, don't explode fire
|
2011-12-08 00:26:39 +01:00
|
|
|
if (block.getType().equals(org.bukkit.Material.AIR) || block.getType().equals(org.bukkit.Material.FIRE)) {
|
2011-12-07 14:23:06 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
int blockId = block.getTypeId();
|
|
|
|
int blockX = block.getX();
|
|
|
|
int blockY = block.getY();
|
|
|
|
int blockZ = block.getZ();
|
|
|
|
// following code is lifted from Explosion.a(boolean), and modified
|
|
|
|
net.minecraft.server.Block.byId[blockId].dropNaturally(this.world, blockX, blockY, blockZ, block.getData(), yield, 0);
|
|
|
|
block.setType(org.bukkit.Material.AIR);
|
|
|
|
// not sure what this does, seems to have something to do with the 'base' material of a block.
|
|
|
|
// For example, WOODEN_STAIRS does something with WOOD in this method
|
2012-01-12 16:27:39 +01:00
|
|
|
net.minecraft.server.Block.byId[blockId].wasExploded(this.world, blockX, blockY, blockZ);
|
2011-12-07 14:23:06 +01:00
|
|
|
}
|
2012-01-13 09:52:26 +01:00
|
|
|
|
|
|
|
public void sendPluginMessage(Plugin source, String channel, byte[] message) {
|
|
|
|
StandardMessenger.validatePluginMessage(server.getMessenger(), source, channel, message);
|
|
|
|
|
|
|
|
for (Player player : getPlayers()) {
|
|
|
|
player.sendPluginMessage(source, channel, message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Set<String> getListeningPluginChannels() {
|
|
|
|
Set<String> result = new HashSet<String>();
|
|
|
|
|
|
|
|
for (Player player : getPlayers()) {
|
|
|
|
result.addAll(player.getListeningPluginChannels());
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2012-01-15 18:44:15 +01:00
|
|
|
|
|
|
|
public org.bukkit.WorldType getWorldType() {
|
|
|
|
return org.bukkit.WorldType.getByName(world.getWorldData().getType().name());
|
|
|
|
}
|
2012-01-29 18:40:45 +01:00
|
|
|
|
|
|
|
public boolean canGenerateStructures() {
|
|
|
|
return world.getWorldData().o();
|
|
|
|
}
|
2012-02-10 16:23:52 +01:00
|
|
|
|
|
|
|
public long getTicksPerAnimalSpawns() {
|
|
|
|
return world.ticksPerAnimalSpawns;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTicksPerAnimalSpawns(int ticksPerAnimalSpawns) {
|
|
|
|
world.ticksPerAnimalSpawns = ticksPerAnimalSpawns;
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getTicksPerMonsterSpawns() {
|
|
|
|
return world.ticksPerMonsterSpawns;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTicksPerMonsterSpawns(int ticksPerMonsterSpawns) {
|
|
|
|
world.ticksPerMonsterSpawns = ticksPerMonsterSpawns;
|
|
|
|
}
|
2010-12-27 03:13:03 +01:00
|
|
|
}
|