From ba363bce2016a0c0901eb686f84ae55a29a33900 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 15 Jan 2015 19:39:15 -0800 Subject: [PATCH 01/27] [Forge] Update to 1.8 --- config/checkstyle/import-control.xml | 1 + worldedit-forge/build.gradle | 4 +- .../sk89q/worldedit/forge/ClientProxy.java | 2 +- .../sk89q/worldedit/forge/CommonProxy.java | 3 +- .../worldedit/forge/ForgeEntityType.java | 2 +- .../forge/ForgePermissionsProvider.java | 4 +- .../sk89q/worldedit/forge/ForgePlatform.java | 8 ++- .../sk89q/worldedit/forge/ForgePlayer.java | 9 ++- .../com/sk89q/worldedit/forge/ForgeWorld.java | 66 ++++++++++--------- .../sk89q/worldedit/forge/ForgeWorldEdit.java | 32 ++++----- .../com/sk89q/worldedit/forge/KeyHandler.java | 8 ++- .../sk89q/worldedit/forge/NBTConverter.java | 20 +++--- .../worldedit/forge/ThreadSafeCache.java | 12 ++-- .../worldedit/forge/TileEntityUtils.java | 7 +- .../worldedit/forge/WECUIPacketHandler.java | 11 ++-- .../sk89q/worldedit/forge/gui/GuiHandler.java | 2 +- 16 files changed, 104 insertions(+), 87 deletions(-) diff --git a/config/checkstyle/import-control.xml b/config/checkstyle/import-control.xml index 7a5600470..ab87b642b 100644 --- a/config/checkstyle/import-control.xml +++ b/config/checkstyle/import-control.xml @@ -54,6 +54,7 @@ + diff --git a/worldedit-forge/build.gradle b/worldedit-forge/build.gradle index f7b51a33e..563ceeea4 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -19,8 +19,8 @@ dependencies { } minecraft { - ext.forgeVersion = "10.13.1.1225" - version = "1.7.10-$forgeVersion" + ext.forgeVersion = "11.14.0.1281" + version = "1.8-$forgeVersion-1.8" replaceIn "com/sk89q/worldedit/forge/ForgeWorldEdit.java" replace "%VERSION%", project.version diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ClientProxy.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ClientProxy.java index ebb5fa675..e029085ab 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ClientProxy.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ClientProxy.java @@ -19,7 +19,7 @@ package com.sk89q.worldedit.forge; -import cpw.mods.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.FMLCommonHandler; public class ClientProxy extends CommonProxy { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommonProxy.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommonProxy.java index 8163afaae..fbb07b9d2 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommonProxy.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommonProxy.java @@ -19,8 +19,9 @@ package com.sk89q.worldedit.forge; +import net.minecraftforge.fml.common.network.NetworkRegistry; + import com.sk89q.worldedit.forge.gui.GuiHandler; -import cpw.mods.fml.common.network.NetworkRegistry; public class CommonProxy { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntityType.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntityType.java index 4888c748d..8fb19f3cd 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntityType.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntityType.java @@ -133,7 +133,7 @@ public class ForgeEntityType implements EntityType { @Override public boolean isTagged() { - return entity instanceof EntityLiving && ((EntityLiving) entity).hasCustomNameTag(); + return entity instanceof EntityLiving && ((EntityLiving) entity).hasCustomName(); } @Override diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java index 60408df6c..ffd8de06b 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java @@ -19,10 +19,10 @@ package com.sk89q.worldedit.forge; -import cpw.mods.fml.common.FMLCommonHandler; import net.minecraft.command.ICommand; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.world.WorldSettings.GameType; +import net.minecraftforge.fml.common.FMLCommonHandler; public interface ForgePermissionsProvider { @@ -42,7 +42,7 @@ public interface ForgePermissionsProvider { public boolean hasPermission(EntityPlayerMP player, String permission) { ForgeConfiguration configuration = platform.getConfiguration(); return configuration.cheatMode || - FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().func_152596_g(player.getGameProfile()) || + FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().canSendCommands(player.getGameProfile()) || (configuration.creativeEnable && player.theItemInWorldManager.getGameType() == GameType.CREATIVE); } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java index 442b2c055..7edb92b3a 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -28,7 +28,7 @@ import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.world.World; -import cpw.mods.fml.common.FMLCommonHandler; + import net.minecraft.block.Block; import net.minecraft.command.ServerCommandManager; import net.minecraft.entity.EntityList; @@ -38,8 +38,10 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.management.ServerConfigurationManager; import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.fml.common.FMLCommonHandler; import javax.annotation.Nullable; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -121,7 +123,7 @@ class ForgePlatform extends AbstractPlatform implements MultiUserPlatform { if (player instanceof ForgePlayer) { return player; } else { - EntityPlayerMP entity = server.getConfigurationManager().func_152612_a(player.getName()); + EntityPlayerMP entity = server.getConfigurationManager().getPlayerByUsername(player.getName()); return entity != null ? new ForgePlayer(this, entity) : null; } } @@ -202,7 +204,7 @@ class ForgePlatform extends AbstractPlatform implements MultiUserPlatform { List users = new ArrayList(); ServerConfigurationManager scm = server.getConfigurationManager(); for (String name : scm.getAllUsernames()) { - EntityPlayerMP entity = scm.func_152612_a(name); + EntityPlayerMP entity = scm.getPlayerByUsername(name); if (entity != null) { users.add(new ForgePlayer(this, entity)); } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index 945b790a4..7a5093a4e 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -33,8 +33,10 @@ import com.sk89q.worldedit.util.Location; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.server.S3FPacketCustomPayload; import net.minecraft.util.ChatComponentText; +import io.netty.buffer.Unpooled; import javax.annotation.Nullable; @@ -64,7 +66,7 @@ public class ForgePlayer extends AbstractPlayerActor { @Override public String getName() { - return this.player.getCommandSenderName(); + return this.player.getName(); } @Override @@ -114,7 +116,8 @@ public class ForgePlayer extends AbstractPlayerActor { if (params.length > 0) { send = send + "|" + StringUtil.joinString(params, "|"); } - S3FPacketCustomPayload packet = new S3FPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)); + PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET))); + S3FPacketCustomPayload packet = new S3FPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer); this.player.playerNetServerHandler.sendPacket(packet); } @@ -174,7 +177,7 @@ public class ForgePlayer extends AbstractPlayerActor { @Override public SessionKey getSessionKey() { - return new SessionKeyImpl(player.getUniqueID(), player.getCommandSenderName()); + return new SessionKeyImpl(player.getUniqueID(), player.getName()); } private static class SessionKeyImpl implements SessionKey { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index c89863610..325bcc8ef 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -39,7 +39,9 @@ import com.sk89q.worldedit.util.TreeGenerator.TreeType; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.registry.WorldData; + import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityList; import net.minecraft.entity.item.EntityItem; import net.minecraft.inventory.IInventory; @@ -47,6 +49,8 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ClassInheritanceMultiMap; import net.minecraft.util.LongHashMap; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; @@ -69,6 +73,7 @@ import net.minecraft.world.gen.feature.WorldGenTrees; import net.minecraft.world.gen.feature.WorldGenerator; import javax.annotation.Nullable; + import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.ArrayList; @@ -85,6 +90,7 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class ForgeWorld extends AbstractWorld { + private static final int UPDATE = 1, NOTIFY = 2, NOTIFY_CLIENT = 4; private static final Logger logger = Logger.getLogger(ForgeWorld.class.getCanonicalName()); private static final Random random = new Random(); private final WeakReference worldRef; @@ -154,33 +160,29 @@ public class ForgeWorld extends AbstractWorld { // First set the block Chunk chunk = world.getChunkFromChunkCoords(x >> 4, z >> 4); - int previousId = 0; - - if (notifyAndLight) { - previousId = Block.getIdFromBlock(chunk.getBlock(x & 15, y, z & 15)); - } - - boolean successful = chunk.func_150807_a(x & 15, y, z & 15, Block.getBlockById(block.getId()), block.getData()); + BlockPos pos = new BlockPos(x, y, z); + IBlockState old = chunk.getBlockState(pos); + IBlockState newState = Block.getBlockById(block.getId()).getStateFromMeta(block.getData()); + IBlockState successState = chunk.setBlockState(pos, newState); + boolean successful = successState != null; // Create the TileEntity if (successful) { - CompoundTag tag = block.getNbtData(); - if (tag != null) { - NBTTagCompound nativeTag = NBTConverter.toNative(tag); + if (block.hasNbtData()) { + // Kill the old TileEntity + world.removeTileEntity(pos); + NBTTagCompound nativeTag = NBTConverter.toNative(block.getNbtData()); nativeTag.setString("id", block.getNbtId()); - TileEntityUtils.setTileEntity(getWorld(), position, nativeTag); + TileEntityUtils.setTileEntity(world, position, nativeTag); } } if (notifyAndLight) { - world.func_147451_t(x, y, z); - world.markBlockForUpdate(x, y, z); - world.notifyBlockChange(x, y, z, Block.getBlockById(previousId)); - - Block mcBlock = Block.getBlockById(previousId); - if (mcBlock != null && mcBlock.hasComparatorInputOverride()) { - world.func_147453_f(x, y, z, Block.getBlockById(block.getId())); + if (!successful) { + newState = old; } + world.checkLight(pos); + world.markAndNotifyBlock(pos, chunk, old, newState, UPDATE | NOTIFY); } return successful; @@ -189,13 +191,13 @@ public class ForgeWorld extends AbstractWorld { @Override public int getBlockLightLevel(Vector position) { checkNotNull(position); - return getWorld().getBlockLightValue(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + return getWorld().getLight(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ())); } @Override public boolean clearContainerBlockContents(Vector position) { checkNotNull(position); - TileEntity tile = getWorld().getTileEntity(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + TileEntity tile = getWorld().getTileEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ())); if ((tile instanceof IInventory)) { IInventory inv = (IInventory) tile; int size = inv.getSizeInventory(); @@ -210,7 +212,7 @@ public class ForgeWorld extends AbstractWorld { @Override public BaseBiome getBiome(Vector2D position) { checkNotNull(position); - return new BaseBiome(getWorld().getBiomeGenForCoords(position.getBlockX(), position.getBlockZ()).biomeID); + return new BaseBiome(getWorld().getBiomeGenForCoords(new BlockPos(position.getBlockX(), 0, position.getBlockZ())).biomeID); } @Override @@ -218,8 +220,8 @@ public class ForgeWorld extends AbstractWorld { checkNotNull(position); checkNotNull(biome); - Chunk chunk = getWorld().getChunkFromBlockCoords(position.getBlockX(), position.getBlockZ()); - if ((chunk != null) && (chunk.isChunkLoaded)) { + Chunk chunk = getWorld().getChunkFromBlockCoords(new BlockPos(position.getBlockX(), 0, position.getBlockZ())); + if ((chunk != null) && (chunk.isLoaded())) { chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = (byte) biome.getId(); return true; } @@ -237,7 +239,7 @@ public class ForgeWorld extends AbstractWorld { } EntityItem entity = new EntityItem(getWorld(), position.getX(), position.getY(), position.getZ(), ForgeWorldEdit.toForgeItemStack(item)); - entity.delayBeforeCanPickup = 10; + entity.setPickupDelay(10); getWorld().spawnEntityInWorld(entity); } @@ -384,23 +386,23 @@ public class ForgeWorld extends AbstractWorld { @Override public BaseBlock getBlock(Vector position) { World world = getWorld(); - int id = Block.getIdFromBlock(world.getBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ())); - int data = world.getBlockMetadata(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - TileEntity tile = getWorld().getTileEntity(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + IBlockState state = world.getBlockState(pos); + TileEntity tile = getWorld().getTileEntity(pos); if (tile != null) { - return new TileEntityBaseBlock(id, data, tile); + return new TileEntityBaseBlock(Block.getIdFromBlock(state.getBlock()), state.getBlock().getMetaFromState(state), tile); } else { - return new BaseBlock(id, data); + return new BaseBlock(Block.getIdFromBlock(state.getBlock()), state.getBlock().getMetaFromState(state)); } } @Override public BaseBlock getLazyBlock(Vector position) { World world = getWorld(); - int id = Block.getIdFromBlock(world.getBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ())); - int data = world.getBlockMetadata(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - return new LazyBlock(id, data, this, position); + BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + IBlockState state = world.getBlockState(pos); + return new LazyBlock(Block.getIdFromBlock(state.getBlock()), state.getBlock().getMetaFromState(state), this, position); } @Override diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java index 7284796e6..30543a238 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java @@ -27,19 +27,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.internal.LocalWorldAdapter; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.Mod; -import cpw.mods.fml.common.Mod.EventHandler; -import cpw.mods.fml.common.Mod.Instance; -import cpw.mods.fml.common.SidedProxy; -import cpw.mods.fml.common.event.FMLInitializationEvent; -import cpw.mods.fml.common.event.FMLPostInitializationEvent; -import cpw.mods.fml.common.event.FMLPreInitializationEvent; -import cpw.mods.fml.common.event.FMLServerAboutToStartEvent; -import cpw.mods.fml.common.event.FMLServerStartedEvent; -import cpw.mods.fml.common.event.FMLServerStoppingEvent; -import cpw.mods.fml.common.eventhandler.Event.Result; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; + import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -47,6 +35,20 @@ import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.CommandEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.Mod.Instance; +import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent; +import net.minecraftforge.fml.common.event.FMLServerStartedEvent; +import net.minecraftforge.fml.common.event.FMLServerStoppingEvent; +import net.minecraftforge.fml.common.eventhandler.Event.Result; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + import org.apache.logging.log4j.Logger; import java.io.File; @@ -156,7 +158,7 @@ public class ForgeWorldEdit { Action action = event.action; switch (action) { case LEFT_CLICK_BLOCK: { - WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), event.x, event.y, event.z); + WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), event.pos.getX(), event.pos.getY(), event.pos.getZ()); if (we.handleBlockLeftClick(player, pos)) { event.setCanceled(true); @@ -169,7 +171,7 @@ public class ForgeWorldEdit { break; } case RIGHT_CLICK_BLOCK: { - WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), event.x, event.y, event.z); + WorldVector pos = new WorldVector(LocalWorldAdapter.adapt(world), event.pos.getX(), event.pos.getY(), event.pos.getZ()); if (we.handleBlockRightClick(player, pos)) { event.setCanceled(true); diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/KeyHandler.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/KeyHandler.java index b8ffa78db..ea037e548 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/KeyHandler.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/KeyHandler.java @@ -20,11 +20,13 @@ package com.sk89q.worldedit.forge; import com.sk89q.worldedit.forge.gui.GuiHandler; -import cpw.mods.fml.client.registry.ClientRegistry; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import cpw.mods.fml.common.gameevent.InputEvent.KeyInputEvent; + import net.minecraft.client.Minecraft; import net.minecraft.client.settings.KeyBinding; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent.KeyInputEvent; + import org.lwjgl.input.Keyboard; public class KeyHandler { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/NBTConverter.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/NBTConverter.java index 98f88c6e8..69f4ab6ad 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/NBTConverter.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/NBTConverter.java @@ -170,7 +170,7 @@ final class NBTConverter { } public static IntArrayTag fromNative(NBTTagIntArray other) { - int[] value = other.func_150302_c(); + int[] value = other.getIntArray(); return new IntArrayTag(Arrays.copyOf(value, value.length)); } @@ -192,28 +192,28 @@ final class NBTConverter { } public static LongTag fromNative(NBTTagLong other) { - return new LongTag(other.func_150291_c()); + return new LongTag(other.getLong()); } public static StringTag fromNative(NBTTagString other) { - return new StringTag(other.func_150285_a_()); + return new StringTag(other.getString()); } public static IntTag fromNative(NBTTagInt other) { - return new IntTag(other.func_150287_d()); + return new IntTag(other.getInt()); } public static ByteTag fromNative(NBTTagByte other) { - return new ByteTag(other.func_150290_f()); + return new ByteTag(other.getByte()); } public static ByteArrayTag fromNative(NBTTagByteArray other) { - byte[] value = other.func_150292_c(); + byte[] value = other.getByteArray(); return new ByteArrayTag(Arrays.copyOf(value, value.length)); } public static CompoundTag fromNative(NBTTagCompound other) { - @SuppressWarnings("unchecked") Collection tags = other.func_150296_c(); + @SuppressWarnings("unchecked") Set tags = other.getKeySet(); Map map = new HashMap(); for (String tagName : tags) { map.put(tagName, fromNative(other.getTag(tagName))); @@ -222,15 +222,15 @@ final class NBTConverter { } public static FloatTag fromNative(NBTTagFloat other) { - return new FloatTag(other.func_150288_h()); + return new FloatTag(other.getFloat()); } public static ShortTag fromNative(NBTTagShort other) { - return new ShortTag(other.func_150289_e()); + return new ShortTag(other.getShort()); } public static DoubleTag fromNative(NBTTagDouble other) { - return new DoubleTag(other.func_150286_g()); + return new DoubleTag(other.getDouble()); } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ThreadSafeCache.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ThreadSafeCache.java index 1322f0713..0ca19c5b0 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ThreadSafeCache.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ThreadSafeCache.java @@ -19,10 +19,11 @@ package com.sk89q.worldedit.forge; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import cpw.mods.fml.common.gameevent.TickEvent; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; import java.util.Collections; import java.util.HashSet; @@ -55,8 +56,9 @@ public class ThreadSafeCache { if (now - lastRefresh > REFRESH_DELAY) { Set onlineIds = new HashSet(); - - if (FMLCommonHandler.instance().getMinecraftServerInstance() == null) { + + MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance(); + if (server == null || server.getConfigurationManager() == null) { return; } for (Object object : FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().playerEntityList) { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/TileEntityUtils.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/TileEntityUtils.java index fd8d6e5fe..4bc57b2b8 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/TileEntityUtils.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/TileEntityUtils.java @@ -20,12 +20,15 @@ package com.sk89q.worldedit.forge; import com.sk89q.worldedit.Vector; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagInt; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; import net.minecraft.world.World; import javax.annotation.Nullable; + import java.lang.reflect.Constructor; import static com.google.common.base.Preconditions.checkNotNull; @@ -81,7 +84,7 @@ final class TileEntityUtils { tileEntity.readFromNBT(tag); } - world.setTileEntity(position.getBlockX(), position.getBlockY(), position.getBlockZ(), tileEntity); + world.setTileEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()), tileEntity); } /** @@ -97,7 +100,7 @@ final class TileEntityUtils { updateForSet(tag, position); TileEntity tileEntity = TileEntity.createAndLoadEntity(tag); if (tileEntity != null) { - world.setTileEntity(position.getBlockX(), position.getBlockY(), position.getBlockZ(), tileEntity); + world.setTileEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()), tileEntity); } } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java index 03cf3ab0c..32b29d6a9 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java @@ -24,14 +24,13 @@ import java.nio.charset.Charset; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.play.client.C17PacketCustomPayload; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.FMLEventChannel; +import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent; +import net.minecraftforge.fml.common.network.NetworkRegistry; import com.sk89q.worldedit.LocalSession; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import cpw.mods.fml.common.network.FMLEventChannel; -import cpw.mods.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent; -import cpw.mods.fml.common.network.NetworkRegistry; - public class WECUIPacketHandler { public static final Charset UTF_8_CHARSET = Charset.forName("UTF-8"); private static FMLEventChannel WECUI_CHANNEL; @@ -52,7 +51,7 @@ public class WECUIPacketHandler { return; } - String text = new String(rawPacket.func_149558_e(), UTF_8_CHARSET); + String text = new String(rawPacket.getBufferData().array(), UTF_8_CHARSET); session.handleCUIInitializationMessage(text); } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/gui/GuiHandler.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/gui/GuiHandler.java index 4aba5eda0..d88b97379 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/gui/GuiHandler.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/gui/GuiHandler.java @@ -19,9 +19,9 @@ package com.sk89q.worldedit.forge.gui; -import cpw.mods.fml.common.network.IGuiHandler; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.world.World; +import net.minecraftforge.fml.common.network.IGuiHandler; public class GuiHandler implements IGuiHandler { From 5c99d4bf59f9e5db7f45881d55dac12099939bf4 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 15 Feb 2015 09:53:25 -0800 Subject: [PATCH 02/27] Fix Forge CUI handler --- .../sk89q/worldedit/forge/ForgePlayer.java | 5 ++--- .../sk89q/worldedit/forge/ForgeWorldEdit.java | 1 + .../worldedit/forge/WECUIPacketHandler.java | 22 ++++++++++++++----- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index 7a5093a4e..306be41fe 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -34,8 +34,8 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; -import net.minecraft.network.play.server.S3FPacketCustomPayload; import net.minecraft.util.ChatComponentText; +import net.minecraftforge.fml.common.network.internal.FMLProxyPacket; import io.netty.buffer.Unpooled; import javax.annotation.Nullable; @@ -117,8 +117,7 @@ public class ForgePlayer extends AbstractPlayerActor { send = send + "|" + StringUtil.joinString(params, "|"); } PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET))); - S3FPacketCustomPayload packet = new S3FPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer); - this.player.playerNetServerHandler.sendPacket(packet); + WECUIPacketHandler.WECUI_CHANNEL.sendTo(new FMLProxyPacket(buffer, ForgeWorldEdit.CUI_PLUGIN_CHANNEL), player); } @Override diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java index 30543a238..f7f4c6ea5 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java @@ -95,6 +95,7 @@ public class ForgeWorldEdit { @EventHandler public void init(FMLInitializationEvent event) { MinecraftForge.EVENT_BUS.register(this); + WECUIPacketHandler.init(); proxy.registerHandlers(); } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java index 32b29d6a9..3acc1f6e5 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java @@ -23,9 +23,13 @@ import java.nio.charset.Charset; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.network.NetHandlerPlayServer; -import net.minecraft.network.play.client.C17PacketCustomPayload; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.ThreadQuickExitException; +import net.minecraft.network.play.server.S20PacketEntityProperties; +import net.minecraft.network.play.server.S3FPacketCustomPayload; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.FMLEventChannel; +import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent; import net.minecraftforge.fml.common.network.NetworkRegistry; @@ -33,7 +37,7 @@ import com.sk89q.worldedit.LocalSession; public class WECUIPacketHandler { public static final Charset UTF_8_CHARSET = Charset.forName("UTF-8"); - private static FMLEventChannel WECUI_CHANNEL; + public static FMLEventChannel WECUI_CHANNEL; public static void init() { WECUI_CHANNEL = NetworkRegistry.INSTANCE.newEventDrivenChannel(ForgeWorldEdit.CUI_PLUGIN_CHANNEL); @@ -42,7 +46,6 @@ public class WECUIPacketHandler { @SubscribeEvent public void onPacketData(ServerCustomPacketEvent event) { - C17PacketCustomPayload rawPacket = (C17PacketCustomPayload) event.packet.toC17Packet(); if (event.packet.channel().equals(ForgeWorldEdit.CUI_PLUGIN_CHANNEL)) { EntityPlayerMP player = getPlayerFromEvent(event); LocalSession session = ForgeWorldEdit.inst.getSession((EntityPlayerMP) player); @@ -50,9 +53,18 @@ public class WECUIPacketHandler { if (session.hasCUISupport()) { return; } - - String text = new String(rawPacket.getBufferData().array(), UTF_8_CHARSET); + + String text = event.packet.payload().toString(UTF_8_CHARSET); session.handleCUIInitializationMessage(text); + session.describeCUI(ForgeWorldEdit.inst.wrap(player)); + } + } + + @SubscribeEvent + public void callProcessPacket(ClientCustomPacketEvent event) { + try { + new S3FPacketCustomPayload(event.packet.channel(), new PacketBuffer(event.packet.payload())).processPacket(event.handler); + } catch (ThreadQuickExitException suppress) { } } From 0d5c115e4dd60f443e2f35d8909784bc414892ae Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 15 Feb 2015 10:40:36 -0800 Subject: [PATCH 03/27] Send without a proxy packet --- .../src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index 306be41fe..7a5093a4e 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -34,8 +34,8 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S3FPacketCustomPayload; import net.minecraft.util.ChatComponentText; -import net.minecraftforge.fml.common.network.internal.FMLProxyPacket; import io.netty.buffer.Unpooled; import javax.annotation.Nullable; @@ -117,7 +117,8 @@ public class ForgePlayer extends AbstractPlayerActor { send = send + "|" + StringUtil.joinString(params, "|"); } PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET))); - WECUIPacketHandler.WECUI_CHANNEL.sendTo(new FMLProxyPacket(buffer, ForgeWorldEdit.CUI_PLUGIN_CHANNEL), player); + S3FPacketCustomPayload packet = new S3FPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer); + this.player.playerNetServerHandler.sendPacket(packet); } @Override From aa3a2d4764ff22ab408b4b6edf606f544d8b250f Mon Sep 17 00:00:00 2001 From: zml Date: Mon, 29 Jun 2015 12:57:01 -0700 Subject: [PATCH 04/27] Add support for delegating permissions to Sponge. When Sponge is not installed, behaviour is as before. Closes #331 --- config/checkstyle/import-control.xml | 1 + worldedit-forge/build.gradle | 7 ++++++- .../worldedit/forge/ForgePermissionsProvider.java | 14 ++++++++++++++ .../com/sk89q/worldedit/forge/ForgeWorldEdit.java | 10 ++++++++-- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/config/checkstyle/import-control.xml b/config/checkstyle/import-control.xml index ab87b642b..3e4233471 100644 --- a/config/checkstyle/import-control.xml +++ b/config/checkstyle/import-control.xml @@ -55,6 +55,7 @@ + diff --git a/worldedit-forge/build.gradle b/worldedit-forge/build.gradle index 563ceeea4..331008ad4 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -15,9 +15,14 @@ apply plugin: 'forge' dependencies { compile project(':worldedit-core') + compile 'org.spongepowered:spongeapi:2.1-SNAPSHOT' testCompile group: 'org.mockito', name: 'mockito-core', version:'1.9.0-rc1' } +repositories { + maven { url ="https://repo.spongepowered.org/maven" } +} + minecraft { ext.forgeVersion = "11.14.0.1281" version = "1.8-$forgeVersion-1.8" @@ -31,7 +36,7 @@ project.archivesBaseName = "${project.archivesBaseName}-mc${minecraft.version}" processResources { from (sourceSets.main.resources.srcDirs) { expand 'version': project.version, - 'mcVersion': project.minecraft.version, + 'mcVersion': project.minecraft.version, 'forgeVersion': project.minecraft.forgeVersion, 'internalVersion': project.internalVersion include 'mcmod.info' diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java index ffd8de06b..aa5dd5c2d 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java @@ -23,6 +23,7 @@ import net.minecraft.command.ICommand; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.world.WorldSettings.GameType; import net.minecraftforge.fml.common.FMLCommonHandler; +import org.spongepowered.api.entity.player.Player; public interface ForgePermissionsProvider { @@ -49,4 +50,17 @@ public interface ForgePermissionsProvider { @Override public void registerPermission(ICommand command, String permission) {} } + + public static class SpongePermissionsProvider implements ForgePermissionsProvider { + + @Override + public boolean hasPermission(EntityPlayerMP player, String permission) { + return ((Player) player).hasPermission(permission); + } + + @Override + public void registerPermission(ICommand command, String permission) { + + } + } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java index f7f4c6ea5..017ade171 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java @@ -36,6 +36,7 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.CommandEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.Mod.Instance; @@ -60,7 +61,7 @@ import static net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; /** * The Forge implementation of WorldEdit. */ -@Mod(modid = ForgeWorldEdit.MOD_ID, name = "WorldEdit", version = "%VERSION%", acceptableRemoteVersions = "*") +@Mod(modid = ForgeWorldEdit.MOD_ID, name = "WorldEdit", version = "%VERSION%", acceptableRemoteVersions = "*", dependencies = "after:Sponge") public class ForgeWorldEdit { public static Logger logger; @@ -116,7 +117,12 @@ public class ForgeWorldEdit { this.platform = new ForgePlatform(this); WorldEdit.getInstance().getPlatformManager().register(platform); - this.provider = new ForgePermissionsProvider.VanillaPermissionsProvider(platform); + + if (Loader.isModLoaded("Sponge")) { + this.provider = new ForgePermissionsProvider.SpongePermissionsProvider(); + } else { + this.provider = new ForgePermissionsProvider.VanillaPermissionsProvider(platform); + } } @EventHandler From 3f171a95b72771e897b6d492c6f92542654f9764 Mon Sep 17 00:00:00 2001 From: zml Date: Wed, 22 Jul 2015 00:04:31 -0700 Subject: [PATCH 05/27] Clean up sending of formatted chat This now fully uses MC's ChatComponentStyle for the general chat styling, and cleans up some duplication --- .../sk89q/worldedit/forge/ForgePlayer.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index 7a5093a4e..b84a53741 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -37,6 +37,7 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.server.S3FPacketCustomPayload; import net.minecraft.util.ChatComponentText; import io.netty.buffer.Unpooled; +import net.minecraft.util.EnumChatFormatting; import javax.annotation.Nullable; @@ -130,23 +131,26 @@ public class ForgePlayer extends AbstractPlayerActor { @Override public void printDebug(String msg) { - for (String part : msg.split("\n")) { - this.player.addChatMessage(new ChatComponentText("\u00a77" + part)); - } + sendColorized(msg, EnumChatFormatting.GRAY); } @Override public void print(String msg) { - for (String part : msg.split("\n")) { - this.player.addChatMessage(new ChatComponentText("\u00a7d" + part)); - } + sendColorized(msg, EnumChatFormatting.LIGHT_PURPLE); } @Override public void printError(String msg) { + sendColorized(msg, EnumChatFormatting.RED); + } + + private void sendColorized(String msg, EnumChatFormatting formatting) { for (String part : msg.split("\n")) { - this.player.addChatMessage(new ChatComponentText("\u00a7c" + part)); + ChatComponentText component = new ChatComponentText(part); + component.getChatStyle().setColor(formatting); + this.player.addChatMessage(component); } + } @Override @@ -216,4 +220,4 @@ public class ForgePlayer extends AbstractPlayerActor { } -} \ No newline at end of file +} From 07edf3d365785f6205aa629d42ab0b2bcb7eda84 Mon Sep 17 00:00:00 2001 From: zml Date: Wed, 22 Jul 2015 00:08:36 -0700 Subject: [PATCH 06/27] Fix swapping of pitch and yaw in setLocation Also use rotation(Pitch|Yaw) in getLocation for consistency with getPitch and getYaw. --- .../main/java/com/sk89q/worldedit/forge/ForgePlayer.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index b84a53741..05153adeb 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -81,8 +81,8 @@ public class ForgePlayer extends AbstractPlayerActor { return new Location( ForgeWorldEdit.inst.getWorld(this.player.worldObj), position, - this.player.cameraYaw, - this.player.cameraPitch); + this.player.rotationYaw, + this.player.rotationPitch); } @Override @@ -150,12 +150,11 @@ public class ForgePlayer extends AbstractPlayerActor { component.getChatStyle().setColor(formatting); this.player.addChatMessage(component); } - } @Override public void setPosition(Vector pos, float pitch, float yaw) { - this.player.playerNetServerHandler.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), pitch, yaw); + this.player.playerNetServerHandler.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch); } @Override From 096729883c662730ed47dd5519b516918e803a1d Mon Sep 17 00:00:00 2001 From: Wyatt Childers Date: Mon, 7 Sep 2015 18:15:44 -0400 Subject: [PATCH 07/27] Updated the Sponge permissions delegate for upstream API changes --- .../com/sk89q/worldedit/forge/ForgePermissionsProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java index aa5dd5c2d..c68131265 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePermissionsProvider.java @@ -23,7 +23,7 @@ import net.minecraft.command.ICommand; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.world.WorldSettings.GameType; import net.minecraftforge.fml.common.FMLCommonHandler; -import org.spongepowered.api.entity.player.Player; +import org.spongepowered.api.entity.living.player.Player; public interface ForgePermissionsProvider { From 39e17ddbcef9cf1a49c136a51c272a7b878e8f2a Mon Sep 17 00:00:00 2001 From: zml Date: Tue, 5 Jan 2016 17:43:55 -0800 Subject: [PATCH 08/27] forge: Correct Sponge mod id --- .../main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java index 017ade171..40d0bda24 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java @@ -61,7 +61,7 @@ import static net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; /** * The Forge implementation of WorldEdit. */ -@Mod(modid = ForgeWorldEdit.MOD_ID, name = "WorldEdit", version = "%VERSION%", acceptableRemoteVersions = "*", dependencies = "after:Sponge") +@Mod(modid = ForgeWorldEdit.MOD_ID, name = "WorldEdit", version = "%VERSION%", acceptableRemoteVersions = "*", dependencies = "after:sponge") public class ForgeWorldEdit { public static Logger logger; @@ -118,7 +118,7 @@ public class ForgeWorldEdit { WorldEdit.getInstance().getPlatformManager().register(platform); - if (Loader.isModLoaded("Sponge")) { + if (Loader.isModLoaded("sponge")) { this.provider = new ForgePermissionsProvider.SpongePermissionsProvider(); } else { this.provider = new ForgePermissionsProvider.VanillaPermissionsProvider(platform); From 633e734b70ec60738796a4d31d81e80e6928ba0b Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 12 Jan 2016 01:46:10 -0800 Subject: [PATCH 09/27] Update to 1.8.9 --- worldedit-forge/build.gradle | 23 +++++++++------ .../sk89q/worldedit/forge/ClientProxy.java | 4 +-- .../sk89q/worldedit/forge/CommandWrapper.java | 2 +- .../com/sk89q/worldedit/forge/ForgeWorld.java | 29 ++++++++++++------- .../sk89q/worldedit/forge/ForgeWorldEdit.java | 16 +++++----- .../worldedit/forge/WECUIPacketHandler.java | 6 ++-- 6 files changed, 45 insertions(+), 35 deletions(-) diff --git a/worldedit-forge/build.gradle b/worldedit-forge/build.gradle index 331008ad4..f95b9d4fb 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -7,25 +7,30 @@ buildscript { } dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' + classpath 'net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT' } } -apply plugin: 'forge' +apply plugin: 'net.minecraftforge.gradle.forge' dependencies { compile project(':worldedit-core') - compile 'org.spongepowered:spongeapi:2.1-SNAPSHOT' + compile 'org.spongepowered:spongeapi:3.1.0-SNAPSHOT' testCompile group: 'org.mockito', name: 'mockito-core', version:'1.9.0-rc1' } repositories { - maven { url ="https://repo.spongepowered.org/maven" } + maven { + name = "Sponge" + url = "https://repo.spongepowered.org/maven" + } } +ext.forgeVersion = "11.15.0.1695" minecraft { - ext.forgeVersion = "11.14.0.1281" - version = "1.8-$forgeVersion-1.8" + version = "1.8.9-${project.forgeVersion}" + mappings = "snapshot_20160111" + runDir = 'run' replaceIn "com/sk89q/worldedit/forge/ForgeWorldEdit.java" replace "%VERSION%", project.version @@ -37,7 +42,7 @@ processResources { from (sourceSets.main.resources.srcDirs) { expand 'version': project.version, 'mcVersion': project.minecraft.version, - 'forgeVersion': project.minecraft.forgeVersion, + 'forgeVersion': project.forgeVersion, 'internalVersion': project.internalVersion include 'mcmod.info' } @@ -60,8 +65,8 @@ shadowJar { } } -reobf.reobf(shadowJar) { spec -> - spec.classpath = sourceSets.main.compileClasspath; +reobf { + shadowJar } task deobfJar(type: Jar) { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ClientProxy.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ClientProxy.java index e029085ab..688728a63 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ClientProxy.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ClientProxy.java @@ -19,14 +19,14 @@ package com.sk89q.worldedit.forge; -import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.common.MinecraftForge; public class ClientProxy extends CommonProxy { @Override public void registerHandlers() { super.registerHandlers(); - FMLCommonHandler.instance().bus().register(new KeyHandler()); + MinecraftForge.EVENT_BUS.register(new KeyHandler()); } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java index fb5c55550..daf76bad6 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java @@ -79,7 +79,7 @@ public class CommandWrapper extends CommandBase { } @Override - public int compareTo(@Nullable Object o) { + public int compareTo(@Nullable ICommand o) { if (o == null) { return 0; } else if (o instanceof ICommand) { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index 325bcc8ef..6b3f5e655 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -41,9 +41,14 @@ import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.registry.WorldData; import net.minecraft.block.Block; +import net.minecraft.block.BlockLeaves; +import net.minecraft.block.BlockOldLeaf; +import net.minecraft.block.BlockOldLog; +import net.minecraft.block.BlockPlanks; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityList; import net.minecraft.entity.item.EntityItem; +import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -90,9 +95,14 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class ForgeWorld extends AbstractWorld { + private static final Random random = new Random(); private static final int UPDATE = 1, NOTIFY = 2, NOTIFY_CLIENT = 4; private static final Logger logger = Logger.getLogger(ForgeWorld.class.getCanonicalName()); - private static final Random random = new Random(); + + 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)); + private final WeakReference worldRef; /** @@ -348,12 +358,12 @@ public class ForgeWorld extends AbstractWorld { case REDWOOD: return new WorldGenTaiga2(true); case TALL_REDWOOD: return new WorldGenTaiga1(); case BIRCH: return new WorldGenForest(true, false); - case JUNGLE: return new WorldGenMegaJungle(true, 10, 20, 3, 3); - case SMALL_JUNGLE: return new WorldGenTrees(true, 4 + random.nextInt(7), 3, 3, false); - case SHORT_JUNGLE: return new WorldGenTrees(true, 4 + random.nextInt(7), 3, 3, true); - case JUNGLE_BUSH: return new WorldGenShrub(3, 0); - case RED_MUSHROOM: return new WorldGenBigMushroom(1); - case BROWN_MUSHROOM: return new WorldGenBigMushroom(0); + 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); @@ -427,7 +437,6 @@ public class ForgeWorld extends AbstractWorld { } @Override - @SuppressWarnings("unchecked") public List getEntities(Region region) { List entities = new ArrayList(); World world = getWorld(); @@ -443,8 +452,8 @@ public class ForgeWorld extends AbstractWorld { @Override public List getEntities() { List entities = new ArrayList(); - for (Object entity : getWorld().loadedEntityList) { - entities.add(new ForgeEntity((net.minecraft.entity.Entity) entity)); + for (net.minecraft.entity.Entity entity : getWorld().loadedEntityList) { + entities.add(new ForgeEntity(entity)); } return entities; } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java index 40d0bda24..2ba05bf28 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.forge; +import org.apache.logging.log4j.Logger; + import com.google.common.base.Joiner; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -28,6 +30,8 @@ import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.internal.LocalWorldAdapter; +import java.io.File; +import java.util.Map; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -35,7 +39,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.CommandEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; @@ -50,13 +54,7 @@ import net.minecraftforge.fml.common.event.FMLServerStoppingEvent; import net.minecraftforge.fml.common.eventhandler.Event.Result; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.apache.logging.log4j.Logger; - -import java.io.File; -import java.util.Map; - import static com.google.common.base.Preconditions.checkNotNull; -import static net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; /** * The Forge implementation of WorldEdit. @@ -90,7 +88,7 @@ public class ForgeWorldEdit { config = new ForgeConfiguration(this); config.load(); - FMLCommonHandler.instance().bus().register(ThreadSafeCache.getInstance()); + MinecraftForge.EVENT_BUS.register(ThreadSafeCache.getInstance()); } @EventHandler @@ -203,7 +201,7 @@ public class ForgeWorldEdit { public static ItemStack toForgeItemStack(BaseItemStack item) { ItemStack ret = new ItemStack(Item.getItemById(item.getType()), item.getAmount(), item.getData()); for (Map.Entry entry : item.getEnchantments().entrySet()) { - ret.addEnchantment(net.minecraft.enchantment.Enchantment.enchantmentsList[((Integer) entry.getKey())], (Integer) entry.getValue()); + ret.addEnchantment(net.minecraft.enchantment.Enchantment.getEnchantmentById(entry.getKey()), entry.getValue()); } return ret; diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java index 3acc1f6e5..a4ae912aa 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java @@ -19,13 +19,13 @@ package com.sk89q.worldedit.forge; -import java.nio.charset.Charset; +import com.sk89q.worldedit.LocalSession; +import java.nio.charset.Charset; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.PacketBuffer; import net.minecraft.network.ThreadQuickExitException; -import net.minecraft.network.play.server.S20PacketEntityProperties; import net.minecraft.network.play.server.S3FPacketCustomPayload; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.FMLEventChannel; @@ -33,8 +33,6 @@ import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientCustomPacketE import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent; import net.minecraftforge.fml.common.network.NetworkRegistry; -import com.sk89q.worldedit.LocalSession; - public class WECUIPacketHandler { public static final Charset UTF_8_CHARSET = Charset.forName("UTF-8"); public static FMLEventChannel WECUI_CHANNEL; From ea4dafe9af5a4e3d6705c1f1235660078de47cb5 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 12 Jan 2016 02:03:02 -0800 Subject: [PATCH 10/27] Use ATs for accessing fields. --- worldedit-forge/build.gradle | 3 +- .../com/sk89q/worldedit/forge/ForgeWorld.java | 60 ++++--------------- .../main/resources/META-INF/worldedit_at.cfg | 4 ++ 3 files changed, 19 insertions(+), 48 deletions(-) create mode 100644 worldedit-forge/src/main/resources/META-INF/worldedit_at.cfg diff --git a/worldedit-forge/build.gradle b/worldedit-forge/build.gradle index f95b9d4fb..dd5d5c9bd 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -55,7 +55,8 @@ processResources { jar { manifest { attributes("Class-Path": "truezip.jar WorldEdit/truezip.jar js.jar WorldEdit/js.jar", - "WorldEdit-Version": version) + "WorldEdit-Version": version, + "FMLAT": "worldedit_at.cfg") } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index 6b3f5e655..73eea7866 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -40,6 +40,14 @@ import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.registry.WorldData; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.block.BlockLeaves; import net.minecraft.block.BlockOldLeaf; @@ -56,7 +64,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockPos; import net.minecraft.util.ClassInheritanceMultiMap; -import net.minecraft.util.LongHashMap; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; import net.minecraft.world.WorldServer; @@ -77,16 +84,6 @@ import net.minecraft.world.gen.feature.WorldGenTaiga2; import net.minecraft.world.gen.feature.WorldGenTrees; import net.minecraft.world.gen.feature.WorldGenerator; -import javax.annotation.Nullable; - -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; import static com.google.common.base.Preconditions.checkNotNull; @@ -276,38 +273,7 @@ public class ForgeWorld extends AbstractWorld { return false; } ChunkProviderServer chunkServer = (ChunkProviderServer) provider; - Field u; - try { - u = ChunkProviderServer.class.getDeclaredField("field_73248_b"); // chunksToUnload - } catch(NoSuchFieldException e) { - u = ChunkProviderServer.class.getDeclaredField("chunksToUnload"); - } - u.setAccessible(true); - Set unloadQueue = (Set) u.get(chunkServer); - Field m; - try { - m = ChunkProviderServer.class.getDeclaredField("field_73244_f"); // loadedChunkHashMap - } catch(NoSuchFieldException e) { - m = ChunkProviderServer.class.getDeclaredField("loadedChunkHashMap"); - } - m.setAccessible(true); - LongHashMap loadedMap = (LongHashMap) m.get(chunkServer); - Field lc; - try { - lc = ChunkProviderServer.class.getDeclaredField("field_73245_g"); // loadedChunkHashMap - } catch(NoSuchFieldException e) { - lc = ChunkProviderServer.class.getDeclaredField("loadedChunks"); - } - lc.setAccessible(true); - @SuppressWarnings("unchecked") List loaded = (List) lc.get(chunkServer); - Field p; - try { - p = ChunkProviderServer.class.getDeclaredField("field_73246_d"); // currentChunkProvider - } catch(NoSuchFieldException e) { - p = ChunkProviderServer.class.getDeclaredField("currentChunkProvider"); - } - p.setAccessible(true); - IChunkProvider chunkProvider = (IChunkProvider) p.get(chunkServer); + IChunkProvider chunkProvider = chunkServer.serverChunkGenerator; for (Vector2D coord : chunks) { long pos = ChunkCoordIntPair.chunkXZ2Int(coord.getBlockX(), coord.getBlockZ()); @@ -316,11 +282,11 @@ public class ForgeWorld extends AbstractWorld { mcChunk = chunkServer.loadChunk(coord.getBlockX(), coord.getBlockZ()); mcChunk.onChunkUnload(); } - unloadQueue.remove(pos); - loadedMap.remove(pos); + chunkServer.droppedChunksSet.remove(pos); + chunkServer.id2ChunkMap.remove(pos); mcChunk = chunkProvider.provideChunk(coord.getBlockX(), coord.getBlockZ()); - loadedMap.add(pos, mcChunk); - loaded.add(mcChunk); + chunkServer.id2ChunkMap.add(pos, mcChunk); + chunkServer.loadedChunks.add(mcChunk); if (mcChunk != null) { mcChunk.onChunkLoad(); mcChunk.populateChunk(chunkProvider, chunkProvider, coord.getBlockX(), coord.getBlockZ()); diff --git a/worldedit-forge/src/main/resources/META-INF/worldedit_at.cfg b/worldedit-forge/src/main/resources/META-INF/worldedit_at.cfg new file mode 100644 index 000000000..33f039ce3 --- /dev/null +++ b/worldedit-forge/src/main/resources/META-INF/worldedit_at.cfg @@ -0,0 +1,4 @@ +public net.minecraft.world.gen.ChunkProviderServer field_73248_b # droppedChunksSet +public net.minecraft.world.gen.ChunkProviderServer field_73244_f # id2ChunkMap +public net.minecraft.world.gen.ChunkProviderServer field_73245_g # loadedChunks +public net.minecraft.world.gen.ChunkProviderServer field_73246_d # serverChunkGenerator From 5f08034ec11586610a4723dcbc0699ccf670a709 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 12 Jan 2016 02:06:59 -0800 Subject: [PATCH 11/27] Update gradle wrapper to 2.10 --- gradle/wrapper/gradle-wrapper.jar | Bin 51106 -> 53636 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 10 +- gradlew.bat | 180 +++++++++++------------ 4 files changed, 95 insertions(+), 99 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 3c7abdf12790879c06b07176de29647f77aa4129..13372aef5e24af05341d49695ee84e5f9b594659 100644 GIT binary patch delta 40732 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 delta 38240 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 +cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" -cd "$SAVED" >&- +cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -114,6 +109,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` diff --git a/gradlew.bat b/gradlew.bat index 8a0b282aa..aec99730b 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,90 +1,90 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 337ecb2864f397c901537611f6e5623f49e7d848 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 12 Jan 2016 02:15:33 -0800 Subject: [PATCH 12/27] Correct line endings from previous commits --- .../worldedit/forge/ForgeConfiguration.java | 88 +- .../sk89q/worldedit/forge/ForgePlayer.java | 444 ++++----- .../com/sk89q/worldedit/forge/ForgeWorld.java | 920 +++++++++--------- .../worldedit/forge/TileEntityBaseBlock.java | 78 +- .../worldedit/forge/WECUIPacketHandler.java | 142 +-- 5 files changed, 836 insertions(+), 836 deletions(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeConfiguration.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeConfiguration.java index efcaa1aab..011a6a3a1 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeConfiguration.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeConfiguration.java @@ -1,45 +1,45 @@ -/* - * 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.forge; - -import com.sk89q.worldedit.util.PropertiesConfiguration; - -import java.io.File; - -public class ForgeConfiguration extends PropertiesConfiguration { - - public boolean creativeEnable = false; - public boolean cheatMode = false; - - public ForgeConfiguration(ForgeWorldEdit mod) { - super(new File(mod.getWorkingDir() + File.separator + "worldedit.properties")); - } - - @Override - protected void loadExtra() { - creativeEnable = getBool("use-in-creative", false); - cheatMode = getBool("cheat-mode", false); - } - - @Override - public File getWorkingDirectory() { - return ForgeWorldEdit.inst.getWorkingDir(); - } +/* + * 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.forge; + +import com.sk89q.worldedit.util.PropertiesConfiguration; + +import java.io.File; + +public class ForgeConfiguration extends PropertiesConfiguration { + + public boolean creativeEnable = false; + public boolean cheatMode = false; + + public ForgeConfiguration(ForgeWorldEdit mod) { + super(new File(mod.getWorkingDir() + File.separator + "worldedit.properties")); + } + + @Override + protected void loadExtra() { + creativeEnable = getBool("use-in-creative", false); + cheatMode = getBool("cheat-mode", false); + } + + @Override + public File getWorkingDirectory() { + return ForgeWorldEdit.inst.getWorkingDir(); + } } \ No newline at end of file diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index 05153adeb..4553c1694 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -1,222 +1,222 @@ -/* - * 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.forge; - -import com.sk89q.util.StringUtil; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.WorldVector; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.extension.platform.AbstractPlayerActor; -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.util.Location; - -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.network.PacketBuffer; -import net.minecraft.network.play.server.S3FPacketCustomPayload; -import net.minecraft.util.ChatComponentText; -import io.netty.buffer.Unpooled; -import net.minecraft.util.EnumChatFormatting; - -import javax.annotation.Nullable; - -import java.util.UUID; - -public class ForgePlayer extends AbstractPlayerActor { - - private final ForgePlatform platform; - private final EntityPlayerMP player; - - protected ForgePlayer(ForgePlatform platform, EntityPlayerMP player) { - this.platform = platform; - this.player = player; - ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId()); - } - - @Override - public UUID getUniqueId() { - return player.getUniqueID(); - } - - @Override - public int getItemInHand() { - ItemStack is = this.player.getCurrentEquippedItem(); - return is == null ? 0 : Item.getIdFromItem(is.getItem()); - } - - @Override - public String getName() { - return this.player.getName(); - } - - @Override - public BaseEntity getState() { - throw new UnsupportedOperationException("Cannot create a state from this object"); - } - - @Override - public Location getLocation() { - Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ); - return new Location( - ForgeWorldEdit.inst.getWorld(this.player.worldObj), - position, - this.player.rotationYaw, - this.player.rotationPitch); - } - - @Override - public WorldVector getPosition() { - return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ); - } - - @Override - public com.sk89q.worldedit.world.World getWorld() { - return ForgeWorldEdit.inst.getWorld(this.player.worldObj); - } - - @Override - public double getPitch() { - return this.player.rotationPitch; - } - - @Override - public double getYaw() { - return this.player.rotationYaw; - } - - @Override - public void giveItem(int type, int amt) { - this.player.inventory.addItemStackToInventory(new ItemStack(Item.getItemById(type), amt, 0)); - } - - @Override - public void dispatchCUIEvent(CUIEvent event) { - String[] params = event.getParameters(); - String send = event.getTypeId(); - if (params.length > 0) { - send = send + "|" + StringUtil.joinString(params, "|"); - } - PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET))); - S3FPacketCustomPayload packet = new S3FPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer); - this.player.playerNetServerHandler.sendPacket(packet); - } - - @Override - public void printRaw(String msg) { - for (String part : msg.split("\n")) { - this.player.addChatMessage(new ChatComponentText(part)); - } - } - - @Override - public void printDebug(String msg) { - sendColorized(msg, EnumChatFormatting.GRAY); - } - - @Override - public void print(String msg) { - sendColorized(msg, EnumChatFormatting.LIGHT_PURPLE); - } - - @Override - public void printError(String msg) { - sendColorized(msg, EnumChatFormatting.RED); - } - - private void sendColorized(String msg, EnumChatFormatting formatting) { - for (String part : msg.split("\n")) { - ChatComponentText component = new ChatComponentText(part); - component.getChatStyle().setColor(formatting); - this.player.addChatMessage(component); - } - } - - @Override - public void setPosition(Vector pos, float pitch, float yaw) { - this.player.playerNetServerHandler.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch); - } - - @Override - public String[] getGroups() { - return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username); - } - - @Override - public BlockBag getInventoryBlockBag() { - return null; - } - - @Override - public boolean hasPermission(String perm) { - return ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm); - } - - @Nullable - @Override - public T getFacet(Class cls) { - return null; - } - - @Override - public SessionKey getSessionKey() { - return new SessionKeyImpl(player.getUniqueID(), player.getName()); - } - - private static class SessionKeyImpl implements SessionKey { - // If not static, this will leak a reference - - private final UUID uuid; - private final String name; - - private SessionKeyImpl(UUID uuid, String name) { - this.uuid = uuid; - this.name = name; - } - - @Override - public UUID getUniqueId() { - return uuid; - } - - @Nullable - @Override - public String getName() { - return name; - } - - @Override - public boolean isActive() { - // We can't directly check if the player is online because - // the list of players is not thread safe - return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid); - } - - @Override - public boolean isPersistent() { - return true; - } - - } - -} +/* + * 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.forge; + +import com.sk89q.util.StringUtil; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldVector; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.extension.platform.AbstractPlayerActor; +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.util.Location; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S3FPacketCustomPayload; +import net.minecraft.util.ChatComponentText; +import io.netty.buffer.Unpooled; +import net.minecraft.util.EnumChatFormatting; + +import javax.annotation.Nullable; + +import java.util.UUID; + +public class ForgePlayer extends AbstractPlayerActor { + + private final ForgePlatform platform; + private final EntityPlayerMP player; + + protected ForgePlayer(ForgePlatform platform, EntityPlayerMP player) { + this.platform = platform; + this.player = player; + ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId()); + } + + @Override + public UUID getUniqueId() { + return player.getUniqueID(); + } + + @Override + public int getItemInHand() { + ItemStack is = this.player.getCurrentEquippedItem(); + return is == null ? 0 : Item.getIdFromItem(is.getItem()); + } + + @Override + public String getName() { + return this.player.getName(); + } + + @Override + public BaseEntity getState() { + throw new UnsupportedOperationException("Cannot create a state from this object"); + } + + @Override + public Location getLocation() { + Vector position = new Vector(this.player.posX, this.player.posY, this.player.posZ); + return new Location( + ForgeWorldEdit.inst.getWorld(this.player.worldObj), + position, + this.player.rotationYaw, + this.player.rotationPitch); + } + + @Override + public WorldVector getPosition() { + return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ); + } + + @Override + public com.sk89q.worldedit.world.World getWorld() { + return ForgeWorldEdit.inst.getWorld(this.player.worldObj); + } + + @Override + public double getPitch() { + return this.player.rotationPitch; + } + + @Override + public double getYaw() { + return this.player.rotationYaw; + } + + @Override + public void giveItem(int type, int amt) { + this.player.inventory.addItemStackToInventory(new ItemStack(Item.getItemById(type), amt, 0)); + } + + @Override + public void dispatchCUIEvent(CUIEvent event) { + String[] params = event.getParameters(); + String send = event.getTypeId(); + if (params.length > 0) { + send = send + "|" + StringUtil.joinString(params, "|"); + } + PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET))); + S3FPacketCustomPayload packet = new S3FPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer); + this.player.playerNetServerHandler.sendPacket(packet); + } + + @Override + public void printRaw(String msg) { + for (String part : msg.split("\n")) { + this.player.addChatMessage(new ChatComponentText(part)); + } + } + + @Override + public void printDebug(String msg) { + sendColorized(msg, EnumChatFormatting.GRAY); + } + + @Override + public void print(String msg) { + sendColorized(msg, EnumChatFormatting.LIGHT_PURPLE); + } + + @Override + public void printError(String msg) { + sendColorized(msg, EnumChatFormatting.RED); + } + + private void sendColorized(String msg, EnumChatFormatting formatting) { + for (String part : msg.split("\n")) { + ChatComponentText component = new ChatComponentText(part); + component.getChatStyle().setColor(formatting); + this.player.addChatMessage(component); + } + } + + @Override + public void setPosition(Vector pos, float pitch, float yaw) { + this.player.playerNetServerHandler.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch); + } + + @Override + public String[] getGroups() { + return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username); + } + + @Override + public BlockBag getInventoryBlockBag() { + return null; + } + + @Override + public boolean hasPermission(String perm) { + return ForgeWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm); + } + + @Nullable + @Override + public T getFacet(Class cls) { + return null; + } + + @Override + public SessionKey getSessionKey() { + return new SessionKeyImpl(player.getUniqueID(), player.getName()); + } + + private static class SessionKeyImpl implements SessionKey { + // If not static, this will leak a reference + + private final UUID uuid; + private final String name; + + private SessionKeyImpl(UUID uuid, String name) { + this.uuid = uuid; + this.name = name; + } + + @Override + public UUID getUniqueId() { + return uuid; + } + + @Nullable + @Override + public String getName() { + return name; + } + + @Override + public boolean isActive() { + // We can't directly check if the player is online because + // the list of players is not thread safe + return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid); + } + + @Override + public boolean isPersistent() { + return true; + } + + } + +} diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index 73eea7866..bec590b03 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -1,460 +1,460 @@ -/* - * 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.forge; - -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.Vector2D; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.blocks.LazyBlock; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.entity.Entity; -import com.sk89q.worldedit.internal.Constants; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.TreeGenerator.TreeType; -import com.sk89q.worldedit.world.AbstractWorld; -import com.sk89q.worldedit.world.biome.BaseBiome; -import com.sk89q.worldedit.world.registry.WorldData; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nullable; -import net.minecraft.block.Block; -import net.minecraft.block.BlockLeaves; -import net.minecraft.block.BlockOldLeaf; -import net.minecraft.block.BlockOldLog; -import net.minecraft.block.BlockPlanks; -import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.EntityList; -import net.minecraft.entity.item.EntityItem; -import net.minecraft.init.Blocks; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.BlockPos; -import net.minecraft.util.ClassInheritanceMultiMap; -import net.minecraft.world.ChunkCoordIntPair; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.IChunkProvider; -import net.minecraft.world.gen.ChunkProviderServer; -import net.minecraft.world.gen.feature.WorldGenBigMushroom; -import net.minecraft.world.gen.feature.WorldGenBigTree; -import net.minecraft.world.gen.feature.WorldGenCanopyTree; -import net.minecraft.world.gen.feature.WorldGenForest; -import net.minecraft.world.gen.feature.WorldGenMegaJungle; -import net.minecraft.world.gen.feature.WorldGenMegaPineTree; -import net.minecraft.world.gen.feature.WorldGenSavannaTree; -import net.minecraft.world.gen.feature.WorldGenShrub; -import net.minecraft.world.gen.feature.WorldGenSwamp; -import net.minecraft.world.gen.feature.WorldGenTaiga1; -import net.minecraft.world.gen.feature.WorldGenTaiga2; -import net.minecraft.world.gen.feature.WorldGenTrees; -import net.minecraft.world.gen.feature.WorldGenerator; - - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * An adapter to Minecraft worlds for WorldEdit. - */ -public class ForgeWorld extends AbstractWorld { - - private static final Random random = new Random(); - private static final int UPDATE = 1, NOTIFY = 2, NOTIFY_CLIENT = 4; - private static final Logger logger = Logger.getLogger(ForgeWorld.class.getCanonicalName()); - - 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)); - - private final WeakReference worldRef; - - /** - * Construct a new world. - * - * @param world the world - */ - ForgeWorld(World world) { - checkNotNull(world); - this.worldRef = new WeakReference(world); - } - - /** - * Get the underlying handle to the world. - * - * @return the world - * @throws WorldEditException thrown if a reference to the world was lost (i.e. world was unloaded) - */ - public World getWorldChecked() throws WorldEditException { - World world = worldRef.get(); - if (world != null) { - return world; - } else { - throw new WorldReferenceLostException("The reference to the world was lost (i.e. the world may have been unloaded)"); - } - } - - /** - * Get the underlying handle to the world. - * - * @return the world - * @throws RuntimeException thrown if a reference to the world was lost (i.e. world was unloaded) - */ - public World getWorld() { - World world = worldRef.get(); - if (world != null) { - return world; - } else { - throw new RuntimeException("The reference to the world was lost (i.e. the world may have been unloaded)"); - } - } - - @Override - public String getName() { - return getWorld().getWorldInfo().getWorldName(); - } - - @Override - public boolean useItem(Vector position, BaseItem item, Direction face) { - Item nativeItem = Item.getItemById(item.getType()); - ItemStack stack = new ItemStack(nativeItem, 1, item.getData()); - World world = getWorld(); - return stack.tryPlaceItemIntoWorld(new WorldEditFakePlayer((WorldServer) world), world, position.getBlockX(), position.getBlockY(), position.getBlockZ(), ForgeAdapter.adapt(face), 0, 0, 0); - } - - @Override - public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException { - checkNotNull(position); - checkNotNull(block); - - World world = getWorldChecked(); - int x = position.getBlockX(); - int y = position.getBlockY(); - int z = position.getBlockZ(); - - // First set the block - Chunk chunk = world.getChunkFromChunkCoords(x >> 4, z >> 4); - BlockPos pos = new BlockPos(x, y, z); - IBlockState old = chunk.getBlockState(pos); - IBlockState newState = Block.getBlockById(block.getId()).getStateFromMeta(block.getData()); - IBlockState successState = chunk.setBlockState(pos, newState); - boolean successful = successState != null; - - // Create the TileEntity - if (successful) { - if (block.hasNbtData()) { - // Kill the old TileEntity - world.removeTileEntity(pos); - NBTTagCompound nativeTag = NBTConverter.toNative(block.getNbtData()); - nativeTag.setString("id", block.getNbtId()); - TileEntityUtils.setTileEntity(world, position, nativeTag); - } - } - - if (notifyAndLight) { - if (!successful) { - newState = old; - } - world.checkLight(pos); - world.markAndNotifyBlock(pos, chunk, old, newState, UPDATE | NOTIFY); - } - - return successful; - } - - @Override - public int getBlockLightLevel(Vector position) { - checkNotNull(position); - return getWorld().getLight(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ())); - } - - @Override - public boolean clearContainerBlockContents(Vector position) { - checkNotNull(position); - TileEntity tile = getWorld().getTileEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ())); - 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; - } - - @Override - public BaseBiome getBiome(Vector2D position) { - checkNotNull(position); - return new BaseBiome(getWorld().getBiomeGenForCoords(new BlockPos(position.getBlockX(), 0, position.getBlockZ())).biomeID); - } - - @Override - public boolean setBiome(Vector2D position, BaseBiome biome) { - checkNotNull(position); - checkNotNull(biome); - - Chunk chunk = getWorld().getChunkFromBlockCoords(new BlockPos(position.getBlockX(), 0, position.getBlockZ())); - if ((chunk != null) && (chunk.isLoaded())) { - chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = (byte) biome.getId(); - return true; - } - - return false; - } - - @Override - public void dropItem(Vector position, BaseItemStack item) { - checkNotNull(position); - checkNotNull(item); - - if (item.getType() == 0) { - return; - } - - EntityItem entity = new EntityItem(getWorld(), position.getX(), position.getY(), position.getZ(), ForgeWorldEdit.toForgeItemStack(item)); - entity.setPickupDelay(10); - getWorld().spawnEntityInWorld(entity); - } - - @Override - public boolean regenerate(Region region, EditSession editSession) { - BaseBlock[] history = new BaseBlock[256 * (getMaxY() + 1)]; - - for (Vector2D chunk : region.getChunks()) { - Vector min = new Vector(chunk.getBlockX() * 16, 0, chunk.getBlockZ() * 16); - - for (int x = 0; x < 16; x++) { - for (int y = 0; y < getMaxY() + 1; y++) { - for (int z = 0; z < 16; z++) { - Vector pt = min.add(x, y, z); - int index = y * 16 * 16 + z * 16 + x; - history[index] = editSession.getBlock(pt); - } - } - } - try { - Set chunks = region.getChunks(); - IChunkProvider provider = getWorld().getChunkProvider(); - if (!(provider instanceof ChunkProviderServer)) { - return false; - } - ChunkProviderServer chunkServer = (ChunkProviderServer) provider; - IChunkProvider chunkProvider = chunkServer.serverChunkGenerator; - - for (Vector2D coord : chunks) { - long pos = ChunkCoordIntPair.chunkXZ2Int(coord.getBlockX(), coord.getBlockZ()); - Chunk mcChunk; - if (chunkServer.chunkExists(coord.getBlockX(), coord.getBlockZ())) { - mcChunk = chunkServer.loadChunk(coord.getBlockX(), coord.getBlockZ()); - mcChunk.onChunkUnload(); - } - chunkServer.droppedChunksSet.remove(pos); - chunkServer.id2ChunkMap.remove(pos); - mcChunk = chunkProvider.provideChunk(coord.getBlockX(), coord.getBlockZ()); - chunkServer.id2ChunkMap.add(pos, mcChunk); - chunkServer.loadedChunks.add(mcChunk); - if (mcChunk != null) { - mcChunk.onChunkLoad(); - mcChunk.populateChunk(chunkProvider, chunkProvider, coord.getBlockX(), coord.getBlockZ()); - } - } - } catch (Throwable t) { - logger.log(Level.WARNING, "Failed to generate chunk", t); - return false; - } - - for (int x = 0; x < 16; x++) { - for (int y = 0; y < getMaxY() + 1; y++) { - for (int z = 0; z < 16; z++) { - Vector pt = min.add(x, y, z); - int index = y * 16 * 16 + z * 16 + x; - - if (!region.contains(pt)) - editSession.smartSetBlock(pt, history[index]); - else { - editSession.rememberChange(pt, history[index], editSession.rawGetBlock(pt)); - } - } - } - } - } - - return false; - } - - @Nullable - private static WorldGenerator createWorldGenerator(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 WorldGenForest(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 WorldGenForest(true, true); - case RANDOM: - case PINE: - case RANDOM_REDWOOD: - default: - return null; - } - } - - @Override - public boolean generateTree(TreeType type, EditSession editSession, Vector position) throws MaxChangedBlocksException { - WorldGenerator generator = createWorldGenerator(type); - return generator != null ? generator.generate(getWorld(), random, position.getBlockX(), position.getBlockY(), position.getBlockZ()) : false; - } - - @Override - public WorldData getWorldData() { - return ForgeWorldData.getInstance(); - } - - @Override - public boolean isValidBlockType(int id) { - return (id == 0) || (net.minecraft.block.Block.getBlockById(id) != null); - } - - @Override - public BaseBlock getBlock(Vector position) { - World world = getWorld(); - BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - IBlockState state = world.getBlockState(pos); - TileEntity tile = getWorld().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 = world.getBlockState(pos); - return new LazyBlock(Block.getIdFromBlock(state.getBlock()), state.getBlock().getMetaFromState(state), this, position); - } - - @Override - public int hashCode() { - return getWorld().hashCode(); - } - - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } else if ((o instanceof ForgeWorld)) { - ForgeWorld other = ((ForgeWorld) o); - 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; - } - } - - @Override - public List getEntities(Region region) { - List entities = new ArrayList(); - World world = getWorld(); - List ents = world.loadedEntityList; - for (net.minecraft.entity.Entity entity : ents) { - if (region.contains(new Vector(entity.posX, entity.posY, entity.posZ))) { - entities.add(new ForgeEntity(entity)); - } - } - return entities; - } - - @Override - public List getEntities() { - List entities = new ArrayList(); - for (net.minecraft.entity.Entity entity : getWorld().loadedEntityList) { - entities.add(new ForgeEntity(entity)); - } - return entities; - } - - @Nullable - @Override - public Entity createEntity(Location location, BaseEntity entity) { - World world = getWorld(); - net.minecraft.entity.Entity createdEntity = EntityList.createEntityByName(entity.getTypeId(), world); - if (createdEntity != null) { - CompoundTag nativeTag = entity.getNbtData(); - if (nativeTag != null) { - NBTTagCompound tag = NBTConverter.toNative(entity.getNbtData()); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { - tag.removeTag(name); - } - createdEntity.readFromNBT(tag); - } - - createdEntity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - - world.spawnEntityInWorld(createdEntity); - return new ForgeEntity(createdEntity); - } else { - return null; - } - } - - /** - * Thrown when the reference to the world is lost. - */ - private static class WorldReferenceLostException extends WorldEditException { - private WorldReferenceLostException(String message) { - super(message); - } - } - -} +/* + * 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.forge; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.blocks.LazyBlock; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.internal.Constants; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.TreeGenerator.TreeType; +import com.sk89q.worldedit.world.AbstractWorld; +import com.sk89q.worldedit.world.biome.BaseBiome; +import com.sk89q.worldedit.world.registry.WorldData; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLeaves; +import net.minecraft.block.BlockOldLeaf; +import net.minecraft.block.BlockOldLog; +import net.minecraft.block.BlockPlanks; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ClassInheritanceMultiMap; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.ChunkProviderServer; +import net.minecraft.world.gen.feature.WorldGenBigMushroom; +import net.minecraft.world.gen.feature.WorldGenBigTree; +import net.minecraft.world.gen.feature.WorldGenCanopyTree; +import net.minecraft.world.gen.feature.WorldGenForest; +import net.minecraft.world.gen.feature.WorldGenMegaJungle; +import net.minecraft.world.gen.feature.WorldGenMegaPineTree; +import net.minecraft.world.gen.feature.WorldGenSavannaTree; +import net.minecraft.world.gen.feature.WorldGenShrub; +import net.minecraft.world.gen.feature.WorldGenSwamp; +import net.minecraft.world.gen.feature.WorldGenTaiga1; +import net.minecraft.world.gen.feature.WorldGenTaiga2; +import net.minecraft.world.gen.feature.WorldGenTrees; +import net.minecraft.world.gen.feature.WorldGenerator; + + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * An adapter to Minecraft worlds for WorldEdit. + */ +public class ForgeWorld extends AbstractWorld { + + private static final Random random = new Random(); + private static final int UPDATE = 1, NOTIFY = 2, NOTIFY_CLIENT = 4; + private static final Logger logger = Logger.getLogger(ForgeWorld.class.getCanonicalName()); + + 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)); + + private final WeakReference worldRef; + + /** + * Construct a new world. + * + * @param world the world + */ + ForgeWorld(World world) { + checkNotNull(world); + this.worldRef = new WeakReference(world); + } + + /** + * Get the underlying handle to the world. + * + * @return the world + * @throws WorldEditException thrown if a reference to the world was lost (i.e. world was unloaded) + */ + public World getWorldChecked() throws WorldEditException { + World world = worldRef.get(); + if (world != null) { + return world; + } else { + throw new WorldReferenceLostException("The reference to the world was lost (i.e. the world may have been unloaded)"); + } + } + + /** + * Get the underlying handle to the world. + * + * @return the world + * @throws RuntimeException thrown if a reference to the world was lost (i.e. world was unloaded) + */ + public World getWorld() { + World world = worldRef.get(); + if (world != null) { + return world; + } else { + throw new RuntimeException("The reference to the world was lost (i.e. the world may have been unloaded)"); + } + } + + @Override + public String getName() { + return getWorld().getWorldInfo().getWorldName(); + } + + @Override + public boolean useItem(Vector position, BaseItem item, Direction face) { + Item nativeItem = Item.getItemById(item.getType()); + ItemStack stack = new ItemStack(nativeItem, 1, item.getData()); + World world = getWorld(); + return stack.tryPlaceItemIntoWorld(new WorldEditFakePlayer((WorldServer) world), world, position.getBlockX(), position.getBlockY(), position.getBlockZ(), ForgeAdapter.adapt(face), 0, 0, 0); + } + + @Override + public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException { + checkNotNull(position); + checkNotNull(block); + + World world = getWorldChecked(); + int x = position.getBlockX(); + int y = position.getBlockY(); + int z = position.getBlockZ(); + + // First set the block + Chunk chunk = world.getChunkFromChunkCoords(x >> 4, z >> 4); + BlockPos pos = new BlockPos(x, y, z); + IBlockState old = chunk.getBlockState(pos); + IBlockState newState = Block.getBlockById(block.getId()).getStateFromMeta(block.getData()); + IBlockState successState = chunk.setBlockState(pos, newState); + boolean successful = successState != null; + + // Create the TileEntity + if (successful) { + if (block.hasNbtData()) { + // Kill the old TileEntity + world.removeTileEntity(pos); + NBTTagCompound nativeTag = NBTConverter.toNative(block.getNbtData()); + nativeTag.setString("id", block.getNbtId()); + TileEntityUtils.setTileEntity(world, position, nativeTag); + } + } + + if (notifyAndLight) { + if (!successful) { + newState = old; + } + world.checkLight(pos); + world.markAndNotifyBlock(pos, chunk, old, newState, UPDATE | NOTIFY); + } + + return successful; + } + + @Override + public int getBlockLightLevel(Vector position) { + checkNotNull(position); + return getWorld().getLight(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ())); + } + + @Override + public boolean clearContainerBlockContents(Vector position) { + checkNotNull(position); + TileEntity tile = getWorld().getTileEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ())); + 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; + } + + @Override + public BaseBiome getBiome(Vector2D position) { + checkNotNull(position); + return new BaseBiome(getWorld().getBiomeGenForCoords(new BlockPos(position.getBlockX(), 0, position.getBlockZ())).biomeID); + } + + @Override + public boolean setBiome(Vector2D position, BaseBiome biome) { + checkNotNull(position); + checkNotNull(biome); + + Chunk chunk = getWorld().getChunkFromBlockCoords(new BlockPos(position.getBlockX(), 0, position.getBlockZ())); + if ((chunk != null) && (chunk.isLoaded())) { + chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = (byte) biome.getId(); + return true; + } + + return false; + } + + @Override + public void dropItem(Vector position, BaseItemStack item) { + checkNotNull(position); + checkNotNull(item); + + if (item.getType() == 0) { + return; + } + + EntityItem entity = new EntityItem(getWorld(), position.getX(), position.getY(), position.getZ(), ForgeWorldEdit.toForgeItemStack(item)); + entity.setPickupDelay(10); + getWorld().spawnEntityInWorld(entity); + } + + @Override + public boolean regenerate(Region region, EditSession editSession) { + BaseBlock[] history = new BaseBlock[256 * (getMaxY() + 1)]; + + for (Vector2D chunk : region.getChunks()) { + Vector min = new Vector(chunk.getBlockX() * 16, 0, chunk.getBlockZ() * 16); + + for (int x = 0; x < 16; x++) { + for (int y = 0; y < getMaxY() + 1; y++) { + for (int z = 0; z < 16; z++) { + Vector pt = min.add(x, y, z); + int index = y * 16 * 16 + z * 16 + x; + history[index] = editSession.getBlock(pt); + } + } + } + try { + Set chunks = region.getChunks(); + IChunkProvider provider = getWorld().getChunkProvider(); + if (!(provider instanceof ChunkProviderServer)) { + return false; + } + ChunkProviderServer chunkServer = (ChunkProviderServer) provider; + IChunkProvider chunkProvider = chunkServer.serverChunkGenerator; + + for (Vector2D coord : chunks) { + long pos = ChunkCoordIntPair.chunkXZ2Int(coord.getBlockX(), coord.getBlockZ()); + Chunk mcChunk; + if (chunkServer.chunkExists(coord.getBlockX(), coord.getBlockZ())) { + mcChunk = chunkServer.loadChunk(coord.getBlockX(), coord.getBlockZ()); + mcChunk.onChunkUnload(); + } + chunkServer.droppedChunksSet.remove(pos); + chunkServer.id2ChunkMap.remove(pos); + mcChunk = chunkProvider.provideChunk(coord.getBlockX(), coord.getBlockZ()); + chunkServer.id2ChunkMap.add(pos, mcChunk); + chunkServer.loadedChunks.add(mcChunk); + if (mcChunk != null) { + mcChunk.onChunkLoad(); + mcChunk.populateChunk(chunkProvider, chunkProvider, coord.getBlockX(), coord.getBlockZ()); + } + } + } catch (Throwable t) { + logger.log(Level.WARNING, "Failed to generate chunk", t); + return false; + } + + for (int x = 0; x < 16; x++) { + for (int y = 0; y < getMaxY() + 1; y++) { + for (int z = 0; z < 16; z++) { + Vector pt = min.add(x, y, z); + int index = y * 16 * 16 + z * 16 + x; + + if (!region.contains(pt)) + editSession.smartSetBlock(pt, history[index]); + else { + editSession.rememberChange(pt, history[index], editSession.rawGetBlock(pt)); + } + } + } + } + } + + return false; + } + + @Nullable + private static WorldGenerator createWorldGenerator(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 WorldGenForest(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 WorldGenForest(true, true); + case RANDOM: + case PINE: + case RANDOM_REDWOOD: + default: + return null; + } + } + + @Override + public boolean generateTree(TreeType type, EditSession editSession, Vector position) throws MaxChangedBlocksException { + WorldGenerator generator = createWorldGenerator(type); + return generator != null ? generator.generate(getWorld(), random, position.getBlockX(), position.getBlockY(), position.getBlockZ()) : false; + } + + @Override + public WorldData getWorldData() { + return ForgeWorldData.getInstance(); + } + + @Override + public boolean isValidBlockType(int id) { + return (id == 0) || (net.minecraft.block.Block.getBlockById(id) != null); + } + + @Override + public BaseBlock getBlock(Vector position) { + World world = getWorld(); + BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + IBlockState state = world.getBlockState(pos); + TileEntity tile = getWorld().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 = world.getBlockState(pos); + return new LazyBlock(Block.getIdFromBlock(state.getBlock()), state.getBlock().getMetaFromState(state), this, position); + } + + @Override + public int hashCode() { + return getWorld().hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } else if ((o instanceof ForgeWorld)) { + ForgeWorld other = ((ForgeWorld) o); + 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; + } + } + + @Override + public List getEntities(Region region) { + List entities = new ArrayList(); + World world = getWorld(); + List ents = world.loadedEntityList; + for (net.minecraft.entity.Entity entity : ents) { + if (region.contains(new Vector(entity.posX, entity.posY, entity.posZ))) { + entities.add(new ForgeEntity(entity)); + } + } + return entities; + } + + @Override + public List getEntities() { + List entities = new ArrayList(); + for (net.minecraft.entity.Entity entity : getWorld().loadedEntityList) { + entities.add(new ForgeEntity(entity)); + } + return entities; + } + + @Nullable + @Override + public Entity createEntity(Location location, BaseEntity entity) { + World world = getWorld(); + net.minecraft.entity.Entity createdEntity = EntityList.createEntityByName(entity.getTypeId(), world); + if (createdEntity != null) { + CompoundTag nativeTag = entity.getNbtData(); + if (nativeTag != null) { + NBTTagCompound tag = NBTConverter.toNative(entity.getNbtData()); + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.removeTag(name); + } + createdEntity.readFromNBT(tag); + } + + createdEntity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + + world.spawnEntityInWorld(createdEntity); + return new ForgeEntity(createdEntity); + } else { + return null; + } + } + + /** + * Thrown when the reference to the world is lost. + */ + private static class WorldReferenceLostException extends WorldEditException { + private WorldReferenceLostException(String message) { + super(message); + } + } + +} diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/TileEntityBaseBlock.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/TileEntityBaseBlock.java index a17ac5d43..068482408 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/TileEntityBaseBlock.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/TileEntityBaseBlock.java @@ -1,40 +1,40 @@ -/* - * 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.forge; - -import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.blocks.TileEntityBlock; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; - -public class TileEntityBaseBlock extends BaseBlock implements TileEntityBlock { - - public TileEntityBaseBlock(int type, int data, TileEntity tile) { - super(type, data); - setNbtData(NBTConverter.fromNative(copyNbtData(tile))); - } - - private static NBTTagCompound copyNbtData(TileEntity tile) { - NBTTagCompound tag = new NBTTagCompound(); - tile.writeToNBT(tag); - return tag; - } - +/* + * 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.forge; + +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.TileEntityBlock; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; + +public class TileEntityBaseBlock extends BaseBlock implements TileEntityBlock { + + public TileEntityBaseBlock(int type, int data, TileEntity tile) { + super(type, data); + setNbtData(NBTConverter.fromNative(copyNbtData(tile))); + } + + private static NBTTagCompound copyNbtData(TileEntity tile) { + NBTTagCompound tag = new NBTTagCompound(); + tile.writeToNBT(tag); + return tag; + } + } \ No newline at end of file diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java index a4ae912aa..24da15c53 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/WECUIPacketHandler.java @@ -1,72 +1,72 @@ -/* - * 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.forge; - -import com.sk89q.worldedit.LocalSession; - -import java.nio.charset.Charset; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.network.NetHandlerPlayServer; -import net.minecraft.network.PacketBuffer; -import net.minecraft.network.ThreadQuickExitException; -import net.minecraft.network.play.server.S3FPacketCustomPayload; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.network.FMLEventChannel; -import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent; -import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent; -import net.minecraftforge.fml.common.network.NetworkRegistry; - -public class WECUIPacketHandler { - public static final Charset UTF_8_CHARSET = Charset.forName("UTF-8"); - public static FMLEventChannel WECUI_CHANNEL; - - public static void init() { - WECUI_CHANNEL = NetworkRegistry.INSTANCE.newEventDrivenChannel(ForgeWorldEdit.CUI_PLUGIN_CHANNEL); - WECUI_CHANNEL.register(new WECUIPacketHandler()); - } - - @SubscribeEvent - public void onPacketData(ServerCustomPacketEvent event) { - if (event.packet.channel().equals(ForgeWorldEdit.CUI_PLUGIN_CHANNEL)) { - EntityPlayerMP player = getPlayerFromEvent(event); - LocalSession session = ForgeWorldEdit.inst.getSession((EntityPlayerMP) player); - - if (session.hasCUISupport()) { - return; - } - - String text = event.packet.payload().toString(UTF_8_CHARSET); - session.handleCUIInitializationMessage(text); - session.describeCUI(ForgeWorldEdit.inst.wrap(player)); - } - } - - @SubscribeEvent - public void callProcessPacket(ClientCustomPacketEvent event) { - try { - new S3FPacketCustomPayload(event.packet.channel(), new PacketBuffer(event.packet.payload())).processPacket(event.handler); - } catch (ThreadQuickExitException suppress) { - } - } - - private static EntityPlayerMP getPlayerFromEvent(ServerCustomPacketEvent event) { - return ((NetHandlerPlayServer) event.handler).playerEntity; - } +/* + * 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.forge; + +import com.sk89q.worldedit.LocalSession; + +import java.nio.charset.Charset; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.ThreadQuickExitException; +import net.minecraft.network.play.server.S3FPacketCustomPayload; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.FMLEventChannel; +import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent; +import net.minecraftforge.fml.common.network.NetworkRegistry; + +public class WECUIPacketHandler { + public static final Charset UTF_8_CHARSET = Charset.forName("UTF-8"); + public static FMLEventChannel WECUI_CHANNEL; + + public static void init() { + WECUI_CHANNEL = NetworkRegistry.INSTANCE.newEventDrivenChannel(ForgeWorldEdit.CUI_PLUGIN_CHANNEL); + WECUI_CHANNEL.register(new WECUIPacketHandler()); + } + + @SubscribeEvent + public void onPacketData(ServerCustomPacketEvent event) { + if (event.packet.channel().equals(ForgeWorldEdit.CUI_PLUGIN_CHANNEL)) { + EntityPlayerMP player = getPlayerFromEvent(event); + LocalSession session = ForgeWorldEdit.inst.getSession((EntityPlayerMP) player); + + if (session.hasCUISupport()) { + return; + } + + String text = event.packet.payload().toString(UTF_8_CHARSET); + session.handleCUIInitializationMessage(text); + session.describeCUI(ForgeWorldEdit.inst.wrap(player)); + } + } + + @SubscribeEvent + public void callProcessPacket(ClientCustomPacketEvent event) { + try { + new S3FPacketCustomPayload(event.packet.channel(), new PacketBuffer(event.packet.payload())).processPacket(event.handler); + } catch (ThreadQuickExitException suppress) { + } + } + + private static EntityPlayerMP getPlayerFromEvent(ServerCustomPacketEvent event) { + return ((NetHandlerPlayServer) event.handler).playerEntity; + } } \ No newline at end of file From e91859130c39fe2b32473da77a44da54c9bf2822 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 12 Jan 2016 02:23:49 -0800 Subject: [PATCH 13/27] Fixes for master-rebase on forge1.8 --- .../sk89q/worldedit/forge/CommandWrapper.java | 23 ++------ .../sk89q/worldedit/forge/ForgeAdapter.java | 24 ++++----- .../worldedit/forge/ForgeItemRegistry.java | 53 ------------------- .../com/sk89q/worldedit/forge/ForgeWorld.java | 17 +----- .../sk89q/worldedit/forge/ForgeWorldData.java | 7 --- 5 files changed, 17 insertions(+), 107 deletions(-) delete mode 100644 worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeItemRegistry.java diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java index daf76bad6..2b555c851 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java @@ -19,18 +19,14 @@ package com.sk89q.worldedit.forge; -import com.google.common.base.Joiner; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.util.command.CommandMapping; + +import java.util.Arrays; +import java.util.List; +import javax.annotation.Nullable; import net.minecraft.command.CommandBase; import net.minecraft.command.ICommand; import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayerMP; - -import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.List; public class CommandWrapper extends CommandBase { private CommandMapping command; @@ -52,17 +48,6 @@ public class CommandWrapper extends CommandBase { @Override public void processCommand(ICommandSender var1, String[] var2) {} - @Override - public List addTabCompletionOptions(ICommandSender sender, String[] arguments) { - if (sender instanceof EntityPlayerMP) { - CommandSuggestionEvent event = new CommandSuggestionEvent(ForgeWorldEdit.inst.wrap((EntityPlayerMP) sender), command.getPrimaryAlias() + " " + Joiner.on(" ").join(arguments)); - WorldEdit.getInstance().getEventBus().post(event); - return event.getSuggestions(); - } else { - return super.addTabCompletionOptions(sender, arguments); - } - } - @Override public String getCommandUsage(ICommandSender icommandsender) { return "/" + command.getPrimaryAlias() + " " + command.getDescription().getUsage(); diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java index c7195da31..9c64b9403 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java @@ -20,10 +20,9 @@ package com.sk89q.worldedit.forge; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.world.World; +import net.minecraft.util.BlockPos; import net.minecraft.util.Vec3; -import net.minecraftforge.common.util.ForgeDirection; final class ForgeAdapter { @@ -38,15 +37,16 @@ final class ForgeAdapter { return new Vector(vector.xCoord, vector.yCoord, vector.zCoord); } - public static int adapt(Direction face) { - switch (face) { - case NORTH: return ForgeDirection.NORTH.ordinal(); - case SOUTH: return ForgeDirection.SOUTH.ordinal(); - case WEST: return ForgeDirection.WEST.ordinal(); - case EAST: return ForgeDirection.EAST.ordinal(); - case UP: return ForgeDirection.UP.ordinal(); - case DOWN: return ForgeDirection.DOWN.ordinal(); - default: return ForgeDirection.UNKNOWN.ordinal(); - } + public static Vector adapt(BlockPos pos) { + return new Vector(pos.getX(), pos.getY(), pos.getZ()); } + + public static Vec3 toVec3(Vector vector) { + return new Vec3(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + } + + public static BlockPos toBlockPos(Vector vector) { + return new BlockPos(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + } + } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeItemRegistry.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeItemRegistry.java deleted file mode 100644 index 3dcb0dbf3..000000000 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeItemRegistry.java +++ /dev/null @@ -1,53 +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.forge; - -import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.world.registry.ItemRegistry; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nullable; - -public class ForgeItemRegistry implements ItemRegistry { - - @Nullable - @Override - public BaseItem createFromId(String id) { - Item item = (Item) Item.itemRegistry.getObject(id); - if (item != null) { - return new BaseItem(Item.getIdFromItem(item), (short) item.getDamage(new ItemStack(item, 1))); - } else { - return null; - } - } - - @Nullable - @Override - public BaseItem createFromId(int id) { - Item item = (Item) Item.itemRegistry.getObjectById(id); - if (item != null) { - return new BaseItem(Item.getIdFromItem(item), (short) item.getDamage(new ItemStack(item, 1))); - } else { - return null; - } - } - -} diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index bec590b03..e89c46112 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -26,14 +26,12 @@ import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.LazyBlock; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.TreeGenerator.TreeType; import com.sk89q.worldedit.world.AbstractWorld; @@ -58,15 +56,11 @@ import net.minecraft.entity.EntityList; import net.minecraft.entity.item.EntityItem; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockPos; -import net.minecraft.util.ClassInheritanceMultiMap; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; -import net.minecraft.world.WorldServer; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.gen.ChunkProviderServer; @@ -84,7 +78,6 @@ import net.minecraft.world.gen.feature.WorldGenTaiga2; import net.minecraft.world.gen.feature.WorldGenTrees; import net.minecraft.world.gen.feature.WorldGenerator; - import static com.google.common.base.Preconditions.checkNotNull; /** @@ -147,14 +140,6 @@ public class ForgeWorld extends AbstractWorld { return getWorld().getWorldInfo().getWorldName(); } - @Override - public boolean useItem(Vector position, BaseItem item, Direction face) { - Item nativeItem = Item.getItemById(item.getType()); - ItemStack stack = new ItemStack(nativeItem, 1, item.getData()); - World world = getWorld(); - return stack.tryPlaceItemIntoWorld(new WorldEditFakePlayer((WorldServer) world), world, position.getBlockX(), position.getBlockY(), position.getBlockZ(), ForgeAdapter.adapt(face), 0, 0, 0); - } - @Override public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException { checkNotNull(position); @@ -346,7 +331,7 @@ public class ForgeWorld extends AbstractWorld { @Override public boolean generateTree(TreeType type, EditSession editSession, Vector position) throws MaxChangedBlocksException { WorldGenerator generator = createWorldGenerator(type); - return generator != null ? generator.generate(getWorld(), random, position.getBlockX(), position.getBlockY(), position.getBlockZ()) : false; + return generator != null ? generator.generate(getWorld(), random, ForgeAdapter.toBlockPos(position)) : false; } @Override diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldData.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldData.java index 33248463b..249e93ddc 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldData.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldData.java @@ -20,7 +20,6 @@ package com.sk89q.worldedit.forge; import com.sk89q.worldedit.world.registry.BiomeRegistry; -import com.sk89q.worldedit.world.registry.ItemRegistry; import com.sk89q.worldedit.world.registry.LegacyWorldData; /** @@ -29,14 +28,8 @@ import com.sk89q.worldedit.world.registry.LegacyWorldData; class ForgeWorldData extends LegacyWorldData { private static final ForgeWorldData INSTANCE = new ForgeWorldData(); - private final ItemRegistry itemRegistry = new ForgeItemRegistry(); private final BiomeRegistry biomeRegistry = new ForgeBiomeRegistry(); - @Override - public ItemRegistry getItemRegistry() { - return itemRegistry; - } - @Override public BiomeRegistry getBiomeRegistry() { return biomeRegistry; From e19820e04d8fd90c4c587abf252e70c83437e345 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 12 Jan 2016 15:32:58 -0800 Subject: [PATCH 14/27] Fix shadow, remove extra source jar in forge --- build.gradle | 19 ++++++++++++------- worldedit-forge/build.gradle | 6 ++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index b797f51f2..be685f667 100644 --- a/build.gradle +++ b/build.gradle @@ -75,11 +75,6 @@ subprojects { } } - task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource - } - task javadocJar(type: Jar, dependsOn: javadoc) { classifier = 'javadoc' from javadoc.destinationDir @@ -87,13 +82,23 @@ subprojects { artifacts { archives jar - archives sourcesJar archives javadocJar } + if (!name.equals('worldedit-forge')) { + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource + } + + artifacts { + archives sourcesJar + } + build.dependsOn(sourcesJar) + } + build.dependsOn(checkstyleMain) build.dependsOn(checkstyleTest) - build.dependsOn(sourcesJar) build.dependsOn(javadocJar) shadowJar { diff --git a/worldedit-forge/build.gradle b/worldedit-forge/build.gradle index dd5d5c9bd..d705b95ea 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -67,7 +67,9 @@ shadowJar { } reobf { - shadowJar + shadowJar { + mappingType = 'SEARGE' + } } task deobfJar(type: Jar) { @@ -79,4 +81,4 @@ artifacts { archives deobfJar } -build.dependsOn(shadowJar) +build.dependsOn(reobfShadowJar) From 8c5b455d0f64280518d3eff7ee877202c08cbba2 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 12 Jan 2016 20:54:19 -0800 Subject: [PATCH 15/27] [Forge] Don't need to depend this --- worldedit-forge/build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/worldedit-forge/build.gradle b/worldedit-forge/build.gradle index d705b95ea..a6aa0eaf8 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -80,5 +80,3 @@ task deobfJar(type: Jar) { artifacts { archives deobfJar } - -build.dependsOn(reobfShadowJar) From 1fe197df98517d8ea825008e602f59c34fc694bc Mon Sep 17 00:00:00 2001 From: wizjany Date: Sat, 16 Jan 2016 23:42:21 -0500 Subject: [PATCH 16/27] Fix build script versioning, release a 1.8.9 build. --- build.gradle | 2 +- worldedit-forge/build.gradle | 3 +++ worldedit-forge/src/main/resources/mcmod.info | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index be685f667..fbe0f78ad 100644 --- a/build.gradle +++ b/build.gradle @@ -38,7 +38,7 @@ if (!project.hasProperty("artifactory_password")) ext.artifactory_password = "" if (!project.hasProperty("gitCommitHash")) { try { - def repo = Grgit.open(project.file('.')) + def repo = org.ajoberstar.grgit.Grgit.open(project.file('.')) ext.gitCommitHash = repo.head().abbreviatedId } catch (Exception e) { ext.gitCommitHash = "no_git_id" diff --git a/worldedit-forge/build.gradle b/worldedit-forge/build.gradle index a6aa0eaf8..2873f5608 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -26,7 +26,10 @@ repositories { } } +version = "6.1.1" ext.forgeVersion = "11.15.0.1695" +ext.internalVersion = version + ";" + gitCommitHash + minecraft { version = "1.8.9-${project.forgeVersion}" mappings = "snapshot_20160111" diff --git a/worldedit-forge/src/main/resources/mcmod.info b/worldedit-forge/src/main/resources/mcmod.info index df47ddfac..b21a45185 100644 --- a/worldedit-forge/src/main/resources/mcmod.info +++ b/worldedit-forge/src/main/resources/mcmod.info @@ -6,7 +6,7 @@ "mcversion": "${mcVersion}", "url": "http://wiki.sk89q.com/wiki/WorldEdit", "updateUrl": "", - "authors": [ "sk89q", "wizjany", "TomyLobo" ], + "authors": [ "sk89q", "wizjany", "TomyLobo", "kenzierocks" ], "credits": "", "logoFile": "", "screenshots": [], From 136c66868f20ca19cc6c46495e88acecaedad5e8 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 17:01:09 -0800 Subject: [PATCH 17/27] Move sponge dependency to mcmod --- .../main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java | 2 +- worldedit-forge/src/main/resources/mcmod.info | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java index 2ba05bf28..5ae29054e 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java @@ -59,7 +59,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * The Forge implementation of WorldEdit. */ -@Mod(modid = ForgeWorldEdit.MOD_ID, name = "WorldEdit", version = "%VERSION%", acceptableRemoteVersions = "*", dependencies = "after:sponge") +@Mod(modid = ForgeWorldEdit.MOD_ID, name = "WorldEdit", version = "%VERSION%", acceptableRemoteVersions = "*") public class ForgeWorldEdit { public static Logger logger; diff --git a/worldedit-forge/src/main/resources/mcmod.info b/worldedit-forge/src/main/resources/mcmod.info index b21a45185..02b53f838 100644 --- a/worldedit-forge/src/main/resources/mcmod.info +++ b/worldedit-forge/src/main/resources/mcmod.info @@ -14,7 +14,8 @@ "Forge@[${forgeVersion},)" ], "dependencies": [ - "Forge@[${forgeVersion},)" + "Forge@[${forgeVersion},)", + "sponge" ], "dependants": [] }] From a9fc46cef620c2b8b7cd97bd2ff47411f3e67e30 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 17:11:29 -0800 Subject: [PATCH 18/27] Correlate modids in code and mcmod.info --- worldedit-forge/src/main/resources/mcmod.info | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-forge/src/main/resources/mcmod.info b/worldedit-forge/src/main/resources/mcmod.info index 02b53f838..599e2f5e1 100644 --- a/worldedit-forge/src/main/resources/mcmod.info +++ b/worldedit-forge/src/main/resources/mcmod.info @@ -1,5 +1,5 @@ [{ - "modid": "WorldEdit", + "modid": "worldedit", "name": "WorldEdit", "description": "WorldEdit is an easy-to-use in-game world editor for Minecraft, supporting both single player and multiplayer.", "version": "${internalVersion}", From 74167b8b9f86870842b392a4cf34ae68e22b346b Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 17:37:45 -0800 Subject: [PATCH 19/27] Update forge version. Not really needed, but why not? --- worldedit-forge/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-forge/build.gradle b/worldedit-forge/build.gradle index 2873f5608..e977bee24 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -27,7 +27,7 @@ repositories { } version = "6.1.1" -ext.forgeVersion = "11.15.0.1695" +ext.forgeVersion = "11.15.1.1760" ext.internalVersion = version + ";" + gitCommitHash minecraft { From fb52a86eae56aed82b3b5b43f71adb23f1dd5d42 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 17:40:18 -0800 Subject: [PATCH 20/27] Update shadow plugin in build.gradle Needed to build this with the latest Gradle release. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index fbe0f78ad..aebadd65e 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ buildscript { } dependencies { - classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.0' + classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1' classpath 'org.ajoberstar:gradle-git:0.12.0' } From 775075d3a732fdffea28cdb650c98fce90548864 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 17:41:03 -0800 Subject: [PATCH 21/27] Update gradle wrapper to 2.11. --- gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 53638 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew.bat | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 13372aef5e24af05341d49695ee84e5f9b594659..5ccda13e9cb94678ba179b32452cf3d60dc36353 100644 GIT binary patch delta 2494 zcmaJ?2~bl<7~Z^uBtnRCgu;^}f}lt#5nC@{)WJe(6oW#cl?qW1Ml(Poo;Y$;utS+r zSgWnrB87@tMvkC(U`06s$TipaX(I0>zsY5lAl+TM7y0A-%<7A`34Qf-SYlVX-#bP!Yl0it;LN zMY;Dvb>dF*V1>8h-3Kr*%6%FiG4t*$oZkWWM7gB+<*Z1klS?w5OniMxd_$PWKXTV? z&1LPK9n^ypAv|Y!*Zx;|XY&)D=nD!SA6ATAw{(y}o%7&MqlI(#mIvBm;95MCF)CDh zZSu%m(%8B2^6%qtS1K*)s}Zfe&s%#d?Plt#9iv(8(u=Xx5gRIVvrA+z!b=N2f9PGQ zz6ZbCIPAG-``PubJF9tZNeNMg(KI6QpePrr{yEPsHW}+|A9HcCm znRjGN&Itg(5PIjruB6#;b96P~IL5r9$V?tL#Lgt!@_1Oc?5((e3?cvyS^?mPb=EER z`X|~h5s}moXpVbsvpY^VO<61lvon+M4^$zjK%lZ*^QF30`hNmDaFU` z&()T1{{{s-EhO&eLAt|6f3NHZR+3Q}!MgcPznm4jpYLF?i3{t=;su-&KlkGU&@v4G zAM7iq%>+uiWcu%G0{LR5Xzj7!L-6sHmE0y&teY)Nea`& zXkP$wiXQNL^XnEw@`Z3V2D$@K{4 z3T)nfGgDl8^p+w->_)E(dS5?PX%0M?)*ypt!o;xksNQ_{LqJ{~ zO^L-g{$jBlhSy85nO5_S0l7#!h8lpYb(A8qJv>_HL;_q!0mf(G0Hby81e;k;Q=T>$ z`@}{v8MIwDoFzkNB3=rB8^=(sEhZantzc=rgaoNULG0uhe_U@zFw+K_(k;N4PlFq- zQrS~I`v%%v7h7~dIYHB4YQrL;yM%N{{jqMO!39@%yWL{rODrz$NL9x%+o2N;$aXr30f7#zvZ z5d%%-YhYiA9czam^PxL1i3!(pZyz! zY1adZnbzwxHJlEQmO4YzR&rlLc`HrTWx?JoUuN}iV$NmDF?S>zB~~(3kbo0N{C*C? zoZ-?oHlVtVri_J9Q!^JHYO^D}3WN<5v&$@m6K$3_(Qdc?kSKI^X>`x{a1t3x(4P8D z?Pqd3O{JD1=kH8b%(=li;!J34f4%%2G_|J^uU1**^vMeSyKDv@p_ST)68mzrxAlnZ z0(&~x2H|zmJO^msslX3scmeA?FIqrF3t2|aw}C?rtU=4;$D9z{ ZNX!=^01=ow(TPLsg{!-~g;BK(_%D0s@`L~Y delta 2495 zcmZWq2~bl<7~VWWh!O%s2=L^Hpj?WCAj;u|SV0*qD0om*aJUMLP_;l+E(K}97G>4Z zmZ=Be!Jr(8wpv6GNVqS>W0Yi&(7NJWP*Z4zjQ*q?hfk z&+>{qP4x+O#_#21G2`b>w{iM$0RSp7EaKDfS+f8JsfEfLD=P#NW;{WbuwTUkV2us{ zo&e^ky_M}@^*o}oZ*8bh$gmnL7OLU!rU3KhL2KlSP`RR3F-NIz3rR^e2$3t~bN++@ zkxr8)Bj)rwhhw_oj!3&KkD@DEn&hI~wE7jsz6Z115A${%mady!^Vl{uqYGIpcldUFnRuP#fETm9UQSNu(;Ao1bz zti^6BL$ll`HA72|UXVC$y8qa-*G9YD%rfDQsF{4GqdXgxPvIV%6Fp2IS*H$(RVhv^<`HgLlC_ZZ)Z495)iIL8Y2IwlerLZf!QN(%vopqb z-_RpiUqLU6mG7${5%bDbW^ob#)Xq@8QwE=H7by1>rAY{X;>0t`n2F%u7dujne3j?| z;0{kzIV+vY&#=}8PG8^?`VW;9YvW+mQ+71JHi8ZLNV%Bh&HS~8#U?JTW_e+C#X3SJ z)R%WN0DO9NDYtSI!P?3RY?#J(MogH};I2Jqu(H8xE>n5{J;*A4_-qS+5qRhOBYI2T z8s{1u$fHbj$a!UEz^RS2Pdz&rw>2s{DdvA1M(Dlj6y^m#jOt_N5J;Ur(Tv|69b1Yx z1L$W*$oOBCV+pGp6*f%Vmb-a3O^|2`vbmJQ0g!iXwT$6B8d$6>#&H>DQ5aJ97XW zIV;HaWKHS8V=XihxPkFOvCN46I|5u|2Kt8Je1svkR zB&=-O?u3b!iPD-bq&A4G&EpU+Zf7kJ#i7ju4u2rx7Noj}L%f}aiRS4xu)c%%wB6Ab zUW_XCr~v@>9I|vL_8GiW1byKHb|&P~gS{GjZEb*FOC%#SZIrXteqAB0Atvrp>- z;KP~N0$saT5N8?PG?iJ2mOA@Gt}ZrIZ##mVRiN$S?rUzE$bFbQPGza0zK80Xo0|WjC DxnnmS diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7f72d79da..b2c6e7a02 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Jan 12 02:06:32 PST 2016 +#Mon Feb 22 17:40:44 PST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip diff --git a/gradlew.bat b/gradlew.bat index aec99730b..72d362daf 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -46,7 +46,7 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args From e53fb782d4fd4dbf8b375ae17eee5c3d1088949b Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 18:21:46 -0800 Subject: [PATCH 22/27] Disable Grgit on 6. It appears to be incompatible. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index aebadd65e..63aa60726 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ buildscript { dependencies { classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1' - classpath 'org.ajoberstar:gradle-git:0.12.0' + classpath 'org.ajoberstar:gradle-git:1.4.2' } } @@ -36,7 +36,7 @@ if (!project.hasProperty("artifactory_contextUrl")) ext.artifactory_contextUrl = if (!project.hasProperty("artifactory_user")) ext.artifactory_user = "guest" if (!project.hasProperty("artifactory_password")) ext.artifactory_password = "" -if (!project.hasProperty("gitCommitHash")) { +if (!project.hasProperty("gitCommitHash") && !JavaVersion.current().isJava6()) { try { def repo = org.ajoberstar.grgit.Grgit.open(project.file('.')) ext.gitCommitHash = repo.head().abbreviatedId From 698a610eaa8a6051e2a9e460be07055154d316fb Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 18:31:55 -0800 Subject: [PATCH 23/27] Kill lock files in cache. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e526c902f..05606e10a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ jdk: - openjdk6 # Caching for Gradle files, prevents hitting Maven too much. before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock + - find $HOME/.gradle/ -name '*.lock' -print -exec 'rm -f {} \;' cache: directories: - $HOME/.gradle/caches/ From a1680886a461e1ca17fc92f925955aa404546d2b Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 19:13:08 -0800 Subject: [PATCH 24/27] Weird hack for java6. I hope it works. --- build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 63aa60726..264c20903 100644 --- a/build.gradle +++ b/build.gradle @@ -38,9 +38,12 @@ if (!project.hasProperty("artifactory_password")) ext.artifactory_password = "" if (!project.hasProperty("gitCommitHash") && !JavaVersion.current().isJava6()) { try { - def repo = org.ajoberstar.grgit.Grgit.open(project.file('.')) + def Grgit = Class.forName("org.ajoberstar.grgit.Grgit"); + def Grgit_open = Grgit.getDeclaredMethod("open", File.class) + def repo = Grgit_open.invoke(null, project.file('.')) ext.gitCommitHash = repo.head().abbreviatedId } catch (Exception e) { + println "Error getting commit hash: " + e.getMessage() ext.gitCommitHash = "no_git_id" } } From a64a53db7ff68acefbfef329b66b7f97abc00711 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 19:16:14 -0800 Subject: [PATCH 25/27] Default gitCommitHash --- build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 264c20903..144b8de13 100644 --- a/build.gradle +++ b/build.gradle @@ -44,9 +44,11 @@ if (!project.hasProperty("gitCommitHash") && !JavaVersion.current().isJava6()) { ext.gitCommitHash = repo.head().abbreviatedId } catch (Exception e) { println "Error getting commit hash: " + e.getMessage() - ext.gitCommitHash = "no_git_id" } } +if (!project.hasProperty("gitCommitHash")) { + ext.gitCommitHash = "no_git_id" +} subprojects { apply plugin: 'java' From f5c015317eedcdcba9f56fe77dced71de67de6af Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 22 Feb 2016 19:22:30 -0800 Subject: [PATCH 26/27] Fix finding locks --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 05606e10a..9321cf073 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ jdk: - openjdk6 # Caching for Gradle files, prevents hitting Maven too much. before_cache: - - find $HOME/.gradle/ -name '*.lock' -print -exec 'rm -f {} \;' + - find $HOME/.gradle/ -name '*.lock' -print -exec rm -f {} \; cache: directories: - $HOME/.gradle/caches/ From 79290caaa7e0eab78e38787128148f80f7e877d0 Mon Sep 17 00:00:00 2001 From: Wyatt Childers Date: Sat, 5 Mar 2016 16:10:03 -0500 Subject: [PATCH 27/27] Fixed a bug where virtually all mobs were determined to be Animals on the Forge 1.8 platform --- .../main/java/com/sk89q/worldedit/forge/ForgeEntityType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntityType.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntityType.java index 8fb19f3cd..c56375105 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntityType.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntityType.java @@ -36,6 +36,7 @@ import net.minecraft.entity.item.EntityTNTPrimed; import net.minecraft.entity.item.EntityXPOrb; import net.minecraft.entity.monster.EntityGolem; import net.minecraft.entity.passive.EntityAmbientCreature; +import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.passive.EntityTameable; import net.minecraft.entity.passive.IAnimals; import net.minecraft.entity.player.EntityPlayer; @@ -108,7 +109,7 @@ public class ForgeEntityType implements EntityType { @Override public boolean isAnimal() { - return entity instanceof IAnimals; + return entity instanceof EntityAnimal; } @Override