From 4a6614f34f9d430691487ba600e3b25ce09235de Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 6 Apr 2014 15:06:38 -0700 Subject: [PATCH] Cleaned up ForgeWorld, AbstractWorld. Change block setting method in Forge to a more proper one. --- .../sk89q/worldedit/bukkit/BukkitWorld.java | 2 +- .../sk89q/worldedit/forge/ForgePlatform.java | 5 +- .../sk89q/worldedit/forge/ForgePlayer.java | 10 +- .../com/sk89q/worldedit/forge/ForgeWorld.java | 601 ++++++++++-------- .../sk89q/worldedit/forge/ForgeWorldEdit.java | 5 +- .../java/com/sk89q/worldedit/LocalWorld.java | 4 +- .../sk89q/worldedit/extent/InputExtent.java | 1 + .../worldedit/internal/LocalWorldAdapter.java | 2 +- .../sk89q/worldedit/world/AbstractWorld.java | 47 +- .../java/com/sk89q/worldedit/world/World.java | 2 +- 10 files changed, 378 insertions(+), 301 deletions(-) diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index c34344e68..3617df143 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -1236,7 +1236,7 @@ public class BukkitWorld extends LocalWorld { } @Override - public boolean setBlock(Vector pt, BaseBlock block, boolean notifyAdjacent) { + public boolean setBlock(Vector pt, BaseBlock block, boolean notifyAdjacent) throws WorldEditException { if (!skipNmsSafeSet) { try { return (Boolean) nmsSetSafeMethod.invoke(null, this, pt, block, notifyAdjacent); diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java b/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java index d2c1d7663..f24396222 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -22,7 +22,6 @@ package com.sk89q.worldedit.forge; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.worldedit.BiomeTypes; import com.sk89q.worldedit.LocalConfiguration; -import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.ServerInterface; import cpw.mods.fml.common.FMLCommonHandler; import net.minecraft.command.CommandBase; @@ -81,9 +80,9 @@ class ForgePlatform extends ServerInterface { return -1; } - public List getWorlds() { + public List getWorlds() { List worlds = Arrays.asList(DimensionManager.getWorlds()); - List ret = new ArrayList(worlds.size()); + List ret = new ArrayList(worlds.size()); for (WorldServer world : worlds) { ret.add(new ForgeWorld(world)); } diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgePlayer.java b/src/forge/java/com/sk89q/worldedit/forge/ForgePlayer.java index d08872dce..dec4dd7b6 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -20,8 +20,12 @@ package com.sk89q.worldedit.forge; import com.sk89q.util.StringUtil; -import com.sk89q.worldedit.*; +import com.sk89q.worldedit.LocalPlayer; +import com.sk89q.worldedit.ServerInterface; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldVector; import com.sk89q.worldedit.extent.inventory.BlockBag; +import com.sk89q.worldedit.internal.LocalWorldAdapter; import com.sk89q.worldedit.internal.cui.CUIEvent; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; @@ -46,10 +50,10 @@ public class ForgePlayer extends LocalPlayer { } public WorldVector getPosition() { - return new WorldVector(ForgeWorldEdit.inst.getWorld(this.player.worldObj), this.player.posX, this.player.posY, this.player.posZ); + return new WorldVector(LocalWorldAdapter.wrap(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ); } - public LocalWorld getWorld() { + public com.sk89q.worldedit.world.World getWorld() { return ForgeWorldEdit.inst.getWorld(this.player.worldObj); } diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java index 2da4123b2..2f64a1f82 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -21,9 +21,13 @@ package com.sk89q.worldedit.forge; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.*; -import com.sk89q.worldedit.blocks.*; -import com.sk89q.worldedit.foundation.Block; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.blocks.LazyBlock; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.TreeGenerator.TreeType; +import com.sk89q.worldedit.world.AbstractWorld; +import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityHanging; import net.minecraft.entity.EntityLiving; @@ -35,7 +39,8 @@ import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.passive.EntityTameable; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.inventory.IInventory; -import net.minecraft.tileentity.*; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.LongHashMap; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; @@ -45,254 +50,120 @@ import net.minecraft.world.gen.ChunkProviderServer; import java.lang.ref.WeakReference; import java.lang.reflect.Field; -import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; -public class ForgeWorld extends LocalWorld { - private WeakReference world; - +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * An adapter to Minecraft worlds for WorldEdit. + */ +public class ForgeWorld extends AbstractWorld { + + private static final Logger logger = Logger.getLogger(ForgeWorld.class.getCanonicalName()); + private final WeakReference worldRef; + + /** + * Construct a new world. + * + * @param world the world + */ ForgeWorld(World world) { - this.world = new WeakReference(world); + checkNotNull(world); + this.worldRef = new WeakReference(world); } + /** + * Get the underlying handle to the world. + * + * @return the world + * @throws WorldEditException thrown if a reference to the world was lost (i.e. world was unloaded) + */ + public World getWorldChecked() throws WorldEditException { + World world = worldRef.get(); + if (world != null) { + return world; + } else { + throw new WorldReferenceLostException("The reference to the world was lost (i.e. the world may have been unloaded)"); + } + } + + /** + * Get the underlying handle to the world. + * + * @return the world + * @throws RuntimeException thrown if a reference to the world was lost (i.e. world was unloaded) + */ + public World getWorld() { + World world = worldRef.get(); + if (world != null) { + return world; + } else { + throw new RuntimeException("The reference to the world was lost (i.e. the world may have been unloaded)"); + } + } + + @Override public String getName() { - return this.world.get().provider.getDimensionName(); + return getWorld().provider.getDimensionName(); } - public boolean setBlockType(Vector pt, int type) { - return this.world.get().setBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), type, 0, 3); - } + @Override + public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException { + checkNotNull(position); + checkNotNull(block); - public boolean setBlockTypeFast(Vector pt, int type) { - return this.world.get().setBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), type); - } + World world = getWorldChecked(); + int x = position.getBlockX(); + int y = position.getBlockY(); + int z = position.getBlockZ(); - public boolean setTypeIdAndData(Vector pt, int type, int data) { - return this.world.get().setBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), type, data, 3); - } + // First set the block + Chunk chunk = world.getChunkFromChunkCoords(x >> 4, z >> 4); + int previousId = 0; - public boolean setTypeIdAndDataFast(Vector pt, int type, int data) { - return this.world.get().setBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), type, data, 3); - } - - public int getBlockType(Vector pt) { - return this.world.get().getBlockId(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - } - - public void setBlockData(Vector pt, int data) { - this.world.get().setBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), data, 0, 3); - } - - public void setBlockDataFast(Vector pt, int data) { - this.world.get().setBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), data, 0, 3); - } - - public int getBlockData(Vector pt) { - return this.world.get().getBlockMetadata(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - } - - public int getBlockLightLevel(Vector pt) { - return this.world.get().getBlockLightValue(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - } - - public boolean isValidBlockType(int id) { - return (id == 0) || (net.minecraft.block.Block.blocksList[id] != null); - } - - public BiomeType getBiome(Vector2D pt) { - return ForgeBiomeTypes.getFromBaseBiome(this.world.get().getBiomeGenForCoords(pt.getBlockX(), pt.getBlockZ())); - } - - public void setBiome(Vector2D pt, BiomeType biome) { - if (this.world.get().getChunkProvider().chunkExists(pt.getBlockX(), pt.getBlockZ())) { - Chunk chunk = this.world.get().getChunkFromBlockCoords(pt.getBlockX(), pt.getBlockZ()); - if ((chunk != null) && (chunk.isChunkLoaded)) { - byte[] biomevals = chunk.getBiomeArray(); - biomevals[((pt.getBlockZ() & 0xF) << 4 | pt.getBlockX() & 0xF)] = (byte) ForgeBiomeTypes.getFromBiomeType(biome).biomeID; - } - } - } - - public boolean regenerate(Region region, EditSession editSession) { - BaseBlock[] history = new BaseBlock[256 * (getMaxY() + 1)]; - - for (Vector2D chunk : region.getChunks()) { - Vector min = new Vector(chunk.getBlockX() * 16, 0, chunk.getBlockZ() * 16); - - for (int x = 0; x < 16; x++) { - for (int y = 0; y < getMaxY() + 1; y++) { - for (int z = 0; z < 16; z++) { - Vector pt = min.add(x, y, z); - int index = y * 16 * 16 + z * 16 + x; - history[index] = editSession.getBlock(pt); - } - } - } - try { - Set chunks = region.getChunks(); - IChunkProvider provider = this.world.get().getChunkProvider(); - if (!(provider instanceof ChunkProviderServer)) { - return false; - } - ChunkProviderServer chunkServer = (ChunkProviderServer) provider; - Field u = null; - try { - u = ChunkProviderServer.class.getDeclaredField("field_73248_b"); // chunksToUnload - } catch(NoSuchFieldException e) { - u = ChunkProviderServer.class.getDeclaredField("chunksToUnload"); - } - u.setAccessible(true); - Set unloadQueue = (Set) u.get(chunkServer); - Field m = null; - try { - m = ChunkProviderServer.class.getDeclaredField("field_73244_f"); // loadedChunkHashMap - } catch(NoSuchFieldException e) { - m = ChunkProviderServer.class.getDeclaredField("loadedChunkHashMap"); - } - m.setAccessible(true); - LongHashMap loadedMap = (LongHashMap) m.get(chunkServer); - Field lc = null; - try { - lc = ChunkProviderServer.class.getDeclaredField("field_73245_g"); // loadedChunkHashMap - } catch(NoSuchFieldException e) { - lc = ChunkProviderServer.class.getDeclaredField("loadedChunks"); - } - lc.setAccessible(true); - List loaded = (List) lc.get(chunkServer); - Field p = null; - try { - p = ChunkProviderServer.class.getDeclaredField("field_73246_d"); // currentChunkProvider - } catch(NoSuchFieldException e) { - p = ChunkProviderServer.class.getDeclaredField("currentChunkProvider"); - } - p.setAccessible(true); - IChunkProvider chunkProvider = (IChunkProvider) p.get(chunkServer); - - for (Vector2D coord : chunks) { - long pos = ChunkCoordIntPair.chunkXZ2Int(coord.getBlockX(), coord.getBlockZ()); - Chunk mcChunk = null; - if (chunkServer.chunkExists(coord.getBlockX(), coord.getBlockZ())) { - mcChunk = chunkServer.loadChunk(coord.getBlockX(), coord.getBlockZ()); - mcChunk.onChunkUnload(); - } - unloadQueue.remove(pos); - loadedMap.remove(pos); - mcChunk = chunkProvider.provideChunk(coord.getBlockX(), coord.getBlockZ()); - loadedMap.add(pos, mcChunk); - loaded.add(mcChunk); - if (mcChunk != null) { - mcChunk.onChunkLoad(); - } - mcChunk.populateChunk(chunkProvider, chunkProvider, coord.getBlockX(), coord.getBlockZ()); - } - } catch (Throwable t) { - t.printStackTrace(); - return false; - } - - for (int x = 0; x < 16; x++) { - for (int y = 0; y < getMaxY() + 1; y++) { - for (int z = 0; z < 16; z++) { - Vector pt = min.add(x, y, z); - int index = y * 16 * 16 + z * 16 + x; - - if (!region.contains(pt)) - editSession.smartSetBlock(pt, history[index]); - else { - editSession.rememberChange(pt, history[index], editSession.rawGetBlock(pt)); - } - } - } - } + if (notifyAndLight) { + previousId = chunk.getBlockID(x & 15, y, z & 15); } - return false; - } - - public boolean setBlock(Vector pt, Block block, boolean notify) { - if (!(block instanceof BaseBlock)) { - return false; - } - - boolean successful = this.world.get().setBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), block.getId()); + boolean successful = chunk.setBlockIDWithMetadata(x & 15, y, z & 15, block.getId(), block.getData()); + // Create the TileEntity if (successful) { - if (block instanceof TileEntityBlock) { - copyToWorld(pt, (BaseBlock) block); + CompoundTag tag = block.getNbtData(); + if (tag != null) { + NBTTagCompound nativeTag = NBTConverter.toNative(tag); + nativeTag.setString("id", block.getNbtId()); + TileEntityUtils.setTileEntity(getWorld(), position, nativeTag); } } - this.world.get().setBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), block.getId(), block.getData(), 3); + + if (notifyAndLight) { + world.updateAllLightTypes(x, y, z); + world.markBlockForUpdate(x, y, z); + world.notifyBlockChange(x, y, z, previousId); + + Block mcBlock = Block.blocksList[block.getId()]; + if (mcBlock != null && mcBlock.hasComparatorInputOverride()) { + world.func_96440_m(x, y, z, block.getId()); + } + } + return successful; } - public BaseBlock getBlock(Vector pt) { - int type = getBlockType(pt); - int data = getBlockData(pt); - TileEntity tile = this.world.get().getBlockTileEntity(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (tile != null) { - TileEntityBaseBlock block = new TileEntityBaseBlock(type, data, tile); - return block; - } - return new BaseBlock(type, data); + @Override + public int getBlockLightLevel(Vector position) { + checkNotNull(position); + return getWorld().getBlockLightValue(position.getBlockX(), position.getBlockY(), position.getBlockZ()); } - public boolean copyToWorld(Vector pt, BaseBlock block) { - return copyToWorld(pt, block, true); - } - - public boolean copyToWorld(Vector pt, BaseBlock block, boolean copyData) { - if (!(block instanceof TileEntityBlock)) { - return false; - } - if (block instanceof SignBlock) { - // Signs - TileEntitySign sign = new TileEntitySign(); - sign.signText = ((SignBlock) block).getText(); - world.get().setBlockTileEntity(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), sign); - return true; - } - - if (block instanceof MobSpawnerBlock) { - // Mob spawners - TileEntityMobSpawner spawner = new TileEntityMobSpawner(); - spawner.getSpawnerLogic().setMobID(((MobSpawnerBlock) block).getMobType()); - world.get().setBlockTileEntity(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), spawner); - return true; - } - - if (block instanceof NoteBlock) { - // Note block - TileEntityNote note = new TileEntityNote(); - note.note = ((NoteBlock) block).getNote(); - world.get().setBlockTileEntity(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), note); - return true; - } - - if (block instanceof SkullBlock) { - // Skull block - TileEntitySkull skull = new TileEntitySkull(); - skull.setSkullType(((SkullBlock) block).getSkullType(), ((SkullBlock) block).getOwner()); - skull.setSkullRotation(((SkullBlock) block).getRot()); - world.get().setBlockTileEntity(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), skull); - return true; - } - - CompoundTag tag = block.getNbtData(); - if (tag != null) { - TileEntityUtils.setTileEntity(this.world.get(), pt, NBTConverter.toNative(tag)); - return true; - } - - return false; - } - - public boolean copyFromWorld(Vector pt, BaseBlock block) { - return false; - } - - public boolean clearContainerBlockContents(Vector pt) { - TileEntity tile = this.world.get().getBlockTileEntity(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + @Override + public boolean clearContainerBlockContents(Vector position) { + checkNotNull(position); + TileEntity tile = getWorld().getBlockTileEntity(position.getBlockX(), position.getBlockY(), position.getBlockZ()); if ((tile instanceof IInventory)) { IInventory inv = (IInventory) tile; int size = inv.getSizeInventory(); @@ -304,21 +175,96 @@ public class ForgeWorld extends LocalWorld { return false; } - public void dropItem(Vector pt, BaseItemStack item) { + @Override + public BiomeType getBiome(Vector2D position) { + checkNotNull(position); + return ForgeBiomeTypes.getFromBaseBiome(getWorld().getBiomeGenForCoords(position.getBlockX(), position.getBlockZ())); + } + + @Override + public void setBiome(Vector2D position, BiomeType biome) { + checkNotNull(position); + checkNotNull(biome); + + if (getWorld().getChunkProvider().chunkExists(position.getBlockX(), position.getBlockZ())) { + Chunk chunk = getWorld().getChunkFromBlockCoords(position.getBlockX(), position.getBlockZ()); + if ((chunk != null) && (chunk.isChunkLoaded)) { + chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = (byte) ForgeBiomeTypes.getFromBiomeType(biome).biomeID; + } + } + } + + @Override + public void dropItem(Vector position, BaseItemStack item) { + checkNotNull(position); + checkNotNull(item); + if ((item == null) || (item.getType() == 0)) { return; } - EntityItem entity = new EntityItem(this.world.get(), pt.getX(), pt.getY(), pt.getZ(), ForgeUtil.toForgeItemStack(item)); + + EntityItem entity = new EntityItem(getWorld(), position.getX(), position.getY(), position.getZ(), ForgeUtil.toForgeItemStack(item)); entity.delayBeforeCanPickup = 10; - this.world.get().spawnEntityInWorld(entity); + getWorld().spawnEntityInWorld(entity); } + @Override + @SuppressWarnings({"unchecked", "ConstantConditions"}) + public int killMobs(Vector origin, double radius, int flags) { + boolean killPets = (flags & 0x1) != 0; + boolean killNPCs = (flags & 0x2) != 0; + boolean killAnimals = (flags & 0x4) != 0; + + boolean killGolems = (flags & 0x8) != 0; + boolean killAmbient = (flags & 0x10) != 0; + + int num = 0; + double radiusSq = radius * radius; + + for (Entity obj : (Iterable) getWorld().loadedEntityList) { + if ((obj instanceof EntityLiving)) { + EntityLiving ent = (EntityLiving) obj; + + if (!killAnimals && ent instanceof EntityAnimal) { + continue; + } + + if (!killPets && ent instanceof EntityTameable && ((EntityTameable) ent).isTamed()) { + continue; // tamed pet + } + + if (!killGolems && ent instanceof EntityGolem) { + continue; + } + + if (!killNPCs && ent instanceof EntityVillager) { + continue; + } + + if (!killAmbient && ent instanceof EntityAmbientCreature) { + continue; + } + + if ((radius < 0.0D) || (origin.distanceSq(new Vector(ent.posX, ent.posY, ent.posZ)) <= radiusSq)) { + ent.isDead = true; + num++; + } + } + } + + return num; + } + + @Override + @SuppressWarnings("unchecked") public int removeEntities(EntityType type, Vector origin, int radius) { + checkNotNull(type); + checkNotNull(origin); + int num = 0; double radiusSq = Math.pow(radius, 2.0D); - for (Iterator it = this.world.get().loadedEntityList.iterator(); it.hasNext();) { - Entity ent = it.next(); + for (Entity ent : (Iterable) getWorld().loadedEntityList) { if ((radius != -1) && (origin.distanceSq(new Vector(ent.posX, ent.posY, ent.posZ)) > radiusSq)) { continue; } @@ -377,66 +323,159 @@ public class ForgeWorld extends LocalWorld { return num; } - public int killMobs(Vector origin, double radius, int flags) { - boolean killPets = (flags & 0x1) != 0; - boolean killNPCs = (flags & 0x2) != 0; - boolean killAnimals = (flags & 0x4) != 0; + @Override + public boolean regenerate(Region region, EditSession editSession) { + BaseBlock[] history = new BaseBlock[256 * (getMaxY() + 1)]; - boolean killGolems = (flags & 0x8) != 0; - boolean killAmbient = (flags & 0x10) != 0; + for (Vector2D chunk : region.getChunks()) { + Vector min = new Vector(chunk.getBlockX() * 16, 0, chunk.getBlockZ() * 16); - int num = 0; - double radiusSq = radius * radius; - - for (Iterator it = this.world.get().loadedEntityList.iterator(); it.hasNext();) { - Entity obj = it.next(); - if (!(obj instanceof EntityLiving)) { - continue; + for (int x = 0; x < 16; x++) { + for (int y = 0; y < getMaxY() + 1; y++) { + for (int z = 0; z < 16; z++) { + Vector pt = min.add(x, y, z); + int index = y * 16 * 16 + z * 16 + x; + history[index] = editSession.getBlock(pt); + } + } } - EntityLiving ent = (EntityLiving) obj; + try { + Set chunks = region.getChunks(); + IChunkProvider provider = getWorld().getChunkProvider(); + if (!(provider instanceof ChunkProviderServer)) { + return false; + } + ChunkProviderServer chunkServer = (ChunkProviderServer) provider; + Field u; + try { + u = ChunkProviderServer.class.getDeclaredField("field_73248_b"); // chunksToUnload + } catch(NoSuchFieldException e) { + u = ChunkProviderServer.class.getDeclaredField("chunksToUnload"); + } + u.setAccessible(true); + Set unloadQueue = (Set) u.get(chunkServer); + Field m; + try { + m = ChunkProviderServer.class.getDeclaredField("field_73244_f"); // loadedChunkHashMap + } catch(NoSuchFieldException e) { + m = ChunkProviderServer.class.getDeclaredField("loadedChunkHashMap"); + } + m.setAccessible(true); + LongHashMap loadedMap = (LongHashMap) m.get(chunkServer); + Field lc; + try { + lc = ChunkProviderServer.class.getDeclaredField("field_73245_g"); // loadedChunkHashMap + } catch(NoSuchFieldException e) { + lc = ChunkProviderServer.class.getDeclaredField("loadedChunks"); + } + lc.setAccessible(true); + @SuppressWarnings("unchecked") List loaded = (List) lc.get(chunkServer); + Field p; + try { + p = ChunkProviderServer.class.getDeclaredField("field_73246_d"); // currentChunkProvider + } catch(NoSuchFieldException e) { + p = ChunkProviderServer.class.getDeclaredField("currentChunkProvider"); + } + p.setAccessible(true); + IChunkProvider chunkProvider = (IChunkProvider) p.get(chunkServer); - if (!killAnimals && ent instanceof EntityAnimal) { - continue; + for (Vector2D coord : chunks) { + long pos = ChunkCoordIntPair.chunkXZ2Int(coord.getBlockX(), coord.getBlockZ()); + Chunk mcChunk; + if (chunkServer.chunkExists(coord.getBlockX(), coord.getBlockZ())) { + mcChunk = chunkServer.loadChunk(coord.getBlockX(), coord.getBlockZ()); + mcChunk.onChunkUnload(); + } + unloadQueue.remove(pos); + loadedMap.remove(pos); + mcChunk = chunkProvider.provideChunk(coord.getBlockX(), coord.getBlockZ()); + loadedMap.add(pos, mcChunk); + loaded.add(mcChunk); + if (mcChunk != null) { + mcChunk.onChunkLoad(); + mcChunk.populateChunk(chunkProvider, chunkProvider, coord.getBlockX(), coord.getBlockZ()); + } + } + } catch (Throwable t) { + logger.log(Level.WARNING, "Failed to generate chunk", t); + return false; } - if (!killPets && ent instanceof EntityTameable && ((EntityTameable) ent).isTamed()) { - continue; // tamed pet - } + for (int x = 0; x < 16; x++) { + for (int y = 0; y < getMaxY() + 1; y++) { + for (int z = 0; z < 16; z++) { + Vector pt = min.add(x, y, z); + int index = y * 16 * 16 + z * 16 + x; - if (!killGolems && ent instanceof EntityGolem) { - continue; - } - - if (!killNPCs && ent instanceof EntityVillager) { - continue; - } - - if (!killAmbient && ent instanceof EntityAmbientCreature) { - continue; - } - - - if ((radius < 0.0D) || (origin.distanceSq(new Vector(ent.posX, ent.posY, ent.posZ)) <= radiusSq)) { - ent.isDead = true; - num++; + if (!region.contains(pt)) + editSession.smartSetBlock(pt, history[index]); + else { + editSession.rememberChange(pt, history[index], editSession.rawGetBlock(pt)); + } + } + } } } - return num; - } - - public World getWorld() { - return world.get(); - } - - public boolean equals(Object other) { - if ((other instanceof ForgeWorld)) { - return ((ForgeWorld) other).world.get().equals(this.world.get()); - } return false; } - public int hashCode() { - return this.world.get().hashCode(); + @Override + public boolean generateTree(TreeType type, EditSession editSession, Vector position) throws MaxChangedBlocksException { + return false; } + + @Override + public boolean isValidBlockType(int id) { + return (id == 0) || (net.minecraft.block.Block.blocksList[id] != null); + } + + @Override + public BaseBlock getBlock(Vector position) { + World world = getWorld(); + int id = world.getBlockId(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + int data = world.getBlockMetadata(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + TileEntity tile = getWorld().getBlockTileEntity(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + + if (tile != null) { + return new TileEntityBaseBlock(id, data, tile); + } else { + return new BaseBlock(id, data); + } + } + + @Override + public BaseBlock getLazyBlock(Vector position) { + World world = getWorld(); + int id = world.getBlockId(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + int data = world.getBlockMetadata(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + return new LazyBlock(id, data, this, position); + } + + @Override + public int hashCode() { + return getWorld().hashCode(); + } + + @Override + public boolean equals(Object o) { + if ((o instanceof ForgeWorld)) { + ForgeWorld other = ((ForgeWorld) o); + World otherWorld = other.worldRef.get(); + World thisWorld = other.worldRef.get(); + return otherWorld != null && thisWorld != null && otherWorld.equals(thisWorld); + } else { + return false; + } + } + + /** + * Thrown when the reference to the world is lost. + */ + private static class WorldReferenceLostException extends WorldEditException { + private WorldReferenceLostException(String message) { + super(message); + } + } + } \ No newline at end of file diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java index b0e18a0e7..283e99a97 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java @@ -26,6 +26,7 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldVector; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.PlatformRejectionException; +import com.sk89q.worldedit.internal.LocalWorldAdapter; import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; @@ -136,7 +137,7 @@ public class ForgeWorldEdit { Action action = event.action; switch (action) { case LEFT_CLICK_BLOCK: { - WorldVector pos = new WorldVector(world, event.x, event.y, event.z); + WorldVector pos = new WorldVector(LocalWorldAdapter.wrap(world), event.x, event.y, event.z); if (we.handleBlockLeftClick(player, pos)) { event.setCanceled(true); @@ -147,7 +148,7 @@ public class ForgeWorldEdit { } } case RIGHT_CLICK_BLOCK: { - WorldVector pos = new WorldVector(world, event.x, event.y, event.z); + WorldVector pos = new WorldVector(LocalWorldAdapter.wrap(world), event.x, event.y, event.z); if (we.handleBlockRightClick(player, pos)) { event.setCanceled(true); diff --git a/src/main/java/com/sk89q/worldedit/LocalWorld.java b/src/main/java/com/sk89q/worldedit/LocalWorld.java index 787902173..e10b3f4f8 100644 --- a/src/main/java/com/sk89q/worldedit/LocalWorld.java +++ b/src/main/java/com/sk89q/worldedit/LocalWorld.java @@ -135,7 +135,7 @@ public abstract class LocalWorld extends AbstractWorld { } @Override - public boolean setBlock(Vector pt, BaseBlock block, boolean notifyAdjacent) { + public boolean setBlock(Vector pt, BaseBlock block, boolean notifyAdjacent) throws WorldEditException { boolean successful; // Default implementation will call the old deprecated methods @@ -164,7 +164,7 @@ public abstract class LocalWorld extends AbstractWorld { public abstract boolean copyToWorld(Vector position, BaseBlock block); @Override - public boolean setBlock(Vector pt, BaseBlock block) { + public boolean setBlock(Vector pt, BaseBlock block) throws WorldEditException { return setBlock(pt, block, true); } diff --git a/src/main/java/com/sk89q/worldedit/extent/InputExtent.java b/src/main/java/com/sk89q/worldedit/extent/InputExtent.java index 547cb4acc..f40750720 100644 --- a/src/main/java/com/sk89q/worldedit/extent/InputExtent.java +++ b/src/main/java/com/sk89q/worldedit/extent/InputExtent.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.extent; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.function.pattern.Pattern; diff --git a/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java b/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java index 3d153caa1..3e061de36 100644 --- a/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java +++ b/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java @@ -82,7 +82,7 @@ public class LocalWorldAdapter extends LocalWorld { } @Override - public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) { + public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException { return world.setBlock(position, block, notifyAndLight); } diff --git a/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java b/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java index 453e1bf93..778b4d960 100644 --- a/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java +++ b/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java @@ -44,7 +44,7 @@ public abstract class AbstractWorld implements World { @Override public int getMaxY() { - return 255; + return getMaximumPoint().getBlockY(); } @Override @@ -67,6 +67,44 @@ public abstract class AbstractWorld implements World { new BaseBlock(BlockID.WATER, -1)); } + @Override + public int getBlockType(Vector pt) { + return getLazyBlock(pt).getType(); + } + + @Override + public int getBlockData(Vector pt) { + return getLazyBlock(pt).getData(); + } + + @Override + public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException { + return setBlock(position, block, true); + } + + @Override + public boolean setBlockType(Vector position, int type) { + try { + return setBlock(position, new BaseBlock(type)); + } catch (WorldEditException e) { + throw new RuntimeException(e); + } + } + + @Override + public void setBlockData(Vector position, int data) { + try { + setBlock(position, new BaseBlock(getLazyBlock(position).getId(), data)); + } catch (WorldEditException e) { + throw new RuntimeException(e); + } + } + + @Override + public void setBlockDataFast(Vector position, int data) { + setBlockData(position, data); + } + @SuppressWarnings("deprecation") @Override public boolean setBlockTypeFast(Vector pt, int type) { @@ -132,11 +170,6 @@ public abstract class AbstractWorld implements World { return killMobs(origin, radius, killPets ? KillFlags.PETS : 0); } - @Override - public int killMobs(Vector origin, double radius, int flags) { - return killMobs(origin, (int) radius, (flags & KillFlags.PETS) != 0); - } - @Override public boolean generateTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException { return generateTree(TreeType.TREE, editSession, pt); @@ -212,7 +245,7 @@ public abstract class AbstractWorld implements World { @Override public Vector getMaximumPoint() { - return new Vector(30000000, getMaxY(), 30000000); + return new Vector(30000000, 255, 30000000); } @Override diff --git a/src/main/java/com/sk89q/worldedit/world/World.java b/src/main/java/com/sk89q/worldedit/world/World.java index d6daca3e1..9f69b122e 100644 --- a/src/main/java/com/sk89q/worldedit/world/World.java +++ b/src/main/java/com/sk89q/worldedit/world/World.java @@ -103,7 +103,7 @@ public interface World extends Extent { * @param notifyAndLight true to to notify and light * @return true if the block was successfully set (return value may not be accurate) */ - boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight); + boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException; /** * @deprecated Use {@link #setBlock(Vector, BaseBlock)}