package com.denizenscript.depenizen.bukkit.commands.worldedit;
import com.denizenscript.denizen.objects.CuboidTag;
import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizen.utilities.Utilities;
import com.denizenscript.denizen.utilities.debugging.Debug;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
import com.denizenscript.denizencore.objects.Argument;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.*;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.io.Closer;
import com.sk89q.worldedit.world.World;
import java.io.*;
import java.net.URLDecoder;
public class WorldEditCommand extends AbstractCommand {
// <--[command]
// @Name worldedit
// @Syntax worldedit [cuboid_to_schematic/cuboid_to_clipboard/schematic_to_paste/schematic_to_clipboard] (rotate:<amount>) (undoable:true/false) (cuboid:<CuboidTag>) (target:<player>)
// @Group Depenizen
// @Plugin Depenizen, WorldEdit
// @Required 2
// @Short Allows access to various worldedit actions.
// @Description
// Allows access to various worldedit actions.
// If no targets are specified, the target will be the player in the queue.
// The file path starts in the denizen folder: /plugins/Denizen/schematics/
// @Tags
// <PlayerTag.we_selection>
// @Usage
// Use to save a cuboid to a schematic.
// - worldedit CUBOIDSCHEMATIC cuboid:<player.we_selection> position:<player.location>
// @Usage
// Use to copy a cuboid to a player's clipboard.
// - worldedit CUBOIDCLIPBOARD cuboid:<player.we_selection> position:<player.location>
// @Usage
// Use to load a schematic into a player's clipboard.
// - worldedit SCHEMATICCLIPBOARD file:<[filepath]>
// @Usage
// Use to paste a schematic at a location
// - worldedit SCHEMATICPASTE file:<[filepath]> position:<player.location>
// @Usage
// Use to paste a schematic at a location with a player attached
// - worldedit SCHEMATICPASTE file:<[filepath]> position:<player.location> undoable:true rotate:90
// -->
private enum Action {CUBOIDSCHEMATIC, CUBOIDCLIPBOARD, SCHEMATICPASTE, SCHEMATICCLIPBOARD}
@Override
public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {
for (Argument arg : scriptEntry.getProcessedArgs()) {
if (!scriptEntry.hasObject("target")
&& arg.matchesPrefix("target")
&& arg.matchesArgumentType(PlayerTag.class)) {
scriptEntry.addObject("target", arg.asType(PlayerTag.class));
}
else if (!scriptEntry.hasObject("position")
&& arg.matchesPrefix("position")) {
scriptEntry.addObject("position", arg.asType(LocationTag.class));
}
else if (!scriptEntry.hasObject("file")
&& arg.matchesPrefix("file")) {
scriptEntry.addObject("file", arg.asElement());
}
else if (!scriptEntry.hasObject("action")
&& arg.matchesEnum(Action.values())) {
scriptEntry.addObject("action", arg.asElement());
}
else if (!scriptEntry.hasObject("cuboid")
&& arg.matchesPrefix("cuboid")) {
scriptEntry.addObject("cuboid", arg.asType(CuboidTag.class));
}
else if (!scriptEntry.hasObject("noair")
&& arg.matchesPrefix("noair")) {
scriptEntry.addObject("noair", arg.asElement());
}
else if (!scriptEntry.hasObject("undoable")
&& arg.matchesPrefix("undoable")) {
scriptEntry.addObject("undoable", arg.asElement());
}
else if (!scriptEntry.hasObject("rotate")
&& arg.matchesPrefix("rotate")) {
scriptEntry.addObject("rotate", arg.asElement());
}
else if (!scriptEntry.hasObject("action")
&& arg.matchesEnum(Action.values())) {
scriptEntry.addObject("action", arg.asElement());
}
else {
arg.reportUnhandled();
}
}
if (!scriptEntry.hasObject("action")) {
throw new InvalidArgumentsException("Action not specified! (play/stop)");
}
if (!scriptEntry.hasObject("rotate")) {
scriptEntry.addObject("rotate", new ElementTag("0"));
}
if (!scriptEntry.hasObject("noair")) {
scriptEntry.addObject("noair", new ElementTag(true));
}
if (!scriptEntry.hasObject("target")) {
if (Utilities.entryHasPlayer(scriptEntry)) {
scriptEntry.addObject("target", Utilities.getEntryPlayer(scriptEntry));
}
else {
throw new InvalidArgumentsException("Must specify players to add, remove or spectate!");
}
}
}
@SuppressWarnings("unchecked")
@Override
public void execute(ScriptEntry scriptEntry) {
ElementTag file = scriptEntry.getObjectTag("file");
ElementTag action = scriptEntry.getObjectTag("action");
PlayerTag target = scriptEntry.getObjectTag("target");
LocationTag position = scriptEntry.getObjectTag("position");
ElementTag noAir = scriptEntry.getObjectTag("noair");
CuboidTag cuboid = scriptEntry.getObjectTag("cuboid");
ElementTag id = scriptEntry.getObjectTag("id");
ElementTag data = scriptEntry.getObjectTag("data");
ElementTag undoable = scriptEntry.getObjectTag("undoable");
ElementTag rotate = scriptEntry.getObjectTag("rotate");
// Report to dB
Debug.report(scriptEntry, getName(), action.debug()
+ (target != null ? target.debug() : "")
+ (position != null ? position.debug() : "")
+ (noAir != null ? noAir.debug() : "")
+ (cuboid != null ? cuboid.debug() : "")
+ (id != null ? id.debug() : "")
+ (data != null ? data.debug() : "")
+ (rotate != null ? rotate.debug() : "")
+ (file != null ? file.debug() : ""));
if (action.asString().equalsIgnoreCase("schematicpaste")) {
if (file == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "File path not specified!");
return;
}
if (position == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Location not specified!");
return;
}
if (noAir == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Air Boolean not specified!");
return;
}
String directory = URLDecoder.decode(System.getProperty("user.dir"));
File file_load = new File(directory + "/plugins/Denizen/schematics/" + file + ".schematic");
Clipboard clipboard;
ClipboardFormat format = ClipboardFormats.findByFile(file_load);
if (format == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "File not found!");
return;
}
try {
clipboard = format.getReader(new FileInputStream(file_load)).read();
} catch (IOException e) {
Debug.echoError(scriptEntry.getResidingQueue(), "File not found!");
return;
}
EditSession editSession;
World w = new BukkitWorld(position.getWorld());
if (undoable.asBoolean()) {
if (target == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Targets not found!");
return;
}
com.sk89q.worldedit.entity.Player p = BukkitAdapter.adapt(target.getOfflinePlayer().getPlayer());
editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1, p);
} else {
editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(w, -1);
}
ClipboardHolder holder = new ClipboardHolder(clipboard);
if (rotate != null) {
AffineTransform transform = new AffineTransform();
transform = transform.rotateY(rotate.asInt());
holder.setTransform(holder.getTransform().combine(transform));
}
Operation operation = holder
.createPaste(editSession)
.to(BlockVector3.at(position.getBlockX(), position.getBlockY(), position.getBlockZ()))
.ignoreAirBlocks(!noAir.asBoolean())
.build();
try {
Operations.complete(operation);
} catch (WorldEditException e) {
Debug.echoError(scriptEntry.getResidingQueue(), "WorldEdit caught an exception while pasting a schematic!");
}
editSession.flushSession();
}
else if (action.asString().equalsIgnoreCase("cuboidschematic")) {
if (cuboid == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Cuboid not specified!");
return;
}
if (file == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "File not specified!");
return;
}
String directory = URLDecoder.decode(System.getProperty("user.dir"));
File file_load = new File(directory + "/plugins/Denizen/schematics/" + file + ".schematic");
LocationTag top1 = new LocationTag(cuboid.getHigh(0));
LocationTag bot1 = new LocationTag(cuboid.getLow(0));
BlockVector3 top = BlockVector3.at(top1.getBlockX(), top1.getBlockY(), top1.getBlockZ());
BlockVector3 bot = BlockVector3.at(bot1.getBlockX(), bot1.getBlockY(), bot1.getBlockZ());
World w = new BukkitWorld(cuboid.getWorld());
CuboidRegion region = new CuboidRegion(w, bot, top);
if (position == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Position not specified!");
return;
}
BlockVector3 pos = BlockVector3.at(position.getBlockX(), position.getBlockY(), position.getBlockZ());
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
clipboard.setOrigin(pos);
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(region.getWorld(), -1);
ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
forwardExtentCopy.setCopyingEntities(false);
try {
Operations.complete(forwardExtentCopy);
} catch (WorldEditException e) {
Debug.echoError(scriptEntry.getResidingQueue(), "WorldEdit caught an exception while loading a schematic to clipboard!");
}
try {
try (ClipboardWriter writer = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(file_load))) {
writer.write(clipboard);
}
} catch (IOException e) {
e.printStackTrace();
}
}
else if (action.asString().equalsIgnoreCase("cuboidclipboard")) {
if (target == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Targets not found!");
return;
}
if (cuboid == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Cuboid not specified!");
return;
}
if (position == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Position not specified!");
return;
}
LocationTag top1 = new LocationTag(cuboid.getHigh(0));
LocationTag bot1 = new LocationTag(cuboid.getLow(0));
BlockVector3 top = BlockVector3.at(top1.getBlockX(), top1.getBlockY(), top1.getBlockZ());
BlockVector3 bot = BlockVector3.at(bot1.getBlockX(), bot1.getBlockY(), bot1.getBlockZ());
World w = new BukkitWorld(cuboid.getWorld());
CuboidRegion region = new CuboidRegion(w, bot, top);
com.sk89q.worldedit.entity.Player p = BukkitAdapter.adapt(target.getOfflinePlayer().getPlayer());
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
BlockVector3 pos = BlockVector3.at(position.getBlockX(), position.getBlockY(), position.getBlockZ());
clipboard.setOrigin(pos);
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(region.getWorld(), -1,p);
ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
forwardExtentCopy.setCopyingEntities(false);
try {
Operations.complete(forwardExtentCopy);
} catch (WorldEditException e) {
Debug.echoError(scriptEntry.getResidingQueue(), "WorldEdit caught an exception while loading a schematic to clipboard!");
}
ClipboardHolder holder = new ClipboardHolder(clipboard);
WorldEdit.getInstance().getSessionManager().get(p).setClipboard(holder);
}
else if (action.asString().equalsIgnoreCase("schematicclipboard")) {
if (file == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "File path not specified!");
return;
}
String directory = URLDecoder.decode(System.getProperty("user.dir"));
File file_load = new File(directory + "/plugins/Denizen/schematics/" + file + ".schematic");
ClipboardFormat format = ClipboardFormats.findByFile(file_load);
if (format == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "File not found!");
return;
}
if (target == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Target not found!");
return;
}
Clipboard clipboard = null;
try (Closer closer = Closer.create()) {
FileInputStream fis = closer.register(new FileInputStream(file_load));
BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
ClipboardReader reader = closer.register(format.getReader(bis));
clipboard = reader.read();
} catch (IOException e) {
e.printStackTrace();
}
if (clipboard == null) {
Debug.echoError(scriptEntry.getResidingQueue(), "Clipboard returned null");
return;
}
ClipboardHolder holder = new ClipboardHolder(clipboard);
com.sk89q.worldedit.entity.Player p = BukkitAdapter.adapt(target.getOfflinePlayer().getPlayer());
WorldEdit.getInstance().getSessionManager().get(p).setClipboard(holder);
}
}
}