From e967ddf39322dd7d0a7223ca902a55918ab6db45 Mon Sep 17 00:00:00 2001 From: Me4502 Date: Thu, 17 Nov 2016 17:58:34 +1000 Subject: [PATCH] Switched to an adapter system. Currently has adapters for 1.10 and 1.11. Currently, due to the small number of changes it's loading the 1.11 adapter for 1.10. This needs fixing. --- .gitignore | 4 +- .../sk89q/worldedit/sponge/SpongeAdapter.java | 3 +- .../worldedit/sponge/SpongeBiomeRegistry.java | 5 +- .../sk89q/worldedit/sponge/SpongeEntity.java | 3 +- .../sponge/SpongePermissionsProvider.java | 20 +- .../worldedit/sponge/SpongePlatform.java | 11 +- .../sk89q/worldedit/sponge/SpongePlayer.java | 7 +- .../sk89q/worldedit/sponge/SpongeWorld.java | 17 +- .../worldedit/sponge/SpongeWorldEdit.java | 50 +++- .../AdapterLoadException.java} | 32 +-- .../sponge/adapter/SpongeImplAdapter.java | 105 ++++++++ .../sponge/adapter/SpongeImplLoader.java | 157 ++++++++++++ .../sk89q/worldedit/sponge/nms/IDHelper.java | 57 ----- .../worldedit/sponge/nms/NBTConverter.java | 237 ------------------ .../sk89q/worldedit/sponge/nms/NMSHelper.java | 50 ---- .../worldedit/sponge/nms/SpongeNMSWorld.java | 169 ------------- .../worldedit/sponge/nms/TileEntityUtils.java | 145 ----------- .../Sponge_1_10_Impl.class | Bin 0 -> 15176 bytes .../Sponge_1_11_Impl.class | Bin 0 -> 15176 bytes 19 files changed, 362 insertions(+), 710 deletions(-) rename worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/{nms/TileEntityBaseBlock.java => adapter/AdapterLoadException.java} (56%) create mode 100644 worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplAdapter.java create mode 100644 worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplLoader.java delete mode 100644 worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/IDHelper.java delete mode 100644 worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/NBTConverter.java delete mode 100644 worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/NMSHelper.java delete mode 100644 worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/SpongeNMSWorld.java delete mode 100644 worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/TileEntityUtils.java create mode 100644 worldedit-sponge/src/main/resources/com.sk89q.worldedit.sponge.adapter.impl/Sponge_1_10_Impl.class create mode 100644 worldedit-sponge/src/main/resources/com.sk89q.worldedit.sponge.adapter.impl/Sponge_1_11_Impl.class diff --git a/.gitignore b/.gitignore index 05139ba48..857f7749d 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,6 @@ out run /dependency-reduced-pom.xml -*-private.sh \ No newline at end of file +*-private.sh + +!impl/*.class \ No newline at end of file diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java index 51723964f..e54f66a84 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.sponge; import com.flowpowered.math.vector.Vector3d; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.sponge.nms.SpongeNMSWorld; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; @@ -31,7 +30,7 @@ final class SpongeAdapter { } public static World adapt(org.spongepowered.api.world.World world) { - return new SpongeNMSWorld(world); + return SpongeWorldEdit.inst().getAdapter().getWorld(world); } public static Location adapt(org.spongepowered.api.world.Location loc, Vector3d rot) { diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBiomeRegistry.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBiomeRegistry.java index 3e5a0a2f1..83974cbdc 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBiomeRegistry.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBiomeRegistry.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.sponge; -import com.sk89q.worldedit.sponge.nms.IDHelper; import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BiomeData; import com.sk89q.worldedit.world.registry.BiomeRegistry; @@ -45,7 +44,7 @@ class SpongeBiomeRegistry implements BiomeRegistry { public List getBiomes() { List list = new ArrayList(); for (BiomeType biome : Sponge.getGame().getRegistry().getAllOf(BiomeType.class)) { - list.add(new BaseBiome(IDHelper.resolve(biome))); + list.add(new BaseBiome(SpongeWorldEdit.inst().getAdapter().resolve(biome))); } return list; } @@ -53,7 +52,7 @@ class SpongeBiomeRegistry implements BiomeRegistry { @Nullable @Override public BiomeData getData(BaseBiome biome) { - return new SpongeBiomeData(IDHelper.resolveBiome(biome.getId())); + return new SpongeBiomeData(SpongeWorldEdit.inst().getAdapter().resolveBiome(biome.getId())); } private static class SpongeBiomeData implements BiomeData { diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntity.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntity.java index b078f7fa2..3f3d8bb79 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntity.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntity.java @@ -24,7 +24,6 @@ import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.metadata.EntityType; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.sponge.nms.NMSHelper; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.NullWorld; import org.spongepowered.api.world.World; @@ -47,7 +46,7 @@ class SpongeEntity implements Entity { public BaseEntity getState() { org.spongepowered.api.entity.Entity entity = entityRef.get(); if (entity != null) { - return NMSHelper.createBaseEntity(entity); + return SpongeWorldEdit.inst().getAdapter().createBaseEntity(entity); } else { return null; } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePermissionsProvider.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePermissionsProvider.java index 62c75d5f3..049bd4ab1 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePermissionsProvider.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePermissionsProvider.java @@ -19,8 +19,14 @@ package com.sk89q.worldedit.sponge; +import org.spongepowered.api.Sponge; import org.spongepowered.api.command.CommandCallable; import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.service.context.Contextual; +import org.spongepowered.api.service.permission.PermissionDescription; +import org.spongepowered.api.service.permission.PermissionService; + +import java.util.stream.Collectors; public class SpongePermissionsProvider { @@ -28,5 +34,17 @@ public class SpongePermissionsProvider { return player.hasPermission(permission); } - public void registerPermission(CommandCallable command, String permission) { } + public void registerPermission(CommandCallable command, String permission) { + Sponge.getGame().getServiceManager().getRegistration(PermissionService.class).ifPresent((permissionService -> { + PermissionDescription.Builder permissionBuilder = permissionService.getProvider().newDescriptionBuilder(SpongeWorldEdit.inst()).get(); + permissionBuilder.id(permission).register(); + })); + } + + public String[] getGroups(Player player) { + PermissionService permissionService = Sponge.getGame().getServiceManager().getRegistration(PermissionService.class).get().getProvider(); + return player.getParents().stream() + .filter(subject -> subject.getContainingCollection().equals(permissionService.getGroupSubjects())) + .map(Contextual::getIdentifier).collect(Collectors.toList()).toArray(new String[0]); + } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java index c409540c2..39c10784b 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java @@ -25,8 +25,6 @@ import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extension.platform.*; import com.sk89q.worldedit.sponge.config.SpongeConfiguration; -import com.sk89q.worldedit.sponge.nms.IDHelper; -import com.sk89q.worldedit.sponge.nms.SpongeNMSWorld; import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.world.World; @@ -61,11 +59,8 @@ class SpongePlatform extends AbstractPlatform implements MultiUserPlatform { Optional optType = Sponge.getRegistry().getType(ItemType.class, name); - if (optType.isPresent()) { - return IDHelper.resolve(optType.get()); - } + return optType.map(itemType -> SpongeWorldEdit.inst().getAdapter().resolve(itemType)).orElse(0); - return 0; } @Override @@ -89,7 +84,7 @@ class SpongePlatform extends AbstractPlatform implements MultiUserPlatform { Collection worlds = Sponge.getServer().getWorlds(); List ret = new ArrayList<>(worlds.size()); for (org.spongepowered.api.world.World world : worlds) { - ret.add(new SpongeNMSWorld(world)); + ret.add(SpongeWorldEdit.inst().getAdapter().getWorld(world)); } return ret; } @@ -113,7 +108,7 @@ class SpongePlatform extends AbstractPlatform implements MultiUserPlatform { } else { for (org.spongepowered.api.world.World ws : Sponge.getServer().getWorlds()) { if (ws.getName().equals(world.getName())) { - return new SpongeNMSWorld(ws); + return SpongeWorldEdit.inst().getAdapter().getWorld(ws); } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java index 798bec47d..76c06a3f4 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java @@ -29,7 +29,6 @@ import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.internal.LocalWorldAdapter; import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.session.SessionKey; -import com.sk89q.worldedit.sponge.nms.IDHelper; import com.sk89q.worldedit.util.Location; import org.spongepowered.api.data.type.HandTypes; import org.spongepowered.api.entity.living.player.Player; @@ -62,7 +61,7 @@ public class SpongePlayer extends AbstractPlayerActor { @Override public int getItemInHand() { Optional is = this.player.getItemInHand(HandTypes.MAIN_HAND); - return is.isPresent() ? IDHelper.resolve(is.get().getItem()) : 0; + return is.isPresent() ? SpongeWorldEdit.inst().getAdapter().resolve(is.get().getItem()) : 0; } @Override @@ -106,7 +105,7 @@ public class SpongePlayer extends AbstractPlayerActor { @Override public void giveItem(int type, int amt) { - this.player.getInventory().offer(ItemStack.of(IDHelper.resolveItem(type), amt)); + this.player.getInventory().offer(ItemStack.of(SpongeWorldEdit.inst().getAdapter().resolveItem(type), amt)); } @Override @@ -160,7 +159,7 @@ public class SpongePlayer extends AbstractPlayerActor { @Override public String[] getGroups() { - return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username); + return SpongeWorldEdit.inst().getPermissionsProvider().getGroups(this.player); } @Override diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java index 71146fefc..3da03bffd 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java @@ -30,7 +30,6 @@ import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.sponge.nms.IDHelper; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.biome.BaseBiome; @@ -142,10 +141,7 @@ public abstract class SpongeWorld extends AbstractWorld { // Create the TileEntity if (block.hasNbtData()) { // Kill the old TileEntity - Optional optTile = world.getTileEntity(pos); - if (optTile.isPresent()) { - applyTileEntityData(optTile.get(), block); - } + world.getTileEntity(pos).ifPresent(tileEntity -> applyTileEntityData(tileEntity, block)); } return true; @@ -177,7 +173,7 @@ public abstract class SpongeWorld extends AbstractWorld { @Override public BaseBiome getBiome(Vector2D position) { checkNotNull(position); - return new BaseBiome(IDHelper.resolve(getWorld().getBiome(position.getBlockX(), 0, position.getBlockZ()))); + return new BaseBiome(SpongeWorldEdit.inst().getAdapter().resolve(getWorld().getBiome(position.getBlockX(), 0, position.getBlockZ()))); } @Override @@ -185,7 +181,7 @@ public abstract class SpongeWorld extends AbstractWorld { checkNotNull(position); checkNotNull(biome); - getWorld().setBiome(position.getBlockX(), 0, position.getBlockZ(), IDHelper.resolveBiome(biome.getId())); + getWorld().setBiome(position.getBlockX(), 0, position.getBlockZ(), SpongeWorldEdit.inst().getAdapter().resolveBiome(biome.getId())); return true; } @@ -214,7 +210,7 @@ public abstract class SpongeWorld extends AbstractWorld { @Override public boolean isValidBlockType(int id) { - return (id == 0) || (IDHelper.resolveBlock(id) != null); + return id == 0 || SpongeWorldEdit.inst().getAdapter().resolveBlock(id) != null; } @Override @@ -231,10 +227,9 @@ public abstract class SpongeWorld extends AbstractWorld { World otherWorld = other.worldRef.get(); World thisWorld = worldRef.get(); return otherWorld != null && thisWorld != null && otherWorld.equals(thisWorld); - } else if (o instanceof com.sk89q.worldedit.world.World) { - return ((com.sk89q.worldedit.world.World) o).getName().equals(getName()); } else { - return false; + return o instanceof com.sk89q.worldedit.world.World + && ((com.sk89q.worldedit.world.World) o).getName().equals(getName()); } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java index 96ec5c2b6..4d46eb4d2 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java @@ -26,11 +26,13 @@ import com.sk89q.worldedit.WorldVector; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.internal.LocalWorldAdapter; +import com.sk89q.worldedit.sponge.adapter.AdapterLoadException; +import com.sk89q.worldedit.sponge.adapter.SpongeImplAdapter; +import com.sk89q.worldedit.sponge.adapter.SpongeImplLoader; import com.sk89q.worldedit.sponge.config.SpongeConfiguration; -import com.sk89q.worldedit.sponge.nms.NMSHelper; -import com.sk89q.worldedit.sponge.nms.SpongeNMSWorld; import org.slf4j.Logger; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.block.BlockType; @@ -50,6 +52,7 @@ import org.spongepowered.api.world.Location; import org.spongepowered.api.world.World; import java.io.File; +import java.io.IOException; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -84,6 +87,7 @@ public class SpongeWorldEdit { } private SpongePlatform platform; + private SpongeImplAdapter spongeAdapter; @Inject private SpongeConfiguration config; @@ -134,6 +138,44 @@ public class SpongeWorldEdit { @Listener public void serverStarted(GameStartedServerEvent event) { WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent()); + + loadAdapter(); + } + + private void loadAdapter() { + WorldEdit worldEdit = WorldEdit.getInstance(); + + // Attempt to load a Sponge adapter + SpongeImplLoader adapterLoader = new SpongeImplLoader(); + + try { + adapterLoader.addFromPath(getClass().getClassLoader()); + } catch (IOException e) { + logger.warn("Failed to search path for Sponge adapters"); + } + + try { + adapterLoader.addFromJar(container.getSource().get().toFile()); + } catch (IOException e) { + logger.warn("Failed to search " + container.getSource().get().toFile() + " for Sponge adapters", e); + } + try { + spongeAdapter = adapterLoader.loadAdapter(); + logger.info("Using " + spongeAdapter.getClass().getCanonicalName() + " as the Sponge adapter"); + } catch (AdapterLoadException e) { + Platform platform = worldEdit.getPlatformManager().queryCapability(Capability.WORLD_EDITING); + if (platform instanceof SpongePlatform) { + logger.warn(e.getMessage()); + } else { + logger.info("WorldEdit could not find a Sponge adapter for this MC version, " + + "but it seems that you have another implementation of WorldEdit installed (" + platform.getPlatformName() + ") " + + "that handles the world editing."); + } + } + } + + public SpongeImplAdapter getAdapter() { + return this.spongeAdapter; } @Listener @@ -199,7 +241,7 @@ public class SpongeWorldEdit { } public static ItemStack toSpongeItemStack(BaseItemStack item) { - return NMSHelper.makeSpongeStack(item); + return inst().getAdapter().makeSpongeStack(item); } /** @@ -249,7 +291,7 @@ public class SpongeWorldEdit { */ public SpongeWorld getWorld(World world) { checkNotNull(world); - return new SpongeNMSWorld(world); + return getAdapter().getWorld(world); } /** diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/TileEntityBaseBlock.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/AdapterLoadException.java similarity index 56% rename from worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/TileEntityBaseBlock.java rename to worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/AdapterLoadException.java index 524d680de..957786d64 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/TileEntityBaseBlock.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/AdapterLoadException.java @@ -17,25 +17,25 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.sponge.nms; +package com.sk89q.worldedit.sponge.adapter; -import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.blocks.TileEntityBlock; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; +/** + * Thrown when no adapter can be found. + */ +public class AdapterLoadException extends Exception { -@Deprecated -public class TileEntityBaseBlock extends BaseBlock implements TileEntityBlock { - - public TileEntityBaseBlock(int type, int data, TileEntity tile) { - super(type, data); - setNbtData(NBTConverter.fromNative(copyNbtData(tile))); + public AdapterLoadException() { } - private static NBTTagCompound copyNbtData(TileEntity tile) { - NBTTagCompound tag = new NBTTagCompound(); - tile.writeToNBT(tag); - return tag; + public AdapterLoadException(String message) { + super(message); } -} \ No newline at end of file + public AdapterLoadException(String message, Throwable cause) { + super(message, cause); + } + + public AdapterLoadException(Throwable cause) { + super(cause); + } +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplAdapter.java new file mode 100644 index 000000000..ecb9179f5 --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplAdapter.java @@ -0,0 +1,105 @@ +package com.sk89q.worldedit.sponge.adapter; + +import com.sk89q.jnbt.*; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.sponge.SpongeWorld; +import net.minecraft.nbt.*; +import org.spongepowered.api.block.BlockType; +import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.item.ItemType; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.world.World; +import org.spongepowered.api.world.biome.BiomeType; + +/** + * An interface for various things that can't be done through the Sponge API. + */ +public interface SpongeImplAdapter { + + /** + * Resolves the numerical ID from this {@link ItemType} + * + * @param type The itemtype + * @return The numerical ID + */ + int resolve(ItemType type); + + /** + * Resolves the numerical ID from this {@link BlockType} + * + * @param type The blocktype + * @return The numerical ID + */ + int resolve(BlockType type); + + /** + * Resolves the numerical ID from this {@link BiomeType} + * + * @param type The biometype + * @return The numerical ID + */ + int resolve(BiomeType type); + + ItemType resolveItem(int intID); + + BlockType resolveBlock(int intID); + + BiomeType resolveBiome(int intID); + + NBTBase toNative(Tag tag); + + NBTTagIntArray toNative(IntArrayTag tag); + + NBTTagList toNative(ListTag tag); + + NBTTagLong toNative(LongTag tag); + + NBTTagString toNative(StringTag tag); + + NBTTagInt toNative(IntTag tag); + + NBTTagByte toNative(ByteTag tag); + + NBTTagByteArray toNative(ByteArrayTag tag); + + NBTTagCompound toNative(CompoundTag tag); + + NBTTagFloat toNative(FloatTag tag); + + NBTTagShort toNative(ShortTag tag); + + NBTTagDouble toNative(DoubleTag tag); + + Tag fromNative(NBTBase other); + + IntArrayTag fromNative(NBTTagIntArray other); + + ListTag fromNative(NBTTagList other); + + EndTag fromNative(NBTTagEnd other); + + LongTag fromNative(NBTTagLong other); + + StringTag fromNative(NBTTagString other); + + IntTag fromNative(NBTTagInt other); + + ByteTag fromNative(NBTTagByte other); + + ByteArrayTag fromNative(NBTTagByteArray other); + + CompoundTag fromNative(NBTTagCompound other); + + FloatTag fromNative(NBTTagFloat other); + + ShortTag fromNative(NBTTagShort other); + + DoubleTag fromNative(NBTTagDouble other); + + BaseEntity createBaseEntity(Entity entity); + + ItemStack makeSpongeStack(BaseItemStack itemStack); + + SpongeWorld getWorld(World world); +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplLoader.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplLoader.java new file mode 100644 index 000000000..adc4d051d --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplLoader.java @@ -0,0 +1,157 @@ +package com.sk89q.worldedit.sponge.adapter; + +import com.sk89q.worldedit.util.io.Closer; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Loads Sponge implementation adapters. + */ +public class SpongeImplLoader { + + private static final Logger log = Logger.getLogger(SpongeImplLoader.class.getCanonicalName()); + private final List adapterCandidates = new ArrayList<>(); + private String customCandidate; + + private static final String SEARCH_PACKAGE = "com.sk89q.worldedit.sponge.adapter.impl"; + private static final String SEARCH_PACKAGE_DOT = SEARCH_PACKAGE + "."; + private static final String SEARCH_PATH = SEARCH_PACKAGE.replace(".", "/"); + private static final String CLASS_SUFFIX = ".class"; + + private static final String LOAD_ERROR_MESSAGE = + "\n**********************************************\n" + + "** This WorldEdit version does not support your version of Sponge.\n" + + "** WorldEdit will not function! \n" + + "** \n" + + "** Please ensure you are running the latest version\n" + + "**********************************************\n"; + + /** + * Create a new instance. + */ + public SpongeImplLoader() { + addDefaults(); + } + + /** + * Add default candidates, such as any defined with + * {@code -Dworldedit.sponge.adapter}. + */ + private void addDefaults() { + String className = System.getProperty("worldedit.sponge.adapter"); + if (className != null) { + customCandidate = className; + adapterCandidates.add(className); + log.log(Level.INFO, "-Dworldedit.sponge.adapter used to add " + className + " to the list of available Sponge adapters"); + } + } + + /** + * Search the given JAR for candidate implementations. + * + * @param file the file + * @throws IOException thrown on I/O error + */ + public void addFromJar(File file) throws IOException { + Closer closer = Closer.create(); + JarFile jar = closer.register(new JarFile(file)); + try { + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry jarEntry = (JarEntry) entries.nextElement(); + + String className = jarEntry.getName().replaceAll("[/\\\\]+", "."); + + if (!className.startsWith(SEARCH_PACKAGE_DOT) || jarEntry.isDirectory() || className.contains("$")) continue; + + int beginIndex = 0; + int endIndex = className.length() - CLASS_SUFFIX.length(); + className = className.substring(beginIndex, endIndex); + adapterCandidates.add(className); + } + } finally { + closer.close(); + } + } + + /** + * Search for classes stored as separate files available via the given + * class loader. + * + * @param classLoader the class loader + * @throws IOException thrown on error + */ + public void addFromPath(ClassLoader classLoader) throws IOException { + Enumeration resources = classLoader.getResources(SEARCH_PATH); + while (resources.hasMoreElements()) { + File file = new File(resources.nextElement().getFile()); + addFromPath(file); + } + } + + /** + * Search for classes stored as separate files available via the given + * path. + * + * @param file the path + */ + private void addFromPath(File file) { + String resource = SEARCH_PACKAGE_DOT + file.getName(); + if (file.isDirectory()) { + File[] files = file.listFiles(); + if (files != null) { + for (File child : files) { + addFromPath(child); + } + } + } else if (resource.endsWith(CLASS_SUFFIX)) { + int beginIndex = 0; + int endIndex = resource.length() - CLASS_SUFFIX.length(); + String className = resource.substring(beginIndex, endIndex); + if (!className.contains("$")) { + adapterCandidates.add(className); + } + } + } + + /** + * Iterate through the list of candidates and load an adapter. + * + * @return an adapter + * @throws AdapterLoadException thrown if no adapter could be found + */ + public SpongeImplAdapter loadAdapter() throws AdapterLoadException { + for (String className : adapterCandidates) { + try { + Class cls = Class.forName(className); + if (SpongeImplAdapter.class.isAssignableFrom(cls)) { + return (SpongeImplAdapter) cls.newInstance(); + } else { + log.log(Level.WARNING, "Failed to load the Sponge adapter class '" + className + + "' because it does not implement " + SpongeImplAdapter.class.getCanonicalName()); + } + } catch (ClassNotFoundException e) { + log.log(Level.WARNING, "Failed to load the Sponge adapter class '" + className + + "' that is not supposed to be missing", e); + } catch (IllegalAccessException e) { + log.log(Level.WARNING, "Failed to load the Sponge adapter class '" + className + + "' that is not supposed to be raising this error", e); + } catch (Throwable e) { + if (className.equals(customCandidate)) { + log.log(Level.WARNING, "Failed to load the Sponge adapter class '" + className + "'", e); + } + } + } + + throw new AdapterLoadException(LOAD_ERROR_MESSAGE); + } +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/IDHelper.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/IDHelper.java deleted file mode 100644 index d607bfb64..000000000 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/IDHelper.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.sponge.nms; - -import net.minecraft.block.Block; -import net.minecraft.item.Item; -import net.minecraft.world.biome.Biome; -import org.spongepowered.api.block.BlockType; -import org.spongepowered.api.item.ItemType; -import org.spongepowered.api.world.biome.BiomeType; - -@Deprecated -public final class IDHelper { - - private IDHelper() { } - - public static int resolve(ItemType type) { - return Item.getIdFromItem((Item) type); - } - - public static int resolve(BlockType type) { - return Block.getIdFromBlock((Block) type); - } - - public static int resolve(BiomeType type) { - return Biome.getIdForBiome((Biome) type); - } - - public static ItemType resolveItem(int intID) { - return (ItemType) Item.getItemById(intID); - } - - public static BlockType resolveBlock(int intID) { - return (BlockType) Block.getBlockById(intID); - } - - public static BiomeType resolveBiome(int intID) { - return (BiomeType) Biome.getBiome(intID); - } -} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/NBTConverter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/NBTConverter.java deleted file mode 100644 index 48e8b5da0..000000000 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/NBTConverter.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.sponge.nms; - -import com.sk89q.jnbt.*; -import net.minecraft.nbt.*; - -import java.util.*; -import java.util.Map.Entry; - -/** - * Converts between JNBT and Minecraft NBT classes. - */ -@Deprecated -final class NBTConverter { - - private NBTConverter() { - } - - public static NBTBase toNative(Tag tag) { - if (tag instanceof IntArrayTag) { - return toNative((IntArrayTag) tag); - - } else if (tag instanceof ListTag) { - return toNative((ListTag) tag); - - } else if (tag instanceof LongTag) { - return toNative((LongTag) tag); - - } else if (tag instanceof StringTag) { - return toNative((StringTag) tag); - - } else if (tag instanceof IntTag) { - return toNative((IntTag) tag); - - } else if (tag instanceof ByteTag) { - return toNative((ByteTag) tag); - - } else if (tag instanceof ByteArrayTag) { - return toNative((ByteArrayTag) tag); - - } else if (tag instanceof CompoundTag) { - return toNative((CompoundTag) tag); - - } else if (tag instanceof FloatTag) { - return toNative((FloatTag) tag); - - } else if (tag instanceof ShortTag) { - return toNative((ShortTag) tag); - - } else if (tag instanceof DoubleTag) { - return toNative((DoubleTag) tag); - } else { - throw new IllegalArgumentException("Can't convert tag of type " + tag.getClass().getCanonicalName()); - } - } - - public static NBTTagIntArray toNative(IntArrayTag tag) { - int[] value = tag.getValue(); - return new NBTTagIntArray(Arrays.copyOf(value, value.length)); - } - - public static NBTTagList toNative(ListTag tag) { - NBTTagList list = new NBTTagList(); - for (Tag child : tag.getValue()) { - if (child instanceof EndTag) { - continue; - } - list.appendTag(toNative(child)); - } - return list; - } - - public static NBTTagLong toNative(LongTag tag) { - return new NBTTagLong(tag.getValue()); - } - - public static NBTTagString toNative(StringTag tag) { - return new NBTTagString(tag.getValue()); - } - - public static NBTTagInt toNative(IntTag tag) { - return new NBTTagInt(tag.getValue()); - } - - public static NBTTagByte toNative(ByteTag tag) { - return new NBTTagByte(tag.getValue()); - } - - public static NBTTagByteArray toNative(ByteArrayTag tag) { - byte[] value = tag.getValue(); - return new NBTTagByteArray(Arrays.copyOf(value, value.length)); - } - - public static NBTTagCompound toNative(CompoundTag tag) { - NBTTagCompound compound = new NBTTagCompound(); - for (Entry child : tag.getValue().entrySet()) { - compound.setTag(child.getKey(), toNative(child.getValue())); - } - return compound; - } - - public static NBTTagFloat toNative(FloatTag tag) { - return new NBTTagFloat(tag.getValue()); - } - - public static NBTTagShort toNative(ShortTag tag) { - return new NBTTagShort(tag.getValue()); - } - - public static NBTTagDouble toNative(DoubleTag tag) { - return new NBTTagDouble(tag.getValue()); - } - - public static Tag fromNative(NBTBase other) { - if (other instanceof NBTTagIntArray) { - return fromNative((NBTTagIntArray) other); - - } else if (other instanceof NBTTagList) { - return fromNative((NBTTagList) other); - - } else if (other instanceof NBTTagEnd) { - return fromNative((NBTTagEnd) other); - - } else if (other instanceof NBTTagLong) { - return fromNative((NBTTagLong) other); - - } else if (other instanceof NBTTagString) { - return fromNative((NBTTagString) other); - - } else if (other instanceof NBTTagInt) { - return fromNative((NBTTagInt) other); - - } else if (other instanceof NBTTagByte) { - return fromNative((NBTTagByte) other); - - } else if (other instanceof NBTTagByteArray) { - return fromNative((NBTTagByteArray) other); - - } else if (other instanceof NBTTagCompound) { - return fromNative((NBTTagCompound) other); - - } else if (other instanceof NBTTagFloat) { - return fromNative((NBTTagFloat) other); - - } else if (other instanceof NBTTagShort) { - return fromNative((NBTTagShort) other); - - } else if (other instanceof NBTTagDouble) { - return fromNative((NBTTagDouble) other); - } else { - throw new IllegalArgumentException("Can't convert other of type " + other.getClass().getCanonicalName()); - } - } - - public static IntArrayTag fromNative(NBTTagIntArray other) { - int[] value = other.getIntArray(); - return new IntArrayTag(Arrays.copyOf(value, value.length)); - } - - public static ListTag fromNative(NBTTagList other) { - other = (NBTTagList) other.copy(); - List list = new ArrayList(); - Class listClass = StringTag.class; - int tags = other.tagCount(); - for (int i = 0; i < tags; i++) { - Tag child = fromNative(other.removeTag(0)); - list.add(child); - listClass = child.getClass(); - } - return new ListTag(listClass, list); - } - - public static EndTag fromNative(NBTTagEnd other) { - return new EndTag(); - } - - public static LongTag fromNative(NBTTagLong other) { - return new LongTag(other.getLong()); - } - - public static StringTag fromNative(NBTTagString other) { - return new StringTag(other.getString()); - } - - public static IntTag fromNative(NBTTagInt other) { - return new IntTag(other.getInt()); - } - - public static ByteTag fromNative(NBTTagByte other) { - return new ByteTag(other.getByte()); - } - - public static ByteArrayTag fromNative(NBTTagByteArray other) { - byte[] value = other.getByteArray(); - return new ByteArrayTag(Arrays.copyOf(value, value.length)); - } - - public static CompoundTag fromNative(NBTTagCompound other) { - @SuppressWarnings("unchecked") Set tags = other.getKeySet(); - Map map = new HashMap(); - for (String tagName : tags) { - map.put(tagName, fromNative(other.getTag(tagName))); - } - return new CompoundTag(map); - } - - public static FloatTag fromNative(NBTTagFloat other) { - return new FloatTag(other.getFloat()); - } - - public static ShortTag fromNative(NBTTagShort other) { - return new ShortTag(other.getShort()); - } - - public static DoubleTag fromNative(NBTTagDouble other) { - return new DoubleTag(other.getDouble()); - } - -} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/NMSHelper.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/NMSHelper.java deleted file mode 100644 index 7abd7588b..000000000 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/NMSHelper.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.sponge.nms; - -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.entity.BaseEntity; -import net.minecraft.item.Item; -import net.minecraft.nbt.NBTTagCompound; -import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.item.inventory.ItemStack; - -import java.util.Map; - -@Deprecated -public final class NMSHelper { - - private NMSHelper() { } - - public static ItemStack makeSpongeStack(BaseItemStack itemStack) { - net.minecraft.item.ItemStack newStack = new net.minecraft.item.ItemStack(Item.getItemById(itemStack.getType()), itemStack.getAmount(), itemStack.getData()); - for (Map.Entry entry : itemStack.getEnchantments().entrySet()) { - newStack.addEnchantment(net.minecraft.enchantment.Enchantment.getEnchantmentByID(entry.getKey()), entry.getValue()); - } - return (ItemStack) (Object) newStack; - } - - public static BaseEntity createBaseEntity(Entity entity) { - String id = entity.getType().getId(); - NBTTagCompound tag = new NBTTagCompound(); - ((net.minecraft.entity.Entity) entity).writeToNBT(tag); - return new BaseEntity(id, NBTConverter.fromNative(tag)); - } -} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/SpongeNMSWorld.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/SpongeNMSWorld.java deleted file mode 100644 index bb3408e15..000000000 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/SpongeNMSWorld.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.sponge.nms; - -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.blocks.LazyBlock; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.sponge.SpongeWorld; -import com.sk89q.worldedit.util.TreeGenerator; -import net.minecraft.block.*; -import net.minecraft.block.state.IBlockState; -import net.minecraft.init.Blocks; -import net.minecraft.inventory.IInventory; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagInt; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.gen.feature.*; -import org.spongepowered.api.block.BlockState; -import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.world.Location; -import org.spongepowered.api.world.World; - -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkNotNull; - -@Deprecated -public class SpongeNMSWorld extends SpongeWorld { - - private static final IBlockState JUNGLE_LOG = Blocks.LOG.getDefaultState().withProperty(BlockOldLog.VARIANT, BlockPlanks.EnumType.JUNGLE); - private static final IBlockState JUNGLE_LEAF = Blocks.LEAVES.getDefaultState().withProperty(BlockOldLeaf.VARIANT, BlockPlanks.EnumType.JUNGLE).withProperty(BlockLeaves.CHECK_DECAY, Boolean.valueOf(false)); - private static final IBlockState JUNGLE_SHRUB = Blocks.LEAVES.getDefaultState().withProperty(BlockOldLeaf.VARIANT, BlockPlanks.EnumType.OAK).withProperty(BlockLeaves.CHECK_DECAY, Boolean.valueOf(false)); - - /** - * Construct a new world. - * - * @param world the world - */ - public SpongeNMSWorld(World world) { - super(world); - } - - @Override - protected BlockState getBlockState(BaseBlock block) { - return (BlockState) Block.getBlockById(block.getId()).getStateFromMeta(block.getData()); - } - - private NBTTagCompound updateForSet(NBTTagCompound tag, Vector position) { - checkNotNull(tag); - checkNotNull(position); - - tag.setTag("x", new NBTTagInt(position.getBlockX())); - tag.setTag("y", new NBTTagInt(position.getBlockY())); - tag.setTag("z", new NBTTagInt(position.getBlockZ())); - - return tag; - } - - @Override - protected void applyTileEntityData(org.spongepowered.api.block.tileentity.TileEntity entity, BaseBlock block) { - NBTTagCompound tag = NBTConverter.toNative(block.getNbtData()); - - Location loc = entity.getLocation(); - - updateForSet(tag, new Vector(loc.getX(), loc.getY(), loc.getZ())); - ((TileEntity) entity).readFromNBT(tag); - } - - @Override - protected void applyEntityData(Entity entity, BaseEntity data) { - NBTTagCompound tag = NBTConverter.toNative(data.getNbtData()); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.removeTag(name); - } - ((net.minecraft.entity.Entity) entity).readFromNBT(tag); - } - - @Override - public boolean clearContainerBlockContents(Vector position) { - BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - TileEntity tile =((net.minecraft.world.World) getWorld()).getTileEntity(pos); - if (tile instanceof IInventory) { - IInventory inv = (IInventory) tile; - int size = inv.getSizeInventory(); - for (int i = 0; i < size; i++) { - inv.setInventorySlotContents(i, null); - } - return true; - } - return false; - } - - @Nullable - private static WorldGenerator createWorldGenerator(TreeGenerator.TreeType type) { - switch (type) { - case TREE: return new WorldGenTrees(true); - case BIG_TREE: return new WorldGenBigTree(true); - case REDWOOD: return new WorldGenTaiga2(true); - case TALL_REDWOOD: return new WorldGenTaiga1(); - case BIRCH: return new WorldGenBirchTree(true, false); - case JUNGLE: return new WorldGenMegaJungle(true, 10, 20, JUNGLE_LOG, JUNGLE_LEAF); - case SMALL_JUNGLE: return new WorldGenTrees(true, 4 + random.nextInt(7), JUNGLE_LOG, JUNGLE_LEAF, false); - case SHORT_JUNGLE: return new WorldGenTrees(true, 4 + random.nextInt(7), JUNGLE_LOG, JUNGLE_LEAF, true); - case JUNGLE_BUSH: return new WorldGenShrub(JUNGLE_LOG, JUNGLE_SHRUB); - case RED_MUSHROOM: return new WorldGenBigMushroom(Blocks.BROWN_MUSHROOM_BLOCK); - case BROWN_MUSHROOM: return new WorldGenBigMushroom(Blocks.RED_MUSHROOM_BLOCK); - case SWAMP: return new WorldGenSwamp(); - case ACACIA: return new WorldGenSavannaTree(true); - case DARK_OAK: return new WorldGenCanopyTree(true); - case MEGA_REDWOOD: return new WorldGenMegaPineTree(false, random.nextBoolean()); - case TALL_BIRCH: return new WorldGenBirchTree(true, true); - case RANDOM: - case PINE: - case RANDOM_REDWOOD: - default: - return null; - } - } - - @Override - public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pos) throws MaxChangedBlocksException { - WorldGenerator generator = createWorldGenerator(type); - return generator != null && generator.generate((net.minecraft.world.World) getWorld(), random, new BlockPos(pos.getX(), pos.getY(), pos.getZ())); - } - - @Override - public BaseBlock getBlock(Vector position) { - World world = getWorld(); - BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - IBlockState state = ((net.minecraft.world.World) world).getBlockState(pos); - TileEntity tile = ((net.minecraft.world.World) world).getTileEntity(pos); - - if (tile != null) { - return new TileEntityBaseBlock(Block.getIdFromBlock(state.getBlock()), state.getBlock().getMetaFromState(state), tile); - } else { - return new BaseBlock(Block.getIdFromBlock(state.getBlock()), state.getBlock().getMetaFromState(state)); - } - } - - @Override - public BaseBlock getLazyBlock(Vector position) { - World world = getWorld(); - BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - IBlockState state = ((net.minecraft.world.World) world).getBlockState(pos); - return new LazyBlock(Block.getIdFromBlock(state.getBlock()), state.getBlock().getMetaFromState(state), this, position); - } -} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/TileEntityUtils.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/TileEntityUtils.java deleted file mode 100644 index 32b9a8be3..000000000 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/nms/TileEntityUtils.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.sponge.nms; - -import com.sk89q.worldedit.Vector; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagInt; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import javax.annotation.Nullable; -import java.lang.reflect.Constructor; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Utility methods for setting tile entities in the world. - */ -@Deprecated -final class TileEntityUtils { - - private TileEntityUtils() { - } - - /** - * Update the given tag compound with position information. - * - * @param tag the tag - * @param position the position - * @return a tag compound - */ - private static NBTTagCompound updateForSet(NBTTagCompound tag, Vector position) { - checkNotNull(tag); - checkNotNull(position); - - tag.setTag("x", new NBTTagInt(position.getBlockX())); - tag.setTag("y", new NBTTagInt(position.getBlockY())); - tag.setTag("z", new NBTTagInt(position.getBlockZ())); - - return tag; - } - - /** - * Set a tile entity at the given location. - * - * @param world the world - * @param position the position - * @param clazz the tile entity class - * @param tag the tag for the tile entity (may be null to not set NBT data) - */ - static void setTileEntity(World world, Vector position, Class clazz, @Nullable NBTTagCompound tag) { - checkNotNull(world); - checkNotNull(position); - checkNotNull(clazz); - - TileEntity tileEntity = constructTileEntity(world, position, clazz); - - if (tileEntity == null) { - return; - } - - if (tag != null) { - // Set X, Y, Z - updateForSet(tag, position); - tileEntity.readFromNBT(tag); - } - - world.setTileEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()), tileEntity); - } - - /** - * Set a tile entity at the given location using the tile entity ID from - * the tag. - * - * @param world the world - * @param position the position - * @param tag the tag for the tile entity (may be null to do nothing) - */ - static void setTileEntity(World world, Vector position, @Nullable NBTTagCompound tag) { - if (tag != null) { - updateForSet(tag, position); - TileEntity tileEntity = TileEntity.create(world, tag); - if (tileEntity != null) { - world.setTileEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()), tileEntity); - } - } - } - - /** - * Construct a tile entity from the given class. - * - * @param world the world - * @param position the position - * @param clazz the class - * @return a tile entity (may be null if it failed) - */ - @Nullable - static TileEntity constructTileEntity(World world, Vector position, Class clazz) { - Constructor baseConstructor; - try { - baseConstructor = clazz.getConstructor(); // creates "blank" TE - } catch (Throwable e) { - return null; // every TE *should* have this constructor, so this isn't necessary - } - - TileEntity genericTE; - try { - // Downcast here for return while retaining the type - genericTE = (TileEntity) baseConstructor.newInstance(); - } catch (Throwable e) { - return null; - } - - /* - genericTE.blockType = Block.blocksList[block.getId()]; - genericTE.blockMetadata = block.getData(); - genericTE.xCoord = pt.getBlockX(); - genericTE.yCoord = pt.getBlockY(); - genericTE.zCoord = pt.getBlockZ(); - genericTE.worldObj = world; - */ // handled by internal code - - return genericTE; - } - - -} diff --git a/worldedit-sponge/src/main/resources/com.sk89q.worldedit.sponge.adapter.impl/Sponge_1_10_Impl.class b/worldedit-sponge/src/main/resources/com.sk89q.worldedit.sponge.adapter.impl/Sponge_1_10_Impl.class new file mode 100644 index 0000000000000000000000000000000000000000..72340e8bac38ee6bdc0ca763f330984c0e530df9 GIT binary patch literal 15176 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 Zitfkr5j=PBUG&#d{4!8ouWndd^FJV+16BY4 literal 0 HcmV?d00001 diff --git a/worldedit-sponge/src/main/resources/com.sk89q.worldedit.sponge.adapter.impl/Sponge_1_11_Impl.class b/worldedit-sponge/src/main/resources/com.sk89q.worldedit.sponge.adapter.impl/Sponge_1_11_Impl.class new file mode 100644 index 0000000000000000000000000000000000000000..20adf7091c03d9129a7187bc3c51ae07ee7e79f5 GIT binary patch literal 15176 zcmbVT34B!5)j#KEdCALzKv-f}gKQxQ3{eV5FeM2Af+2`u5wYTs3}GOdiIWK!wQ5_f zRoiO!(%RPAR_tPHv7G_aDt52kw2QTSwX3yuUu~8C&wX#+ym>P(@O}J#-1qLi=l<`x z=bU@ax%Xurd+DKviD-p-OF2Er8>QGJMW;!h;>`wMWKs!t8N9_LgS!phYEn60EREX? zzC;>(4Bjq{I}F}w@GcXBFEx0#JTEhNk326o_!aWJ!r;B~ywc#XJog#gE6+ZIBl6sD zaKAhc7#x-7L4yy;bHLz1gJUMu@#Zp)%X3KhyUOGQ4@)&^(qbMlX)+%+_=w3@^QcKp ze2u}^nzVv9n>2;5tKe7i^%Z;r-zdea41Tr2uMzy4gyv?0Uu)7dzQyF%@vSDc@NEX) zZc;VB-lR4jG58H8)$kilx{L2Hse|t{_)R9w8>k>giPYL?y>{;J69 zHj&O_A}7edgTE$1x>Ka_brB9k(#_uxxg3=>e$(J@nRL4h-^P!NJf0BAd|Oug9a;Q+ zvdZtuqVJd0eNPs9+~6lo{ysk?#Sf(Tp-FG&AIaN~4gQJAKjoiE%g+sdx`LnKUsUif z`Bw)2+N68*;D4F?Z+<~Y{$uce4Svz!mkd75WOc@3kwp7Icz8H6Y$#%yvOPKw>4+tx$xINw%VXEu` zZuiLGzDQzwc;5h8s=DI6;enmuL{#cdV{!68beL&PS8seUG<<0F1y_ZR2&<94Xfiac zxetZ=!b8bOA`~4Q8VK1d+S|0ZscCN~8o-^Ahz!RE4r7YCx~_Pl-x)U)KN3kq`aJI|24llnnPXO)WH#X##A#_t2K` zkYkYR@+RnvC0i4T@aQ-bp({g$`DXcN%Jc~WfT zJrI>WeU5*+3<8XN0HjQF3X2D`Xefj!LootUL3ZFk&cF^Rz)n6J&Pb-Ud5i2xCZcD; zwP}Dn!@t1nXr`5U*pT-441)lu)qYfGTp=N}jV9r+0__Z4LQzNvnUPFwd5lWmSy+}! z2K?E6rrl0qPizVfIp2iatOhBI5d)s4ur5r7U*X5 z=b3nBtj$Ilyt$r`>D)lu%M1bB^xV(@&+P2R3k%J^)@~dK$NEE#k@&?TY_v2Z{XuBS zllz8&c=!w^qDjD5jUU(@TL`%4Ks<2U%Q|I%&Mmc)|>A_=CMh4t#VT$o@%WME{RA)Gd>#EJRZlV^JDiGmF$ zLx;7(eFn{=U0dE9S>MP}rb!<2()3K_18|u-vtpX;F*MzT8HKPk5z!S5hKF+75hl<+KbNwA z%a+Zt%0q>51*ih{iYhi#iFUz3E4Dp&-f}(udv2gmGu|JeBM9F1<9YBNFCGk^i2>v6 z7{{6C;d@MAj z#Hc=2*#nR_piT0Iayd*mQ`UQQc!n97%3_ft&N%07o_^g==j3h3KtiG&2 zlH6q<+P4I8q~{H3ssMhR6SQptHX)Rx$H^WotY0rIGKO$(Z)A9Q!SdzHnU>V~k6QM5 zZ@9pvL1ti+49rx{lSMCho?fhv_pGeO8JwDITFy zNZ)gJrfVFQDpdv&x7=>esnk+ss+?(VE`hyf&w1NYrmC=%r6xd7h2`YVDQ9y_O;nZ8 zabZ%={5J6DaJppClk_8`(LM?%*^%C#73j5NyY&7B$2Z?tH#STE zv(SyN-wv+Q`CLA<6Cb7bd8CTIp>E7V%n_15=C7?idtecYzd+wUkc=aj?*HU>XB@F~ zznH%|*N;j+F4WG|aZR5nItKfsAz$V5nJ^nyu!@pt(4F1<{MX1+x~3q^0Jmb8)P<)O@wTQVZ20#B`qwF-5*& z?POBq@_kD!R(0de2Mdzkc0`aDCOZ>bgPWinu;w5(#97c_-yf+E+|GUS4B^pLSeL0yBy!&1#^t)Yr>?V8Pp z+~cvOE)-!;@>`3HUSz2j^>Uo!gBa6hEtKmF)oQ6W)h^887A|mvwsaZMVW7g?%HZIL0}7BiPf0sk4O9GHiYR7o*ais@3EBgG6UW=SzeiaIIk zrD%lya(9S6M0)nfRyEU77prYK64kbE+w>(c1l6Oq3mQy&huSF|@3PdTFgmqcHq~W9 zvIqKCm#bBldWBkx16)=;o5I5fpdw3Mq4rwpN`*96J zVW|C<>X&&AND;L~eb7>e)SAp>whyrr4?_)DYEZ>26<5fTmlbyRdX56=l%cMY*%F2t zwp6mfj>*XzEH$DIBmQK!xDF%w9^E0#W+k%rBTO3$5j!cvxR>q=>_DCQt{`w%8*0>2 z*QjePbse`F>XnwdUfp1*S6S*c>Lx?oY^m3(TP*cDb*rInGt}*tdcAssq26ezJJg+) zdXu^d2eJPzLpj@R>%N1LUR-;wI14m;A@U)i)&9zWL&aGPEBGm50sK_KT=%R*TJQr- zRn~wz@d+f1gd1OVvW>DkaQw=;8t3L>LY4&QG~9A$>(~USBfISE+km?uzz)Lf{U;sQ z@b$-%i7t7Y{b6a2pWc(;=n>8Y@r3?(!L-0XATP<$!zyGVaMU*1i5z&Ad@9KGlv%#; zQ3Ax8ADenkKDC!CJEeBn$wSU(2&sE`Xebf`CriE8IL>i+iRW06lMf*0m+ak9#T2B> zKK+1Tk`RPr@mLh!#OxFI)Eq)*5uBpX{nKGwT6jQ?dkz+A+B4IsMR&ZU>EVAUxb1xf%wB zZ-1BJaxA7Rxht`^BdE)5Y3i&a&wz5S9=$wihuUS|G1->yw#aQAI-I40h0S20ZnG?D zT83q>Kh~>?WkdyfNU9iClQ*5D2O#!LCoPz6A0FB1aMxa3*QP&uLhPtPv~3VA-XL1t zF*(CW<_cYSfIm)*>V28pZC|OBLYo&wa1t#Yj>rX;{z{m&AjdF#`@%22T&v4mXm}ij zZj$?8xeU)P37>b1>o&-eauG6j79IrM1cYI^_0A&n2ttn_^6L(?9&(A zSr8;V#dYfiM0*4$4@RRHF)}qsHPlje;1Cd2*h_~rrIEKfuR$K4oOkIlkkcT zh8*t0e$Uxyjsc5-!;NJ%VP6T`4cVO|OdC+4m@MYTTW0%;Vv*b0-L^q#7Y3Wso7AR; z>a}SIwPrcwozu~N!15)+!@!D$MlcKR#c}0c+D=w9g7a`~qww2eQG>ZNTKsn)QI|gq(B^mjkfz!UEYIisObUS3U(u^!NF!(Pdm!)-3dQ zo(v+ayIE9uW#K!?v&ov814Lv8^IdX(rl;^-2g&7ANT&|4nik>SwA_UmXzY-F(6 zP;bU(qg+{g;4el*J2Z?hu_OAAS+Fm&uch{1=D?f_&e$f&n{Pa9$G36px$n`)UU55h0ing|1G#>x9?r0u8NT0$VeSMmWXolR0;%_Kt$OWl>;*{1^f{EJx^WSG9`BY-KwqFQqQ>+k`Z7uxycSP|XIaB3Dmg)= zAH%zM{4za$x=rJZ2Q__#zKW58^jHBT;{=uYkMjgGdYqonNZ+RK6hNAAiYEGz+RlLVUHV=Dq{>q?$&a-03`n@U zvypg+inU&zXn2$+A0?|EI-H!Mss~V?;?$?4XsXnwIrV8NnlANfr(T_+bEID5)N4{S zL+Ue~`pgu~lKO0?K08Hoq(0ZF&rMOS)aN<%c_}(q>hqoY{1h#a`a-9^Fhz?V7^B6z z$Ea?1nwC`6r>LPJMU5$1inkOkOH=3(sHsRB@fB2!_bxJM3r(V}s9j98bP0Aq4=tx1 zw2F4pI=YlL(r)zZpkR*-9iz%6Rq!{19UeXq+@i59-u*w zsGo3+`w4oAegF~w5HnApib<93KQ!Vl-qGU@NWTaqQ^54{Eo0QQyRq@%6Lemh&d;jU z)CwA=5=!d1YV9HJTvIUDj{#Uh6X_@PQ&7tkKXayd2-GE*V%-?6fUsV+1yij&Nx1y% zUV4&NGaaQxc)|7NDO$6pxTg3~YCcM($4>vUvA(7_MQc-Z;jz=-ZxnuPdCq|(iAJ%3 zuc1YBEiI$#sEMwpX1ak|ASrPc^;p;XvKwo7d5YGhsWmGm+gIJ}QAedaX(cB8 zEr3KY&pLqXupIGP))=)3V0)U@`_XRmpjj@O1+?EeXwNxl?G75)>kzaJDcYE(O@6>T zJb=0E{oVn5J|D1C05_-TqBM2+0pA)3_y-5@j}D;M*0#Xbx@}wAnx>1hpth|Yg~hx} z0~fNjKLOCTwLe3EBGSJ&Q#=M8iLG^w(KguHC1PtmCkYwON!sBtxTP6`+qtH=v8MPW z?Go#|6!vzK5KLi++U_npcKUH`cg1=iPuJM*gXP>!4fKBO*L!F)eL(Xm_SQhNU~hlZ z_SWSps|(8dJNPT3_4E(=Cpi9>C><>}{l7sk7C4dAi&SmU3$VZ!=sdly|2XUND0h$O z;_?)|B28Ch#b(>yeSy08FMvc)FXjX86~HS~6i(AVKj8g=fG;_Kr(HnXjl=wU1+Xtg zku>f110D|oMC=ELa(Qk8@~sey?2f15cbgo)+mxby@xv>e`ic}Ckb2aqM^kiA>Mc&a zB}Ip%-saTXQZyj-4yWFcqCu&5I`z&J#iZWt)Vos@m-;rRzAZ&VQs3j$_oV15sqb~_ zdsCE2eWCmu$eIE6UzDE!#xVRv6Z zocI#r#Fr5#zKV$O7~;g&5huO@@AoaliN_HqzKuBX9a!r35GS5QoOlYzKLE;)JSuqF zwbG}#h>Ib5+Y&8Lyr|S_DRK1d-NYl<#FO2CaX71MdlNs6?edJCEN>HIGO<`sz<}lr zNAr`Qd2#TYVMa%=ldr~39^Fz^-HrM+D~pR(mP{*|R(uc5uWu+y(X}bMZcS-pP3cK` zrJ`Lmr3k~_HL9Iib{OK%G}*E@rs-9Fv==;Rp7;Z_X%5YA&ntpwEqYh${A~|`}LV44P)1_-lme!QiH`J7*=ndErC+UqvvU-5~y$jPp1a1#&4C*p;oTZoUXv!4fq|?T&^u(=>OC_cd*6tY-8qgc|J^7 zVw$L;1ix{zc!Aru&@u1Hq+X(F1}`#ru?}zz+7|1a1$%O#d7_~^)AXjSFtuevI6?Ye z0u-_A`h2wcg7)S#y~U3h$4y(Lo}%|2JN>oBQ}n*9 z&UNO(OYtMLWpGU){F-bzUBOM7X~|sH&^)x*nM<$hGK-pG^ zQWc_XFGR_ClvKv+5x#9J8o|os-;U#SUy43_oIY}#K6;WqR)mX}qT_UbiavgvK9OlV zP7f5Fpiese%F};bx8?S;T))`Mk>EsB2XQVzXsjp29jGhbfLub(SS6IglO~lRV|ftD aRdg?&58=6!@1nn!;+KKyM)m4-HU9$-Py<~6 literal 0 HcmV?d00001