mirror of
https://github.com/md5sha256/AreaShop.git
synced 2026-11-07 01:42:34 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3dceaf98cd | ||
|
|
33c29a3756 | ||
|
|
771734360f | ||
|
|
539e908d32 |
No files matched your search
@@ -0,0 +1,23 @@
|
||||
name: Java CI with Gradle
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# Only run on PRs if the source branch is on someone else's repo
|
||||
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: ["ubuntu-latest", "windows-latest"]
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: gradle/wrapper-validation-action@v1.0.4
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: 'gradle'
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew clean build
|
||||
@@ -184,6 +184,13 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if Vault is present
|
||||
if(getServer().getPluginManager().getPlugin("Vault") == null) {
|
||||
error("Vault plugin is not present or has not loaded correctly");
|
||||
shutdownOnError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find WorldEdit integration version to load
|
||||
String weHandlerVersion;
|
||||
Plugin plugin = getServer().getPluginManager().getPlugin("WorldEdit");
|
||||
@@ -246,13 +253,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if Vault is present
|
||||
if(getServer().getPluginManager().getPlugin("Vault") == null) {
|
||||
error("Vault plugin is not present or has not loaded correctly");
|
||||
shutdownOnError();
|
||||
return;
|
||||
}
|
||||
|
||||
AreaShopModule asModule = new AreaShopModule(this, messageBridge, nms, bukkitInterface, worldEditInterface, worldGuardInterface, signErrorLogger, dependencyModule);
|
||||
injector = Guice.createInjector(Stage.PRODUCTION, new BukkitModule(getServer()), asModule);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public abstract class GeneralRegion implements GeneralRegionInterface, Comparable<GeneralRegion>, ReplacementProvider {
|
||||
|
||||
@@ -809,6 +810,40 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all blocks in a region for restoring later.
|
||||
* @param fileName The name of the file to save to (extension and folder will be added)
|
||||
* @return true if the region has been saved properly, otherwise false
|
||||
*/
|
||||
public CompletableFuture<Boolean> saveRegionBlocksAsync(String fileName) {
|
||||
if (!worldEditInterface.supportsAsyncOperations()) {
|
||||
return CompletableFuture.completedFuture(saveRegionBlocks(fileName));
|
||||
}
|
||||
// Check if the region is correct
|
||||
ProtectedRegion region = getRegion();
|
||||
if(region == null) {
|
||||
AreaShop.debug("Region '" + getName() + "' does not exist in WorldGuard, save failed");
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
// The path to save the schematic
|
||||
File saveFile = new File(plugin.getFileManager().getSchematicFolder() + File.separator + fileName);
|
||||
// Create parent directories
|
||||
File parent = saveFile.getParentFile();
|
||||
if(parent != null && !parent.exists()) {
|
||||
if(!parent.mkdirs()) {
|
||||
AreaShop.warn("Did not save region " + getName() + ", schematic directory could not be created: " + saveFile.getAbsolutePath());
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
}
|
||||
return worldEditInterface.saveRegionBlocksAsync(saveFile, this)
|
||||
.thenApply(result -> {
|
||||
if(result) {
|
||||
AreaShop.debug("Saved schematic async for region " + getName());
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore all blocks in a region for restoring later.
|
||||
* @param fileName The name of the file to save to (extension and folder will be added)
|
||||
@@ -831,6 +866,35 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore all blocks in a region for restoring later.
|
||||
* @param fileName The name of the file to save to (extension and folder will be added)
|
||||
* @return true if the region has been restored properly, otherwise false
|
||||
*/
|
||||
public CompletableFuture<Boolean> restoreRegionBlocksAsync(String fileName) {
|
||||
if (!worldEditInterface.supportsAsyncOperations()) {
|
||||
return CompletableFuture.completedFuture(restoreRegionBlocks(fileName));
|
||||
}
|
||||
if(getRegion() == null) {
|
||||
AreaShop.debug("Region '" + getName() + "' does not exist in WorldGuard, restore failed");
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
// The path to save the schematic
|
||||
File restoreFile = new File(plugin.getFileManager().getSchematicFolder() + File.separator + fileName);
|
||||
return worldEditInterface.restoreRegionBlocksAsync(restoreFile, this)
|
||||
.thenApply(result -> {
|
||||
if(result) {
|
||||
AreaShop.debug("Restored schematic async for region " + getName());
|
||||
// Sync back to main
|
||||
Do.syncLater(10, getSignsFeature().signManager()::update);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reset all flags of the region.
|
||||
*/
|
||||
@@ -1452,14 +1516,23 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
|
||||
String save = profileSection.getString(type.getValue() + ".save");
|
||||
String restore = profileSection.getString(type.getValue() + ".restore");
|
||||
// Save the region if needed
|
||||
boolean async = worldEditInterface.supportsAsyncOperations();
|
||||
if(save != null && !save.isEmpty()) {
|
||||
save = Message.fromString(save).replacements(this).getSingle();
|
||||
saveRegionBlocks(save);
|
||||
if (async) {
|
||||
saveRegionBlocksAsync(save);
|
||||
} else {
|
||||
saveRegionBlocks(save);
|
||||
}
|
||||
}
|
||||
// Restore the region if needed
|
||||
if(restore != null && !restore.isEmpty()) {
|
||||
restore = Message.fromString(restore).replacements(this).getSingle();
|
||||
restoreRegionBlocks(restore);
|
||||
if (async) {
|
||||
restoreRegionBlocksAsync(restore);
|
||||
} else {
|
||||
restoreRegionBlocks(restore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,8 @@ debug: false
|
||||
version: ${project.version}
|
||||
# Maximum number of blocks to save to or restore from a .schemetic file.
|
||||
maximumBlocks: 1000000
|
||||
# Maximum number of entities to save to or restore from a .schematic file (FAWE only)
|
||||
maximumEntities: 1000
|
||||
# Maximum number of locations the teleport function should check to find a safe spot.
|
||||
maximumTries: 50000
|
||||
|
||||
|
||||
+220
-36
@@ -2,19 +2,22 @@ package me.wiefferink.areashop.adapters.plugins;
|
||||
|
||||
import com.fastasyncworldedit.core.FaweAPI;
|
||||
import com.fastasyncworldedit.core.extent.clipboard.MemoryOptimizedClipboard;
|
||||
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReader;
|
||||
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
|
||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
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.extent.clipboard.io.BuiltInClipboardFormat;
|
||||
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.extent.clipboard.io.ClipboardWriter;
|
||||
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
@@ -36,14 +39,12 @@ import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
// Future: this class could use the schematic save/paste api of FAWE: https://github.com/boy0001/FastAsyncWorldedit/wiki/Pasting-a-schematic
|
||||
// This would not allow for shaping the schematic to a polygon region though
|
||||
@@ -82,16 +83,20 @@ public class FastAsyncWorldEditHandler extends WorldEditInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAsyncOperations() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Beta
|
||||
public CompletableFuture<Boolean> restoreRegionBlocksAsync(File rawFile, GeneralRegionInterface regionInterface) {
|
||||
// TODO implement using the FastAsyncWorldEdit api to paste async
|
||||
File file = null;
|
||||
ClipboardFormat format = null;
|
||||
for (ClipboardFormat formatOption : BuiltInClipboardFormat.values()) {
|
||||
if (new File(rawFile.getAbsolutePath() + "." + formatOption.getPrimaryFileExtension())
|
||||
.exists()) {
|
||||
file = new File(
|
||||
rawFile.getAbsolutePath() + "." + formatOption.getPrimaryFileExtension());
|
||||
format = formatOption;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -100,6 +105,11 @@ public class FastAsyncWorldEditHandler extends WorldEditInterface {
|
||||
+ ", schematic file does not exist: " + rawFile.getAbsolutePath());
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
ClipboardFormat format = ClipboardFormats.findByFile(file);
|
||||
if (format == null) {
|
||||
pluginInterface.debugI("Did not restore region " + regionInterface.getName() + ", could not find a valid clipboard format");
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
pluginInterface.debugI("Trying to restore region", regionInterface.getName(), " from file",
|
||||
file.getAbsolutePath(), "with format", format.getName());
|
||||
|
||||
@@ -113,36 +123,36 @@ public class FastAsyncWorldEditHandler extends WorldEditInterface {
|
||||
+ regionInterface.getWorldName());
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
final CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
|
||||
final FaweLimit limit = new FaweLimit();
|
||||
final FaweLimit limit = FaweLimit.MAX.copy();
|
||||
limit.MAX_CHANGES = pluginInterface.getConfig().getInt("maximumBlocks");
|
||||
EditSession editSession = WorldEdit.getInstance().newEditSessionBuilder()
|
||||
limit.MAX_ENTITIES = pluginInterface.getConfig().getInt("maximumEntities", (int) (limit.MAX_CHANGES / 1000));
|
||||
EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit()
|
||||
.newEditSessionBuilder()
|
||||
.world(world)
|
||||
.limit(limit)
|
||||
.relightMode(RelightMode.OPTIMAL)
|
||||
.build();
|
||||
editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE);
|
||||
ProtectedRegion region = regionInterface.getRegion();
|
||||
final RegionType regionType = region.getType();
|
||||
// Get the origin and size of the region
|
||||
final BlockVector3 origin = BlockVector3
|
||||
.at(region.getMinimumPoint().getBlockX(), region.getMinimumPoint().getBlockY(),
|
||||
BlockVector3 origin = BlockVector3
|
||||
.at(region.getMinimumPoint().getBlockX(),
|
||||
region.getMinimumPoint().getBlockY(),
|
||||
region.getMinimumPoint().getBlockZ());
|
||||
final RegionBoundMask mask = new RegionBoundMask(region);
|
||||
final File finalFile = file;
|
||||
final String regionName = regionInterface.getName();
|
||||
final double regionWidth = regionInterface.getWidth(), regionHeight = regionInterface.getHeight(), regionDepth = regionInterface.getDepth();
|
||||
final LocalSession session =
|
||||
new LocalSession(pluginInterface.getWorldEdit().getLocalConfiguration());
|
||||
final CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
|
||||
final RegionType regionType = region.getType();
|
||||
final Mask mask = new RegionBoundMask(region);
|
||||
FaweAPI.getTaskManager().async(() -> {
|
||||
// Read the schematic and paste it into the world
|
||||
try (Closer closer = Closer.create()) {
|
||||
FileInputStream fis = closer.register(new FileInputStream(finalFile));
|
||||
BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
|
||||
NBTInputStream nbtStream = new NBTInputStream(new GZIPInputStream(bis));
|
||||
ClipboardReader reader = new FastSchematicReader(nbtStream);
|
||||
final FileInputStream fis = closer.register(new FileInputStream(finalFile));
|
||||
final ClipboardReader reader = format.getReader(fis);
|
||||
final Clipboard clipboard = reader.read();
|
||||
|
||||
Clipboard clipboard = reader.read();
|
||||
if (clipboard.getDimensions().getY() != regionHeight
|
||||
|| clipboard.getDimensions().getX() != regionWidth
|
||||
|| clipboard.getDimensions().getZ() != regionDepth) {
|
||||
@@ -178,35 +188,29 @@ public class FastAsyncWorldEditHandler extends WorldEditInterface {
|
||||
"exceeded the block limit while restoring schematic of " + regionInterface.getName()
|
||||
+ ", limit in exception: " + e.getBlockLimit() + ", limit passed by AreaShop: "
|
||||
+ pluginInterface.getConfig().getInt("maximumBlocks"));
|
||||
CompletableFuture.completedFuture(false);
|
||||
completableFuture.complete(false);
|
||||
} catch (IOException e) {
|
||||
pluginInterface.getLogger().warning(
|
||||
"An error occured while restoring schematic of " + regionInterface.getName()
|
||||
"An error occurred while restoring schematic of " + regionInterface.getName()
|
||||
+ ", enable debug to see the complete stacktrace");
|
||||
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
|
||||
CompletableFuture.completedFuture(false);
|
||||
completableFuture.complete(false);
|
||||
} catch (Exception e) {
|
||||
pluginInterface.getLogger()
|
||||
.warning("crashed during restore of " + regionInterface.getName());
|
||||
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
|
||||
CompletableFuture.completedFuture(false);
|
||||
completableFuture.complete(false);
|
||||
}
|
||||
editSession.flushQueue();
|
||||
CompletableFuture.completedFuture(true);
|
||||
completableFuture.complete(true);
|
||||
});
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreRegionBlocks(File rawFile, GeneralRegionInterface regionInterface) {
|
||||
return restoreRegionBlocksAsync(rawFile, regionInterface).join();
|
||||
}
|
||||
|
||||
|
||||
@Beta
|
||||
public CompletableFuture<Boolean> saveRegionBlocksAsync(File file, GeneralRegionInterface regionInterface) {
|
||||
// TODO implement using the FastAsyncWorldEdit api to save async
|
||||
ClipboardFormat format = BuiltInClipboardFormat.MINECRAFT_STRUCTURE;
|
||||
ClipboardFormat format = BuiltInClipboardFormat.FAST;
|
||||
// TODO allow selecting FAWE format in the config? (when enabled you cannot go back to vanilla WorldEdit easily)
|
||||
|
||||
file = new File(file.getAbsolutePath() + "." + format.getPrimaryFileExtension());
|
||||
@@ -224,7 +228,7 @@ public class FastAsyncWorldEditHandler extends WorldEditInterface {
|
||||
}
|
||||
final FaweLimit limit = new FaweLimit();
|
||||
limit.MAX_CHANGES = pluginInterface.getConfig().getInt("maximumBlocks");
|
||||
EditSession editSession = WorldEdit.getInstance().newEditSessionBuilder()
|
||||
EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit().newEditSessionBuilder()
|
||||
.world(world)
|
||||
.relightMode(RelightMode.OPTIMAL)
|
||||
.limit(limit)
|
||||
@@ -253,6 +257,7 @@ public class FastAsyncWorldEditHandler extends WorldEditInterface {
|
||||
+ ", limit in exception: " + e.getBlockLimit() + ", limit passed by AreaShop: "
|
||||
+ pluginInterface.getConfig().getInt("maximumBlocks"));
|
||||
completableFuture.complete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try (Closer closer = Closer.create()) {
|
||||
@@ -262,7 +267,7 @@ public class FastAsyncWorldEditHandler extends WorldEditInterface {
|
||||
writer.write(clipboard);
|
||||
} catch (IOException e) {
|
||||
pluginInterface.getLogger().warning(
|
||||
"An error occured while saving schematic of " + regionName
|
||||
"An error occurred while saving schematic of " + regionName
|
||||
+ ", enable debug to see the complete stacktrace");
|
||||
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
|
||||
completableFuture.complete(false);
|
||||
@@ -271,15 +276,194 @@ public class FastAsyncWorldEditHandler extends WorldEditInterface {
|
||||
.warning("Crashed during save of " + regionName);
|
||||
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
|
||||
completableFuture.complete(false);
|
||||
return;
|
||||
}
|
||||
completableFuture.complete(true);
|
||||
});
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreRegionBlocks(File rawFile, GeneralRegionInterface regionInterface) {
|
||||
// TODO implement using the FastAsyncWorldEdit api to paste async
|
||||
File file = null;
|
||||
for (ClipboardFormat formatOption : BuiltInClipboardFormat.values()) {
|
||||
if (new File(rawFile.getAbsolutePath() + "." + formatOption.getPrimaryFileExtension())
|
||||
.exists()) {
|
||||
file = new File(
|
||||
rawFile.getAbsolutePath() + "." + formatOption.getPrimaryFileExtension());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (file == null) {
|
||||
pluginInterface.getLogger().info("Did not restore region " + regionInterface.getName()
|
||||
+ ", schematic file does not exist: " + rawFile.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
ClipboardFormat format = ClipboardFormats.findByFile(file);
|
||||
if (format == null) {
|
||||
pluginInterface.debugI("Did not restore region " + regionInterface.getName() + ", could not find a valid clipboard format");
|
||||
return false;
|
||||
}
|
||||
pluginInterface.debugI("Trying to restore region", regionInterface.getName(), " from file",
|
||||
file.getAbsolutePath(), "with format", format.getName());
|
||||
|
||||
com.sk89q.worldedit.world.World world = null;
|
||||
if (regionInterface.getName() != null) {
|
||||
world = BukkitAdapter.adapt(regionInterface.getWorld());
|
||||
}
|
||||
if (world == null) {
|
||||
pluginInterface.getLogger().info(
|
||||
"Did not restore region " + regionInterface.getName() + ", world not found: "
|
||||
+ regionInterface.getWorldName());
|
||||
return false;
|
||||
}
|
||||
final FaweLimit limit = FaweLimit.MAX.copy();
|
||||
limit.MAX_CHANGES = pluginInterface.getConfig().getInt("maximumBlocks");
|
||||
limit.MAX_ENTITIES = pluginInterface.getConfig().getInt("maximumEntities", (int) (limit.MAX_CHANGES / 1000));
|
||||
EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit()
|
||||
.newEditSessionBuilder()
|
||||
.world(world)
|
||||
.limit(limit)
|
||||
.build();
|
||||
editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE);
|
||||
ProtectedRegion region = regionInterface.getRegion();
|
||||
// Get the origin and size of the region
|
||||
BlockVector3 origin = BlockVector3
|
||||
.at(region.getMinimumPoint().getBlockX(), region.getMinimumPoint().getBlockY(),
|
||||
region.getMinimumPoint().getBlockZ());
|
||||
|
||||
|
||||
// Read the schematic and paste it into the world
|
||||
try(Closer closer = Closer.create()) {
|
||||
final FileInputStream fis = closer.register(new FileInputStream(file));
|
||||
final ClipboardReader reader = format.getReader(fis);
|
||||
final Clipboard clipboard = reader.read();
|
||||
if (clipboard.getDimensions().getY() != regionInterface.getHeight()
|
||||
|| clipboard.getDimensions().getX() != regionInterface.getWidth()
|
||||
|| clipboard.getDimensions().getZ() != regionInterface.getDepth()) {
|
||||
pluginInterface.getLogger().warning(
|
||||
"Size of the region " + regionInterface.getName()
|
||||
+ " is not the same as the schematic to restore!");
|
||||
pluginInterface.debugI(
|
||||
"schematic|region, x:" + clipboard.getDimensions().getX() + "|"
|
||||
+ regionInterface.getWidth() + ", y:" + clipboard.getDimensions().getY()
|
||||
+ "|" + regionInterface.getHeight() + ", z:" + clipboard.getDimensions()
|
||||
.getZ() + "|" + regionInterface.getDepth());
|
||||
}
|
||||
clipboard.setOrigin(clipboard.getMinimumPoint());
|
||||
ClipboardHolder clipboardHolder = new ClipboardHolder(clipboard);
|
||||
LocalSession session =
|
||||
new LocalSession(pluginInterface.getWorldEdit().getLocalConfiguration());
|
||||
session.setBlockChangeLimit(pluginInterface.getConfig().getInt("maximumBlocks"));
|
||||
session.setClipboard(clipboardHolder);
|
||||
|
||||
// Build operation
|
||||
|
||||
BlockTransformExtent extent = new BlockTransformExtent(clipboard);
|
||||
ForwardExtentCopy copy =
|
||||
new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(),
|
||||
editSession, origin);
|
||||
copy.setTransform(clipboardHolder.getTransform());
|
||||
// Mask to region (for polygon and other weird shaped regions)
|
||||
// TODO make this more efficient (especially for polygon regions)
|
||||
if (region.getType() != RegionType.CUBOID) {
|
||||
copy.setSourceMask(new RegionBoundMask(region));
|
||||
}
|
||||
Operations.completeLegacy(copy);
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
pluginInterface.getLogger().warning(
|
||||
"exceeded the block limit while restoring schematic of " + regionInterface.getName()
|
||||
+ ", limit in exception: " + e.getBlockLimit() + ", limit passed by AreaShop: "
|
||||
+ pluginInterface.getConfig().getInt("maximumBlocks"));
|
||||
return false;
|
||||
} catch (FaweException ex) {
|
||||
pluginInterface.getLogger().warning(
|
||||
"exceeded the block entity limit while restoring schematic of " + regionInterface.getName()
|
||||
+ ", limit passed by AreaShop: "
|
||||
+ pluginInterface.getConfig().getInt("maximumEntities"));
|
||||
return false;
|
||||
}
|
||||
catch (IOException e) {
|
||||
pluginInterface.getLogger().warning(
|
||||
"An error occurred while restoring schematic of " + regionInterface.getName()
|
||||
+ ", enable debug to see the complete stacktrace");
|
||||
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
pluginInterface.getLogger()
|
||||
.warning("crashed during restore of " + regionInterface.getName());
|
||||
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
|
||||
return false;
|
||||
}
|
||||
editSession.flushQueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveRegionBlocks(File file, GeneralRegionInterface regionInterface) {
|
||||
return saveRegionBlocksAsync(file, regionInterface).join();
|
||||
// TODO implement using the FastAsyncWorldEdit api to save async
|
||||
ClipboardFormat format = BuiltInClipboardFormat.FAST;
|
||||
// TODO allow selecting FAWE format in the config? (when enabled you cannot go back to vanilla WorldEdit easily)
|
||||
|
||||
file = new File(file.getAbsolutePath() + "." + format.getPrimaryFileExtension());
|
||||
pluginInterface.debugI("Trying to save region", regionInterface.getName(), " to file",
|
||||
file.getAbsolutePath(), "with format", format.getName());
|
||||
com.sk89q.worldedit.world.World world = null;
|
||||
if (regionInterface.getWorld() != null) {
|
||||
world = BukkitAdapter.adapt(regionInterface.getWorld());
|
||||
}
|
||||
if (world == null) {
|
||||
pluginInterface.getLogger().warning(
|
||||
"Did not save region " + regionInterface.getName() + ", world not found: "
|
||||
+ regionInterface.getWorldName());
|
||||
return false;
|
||||
}
|
||||
EditSession editSession =
|
||||
pluginInterface.getWorldEdit().getWorldEdit()
|
||||
.newEditSessionBuilder()
|
||||
.world(world)
|
||||
.maxBlocks(pluginInterface.getConfig().getInt("maximumBlocks"))
|
||||
.build();
|
||||
|
||||
// Create a clipboard
|
||||
CuboidRegion selection =
|
||||
new CuboidRegion(world, regionInterface.getRegion().getMinimumPoint(),
|
||||
regionInterface.getRegion().getMaximumPoint());
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(selection);
|
||||
clipboard.setOrigin(regionInterface.getRegion().getMinimumPoint());
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(editSession,
|
||||
new CuboidRegion(world, regionInterface.getRegion().getMinimumPoint(),
|
||||
regionInterface.getRegion().getMaximumPoint()), clipboard,
|
||||
regionInterface.getRegion().getMinimumPoint());
|
||||
try {
|
||||
Operations.completeLegacy(copy);
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
pluginInterface.getLogger().warning(
|
||||
"Exceeded the block limit while saving schematic of " + regionInterface.getName()
|
||||
+ ", limit in exception: " + e.getBlockLimit() + ", limit passed by AreaShop: "
|
||||
+ pluginInterface.getConfig().getInt("maximumBlocks"));
|
||||
return false;
|
||||
}
|
||||
|
||||
try (Closer closer = Closer.create()) {
|
||||
FileOutputStream fos = closer.register(new FileOutputStream(file));
|
||||
BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
|
||||
ClipboardWriter writer = closer.register(format.getWriter(bos));
|
||||
writer.write(clipboard);
|
||||
} catch (IOException e) {
|
||||
pluginInterface.getLogger().warning(
|
||||
"An error occurred while saving schematic of " + regionInterface.getName()
|
||||
+ ", enable debug to see the complete stacktrace");
|
||||
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
pluginInterface.getLogger()
|
||||
.warning("Crashed during save of " + regionInterface.getName());
|
||||
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+26
@@ -3,6 +3,7 @@ package me.wiefferink.areashop.interfaces;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public abstract class WorldEditInterface {
|
||||
protected final AreaShopInterface pluginInterface;
|
||||
@@ -11,6 +12,10 @@ public abstract class WorldEditInterface {
|
||||
this.pluginInterface = pluginInterface;
|
||||
}
|
||||
|
||||
public boolean supportsAsyncOperations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Different way to restore blocks per implementation, newer ones support entities as well.
|
||||
* Why: the schematic api has changed between WorldEdit 5 and 6, and the schematic format changed between 6 and 7
|
||||
@@ -20,6 +25,16 @@ public abstract class WorldEditInterface {
|
||||
*/
|
||||
public abstract boolean restoreRegionBlocks(File file, GeneralRegionInterface regionInterface);
|
||||
|
||||
/**
|
||||
* Different way to restore blocks per implementation, newer ones support entities as well.
|
||||
* @param file File to try restoring from to the location of the region
|
||||
* @param regionInterface Region to restore from
|
||||
* @return true when successful, otherwise false
|
||||
*/
|
||||
public CompletableFuture<Boolean> restoreRegionBlocksAsync(File file, GeneralRegionInterface regionInterface) {
|
||||
return CompletableFuture.completedFuture(restoreRegionBlocks(file, regionInterface));
|
||||
}
|
||||
|
||||
/**
|
||||
* Different way to save blocks per implementation, newer ones support entities as well.
|
||||
* Why: the schematic api has changed between WorldEdit 5 and 6, and the schematic format changed between 6 and 7
|
||||
@@ -29,6 +44,17 @@ public abstract class WorldEditInterface {
|
||||
*/
|
||||
public abstract boolean saveRegionBlocks(File file, GeneralRegionInterface regionInterface);
|
||||
|
||||
/**
|
||||
* Different way to save blocks per implementation, newer ones support entities as well.
|
||||
* Why: the schematic api has changed between WorldEdit 5 and 6, and the schematic format changed between 6 and 7
|
||||
* @param file File to try saving the region to
|
||||
* @param regionInterface Region to restore from
|
||||
* @return true when successful, otherwise false
|
||||
*/
|
||||
public CompletableFuture<Boolean> saveRegionBlocksAsync(File file, GeneralRegionInterface regionInterface) {
|
||||
return CompletableFuture.completedFuture(saveRegionBlocks(file, regionInterface));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selection of the player.
|
||||
* Why: the underlying WorldEdit selection class has changed from interface <-> class
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "me.wiefferink"
|
||||
version = "2.7.4"
|
||||
version = "2.7.5"
|
||||
|
||||
subprojects {
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ pluginManagement {
|
||||
buildCache {
|
||||
local {
|
||||
directory = File(rootDir, "build-cache")
|
||||
removeUnusedEntriesAfterDays = 7
|
||||
removeUnusedEntriesAfterDays = 30
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user