From e620d3eb0ebafa7d4472d7beabec7cb2b2e7fc2e Mon Sep 17 00:00:00 2001 From: Esophose Date: Thu, 9 May 2019 04:30:13 -0600 Subject: [PATCH] WorldEdit schematic support, +bug fix --- build.gradle | 3 + .../skyblock/config/FileManager.java | 4 + .../skyblock/island/IslandManager.java | 35 +++++--- .../skyblock/levelling/LevellingManager.java | 2 +- .../goodandevil/skyblock/menus/Creator.java | 18 ++++- .../skyblock/placeholder/EZPlaceholder.java | 4 +- .../utils/structure/StructureUtil.java | 80 ++++++++++++++++++- src/main/resources/language.yml | 2 + src/main/resources/plugin.yml | 2 +- 9 files changed, 128 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index d93a1620..a943e3f7 100644 --- a/build.gradle +++ b/build.gradle @@ -37,6 +37,9 @@ dependencies { // WildStacker implementation (group: 'com.bgsoftware', name: 'wildstacker-api', version: 'b14') + // WorldEdit + implementation (group: 'com.sk89q', name: 'worldedit', version: '7.0.0') + // Apache Commons shade (group: 'org.apache.commons', name: 'commons-lang3', version: '3.0') shade (group: 'commons-io', name: 'commons-io', version: '2.5') diff --git a/src/main/java/me/goodandevil/skyblock/config/FileManager.java b/src/main/java/me/goodandevil/skyblock/config/FileManager.java index 029dd29b..f30bea82 100644 --- a/src/main/java/me/goodandevil/skyblock/config/FileManager.java +++ b/src/main/java/me/goodandevil/skyblock/config/FileManager.java @@ -49,6 +49,10 @@ public class FileManager { new File(skyblock.getDataFolder().toString() + "/structures").mkdir(); } + if (Bukkit.getPluginManager().isPluginEnabled("WorldEdit") && !new File(skyblock.getDataFolder().toString() + "/schematics").exists()) { + new File(skyblock.getDataFolder().toString() + "/schematics").mkdir(); + } + Map configFiles = new LinkedHashMap<>(); configFiles.put("worlds.yml", new File(skyblock.getDataFolder(), "worlds.yml")); configFiles.put("levelling.yml", new File(skyblock.getDataFolder(), "levelling.yml")); diff --git a/src/main/java/me/goodandevil/skyblock/island/IslandManager.java b/src/main/java/me/goodandevil/skyblock/island/IslandManager.java index 51d934e8..b2a5d63c 100644 --- a/src/main/java/me/goodandevil/skyblock/island/IslandManager.java +++ b/src/main/java/me/goodandevil/skyblock/island/IslandManager.java @@ -746,21 +746,30 @@ public class IslandManager { } try { - File structureFile = null; - - if (world == IslandWorld.Normal) { - structureFile = new File(new File(skyblock.getDataFolder().toString() + "/structures"), - structure.getOverworldFile()); - } else if (world == IslandWorld.Nether) { - structureFile = new File(new File(skyblock.getDataFolder().toString() + "/structures"), - structure.getNetherFile()); - } else if (world == IslandWorld.End) { - structureFile = new File(new File(skyblock.getDataFolder().toString() + "/structures"), - structure.getEndFile()); + String structureFileName = null; + switch (world) { + case Normal: + structureFileName = structure.getOverworldFile(); + break; + case Nether: + structureFileName = structure.getNetherFile(); + break; + case End: + structureFileName = structure.getEndFile(); + break; + } + + boolean isStructureFile = structureFileName.endsWith(".structure"); + File structureFile = new File(new File(skyblock.getDataFolder().toString() + "/" + (isStructureFile ? "structures" : "schematics")), structureFileName); + + Float[] direction; + if (isStructureFile) { + direction = StructureUtil.pasteStructure(StructureUtil.loadStructure(structureFile), + island.getLocation(world, IslandEnvironment.Island), BlockDegreesType.ROTATE_360); + } else { + direction = StructureUtil.pasteSchematic(structureFile, island.getLocation(world, IslandEnvironment.Island)); } - Float[] direction = StructureUtil.pasteStructure(StructureUtil.loadStructure(structureFile), - island.getLocation(world, IslandEnvironment.Island), BlockDegreesType.ROTATE_360); org.bukkit.Location spawnLocation = island.getLocation(world, IslandEnvironment.Main).clone(); spawnLocation.setYaw(direction[0]); spawnLocation.setPitch(direction[1]); diff --git a/src/main/java/me/goodandevil/skyblock/levelling/LevellingManager.java b/src/main/java/me/goodandevil/skyblock/levelling/LevellingManager.java index 501c193c..375d5bc2 100644 --- a/src/main/java/me/goodandevil/skyblock/levelling/LevellingManager.java +++ b/src/main/java/me/goodandevil/skyblock/levelling/LevellingManager.java @@ -52,7 +52,7 @@ public class LevellingManager { WorldManager worldManager = skyblock.getWorldManager(); StackableManager stackableManager = skyblock.getStackableManager(); - if (islandManager.getIslandPlayerAt(player) != island) { + if (player != null && islandManager.getIslandPlayerAt(player) != island) { String message = ChatColor.translateAlternateColorCodes('&', this.skyblock.getFileManager() .getConfig(new File(this.skyblock.getDataFolder(), "language.yml")) .getFileConfiguration().getString("Command.Island.Level.Scanning.NotOnIsland.Message")); diff --git a/src/main/java/me/goodandevil/skyblock/menus/Creator.java b/src/main/java/me/goodandevil/skyblock/menus/Creator.java index 98a2b621..23404465 100644 --- a/src/main/java/me/goodandevil/skyblock/menus/Creator.java +++ b/src/main/java/me/goodandevil/skyblock/menus/Creator.java @@ -127,7 +127,8 @@ public class Creator { } if (!fileManager.isFileExist( - new File(new File(skyblock.getDataFolder().toString() + "/structures"), + new File(new File(skyblock.getDataFolder().toString() + "/" + + (structureList.getOverworldFile().endsWith(".structure") ? "structures" : "schematics")), structureList.getOverworldFile()))) { messageManager.sendMessage(player, configLoad.getString("Island.Creator.Selector.File.Overworld.Message")); @@ -138,7 +139,8 @@ public class Creator { return; } else if (!fileManager.isFileExist( - new File(new File(skyblock.getDataFolder().toString() + "/structures"), + new File(new File(skyblock.getDataFolder().toString() + "/" + + (structureList.getNetherFile().endsWith(".structure") ? "structures" : "schematics")), structureList.getNetherFile()))) { messageManager.sendMessage(player, configLoad.getString("Island.Creator.Selector.File.Nether.Message")); @@ -147,6 +149,18 @@ public class Creator { event.setWillClose(false); event.setWillDestroy(false); + return; + } else if (!fileManager.isFileExist( + new File(new File(skyblock.getDataFolder().toString() + "/" + + (structureList.getEndFile().endsWith(".structure") ? "structures" : "schematics")), + structureList.getEndFile()))) { + messageManager.sendMessage(player, + configLoad.getString("Island.Creator.Selector.File.End.Message")); + soundManager.playSound(player, Sounds.ANVIL_LAND.bukkitSound(), 1.0F, 1.0F); + + event.setWillClose(false); + event.setWillDestroy(false); + return; } else if (fileManager.getConfig(new File(skyblock.getDataFolder(), "config.yml")) .getFileConfiguration().getBoolean("Island.Creation.Cooldown.Creation.Enable") diff --git a/src/main/java/me/goodandevil/skyblock/placeholder/EZPlaceholder.java b/src/main/java/me/goodandevil/skyblock/placeholder/EZPlaceholder.java index 3b58f247..693cde2e 100644 --- a/src/main/java/me/goodandevil/skyblock/placeholder/EZPlaceholder.java +++ b/src/main/java/me/goodandevil/skyblock/placeholder/EZPlaceholder.java @@ -85,8 +85,8 @@ public class EZPlaceholder extends PlaceholderExpansion implements Listener { return ChatColor.translateAlternateColorCodes('&', configLoad.getString("Placeholder.fabledskyblock_leaderboard_bank.Empty.Message")); } else if (identifier.equalsIgnoreCase("leaderboard_bank_" + (i + 1))) { - if (i < leaderboardLevelPlayers.size()) { - Leaderboard leaderboard = leaderboardLevelPlayers.get(i); + if (i < leaderboardBankPlayers.size()) { + Leaderboard leaderboard = leaderboardBankPlayers.get(i); Visit visit = leaderboard.getVisit(); IslandLevel level = visit.getLevel(); diff --git a/src/main/java/me/goodandevil/skyblock/utils/structure/StructureUtil.java b/src/main/java/me/goodandevil/skyblock/utils/structure/StructureUtil.java index d6626872..2edaab36 100644 --- a/src/main/java/me/goodandevil/skyblock/utils/structure/StructureUtil.java +++ b/src/main/java/me/goodandevil/skyblock/utils/structure/StructureUtil.java @@ -2,7 +2,18 @@ package me.goodandevil.skyblock.utils.structure; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; - +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; +import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.session.ClipboardHolder; import me.goodandevil.skyblock.SkyBlock; import me.goodandevil.skyblock.config.FileManager; import me.goodandevil.skyblock.config.FileManager.Config; @@ -14,10 +25,10 @@ import me.goodandevil.skyblock.utils.world.block.BlockDegreesType; import me.goodandevil.skyblock.utils.world.block.BlockUtil; import me.goodandevil.skyblock.utils.world.entity.EntityData; import me.goodandevil.skyblock.utils.world.entity.EntityUtil; - import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Entity; @@ -25,7 +36,12 @@ import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -177,6 +193,64 @@ public final class StructureUtil { return new Float[] { yaw, pitch }; } + @SuppressWarnings("deprecation") + public static Float[] pasteSchematic(File schematicFile, org.bukkit.Location location) { + if (!Bukkit.getPluginManager().isPluginEnabled("WorldEdit")) + throw new IllegalStateException("Tried to generate an island using a schematic file without WorldEdit installed!"); + + Bukkit.getScheduler().runTask(SkyBlock.getInstance(), () -> { + if (NMSUtil.getVersionNumber() > 12) { // WorldEdit 7 + ClipboardFormat format = ClipboardFormats.findByFile(schematicFile); + try (ClipboardReader reader = format.getReader(new FileInputStream(schematicFile))) { + Clipboard clipboard = reader.read(); + try (EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(location.getWorld()), -1)) { + Operation operation = new ClipboardHolder(clipboard) + .createPaste(editSession) + .to(BlockVector3.at(location.getX(), location.getY(), location.getZ())) + .ignoreAirBlocks(true) + .build(); + Operations.complete(operation); + } catch (WorldEditException e) { + e.printStackTrace(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } else { // WorldEdit 6 or earlier + // I don't want to use modules so reflection it is + // TODO: Cache this later + try { + Class bukkitWorldClass = Class.forName("com.sk89q.worldedit.bukkit.BukkitWorld"); + Constructor bukkitWorldConstructor = bukkitWorldClass.getConstructor(World.class); + Class editSessionClass = Class.forName("com.sk89q.worldedit.EditSession"); + Class localWorldClass = Class.forName("com.sk89q.worldedit.LocalWorld"); + Constructor editSessionConstructor = editSessionClass.getConstructor(localWorldClass, int.class); + Class cuboidClipboardClass = Class.forName("com.sk89q.worldedit.CuboidClipboard"); + Method loadSchematicMethod = cuboidClipboardClass.getMethod("loadSchematic", File.class); + Class vectorClass = Class.forName("com.sk89q.worldedit.Vector"); + Constructor vectorConstructor = vectorClass.getConstructor(double.class, double.class, double.class); + Method pasteMethod = cuboidClipboardClass.getMethod("paste", editSessionClass, vectorClass, boolean.class); + + Object editSessionObj = editSessionConstructor.newInstance(bukkitWorldConstructor.newInstance(location.getWorld()), 999999999); + Object cuboidClipboardObj = loadSchematicMethod.invoke(null, schematicFile); + Object vectorObj = vectorConstructor.newInstance(location.getX(), location.getY(), location.getZ()); + + pasteMethod.invoke(cuboidClipboardObj, editSessionObj, vectorObj, true); + + /* + EditSession es = new EditSession(new BukkitWorld(location.getWorld()), 999999999); + CuboidClipboard cc = CuboidClipboard.loadSchematic(schematicFile); + cc.paste(es, new Vector(location.getX(), location.getY(), location.getZ()), true); + */ + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + return new Float[] { location.getYaw(), location.getPitch() }; + } + public static ItemStack getTool() throws Exception { SkyBlock skyblock = SkyBlock.getInstance(); diff --git a/src/main/resources/language.yml b/src/main/resources/language.yml index e47999c5..c90e14c3 100644 --- a/src/main/resources/language.yml +++ b/src/main/resources/language.yml @@ -894,6 +894,8 @@ Island: Message: "&bSkyBlock &8| &cError&8: &eThe structure file for the overworld does not exist." Nether: Message: "&bSkyBlock &8| &cError&8: &eThe structure file for the nether does not exist." + End: + Message: "&bSkyBlock &8| &cError&8: &eThe structure file for the end does not exist." Cooldown: Word: Minute: "minute(s)" diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 537b38ca..213f5b04 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,7 +4,7 @@ version: @version@ api-version: 1.13 description: A unique SkyBlock plugin author: Songoda -softdepend: [PlaceholderAPI, MVdWPlaceholderAPI, Vault, LeaderHeads, EpicSpawners, WildStacker] +softdepend: [PlaceholderAPI, MVdWPlaceholderAPI, Vault, LeaderHeads, EpicSpawners, WildStacker, WorldEdit] loadbefore: [Multiverse-Core] commands: island: