mirror of
https://github.com/TotalFreedomMC/TF-PlotSquared.git
synced 2024-12-23 00:15:06 +00:00
Various
some sponge stuff schematic/mca/bo3 uploading rework fix minor issue with plot visit fix #956
This commit is contained in:
parent
75bf01c13f
commit
98c4483535
14 changed files with 532 additions and 185 deletions
|
@ -162,6 +162,22 @@ public class BukkitUtil extends WorldUtil {
|
|||
return new Location(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(), temp.getYaw(), temp.getPitch());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpawn(Location loc) {
|
||||
World world = getWorld(loc.getWorld());
|
||||
if (world != null) {
|
||||
world.setSpawnLocation(loc.getX(), loc.getY(), loc.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveWorld(String worldname) {
|
||||
World world = getWorld(worldname);
|
||||
if (world != null) {
|
||||
world.save();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighestBlock(final String world, final int x, final int z) {
|
||||
return getWorld(world).getHighestBlockAt(x, z).getY();
|
||||
|
|
|
@ -8,15 +8,16 @@ import com.intellectualcrafters.plot.flag.FlagManager;
|
|||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import com.intellectualcrafters.plot.util.BO3Handler;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.Permissions;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.StringMan;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
import com.plotsquared.general.commands.CommandDeclaration;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
@CommandDeclaration(command = "download", aliases = { "dl" }, category = CommandCategory.SCHEMATIC, requiredType = RequiredType.NONE, description = "Download your plot", permission = "plots.download")
|
||||
@CommandDeclaration(usage = "/plot download [schematic|bo3|world]", command = "download", aliases = { "dl" }, category = CommandCategory.SCHEMATIC, requiredType = RequiredType.NONE, description = "Download your plot", permission = "plots.download")
|
||||
public class Download extends SubCommand {
|
||||
|
||||
@Override
|
||||
|
@ -41,26 +42,63 @@ public class Download extends SubCommand {
|
|||
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
|
||||
return false;
|
||||
}
|
||||
plot.addRunning();
|
||||
MainUtil.sendMessage(plr, C.GENERATING_LINK);
|
||||
SchematicHandler.manager.getCompoundTag(plot, new RunnableVal<CompoundTag>() {
|
||||
@Override
|
||||
public void run(final CompoundTag value) {
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final URL url = SchematicHandler.manager.upload(value, null, null);
|
||||
if (url == null) {
|
||||
MainUtil.sendMessage(plr, C.GENERATING_LINK_FAILED);
|
||||
plot.removeRunning();
|
||||
return;
|
||||
if (args.length == 0 || (args.length == 1 && StringMan.isEqualIgnoreCaseToAny(args[0], "sch", "schem", "schematic"))) {
|
||||
plot.addRunning();
|
||||
SchematicHandler.manager.getCompoundTag(plot, new RunnableVal<CompoundTag>() {
|
||||
@Override
|
||||
public void run(final CompoundTag value) {
|
||||
plot.removeRunning();
|
||||
SchematicHandler.manager.upload(value, null, null, new RunnableVal<URL>() {
|
||||
@Override
|
||||
public void run(URL url) {
|
||||
if (url == null) {
|
||||
MainUtil.sendMessage(plr, C.GENERATING_LINK_FAILED);
|
||||
return;
|
||||
}
|
||||
MainUtil.sendMessage(plr, url.toString());
|
||||
}
|
||||
MainUtil.sendMessage(plr, url.toString());
|
||||
plot.removeRunning();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (args.length == 1 && StringMan.isEqualIgnoreCaseToAny(args[0], "bo3", "bo2", "b03", "b02")) {
|
||||
if (!Permissions.hasPermission(plr, "plots.download.bo3")) {
|
||||
C.NO_PERMISSION.send(plr, "plots.download.bo3");
|
||||
}
|
||||
});
|
||||
plot.addRunning();
|
||||
BO3Handler.upload(plot, null, null, new RunnableVal<URL>() {
|
||||
@Override
|
||||
public void run(URL url) {
|
||||
plot.removeRunning();
|
||||
if (url == null) {
|
||||
MainUtil.sendMessage(plr, C.GENERATING_LINK_FAILED);
|
||||
return;
|
||||
}
|
||||
MainUtil.sendMessage(plr, url.toString());
|
||||
}
|
||||
});
|
||||
} else if (args.length == 1 && StringMan.isEqualIgnoreCaseToAny(args[0], "mcr", "world", "mca")) {
|
||||
if (!Permissions.hasPermission(plr, "plots.download.world")) {
|
||||
C.NO_PERMISSION.send(plr, "plots.download.world");
|
||||
}
|
||||
MainUtil.sendMessage(plr, "&cNote: The `.mca` files are 512x512");
|
||||
plot.addRunning();
|
||||
WorldUtil.IMP.upload(plot, null, null, new RunnableVal<URL>() {
|
||||
@Override
|
||||
public void run(URL url) {
|
||||
plot.removeRunning();
|
||||
if (url == null) {
|
||||
MainUtil.sendMessage(plr, C.GENERATING_LINK_FAILED);
|
||||
return;
|
||||
}
|
||||
MainUtil.sendMessage(plr, url.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
C.COMMAND_SYNTAX.send(plr, getUsage());
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(plr, C.GENERATING_LINK);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -374,13 +374,13 @@ public class MainCommand extends CommandManager<PlotPlayer> {
|
|||
// ex. /p h:2 SomeUsername
|
||||
// > /p h SomeUsername 2
|
||||
String[] temp = label.split(":");
|
||||
label = temp[0];
|
||||
|
||||
String[] tempArgs = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, tempArgs, 0, args.length);
|
||||
tempArgs[tempArgs.length - 1] = temp[1];
|
||||
|
||||
args = tempArgs;
|
||||
if (temp.length == 2) {
|
||||
label = temp[0];
|
||||
String[] tempArgs = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, tempArgs, 0, args.length);
|
||||
tempArgs[tempArgs.length - 1] = temp[1];
|
||||
args = tempArgs;
|
||||
}
|
||||
}
|
||||
cmd = getInstance().commands.get(label.toLowerCase());
|
||||
} else {
|
||||
|
|
|
@ -64,19 +64,21 @@ public class Save extends SubCommand {
|
|||
final String world = plot.getArea().toString().replaceAll(";", "-").replaceAll("[^A-Za-z0-9]", "");
|
||||
final String file = time + "_" + world + "_" + id.x + "_" + id.y + "_" + size + "_" + name;
|
||||
final UUID uuid = plr.getUUID();
|
||||
|
||||
final URL url = SchematicHandler.manager.upload(value, uuid, file);
|
||||
if (url == null) {
|
||||
MainUtil.sendMessage(plr, C.SAVE_FAILED);
|
||||
plot.removeRunning();
|
||||
return;
|
||||
}
|
||||
MainUtil.sendMessage(plr, C.SAVE_SUCCESS);
|
||||
final List<String> schematics = (List<String>) plr.getMeta("plot_schematics");
|
||||
if (schematics != null) {
|
||||
schematics.add(file);
|
||||
}
|
||||
plot.removeRunning();
|
||||
SchematicHandler.manager.upload(value, uuid, file, new RunnableVal<URL>() {
|
||||
@Override
|
||||
public void run(URL url) {
|
||||
plot.removeRunning();
|
||||
if (url == null) {
|
||||
MainUtil.sendMessage(plr, C.SAVE_FAILED);
|
||||
return;
|
||||
}
|
||||
MainUtil.sendMessage(plr, C.SAVE_SUCCESS);
|
||||
final List<String> schematics = (List<String>) plr.getMeta("plot_schematics");
|
||||
if (schematics != null) {
|
||||
schematics.add(file);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,8 +30,12 @@ import com.intellectualcrafters.plot.util.Permissions;
|
|||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.plotsquared.general.commands.Argument;
|
||||
import com.plotsquared.general.commands.CommandDeclaration;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(
|
||||
command = "visit",
|
||||
|
@ -82,8 +86,6 @@ public class Visit extends SubCommand {
|
|||
}
|
||||
if (user != null) {
|
||||
unsorted = PS.get().getBasePlots(user);
|
||||
} else if (PS.get().getPlotAreaByString(args[0]) != null) {
|
||||
unsorted = PS.get().getPlotAreaByString(args[0]).getPlots();
|
||||
} else {
|
||||
final Plot plot = MainUtil.getPlotFromString(player, args[0], true);
|
||||
if (plot != null) {
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
package com.intellectualcrafters.plot.object;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import java.io.File;
|
||||
|
||||
public class BO3 {
|
||||
private final ChunkLoc chunk;
|
||||
private final String world;
|
||||
private final StringBuilder blocks;
|
||||
private final StringBuilder children;
|
||||
private final String name;
|
||||
|
||||
public BO3(final String name, final ChunkLoc loc) {
|
||||
public BO3(final String name, final String world, final ChunkLoc loc) {
|
||||
this.world = world;
|
||||
this.name = name;
|
||||
chunk = loc;
|
||||
blocks = new StringBuilder();
|
||||
|
@ -21,6 +28,10 @@ public class BO3 {
|
|||
public ChunkLoc getLoc() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public String getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
@ -42,4 +53,12 @@ public class BO3 {
|
|||
public String getChildren() {
|
||||
return children.toString();
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return MainUtil.getFile(PS.get().IMP.getDirectory(), Settings.BO3_SAVE_PATH + File.separator + getWorld() + File.separator + getFilename());
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return name + (((chunk.x == 0) && (chunk.z == 0)) ? "" : ("_" + chunk.x + "_" + chunk.z)) + ".bo3";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class BlockLoc {
|
|||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
return x == 0 && y == 0 && z == 0;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
|
@ -47,7 +47,11 @@ public class BlockLoc {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (x == 0 && y == 0 && z == 0) {
|
||||
return "";
|
||||
}
|
||||
return x + "," + y + "," + z + "," + yaw + "," + pitch;
|
||||
|
||||
}
|
||||
|
||||
public static BlockLoc fromString(final String string) {
|
||||
|
|
|
@ -564,43 +564,42 @@ public class Plot {
|
|||
* @return true if merged in that direction
|
||||
*/
|
||||
public boolean getMerged(final int direction) {
|
||||
if (isMerged()) {
|
||||
switch (direction) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return this.getSettings().getMerged(direction);
|
||||
case 7:
|
||||
int i = direction - 4;
|
||||
int i2 = 0;
|
||||
if (this.getSettings().getMerged(i2)) {
|
||||
if (this.getSettings().getMerged(i)) {
|
||||
if (this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2)) {
|
||||
if (this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i)) {
|
||||
return true;
|
||||
}
|
||||
if (settings == null) {
|
||||
return false;
|
||||
}
|
||||
switch (direction) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return this.getSettings().getMerged(direction);
|
||||
case 7:
|
||||
int i = direction - 4;
|
||||
int i2 = 0;
|
||||
if (this.getSettings().getMerged(i2)) {
|
||||
if (this.getSettings().getMerged(i)) {
|
||||
if (this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2)) {
|
||||
if (this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
i = direction - 4;
|
||||
i2 = direction - 3;
|
||||
return this.getSettings().getMerged(i2)
|
||||
&& this.getSettings().getMerged(i)
|
||||
&& this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2)
|
||||
&& this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i);
|
||||
}
|
||||
return false;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
i = direction - 4;
|
||||
i2 = direction - 3;
|
||||
return this.getSettings().getMerged(i2)
|
||||
&& this.getSettings().getMerged(i)
|
||||
&& this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2)
|
||||
&& this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i);
|
||||
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the denied users
|
||||
* @return
|
||||
|
@ -1129,13 +1128,13 @@ public class Plot {
|
|||
* @param loc
|
||||
*/
|
||||
public void setHome(final BlockLoc loc) {
|
||||
final BlockLoc pos = this.getSettings().getPosition();
|
||||
if (pos.equals(new BlockLoc(0, 0, 0)) && loc == null || pos.equals(loc)) {
|
||||
final Plot plot = this.getBasePlot(false);
|
||||
final BlockLoc pos = plot.getSettings().getPosition();
|
||||
if (new BlockLoc(0, 0, 0).equals(loc)) {
|
||||
return;
|
||||
}
|
||||
final Plot plot = this.getBasePlot(false);
|
||||
plot.getSettings().setPosition(loc);
|
||||
DBFunc.setPosition(plot, this.getSettings().getPosition().toString());
|
||||
DBFunc.setPosition(plot, plot.getSettings().getPosition().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1761,27 +1760,40 @@ public class Plot {
|
|||
}
|
||||
|
||||
/**
|
||||
* Upload the plot as a schematic to the configured web interface
|
||||
* Upload the plot as a schematic to the configured web interface<br>
|
||||
* @param whenDone value will be null if uploading fails
|
||||
*/
|
||||
public void upload(final RunnableVal<URL> whenDone) {
|
||||
SchematicHandler.manager.getCompoundTag(this, new RunnableVal<CompoundTag>() {
|
||||
@Override
|
||||
public void run(final CompoundTag value) {
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final URL url = SchematicHandler.manager.upload(value, null, null);
|
||||
if (whenDone != null) {
|
||||
whenDone.value = url;
|
||||
}
|
||||
TaskManager.runTask(whenDone);
|
||||
}
|
||||
});
|
||||
SchematicHandler.manager.upload(value, null, null, whenDone);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload this plot as a world file<br>
|
||||
* - The mca files are each 512x512, so depending on the plot size it may also download adjacent plots<br>
|
||||
* - Works best when (plot width + road width) % 512 == 0<br>
|
||||
* @see com.intellectualcrafters.plot.util.WorldUtil
|
||||
* @param whenDone
|
||||
*/
|
||||
public void uploadWorld(RunnableVal<URL> whenDone) {
|
||||
WorldUtil.IMP.upload(this, null, null, whenDone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload this plot as a BO3<br>
|
||||
* - May not work on non default generator<br>
|
||||
* - BO3 includes flags/ignores plot main/floor block<br>
|
||||
* @see com.intellectualcrafters.plot.util.BO3Handler
|
||||
* @param whenDone
|
||||
*/
|
||||
public void uploadBO3(RunnableVal<URL> whenDone) {
|
||||
BO3Handler.upload(this, null, null, whenDone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
|
|
|
@ -12,8 +12,13 @@ import com.intellectualcrafters.plot.object.PlotArea;
|
|||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
@ -22,17 +27,29 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class BO3Handler {
|
||||
|
||||
/**
|
||||
* @see #saveBO3(PlotPlayer, Plot)
|
||||
* @see #saveBO3(PlotPlayer, Plot, RunnableVal)
|
||||
* @param plot
|
||||
* @return if successfully exported
|
||||
*/
|
||||
public static boolean saveBO3(final Plot plot) {
|
||||
return saveBO3(null, plot);
|
||||
}
|
||||
|
||||
public static boolean saveBO3(final PlotPlayer player, final Plot plot) {
|
||||
return saveBO3(player, plot, new RunnableVal<BO3>() {
|
||||
@Override
|
||||
public void run(BO3 bo3) {
|
||||
save(plot, bo3);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean contains(final PlotBlock[] blocks, final PlotBlock block) {
|
||||
for (final PlotBlock item : blocks) {
|
||||
|
@ -50,7 +67,10 @@ public class BO3Handler {
|
|||
* @param plot
|
||||
* @return
|
||||
*/
|
||||
public static boolean saveBO3(final PlotPlayer plr, final Plot plot) {
|
||||
public static boolean saveBO3(final PlotPlayer plr, final Plot plot, RunnableVal<BO3> saveTask) {
|
||||
if (saveTask == null) {
|
||||
throw new IllegalArgumentException("Save task cannot be null!");
|
||||
}
|
||||
final PlotArea plotworld = plot.getArea();
|
||||
if (!(plotworld instanceof ClassicPlotWorld) || (plotworld.TYPE != 0)) {
|
||||
MainUtil.sendMessage(plr, "BO3 exporting only supports type 0 classic generation.");
|
||||
|
@ -83,8 +103,8 @@ public class BO3Handler {
|
|||
|
||||
boolean content = false;
|
||||
for (RegionWrapper region : regions) {
|
||||
Location pos1 = new Location(plot.getArea().worldname, region.minX, region.minY, region.minZ);
|
||||
Location pos2 = new Location(plot.getArea().worldname, region.maxX, region.maxY, region.maxZ);
|
||||
Location pos1 = new Location(plotworld.worldname, region.minX, region.minY, region.minZ);
|
||||
Location pos2 = new Location(plotworld.worldname, region.maxX, region.maxY, region.maxZ);
|
||||
for (int x = pos1.getX(); x <= pos2.getX(); x++) {
|
||||
final int X = ((x + 7) - cx) >> 4;
|
||||
final int xx = (x - cx) % 16;
|
||||
|
@ -97,7 +117,7 @@ public class BO3Handler {
|
|||
final PlotBlock block = WorldUtil.IMP.getBlock(new Location(plot.getArea().worldname, x, y, z));
|
||||
if (!contains(cpw.MAIN_BLOCK, block)) {
|
||||
if (bo3 == null) {
|
||||
bo3 = new BO3(alias, loc);
|
||||
bo3 = new BO3(alias, plotworld.worldname, loc);
|
||||
map.put(loc, bo3);
|
||||
content = true;
|
||||
}
|
||||
|
@ -107,7 +127,7 @@ public class BO3Handler {
|
|||
final PlotBlock floor = WorldUtil.IMP.getBlock(new Location(plot.getArea().worldname, x, height, z));
|
||||
if (!contains(cpw.TOP_BLOCK, floor)) {
|
||||
if (bo3 == null) {
|
||||
bo3 = new BO3(alias, loc);
|
||||
bo3 = new BO3(alias, plotworld.worldname, loc);
|
||||
map.put(loc, bo3);
|
||||
content = true;
|
||||
}
|
||||
|
@ -117,7 +137,7 @@ public class BO3Handler {
|
|||
final PlotBlock block = WorldUtil.IMP.getBlock(new Location(plot.getArea().worldname, x, y, z));
|
||||
if (block.id != 0) {
|
||||
if (bo3 == null) {
|
||||
bo3 = new BO3(alias, loc);
|
||||
bo3 = new BO3(alias, plotworld.worldname, loc);
|
||||
map.put(loc, bo3);
|
||||
content = true;
|
||||
}
|
||||
|
@ -164,14 +184,78 @@ public class BO3Handler {
|
|||
}
|
||||
|
||||
for (final Entry<ChunkLoc, BO3> entry : map.entrySet()) {
|
||||
save(plot, entry.getValue());
|
||||
saveTask.run(entry.getValue());
|
||||
}
|
||||
|
||||
MainUtil.sendMessage(plr, "BO3 exporting was successful!");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static void upload(final Plot plot, final UUID uuid, final String file, final RunnableVal<URL> whenDone) {
|
||||
if (plot == null) {
|
||||
throw new IllegalArgumentException("Arguments may not be null!");
|
||||
}
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (final ZipOutputStream zos = new ZipOutputStream(baos)) {
|
||||
saveBO3(null, plot, new RunnableVal<BO3>() {
|
||||
@Override
|
||||
public void run(BO3 bo3) {
|
||||
try {
|
||||
final ZipEntry ze = new ZipEntry(bo3.getFilename());
|
||||
zos.putNextEntry(ze);
|
||||
write(zos, plot, bo3);
|
||||
zos.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
whenDone.run();
|
||||
return;
|
||||
}
|
||||
MainUtil.upload(uuid, file, "zip", new RunnableVal<OutputStream>() {
|
||||
@Override
|
||||
public void run(OutputStream output) {
|
||||
try {
|
||||
output.write(baos.toByteArray());
|
||||
baos.flush();
|
||||
baos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, whenDone);
|
||||
}
|
||||
|
||||
public static void write(OutputStream stream, final Plot plot, BO3 bo3) throws IOException {
|
||||
File base = getBaseFile(bo3.getWorld());
|
||||
final List<String> lines = Files.readAllLines(base.toPath(), StandardCharsets.UTF_8);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
final String line = lines.get(i).trim();
|
||||
final String result = StringMan.replaceAll(line, "%owner%", MainUtil.getName(plot.owner), "%alias%", plot.toString(), "%blocks%", bo3.getBlocks(), "%branches%", bo3.getChildren(),
|
||||
"%flags%", StringMan.join(FlagManager.getPlotFlags(plot).values(), ","));
|
||||
if (!StringMan.isEqual(result, line)) {
|
||||
lines.set(i, result);
|
||||
}
|
||||
}
|
||||
stream.write(StringMan.join(lines, System.getProperty("line.separator")).getBytes());
|
||||
}
|
||||
|
||||
public static boolean save(final Plot plot, final BO3 bo3) {
|
||||
try {
|
||||
File bo3File = bo3.getFile();
|
||||
bo3File.createNewFile();
|
||||
try (FileOutputStream fos = new FileOutputStream(bo3File)) {
|
||||
write(fos, plot, bo3);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
final File base = getBaseFile(plot.getArea().worldname);
|
||||
try {
|
||||
final List<String> lines = Files.readAllLines(base.toPath(), StandardCharsets.UTF_8);
|
||||
|
|
|
@ -26,12 +26,35 @@ import com.intellectualcrafters.plot.config.Settings;
|
|||
import com.intellectualcrafters.plot.database.DBFunc;
|
||||
import com.intellectualcrafters.plot.flag.Flag;
|
||||
import com.intellectualcrafters.plot.flag.FlagManager;
|
||||
import com.intellectualcrafters.plot.object.*;
|
||||
|
||||
import com.intellectualcrafters.plot.object.ChunkLoc;
|
||||
import com.intellectualcrafters.plot.object.ConsolePlayer;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
|
@ -106,6 +129,86 @@ public class MainUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static void upload(UUID uuid, String file, String extension, final RunnableVal<OutputStream> writeTask, final RunnableVal<URL> whenDone) {
|
||||
if (writeTask == null) {
|
||||
PS.debug("&cWrite task cannot be null");
|
||||
TaskManager.runTask(whenDone);
|
||||
return;
|
||||
}
|
||||
final String filename;
|
||||
final String website;
|
||||
if (uuid == null) {
|
||||
uuid = UUID.randomUUID();
|
||||
website = Settings.WEB_URL + "upload.php?" + uuid;
|
||||
filename = "plot." + extension;
|
||||
} else {
|
||||
website = Settings.WEB_URL + "save.php?" + uuid;
|
||||
filename = file + "." + extension;
|
||||
}
|
||||
final URL url;
|
||||
try {
|
||||
url = new URL(Settings.WEB_URL + "?key=" + uuid + "&ip=" + Settings.WEB_IP + "&type=" + extension);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
whenDone.run();
|
||||
return;
|
||||
}
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final String boundary = Long.toHexString(System.currentTimeMillis());
|
||||
final URLConnection con = new URL(website).openConnection();
|
||||
con.setDoOutput(true);
|
||||
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
try (OutputStream output = con.getOutputStream();
|
||||
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8), true)) {
|
||||
final String CRLF = "\r\n";
|
||||
writer.append("--" + boundary).append(CRLF);
|
||||
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
|
||||
writer.append("Content-Type: text/plain; charset=" + StandardCharsets.UTF_8.displayName()).append(CRLF);
|
||||
final String param = "value";
|
||||
writer.append(CRLF).append(param).append(CRLF).flush();
|
||||
writer.append("--" + boundary).append(CRLF);
|
||||
writer.append("Content-Disposition: form-data; name=\"schematicFile\"; filename=\"" + filename + "\"").append(CRLF);
|
||||
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(filename)).append(CRLF);
|
||||
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
|
||||
writer.append(CRLF).flush();
|
||||
writeTask.value = output;
|
||||
writeTask.run();
|
||||
output.flush();
|
||||
writer.append(CRLF).flush();
|
||||
writer.append("--" + boundary + "--").append(CRLF).flush();
|
||||
}
|
||||
// try (Reader response = new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8)) {
|
||||
// final char[] buffer = new char[256];
|
||||
// final StringBuilder result = new StringBuilder();
|
||||
// while (true) {
|
||||
// final int r = response.read(buffer);
|
||||
// if (r < 0) {
|
||||
// break;
|
||||
// }
|
||||
// result.append(buffer, 0, r);
|
||||
// }
|
||||
// if (!result.toString().startsWith("Success")) {
|
||||
// PS.debug(result);
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
final int responseCode = ((HttpURLConnection) con).getResponseCode();
|
||||
if (responseCode == 200) {
|
||||
whenDone.value = url;
|
||||
}
|
||||
TaskManager.runTask(whenDone);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
TaskManager.runTask(whenDone);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the biome if it was modified
|
||||
* @param area
|
||||
|
|
|
@ -24,7 +24,6 @@ import com.intellectualcrafters.plot.object.PlotBlock;
|
|||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import com.intellectualcrafters.plot.object.schematic.PlotItem;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -34,14 +33,10 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
@ -566,72 +561,26 @@ public abstract class SchematicHandler {
|
|||
return null;
|
||||
}
|
||||
|
||||
public URL upload(final CompoundTag tag, UUID uuid, String file) {
|
||||
public void upload(final CompoundTag tag, UUID uuid, String file, RunnableVal<URL> whenDone) {
|
||||
if (tag == null) {
|
||||
PS.debug("&cCannot save empty tag");
|
||||
return null;
|
||||
TaskManager.runTask(whenDone);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String website;
|
||||
if (uuid == null) {
|
||||
uuid = UUID.randomUUID();
|
||||
website = Settings.WEB_URL + "upload.php?" + uuid;
|
||||
file = "plot";
|
||||
} else {
|
||||
website = Settings.WEB_URL + "save.php?" + uuid;
|
||||
MainUtil.upload(uuid, file, "schematic", new RunnableVal<OutputStream>() {
|
||||
@Override
|
||||
public void run(OutputStream output) {
|
||||
try {
|
||||
GZIPOutputStream gzip = new GZIPOutputStream(output, true);
|
||||
NBTOutputStream nos = new NBTOutputStream(gzip);
|
||||
nos.writeTag(tag);
|
||||
nos.flush();
|
||||
gzip.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
final String boundary = Long.toHexString(System.currentTimeMillis());
|
||||
final URLConnection con = new URL(website).openConnection();
|
||||
con.setDoOutput(true);
|
||||
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
try (OutputStream output = con.getOutputStream();
|
||||
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8), true)) {
|
||||
final String CRLF = "\r\n";
|
||||
writer.append("--" + boundary).append(CRLF);
|
||||
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
|
||||
writer.append("Content-Type: text/plain; charset=" + StandardCharsets.UTF_8.displayName()).append(CRLF);
|
||||
final String param = "value";
|
||||
writer.append(CRLF).append(param).append(CRLF).flush();
|
||||
writer.append("--" + boundary).append(CRLF);
|
||||
writer.append("Content-Disposition: form-data; name=\"schematicFile\"; filename=\"" + file + ".schematic" + "\"").append(CRLF);
|
||||
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(file + ".schematic")).append(CRLF);
|
||||
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
|
||||
writer.append(CRLF).flush();
|
||||
final GZIPOutputStream gzip = new GZIPOutputStream(output);
|
||||
final NBTOutputStream nos = new NBTOutputStream(gzip);
|
||||
nos.writeTag(tag);
|
||||
gzip.finish();
|
||||
nos.flush();
|
||||
output.flush();
|
||||
writer.append(CRLF).flush();
|
||||
writer.append("--" + boundary + "--").append(CRLF).flush();
|
||||
nos.close();
|
||||
}
|
||||
// try (Reader response = new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8)) {
|
||||
// final char[] buffer = new char[256];
|
||||
// final StringBuilder result = new StringBuilder();
|
||||
// while (true) {
|
||||
// final int r = response.read(buffer);
|
||||
// if (r < 0) {
|
||||
// break;
|
||||
// }
|
||||
// result.append(buffer, 0, r);
|
||||
// }
|
||||
// if (!result.toString().equals("The file plot.schematic has been uploaded.")) {
|
||||
// PS.debug(result);
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
final int responseCode = ((HttpURLConnection) con).getResponseCode();
|
||||
if (responseCode != 200) {
|
||||
return null;
|
||||
}
|
||||
return new URL(Settings.WEB_URL + "?key=" + uuid + "&ip=" + Settings.WEB_IP);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}, whenDone);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
package com.intellectualcrafters.plot.util;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import com.intellectualcrafters.plot.object.schematic.PlotItem;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public abstract class WorldUtil {
|
||||
public static WorldUtil IMP;
|
||||
|
@ -19,6 +30,10 @@ public abstract class WorldUtil {
|
|||
public abstract String[] getSign(Location loc);
|
||||
|
||||
public abstract Location getSpawn(String world);
|
||||
|
||||
public abstract void setSpawn(Location loc);
|
||||
|
||||
public abstract void saveWorld(String world);
|
||||
|
||||
public abstract String getClosestMatchingName(PlotBlock plotBlock);
|
||||
|
||||
|
@ -37,4 +52,78 @@ public abstract class WorldUtil {
|
|||
public abstract void setSign(String world, int x, int y, int z, String[] lines);
|
||||
|
||||
public abstract void setBiomes(String world, RegionWrapper region, String biome);
|
||||
|
||||
public void upload(final Plot plot, final UUID uuid, final String file, final RunnableVal<URL> whenDone) {
|
||||
if (plot == null) {
|
||||
throw new IllegalArgumentException("Plot may not be null!");
|
||||
}
|
||||
final Location home = plot.getHome();
|
||||
MainUtil.upload(uuid, file, "zip", new RunnableVal<OutputStream>() {
|
||||
@Override
|
||||
public void run(OutputStream output) {
|
||||
try (final ZipOutputStream zos = new ZipOutputStream(output)) {
|
||||
final byte[] buffer = new byte[1024];
|
||||
final File dat = getDat(plot.getArea().worldname);
|
||||
Location spawn = getSpawn(plot.getArea().worldname);
|
||||
setSpawn(home);
|
||||
if (dat != null) {
|
||||
final ZipEntry ze = new ZipEntry("world" + File.separator + dat.getName());
|
||||
zos.putNextEntry(ze);
|
||||
final FileInputStream in = new FileInputStream(dat);
|
||||
int len;
|
||||
while ((len = in.read(buffer)) > 0) {
|
||||
zos.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
setSpawn(spawn);
|
||||
for (Plot current : plot.getConnectedPlots()) {
|
||||
final Location bot = current.getBottomAbs();
|
||||
final Location top = current.getTopAbs();
|
||||
final int brx = bot.getX() >> 9;
|
||||
final int brz = bot.getZ() >> 9;
|
||||
final int trx = top.getX() >> 9;
|
||||
final int trz = top.getZ() >> 9;
|
||||
for (int x = brx; x <= trx; x++) {
|
||||
for (int z = brz; z <= trz; z++) {
|
||||
final File file = getMcr(plot.getArea().worldname, x, z);
|
||||
if (file != null) {
|
||||
//final String name = "r." + (x - cx) + "." + (z - cz) + ".mca";
|
||||
String name = file.getName();
|
||||
final ZipEntry ze = new ZipEntry("world" + File.separator + "region" + File.separator + name);
|
||||
zos.putNextEntry(ze);
|
||||
final FileInputStream in = new FileInputStream(file);
|
||||
int len;
|
||||
while ((len = in.read(buffer)) > 0) {
|
||||
zos.write(buffer, 0, len);
|
||||
}
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
zos.closeEntry();
|
||||
zos.flush();
|
||||
zos.finish();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, whenDone);
|
||||
}
|
||||
|
||||
public File getDat(final String world) {
|
||||
final File file = new File(PS.get().IMP.getWorldContainer() + File.separator + world + File.separator + "level.dat");
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public File getMcr(final String world, final int x, final int z) {
|
||||
final File file = new File(PS.get().IMP.getWorldContainer(), world + File.separator + "region" + File.separator + "r." + x + "." + z + ".mca");
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.plotsquared.listener;
|
|||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
|
@ -14,13 +15,15 @@ import com.sk89q.worldedit.command.tool.Tool;
|
|||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.event.extent.EditSessionEvent;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.*;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.ChangeSetExtent;
|
||||
import com.sk89q.worldedit.extent.MaskingExtent;
|
||||
import com.sk89q.worldedit.extent.reorder.MultiStageReorder;
|
||||
import com.sk89q.worldedit.extent.world.FastModeExtent;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.eventbus.EventHandler.Priority;
|
||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashSet;
|
||||
|
||||
|
@ -39,18 +42,30 @@ public class WESubscriber {
|
|||
if (actor != null && actor.isPlayer()) {
|
||||
final String name = actor.getName();
|
||||
final PlotPlayer pp = PlotPlayer.wrap(name);
|
||||
if (pp != null && pp.getAttribute("worldedit")) {
|
||||
return;
|
||||
}
|
||||
final HashSet<RegionWrapper> mask = WEManager.getMask(pp);
|
||||
if (mask.isEmpty()) {
|
||||
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
|
||||
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
|
||||
}
|
||||
if (PS.get().hasPlotArea(world)) {
|
||||
final HashSet<RegionWrapper> mask;
|
||||
if (pp == null) {
|
||||
Player player = (Player) actor;
|
||||
Location loc = player.getLocation();
|
||||
com.intellectualcrafters.plot.object.Location pLoc = new com.intellectualcrafters.plot.object.Location(player.getWorld().getName(), loc.getBlockX(), loc.getBlockX(), loc.getBlockZ());
|
||||
Plot plot = pLoc.getPlot();
|
||||
if (plot == null) {
|
||||
event.setExtent(new com.sk89q.worldedit.extent.NullExtent());
|
||||
return;
|
||||
}
|
||||
mask = plot.getRegions();
|
||||
} else if (pp.getAttribute("worldedit")) {
|
||||
return;
|
||||
} else {
|
||||
mask = WEManager.getMask(pp);
|
||||
if (mask.isEmpty()) {
|
||||
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
|
||||
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
|
||||
}
|
||||
if (PS.get().hasPlotArea(world)) {
|
||||
event.setExtent(new com.sk89q.worldedit.extent.NullExtent());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Settings.CHUNK_PROCESSOR) {
|
||||
if (Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.plotsquared.sponge.SpongeMain;
|
|||
import com.plotsquared.sponge.object.SpongePlayer;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.block.BlockState;
|
||||
import org.spongepowered.api.block.BlockType;
|
||||
|
@ -355,7 +356,20 @@ public class SpongeUtil extends WorldUtil {
|
|||
result.setY(getHighestBlock(world, result.getX(), result.getZ()));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSpawn(Location loc) {
|
||||
World world = getWorld(loc.getWorld());
|
||||
if (world != null) {
|
||||
world.getProperties().setSpawnPosition(new Vector3i(loc.getX(), loc.getY(), loc.getZ()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveWorld(String worldname) {
|
||||
throw new NotImplementedException("TODO WIP"); // TODO FIXME
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSign(final Location loc) {
|
||||
final World world = SpongeUtil.getWorld(loc.getWorld());
|
||||
|
|
Loading…
Reference in a new issue