diff --git a/bukkit0/build.gradle b/bukkit0/build.gradle index 10d3a21c..9da4a980 100644 --- a/bukkit0/build.gradle +++ b/bukkit0/build.gradle @@ -1,6 +1,7 @@ dependencies { compile project(':core') compile 'org.bukkit.craftbukkitv1_10:craftbukkitv1_10:1.10' + compile 'org.bukkit.craftbukkitv1_11:Craftbukkit:1.11' compile 'net.milkbowl.vault:VaultAPI:1.5' compile 'com.massivecraft:factions:2.8.0' compile 'com.drtshock:factions:1.6.9.5' diff --git a/bukkit111/build.gradle b/bukkit111/build.gradle new file mode 100644 index 00000000..1d3deb91 --- /dev/null +++ b/bukkit111/build.gradle @@ -0,0 +1,31 @@ +dependencies { + compile project(':bukkit0') +} + +processResources { + from('src/main/resources') { + include 'plugin.yml' + expand( + name: project.parent.name, + version: project.parent.version + ) + } +} + +apply plugin: 'com.github.johnrengelman.shadow' +// We only want the shadow jar produced +jar.enabled = false +shadowJar { + dependencies { + include(dependency(':bukkit0')) + include(dependency(':core')) + } + archiveName = "${parent.name}-${project.name}-${parent.version}.jar" + destinationDir = file '../target' +} +shadowJar.doLast { + task -> + ant.checksum file: task.archivePath +} + +build.dependsOn(shadowJar); \ No newline at end of file diff --git a/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitChunk_1_11.java b/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitChunk_1_11.java new file mode 100644 index 00000000..70f379de --- /dev/null +++ b/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitChunk_1_11.java @@ -0,0 +1,413 @@ +package com.boydti.fawe.bukkit.v1_11; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.BytePair; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.FaweQueue; +import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.MathMan; +import com.boydti.fawe.util.ReflectionUtils; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.LongTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.internal.Constants; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import net.minecraft.server.v1_11_R1.Block; +import net.minecraft.server.v1_11_R1.BlockPosition; +import net.minecraft.server.v1_11_R1.ChunkSection; +import net.minecraft.server.v1_11_R1.DataBits; +import net.minecraft.server.v1_11_R1.DataPalette; +import net.minecraft.server.v1_11_R1.DataPaletteBlock; +import net.minecraft.server.v1_11_R1.DataPaletteGlobal; +import net.minecraft.server.v1_11_R1.Entity; +import net.minecraft.server.v1_11_R1.EntityPlayer; +import net.minecraft.server.v1_11_R1.EntityTypes; +import net.minecraft.server.v1_11_R1.IBlockData; +import net.minecraft.server.v1_11_R1.MinecraftKey; +import net.minecraft.server.v1_11_R1.NBTTagCompound; +import net.minecraft.server.v1_11_R1.TileEntity; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_11_R1.CraftChunk; +import org.bukkit.event.entity.CreatureSpawnEvent; + +public class BukkitChunk_1_11 extends CharFaweChunk { + + public DataPaletteBlock[] sectionPalettes; + + public static Map> entityKeys; + + /** + * A FaweSections object represents a chunk and the blocks that you wish to change in it. + * + * @param parent + * @param x + * @param z + */ + public BukkitChunk_1_11(FaweQueue parent, int x, int z) { + super(parent, x, z); + } + + @Override + public Chunk getNewChunk() { + return ((com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11) getParent()).getWorld().getChunkAt(getX(), getZ()); + } + + @Override + public CharFaweChunk copy(boolean shallow) { + BukkitChunk_1_11 value = (BukkitChunk_1_11) super.copy(shallow); + if (sectionPalettes != null) { + value.sectionPalettes = new DataPaletteBlock[16]; + try { + Field fieldBits = DataPaletteBlock.class.getDeclaredField("b"); + fieldBits.setAccessible(true); + Field fieldPalette = DataPaletteBlock.class.getDeclaredField("c"); + fieldPalette.setAccessible(true); + Field fieldSize = DataPaletteBlock.class.getDeclaredField("e"); + fieldSize.setAccessible(true); + for (int i = 0; i < sectionPalettes.length; i++) { + DataPaletteBlock current = sectionPalettes[i]; + if (current == null) { + continue; + } + // Clone palette + DataPalette currentPalette = (DataPalette) fieldPalette.get(current); + if (!(currentPalette instanceof DataPaletteGlobal)) { + current.a(128, null); + } + DataPaletteBlock paletteBlock = newDataPaletteBlock(); + currentPalette = (DataPalette) fieldPalette.get(current); + if (!(currentPalette instanceof DataPaletteGlobal)) { + throw new RuntimeException("Palette must be global!"); + } + fieldPalette.set(paletteBlock, currentPalette); + // Clone size + fieldSize.set(paletteBlock, fieldSize.get(current)); + // Clone palette + DataBits currentBits = (DataBits) fieldBits.get(current); + DataBits newBits = new DataBits(1, 0); + for (Field field : DataBits.class.getDeclaredFields()) { + field.setAccessible(true); + Object currentValue = field.get(currentBits); + if (currentValue instanceof long[]) { + currentValue = ((long[]) currentValue).clone(); + } + field.set(newBits, currentValue); + } + fieldBits.set(paletteBlock, newBits); + value.sectionPalettes[i] = paletteBlock; + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + } + return value; + } + + public DataPaletteBlock newDataPaletteBlock() { + try { + return new DataPaletteBlock(); + } catch (Throwable e) { + try { + Constructor constructor = DataPaletteBlock.class.getDeclaredConstructor(IBlockData[].class); + return constructor.newInstance((Object) null); + } catch (Throwable e2) { + throw new RuntimeException(e2); + } + } + } + + public void optimize() { + if (sectionPalettes != null) { + return; + } + char[][] arrays = getCombinedIdArrays(); + IBlockData lastBlock = null; + char lastChar = Character.MAX_VALUE; + for (int layer = 0; layer < 16; layer++) { + if (getCount(layer) > 0) { + if (sectionPalettes == null) { + sectionPalettes = new DataPaletteBlock[16]; + } + DataPaletteBlock palette = newDataPaletteBlock(); + char[] blocks = getIdArray(layer); + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + char combinedId = blocks[FaweCache.CACHE_J[y][z][x]]; + if (combinedId > 1) { + palette.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF)); + } + } + } + } + } + } + } + + @Override + public void start() { + getChunk().load(true); + } + + @Override + public FaweChunk call() { + try { + final Chunk chunk = this.getChunk(); + final World world = chunk.getWorld(); + final boolean flag = world.getEnvironment() == World.Environment.NORMAL; + net.minecraft.server.v1_11_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + nmsChunk.f(true); // Set Modified + nmsChunk.mustSave = true; + net.minecraft.server.v1_11_R1.World nmsWorld = nmsChunk.world; + ChunkSection[] sections = nmsChunk.getSections(); + Class clazzChunk = nmsChunk.getClass(); + final Collection[] entities = (Collection[]) getParent().getEntitySlices.invoke(nmsChunk); + Map tiles = nmsChunk.getTileEntities(); + // Remove entities + for (int i = 0; i < entities.length; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + Collection ents = entities[i]; + if (!ents.isEmpty()) { + synchronized (BukkitQueue_0.adapter) { + ents.clear(); + } + } + } else { + Collection ents = entities[i]; + if (!ents.isEmpty()) { + char[] array = this.getIdArray(i); + ents = new ArrayList<>(entities[i]); + synchronized (BukkitQueue_0.adapter) { + for (Entity entity : ents) { + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.locX) & 15); + int z = ((int) Math.round(entity.locZ) & 15); + int y = (int) Math.round(entity.locY); + if (array == null || y < 0 || y > 255) { + continue; + } + if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) { + nmsWorld.removeEntity(entity); + } + } + } + } + } + } + HashSet entsToRemove = this.getEntityRemoves(); + if (!entsToRemove.isEmpty()) { + synchronized (BukkitQueue_0.adapter) { + for (int i = 0; i < entities.length; i++) { + Collection ents = new ArrayList<>(entities[i]); + for (Entity entity : ents) { + if (entsToRemove.contains(entity.getUniqueID())) { + nmsWorld.removeEntity(entity); + } + } + } + } + } + // Set entities + Set entitiesToSpawn = this.getEntities(); + Set createdEntities = new HashSet<>(); + if (!entitiesToSpawn.isEmpty()) { + synchronized (BukkitQueue_0.adapter) { + for (CompoundTag nativeTag : entitiesToSpawn) { + Map entityTagMap = ReflectionUtils.getMap(nativeTag.getValue()); + StringTag idTag = (StringTag) entityTagMap.get("Id"); + ListTag posTag = (ListTag) entityTagMap.get("Pos"); + ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + if (idTag == null || posTag == null || rotTag == null) { + Fawe.debug("Unknown entity tag: " + nativeTag); + continue; + } + double x = posTag.getDouble(0); + double y = posTag.getDouble(1); + double z = posTag.getDouble(2); + float yaw = rotTag.getFloat(0); + float pitch = rotTag.getFloat(1); + String id = idTag.getValue(); + if (entityKeys == null) { + entityKeys = new HashMap<>(); + for (MinecraftKey key : EntityTypes.a()) { + String currentId = EntityTypes.a(key); + Class clazz = EntityTypes.b.get(key); + entityKeys.put(currentId, clazz); + } + } + Class clazz = entityKeys.get(id); + if (clazz != null) { + Entity entity = EntityTypes.a(clazz, nmsWorld); + if (entity != null) { + UUID uuid = entity.getUniqueID(); + entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits())); + entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits())); + if (nativeTag != null) { + NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_11.methodFromNative.invoke(BukkitQueue_1_11.adapter, nativeTag); + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + entity.f(tag); + } + entity.setLocation(x, y, z, yaw, pitch); + nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); + createdEntities.add(entity.getUniqueID()); + } + } + } + } + } + // Change task? + if (getParent().getChangeTask() != null) { + BukkitChunk_1_11 previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false); + getParent().getChangeTask().run(previous, this); + } + // Trim tiles + Iterator> iterator = tiles.entrySet().iterator(); + HashMap toRemove = null; + while (iterator.hasNext()) { + Map.Entry tile = iterator.next(); + BlockPosition pos = tile.getKey(); + int lx = pos.getX() & 15; + int ly = pos.getY(); + int lz = pos.getZ() & 15; + int j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + if (toRemove == null) { + toRemove = new HashMap<>(); + } + toRemove.put(tile.getKey(), tile.getValue()); + } + } + if (toRemove != null) { + for (Map.Entry entry : toRemove.entrySet()) { + BlockPosition bp = entry.getKey(); + TileEntity tile = entry.getValue(); + tiles.remove(bp); + tile.y(); + nmsWorld.s(bp); + tile.invalidateBlockCache(); + } + + } + // Set blocks + for (int j = 0; j < sections.length; j++) { + int count = this.getCount(j); + if (count == 0) { + continue; + } + final char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + ChunkSection section = sections[j]; + if (section == null) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + section = sections[j] = getParent().newChunkSection(j << 4, flag, null); + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = getParent().newChunkSection(j << 4, flag, array); + } + continue; + } else if (count >= 4096) { + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = getParent().newChunkSection(j << 4, flag, array); + } + continue; + } + DataPaletteBlock nibble = section.getBlocks(); + int nonEmptyBlockCount = 0; + for (int y = 0; y < 16; y++) { + short[][] i1 = FaweCache.CACHE_J[y]; + for (int z = 0; z < 16; z++) { + short[] i2 = i1[z]; + for (int x= 0; x < 16; x++) { + char combinedId = array[i2[x]]; + switch (combinedId) { + case 0: + IBlockData existing = nibble.a(x, y, z); + if (existing != com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11.air) { + nonEmptyBlockCount++; + } + continue; + case 1: + nibble.setBlock(x, y, z, com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11.air); + continue; + default: + nonEmptyBlockCount++; + nibble.setBlock(x, y, z, getParent().IBD_CACHE[(int) combinedId]); + } + } + } + } + getParent().setCount(0, nonEmptyBlockCount, section); + } + // Set biomes + int[][] biomes = this.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + BytePair pair = entry.getKey(); + BlockPosition pos = new BlockPosition(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos + TileEntity tileEntity = nmsWorld.getTileEntity(pos); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11.methodFromNative.invoke(com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11.adapter, nativeTag); + tileEntity.a(tag); // ReadTagIntoTile + } + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + return this; + } +} diff --git a/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitMain_111.java b/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitMain_111.java new file mode 100644 index 00000000..6f66509d --- /dev/null +++ b/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitMain_111.java @@ -0,0 +1,23 @@ +package com.boydti.fawe.bukkit.v1_11; + +import com.boydti.fawe.bukkit.ABukkitMain; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.object.FaweQueue; +import com.sk89q.worldedit.world.World; + +public class BukkitMain_111 extends ABukkitMain { + @Override + public BukkitQueue_0 getQueue(World world) { + return new com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11(world); + } + + @Override + public FaweQueue getQueue(String world) { + return new com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11(world); + } + + @Override + public void onEnable() { + super.onEnable(); + } +} \ No newline at end of file diff --git a/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java b/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java new file mode 100644 index 00000000..9e4a755f --- /dev/null +++ b/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java @@ -0,0 +1,520 @@ +package com.boydti.fawe.bukkit.v1_11; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.RunnableVal; +import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.MathMan; +import com.boydti.fawe.util.ReflectionUtils; +import com.boydti.fawe.util.TaskManager; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ExecutorCompletionService; +import net.minecraft.server.v1_11_R1.*; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.craftbukkit.v1_11_R1.CraftChunk; +import org.bukkit.craftbukkit.v1_11_R1.CraftServer; +import org.bukkit.craftbukkit.v1_11_R1.CraftWorld; +import org.bukkit.event.world.WorldInitEvent; +import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.generator.ChunkGenerator; + +public class BukkitQueue_1_11 extends BukkitQueue_0 { + + protected static IBlockData air; + protected static Field fieldBits; + protected static Method getEntitySlices; + + public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE]; + + public BukkitQueue_1_11(final com.sk89q.worldedit.world.World world) { + super(world); + init(); + } + + public BukkitQueue_1_11(final String world) { + super(world); + init(); + } + + @Override + public void setHeightMap(FaweChunk chunk, int[] heightMap) { + CraftChunk craftChunk = (CraftChunk) chunk.getChunk(); + if (craftChunk != null) { + int[] otherMap = craftChunk.getHandle().heightMap; + for (int i = 0; i < heightMap.length; i++) { + if (heightMap[i] > otherMap[i]) { + otherMap[i] = heightMap[i]; + } + } + } + } + + private void init() { + checkVersion("v1_11_R1"); + if (air == null) { + try { + Field fieldAir = DataPaletteBlock.class.getDeclaredField("a"); + fieldAir.setAccessible(true); + air = (IBlockData) fieldAir.get(null); + fieldBits = DataPaletteBlock.class.getDeclaredField("b"); + fieldBits.setAccessible(true); + getEntitySlices = net.minecraft.server.v1_11_R1.Chunk.class.getDeclaredMethod("getEntitySlices"); + getEntitySlices.setAccessible(true); + if (adapter == null) { + setupAdapter(new com.boydti.fawe.bukkit.v1_11.FaweAdapter_1_11()); + Fawe.debug("Using adapter: " + adapter); + Fawe.debug("========================================="); + } + for (int i = 0; i < Character.MAX_VALUE; i++) { + try { + IBD_CACHE[i] = Block.getById(i >> 4).fromLegacyData(i & 0xF); + } catch (Throwable ignore) {} + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + getImpWorld(); + } + + @Override + public boolean next(int amount, ExecutorCompletionService pool, long time) { + return super.next(amount, pool, time); + } + + @Override + public void setSkyLight(ChunkSection section, int x, int y, int z, int value) { + section.getSkyLightArray().a(x & 15, y & 15, z & 15, value); + } + + @Override + public void setBlockLight(ChunkSection section, int x, int y, int z, int value) { + section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value); + } + + protected DataBits lastBits; + protected DataPaletteBlock lastBlocks; + + @Override + public World createWorld(final WorldCreator creator) { + final String name = creator.name(); + ChunkGenerator generator = creator.generator(); + final CraftServer server = (CraftServer) Bukkit.getServer(); + final MinecraftServer console = server.getServer(); + final File folder = new File(server.getWorldContainer(), name); + final World world = server.getWorld(name); + final WorldType type = WorldType.getType(creator.type().getName()); + final boolean generateStructures = creator.generateStructures(); + if (world != null) { + return world; + } + if (folder.exists() && !folder.isDirectory()) { + throw new IllegalArgumentException("File exists with the name '" + name + "' and isn't a folder"); + } + TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(Object value) { + try { + Field field = CraftServer.class.getDeclaredField("worlds"); + field.setAccessible(true); + Map existing = (Map) field.get(server); + if (!existing.getClass().getName().contains("SynchronizedMap")) { + field.set(server, Collections.synchronizedMap(existing)); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + }); + if (generator == null) { + generator = server.getGenerator(name); + } + int dimension = 10 + console.worlds.size(); + boolean used = false; + do { + for (final WorldServer ws : console.worlds) { + used = (ws.dimension == dimension); + if (used) { + ++dimension; + break; + } + } + } while (used); + final boolean hardcore = false; + final IDataManager sdm = new ServerNBTManager(server.getWorldContainer(), name, true, server.getHandle().getServer().getDataConverterManager()); + WorldData worlddata = sdm.getWorldData(); + final WorldSettings worldSettings; + if (worlddata == null) { + worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(server.getDefaultGameMode().getValue()), generateStructures, hardcore, type); + worldSettings.setGeneratorSettings(creator.generatorSettings()); + worlddata = new WorldData(worldSettings, name); + } else { + worldSettings = null; + } + worlddata.checkName(name); + final WorldServer internal = (WorldServer)new WorldServer(console, sdm, worlddata, dimension, console.methodProfiler, creator.environment(), generator).b(); + startSet(true); // Temporarily allow async chunk load since the world isn't added yet + if (worldSettings != null) { + internal.a(worldSettings); + } + endSet(true); + internal.scoreboard = server.getScoreboardManager().getMainScoreboard().getHandle(); + internal.tracker = new EntityTracker(internal); + internal.addIWorldAccess(new WorldManager(console, internal)); + internal.worldData.setDifficulty(EnumDifficulty.EASY); + internal.setSpawnFlags(true, true); + if (generator != null) { + internal.getWorld().getPopulators().addAll(generator.getDefaultPopulators(internal.getWorld())); + } + // Add the world + return TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(World value) { + console.worlds.add(internal); + server.getPluginManager().callEvent(new WorldInitEvent(internal.getWorld())); + server.getPluginManager().callEvent(new WorldLoadEvent(internal.getWorld())); + this.value = internal.getWorld(); + } + }); + } + + @Override + public ChunkSection[] getCachedSections(World world, int cx, int cz) { + CraftChunk chunk = (CraftChunk) world.getChunkAt(cx, cz); + return chunk.getHandle().getSections(); + } + + @Override + public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) { + return chunkSections[cy]; + } + + @Override + public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) { + DataPaletteBlock dataPalette = lastSection.getBlocks(); + IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + Block block = ibd.getBlock(); + int id = Block.getId(block); + if (FaweCache.hasData(id)) { + return (id << 4) + block.toLegacyData(ibd); + } else { + return id << 4; + } + } + + @Override + public int getOpacity(ChunkSection section, int x, int y, int z) { + DataPaletteBlock dataPalette = section.getBlocks(); + IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + return ibd.c(); + } + + @Override + public int getBrightness(ChunkSection section, int x, int y, int z) { + DataPaletteBlock dataPalette = section.getBlocks(); + IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + return ibd.d(); + } + + @Override + public int getOpacityBrightnessPair(ChunkSection section, int x, int y, int z) { + DataPaletteBlock dataPalette = section.getBlocks(); + IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + return MathMan.pair16(ibd.c(), ibd.d()); + } + + @Override + public void refreshChunk(FaweChunk fc) { + BukkitChunk_1_11 fs = (BukkitChunk_1_11) fc; + ensureChunkLoaded(fc.getX(), fc.getZ()); + Chunk chunk = fs.getChunk(); + if (!chunk.isLoaded()) { + return; + } + try { + net.minecraft.server.v1_11_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + WorldServer w = (WorldServer) nmsChunk.getWorld(); + PlayerChunkMap chunkMap = w.getPlayerChunkMap(); + PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ); + if (playerChunk == null) { + return; + } + if (playerChunk.c.isEmpty()) { + return; + } + // Send chunks + int mask = fc.getBitMask(); + if (mask == 65535 && hasEntities(nmsChunk)) { + PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65280); + for (EntityPlayer player : playerChunk.c) { + player.playerConnection.sendPacket(packet); + } + mask = 255; + } + PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, mask); + for (EntityPlayer player : playerChunk.c) { + player.playerConnection.sendPacket(packet); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public boolean hasEntities(net.minecraft.server.v1_11_R1.Chunk nmsChunk) { + try { + final Collection[] entities = (Collection[]) getEntitySlices.invoke(nmsChunk); + for (int i = 0; i < entities.length; i++) { + Collection slice = entities[i]; + if (slice != null && !slice.isEmpty()) { + return true; + } + } + } catch (Throwable ignore) {} + return false; + } + + @Override + public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) { + if (mode != RelightMode.NONE) { + for (int i = 0; i < sections.length; i++) { + ChunkSection section = sections[i]; + if (section != null) { + section.a(new NibbleArray()); // Emitted + if (sky) { + section.b(new NibbleArray()); // Skylight + } + } + } + } + return true; + } + + @Override + public void setFullbright(ChunkSection[] sections) { + for (int i = 0; i < sections.length; i++) { + ChunkSection section = sections[i]; + if (section != null) { + byte[] bytes = section.getSkyLightArray().asBytes(); + Arrays.fill(bytes, (byte) 255); + } + } + } + + @Override + public int getSkyLight(ChunkSection section, int x, int y, int z) { + return section.b(x & 15, y & 15, z & 15); + } + + @Override + public int getEmmittedLight(ChunkSection section, int x, int y, int z) { + return section.c(x & 15, y & 15, z & 15); + } + + @Override + public void relightBlock(int x, int y, int z) { + pos.c(x, y, z); + nmsWorld.c(EnumSkyBlock.BLOCK, pos); + } + + @Override + public void relightSky(int x, int y, int z) { + pos.c(x, y, z); + nmsWorld.c(EnumSkyBlock.SKY, pos); + } + + @Override + public void relight(int x, int y, int z) { + pos.c(x, y, z); + nmsWorld.w(pos); + } + + protected WorldServer nmsWorld; + + @Override + public World getImpWorld() { + World world = super.getImpWorld(); + if (world != null) { + this.nmsWorld = ((CraftWorld) world).getHandle(); + return super.getImpWorld(); + } else { + return null; + } + } + + public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException { + Class clazz = section.getClass(); + Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount"); + Field fieldNonEmptyBlockCount = clazz.getDeclaredField("nonEmptyBlockCount"); + fieldTickingBlockCount.setAccessible(true); + fieldNonEmptyBlockCount.setAccessible(true); + fieldTickingBlockCount.set(section, tickingBlockCount); + fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); + } + + public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException { + Field fieldSection = ChunkSection.class.getDeclaredField("blockIds"); + fieldSection.setAccessible(true); + fieldSection.set(section, palette); + } + + public ChunkSection newChunkSection(int y2, boolean flag, char[] array) { + try { + if (array == null) { + return new ChunkSection(y2, flag); + } else { + return new ChunkSection(y2, flag, array); + } + } catch (Throwable e) { + try { + if (array == null) { + Constructor constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, IBlockData[].class); + return constructor.newInstance(y2, flag, (IBlockData[]) null); + } else { + Constructor constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, char[].class, IBlockData[].class); + return constructor.newInstance(y2, flag, array, (IBlockData[]) null); + } + } catch (Throwable e2) { + throw new RuntimeException(e2); + } + } + } + + @Override + public BukkitChunk_1_11 getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map tilesGeneric, Collection[] entitiesGeneric, Set createdEntities, boolean all) throws Exception { + Map tiles = (Map) tilesGeneric; + Collection[] entities = (Collection[]) entitiesGeneric; + BukkitChunk_1_11 previous = getFaweChunk(fs.getX(), fs.getZ()); + // Copy blocks + char[][] idPrevious = new char[16][]; + for (int layer = 0; layer < sections.length; layer++) { + if (fs.getCount(layer) != 0 || all) { + ChunkSection section = sections[layer]; + if (section != null) { + short solid = 0; + char[] previousLayer = idPrevious[layer] = new char[4096]; + DataPaletteBlock blocks = section.getBlocks(); + for (int j = 0; j < 4096; j++) { + int x = FaweCache.CACHE_X[0][j]; + int y = FaweCache.CACHE_Y[0][j]; + int z = FaweCache.CACHE_Z[0][j]; + IBlockData ibd = blocks.a(x, y, z); + Block block = ibd.getBlock(); + int combined = Block.getId(block); + if (FaweCache.hasData(combined)) { + combined = (combined << 4) + block.toLegacyData(ibd); + } else { + combined = combined << 4; + } + if (combined > 1) { + solid++; + } + previousLayer[j] = (char) combined; + } + previous.count[layer] = solid; + previous.air[layer] = (short) (4096 - solid); + } + } + } + previous.ids = idPrevious; + // Copy tiles + if (tiles != null) { + for (Map.Entry entry : tiles.entrySet()) { + TileEntity tile = entry.getValue(); + NBTTagCompound tag = new NBTTagCompound(); + BlockPosition pos = entry.getKey(); + CompoundTag nativeTag = getTag(tile); + previous.setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag); + } + } + // Copy entities + if (entities != null) { + for (Collection entityList : entities) { + for (Entity ent : entityList) { + if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && createdEntities.contains(ent.getUniqueID()))) { + continue; + } + int x = ((int) Math.round(ent.locX) & 15); + int z = ((int) Math.round(ent.locZ) & 15); + int y = (int) Math.round(ent.locY); + int i = FaweCache.CACHE_I[y][z][x]; + char[] array = fs.getIdArray(i); + if (array == null) { + continue; + } + int j = FaweCache.CACHE_J[y][z][x]; + if (array[j] != 0) { + String id = EntityTypes.b(ent); + if (id != null) { + NBTTagCompound tag = new NBTTagCompound(); + ent.e(tag); // readEntityIntoTag + CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag); + Map map = ReflectionUtils.getMap(nativeTag.getValue()); + map.put("Id", new StringTag(id)); + previous.setEntity(nativeTag); + } + } + } + } + } + return previous; + } + + protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0); + + @Override + public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) { + Map tiles = ((CraftChunk) chunk).getHandle().getTileEntities(); + pos.c(x, y, z); + TileEntity tile = tiles.get(pos); + return tile != null ? getTag(tile) : null; + } + + public CompoundTag getTag(TileEntity tile) { + try { + NBTTagCompound tag = new NBTTagCompound(); + tile.save(tag); // readTagIntoEntity + return (CompoundTag) methodToNative.invoke(adapter, tag); + } catch (Exception e) { + MainUtil.handleError(e); + return null; + } + } + + @Override + public Chunk getChunk(World world, int x, int z) { + return world.getChunkAt(x, z); + } + + @Deprecated + public boolean unloadChunk(final String world, final Chunk chunk) { + net.minecraft.server.v1_11_R1.Chunk c = ((CraftChunk) chunk).getHandle(); + c.mustSave = false; + if (chunk.isLoaded()) { + chunk.unload(false, false); + } + return true; + } + + @Override + public BukkitChunk_1_11 getFaweChunk(int x, int z) { + return new BukkitChunk_1_11(this, x, z); + } +} diff --git a/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweAdapter_1_11.java b/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweAdapter_1_11.java new file mode 100644 index 00000000..be1c7a79 --- /dev/null +++ b/bukkit111/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweAdapter_1_11.java @@ -0,0 +1,355 @@ +package com.boydti.fawe.bukkit.v1_11; + +import com.google.common.base.Preconditions; +import com.sk89q.jnbt.ByteArrayTag; +import com.sk89q.jnbt.ByteTag; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.DoubleTag; +import com.sk89q.jnbt.EndTag; +import com.sk89q.jnbt.FloatTag; +import com.sk89q.jnbt.IntArrayTag; +import com.sk89q.jnbt.IntTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.LongTag; +import com.sk89q.jnbt.NBTConstants; +import com.sk89q.jnbt.ShortTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.internal.Constants; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import net.minecraft.server.v1_11_R1.*; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Biome; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_11_R1.CraftServer; +import org.bukkit.craftbukkit.v1_11_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_11_R1.block.CraftBlock; +import org.bukkit.craftbukkit.v1_11_R1.entity.CraftEntity; +import org.bukkit.event.entity.CreatureSpawnEvent; + +public final class FaweAdapter_1_11 implements BukkitImplAdapter +{ + private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); + private final Field nbtListTagListField; + private final Method nbtCreateTagMethod; + + public FaweAdapter_1_11() + throws NoSuchFieldException, NoSuchMethodException + { + CraftServer.class.cast(Bukkit.getServer()); + + this.nbtListTagListField = NBTTagList.class.getDeclaredField("list"); + this.nbtListTagListField.setAccessible(true); + + this.nbtCreateTagMethod = NBTBase.class.getDeclaredMethod("createTag", new Class[] { Byte.TYPE }); + this.nbtCreateTagMethod.setAccessible(true); + } + + private static void readTagIntoTileEntity(NBTTagCompound tag, TileEntity tileEntity) + { + tileEntity.a(tag); + } + + private static void readTileEntityIntoTag(TileEntity tileEntity, NBTTagCompound tag) + { + tileEntity.save(tag); + } + + @Nullable + private static String getEntityId(net.minecraft.server.v1_11_R1.Entity entity) + { + return EntityTypes.b(entity); + } + + @Nullable + private static net.minecraft.server.v1_11_R1.Entity createEntityFromId(String id, World world) + { + return EntityTypes.a(new MinecraftKey(id), world); + } + + private static void readTagIntoEntity(NBTTagCompound tag, net.minecraft.server.v1_11_R1.Entity entity) + { + entity.f(tag); + } + + private static void readEntityIntoTag(net.minecraft.server.v1_11_R1.Entity entity, NBTTagCompound tag) + { + entity.e(tag); + } + + public int getBlockId(Material material) + { + return material.getId(); + } + + public Material getMaterial(int id) + { + return Material.getMaterial(id); + } + + public int getBiomeId(Biome biome) + { + BiomeBase mcBiome = CraftBlock.biomeToBiomeBase(biome); + return mcBiome != null ? BiomeBase.a(mcBiome) : 0; + } + + public Biome getBiome(int id) + { + BiomeBase mcBiome = BiomeBase.getBiome(id); + return CraftBlock.biomeBaseToBiome(mcBiome); + } + + public BaseBlock getBlock(Location location) + { + Preconditions.checkNotNull(location); + + CraftWorld craftWorld = (CraftWorld)location.getWorld(); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + Block bukkitBlock = location.getBlock(); + BaseBlock block = new BaseBlock(bukkitBlock.getTypeId(), bukkitBlock.getData()); + + TileEntity te = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z)); + if (te != null) + { + NBTTagCompound tag = new NBTTagCompound(); + readTileEntityIntoTag(te, tag); + block.setNbtData((CompoundTag)toNative(tag)); + } + return block; + } + + public boolean setBlock(Location location, BaseBlock block, boolean notifyAndLight) + { + Preconditions.checkNotNull(location); + Preconditions.checkNotNull(block); + + CraftWorld craftWorld = (CraftWorld)location.getWorld(); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + boolean changed = location.getBlock().setTypeIdAndData(block.getId(), (byte)block.getData(), notifyAndLight); + + CompoundTag nativeTag = block.getNbtData(); + if (nativeTag != null) + { + TileEntity tileEntity = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z)); + if (tileEntity != null) + { + NBTTagCompound tag = (NBTTagCompound)fromNative(nativeTag); + tag.set("x", new NBTTagInt(x)); + tag.set("y", new NBTTagInt(y)); + tag.set("z", new NBTTagInt(z)); + readTagIntoTileEntity(tag, tileEntity); + } + } + return changed; + } + + public BaseEntity getEntity(org.bukkit.entity.Entity entity) + { + Preconditions.checkNotNull(entity); + + CraftEntity craftEntity = (CraftEntity)entity; + net.minecraft.server.v1_11_R1.Entity mcEntity = craftEntity.getHandle(); + + String id = getEntityId(mcEntity); + if (id != null) { + NBTTagCompound tag = new NBTTagCompound(); + readEntityIntoTag(mcEntity, tag); + CompoundTag weTag = (CompoundTag) toNative(tag); + return new BaseEntity(id, weTag); + } + return null; + } + + @Nullable + public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state) + { + Preconditions.checkNotNull(location); + Preconditions.checkNotNull(state); + + CraftWorld craftWorld = (CraftWorld)location.getWorld(); + WorldServer worldServer = craftWorld.getHandle(); + + net.minecraft.server.v1_11_R1.Entity createdEntity = createEntityFromId(state.getTypeId(), craftWorld.getHandle()); + if (createdEntity != null) + { + CompoundTag nativeTag = state.getNbtData(); + if (nativeTag != null) + { + NBTTagCompound tag = (NBTTagCompound)fromNative(nativeTag); + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + readTagIntoEntity(tag, createdEntity); + } + createdEntity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + + worldServer.addEntity(createdEntity, CreatureSpawnEvent.SpawnReason.CUSTOM); + return createdEntity.getBukkitEntity(); + } + return null; + } + + private Tag toNative(NBTBase foreign) + { + if (foreign == null) { + return null; + } + if ((foreign instanceof NBTTagCompound)) + { + Map values = new HashMap(); + Set foreignKeys = ((NBTTagCompound)foreign).c(); + for (String str : foreignKeys) + { + NBTBase base = ((NBTTagCompound)foreign).get(str); + values.put(str, toNative(base)); + } + return new CompoundTag(values); + } + if ((foreign instanceof NBTTagByte)) { + return new ByteTag(((NBTTagByte)foreign).g()); + } + if ((foreign instanceof NBTTagByteArray)) { + return new ByteArrayTag(((NBTTagByteArray)foreign).c()); + } + if ((foreign instanceof NBTTagDouble)) { + return new DoubleTag(((NBTTagDouble)foreign).asDouble()); + } + if ((foreign instanceof NBTTagFloat)) { + return new FloatTag(((NBTTagFloat)foreign).i()); + } + if ((foreign instanceof NBTTagInt)) { + return new IntTag(((NBTTagInt)foreign).e()); + } + if ((foreign instanceof NBTTagIntArray)) { + return new IntArrayTag(((NBTTagIntArray)foreign).d()); + } + if ((foreign instanceof NBTTagList)) { + try + { + return toNativeList((NBTTagList)foreign); + } + catch (Throwable e) + { + this.logger.log(Level.WARNING, "Failed to convert NBTTagList", e); + return new ListTag(ByteTag.class, new ArrayList()); + } + } + if ((foreign instanceof NBTTagLong)) { + return new LongTag(((NBTTagLong)foreign).d()); + } + if ((foreign instanceof NBTTagShort)) { + return new ShortTag(((NBTTagShort)foreign).f()); + } + if ((foreign instanceof NBTTagString)) { + return new StringTag(((NBTTagString)foreign).c_()); + } + if ((foreign instanceof NBTTagEnd)) { + return new EndTag(); + } + throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); + } + + private ListTag toNativeList(NBTTagList foreign) + throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException + { + List values = new ArrayList(); + int type = foreign.getTypeId(); + + List foreignList = (List)this.nbtListTagListField.get(foreign); + for (int i = 0; i < foreign.size(); i++) + { + NBTBase element = (NBTBase)foreignList.get(i); + values.add(toNative(element)); + } + Class cls = NBTConstants.getClassFromType(type); + return new ListTag(cls, values); + } + + private NBTBase fromNative(Tag foreign) + { + if (foreign == null) { + return null; + } + Map.Entry entry; + if ((foreign instanceof CompoundTag)) + { + NBTTagCompound tag = new NBTTagCompound(); + for (Iterator localIterator = ((CompoundTag)foreign) + .getValue().entrySet().iterator(); localIterator.hasNext();) + { + entry = (Map.Entry)localIterator.next(); + + tag.set((String)entry.getKey(), fromNative((Tag)entry.getValue())); + } + return tag; + } + if ((foreign instanceof ByteTag)) { + return new NBTTagByte(((ByteTag)foreign).getValue().byteValue()); + } + if ((foreign instanceof ByteArrayTag)) { + return new NBTTagByteArray(((ByteArrayTag)foreign).getValue()); + } + if ((foreign instanceof DoubleTag)) { + return new NBTTagDouble(((DoubleTag)foreign).getValue().doubleValue()); + } + if ((foreign instanceof FloatTag)) { + return new NBTTagFloat(((FloatTag)foreign).getValue().floatValue()); + } + if ((foreign instanceof IntTag)) { + return new NBTTagInt(((IntTag)foreign).getValue().intValue()); + } + if ((foreign instanceof IntArrayTag)) { + return new NBTTagIntArray(((IntArrayTag)foreign).getValue()); + } + if ((foreign instanceof ListTag)) + { + NBTTagList tag = new NBTTagList(); + ListTag foreignList = (ListTag)foreign; + for (Tag t : foreignList.getValue()) { + tag.add(fromNative(t)); + } + return tag; + } + if ((foreign instanceof LongTag)) { + return new NBTTagLong(((LongTag)foreign).getValue().longValue()); + } + if ((foreign instanceof ShortTag)) { + return new NBTTagShort(((ShortTag)foreign).getValue().shortValue()); + } + if ((foreign instanceof StringTag)) { + return new NBTTagString(((StringTag)foreign).getValue()); + } + if ((foreign instanceof EndTag)) { + try + { + return (NBTBase)this.nbtCreateTagMethod.invoke(null, new Object[] { Byte.valueOf((byte) 0) }); + } + catch (Exception e) + { + return null; + } + } + throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); + } +} diff --git a/bukkit111/src/main/resources/plugin.yml b/bukkit111/src/main/resources/plugin.yml new file mode 100644 index 00000000..978f8aca --- /dev/null +++ b/bukkit111/src/main/resources/plugin.yml @@ -0,0 +1,30 @@ +name: ${name} +main: com.boydti.fawe.bukkit.v1_11.BukkitMain_111 +version: ${version} +description: Fast Async WorldEdit plugin +authors: [Empire92] +loadbefore: [WorldEdit,AsyncWorldEdit,AsyncWorldEditInjector] +load: STARTUP +database: false +#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] +commands: + wea: + description: (FAWE) Bypass WorldEdit processing and area restrictions + aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere] + usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass" + fawe: + description: (FAWE) Reload the plugin + aliases: [/fawe,/fawereload] + select: + description: (FAWE) Select your current WorldEdit Region. + aliases: [/select,wer,/wer,worldeditregion,/worldeditregion,/region] + fcancel: + description: (FAWE) Cancel your edit + aliases: [fawecancel,/fcancel,/cancel,/fawecancel] +permissions: + fawe.bypass: + default: false + fawe.admin: + default: op + fawe.reload: + default: false \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/Fawe.java b/core/src/main/java/com/boydti/fawe/Fawe.java index d45c4d2a..4b0c0891 100644 --- a/core/src/main/java/com/boydti/fawe/Fawe.java +++ b/core/src/main/java/com/boydti/fawe/Fawe.java @@ -441,7 +441,7 @@ public class Fawe { MainUtil.handleError(e, false); debug("======================================="); debug("Things to check: "); - debug(" - Using WorldEdit 6.1.1"); + debug(" - Using the latest version of WorldEdit/FAWE"); debug(" - AsyncWorldEdit/WorldEditRegions isn't installed"); debug(" - Any other errors in the startup log"); debug(" - Contact Empire92 for assistance!"); diff --git a/settings.gradle b/settings.gradle index a7b2461a..821fa3a0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ rootProject.name = 'FastAsyncWorldEdit' -include 'core', 'bukkit0', 'bukkit1710', 'bukkit18', 'bukkit19', 'bukkit110', 'forge1710', 'forge189', 'forge194', 'forge110', 'favs', 'nukkit' +include 'core', 'bukkit0', 'bukkit1710', 'bukkit18', 'bukkit19', 'bukkit110', 'bukkit111', 'forge1710', 'forge189', 'forge194', 'forge110', 'favs', 'nukkit'