diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java index d944bb206..340fcf282 100644 --- a/favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java @@ -91,7 +91,7 @@ public class Message @SuppressWarnings("deprecation") public void replace() { - snipeData.sendMessage(ChatColor.AQUA + "Replace Material: " + BlockTypes.getFromStateId(snipeData.getReplaceId())); + snipeData.sendMessage(ChatColor.AQUA + "Replace Material: " + BlockTypes.get(snipeData.getReplaceId())); } /** @@ -144,7 +144,7 @@ public class Message @SuppressWarnings("deprecation") public void voxel() { - snipeData.sendMessage(ChatColor.GOLD + "Voxel: " + ChatColor.RED + BlockTypes.getFromStateId(snipeData.getVoxelId())); + snipeData.sendMessage(ChatColor.GOLD + "Voxel: " + ChatColor.RED + BlockTypes.get(snipeData.getVoxelId())); } /** diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java index 0301d54c0..0c471f446 100644 --- a/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java @@ -333,7 +333,7 @@ public class Sniper { return true; } else { int originalData = snipeData.getReplaceData(); - snipeData.setReplaceData(BlockTypes.AIR.getInternalId()); + snipeData.setReplaceData(0); // SniperReplaceMaterialChangedEvent event = new SniperReplaceMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + originalData)), BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData()))); // callEvent(event); snipeData.getVoxelMessage().replaceData(); diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java index 51188ddee..ef8520cc3 100644 --- a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java @@ -72,7 +72,7 @@ public class OverlayBrush extends PerformBrush @SuppressWarnings("deprecation") private boolean isIgnoredBlock(int materialId) { - BlockTypes type = BlockTypes.getFromStateId(materialId); + BlockTypes type = BlockTypes.get(materialId); switch (type) { case WATER: case LAVA: @@ -86,7 +86,7 @@ public class OverlayBrush extends PerformBrush @SuppressWarnings("deprecation") private boolean isOverrideableMaterial(int materialId) { - BlockMaterial mat = BlockTypes.getFromStateId(materialId).getMaterial(); + BlockMaterial mat = BlockTypes.get(materialId).getMaterial(); if (allBlocks && !(mat.isAir())) { return true; diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java index 2374f3c87..d5b00bad1 100644 --- a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java @@ -9,7 +9,6 @@ import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.block.data.BlockData; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -174,7 +173,7 @@ public class PunishBrush extends PerformBrush target = location.clone(); target.add(x, y, z); Player plr = ((Player) entity); - BlockData bd = BukkitAdapter.adapt(BlockState.get(v.getVoxelId() + (v.getPropertyId() << BlockTypes.BIT_OFFSET))); + BlockData bd = BukkitAdapter.adapt(BlockState.getFromInternalId(v.getVoxelId() + (v.getPropertyId() << BlockTypes.BIT_OFFSET))); plr.sendBlockChange(target, bd); } } diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java index 989501e01..a21c6d846 100644 --- a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java @@ -149,7 +149,7 @@ public class ScannerBrush extends Brush @Override protected final void arrow(final SnipeData v) { - this.checkFor = BukkitAdapter.adapt(BlockTypes.getFromStateId(v.getVoxelId())); + this.checkFor = BukkitAdapter.adapt(BlockTypes.get(v.getVoxelId())); this.scan(v, this.getTargetBlock().getFace(this.getLastBlock())); } @@ -157,7 +157,7 @@ public class ScannerBrush extends Brush @Override protected final void powder(final SnipeData v) { - this.checkFor = BukkitAdapter.adapt(BlockTypes.getFromStateId(v.getVoxelId())); + this.checkFor = BukkitAdapter.adapt(BlockTypes.get(v.getVoxelId())); this.scan(v, this.getTargetBlock().getFace(this.getLastBlock())); } diff --git a/worldedit-bukkit/build.gradle b/worldedit-bukkit/build.gradle index caee7b038..ca6b81c2b 100644 --- a/worldedit-bukkit/build.gradle +++ b/worldedit-bukkit/build.gradle @@ -10,7 +10,7 @@ dependencies { compile project(':worldedit-core') compile 'com.sk89q:dummypermscompat:1.8' compile 'com.destroystokyo.paper:paper-api:1.13-R0.1-SNAPSHOT' - compile "org.spigotmc:spigot:1.13-R0.1-SNAPSHOT" + compile "org.spigotmc:spigot-1.13:SNAPSHOT" testCompile 'org.mockito:mockito-core:1.9.0-rc1' compile 'net.milkbowl.vault:VaultAPI:1.5.6' compile 'com.massivecraft:factions:2.8.0' diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/BlockMaterial_1_13.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/BlockMaterial_1_13.java new file mode 100644 index 000000000..30bffb79b --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/BlockMaterial_1_13.java @@ -0,0 +1,147 @@ +package com.boydti.fawe.bukkit.adapter.v1_13_1; + +import com.sk89q.util.ReflectionUtil; +import com.sk89q.worldedit.blocks.BlockMaterial; +import net.minecraft.server.v1_13_R2.*; +import org.bukkit.craftbukkit.v1_13_R2.block.data.CraftBlockData; + +public class BlockMaterial_1_13 implements BlockMaterial { + private final Block block; + private final IBlockData defaultState; + private final Material material; + private final boolean isTranslucent; + private final CraftBlockData craftBlockData; + + public BlockMaterial_1_13(Block block) { + this(block, block.getBlockData()); + } + + public BlockMaterial_1_13(Block block, IBlockData defaultState) { + this.block = block; + this.defaultState = defaultState; + this.material = defaultState.getMaterial(); + this.craftBlockData = CraftBlockData.fromData(defaultState); + this.isTranslucent = ReflectionUtil.getField(Block.class, block, "n"); + } + + public Block getBlock() { + return block; + } + + public IBlockData getState() { + return defaultState; + } + + public CraftBlockData getCraftBlockData() { + return craftBlockData; + } + + public Material getMaterial() { + return material; + } + + @Override + public boolean isAir() { + return defaultState.isAir(); + } + + @Override + public boolean isFullCube() { + return defaultState.g(); + } + + @Override + public boolean isOpaque() { + return material.f(); + } + + @Override + public boolean isPowerSource() { + return defaultState.isPowerSource(); + } + + @Override + public boolean isLiquid() { + return material.isLiquid(); + } + + @Override + public boolean isSolid() { + return material.isBuildable(); + } + + @Override + public float getHardness() { + return block.strength; + } + + @Override + public float getResistance() { + return block.getDurability(); + } + + @Override + public float getSlipperiness() { + return block.n(); + } + + @Override + public int getLightValue() { + return defaultState.e(); + } + + @Override + public int getLightOpacity() { + return isTranslucent() ? 15 : 0; + } + + @Override + public boolean isFragileWhenPushed() { + return material.getPushReaction() == EnumPistonReaction.DESTROY; + } + + @Override + public boolean isUnpushable() { + return material.getPushReaction() == EnumPistonReaction.BLOCK; + } + + @Override + public boolean isTicksRandomly() { + return block.isTicking(defaultState); + } + + @Override + public boolean isMovementBlocker() { + return material.isSolid(); + } + + @Override + public boolean isBurnable() { + return material.isBurnable(); + } + + @Override + public boolean isToolRequired() { + return !material.isAlwaysDestroyable(); + } + + @Override + public boolean isReplacedDuringPlacement() { + return material.isReplaceable(); + } + + @Override + public boolean isTranslucent() { + return isTranslucent; + } + + @Override + public boolean hasContainer() { + return block instanceof ITileEntity; + } + + @Override + public int getMapColor() { + return material.i().rgb; + } +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/Spigot_v1_13_R1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/Spigot_v1_13_R2.java similarity index 73% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/Spigot_v1_13_R1.java rename to worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/Spigot_v1_13_R2.java index 414ecee22..237c67717 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/Spigot_v1_13_R1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/Spigot_v1_13_R2.java @@ -17,80 +17,41 @@ * along with this program. If not, see . */ -package com.boydti.fawe.bukkit.adapter; - -import static com.google.common.base.Preconditions.checkNotNull; +package com.boydti.fawe.bukkit.adapter.v1_13_1; import com.boydti.fawe.Fawe; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; -import com.sk89q.jnbt.ByteArrayTag; -import com.sk89q.jnbt.ByteTag; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.EndTag; -import com.sk89q.jnbt.FloatTag; -import com.sk89q.jnbt.IntArrayTag; -import com.sk89q.jnbt.IntTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.LongTag; -import com.sk89q.jnbt.NBTConstants; -import com.sk89q.jnbt.ShortTag; -import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.*; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.blocks.BlockMaterial; +import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.bukkit.adapter.CachedBukkitAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.registry.state.BooleanProperty; -import com.sk89q.worldedit.registry.state.DirectionalProperty; -import com.sk89q.worldedit.registry.state.EnumProperty; -import com.sk89q.worldedit.registry.state.IntegerProperty; -import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.registry.state.*; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; -import net.minecraft.server.v1_13_R1.BiomeBase; -import net.minecraft.server.v1_13_R1.Block; -import net.minecraft.server.v1_13_R1.BlockPosition; -import net.minecraft.server.v1_13_R1.BlockStateBoolean; -import net.minecraft.server.v1_13_R1.BlockStateDirection; -import net.minecraft.server.v1_13_R1.BlockStateEnum; -import net.minecraft.server.v1_13_R1.BlockStateInteger; -import net.minecraft.server.v1_13_R1.BlockStateList; -import net.minecraft.server.v1_13_R1.Entity; -import net.minecraft.server.v1_13_R1.EntityTypes; -import net.minecraft.server.v1_13_R1.IBlockData; -import net.minecraft.server.v1_13_R1.IBlockState; -import net.minecraft.server.v1_13_R1.INamable; -import net.minecraft.server.v1_13_R1.MinecraftKey; -import net.minecraft.server.v1_13_R1.NBTBase; -import net.minecraft.server.v1_13_R1.NBTTagByte; -import net.minecraft.server.v1_13_R1.NBTTagByteArray; -import net.minecraft.server.v1_13_R1.NBTTagCompound; -import net.minecraft.server.v1_13_R1.NBTTagDouble; -import net.minecraft.server.v1_13_R1.NBTTagEnd; -import net.minecraft.server.v1_13_R1.NBTTagFloat; -import net.minecraft.server.v1_13_R1.NBTTagInt; -import net.minecraft.server.v1_13_R1.NBTTagIntArray; -import net.minecraft.server.v1_13_R1.NBTTagList; -import net.minecraft.server.v1_13_R1.NBTTagLong; -import net.minecraft.server.v1_13_R1.NBTTagShort; -import net.minecraft.server.v1_13_R1.NBTTagString; -import net.minecraft.server.v1_13_R1.TileEntity; -import net.minecraft.server.v1_13_R1.World; -import net.minecraft.server.v1_13_R1.WorldServer; +import com.sk89q.worldedit.world.block.BlockTypes; +import net.minecraft.server.v1_13_R2.*; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Biome; -import org.bukkit.craftbukkit.v1_13_R1.CraftServer; -import org.bukkit.craftbukkit.v1_13_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_13_R1.block.CraftBlock; -import org.bukkit.craftbukkit.v1_13_R1.entity.CraftEntity; +import org.bukkit.block.data.BlockData; +import org.bukkit.craftbukkit.v1_13_R2.CraftChunk; +import org.bukkit.craftbukkit.v1_13_R2.CraftServer; +import org.bukkit.craftbukkit.v1_13_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_13_R2.block.CraftBlock; +import org.bukkit.craftbukkit.v1_13_R2.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import javax.annotation.Nullable; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -98,25 +59,25 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import javax.annotation.Nullable; +import static com.google.common.base.Preconditions.checkNotNull; -public final class Spigot_v1_13_R1 implements BukkitImplAdapter { +public final class Spigot_v1_13_R2 extends CachedBukkitAdapter implements BukkitImplAdapter{ private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); private final Field nbtListTagListField; private final Method nbtCreateTagMethod; + static { + // A simple test + if (!Bukkit.getServer().getClass().getName().endsWith("DummyServer")) CraftServer.class.cast(Bukkit.getServer()); + } + // ------------------------------------------------------------------------ // Code that may break between versions of Minecraft // ------------------------------------------------------------------------ - public Spigot_v1_13_R1() throws NoSuchFieldException, NoSuchMethodException { - // A simple test - if (!Bukkit.getServer().getClass().getName().endsWith("DummyServer")) CraftServer.class.cast(Bukkit.getServer()); - // test between 1.12 and 1.12.1 since md_5 didn't update revision numbers - TileEntity.class.getDeclaredMethod("load", NBTTagCompound.class); - + public Spigot_v1_13_R2() throws NoSuchFieldException, NoSuchMethodException { // The list of tags on an NBTTagList nbtListTagListField = NBTTagList.class.getDeclaredField("list"); nbtListTagListField.setAccessible(true); @@ -194,6 +155,22 @@ public final class Spigot_v1_13_R1 implements BukkitImplAdapter { entity.save(tag); } + @Override + public BlockMaterial getMaterial(BlockType blockType) { + return new BlockMaterial_1_13(getBlock(blockType)); + } + + @Override + public BlockMaterial getMaterial(BlockState state) { + BlockTypes type = state.getBlockType(); + IBlockData bs = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState(); + return new BlockMaterial_1_13(bs.getBlock(), bs); + } + + public Block getBlock(BlockType blockType) { + return IRegistry.BLOCK.getOrDefault(new MinecraftKey(blockType.getNamespace(), blockType.getResource())); + } + // ------------------------------------------------------------------------ // Code that is less likely to break // ------------------------------------------------------------------------ @@ -201,12 +178,12 @@ public final class Spigot_v1_13_R1 implements BukkitImplAdapter { @Override public int getBiomeId(Biome biome) { BiomeBase mcBiome = CraftBlock.biomeToBiomeBase(biome); - return mcBiome != null ? BiomeBase.a(mcBiome) : 0; + return mcBiome != null ? IRegistry.BIOME.a(mcBiome) : 0; } @Override public Biome getBiome(int id) { - BiomeBase mcBiome = BiomeBase.getBiome(id); + BiomeBase mcBiome = IRegistry.BIOME.fromId(id); return CraftBlock.biomeBaseToBiome(mcBiome); // Defaults to ocean if it's an invalid ID } @@ -236,32 +213,62 @@ public final class Spigot_v1_13_R1 implements BukkitImplAdapter { } @Override - public boolean setBlock(Location location, BlockStateHolder state, boolean notifyAndLight) { - checkNotNull(location); - checkNotNull(state); + public boolean isChunkInUse(org.bukkit.Chunk chunk) { + CraftChunk craftChunk = (CraftChunk) chunk; + PlayerChunkMap chunkMap = ((WorldServer) craftChunk.getHandle().getWorld()).getPlayerChunkMap(); + return chunkMap.isChunkInUse(chunk.getX(), chunk.getZ()); + } - CraftWorld craftWorld = ((CraftWorld) location.getWorld()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); + @Override + public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { + CraftChunk craftChunk = (CraftChunk) chunk; + Chunk nmsChunk = craftChunk.getHandle(); + World nmsWorld = nmsChunk.getWorld(); - // Two pass update: - // Note, this will notify blocks BEFORE the tile entity is set - location.getBlock().setBlockData(BukkitAdapter.adapt(state), false); + IBlockData blockData = ((BlockMaterial_1_13) state.getMaterial()).getState(); + ChunkSection[] sections = nmsChunk.getSections(); + int y4 = y >> 4; + ChunkSection section = sections[y4]; - // Copy NBT data for the block - CompoundTag nativeTag = state.getNbtData(); - if (nativeTag != null) { - // We will assume that the tile entity was created for us, - // though we do not do this on the Forge version - TileEntity tileEntity = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z)); - if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) fromNative(nativeTag); - tag.set("x", new NBTTagInt(x)); - tag.set("y", new NBTTagInt(y)); - tag.set("z", new NBTTagInt(z)); - readTagIntoTileEntity(tag, tileEntity); // Load data + IBlockData existing; + if (section == null) { + existing = ((BlockMaterial_1_13) BlockTypes.AIR.getDefaultState().getMaterial()).getState(); + } else { + existing = section.getType(x & 15, y & 15, z & 15); + } + BlockPosition pos = null; + if (existing instanceof TileEntityBlock || blockData instanceof TileEntityBlock) { + pos = new BlockPosition(x, y, z); + nmsWorld.setTypeAndData(pos, blockData, 0); + // remove tile + CompoundTag nativeTag = state.getNbtData(); + if (nativeTag != null) { + // We will assume that the tile entity was created for us, + // though we do not do this on the Forge version + TileEntity tileEntity = nmsWorld.getTileEntity(pos); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) fromNative(nativeTag); + tag.set("x", new NBTTagInt(x)); + tag.set("y", new NBTTagInt(y)); + tag.set("z", new NBTTagInt(z)); + readTagIntoTileEntity(tag, tileEntity); // Load data + } } + } else { + if (existing == blockData) return true; + if (section == null) { + if (blockData.isAir()) return true; + sections[y4] = new ChunkSection(y4 << 4, nmsWorld.worldProvider.g()); + } + if (existing.e() != blockData.e() || existing.getMaterial().f() != blockData.getMaterial().f()) { + nmsChunk.a(pos = new BlockPosition(x, y, z), blockData, false); + } else { + section.setType(x & 15, y & 15, z & 15, blockData); + } + } + if (update) { + if (pos == null) pos = new BlockPosition(x, y, z); + nmsWorld.getMinecraftWorld().notify(pos, existing, blockData, 0); } return true; } @@ -320,8 +327,9 @@ public final class Spigot_v1_13_R1 implements BukkitImplAdapter { public Map getProperties(BlockType blockType) { Block block; try { - block = Block.getByName(blockType.getId()); + block = IRegistry.BLOCK.getOrDefault(new MinecraftKey(blockType.getNamespace(), blockType.getResource())); } catch (Throwable e) { + e.printStackTrace(); return Collections.emptyMap(); } if (block == null) { @@ -484,4 +492,36 @@ public final class Spigot_v1_13_R1 implements BukkitImplAdapter { } } + private int[] idbToStateOrdinal; + + private boolean init() { + if (idbToStateOrdinal != null) return false; + idbToStateOrdinal = new int[Block.REGISTRY_ID.a()]; // size + for (int i = 0; i < idbToStateOrdinal.length; i++) { + BlockState state = BlockTypes.states[i]; + BlockMaterial_1_13 material = (BlockMaterial_1_13) state.getMaterial(); + int id = Block.REGISTRY_ID.getId(material.getState()); + idbToStateOrdinal[id] = state.getOrdinal(); + } + return true; + } + + @Override + public BlockState adapt(BlockData blockData) { + try { + CraftBlockData cbd = ((CraftBlockData) blockData); + IBlockData ibd = cbd.getState(); + int id = Block.REGISTRY_ID.getId(ibd); + return BlockTypes.states[idbToStateOrdinal[id]]; + } catch (NullPointerException e) { + if (init()) return adapt(blockData); + throw e; + } + } + + @Override + public BlockData adapt(BlockStateHolder state) { + BlockMaterial_1_13 material = (BlockMaterial_1_13) state.getMaterial(); + return material.getCraftBlockData(); + } } \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/cui/StructureCUI.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/cui/StructureCUI.java index 37a57d0ff..15a397bf8 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/cui/StructureCUI.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/cui/StructureCUI.java @@ -22,6 +22,8 @@ import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; import java.util.UUID; + +import com.sk89q.worldedit.world.block.BlockState; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -36,7 +38,7 @@ public class StructureCUI extends CUI { private Vector remove; private NbtCompound removeTag; - private int combined; + private BlockState state; public StructureCUI(FawePlayer player) { super(player); @@ -151,7 +153,7 @@ public class StructureCUI extends CUI { map.put("sizeX", NbtFactory.of("sizeX", 0)); sendNbt(remove, removeTag); Location removeLoc = new Location(player.getWorld(), remove.getX(), remove.getY(), remove.getZ()); - player.sendBlockChange(removeLoc, BukkitAdapter.getBlockData(combined)); + player.sendBlockChange(removeLoc, BukkitAdapter.adapt(state)); } remove = null; } @@ -186,7 +188,7 @@ public class StructureCUI extends CUI { Block block = player.getWorld().getBlockAt(x, y, z); remove = new Vector(x, y, z); - combined = BukkitAdapter.adapt(block.getBlockData()).getInternalId(); + state = BukkitAdapter.adapt(block.getBlockData()); removeTag = compound; Location blockLoc = new Location(player.getWorld(), x, y, z); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java index 24fa650d8..a0b1bab0d 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java @@ -96,13 +96,13 @@ public class BukkitChunk_All extends IntFaweChunk { boolean more = true; final BukkitQueue_All parent = (BukkitQueue_All) getParent(); BukkitImplAdapter adapter = BukkitQueue_0.getAdapter(); - final Chunk chunk = getChunk(); Object[] disableResult = parent.disableLighting(chunk); final World world = chunk.getWorld(); int[][] sections = getCombinedIdArrays(); final int bx = getX() << 4; final int bz = getZ() << 4; + boolean update = adapter != null ? adapter.isChunkInUse(chunk) : true; if (layer == -1) { if (adapter != null) { @@ -241,7 +241,7 @@ public class BukkitChunk_All extends IntFaweChunk { mutableLoc.setX(xx); mutableLoc.setY(yy); mutableLoc.setZ(zz); - setBlock(adapter, mutableLoc, combined); + setBlock(adapter, chunk, mutableLoc, combined, update); } continue; default: @@ -249,25 +249,22 @@ public class BukkitChunk_All extends IntFaweChunk { if (type.getMaterial().hasContainer() && adapter != null) { CompoundTag nbt = getTile(x, yy, z); if (nbt != null) { - mutableLoc.setX(xx); - mutableLoc.setY(yy); - mutableLoc.setZ(zz); synchronized (BukkitChunk_All.this) { BaseBlock state = BaseBlock.getFromInternalId(combined, nbt); - adapter.setBlock(mutableLoc, state, false); + adapter.setBlock(chunk, xx, yy, zz, state, update); } continue; } } if (type.getMaterial().isTicksRandomly()) { synchronized (BukkitChunk_All.this) { - setBlock(adapter, mutableLoc, combined); + setBlock(adapter, chunk, mutableLoc, combined, update); } } else { mutableLoc.setX(xx); mutableLoc.setY(yy); mutableLoc.setZ(zz); - setBlock(adapter, mutableLoc, combined); + setBlock(adapter, chunk, mutableLoc, combined, update); } } continue; @@ -292,7 +289,7 @@ public class BukkitChunk_All extends IntFaweChunk { mutableLoc.setX(bx + x); mutableLoc.setY(y); mutableLoc.setZ(bz + z); - setBlock(adapter, mutableLoc, combined); + setBlock(adapter, chunk, mutableLoc, combined, update); } break; default: @@ -316,7 +313,7 @@ public class BukkitChunk_All extends IntFaweChunk { if (tile != null) { synchronized (BukkitChunk_All.this) { BaseBlock state = BaseBlock.getFromInternalId(combined, tile); - adapter.setBlock(new Location(world, bx + x, y, bz + z), state, false); + adapter.setBlock(chunk, bx + x, y, bz + z, state, update); } break; } @@ -326,13 +323,13 @@ public class BukkitChunk_All extends IntFaweChunk { mutableLoc.setX(bx + x); mutableLoc.setY(y); mutableLoc.setZ(bz + z); - setBlock(adapter, mutableLoc, combined); + setBlock(adapter, chunk, mutableLoc, combined, update); } } else { mutableLoc.setX(bx + x); mutableLoc.setY(y); mutableLoc.setZ(bz + z); - setBlock(adapter, mutableLoc, combined); + setBlock(adapter, chunk, mutableLoc, combined, update); } if (light) { parent.disableLighting(disableResult); @@ -357,20 +354,13 @@ public class BukkitChunk_All extends IntFaweChunk { return this; } - public void setBlock(BukkitImplAdapter adapter, Block block, BlockStateHolder state) { + public void setBlock(BukkitImplAdapter adapter, Chunk chunk, Location location, int combinedId, boolean update) { + com.sk89q.worldedit.world.block.BlockState state = com.sk89q.worldedit.world.block.BlockState.getFromInternalId(combinedId); if (adapter != null) { - adapter.setBlock(block.getLocation(), state, false); + adapter.setBlock(chunk, (int) location.getX(), (int) location.getY(), (int) location.getZ(), state, update); } else { + Block block = location.getWorld().getBlockAt(location); block.setBlockData(BukkitAdapter.adapt(state), false); } } - - public void setBlock(BukkitImplAdapter adapter, Location location, int combinedId) { - if (adapter != null) { - adapter.setBlock(location, com.sk89q.worldedit.world.block.BlockState.get(combinedId), false); - } else { - Block block = location.getWorld().getBlockAt(location); - block.setBlockData(BukkitAdapter.getBlockData(combinedId), false); - } - } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java index 5fe5a4daf..3ab621d64 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java @@ -33,7 +33,6 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -392,7 +391,7 @@ public abstract class BukkitQueue_0 extends NMSMa Location loc = new Location(world, bx + localX, y, bz + localZ); for (int i = 0; i < players.length; i++) { if (send[i]) { - ((BukkitPlayer) players[i]).parent.sendBlockChange(loc, BukkitAdapter.adapt(BlockState.get(combined))); + ((BukkitPlayer) players[i]).parent.sendBlockChange(loc, BukkitAdapter.adapt(BlockState.getFromInternalId(combined))); } } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java index d21e64bcd..ba6feb014 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java @@ -1,7 +1,5 @@ package com.boydti.fawe.bukkit.v0; -import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweCache; import com.boydti.fawe.bukkit.util.BukkitReflectionUtils; import com.boydti.fawe.config.Settings; import com.boydti.fawe.example.NullRelighter; @@ -22,7 +20,6 @@ import java.lang.reflect.Method; import java.util.ArrayDeque; import java.util.Map; import java.util.concurrent.ConcurrentMap; -import java.util.function.Supplier; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -32,7 +29,6 @@ import org.bukkit.ChunkSnapshot; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Biome; -import org.bukkit.block.BlockState; import org.bukkit.block.data.BlockData; public class BukkitQueue_All extends BukkitQueue_0 { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java index 8ea8e6255..14873622b 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java @@ -1,6 +1,5 @@ package com.boydti.fawe.bukkit.wrapper; -import com.bekvon.bukkit.residence.commands.tool; import com.boydti.fawe.FaweCache; import com.boydti.fawe.bukkit.wrapper.state.AsyncSign; import com.boydti.fawe.object.FaweQueue; @@ -8,18 +7,14 @@ import com.boydti.fawe.util.TaskManager; import com.sk89q.worldedit.WorldEditException; import java.util.Collection; import java.util.List; -import java.util.function.Supplier; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.world.block.BlockTypes; -import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.block.BlockState; import org.bukkit.block.PistonMoveReaction; import org.bukkit.block.data.BlockData; import org.bukkit.inventory.ItemStack; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java index 5671474b6..4b04493be 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java @@ -1,8 +1,6 @@ package com.boydti.fawe.bukkit.wrapper; -import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweAPI; -import com.boydti.fawe.bukkit.FaweBukkit; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.HasFaweQueue; @@ -16,7 +14,6 @@ import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.world.biome.BaseBiome; import java.io.File; -import java.lang.reflect.Field; import java.util.Collection; import java.util.List; import java.util.Set; @@ -270,9 +267,9 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue @Override public int getHighestBlockYAt(int x, int z) { for (int y = getMaxHeight() - 1; y >= 0; y--) { - if (queue.getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId()) != 0) { - return y; - } + int stateId = queue.getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId()); + BlockTypes type = BlockTypes.getFromStateId(stateId); + if (!type.getMaterial().isAir()) return y; } return 0; } @@ -308,6 +305,11 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue return getChunkAt(block.getX(), block.getZ()); } + @Override + public boolean isChunkGenerated(int x, int z) { + return parent.isChunkGenerated(x, z); + } + @Override public void getChunkAtAsync(int x, int z, ChunkLoadCallback cb) { parent.getChunkAtAsync(x, z, cb); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java index afe2e3180..480dea5cd 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java @@ -19,15 +19,16 @@ package com.sk89q.worldedit.bukkit; -import static com.google.common.base.Preconditions.checkNotNull; - import com.bekvon.bukkit.residence.commands.material; import com.sk89q.worldedit.NotABlockException; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.bukkit.adapter.IBukkitAdapter; +import com.sk89q.worldedit.bukkit.adapter.SimpleBukkitAdapter; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extension.input.ParserContext; -import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockState; @@ -39,347 +40,136 @@ import com.sk89q.worldedit.world.entity.EntityTypes; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.item.ItemTypes; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.List; -import java.util.Objects; +import static com.google.common.base.Preconditions.checkNotNull; /** * Adapts between Bukkit and WorldEdit equivalent objects. */ -public class BukkitAdapter { +public enum BukkitAdapter { + INSTANCE + ; + private final IBukkitAdapter adapter; - private static final ParserContext TO_BLOCK_CONTEXT = new ParserContext(); - - static { - TO_BLOCK_CONTEXT.setRestricted(false); + BukkitAdapter() { + BukkitImplAdapter tmp = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + if (tmp != null) { + this.adapter = tmp; + } else { + this.adapter = new SimpleBukkitAdapter(); + } + } + + private static final IBukkitAdapter getAdapter() { + return INSTANCE.adapter; } - /** - * Checks equality between a WorldEdit BlockType and a Bukkit Material - * - * @param blockType The WorldEdit BlockType - * @param type The Bukkit Material - * @return If they are equal - */ public static boolean equals(BlockType blockType, Material type) { - return Objects.equals(blockType.getId(), type.getKey().toString()); + return getAdapter().equals(blockType, type); } - /** - * Convert any WorldEdit world into an equivalent wrapped Bukkit world. - * - *

If a matching world cannot be found, a {@link RuntimeException} - * will be thrown.

- * - * @param world the world - * @return a wrapped Bukkit world - */ public static BukkitWorld asBukkitWorld(World world) { - if (world instanceof BukkitWorld) { - return (BukkitWorld) world; - } else { - BukkitWorld bukkitWorld = WorldEditPlugin.getInstance().getInternalPlatform().matchWorld(world); - if (bukkitWorld == null) { - throw new RuntimeException("World '" + world.getName() + "' has no matching version in Bukkit"); - } - return bukkitWorld; - } + return getAdapter().asBukkitWorld(world); } - /** - * Create a WorldEdit world from a Bukkit world. - * - * @param world the Bukkit world - * @return a WorldEdit world - */ public static World adapt(org.bukkit.World world) { - checkNotNull(world); - return new BukkitWorld(world); + return getAdapter().adapt(world); } - /** - * Create a Bukkit world from a WorldEdit world. - * - * @param world the WorldEdit world - * @return a Bukkit world - */ public static org.bukkit.World adapt(World world) { - checkNotNull(world); - if (world instanceof BukkitWorld) { - return ((BukkitWorld) world).getWorld(); - } else { - org.bukkit.World match = Bukkit.getServer().getWorld(world.getName()); - if (match != null) { - return match; - } else { - throw new IllegalArgumentException("Can't find a Bukkit world for " + world); - } - } + return getAdapter().adapt(world); } - /** - * Create a WorldEdit location from a Bukkit location. - * - * @param location the Bukkit location - * @return a WorldEdit location - */ public static Location adapt(org.bukkit.Location location) { - checkNotNull(location); - Vector position = asVector(location); - return new com.sk89q.worldedit.util.Location( - adapt(location.getWorld()), - position, - location.getYaw(), - location.getPitch()); + return getAdapter().adapt(location); } - /** - * Create a Bukkit location from a WorldEdit location. - * - * @param location the WorldEdit location - * @return a Bukkit location - */ public static org.bukkit.Location adapt(Location location) { - checkNotNull(location); - Vector position = location.toVector(); - return new org.bukkit.Location( - adapt((World) location.getExtent()), - position.getX(), position.getY(), position.getZ(), - location.getYaw(), - location.getPitch()); + return getAdapter().adapt(location); } - /** - * Create a Bukkit location from a WorldEdit position with a Bukkit world. - * - * @param world the Bukkit world - * @param position the WorldEdit position - * @return a Bukkit location - */ public static org.bukkit.Location adapt(org.bukkit.World world, Vector position) { - checkNotNull(world); - checkNotNull(position); - return new org.bukkit.Location( - world, - position.getX(), position.getY(), position.getZ()); + return getAdapter().adapt(world, position); } - /** - * Create a Bukkit location from a WorldEdit location with a Bukkit world. - * - * @param world the Bukkit world - * @param location the WorldEdit location - * @return a Bukkit location - */ public static org.bukkit.Location adapt(org.bukkit.World world, Location location) { - checkNotNull(world); - checkNotNull(location); - return new org.bukkit.Location( - world, - location.getX(), location.getY(), location.getZ(), - location.getYaw(), - location.getPitch()); + return getAdapter().adapt(world, location); } - /** - * Create a WorldEdit Vector from a Bukkit location. - * - * @param location The Bukkit location - * @return a WorldEdit vector - */ public static Vector asVector(org.bukkit.Location location) { - checkNotNull(location); - return new Vector(location.getX(), location.getY(), location.getZ()); + return getAdapter().asVector(location); } - /** - * Create a WorldEdit entity from a Bukkit entity. - * - * @param entity the Bukkit entity - * @return a WorldEdit entity - */ public static Entity adapt(org.bukkit.entity.Entity entity) { - checkNotNull(entity); - return new BukkitEntity(entity); + return getAdapter().adapt(entity); } - /** - * Create a Bukkit Material form a WorldEdit ItemType - * - * @param itemType The WorldEdit ItemType - * @return The Bukkit Material - */ public static Material adapt(ItemType itemType) { - checkNotNull(itemType); - if (!itemType.getId().startsWith("minecraft:")) { - throw new IllegalArgumentException("Bukkit only supports Minecraft items"); - } - return Material.getMaterial(itemType.getId().substring(10).toUpperCase()); + return getAdapter().adapt(itemType); } - /** - * Create a Bukkit Material form a WorldEdit BlockType - * - * @param blockType The WorldEdit BlockType - * @return The Bukkit Material - */ public static Material adapt(BlockType blockType) { - checkNotNull(blockType); - if (!blockType.getId().startsWith("minecraft:")) { - throw new IllegalArgumentException("Bukkit only supports Minecraft blocks"); - } - String id = blockType.getId().substring(10).toUpperCase(); - return Material.getMaterial(id); + return getAdapter().adapt(blockType); } - /** - * Create a WorldEdit GameMode from a Bukkit one. - * - * @param gameMode Bukkit GameMode - * @return WorldEdit GameMode - */ public static GameMode adapt(org.bukkit.GameMode gameMode) { - checkNotNull(gameMode); - return GameModes.get(gameMode.name().toLowerCase()); + return getAdapter().adapt(gameMode); } - /** - * Create a WorldEdit EntityType from a Bukkit one. - * - * @param entityType Bukkit EntityType - * @return WorldEdit EntityType - */ public static EntityType adapt(org.bukkit.entity.EntityType entityType) { - return EntityTypes.get(entityType.getName().toLowerCase()); + return getAdapter().adapt(entityType); } public static org.bukkit.entity.EntityType adapt(EntityType entityType) { - if (!entityType.getId().startsWith("minecraft:")) { - throw new IllegalArgumentException("Bukkit only supports vanilla entities"); - } - return org.bukkit.entity.EntityType.fromName(entityType.getId().substring(10).toLowerCase()); + return getAdapter().adapt(entityType); } - /** - * Converts a Material to a BlockType - * - * @param material The material - * @return The blocktype - */ public static BlockType asBlockType(Material material) { - checkNotNull(material); - if (!material.isBlock()) { - throw new IllegalArgumentException(material.getKey().toString() + " is not a block!") { - @Override - public synchronized Throwable fillInStackTrace() { - return this; - } - }; - } - return BlockTypes.get(material.getKey().toString()); + return getAdapter().asBlockType(material); } - - - /** - * Converts a Material to a ItemType - * - * @param material The material - * @return The itemtype - */ public static ItemType asItemType(Material material) { - return CachedBukkitAdapter.asItemType(material); + return getAdapter().asItemType(material); } - /** - * Create a WorldEdit BlockStateHolder from a Bukkit BlockData - * - * @param blockData The Bukkit BlockData - * @return The WorldEdit BlockState - */ public static BlockState adapt(BlockData blockData) { - return CachedBukkitAdapter.adapt(blockData); - } - - public static BlockData getBlockData(int combinedId) { - return CachedBukkitAdapter.getBlockData(combinedId); + return getAdapter().adapt(blockData); } public static BlockTypes adapt(Material material) { - return CachedBukkitAdapter.adapt(material); + return getAdapter().adapt(material); } - /** - * Create a Bukkit BlockData from a WorldEdit BlockStateHolder - * - * @param block The WorldEdit BlockStateHolder - * @return The Bukkit BlockData - */ public static BlockData adapt(BlockStateHolder block) { - return CachedBukkitAdapter.adapt(block); + return getAdapter().adapt(block); + } + + public static BlockData getBlockData(int combinedId) { + return getAdapter().getBlockData(combinedId); } - /** - * Create a WorldEdit BlockStateHolder from a Bukkit ItemStack - * - * @param itemStack The Bukkit ItemStack - * @return The WorldEdit BlockState - */ public static BlockState asBlockState(ItemStack itemStack) { - checkNotNull(itemStack); - if (itemStack.getType().isBlock()) { - return adapt(itemStack.getType().createBlockData()); - } else { - throw new NotABlockException(); - } + return getAdapter().asBlockState(itemStack); } - /** - * Create a WorldEdit BaseItemStack from a Bukkit ItemStack - * - * @param itemStack The Bukkit ItemStack - * @return The WorldEdit BaseItemStack - */ public static BaseItemStack adapt(ItemStack itemStack) { - checkNotNull(itemStack); - return new BukkitItemStack(itemStack); + return getAdapter().adapt(itemStack); } - /** - * Create a Bukkit ItemStack from a WorldEdit BaseItemStack - * - * @param item The WorldEdit BaseItemStack - * @return The Bukkit ItemStack - */ public static ItemStack adapt(BaseItemStack item) { - checkNotNull(item); - if (item instanceof BukkitItemStack) return ((BukkitItemStack) item).getBukkitItemStack(); - return new ItemStack(adapt(item.getType()), item.getAmount()); + return getAdapter().adapt(item); } - /** - * Create a WorldEdit Player from a Bukkit Player. - * - * @param player The Bukkit player - * @return The WorldEdit player - */ public static BukkitPlayer adapt(Player player) { - return WorldEditPlugin.getInstance().wrapPlayer(player); + return getAdapter().adapt(player); } - /** - * Create a Bukkit Player from a WorldEdit Player. - * - * @param player The WorldEdit player - * @return The Bukkit player - */ + public static Player adapt(com.sk89q.worldedit.entity.Player player) { - return ((BukkitPlayer) player).getPlayer(); + return getAdapter().adapt(player); } } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java index c6cfc83ce..7795a0022 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java @@ -21,8 +21,10 @@ package com.sk89q.worldedit.bukkit; import com.bekvon.bukkit.residence.commands.material; import com.sk89q.worldedit.blocks.BlockMaterial; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.command.tool.BlockDataCyler; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -42,24 +44,49 @@ import javax.annotation.Nullable; public class BukkitBlockRegistry extends BundledBlockRegistry { - private Map materialMap = new EnumMap<>(Material.class); + private BukkitBlockMaterial[] materialMap; @Nullable @Override public BlockMaterial getMaterial(BlockType blockType) { + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + if (adapter != null) { + BlockMaterial result = adapter.getMaterial(blockType); + if (result != null) return result; + } Material type = BukkitAdapter.adapt(blockType); if (type == null) { if (blockType == BlockTypes.__RESERVED__) return new PassthroughBlockMaterial(super.getMaterial(BlockTypes.AIR)); return new PassthroughBlockMaterial(null); } - return materialMap.computeIfAbsent(type, m -> new BukkitBlockMaterial(BukkitBlockRegistry.super.getMaterial(blockType), m)); + if (materialMap == null) { + materialMap = new BukkitBlockMaterial[Material.values().length]; + } + BukkitBlockMaterial result = materialMap[type.ordinal()]; + if (result == null) { + result = new BukkitBlockMaterial(BukkitBlockRegistry.super.getMaterial(blockType), type); + materialMap[type.ordinal()] = result; + } + return result; + } + + @Nullable + @Override + public BlockMaterial getMaterial(BlockState state) { + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + if (adapter != null) { + BlockMaterial result = adapter.getMaterial(state); + if (result != null) return result; + } + return super.getMaterial(state); } @Nullable @Override public Map getProperties(BlockType blockType) { - if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) { - return WorldEditPlugin.getInstance().getBukkitImplAdapter().getProperties(blockType); + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + if (adapter != null) { + return adapter.getProperties(blockType); } return super.getProperties(blockType); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitEntity.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitEntity.java index 085f6c8b8..0f94a160a 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitEntity.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitEntity.java @@ -36,7 +36,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * An adapter to adapt a Bukkit entity into a WorldEdit one. */ -class BukkitEntity implements Entity { +public class BukkitEntity implements Entity { private final WeakReference entityRef; @@ -45,7 +45,7 @@ class BukkitEntity implements Entity { * * @param entity the entity */ - BukkitEntity(org.bukkit.entity.Entity entity) { + public BukkitEntity(org.bukkit.entity.Entity entity) { checkNotNull(entity); this.entityRef = new WeakReference<>(entity); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 3fd027903..b328523c7 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -445,7 +445,10 @@ public class BukkitWorld extends AbstractWorld { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); if (adapter != null) { try { - return adapter.setBlock(BukkitAdapter.adapt(getWorld(), position), block, notifyAndLight); + int x = position.getBlockX(); + int y = position.getBlockY(); + int z = position.getBlockZ(); + return adapter.setBlock(getWorld().getChunkAt(x >> 4, z >> 4), x, y, z, block, true); } catch (Exception e) { if (block.getNbtData() != null) { logger.warning("Tried to set a corrupt tile entity at " + position.toString()); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/CachedBukkitAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/CachedBukkitAdapter.java deleted file mode 100644 index 08e55644d..000000000 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/CachedBukkitAdapter.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.sk89q.worldedit.bukkit; - -import com.bekvon.bukkit.residence.commands.material; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.item.ItemType; -import com.sk89q.worldedit.world.item.ItemTypes; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.block.data.BlockData; - -import java.util.List; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class CachedBukkitAdapter { - private static final BlockData[][] blockDataCache = new BlockData[BlockTypes.size()][]; - private static final ItemTypes[] itemTypes; - private static final BlockTypes[] blockTypes; - static { - Material[] materials = Material.values(); - itemTypes = new ItemTypes[materials.length]; - blockTypes = new BlockTypes[materials.length]; - for (int i = 0; i < materials.length; i++) { - Material material = materials[i]; - if (material.isLegacy()) continue; - NamespacedKey key = material.getKey(); - String id = key.getNamespace() + ":" + key.getKey(); - if (material.isBlock()) { - blockTypes[i] = BlockTypes.get(id); - } - if (material.isItem()) { - itemTypes[i] = ItemTypes.get(id); - } - } - blockDataCache[0] = new BlockData[] {Material.AIR.createBlockData()}; - } - - /** - * Converts a Material to a ItemType - * - * @param material The material - * @return The itemtype - */ - public static ItemType asItemType(Material material) { - return itemTypes[material.ordinal()]; - } - - /** - * Create a WorldEdit BlockStateHolder from a Bukkit BlockData - * - * @param blockData The Bukkit BlockData - * @return The WorldEdit BlockState - */ - public static BlockState adapt(BlockData blockData) { - checkNotNull(blockData); - Material material = blockData.getMaterial(); - BlockTypes type = blockTypes[material.ordinal()]; - - List propList = type.getProperties(); - if (propList.size() == 0) return type.getDefaultState(); - String properties = blockData.getAsString(); - - return BlockState.get(type, properties, type.getDefaultState().getInternalPropertiesId()); - } - - public static BlockData getBlockData(int combinedId) { - int typeId = combinedId & BlockTypes.BIT_MASK; - BlockData[] dataCache = blockDataCache[typeId]; - if (dataCache == null) { - BlockTypes type = BlockTypes.get(typeId); - blockDataCache[typeId] = dataCache = new BlockData[type.getMaxStateId() + 1]; - } - int propId = combinedId >> BlockTypes.BIT_OFFSET; - BlockData blockData = dataCache[propId]; - if (blockData == null) { - dataCache[propId] = blockData = Bukkit.createBlockData(BlockState.get(combinedId).getAsString()); - } - return blockData; - } - - public static BlockTypes adapt(Material material) { - return blockTypes[material.ordinal()]; - } - - /** - * Create a Bukkit BlockData from a WorldEdit BlockStateHolder - * - * @param block The WorldEdit BlockStateHolder - * @return The Bukkit BlockData - */ - public static BlockData adapt(BlockStateHolder block) { - checkNotNull(block); - int typeId = block.getInternalBlockTypeId(); - BlockData[] dataCache = blockDataCache[typeId]; - if (dataCache == null) { - BlockTypes type = BlockTypes.get(typeId); - blockDataCache[typeId] = dataCache = new BlockData[type.getMaxStateId() + 1]; - } - int propId = block.getInternalPropertiesId(); - BlockData blockData = dataCache[propId]; - if (blockData == null) { - dataCache[propId] = blockData = Bukkit.createBlockData(block.getAsString()); - } - return blockData; - } -} diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index 98fa9247b..8a564907e 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -21,7 +21,7 @@ package com.sk89q.worldedit.bukkit; import com.boydti.fawe.Fawe; import com.boydti.fawe.bukkit.FaweBukkit; -import com.boydti.fawe.bukkit.adapter.Spigot_v1_13_R1; +import com.boydti.fawe.bukkit.adapter.v1_13_1.Spigot_v1_13_R2; import com.boydti.fawe.util.MainUtil; import com.google.common.base.Joiner; import com.sk89q.util.yaml.YAMLProcessor; @@ -33,7 +33,6 @@ import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader; import com.sk89q.worldedit.event.platform.CommandEvent; -import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; @@ -45,7 +44,6 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import org.bukkit.plugin.*; import org.bukkit.plugin.java.JavaPlugin; @@ -277,7 +275,11 @@ public class WorldEditPlugin extends JavaPlugin //implements TabCompleter // Attempt to load a Bukkit adapter BukkitImplLoader adapterLoader = new BukkitImplLoader(); - adapterLoader.addClass(Spigot_v1_13_R1.class); + try { + adapterLoader.addClass(Spigot_v1_13_R2.class); + } catch (Throwable ignore) { + ignore.printStackTrace(); + } try { adapterLoader.addFromPath(getClass().getClassLoader()); @@ -491,7 +493,7 @@ public class WorldEditPlugin extends JavaPlugin //implements TabCompleter return new BukkitCommandSender(this, sender); } - BukkitServerInterface getInternalPlatform() { + public BukkitServerInterface getInternalPlatform() { return server; } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java index 36b298bb2..140873d8b 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java @@ -21,13 +21,14 @@ package com.sk89q.worldedit.bukkit.adapter; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockMaterial; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.world.block.BlockType; -import net.minecraft.server.v1_13_R1.NBTBase; +import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.block.Biome; import org.bukkit.entity.Entity; @@ -39,7 +40,7 @@ import javax.annotation.Nullable; /** * An interface for adapters of various Bukkit implementations. */ -public interface BukkitImplAdapter { +public interface BukkitImplAdapter extends IBukkitAdapter { /** * Get the biome ID for the given biome. @@ -69,15 +70,9 @@ public interface BukkitImplAdapter { */ BlockState getBlock(Location location); - /** - * Set the block at the given location. - * - * @param location the location - * @param state the block - * @param notifyAndLight notify and light if set - * @return true if a block was likely changed - */ - boolean setBlock(Location location, BlockStateHolder state, boolean notifyAndLight); + boolean setBlock(Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update); + + boolean isChunkInUse(Chunk chunk); /** * Get the state for the given entity. @@ -106,6 +101,14 @@ public interface BukkitImplAdapter { */ Map getProperties(BlockType blockType); + default BlockMaterial getMaterial(BlockType blockType) { + return null; + } + + default BlockMaterial getMaterial(BlockState blockState) { + return null; + } + default Tag toNative(T foreign) { return null; } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java index 719e33b06..bd874167c 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java @@ -170,6 +170,7 @@ public class BukkitImplLoader { log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className + "' that is not supposed to be raising this error", e); } catch (Throwable e) { + e.printStackTrace(); if (className.equals(customCandidate)) { log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className + "'", e); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/CachedBukkitAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/CachedBukkitAdapter.java new file mode 100644 index 000000000..fe3009b9f --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/CachedBukkitAdapter.java @@ -0,0 +1,93 @@ +package com.sk89q.worldedit.bukkit.adapter; + +import com.bekvon.bukkit.residence.commands.material; +import com.sk89q.worldedit.bukkit.adapter.IBukkitAdapter; +import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.item.ItemTypes; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.block.data.BlockData; + +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class CachedBukkitAdapter implements IBukkitAdapter { + private int[] itemTypes; + private int[] blockTypes; + + private boolean init() { + if (itemTypes == null) { + Material[] materials = Material.values(); + itemTypes = new int[materials.length]; + blockTypes = new int[materials.length]; + for (int i = 0; i < materials.length; i++) { + Material material = materials[i]; + if (material.isLegacy()) continue; + NamespacedKey key = material.getKey(); + String id = key.getNamespace() + ":" + key.getKey(); + if (material.isBlock()) { + blockTypes[i] = BlockTypes.get(id).getInternalId(); + } + if (material.isItem()) { + itemTypes[i] = ItemTypes.get(id).getInternalId(); + } + } + return true; + } + return false; + } + + /** + * Converts a Material to a ItemType + * + * @param material The material + * @return The itemtype + */ + @Override + public ItemType asItemType(Material material) { + try { + return ItemTypes.values[itemTypes[material.ordinal()]]; + } catch (NullPointerException e) { + if (init()) return asItemType(material); + return ItemTypes.values[itemTypes[material.ordinal()]]; + } + } + + @Override + public BlockTypes adapt(Material material) { + try { + return BlockTypes.values[blockTypes[material.ordinal()]]; + } catch (NullPointerException e) { + if (init()) return adapt(material); + throw e; + } + } + + /** + * Create a WorldEdit BlockStateHolder from a Bukkit BlockData + * + * @param blockData The Bukkit BlockData + * @return The WorldEdit BlockState + */ + @Override + public BlockState adapt(BlockData blockData) { + try { + checkNotNull(blockData); + Material material = blockData.getMaterial(); + BlockTypes type = BlockTypes.getFromStateId(blockTypes[material.ordinal()]); + List propList = type.getProperties(); + if (propList.size() == 0) return type.getDefaultState(); + String properties = blockData.getAsString(); + return BlockState.get(type, properties, type.getDefaultState()); + } catch (NullPointerException e) { + if (init()) return adapt(blockData); + throw e; + } + } +} diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IBukkitAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IBukkitAdapter.java new file mode 100644 index 000000000..1e7e9e014 --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IBukkitAdapter.java @@ -0,0 +1,341 @@ +package com.sk89q.worldedit.bukkit.adapter; + +import com.sk89q.worldedit.NotABlockException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.bukkit.*; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.sk89q.worldedit.world.entity.EntityType; +import com.sk89q.worldedit.world.entity.EntityTypes; +import com.sk89q.worldedit.world.gamemode.GameMode; +import com.sk89q.worldedit.world.gamemode.GameModes; +import com.sk89q.worldedit.world.item.ItemType; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import static com.google.common.base.Preconditions.checkNotNull; + +public interface IBukkitAdapter { + /** + * Checks equality between a WorldEdit BlockType and a Bukkit Material + * + * @param blockType The WorldEdit BlockType + * @param type The Bukkit Material + * @return If they are equal + */ + default boolean equals(BlockType blockType, Material type) { + return blockType == asItemType(type).getBlockType(); + } + + /** + * Convert any WorldEdit world into an equivalent wrapped Bukkit world. + * + *

If a matching world cannot be found, a {@link RuntimeException} + * will be thrown.

+ * + * @param world the world + * @return a wrapped Bukkit world + */ + default BukkitWorld asBukkitWorld(World world) { + if (world instanceof BukkitWorld) { + return (BukkitWorld) world; + } else { + BukkitWorld bukkitWorld = WorldEditPlugin.getInstance().getInternalPlatform().matchWorld(world); + if (bukkitWorld == null) { + throw new RuntimeException("World '" + world.getName() + "' has no matching version in Bukkit"); + } + return bukkitWorld; + } + } + + /** + * Create a WorldEdit world from a Bukkit world. + * + * @param world the Bukkit world + * @return a WorldEdit world + */ + default World adapt(org.bukkit.World world) { + checkNotNull(world); + return new BukkitWorld(world); + } + + /** + * Create a Bukkit world from a WorldEdit world. + * + * @param world the WorldEdit world + * @return a Bukkit world + */ + default org.bukkit.World adapt(World world) { + checkNotNull(world); + if (world instanceof BukkitWorld) { + return ((BukkitWorld) world).getWorld(); + } else { + org.bukkit.World match = Bukkit.getServer().getWorld(world.getName()); + if (match != null) { + return match; + } else { + throw new IllegalArgumentException("Can't find a Bukkit world for " + world); + } + } + } + + /** + * Create a WorldEdit location from a Bukkit location. + * + * @param location the Bukkit location + * @return a WorldEdit location + */ + default Location adapt(org.bukkit.Location location) { + checkNotNull(location); + Vector position = asVector(location); + return new com.sk89q.worldedit.util.Location( + adapt(location.getWorld()), + position, + location.getYaw(), + location.getPitch()); + } + + /** + * Create a Bukkit location from a WorldEdit location. + * + * @param location the WorldEdit location + * @return a Bukkit location + */ + default org.bukkit.Location adapt(Location location) { + checkNotNull(location); + Vector position = location.toVector(); + return new org.bukkit.Location( + adapt((World) location.getExtent()), + position.getX(), position.getY(), position.getZ(), + location.getYaw(), + location.getPitch()); + } + + /** + * Create a Bukkit location from a WorldEdit position with a Bukkit world. + * + * @param world the Bukkit world + * @param position the WorldEdit position + * @return a Bukkit location + */ + default org.bukkit.Location adapt(org.bukkit.World world, Vector position) { + checkNotNull(world); + checkNotNull(position); + return new org.bukkit.Location( + world, + position.getX(), position.getY(), position.getZ()); + } + + /** + * Create a Bukkit location from a WorldEdit location with a Bukkit world. + * + * @param world the Bukkit world + * @param location the WorldEdit location + * @return a Bukkit location + */ + default org.bukkit.Location adapt(org.bukkit.World world, Location location) { + checkNotNull(world); + checkNotNull(location); + return new org.bukkit.Location( + world, + location.getX(), location.getY(), location.getZ(), + location.getYaw(), + location.getPitch()); + } + + /** + * Create a WorldEdit Vector from a Bukkit location. + * + * @param location The Bukkit location + * @return a WorldEdit vector + */ + default Vector asVector(org.bukkit.Location location) { + checkNotNull(location); + return new Vector(location.getX(), location.getY(), location.getZ()); + } + + /** + * Create a WorldEdit entity from a Bukkit entity. + * + * @param entity the Bukkit entity + * @return a WorldEdit entity + */ + default Entity adapt(org.bukkit.entity.Entity entity) { + checkNotNull(entity); + return new BukkitEntity(entity); + } + + /** + * Create a Bukkit Material form a WorldEdit ItemType + * + * @param itemType The WorldEdit ItemType + * @return The Bukkit Material + */ + default Material adapt(ItemType itemType) { + checkNotNull(itemType); + if (!itemType.getId().startsWith("minecraft:")) { + throw new IllegalArgumentException("Bukkit only supports Minecraft items"); + } + return Material.getMaterial(itemType.getId().substring(10).toUpperCase()); + } + + /** + * Create a Bukkit Material form a WorldEdit BlockType + * + * @param blockType The WorldEdit BlockType + * @return The Bukkit Material + */ + default Material adapt(BlockType blockType) { + checkNotNull(blockType); + if (!blockType.getId().startsWith("minecraft:")) { + throw new IllegalArgumentException("Bukkit only supports Minecraft blocks"); + } + String id = blockType.getId().substring(10).toUpperCase(); + return Material.getMaterial(id); + } + + /** + * Create a WorldEdit GameMode from a Bukkit one. + * + * @param gameMode Bukkit GameMode + * @return WorldEdit GameMode + */ + default GameMode adapt(org.bukkit.GameMode gameMode) { + checkNotNull(gameMode); + return GameModes.get(gameMode.name().toLowerCase()); + } + + /** + * Create a WorldEdit EntityType from a Bukkit one. + * + * @param entityType Bukkit EntityType + * @return WorldEdit EntityType + */ + default EntityType adapt(org.bukkit.entity.EntityType entityType) { + return EntityTypes.get(entityType.getName().toLowerCase()); + } + + default org.bukkit.entity.EntityType adapt(EntityType entityType) { + if (!entityType.getId().startsWith("minecraft:")) { + throw new IllegalArgumentException("Bukkit only supports vanilla entities"); + } + return org.bukkit.entity.EntityType.fromName(entityType.getId().substring(10).toLowerCase()); + } + + /** + * Converts a Material to a BlockType + * + * @param material The material + * @return The blocktype + */ + default BlockType asBlockType(Material material) { + checkNotNull(material); + if (!material.isBlock()) { + throw new IllegalArgumentException(material.getKey().toString() + " is not a block!") { + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + }; + } + return BlockTypes.get(material.getKey().toString()); + } + + + + /** + * Converts a Material to a ItemType + * + * @param material The material + * @return The itemtype + */ + ItemType asItemType(Material material); + + /** + * Create a WorldEdit BlockStateHolder from a Bukkit BlockData + * + * @param blockData The Bukkit BlockData + * @return The WorldEdit BlockState + */ + BlockState adapt(BlockData blockData); + + BlockTypes adapt(Material material); + + /** + * Create a Bukkit BlockData from a WorldEdit BlockStateHolder + * + * @param block The WorldEdit BlockStateHolder + * @return The Bukkit BlockData + */ + BlockData adapt(BlockStateHolder block); + + default BlockData getBlockData(int combinedId) { + return adapt(BlockState.getFromInternalId(combinedId)); + } + + /** + * Create a WorldEdit BlockStateHolder from a Bukkit ItemStack + * + * @param itemStack The Bukkit ItemStack + * @return The WorldEdit BlockState + */ + default BlockState asBlockState(ItemStack itemStack) { + checkNotNull(itemStack); + if (itemStack.getType().isBlock()) { + return adapt(itemStack.getType().createBlockData()); + } else { + throw new NotABlockException(); + } + } + + /** + * Create a WorldEdit BaseItemStack from a Bukkit ItemStack + * + * @param itemStack The Bukkit ItemStack + * @return The WorldEdit BaseItemStack + */ + default BaseItemStack adapt(ItemStack itemStack) { + checkNotNull(itemStack); + return new BukkitItemStack(itemStack); + } + + /** + * Create a Bukkit ItemStack from a WorldEdit BaseItemStack + * + * @param item The WorldEdit BaseItemStack + * @return The Bukkit ItemStack + */ + default ItemStack adapt(BaseItemStack item) { + checkNotNull(item); + if (item instanceof BukkitItemStack) return ((BukkitItemStack) item).getBukkitItemStack(); + return new ItemStack(adapt(item.getType()), item.getAmount()); + } + + /** + * Create a WorldEdit Player from a Bukkit Player. + * + * @param player The Bukkit player + * @return The WorldEdit player + */ + default BukkitPlayer adapt(Player player) { + return WorldEditPlugin.getInstance().wrapPlayer(player); + } + /** + * Create a Bukkit Player from a WorldEdit Player. + * + * @param player The WorldEdit player + * @return The Bukkit player + */ + default Player adapt(com.sk89q.worldedit.entity.Player player) { + return ((BukkitPlayer) player).getPlayer(); + } +} diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/SimpleBukkitAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/SimpleBukkitAdapter.java new file mode 100644 index 000000000..19891fa7d --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/SimpleBukkitAdapter.java @@ -0,0 +1,48 @@ +package com.sk89q.worldedit.bukkit.adapter; + +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockTypes; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class SimpleBukkitAdapter extends CachedBukkitAdapter { + private BlockData[][] blockDataCache; + + public boolean init() { + if (blockDataCache != null) return false; + this.blockDataCache = new BlockData[BlockTypes.size()][]; + blockDataCache[0] = new BlockData[] {Material.AIR.createBlockData()}; + return true; + } + + /** + * Create a Bukkit BlockData from a WorldEdit BlockStateHolder + * + * @param block The WorldEdit BlockStateHolder + * @return The Bukkit BlockData + */ + @Override + public BlockData adapt(BlockStateHolder block) { + try { + checkNotNull(block); + int typeId = block.getInternalBlockTypeId(); + BlockData[] dataCache = blockDataCache[typeId]; + if (dataCache == null) { + BlockTypes type = BlockTypes.get(typeId); + blockDataCache[typeId] = dataCache = new BlockData[type.getMaxStateId() + 1]; + } + int propId = block.getInternalPropertiesId(); + BlockData blockData = dataCache[propId]; + if (blockData == null) { + dataCache[propId] = blockData = Bukkit.createBlockData(block.getAsString()); + } + return blockData; + } catch (NullPointerException e) { + if (init()) return adapt(block); + throw e; + } + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/command/Rollback.java b/worldedit-core/src/main/java/com/boydti/fawe/command/Rollback.java index 4a83ef60d..82254d7a8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/command/Rollback.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/command/Rollback.java @@ -86,7 +86,7 @@ public class Rollback extends FaweCommand { int id = entry.getKey(); BlockStateHolder state = null; try { - state = BlockState.get(id); + state = BlockState.getFromInternalId(id); } catch (Throwable ignore) {}; String itemName = state == null ? "#" + id : state.getAsString(); percentString.append(prefix).append(entry.getValue()).append("% ").append(itemName); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java index e96b80ae7..e9359d2c8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java @@ -2,7 +2,6 @@ package com.boydti.fawe.example; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweAPI; -import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweQueue; @@ -17,11 +16,10 @@ import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.blocks.BlockMaterial; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.registry.BundledBlockData; + import java.util.ArrayDeque; import java.util.Collection; import java.util.HashSet; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java index 59d91ff4f..c8118e4d1 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java @@ -17,7 +17,6 @@ import com.boydti.fawe.util.image.ImageViewer; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.*; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.extent.clipboard.Clipboard; @@ -32,7 +31,6 @@ import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BaseBiome; -import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -74,7 +72,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr protected boolean randomVariation = true; protected int biomePriority = 0; protected int waterId = BlockTypes.WATER.getInternalId(); - protected byte bedrockId = 7; + protected int bedrockId = 7; protected boolean modifiedMain = false; @Override @@ -338,7 +336,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr } public void setBedrockId(int bedrockId) { - this.primtives.bedrockId = (byte) bedrockId; + this.primtives.bedrockId = bedrockId; } public void setFloorThickness(int floorThickness) { @@ -354,7 +352,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr } public void setWaterId(int waterId) { - this.primtives.waterId = (byte) waterId; + this.primtives.waterId = waterId; } public void setTextureRandomVariation(boolean randomVariation) { @@ -1024,7 +1022,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr public BlockState getFloor(int x, int z) { int index = z * getWidth() + x; - return BlockState.get(floor.getInt(index)); + return BlockState.getFromInternalId(floor.getInt(index)); } public int getHeight(int x, int z) { @@ -1048,7 +1046,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr @Override public BlockState getLazyBlock(int x, int y, int z) { - return BlockState.get(getCombinedId4Data(x, y, z)); + return BlockState.getFromInternalId(getCombinedId4Data(x, y, z)); } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java index dea975357..ed2e2e8d7 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java @@ -1,6 +1,5 @@ package com.boydti.fawe.object; -import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MainUtil; import com.sk89q.jnbt.CompoundTag; @@ -126,7 +125,7 @@ public abstract class FaweChunk implements Callable { } catch (Throwable e) { MainUtil.handleError(e); } - return BlockState.get(combined); + return BlockState.getFromInternalId(combined); } public int[][] getCombinedIdArrays() { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java index 736305020..cd82ce393 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java @@ -22,9 +22,7 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BaseBiome; -import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import java.io.File; @@ -75,14 +73,15 @@ public interface FaweQueue extends HasFaweQueue, Extent { @Override default BlockState getLazyBlock(int x, int y, int z) { int combinedId4Data = getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId()); - // TODO FIXME optimize get block tiles try { - CompoundTag tile = getTileEntity(x, y, z); - if (tile != null) { - return BaseBlock.getFromInternalId(combinedId4Data, tile); - } else { - return BlockState.get(combinedId4Data); + BlockState state = BlockState.getFromInternalId(combinedId4Data); + if (state.getMaterial().hasContainer()) { + CompoundTag tile = getTileEntity(x, y, z); + if (tile != null) { + return BaseBlock.getFromInternalId(combinedId4Data, tile); + } } + return state; } catch (Throwable e) { MainUtil.handleError(e); return BlockTypes.AIR.getDefaultState(); @@ -275,7 +274,8 @@ public interface FaweQueue extends HasFaweQueue, Extent { mutable.mutZ(zz); for (int y = 0; y <= getMaxY(); y++) { int combined = getCombinedId4Data(xx, y, zz); - BlockType type = BlockTypes.getFromStateId(combined); + BlockState state = BlockState.getFromInternalId(combined); + BlockTypes type = state.getBlockType(); switch (type.getTypeEnum()) { case AIR: case VOID_AIR: @@ -288,7 +288,6 @@ public interface FaweQueue extends HasFaweQueue, Extent { BaseBlock block = BaseBlock.getFromInternalId(combined, tile); onEach.run(mutable, block); } else { - BlockState state = type.withPropertyId(combined >> BlockTypes.BIT_OFFSET); onEach.run(mutable, state); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java index 0833f0524..143115aa1 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Settings; import com.boydti.fawe.database.DBHandler; @@ -23,7 +22,6 @@ import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; import java.io.IOException; import java.util.Iterator; @@ -95,7 +93,7 @@ public class InspectBrush extends BrushTool implements DoubleActionTraceTool { int index = value.getIndex(); long age = System.currentTimeMillis() - value.getBDFile().lastModified(); String ageFormatted = MainUtil.secToTime(age / 1000); - BBC.TOOL_INSPECT_INFO.send(fp, name, BlockState.get(from).getAsString(), BlockState.get(to).getAsString(), ageFormatted); + BBC.TOOL_INSPECT_INFO.send(fp, name, BlockState.getFromInternalId(from).getAsString(), BlockState.getFromInternalId(to).getAsString(), ageFormatted); count.incrementAndGet(); return; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/change/MutableFullBlockChange.java b/worldedit-core/src/main/java/com/boydti/fawe/object/change/MutableFullBlockChange.java index 078cf3c7e..d5596f562 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/change/MutableFullBlockChange.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/change/MutableFullBlockChange.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.change; import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.HasFaweQueue; import com.boydti.fawe.util.ExtentTraverser; @@ -12,7 +11,6 @@ import com.sk89q.worldedit.extent.inventory.BlockBagException; import com.sk89q.worldedit.history.UndoContext; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; public class MutableFullBlockChange implements Change { @@ -68,14 +66,14 @@ public class MutableFullBlockChange implements Change { if (idFrom != idTo) { if (allowFetch && from != 0) { try { - blockBag.fetchPlacedBlock(BlockState.get(from)); + blockBag.fetchPlacedBlock(BlockState.getFromInternalId(from)); } catch (BlockBagException e) { return; } } if (allowStore && to != 0) { try { - blockBag.storeDroppedBlock(BlockState.get(to)); + blockBag.storeDroppedBlock(BlockState.getFromInternalId(to)); } catch (BlockBagException ignored) { } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java index 7f436850a..b74b0e977 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java @@ -20,7 +20,6 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BaseBiome; -import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; @@ -392,7 +391,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable { for (int z = 0; z < length; z++) { for (int x = 0; x < width; x++, pos += 4) { int combinedId = mbb.getInt(pos); - BlockState state = BlockState.get(combinedId); + BlockState state = BlockState.getFromInternalId(combinedId); task.run(x, y, z, state); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java index 97d781601..ba81a3b07 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java @@ -17,7 +17,6 @@ import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.biome.BaseBiome; -import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; import net.jpountz.util.SafeUtils; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/ResizableClipboardBuilder.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/ResizableClipboardBuilder.java index d489fc714..f50625963 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/ResizableClipboardBuilder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/ResizableClipboardBuilder.java @@ -1,21 +1,17 @@ package com.boydti.fawe.object.clipboard; -import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.change.MutableBlockChange; import com.boydti.fawe.object.change.MutableTileChange; import com.boydti.fawe.object.changeset.MemoryOptimizedHistory; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockTypes; import java.util.Iterator; @@ -74,7 +70,7 @@ public class ResizableClipboardBuilder extends MemoryOptimizedHistory { Change change = iter.next(); if (change instanceof MutableBlockChange) { MutableBlockChange blockChange = (MutableBlockChange) change; - BlockStateHolder block = BlockState.get(blockChange.combinedId); + BlockStateHolder block = BlockState.getFromInternalId(blockChange.combinedId); clipboard.setBlock(blockChange.x, blockChange.y, blockChange.z, block); } else if (change instanceof MutableTileChange) { MutableTileChange tileChange = (MutableTileChange) change; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/ExpressionPattern.java b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/ExpressionPattern.java index 5556fd348..8109513c8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/ExpressionPattern.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/ExpressionPattern.java @@ -1,18 +1,14 @@ package com.boydti.fawe.object.pattern; -import com.boydti.fawe.FaweCache; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.runtime.EvaluationException; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; -import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockTypes; import java.io.IOException; @@ -59,7 +55,7 @@ public class ExpressionPattern extends AbstractPattern { ((WorldEditExpressionEnvironment) expression.getEnvironment()).setCurrentBlock(vector); } double combined = expression.evaluate(vector.getX(), vector.getY(), vector.getZ()); - return BlockState.get((int) combined); + return BlockState.getFromInternalId((int) combined); } catch (EvaluationException e) { e.printStackTrace(); return EditSession.nullBlock; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/PropertyPattern.java b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/PropertyPattern.java index 340e03532..2a0888640 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/PropertyPattern.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/pattern/PropertyPattern.java @@ -14,23 +14,28 @@ import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.registry.state.PropertyKey; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import java.util.ArrayList; import java.util.List; public class PropertyPattern extends AbstractExtentPattern { + private final int[] transformed; + public PropertyPattern(Extent extent, String[] properties) { - super(extent); + this(extent); addRegex(".*[" + StringMan.join(properties, ",") + "]"); } public PropertyPattern(Extent extent) { super(extent); + this.transformed = new int[BlockTypes.states.length]; + for (int i = 0; i < transformed.length; i++) { + transformed[i] = i; + } } - private int[][] intSets = new int[BlockTypes.size()][]; - private static final Operator EQUAL = (length, value, index) -> value; private static final Operator PLUS = (length, value, index) -> index + value; private static final Operator MINUS = (length, value, index) -> index - value; @@ -71,20 +76,14 @@ public class PropertyPattern extends AbstractExtentPattern { List values = property.getValues(); int length = values.size(); - int[] states = null; for (int i = 0; i < values.size(); i++) { int result = operator.apply(length, valueInt, i); if (wrap) result = MathMan.wrap(result, 0, length - 1); else result = Math.max(Math.min(result, length - 1), 0); if (result == i) continue; - if (states == null) { - states = intSets[type.getInternalId()]; - if (states == null) { - intSets[type.getInternalId()] = states = new int[type.getMaxStateId() + 1]; - for (int j = 0; j < states.length; j++) states[j] = j; - } - } + int internalId = valueInt + i; + int state = property.modifyIndex(0, i); if (type.getProperties().size() > 1) { ArrayList properties = new ArrayList<>(type.getProperties().size() - 1); @@ -92,27 +91,30 @@ public class PropertyPattern extends AbstractExtentPattern { if (current == property) continue; properties.add(current); } - applyRecursive(property, properties, 0, state, result, states); + applyRecursive(type, property, properties, 0, state, result); } else { - states[i] = result; + int ordinal = type.withStateId(internalId).getOrdinal(); + transformed[ordinal] = type.withStateId(result).getOrdinal(); } } } - private void applyRecursive(AbstractProperty property, List properties, int propertiesIndex, int state, int index, int[] states) { + private void applyRecursive(BlockType type, AbstractProperty property, List properties, int propertiesIndex, int stateId, int index) { AbstractProperty current = (AbstractProperty) properties.get(propertiesIndex); List values = current.getValues(); if (propertiesIndex + 1 < properties.size()) { for (int i = 0; i < values.size(); i++) { - int newState = current.modifyIndex(state, i); - applyRecursive(property, properties, propertiesIndex + 1, newState, index, states); + int newState = current.modifyIndex(stateId, i); + applyRecursive(type, property, properties, propertiesIndex + 1, newState, index); } } else { - //set chest[waterlogged=north] for (int i = 0; i < values.size(); i++) { - int statesIndex = current.modifyIndex(state, i) >> BlockTypes.BIT_OFFSET; - int existing = states[statesIndex] << BlockTypes.BIT_OFFSET; - states[statesIndex] = property.modifyIndex(existing, index) >> BlockTypes.BIT_OFFSET; + int statesIndex = current.modifyIndex(stateId, i) >> BlockTypes.BIT_OFFSET; + BlockState state = BlockState.getFromInternalId(statesIndex); + int existingOrdinal = transformed[state.getOrdinal()]; + int existing = BlockTypes.states[existingOrdinal].getInternalId(); + //states[statesIndex] << BlockTypes.BIT_OFFSET; + transformed[state.getOrdinal()] = property.modifyIndex(existing, index) >> BlockTypes.BIT_OFFSET; } } } @@ -195,16 +197,14 @@ public class PropertyPattern extends AbstractExtentPattern { } public BlockState apply(BlockState block, BlockState orDefault) { - int typeId = block.getInternalBlockTypeId(); - int[] states = intSets[typeId]; - if (states == null) return orDefault; - int propertyId = block.getInternalPropertiesId(); - int newPropertyId = states[propertyId]; - if (newPropertyId == propertyId) return orDefault; - BlockState newState = block.withPropertyId(newPropertyId); - CompoundTag nbt = block.getNbtData(); - if (nbt == null) return newState; - return new BaseBlock(newState, nbt); + int ordinal = block.getOrdinal(); + int newOrdinal = transformed[ordinal]; + if (newOrdinal != ordinal) { + CompoundTag nbt = block.getNbtData(); + BlockState newState = BlockState.getFromOrdinal(newOrdinal); + return nbt != null ? new BaseBlock(newState, nbt) : newState; + } + return orDefault; } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/queue/FaweQueueDelegateExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/queue/FaweQueueDelegateExtent.java index b71e76e28..d3455cf64 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/queue/FaweQueueDelegateExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/queue/FaweQueueDelegateExtent.java @@ -1,6 +1,5 @@ package com.boydti.fawe.object.queue; -import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.exception.FaweException; import com.sk89q.jnbt.CompoundTag; @@ -31,7 +30,7 @@ public class FaweQueueDelegateExtent extends DelegateFaweQueue { @Override public boolean setBlock(int x, int y, int z, int combinedId) { - return setBlock(x, y, z, BlockState.get(combinedId)); + return setBlock(x, y, z, BlockState.getFromInternalId(combinedId)); } @Override @@ -39,7 +38,7 @@ public class FaweQueueDelegateExtent extends DelegateFaweQueue { if (nbt != null) { return setBlock(x, y, z, BaseBlock.getFromInternalId(combinedId, nbt)); } - return setBlock(x, y, z, BlockState.get(combinedId)); + return setBlock(x, y, z, BlockState.getFromInternalId(combinedId)); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java index 39c851431..9d2644734 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java @@ -19,24 +19,17 @@ package com.sk89q.worldedit.blocks; -import com.boydti.fawe.object.string.MutableCharSequence; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.registry.state.AbstractProperty; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.util.command.parametric.Optional; -import com.sk89q.worldedit.world.block.*; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; -import java.util.List; -import java.util.Map; -import java.util.Objects; - import javax.annotation.Nullable; +import java.util.Objects; /** * Represents a "snapshot" of a block with NBT Data. @@ -48,7 +41,7 @@ import javax.annotation.Nullable; * may be missing.

*/ public class BaseBlock extends BlockState { - private BlockState blockState; + private final BlockState blockState; @Nullable protected CompoundTag nbtData; @@ -90,7 +83,7 @@ public class BaseBlock extends BlockState { * @param nbtData NBT data, which may be null */ public BaseBlock(BlockStateHolder state, @Nullable CompoundTag nbtData) { - super(0); + super(); this.blockState = state.toImmutableState(); this.nbtData = nbtData; } @@ -115,7 +108,7 @@ public class BaseBlock extends BlockState { } protected BaseBlock(int internalId, CompoundTag nbtData) { - this(BlockState.get(internalId), nbtData); + this(BlockState.getFromInternalId(internalId), nbtData); } @Deprecated @@ -138,18 +131,6 @@ public class BaseBlock extends BlockState { return blockState; } -// /** -// * Get the block's data value. -// * -// * Broken - do not use -// * -// * @return data value (0-15) -// */ -// @Deprecated -// public int getData() { -// return 0; -// } - @Override public String getNbtId() { CompoundTag nbtData = getNbtData(); @@ -199,9 +180,24 @@ public class BaseBlock extends BlockState { return blockState.getInternalId(); } + @Override + public BlockMaterial getMaterial() { + return blockState.getMaterial(); + } + + @Override + public BlockTypes getBlockType() { + return blockState.getBlockType(); + } + + @Override + public int getOrdinal() { + return blockState.getOrdinal(); + } + @Override public int hashCode() { - return getInternalId(); + return getOrdinal(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java index 2d3a74288..86d5ef06b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java @@ -240,7 +240,7 @@ public class DefaultBlockParser extends InputParser { if (nbt == null) nbt = state.getNbtData(); if (stateString != null) { - state = BlockState.get(state.getBlockType(), "[" + stateString + "]", state.getInternalPropertiesId()); + state = BlockState.get(state.getBlockType(), "[" + stateString + "]", state); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java index be356ddf2..475ee1cbc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormat.java @@ -306,23 +306,6 @@ public enum ClipboardFormat { map.put("height", dimensions.getY()); map.put("length", dimensions.getZ()); map.put("creator", user); - if (clipboard instanceof BlockArrayClipboard) { - FaweClipboard fc = ((BlockArrayClipboard) clipboard).IMP; - final int[] ids = new int[BlockTypes.size()]; - fc.streamCombinedIds(new NBTStreamer.ByteReader() { - @Override - public void run(int index, int byteValue) { - ids[byteValue & BlockTypes.BIT_MASK]++; - } - }); - Map blocks = new HashMap(); - for (int i = 0; i < ids.length; i++) { - if (ids[i] != 0) { - blocks.put(BlockTypes.get(i).getId(), ids[i]); - } - } - map.put("blocks", blocks); - } Gson gson = new Gson(); String json = gson.toJson(map); return MainUtil.upload(Settings.IMP.WEB.ASSETS, false, json, category, null, new RunnableVal() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java index 179889559..30cfb8034 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java @@ -154,7 +154,7 @@ public class BlockTransformExtent extends ResettableExtent { int maskedId = internalId & mask; int newMaskedId = arr[maskedId]; if (newMaskedId != -1) { - return BlockState.get(newMaskedId | (internalId & (~mask))); + return BlockState.getFromInternalId(newMaskedId | (internalId & (~mask))); } newMaskedId = state.getInternalId(); @@ -169,7 +169,7 @@ public class BlockTransformExtent extends ResettableExtent { } } arr[maskedId] = newMaskedId & mask; - return BlockState.get(newMaskedId); + return BlockState.getFromInternalId(newMaskedId); } public final BlockState transformFast(BlockState block) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java index ef6a9e914..15c143f5b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java @@ -1,7 +1,5 @@ package com.sk89q.worldedit.function.mask; -import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.collection.FastBitSet; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.StringMan; @@ -147,7 +145,7 @@ public class BlockMask extends AbstractExtentMask { single = single && numSet == 1; } if (single) - return new SingleBlockStateMask(getExtent(), BlockState.get(and)); + return new SingleBlockStateMask(getExtent(), BlockState.getFromInternalId(and)); return new SingleBlockStateBitMask(getExtent(), and); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKey.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKey.java index 92f645c56..ef6c77d24 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKey.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/state/PropertyKey.java @@ -1,7 +1,9 @@ package com.sk89q.worldedit.registry.state; +import com.boydti.fawe.Fawe; import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.util.ReflectionUtil; +import com.sk89q.worldedit.world.block.BlockTypes; import java.util.HashMap; import java.util.Map; @@ -64,6 +66,7 @@ public enum PropertyKey { UP, WATERLOGGED, WEST, + UNSTABLE, ; @@ -94,12 +97,18 @@ public enum PropertyKey { * @return PropertyKey enum */ public static final PropertyKey getOrCreate(String id) { - String name = id.toUpperCase(); - PropertyKey property; - try { - property = PropertyKey.valueOf(name); - } catch (IllegalArgumentException ignore) { - property = ReflectionUtils.addEnum(PropertyKey.class, name); + PropertyKey property = PropertyKey.get(id); + if (property == null) { + Fawe.debug("Registering property " + id); + property = ReflectionUtils.addEnum(PropertyKey.class, id.toUpperCase()); + if (property.getId() == null) { + try { + ReflectionUtils.setFailsafeFieldValue(PropertyKey.class.getDeclaredField("id"), property, property.name().toLowerCase()); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + keys.put(property.name().toLowerCase(), property); } return property; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index 1a7322756..f06f8fb6b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -28,8 +28,11 @@ import com.google.common.base.Supplier; import com.google.common.collect.Maps; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BlockMaterial; import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.SingleBlockStateMask; @@ -46,15 +49,7 @@ import java.util.stream.Stream; * An immutable class that represents the state a block can be in. */ @SuppressWarnings("unchecked") -public class BlockState implements BlockStateHolder { - - private final int internalId; - - // TODO FIXME have field for BlockType & propertyId (to avoid all the bit shifting / masking) - protected BlockState(int internalId) { - this.internalId = internalId; - } - +public abstract class BlockState implements BlockStateHolder { /** * Returns a temporary BlockState for a given internal id * @param combinedId @@ -62,10 +57,15 @@ public class BlockState implements BlockStateHolder { * @return BlockState */ @Deprecated - public static BlockState get(int combinedId) throws InputParseException { + public static BlockState getFromInternalId(int combinedId) throws InputParseException { return BlockTypes.getFromStateId(combinedId).withStateId(combinedId); } + @Deprecated + public static BlockState getFromOrdinal(int ordinal) { + return BlockTypes.states[ordinal]; + } + /** * Returns a temporary BlockState for a given type and string * @param state String e.g. minecraft:water[level=4] @@ -83,7 +83,7 @@ public class BlockState implements BlockStateHolder { * @return BlockState */ public static BlockState get(@Nullable BlockType type, String state) throws InputParseException { - return get(type, state, 0); + return get(type, state, null); } /** @@ -93,7 +93,7 @@ public class BlockState implements BlockStateHolder { * @param state String e.g. minecraft:water[level=4] * @return BlockState */ - public static BlockState get(@Nullable BlockType type, String state, int propId) throws InputParseException { + public static BlockState get(@Nullable BlockType type, String state, BlockState defaultState) throws InputParseException { int propStrStart = state.indexOf('['); if (type == null) { CharSequence key; @@ -133,8 +133,12 @@ public class BlockState implements BlockStateHolder { return type.withPropertyId(property.getIndexFor(charSequence)); } - - int stateId = type.getInternalId() + (propId << BlockTypes.BIT_OFFSET); + int stateId; + if (defaultState != null) { + stateId = defaultState.getInternalId(); + } else { + stateId = type.getInternalId(); + } int length = state.length(); AbstractProperty property = null; @@ -210,11 +214,6 @@ public class BlockState implements BlockStateHolder { return this; } - @Deprecated - public int getInternalId() { - return this.internalId; - } - @Override public boolean hasNbtData() { return getNbtData() != null; @@ -246,11 +245,6 @@ public class BlockState implements BlockStateHolder { return this.getInternalId() >> BlockTypes.BIT_OFFSET; } - @Override - public final BlockTypes getBlockType() { - return BlockTypes.get(this.getInternalId() & BlockTypes.BIT_MASK); - } - @Deprecated @Override public final int getInternalBlockTypeId() { @@ -260,8 +254,9 @@ public class BlockState implements BlockStateHolder { @Override public BlockState with(final Property property, final V value) { try { + BlockTypes type = getBlockType(); int newState = ((AbstractProperty) property).modify(this.getInternalId(), value); - return newState != this.getInternalId() ? new BlockState(newState) : this; + return newState != this.getInternalId() ? type.withStateId(newState) : this; } catch (ClassCastException e) { throw new IllegalArgumentException("Property not found: " + property); } @@ -270,8 +265,9 @@ public class BlockState implements BlockStateHolder { @Override public BlockState with(final PropertyKey property, final V value) { try { - int newState = ((AbstractProperty) getBlockType().getProperty(property)).modify(this.getInternalId(), value); - return newState != this.getInternalId() ? new BlockState(newState) : this; + BlockTypes type = getBlockType(); + int newState = ((AbstractProperty) type.getProperty(property)).modify(this.getInternalId(), value); + return newState != this.getInternalId() ? type.withStateId(newState) : this; } catch (ClassCastException e) { throw new IllegalArgumentException("Property not found: " + property); } @@ -313,7 +309,7 @@ public class BlockState implements BlockStateHolder { @Override public int hashCode() { - return getInternalId(); + return getOrdinal(); } @Override @@ -324,38 +320,7 @@ public class BlockState implements BlockStateHolder { @Override @Deprecated public boolean equalsFuzzy(BlockStateHolder o) { - try { - return o.getInternalId() == this.getInternalId(); - } catch (ClassCastException e) { - // Shouldn't happen unless something modifies WorldEdit - e.printStackTrace(); - } - if (!getBlockType().equals(o.getBlockType())) { - return false; - } - - Set differingProperties = new HashSet<>(); - for (Object state : o.getStates().keySet()) { - if (getState((Property) state) == null) { - differingProperties.add((Property) state); - } - } - for (Property property : getStates().keySet()) { - if (o.getState(property) == null) { - differingProperties.add(property); - } - } - - for (Property property : getStates().keySet()) { - if (differingProperties.contains(property)) { - continue; - } - if (!Objects.equals(getState(property), o.getState(property))) { - return false; - } - } - - return true; + return o.getOrdinal() == this.getOrdinal(); } @Override @@ -368,32 +333,3 @@ public class BlockState implements BlockStateHolder { return getAsString(); } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java index c58c0b063..a3db4e02f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.world.block; +import com.sk89q.worldedit.blocks.BlockMaterial; import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.Mask; @@ -44,7 +45,9 @@ public interface BlockStateHolder extends FawePatter * @return */ @Deprecated - BlockStateHolder withPropertyId(int propertyId); + default BlockStateHolder withPropertyId(int propertyId) { + return getBlockType().withPropertyId(propertyId); + } /** * Get combined id (legacy uses) @@ -53,12 +56,21 @@ public interface BlockStateHolder extends FawePatter @Deprecated int getInternalId(); + @Deprecated + int getOrdinal(); + + default BlockMaterial getMaterial() { + return getBlockType().getMaterial(); + } + /** * Get type id (legacy uses) * @return */ @Deprecated - int getInternalBlockTypeId(); + default int getInternalBlockTypeId() { + return getBlockType().getInternalId(); + } /** * Get the block data (legacy uses) @@ -129,9 +141,7 @@ public interface BlockStateHolder extends FawePatter if (getStates().isEmpty()) { return this.getBlockType().getId(); } else { - String properties = - getStates().entrySet().stream().map(entry -> entry.getKey().getName() + "=" + entry.getValue().toString().toLowerCase()).collect(Collectors.joining( - ",")); + String properties = getStates().entrySet().stream().map(entry -> entry.getKey().getName() + "=" + entry.getValue().toString().toLowerCase()).collect(Collectors.joining(",")); return this.getBlockType().getId() + "[" + properties + "]"; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateImpl.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateImpl.java new file mode 100644 index 000000000..458526b93 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateImpl.java @@ -0,0 +1,44 @@ +package com.sk89q.worldedit.world.block; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.blocks.BlockMaterial; +import com.sk89q.worldedit.extension.platform.Capability; + +public class BlockStateImpl extends BlockState { + private final int internalId; + private final int ordinal; + private final BlockTypes type; + private BlockMaterial material; + + protected BlockStateImpl(BlockTypes type, int internalId, int ordinal) { + this.type = type; + this.internalId = internalId; + this.ordinal = ordinal; + } + + public BlockMaterial getMaterial() { + if (this.material == null) { + synchronized (this) { + if (this.material == null) { + this.material = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(this); + } + } + } + return material; + } + + @Deprecated + public int getInternalId() { + return this.internalId; + } + + @Override + public int getOrdinal() { + return ordinal; + } + + @Override + public final BlockTypes getBlockType() { + return type; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java index 7fec8deb8..2b1d6d006 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java @@ -29,13 +29,12 @@ import com.sk89q.worldedit.function.pattern.FawePattern; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.registry.state.PropertyKey; import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.LegacyMapper; import javax.annotation.Nullable; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public interface BlockType extends FawePattern, Comparable { @@ -67,6 +66,17 @@ public interface BlockType extends FawePattern, Comparable { */ String getId(); + default String getNamespace() { + String id = getId(); + int i = id.indexOf(':'); + return i == -1 ? "minecraft" : id.substring(0, i); + } + + default String getResource() { + String id = getId(); + return id.substring(id.indexOf(':') + 1); + } + /** * Gets the name of this block, or the ID if the name cannot be found. * @@ -84,7 +94,7 @@ public interface BlockType extends FawePattern, Comparable { @Deprecated default BlockState withPropertyId(int internalPropertiesId) { if (internalPropertiesId == 0) return getDefaultState(); - return BlockState.get(getInternalId() + (internalPropertiesId << BlockTypes.BIT_OFFSET)); + return BlockState.getFromInternalId(getInternalId() + (internalPropertiesId << BlockTypes.BIT_OFFSET)); } /** @@ -93,7 +103,18 @@ public interface BlockType extends FawePattern, Comparable { * @return The properties map */ @Deprecated - Map getPropertyMap(); + default Map getPropertyMap() { + List properties = getProperties(); + if (properties.isEmpty()) { + return Collections.emptyMap(); + } + + Map map = new HashMap<>(properties.size()); + for (Property property : properties) { + map.put(property.getName(), property); + } + return map; + } /** * Gets the properties of this BlockType. @@ -104,7 +125,9 @@ public interface BlockType extends FawePattern, Comparable { List getProperties(); @Deprecated - Set getPropertiesSet(); + default Set getPropertiesSet() { + return new HashSet<>(getProperties()); + } /** * Gets a property by name. @@ -113,11 +136,17 @@ public interface BlockType extends FawePattern, Comparable { * @return The property */ @Deprecated - Property getProperty(String name); + default Property getProperty(String name) { + return getPropertyMap().get(name); + } - boolean hasProperty(PropertyKey key); + default boolean hasProperty(PropertyKey key) { + return getPropertyMap().containsKey(key.getId()); + } - Property getProperty(PropertyKey key); + default Property getProperty(PropertyKey key) { + return getPropertyMap().get(key.getId()); + } /** * Gets the default state of this block type. @@ -141,7 +170,9 @@ public interface BlockType extends FawePattern, Comparable { * @return The item representation */ @Nullable - ItemType getItemType(); + default ItemType getItemType() { + return ItemTypes.get(this.getTypeEnum()); + } /** * Get the material for this BlockType. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java index c94480115..98af0cd99 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java @@ -19,9 +19,13 @@ package com.sk89q.worldedit.world.block; +import com.boydti.fawe.Fawe; import com.boydti.fawe.command.SuggestInputParseException; import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.ReflectionUtils; +import com.boydti.fawe.util.StringMan; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; @@ -38,10 +42,13 @@ import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.LegacyMapper; +import it.unimi.dsi.fastutil.ints.IntCollections; import javax.annotation.Nullable; import java.util.*; +import java.util.function.IntPredicate; import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.stream.Stream; /** @@ -647,6 +654,11 @@ public enum BlockTypes implements BlockType { YELLOW_WOOL, ZOMBIE_HEAD, ZOMBIE_WALL_HEAD, + DEAD_BRAIN_CORAL, + DEAD_BUBBLE_CORAL, + DEAD_FIRE_CORAL, + DEAD_HORN_CORAL, + DEAD_TUBE_CORAL, ; @@ -666,9 +678,9 @@ public enum BlockTypes implements BlockType { private final Set propertiesSet; private final BlockMaterial blockMaterial; private final int permutations; - private BlockState[] states; + private int[] stateOrdinals; - Settings(BlockTypes type, String id, int internalId) { + Settings(BlockTypes type, String id, int internalId, List states) { this.internalId = internalId; String propertyString = null; int propI = id.indexOf('['); @@ -715,10 +727,20 @@ public enum BlockTypes implements BlockType { this.blockMaterial = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(type); this.itemType = ItemTypes.get(type); - if (propertyString != null) { - this.defaultState = new BlockState(parseProperties(propertyString, propertiesMap)); + if (!propertiesList.isEmpty()) { + this.stateOrdinals = generateStateOrdinals(internalId, states.size(), maxInternalStateId, propertiesList); + for (int propId = 0; propId < this.stateOrdinals.length; propId++) { + int ordinal = this.stateOrdinals[propId]; + if (ordinal != -1) { + int stateId = internalId + (propId << BlockTypes.BIT_OFFSET); + states.add(new BlockStateImpl(type, stateId, ordinal)); + } + } + int defaultPropId = parseProperties(propertyString, propertiesMap) >> BlockTypes.BIT_OFFSET; + this.defaultState = states.get(this.stateOrdinals[defaultPropId]); } else { - this.defaultState = new BlockState(internalId); + this.defaultState = new BlockStateImpl(type, internalId, states.size()); + states.add(this.defaultState); } } @@ -744,9 +766,14 @@ public enum BlockTypes implements BlockType { settings = null; } - private void init(String id, int internalId) { + private void init(String id, int internalId, List states) { try { - ReflectionUtils.setFailsafeFieldValue(BlockTypes.class.getDeclaredField("settings"), this, new Settings(this, id, internalId)); + if (getId() == null) { + String name = (name().indexOf(':') == -1 ? "minecraft:" : "") + name().toLowerCase(); + ReflectionUtils.setFailsafeFieldValue(BlockTypes.class.getDeclaredField("id"), this, name); + } + Settings settings = new Settings(this, id, internalId, states); + ReflectionUtils.setFailsafeFieldValue(BlockTypes.class.getDeclaredField("settings"), this, settings); } catch (Throwable e) { e.printStackTrace(); throw new RuntimeException(e); @@ -754,25 +781,38 @@ public enum BlockTypes implements BlockType { } public BlockState withPropertyId(int propertyId) { - if (settings.propertiesArr.length == 0) return settings.defaultState; - BlockState[] tmp = settings.states; - if (tmp == null) { - synchronized (this) { - if ((tmp = settings.states) == null) { - tmp = settings.states = new BlockState[getMaxStateId() + 1]; - tmp[settings.defaultState.getInternalPropertiesId()] = settings.defaultState; - } - } + if (settings.stateOrdinals == null) return settings.defaultState; + return states[settings.stateOrdinals[propertyId]]; + } + + private static int[] generateStateOrdinals(int internalId, int ordinal, int maxStateId, List props) { + if (props.isEmpty()) return null; + int[] result = new int[maxStateId + 1]; + Arrays.fill(result, -1); + int[] state = new int[props.size()]; + int[] sizes = new int[props.size()]; + for (int i = 0; i < props.size(); i++) { + sizes[i] = props.get(i).getValues().size(); } - BlockState state = tmp[propertyId]; - if (state == null) { - synchronized (this) { - if ((state = tmp[propertyId]) == null) { - state = tmp[propertyId] = new BlockState(getInternalId() + (propertyId << BIT_OFFSET)); - } + int index = 0; + outer: + while (true) { + // Create the state + int stateId = internalId; + for (int i = 0; i < state.length; i++) { + stateId = props.get(i).modifyIndex(stateId, state[i]); } + // Map it to the ordinal + result[stateId >> BlockTypes.BIT_OFFSET] = ordinal++; + // Increment the state + while (++state[index] == sizes[index]) { + state[index] = 0; + index++; + if (index == state.length) break outer; + } + index = 0; } - return state; + return result; } /** @@ -781,16 +821,8 @@ public enum BlockTypes implements BlockType { */ @Deprecated public Collection getStates() { - if (this.settings.states == null || this.settings.states.length <= 1) { - return Collections.singletonList(getDefaultState()); - } - ArrayList states = new ArrayList<>(); - for (BlockState state : settings.states) { - if (state != null) { - states.add(state); - } - } - return states; + if (settings.stateOrdinals == null) return Collections.singletonList(getDefaultState()); + return IntStream.of(settings.stateOrdinals).filter(i -> i != -1).mapToObj(i -> states[i]).collect(Collectors.toList()); } @Deprecated @@ -965,7 +997,11 @@ public enum BlockTypes implements BlockType { private static final Map $REGISTRY = new HashMap<>(); private static int $LENGTH; + private static int $STATE_INDEX; + public static final BlockTypes[] values; + public static final BlockState[] states; + private static final Set $NAMESPACES = new LinkedHashSet(); static { @@ -977,7 +1013,10 @@ public enum BlockTypes implements BlockType { $LENGTH = oldValues.length; int size = blockMap.size(); for (BlockTypes type : oldValues) { - if (!blockMap.containsKey(type.getId())) size++; + if (!blockMap.containsKey(type.getId())) { + Fawe.debug("Invalid block registered " + type.getId()); + size++; + } if (type != __RESERVED__) { $REGISTRY.put(type.name().toLowerCase(), type); } @@ -987,13 +1026,14 @@ public enum BlockTypes implements BlockType { BIT_MASK = ((1 << BIT_OFFSET) - 1); LinkedHashSet newValues = new LinkedHashSet<>(Arrays.asList(oldValues)); - for (BlockTypes type : oldValues) { - String block = blockMap.getOrDefault(type.getId(), type.getId()); - BlockTypes registered = register(block); + ArrayList stateList = new ArrayList<>(); + for (String block : blocks) { + BlockTypes registered = register(block, stateList); if (!newValues.contains(registered)) newValues.add(registered); } // Cache the values values = newValues.toArray(new BlockTypes[newValues.size()]); + states = stateList.toArray(new BlockState[stateList.size()]); } catch (Throwable e) { e.printStackTrace(); throw new RuntimeException(e); @@ -1021,7 +1061,7 @@ public enum BlockTypes implements BlockType { ); } - private static BlockTypes register(final String id) { + private static BlockTypes register(final String id, List states) { // Get the enum name (remove namespace if minecraft:) int propStart = id.indexOf('['); String typeName = id.substring(0, propStart == -1 ? id.length() : propStart); @@ -1032,13 +1072,15 @@ public enum BlockTypes implements BlockType { existing = valueOf(enumName.toUpperCase()); } catch (IllegalArgumentException ignore) {} if (existing == null) { + Fawe.debug("Registering block " + enumName); existing = ReflectionUtils.addEnum(BlockTypes.class, enumName); } int internalId = existing.ordinal(); if (internalId == 0 && existing != __RESERVED__) { internalId = $LENGTH++; } - existing.init(id, internalId); + existing.init(id, internalId, states); + // register states if (typeName.startsWith("minecraft:")) $REGISTRY.put(typeName.substring(10), existing); $REGISTRY.put(typeName, existing); String nameSpace = typeName.substring(0, typeName.indexOf(':')); @@ -1068,6 +1110,11 @@ public enum BlockTypes implements BlockType { return values[internalStateId & BIT_MASK]; } + @Deprecated + public static final BlockTypes getFromStateOrdinal(final int internalStateOrdinal) { + return states[internalStateOrdinal].getBlockType(); + } + public static int size() { return values.length; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java index 3f502425d..5c94bfa18 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/entity/EntityTypes.java @@ -145,6 +145,10 @@ public enum EntityTypes implements EntityType { } EntityTypes(String id) { + init(id); + } + + private void init(String id) { if (id == null) id = "minecraft:" + name().toLowerCase(); // If it has no namespace, assume minecraft. else if (!id.contains(":")) { @@ -278,6 +282,9 @@ public enum EntityTypes implements EntityType { existing = ReflectionUtils.addEnum(EntityTypes.class, enumName); } int internalId = existing.ordinal(); + if (existing.id == null) { + existing.init(null); + } if (internalId == 0 && existing != __RESERVED__) { existing.internalId = $LENGTH++; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java index 28c0f5dc6..b6c594683 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/item/ItemTypes.java @@ -839,8 +839,8 @@ public enum ItemTypes implements ItemType { */ private BlockTypes blockType; - private final String id; - private final BaseItem defaultState; + private String id; + private BaseItem defaultState; private int internalId; ItemTypes() { @@ -848,8 +848,12 @@ public enum ItemTypes implements ItemType { } ItemTypes(String id) { + init(id); + } + + private void init(String id) { if (id == null) id = "minecraft:" + name().toLowerCase(); - // If it has no namespace, assume minecraft. + // If it has no namespace, assume minecraft. else if (!id.contains(":")) { id = "minecraft:" + id; } @@ -973,6 +977,9 @@ public enum ItemTypes implements ItemType { existing = ReflectionUtils.addEnum(ItemTypes.class, enumName); } int internalId = existing.ordinal(); + if (existing.id == null) { + existing.init(null); + } if (internalId == 0 && existing != __RESERVED__) { existing.internalId = $LENGTH++; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BiomeRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BiomeRegistry.java index ab3942463..b734298f3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BiomeRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BiomeRegistry.java @@ -54,5 +54,4 @@ public interface BiomeRegistry { */ @Nullable BiomeData getData(BaseBiome biome); - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java index e25fe8f77..50d212a08 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java @@ -21,6 +21,7 @@ package com.sk89q.worldedit.world.registry; import com.sk89q.worldedit.blocks.BlockMaterial; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockType; import java.util.Collection; @@ -44,6 +45,11 @@ public interface BlockRegistry { @Nullable BlockMaterial getMaterial(BlockType blockType); + @Nullable + default BlockMaterial getMaterial(BlockState state) { + return getMaterial(state.getBlockType()); + } + /** * Get an unmodifiable map of states for this block. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java index cb2ecec92..730db8761 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java @@ -26,7 +26,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.registry.state.PropertyKey; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -142,7 +141,7 @@ public class LegacyMapper { public BlockState getBlockFromLegacy(String input) { if (input.startsWith("minecraft:")) input = input.substring(10); - return BlockState.get(blockArr[getCombinedId(input)]); + return BlockState.getFromInternalId(blockArr[getCombinedId(input)]); } @Nullable @@ -181,7 +180,7 @@ public class LegacyMapper { try { int internalId = blockArr[combinedId]; if (internalId == 0) return null; - return BlockState.get(internalId); + return BlockState.getFromInternalId(internalId); } catch (IndexOutOfBoundsException ignore) { return null; } @@ -191,7 +190,7 @@ public class LegacyMapper { extra = extraId4DataToStateId.get(combinedId & 0xFF0); } if (extra != null) { - return BlockState.get(extra); + return BlockState.getFromInternalId(extra); } return null; } diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/legacy.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/legacy.json index d56e52751..7a5f42453 100644 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/legacy.json +++ b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/legacy.json @@ -311,8 +311,8 @@ "44:14": "minecraft:nether_brick_slab[type=top]", "44:15": "minecraft:quartz_slab[type=top]", "45:0": "minecraft:bricks", - "46:0": "minecraft:tnt", - "46:1": "minecraft:tnt", + "46:0": "minecraft:tnt[unstable=false]", + "46:1": "minecraft:tnt[unstable=true]", "47:0": "minecraft:bookshelf", "48:0": "minecraft:mossy_cobblestone", "49:0": "minecraft:obsidian",