Compare commits

..
43 Commits
Author SHA1 Message Date
Andrew Wong 172b5a99f1 Bump version to release 2022-09-12 22:21:28 +08:00
Andrew Wong 4c5d025e54 Add config option to toggle whether entities are forcefully cleared 2022-09-12 22:20:55 +08:00
Andrew Wong e93a2d04de Forcefully remove entities from FAWE/WE regions before schematic pasting 2022-09-12 22:12:18 +08:00
Andrew Wong af5980d555 Change the messages for update checking and report file manager loading failures 2022-09-12 17:58:09 +08:00
Andrew Wong 3f7249f4a1 Merge pull request #13 from cleonyc/dev/bleeding
Allow unrented event to use placeholders
2022-09-12 17:39:56 +08:00
Andrew Wong 73c6fc858e Update the logging methods to invoke conditionally 2022-09-12 17:37:47 +08:00
Andrew Wong 360c3e7e21 Use Suppliers when logging in the plugin adapters 2022-09-12 17:35:55 +08:00
Andrew Wong 73d0115b78 Actually fix the FAWE and WE handlers when pasting 2022-09-12 17:25:27 +08:00
Andrew Wong baf7eaabf1 Bump versions of WE and FAWE in the libs.toml 2022-09-11 00:50:36 +08:00
Andrew Wong ca8c0487a8 Fix origin setting so that the blocks paste properly 2022-09-11 00:44:47 +08:00
Andrew Wong 24156a03c4 Rewrite region saving and restoring in the adapters 2022-09-10 23:14:28 +08:00
Andrew Wong ec677766d2 Attempt to prevent duplicate signs from loading 2022-09-10 19:27:03 +08:00
Andrew Wong ef6c8fbf9d Only remove leashes, paintings and item frames 2022-09-10 17:54:48 +08:00
Andrew Wong 4f52fe9e6e Forcefully remvoe Entities in the region before pasting 2022-09-10 17:43:07 +08:00
Andrew Wong 3ebe5a6fa9 Use the WG converter to convert WG regions to WE ones 2022-09-10 17:02:29 +08:00
Andrew Wong 3cebe5d2c7 Fix NPE with sign deletion after worlededit operations 2022-09-10 14:59:35 +08:00
Andrew Wong c76415c4f3 Fix NPE when tabbing region restore 2022-09-10 12:47:45 +08:00
Andrew Wong b7bc02aef3 Compile against 1.19.2 and update the gradle wrapper 2022-09-07 15:31:33 +08:00
Cleo d75094e191 Remove unrenting section in eventCommandProfile 2022-07-07 13:51:02 -04:00
Cleo 4045914b48 Fix placeholders in unrented command event [#11] 2022-07-07 13:50:04 -04:00
Andrew Wong 1fac002ee0 Remove the Bukkit113 module and update the versioning url 2022-06-20 19:57:22 +08:00
Andrew Wong 64301e74e0 Bump version 2022-06-20 19:27:28 +08:00
Andrew Wong 5a5a7fc5ef Bump version 2022-06-20 19:25:42 +08:00
Andrew Wong b928caf0c2 Bump worldedit 2022-06-20 19:19:49 +08:00
Andrew Wong 111f629787 Update dependencies and add adapter for 1.19 2022-06-11 00:59:19 +08:00
Andrew Wong 718474ca95 Update gradle wrapper 2022-06-10 23:37:12 +08:00
Andrew Wong 93b9df3e54 Update gradle wrapper to 7.4.1 2022-03-24 18:48:03 +08:00
Andrew Wong bad983a0b8 Update worldedit and fawe adapters 2022-03-24 18:47:02 +08:00
Andrew Wong e2c8b06b68 Bump dependency versions 2022-03-24 16:30:02 +08:00
Andrew Wong 7249e39c02 bump version 2022-03-24 16:27:49 +08:00
Andrew Wong 9d9a58a170 bump to 2.7.6 2022-03-24 16:24:56 +08:00
Andrew Wong e64e884c2a Updates to the fawe module 2022-03-05 00:00:34 +08:00
Andrew Wong 6ad4ff9deb Shade in the provider for 1.18.1 2022-03-05 00:00:23 +08:00
Andrew Wong eec9806492 Add back support for 1.18.1 2022-03-04 23:08:43 +08:00
Andrew Wong 43b2ae8278 Fix bad website in plugin.yml 2022-03-04 22:54:40 +08:00
Andrew Wong 6d5a92e389 1.18.2 2022-03-04 22:48:39 +08:00
Andrew Wong 7d7a62ffa0 Bump gradle wrapper to 7.4 2022-03-03 17:41:52 +08:00
md5sha256 44456d87b6 Fix the sign error file extension 2022-01-25 05:49:47 +08:00
md5sha256 d92c710b27 bump version to snapshot 2022-01-25 05:49:35 +08:00
md5sha256 3dceaf98cd Bump version to 2.7.5 2022-01-25 05:35:08 +08:00
md5sha256 33c29a3756 Fix the fawe integration and do operations async when possible 2022-01-25 05:34:34 +08:00
md5sha256 771734360f add workflow 2022-01-16 23:24:28 +08:00
md5sha256 539e908d32 Initial work on fixing the deadlock in the fawe module 2022-01-16 21:45:11 +08:00
43 changed files with 963 additions and 664 deletions

No files matched your search

+23
View File
@@ -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
+7 -3
View File
@@ -29,16 +29,15 @@ dependencies {
implementation("com.github.NLthijs48:InteractiveMessenger:e7749258ca")
implementation("com.github.NLthijs48:BukkitDo:819d51ec2b")
implementation("io.github.baked-libs:dough-data:1.0.3")
implementation("com.google.inject:guice:5.0.1") {
implementation("com.google.inject:guice:5.1.0") {
exclude("com.google.guava", "guava")
}
implementation("com.google.inject.extensions:guice-assistedinject:5.0.1") {
implementation("com.google.inject.extensions:guice-assistedinject:5.1.0") {
exclude("com.google.guava", "guava")
}
// Project submodules
implementation(projects.areashopInterface)
implementation(projects.areashopBukkit113)
implementation(projects.areashopNms)
// Adapters
runtimeOnly(projects.adapters.plugins.worldedit)
@@ -46,6 +45,11 @@ dependencies {
runtimeOnly(projects.adapters.plugins.fastasyncworldedit)
runtimeOnly(project(":adapters:platform:bukkit-1-17", "reobf"))
runtimeOnly(project(":adapters:platform:bukkit-1-18", "reobf"))
runtimeOnly(project(":adapters:platform:bukkit-1-19", "reobf"))
}
repositories {
mavenCentral()
}
tasks {
@@ -8,7 +8,6 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.managers.RegionManager;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.listeners.PlayerLoginLogoutListener;
@@ -50,8 +49,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.function.Supplier;
/**
* Main class for the AreaShop plugin.
@@ -68,7 +66,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
private WorldEditPlugin worldEdit = null;
private WorldEditInterface worldEditInterface = null;
private NMS nms;
private BukkitInterface bukkitInterface = null;
private MessageBridge messageBridge;
private IFileManager fileManager = null;
private LanguageManager languageManager = null;
@@ -91,7 +88,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
public static final String defaultFile = "default.yml";
public static final String configFile = "config.yml";
public static final String configFileHidden = "hiddenConfig.yml";
public static final String signLogFile = "sign-errors.yml";
public static final String signLogFile = "sign-errors.log";
public static final String versionFile = "versions";
// Euro tag for in the config
@@ -166,7 +163,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
AreaShop.instance = this;
Do.init(this);
managers = new HashSet<>();
boolean error = false;
messageBridge = new SimpleMessageBridge();
signErrorLogger = new SignErrorLogger(new File(getDataFolder(), signLogFile));
@@ -184,6 +180,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");
@@ -237,30 +240,17 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
return;
}
try {
Class<?> clazz = Class.forName("me.wiefferink.areashop.handlers.BukkitHandler1_13");
bukkitInterface = (BukkitInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this);
} catch (Exception e) {
error("Could not load the Bukkit handler (used for sign updates), report this problem to the author:", ExceptionUtils.getStackTrace(e));
shutdownOnError();
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);
AreaShopModule asModule = new AreaShopModule(this, messageBridge, nms, worldEditInterface, worldGuardInterface, signErrorLogger, dependencyModule);
injector = Guice.createInjector(Stage.PRODUCTION, new BukkitModule(getServer()), asModule);
// Load all data from files and check versions
fileManager = injector.getInstance(IFileManager.class);
managers.add((FileManager) fileManager);
boolean loadFilesResult = fileManager.loadFiles(false);
error = error || !loadFilesResult;
if (!loadFilesResult) {
shutdownOnError();
return;
}
setupLanguageManager();
@@ -300,7 +290,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
return;
}
AreaShop.info("Update from AreaShop V" + cleanVersion(result.getCurrentVersion()) + " to AreaShop V" + cleanVersion(result.getLatestVersion()) + " available, get the latest version at https://www.spigotmc.org/resources/areashop.2991/");
AreaShop.info("Update from AreaShop V" + cleanVersion(result.getCurrentVersion()) + " to AreaShop V" + cleanVersion(result.getLatestVersion()) + " available, get the latest version at https://github.com/md5sha256/releases");
for(Player player : Utils.getOnlinePlayers()) {
notifyUpdate(player);
}
@@ -454,6 +444,11 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
return worldEdit;
}
@Override
public Plugin pluginInstance() {
return this;
}
/**
* Function to get WorldGuardInterface for version dependent things.
* @return WorldGuardInterface
@@ -470,14 +465,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
return languageManager;
}
/**
* Get the BukkitHandler, for sign interactions.
* @return BukkitHandler
*/
public BukkitInterface getBukkitHandler() {
return this.bukkitInterface;
}
/**
* Function to get the CommandManager.
* @return the CommandManager
@@ -704,12 +691,19 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
AreaShop.debug(StringUtils.join(message, " "));
}
@Override
public void debugI(Supplier<String> message) {
if (debug) {
info("Debug: " + message.get());
}
}
/**
* Print an information message to the console.
* @param message The message to print
*/
public static void info(Object... message) {
AreaShop.getInstance().getLogger().info(StringUtils.join(message, " "));
AreaShop.getInstance().getLogger().info(() -> StringUtils.join(message, " "));
}
/**
@@ -717,7 +711,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
* @param message The message to print
*/
public static void warn(Object... message) {
AreaShop.getInstance().getLogger().warning(StringUtils.join(message, " "));
AreaShop.getInstance().getLogger().warning(() -> StringUtils.join(message, " "));
}
/**
@@ -725,7 +719,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
* @param message The message to print
*/
public static void error(Object... message) {
AreaShop.getInstance().getLogger().severe(StringUtils.join(message, " "));
AreaShop.getInstance().getLogger().severe(() -> StringUtils.join(message, " "));
}
/**
@@ -3,10 +3,10 @@ package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.features.signs.RegionSign;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -33,8 +33,6 @@ public class AddsignCommand extends CommandAreaShop {
private SignManager signManager;
@Inject
private Plugin plugin;
@Inject
private BukkitInterface bukkitInterface;
@Override
public String getCommandStart() {
@@ -111,7 +109,7 @@ public class AddsignCommand extends CommandAreaShop {
return;
}
region.getSignsFeature().addSign(block.getLocation(), block.getType(), bukkitInterface.getSignFacing(block), profile);
region.getSignsFeature().addSign(block.getLocation(), block.getType(), SignUtils.getSignFacing(block), profile);
if(profile == null) {
messageBridge.message(sender, "addsign-success", region);
} else {
@@ -55,7 +55,7 @@ public class DelsignCommand extends CommandAreaShop {
BlockIterator blockIterator = new BlockIterator(player, 100);
while(blockIterator.hasNext() && block == null) {
Block next = blockIterator.next();
if(next.getType() != Material.AIR) {
if(!next.getType().isAir()) {
block = next;
}
}
@@ -70,8 +70,9 @@ public class DelsignCommand extends CommandAreaShop {
}
RegionSign regionSign = optionalSign.get();
messageBridge.message(sender, "delsign-success", regionSign.getRegion());
signManager.removeSign(regionSign);
regionSign.remove();
// Sometimes the RegionSign data is corrupted. Forcefully set the block to air
block.setType(Material.AIR);
}
@Override
@@ -44,8 +44,7 @@ public class SellCommand extends CommandAreaShop {
if(person.hasPermission("areashop.sell")) {
return true;
}
if(person instanceof Player) {
Player player = (Player)person;
if(person instanceof Player player) {
return region.isOwner(player) && person.hasPermission("areashop.sellown");
}
return false;
@@ -59,9 +58,9 @@ public class SellCommand extends CommandAreaShop {
}
BuyRegion buy;
if(args.length <= 1) {
if(sender instanceof Player) {
if(sender instanceof Player player) {
// get the region by location
List<BuyRegion> regions = Utils.getImportantBuyRegions(((Player)sender).getLocation());
List<BuyRegion> regions = Utils.getImportantBuyRegions((player).getLocation());
if(regions.isEmpty()) {
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
@@ -1,9 +1,11 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.Plugin;
import javax.inject.Inject;
@@ -79,7 +81,10 @@ public class SetrestoreCommand extends CommandAreaShop {
result.add("false");
result.add("general");
} else if(toComplete == 4) {
result.addAll(plugin.getConfig().getConfigurationSection("schematicProfiles").getKeys(false));
ConfigurationSection schemProfiles = fileManager.getConfig().getConfigurationSection("schematicProfiles");
if (schemProfiles != null) {
result.addAll(schemProfiles.getKeys(false));
}
}
return result;
}
@@ -6,11 +6,11 @@ import com.google.inject.assistedinject.AssistedInject;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import io.papermc.lib.PaperLib;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import me.wiefferink.areashop.managers.SignErrorLogger;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.Bukkit;
@@ -37,7 +37,6 @@ public class RegionSign {
private final BlockBehaviourHelper blockHelper;
private final SignErrorLogger errorLogger;
private final BukkitInterface bukkitInterface;
private final SignsFeature signsFeature;
private final String key;
@@ -47,13 +46,11 @@ public class RegionSign {
RegionSign(
@Nonnull BlockBehaviourHelper blockBehaviourHelper,
@Nonnull SignErrorLogger signErrorLogger,
@Nonnull BukkitInterface bukkitInterface,
@Assisted @Nonnull SignsFeature signsFeature,
@Assisted @Nonnull String key
) {
this.blockHelper = blockBehaviourHelper;
this.errorLogger = signErrorLogger;
this.bukkitInterface = bukkitInterface;
this.signsFeature = signsFeature;
this.key = key;
}
@@ -98,8 +95,11 @@ public class RegionSign {
* Remove this sign from the region.
*/
public void remove() {
getLocation().getBlock().setType(Material.AIR);
this.signsFeature.signManager().removeSign(this);
Location location = getLocation();
if (location != null && location.getWorld() != null) {
location.getBlock().setType(Material.AIR);
this.signsFeature.signManager().removeSign(this);
}
getRegion().setSetting("general.signs." + key, null);
// Remove the sign from the region's sign manager
}
@@ -208,7 +208,7 @@ public class RegionSign {
getRegion().setSetting("general.signs." + key + ".signType", block.getType().name());
}
if(!regionConfig.isString("general.signs." + key + ".facing")) {
BlockFace signFacing = bukkitInterface.getSignFacing(block);
BlockFace signFacing = SignUtils.getSignFacing(block);
getRegion().setSetting("general.signs." + key + ".facing", signFacing == null ? null : signFacing.toString());
}
@@ -8,6 +8,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
@@ -40,7 +41,7 @@ public class SignCache {
BlockPosition blockPosition = regionSign.getPosition();
this.allSigns.put(blockPosition.getPosition(), regionSign);
ChunkPosition chunkPosition = new ChunkPosition(blockPosition.getChunk());
Collection<RegionSign> signs = this.signsByChunk.computeIfAbsent(chunkPosition.getPosition(), x -> new ArrayList<>());
Collection<RegionSign> signs = this.signsByChunk.computeIfAbsent(chunkPosition.getPosition(), x -> new HashSet<>());
signs.add(regionSign);
}
@@ -7,7 +7,6 @@ import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
import me.wiefferink.areashop.events.notify.UpdateRegionEvent;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignLinkerManager;
@@ -17,6 +16,7 @@ import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionFactory;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.bukkitdo.Do;
import org.bukkit.Chunk;
@@ -36,6 +36,7 @@ import org.bukkit.event.world.ChunkLoadEvent;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -47,7 +48,6 @@ public class SignListener implements Listener {
private final MessageBridge messageBridge;
private final SignManager signManager;
private final SignLinkerManager signLinkerManager;
private final BukkitInterface bukkitInterface;
private final WorldGuardInterface worldGuardInterface;
private final RegionFactory regionFactory;
private final IFileManager fileManager;
@@ -58,7 +58,6 @@ public class SignListener implements Listener {
@Nonnull RegionFactory regionFactory,
@Nonnull MessageBridge messageBridge,
@Nonnull SignLinkerManager signLinkerManager,
@Nonnull BukkitInterface bukkitInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull SignManager signManager,
@Nonnull IFileManager fileManager) {
@@ -68,7 +67,6 @@ public class SignListener implements Listener {
this.regionFactory = regionFactory;
this.behaviourHelper = behaviourHelper;
this.plugin = plugin;
this.bukkitInterface = bukkitInterface;
this.worldGuardInterface = worldGuardInterface;
this.messageBridge = messageBridge;
}
@@ -92,7 +90,6 @@ public class SignListener implements Listener {
if(chunkSigns.isEmpty()) {
return;
}
chunkSigns.remove(null);
Do.forAll(chunkSigns, RegionSign::update);
}
@@ -292,7 +289,7 @@ public class SignListener implements Listener {
if(durationSet) {
rent.setDuration(thirdLine);
}
rent.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), bukkitInterface.getSignFacing(event.getBlock()), null);
rent.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), SignUtils.getSignFacing(event.getBlock()), null);
AddingRegionEvent addingRegionEvent = plugin.getFileManager().addRegion(rent);
if (addingRegionEvent.isCancelled()) {
@@ -392,7 +389,7 @@ public class SignListener implements Listener {
if(priceSet) {
buy.setPrice(price);
}
buy.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), bukkitInterface.getSignFacing(event.getBlock()), null);
buy.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), SignUtils.getSignFacing(event.getBlock()), null);
AddingRegionEvent addingRegionEvent = plugin.getFileManager().addRegion(buy);
if (addingRegionEvent.isCancelled()) {
@@ -438,10 +435,10 @@ public class SignListener implements Listener {
}
if(thirdLine == null || thirdLine.isEmpty()) {
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), bukkitInterface.getSignFacing(event.getBlock()), null);
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), SignUtils.getSignFacing(event.getBlock()), null);
messageBridge.message(player, "addsign-success", region);
} else {
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), bukkitInterface.getSignFacing(event.getBlock()), thirdLine);
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), SignUtils.getSignFacing(event.getBlock()), thirdLine);
messageBridge.message(player, "addsign-successProfile", thirdLine, region);
}
@@ -1,6 +1,7 @@
package me.wiefferink.areashop.features.signs;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.managers.Manager;
import org.bukkit.Location;
import org.bukkit.World;
@@ -52,10 +53,17 @@ public class SignManager extends Manager {
}
public void removeSign(RegionSign regionSign) {
removeSign(regionSign.getLocation());
Location location = regionSign.getLocation();
if (location.getWorld() == null) {
return;
}
cacheForWorld(location.getWorld()).removeSign(regionSign);
}
public Optional<RegionSign> removeSign(Location location) {
if (location == null || location.getWorld() == null) {
return Optional.empty();
}
return getCacheForWorld(location.getWorld()).flatMap(cache -> cache.removeSign(location));
}
@@ -2,6 +2,8 @@ package me.wiefferink.areashop.features.signs;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import io.github.bakedlibs.dough.blocks.ChunkPosition;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.features.RegionFeature;
import me.wiefferink.areashop.regions.GeneralRegion;
@@ -12,6 +14,8 @@ import org.bukkit.block.BlockFace;
import org.bukkit.configuration.ConfigurationSection;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.Map;
public class SignsFeature extends RegionFeature {
@@ -34,17 +38,18 @@ public class SignsFeature extends RegionFeature {
setRegion(region);
// Setup current signs
ConfigurationSection signSection = region.getConfig().getConfigurationSection("general.signs");
if(signSection != null) {
for(String signKey : signSection.getKeys(false)) {
RegionSign sign = signFactory.createRegionSign(this, signKey);
Location location = sign.getLocation();
if(location == null) {
AreaShop.warn("Sign with key " + signKey + " of region " + region.getName() + " does not have a proper location");
continue;
}
this.globalSignManager.cacheForWorld(location.getWorld()).addSign(sign);
this.internalSignManager.addSign(sign);
if (signSection == null) {
return;
}
for(String signKey : signSection.getKeys(false)) {
RegionSign sign = signFactory.createRegionSign(this, signKey);
Location location = sign.getLocation();
if(location == null) {
AreaShop.warn("Sign with key " + signKey + " of region " + region.getName() + " does not have a proper location");
continue;
}
this.globalSignManager.cacheForWorld(location.getWorld()).addSign(sign);
this.internalSignManager.addSign(sign);
}
}
@@ -6,7 +6,6 @@ import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignLinkerManager;
@@ -30,7 +29,6 @@ public class SignsModule extends AbstractModule {
@Nonnull RegionFactory regionFactory,
@Nonnull MessageBridge messageBridge,
@Nonnull SignLinkerManager signLinkerManager,
@Nonnull BukkitInterface bukkitInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull SignManager signManager,
@Nonnull IFileManager fileManager
@@ -41,7 +39,6 @@ public class SignsModule extends AbstractModule {
regionFactory,
messageBridge,
signLinkerManager,
bukkitInterface,
worldGuardInterface,
signManager,
fileManager
@@ -43,6 +43,7 @@ import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -354,10 +355,10 @@ public class FileManager extends Manager implements IFileManager {
}
final String key = region.getName().toLowerCase(Locale.ENGLISH);
regions.put(key, region);
if (region instanceof BuyRegion) {
buys.put(key, (BuyRegion) region);
} else if (region instanceof RentRegion) {
rents.put(key, (RentRegion) region);
if (region instanceof BuyRegion buyRegion) {
buys.put(key, buyRegion);
} else if (region instanceof RentRegion rentRegion) {
rents.put(key, rentRegion);
}
Bukkit.getPluginManager().callEvent(new AddedRegionEvent(region));
return event;
@@ -837,8 +838,8 @@ public class FileManager extends Manager implements IFileManager {
}
// Load default.yml from the plugin folder, and as backup the default one
try(
InputStreamReader custom = new InputStreamReader(new FileInputStream(defaultFile), Charsets.UTF_8);
InputStreamReader normal = new InputStreamReader(plugin.getResource(AreaShop.defaultFile), Charsets.UTF_8)
InputStreamReader custom = new InputStreamReader(new FileInputStream(defaultFile), StandardCharsets.UTF_8);
InputStreamReader normal = new InputStreamReader(plugin.getResource(AreaShop.defaultFile), StandardCharsets.UTF_8)
) {
defaultConfig = YamlConfiguration.loadConfiguration(custom);
if(defaultConfig.getKeys(false).isEmpty()) {
@@ -878,9 +879,9 @@ public class FileManager extends Manager implements IFileManager {
}
// Load config.yml from the plugin folder
try(
InputStreamReader custom = new InputStreamReader(new FileInputStream(configFile), Charsets.UTF_8);
InputStreamReader normal = new InputStreamReader(plugin.getResource(AreaShop.configFile), Charsets.UTF_8);
InputStreamReader hidden = new InputStreamReader(plugin.getResource(AreaShop.configFileHidden), Charsets.UTF_8)
InputStreamReader custom = new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8);
InputStreamReader normal = new InputStreamReader(plugin.getResource(AreaShop.configFile), StandardCharsets.UTF_8);
InputStreamReader hidden = new InputStreamReader(plugin.getResource(AreaShop.configFileHidden), StandardCharsets.UTF_8)
) {
config = YamlConfiguration.loadConfiguration(custom);
if(config.getKeys(false).isEmpty()) {
@@ -917,7 +918,7 @@ public class FileManager extends Manager implements IFileManager {
File groupFile = new File(groupsPath);
if(groupFile.exists() && groupFile.isFile()) {
try(
InputStreamReader reader = new InputStreamReader(new FileInputStream(groupFile), Charsets.UTF_8)
InputStreamReader reader = new InputStreamReader(new FileInputStream(groupFile), StandardCharsets.UTF_8)
) {
groupsConfig = YamlConfiguration.loadConfiguration(reader);
} catch(IOException e) {
@@ -971,7 +972,7 @@ public class FileManager extends Manager implements IFileManager {
// Load the region file from disk in UTF8 mode
YamlConfiguration regionConfig;
try(
InputStreamReader reader = new InputStreamReader(new FileInputStream(regionFile), Charsets.UTF_8)
InputStreamReader reader = new InputStreamReader(new FileInputStream(regionFile), StandardCharsets.UTF_8)
) {
regionConfig = YamlConfiguration.loadConfiguration(reader);
if(regionConfig.getKeys(false).isEmpty()) {
@@ -4,9 +4,9 @@ import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.features.signs.RegionSign;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -41,8 +41,6 @@ public class SignLinkerManager extends Manager implements Listener {
@Inject
private AreaShop plugin;
@Inject
private BukkitInterface bukkitInterface;
@Inject
private SignManager signManager;
@Inject
private MessageBridge messageBridge;
@@ -147,7 +145,7 @@ public class SignLinkerManager extends Manager implements Listener {
messageBridge.message(player, "linksigns-alreadyRegistered", regionSign.getRegion());
return;
}
linker.setSign(block.getLocation(), block.getType(), bukkitInterface.getSignFacing(block));
linker.setSign(block.getLocation(), block.getType(), SignUtils.getSignFacing(block));
}
}
}
@@ -7,7 +7,6 @@ import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.features.FeatureFactory;
import me.wiefferink.areashop.features.signs.SignsModule;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.CommandManager;
@@ -28,7 +27,6 @@ import javax.annotation.Nonnull;
public class AreaShopModule extends AbstractModule {
private final AreaShop instance;
private final BukkitInterface bukkitInterface;
private final WorldGuardInterface worldGuardInterface;
private final WorldEditInterface worldEditInterface;
private final NMS nms;
@@ -39,7 +37,6 @@ public class AreaShopModule extends AbstractModule {
public AreaShopModule(@Nonnull AreaShop instance,
@Nonnull MessageBridge messageBridge,
@Nonnull NMS nms,
@Nonnull BukkitInterface bukkitInterface,
@Nonnull WorldEditInterface worldEditInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull SignErrorLogger signErrorLogger,
@@ -49,7 +46,6 @@ public class AreaShopModule extends AbstractModule {
this.messageBridge = messageBridge;
this.nms = nms;
this.signErrorLogger = signErrorLogger;
this.bukkitInterface = bukkitInterface;
this.worldEditInterface = worldEditInterface;
this.worldGuardInterface = worldGuardInterface;
this.dependencyModule = dependencyModule;
@@ -63,7 +59,6 @@ public class AreaShopModule extends AbstractModule {
bind(MessageBridge.class).toInstance(this.messageBridge);
bind(NMS.class).toInstance(this.nms);
bind(BlockBehaviourHelper.class).toInstance(this.nms.blockBehaviourHelper());
bind(BukkitInterface.class).toInstance(this.bukkitInterface);
bind(WorldGuardInterface.class).toInstance(this.worldGuardInterface);
bind(WorldEditInterface.class).toInstance(this.worldEditInterface);
bind(SignErrorLogger.class).toInstance(this.signErrorLogger);
@@ -479,7 +479,7 @@ public class BuyRegion extends GeneralRegion {
*/
@SuppressWarnings("deprecation")
public boolean sell(boolean giveMoneyBack, CommandSender executor) {
boolean own = executor instanceof Player && this.isBuyer((Player)executor);
boolean own = executor instanceof Player player && this.isBuyer(player);
if(executor != null) {
if(!executor.hasPermission("areashop.sell") && !own) {
message(executor, "sell-noPermissionOther");
@@ -534,7 +534,7 @@ public class BuyRegion extends GeneralRegion {
// Give back the money
OfflinePlayer player = Bukkit.getOfflinePlayer(getBuyer());
if(player != null && !noPayBack) {
if(player.hasPlayedBefore() && !noPayBack) {
EconomyResponse response = null;
boolean error = false;
try {
@@ -31,6 +31,7 @@ import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import javax.annotation.Nonnull;
import java.awt.geom.Area;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
@@ -45,6 +46,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 {
@@ -682,32 +684,20 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
if(tp == null) {
return null;
}
switch(variable) {
case AreaShop.tagTeleportBlockX:
return tp.getBlockX();
case AreaShop.tagTeleportBlockY:
return tp.getBlockY();
case AreaShop.tagTeleportBlockZ:
return tp.getBlockZ();
case AreaShop.tagTeleportX:
return tp.getX();
case AreaShop.tagTeleportY:
return tp.getY();
case AreaShop.tagTeleportZ:
return tp.getZ();
case AreaShop.tagTeleportPitch:
return tp.getPitch();
case AreaShop.tagTeleportYaw:
return tp.getYaw();
case AreaShop.tagTeleportPitchRound:
return Math.round(tp.getPitch());
case AreaShop.tagTeleportYawRound:
return Math.round(tp.getYaw());
case AreaShop.tagTeleportWorld:
return tp.getWorld().getName();
default:
return null;
}
return switch (variable) {
case AreaShop.tagTeleportBlockX -> tp.getBlockX();
case AreaShop.tagTeleportBlockY -> tp.getBlockY();
case AreaShop.tagTeleportBlockZ -> tp.getBlockZ();
case AreaShop.tagTeleportX -> tp.getX();
case AreaShop.tagTeleportY -> tp.getY();
case AreaShop.tagTeleportZ -> tp.getZ();
case AreaShop.tagTeleportPitch -> tp.getPitch();
case AreaShop.tagTeleportYaw -> tp.getYaw();
case AreaShop.tagTeleportPitchRound -> Math.round(tp.getPitch());
case AreaShop.tagTeleportYawRound -> Math.round(tp.getYaw());
case AreaShop.tagTeleportWorld -> tp.getWorld().getName();
default -> null;
};
}
}
@@ -796,11 +786,9 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
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 false;
}
if(parent != null && !parent.exists() && !parent.mkdirs()) {
AreaShop.warn("Did not save region " + getName() + ", schematic directory could not be created: " + saveFile.getAbsolutePath());
return false;
}
boolean result = worldEditInterface.saveRegionBlocks(saveFile, this);
if(result) {
@@ -809,6 +797,38 @@ 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() && !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(Boolean.TRUE.equals(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 +851,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(Boolean.TRUE.equals(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.
*/
@@ -910,7 +959,6 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
if(found) {
return result;
}
if(this.getFileManager().getRegionSettings().isString(path)) {
return this.getFileManager().getRegionSettings().getString(path).equalsIgnoreCase("true");
}
@@ -1419,8 +1467,8 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
public boolean matchesLimitGroup(String group) {
List<String> worlds = plugin.getConfig().getStringList("limitGroups." + group + ".worlds");
List<String> groups = plugin.getConfig().getStringList("limitGroups." + group + ".groups");
if((worlds == null || worlds.isEmpty() || worlds.contains(getWorldName()))) {
if(groups == null || groups.isEmpty()) {
if(worlds.isEmpty() || worlds.contains(getWorldName())) {
if(groups.isEmpty()) {
return true;
} else {
boolean inGroups = false;
@@ -1452,14 +1500,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
if(save != null && !save.isEmpty()) {
boolean async = worldEditInterface.supportsAsyncOperations();
if(save != null && !save.isBlank()) {
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()) {
if(restore != null && !restore.isBlank()) {
restore = Message.fromString(restore).replacements(this).getSingle();
restoreRegionBlocks(restore);
if (async) {
restoreRegionBlocksAsync(restore);
} else {
restoreRegionBlocks(restore);
}
}
}
@@ -672,10 +672,10 @@ public class RentRegion extends GeneralRegion {
}
// Broadcast and check event
UnrentingRegionEvent event = new UnrentingRegionEvent(this);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(executor, "general-cancelled", event.getReason());
UnrentingRegionEvent unrentingRegionEvent = new UnrentingRegionEvent(this);
Bukkit.getPluginManager().callEvent(unrentingRegionEvent);
if(unrentingRegionEvent.isCancelled()) {
message(executor, "general-cancelled", unrentingRegionEvent.getReason());
return false;
}
@@ -729,13 +729,17 @@ public class RentRegion extends GeneralRegion {
// Remove friends, the owner and renteduntil values
getFriendsFeature().clearFriends();
UUID oldRenter = getRenter();
setRenter(null);
setRentedUntil(null);
setTimesExtended(-1);
removeLastActiveTime();
// Notify about updates
this.notifyAndUpdate(new UnrentedRegionEvent(this, oldRenter, Math.max(0, moneyBack)));
Bukkit.getPluginManager().callEvent(new UnrentedRegionEvent(this, oldRenter, Math.max(0, moneyBack)));
// Placed here so when event is passed, the player renting can still be accessed
setRenter(null);
// Update world (has to be after setting renter to null)
this.update();
return true;
}
@@ -0,0 +1,97 @@
package me.wiefferink.areashop.tools;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Sign;
import org.bukkit.block.data.type.WallSign;
/**
* Sign Utilities class
*/
public final class SignUtils {
private SignUtils() {
}
/**
* Get the {@link BlockFace} of a sign block
* If the passed {@link Block} is not an instance of either
* a {@link Sign} or {@link WallSign}, this method will return <code>null</code>
*
* @param block The sign
* @return Returns the {@link BlockFace} of the sign or <code>null</code>
*/
public static BlockFace getSignFacing(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if (blockData instanceof WallSign wallSign) {
return wallSign.getFacing();
} else if (blockData instanceof org.bukkit.block.data.type.Sign sign) {
return sign.getRotation();
}
return null;
}
/**
* Set the {@link BlockFace} in which the sign will face
* If the passed {@link Block} is not an instance of either
* a {@link Sign} or {@link WallSign}, this method will return <code>null</code>.
*
* @param block The sign block
* @param facing The new {@link BlockFace} the sign should face
* @return Returns <code>true</code> if the sign was successfully placed, <code>false</code> otherwise
*/
public static boolean setSignFacing(Block block, BlockFace facing) {
if (block == null || facing == null) {
return false;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if (blockData instanceof WallSign wallSign) {
wallSign.setFacing(facing);
} else if (blockData instanceof org.bukkit.block.data.type.Sign sign) {
sign.setRotation(facing);
} else {
return false;
}
block.setBlockData(blockData);
return true;
}
/**
* Get the {@link Block} which a given sign is attached to.
* This method will return <code>null</code> if the passed {@link Block}
* is not an instance of either a {@link Sign} or {@link WallSign}.
*
* @param block The sign {@link Block}
* @return Returns the block which the sign is attached to or null
*/
public static Block getSignAttachedTo(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if (blockData instanceof WallSign wallSign) {
return block.getRelative(wallSign.getFacing().getOppositeFace());
} else if (blockData instanceof Sign) {
return block.getRelative(BlockFace.DOWN);
}
return null;
}
}
+4
View File
@@ -121,6 +121,10 @@ debug: false
version: ${project.version}
# Maximum number of blocks to save to or restore from a .schemetic file.
maximumBlocks: 1000000
# Whether to forcefully clear "hanging" entities (painting, itemframes, etc.) on region restore
# Only enable this option if hanging entities at the destination aren't removed on restore normally
# If set to true, there may be a performance impact when performing region restores.
forceClearEntities: false
# Maximum number of locations the teleport function should check to find a safe spot.
maximumTries: 50000
+3 -3
View File
@@ -619,7 +619,7 @@ greeting-resale: "%region% can be bought for %resellprice% from %player%."
update-playerNotify:
- "[darkgreen]Update from AreaShop V%0% to AreaShop V%1% available, get the latest version at "
- "[bold]Spigot[/bold]"
- " hover: %lang:action|Go to the Spigot AreaShop page|%"
- " link: https://www.spigotmc.org/resources/areashop.2991/"
- "[bold]Github[/bold]"
- " hover: %lang:action|Go to the AreaShop Github Releases|%"
- " link: https://github.com/md5sha256/releases"
- " (and leave a review)."
+1 -1
View File
@@ -5,7 +5,7 @@ description: "Selling and renting WorldGuard regions to your players, highly con
depend: [Vault, WorldGuard, WorldEdit]
softdepend: [Multiverse-Core, FastAsyncWorldEdit]
author: NLThijs48
website: https://github.com/md5s256/AreaShop
website: https://github.com/md5sha256/AreaShop
commands:
AreaShop:
description: 'For all commands use /as help.'
@@ -1,7 +1,7 @@
plugins.apply("io.papermc.paperweight.userdev")
dependencies {
paperDevBundle("1.18.1-R0.1-SNAPSHOT")
paperDevBundle("1.18.2-R0.1-SNAPSHOT")
compileOnly(projects.areashopInterface)
compileOnly(projects.areashopNms)
}
@@ -1,4 +1,4 @@
package me.wiefferink.areashop.adapters.platform.v1_18_R1;
package me.wiefferink.areashop.adapters.platform.v1_18_R2;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import net.minecraft.core.BlockPos;
@@ -7,10 +7,10 @@ import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_18_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_18_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock;
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
import java.util.Objects;
@@ -1,4 +1,4 @@
package me.wiefferink.areashop.adapters.platform.v1_18_R1;
package me.wiefferink.areashop.adapters.platform.v1_18_R2;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.NMS;
@@ -0,0 +1,21 @@
plugins.apply("io.papermc.paperweight.userdev")
dependencies {
paperDevBundle("1.19.2-R0.1-SNAPSHOT")
compileOnly(projects.areashopInterface)
compileOnly(projects.areashopNms)
}
description = "AreaShop NMS Helper 1-19"
tasks {
assemble {
dependsOn("reobfJar")
}
named("reobfJar", io.papermc.paperweight.tasks.RemapJar::class) {
outputJar.set(file("build/libs/${project.name}-${project.version}.jar"))
}
}
@@ -0,0 +1,46 @@
package me.wiefferink.areashop.adapters.platform.v1_19_R1;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
import java.util.Objects;
public class BlockBehaviourImpl implements BlockBehaviourHelper {
@Override
public boolean canPlace(Location location, BlockData blockData) {
Objects.requireNonNull(location.getWorld(), "Null World!");
final BlockPos blockPosition = new BlockPos(location.getX(), location.getY(), location.getZ());
final CraftWorld craftWorld = (CraftWorld) location.getWorld();
final ServerLevel world = craftWorld.getHandle();
final CraftBlockData craftBlockData = (CraftBlockData) blockData;
final BlockState ibd = craftBlockData.getState();
return ibd.canSurvive(world, blockPosition);
}
@Override
public boolean isBlockValid(Block block) {
final CraftBlock craftBlock = (CraftBlock) block;
final CraftWorld craftWorld = (CraftWorld) craftBlock.getWorld();
final ServerLevel world = craftWorld.getHandle();
final BlockState ibd = craftBlock.getNMS();
return ibd.canSurvive(world, craftBlock.getPosition());
}
@Override
public boolean isBlockStateValid(org.bukkit.block.BlockState blockState) {
final CraftBlockState craftBlockState = (CraftBlockState) blockState;
final BlockState ibd = craftBlockState.getHandle();
return ibd.canSurvive(craftBlockState.getBlock().getCraftWorld().getHandle(), craftBlockState.getPosition());
}
}
@@ -0,0 +1,15 @@
package me.wiefferink.areashop.adapters.platform.v1_19_R1;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.NMS;
public class NMSImpl implements NMS {
private final BlockBehaviourImpl blockBehaviourHelper = new BlockBehaviourImpl();
@Override
public BlockBehaviourHelper blockBehaviourHelper() {
return this.blockBehaviourHelper;
}
}
@@ -1,9 +1,14 @@
dependencies {
compileOnly(libs.spigot)
compileOnly(projects.areashopInterface)
compileOnly(libs.fastasyncworldeditCore)
compileOnly(libs.fastasyncworldeditBukkit)
compileOnly(libs.fastasyncworldeditCore) {
exclude("net.kyori", "adventure-text-minimessage")
}
compileOnly(libs.fastasyncworldeditBukkit) {
exclude("net.kyori", "adventure-text-minimessage")
}
compileOnly(libs.worldguardCore)
compileOnly(libs.worldguardBukkit)
}
description = "AreaShop FastAsyncWorldEdit"
@@ -1,297 +1,336 @@
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.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.WorldEditException;
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.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Mask2D;
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.function.EntityFunction;
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.function.visitor.EntityVisitor;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.io.Closer;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionType;
import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldEditSelection;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Hanging;
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.io.InputStream;
import java.io.OutputStream;
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
public class FastAsyncWorldEditHandler extends WorldEditInterface {
public FastAsyncWorldEditHandler(AreaShopInterface pluginInterface) {
super(pluginInterface);
}
public FastAsyncWorldEditHandler(AreaShopInterface pluginInterface) {
super(pluginInterface);
}
private static class RegionBoundMask implements Mask {
@Override
public boolean supportsAsyncOperations() {
return true;
}
private final BoundingBox boundingBox;
@Override
public CompletableFuture<Boolean> restoreRegionBlocksAsync(File rawFile, GeneralRegionInterface regionInterface) {
File targetFile = null;
for (ClipboardFormat formatOption : ClipboardFormats.getAll()) {
for (String extension : formatOption.getFileExtensions()) {
File fileOption = new File(rawFile.getAbsolutePath() + "." + extension);
if (fileOption.exists()) {
targetFile = fileOption;
break;
}
}
}
if (targetFile == null || !targetFile.exists() || !targetFile.isFile()) {
pluginInterface.getLogger().info(() -> "Not restoring region. Schematic not found: " + rawFile);
return CompletableFuture.completedFuture(false);
}
File finalFile = targetFile;
ClipboardFormat format = ClipboardFormats.findByFile(targetFile);
if (format == null) {
pluginInterface.getLogger().warning(() -> "Could not find a clipboard format for file: " + finalFile.getAbsolutePath());
return CompletableFuture.completedFuture(false);
}
BlockVector3 min = regionInterface.getRegion().getMinimumPoint();
final World world = BukkitAdapter.adapt(regionInterface.getWorld());
if (world == null) {
pluginInterface.getLogger().warning(() -> "Did not restore region " + regionInterface.getName() + ", world not found: " + regionInterface.getWorldName());
return CompletableFuture.completedFuture(false);
public RegionBoundMask(final ProtectedRegion region) {
final BlockVector3 min = region.getMinimumPoint(), max = region.getMaximumPoint();
this.boundingBox = new BoundingBox(min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ());
}
}
ProtectedRegion wgRegion = regionInterface.getRegion();
long volume = wgRegion.volume();
Region region = new CuboidRegion(wgRegion.getMinimumPoint(), wgRegion.getMaximumPoint());
int maxBlocks = pluginInterface.getConfig().getInt("maximumBlocks", Integer.MAX_VALUE);
if (volume > maxBlocks) {
pluginInterface.getLogger().warning((() -> "Region is bigger than the max allowed block change size! Volume: " + volume + " Limit: " + maxBlocks));
return CompletableFuture.completedFuture(false);
}
pluginInterface.debugI(() -> String.format("Attempting to restore using format: %s", format.getName()));
// Bug in which schematic pasting doesn't clear tile entities properly
// We manually remove tile entities in the destination before we paste the schematic
pluginInterface.debugI(() -> "Clearing entities for region: " + regionInterface.getName());
if (pluginInterface.getConfig().getBoolean("forceClearEntities", false) && failedClearEntities(world, region, regionInterface)) {
pluginInterface.getLogger().warning(() -> "Failed to clear tile entities for region: " + regionInterface.getName() + ". Will attempt to past anyway");
}
BlockVector3 dimensions = regionInterface.computeDimensions();
CompletableFuture<Boolean> future = new CompletableFuture<>();
Bukkit.getScheduler().runTaskAsynchronously(pluginInterface.pluginInstance(), () -> {
Clipboard clipboard;
try (InputStream is = new FileInputStream(finalFile);
ClipboardReader reader = format.getReader(is)) {
clipboard = reader.read();
if (!clipboard.getDimensions().equals(dimensions)) {
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());
future.complete(false);
return;
}
} catch (IOException ex) {
pluginInterface.getLogger().warning("An error occurred while restoring schematic of " + regionInterface.getName() + ", enable debug to see the complete stacktrace");
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
future.complete(false);
return;
} catch (Exception ex) {
pluginInterface.getLogger().warning(() -> "crashed during restore of " + regionInterface.getName());
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
future.complete(false);
return;
}
final EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit().newEditSessionBuilder()
.world(world)
.build();
final Operation operation = new ClipboardHolder(clipboard).createPaste(editSession)
.to(min)
.copyEntities(false) // Don't copy entities as FAWE has bug which doesn't synchronize entity access
.build();
future.complete(true);
try (editSession; clipboard) {
Operations.complete(operation);
future.complete(true);
} catch (WorldEditException ex) {
pluginInterface.getLogger().warning(() -> "An error occurred while restoring schematic of " + regionInterface.getName() + ", enable debug to see the complete stacktrace");
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
future.complete(false);
}
});
return future;
public RegionBoundMask(final BoundingBox boundingBox) {
this.boundingBox = boundingBox.clone();
}
}
@Override
public boolean test(BlockVector3 vector) {
return boundingBox.contains(vector.getX(), vector.getY(), vector.getZ());
}
@Override
public CompletableFuture<Boolean> saveRegionBlocksAsync(File file, GeneralRegionInterface regionInterface) {
final ClipboardFormat format = BuiltInClipboardFormat.FAST;
final File targetFile = new File(file.getAbsolutePath() + "." + format.getPrimaryFileExtension());
ProtectedRegion wgRegion = regionInterface.getRegion();
Region region = new CuboidRegion(wgRegion.getMinimumPoint(), wgRegion.getMaximumPoint());
final World world = BukkitAdapter.adapt(regionInterface.getWorld());
if (world == null) {
pluginInterface.getLogger().warning(() -> "Did not save region " + regionInterface.getName() + ", world not found: " + regionInterface.getWorldName());
return CompletableFuture.completedFuture(false);
}
int maxBlocks = pluginInterface.getConfig().getInt("maximumBlocks", Integer.MAX_VALUE);
long volume = region.getVolume();
if (volume > maxBlocks) {
pluginInterface.getLogger().warning((() -> "Region is bigger than the max allowed block change size! Volume: " + volume + " Limit: " + maxBlocks));
return CompletableFuture.completedFuture(false);
}
pluginInterface.debugI(() -> String.format("Trying to save region %s to file %s with format %s", regionInterface.getName(), file.getName(), format.getName()));
CompletableFuture<Boolean> future = new CompletableFuture<>();
Bukkit.getScheduler().runTaskAsynchronously(pluginInterface.pluginInstance(), () -> {
try (OutputStream os = new FileOutputStream(targetFile);
ClipboardWriter writer = format.getWriter(os);
Clipboard clipboard = new BlockArrayClipboard(region)) {
try (EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit().newEditSessionBuilder()
.world(world)
.build()) {
final ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
// Don't copy entities as FAWE has bug which doesn't synchronize entity access
copy.setCopyingEntities(false);
Operations.complete(copy);
}
writer.write(clipboard);
future.complete(true);
return;
} catch (IOException | WorldEditException ex) {
pluginInterface.getLogger().warning(() -> "An error occurred while saving schematic of " + regionInterface.getName() + ", enable debug to see the complete stacktrace");
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
} catch (Exception ex) {
pluginInterface.getLogger().warning(() -> "crashed during save of " + regionInterface.getName());
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
}
future.complete(false);
});
return future;
}
@Override
public Mask2D toMask2D() {
return null;
}
@Override
public boolean restoreRegionBlocks(File rawFile, GeneralRegionInterface regionInterface) {
File targetFile = null;
for (ClipboardFormat formatOption : ClipboardFormats.getAll()) {
for (String extension : formatOption.getFileExtensions()) {
File fileOption = new File(rawFile.getAbsolutePath() + "." + extension);
if (fileOption.exists()) {
targetFile = fileOption;
break;
}
}
}
if (targetFile == null || !targetFile.exists() || !targetFile.isFile()) {
pluginInterface.getLogger().info(() -> "Not restoring region. Schematic not found: " + rawFile);
return false;
}
File finalFile = targetFile;
ClipboardFormat format = ClipboardFormats.findByFile(targetFile);
if (format == null) {
pluginInterface.getLogger().warning(() -> "Could not find a clipboard format for file: " + finalFile.getAbsolutePath());
return false;
}
BlockVector3 min = regionInterface.getRegion().getMinimumPoint();
final World world = BukkitAdapter.adapt(regionInterface.getWorld());
if (world == null) {
pluginInterface.getLogger().warning(() -> "Did not restore region " + regionInterface.getName() + ", world not found: " + regionInterface.getWorldName());
return false;
@Override
public Mask copy() {
return new RegionBoundMask(boundingBox);
}
}
}
long volume = regionInterface.getRegion().volume();
int maxBlocks = pluginInterface.getConfig().getInt("maximumBlocks", Integer.MAX_VALUE);
if (volume > maxBlocks) {
pluginInterface.getLogger().warning((() -> "Region is bigger than the max allowed block change size! Volume: " + volume + " Limit: " + maxBlocks));
return false;
}
pluginInterface.debugI(String.format("Attempting to restore using format: %s", format.getName()));
// Bug in which schematic pasting doesn't clear tile entities properly
// We manually remove tile entities in the destination before we paste the schematic
pluginInterface.debugI(() -> "Clearing entities for region: " + regionInterface.getName());
ProtectedRegion wgRegion = regionInterface.getRegion();
Region region = new CuboidRegion(wgRegion.getMinimumPoint(), wgRegion.getMaximumPoint());
if (pluginInterface.getConfig().getBoolean("forceClearEntities", false) && failedClearEntities(world, region, regionInterface)) {
pluginInterface.getLogger().warning(() -> "Failed to clear tile entities for region: " + regionInterface.getName() + ". Will attempt to past anyway");
}
BlockVector3 dimensions = regionInterface.computeDimensions();
try (InputStream is = new FileInputStream(finalFile);
ClipboardReader reader = format.getReader(is)) {
Clipboard clipboard = reader.read();
if (!clipboard.getDimensions().equals(dimensions)) {
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());
return false;
}
final Operation operation = new ClipboardHolder(clipboard).createPaste(world)
.to(min)
.copyEntities(false)
.build();
Operations.complete(operation);
return true;
} catch (IOException | WorldEditException ex) {
pluginInterface.getLogger().warning(() -> "An error occurred while restoring schematic of " + regionInterface.getName() + ", enable debug to see the complete stacktrace");
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
} catch (Exception ex) {
pluginInterface.getLogger().warning(() -> "crashed during restore of " + regionInterface.getName());
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
}
return false;
}
@Beta
public CompletableFuture<Boolean> restoreRegionBlocksAsync(File rawFile, GeneralRegionInterface regionInterface) {
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;
}
}
if (file == null) {
pluginInterface.getLogger().info("Did not restore region " + regionInterface.getName()
+ ", schematic file does not exist: " + rawFile.getAbsolutePath());
return CompletableFuture.completedFuture(false);
}
pluginInterface.debugI("Trying to restore region", regionInterface.getName(), " from file",
file.getAbsolutePath(), "with format", format.getName());
@Override
public boolean saveRegionBlocks(File file, GeneralRegionInterface regionInterface) {
final ClipboardFormat format = BuiltInClipboardFormat.FAST;
final File targetFile = new File(file.getAbsolutePath() + "." + format.getPrimaryFileExtension());
ProtectedRegion wgRegion = regionInterface.getRegion();
Region region = new CuboidRegion(wgRegion.getMinimumPoint(), wgRegion.getMaximumPoint());
final World world = BukkitAdapter.adapt(regionInterface.getWorld());
if (world == null) {
pluginInterface.getLogger().warning("Did not save region " + regionInterface.getName() + ", world not found: " + regionInterface.getWorldName());
return false;
}
int maxBlocks = pluginInterface.getConfig().getInt("maximumBlocks", Integer.MAX_VALUE);
long volume = region.getVolume();
if (volume > maxBlocks) {
pluginInterface.getLogger().warning((() -> "Region is bigger than the max allowed block change size! Volume: " + volume + " Limit: " + maxBlocks));
return false;
}
pluginInterface.debugI(() -> String.format("Trying to save region %s to file %s with format %s", regionInterface.getName(), file.getName(), format.getName()));
try (OutputStream os = new FileOutputStream(targetFile);
ClipboardWriter writer = format.getWriter(os);
Clipboard clipboard = new BlockArrayClipboard(region)) {
try (EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit().newEditSessionBuilder()
.world(world)
.build()) {
final ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
copy.setCopyingEntities(true);
Operations.complete(copy);
}
writer.write(clipboard);
return true;
} catch (IOException | WorldEditException ex) {
pluginInterface.getLogger().warning(() -> "An error occurred while saving schematic of " + regionInterface.getName() + ", enable debug to see the complete stacktrace");
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
} catch (Exception ex) {
pluginInterface.getLogger().warning("crashed during save of " + regionInterface.getName());
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
}
return false;
}
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 CompletableFuture.completedFuture(false);
}
final CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
final FaweLimit limit = new FaweLimit();
limit.MAX_CHANGES = pluginInterface.getConfig().getInt("maximumBlocks");
EditSession editSession = WorldEdit.getInstance().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(),
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());
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);
@Override
public WorldEditSelection getPlayerSelection(Player player) {
try {
Region region = pluginInterface.getWorldEdit().getSession(player)
.getSelection(BukkitAdapter.adapt(player.getWorld()));
return new WorldEditSelection(player.getWorld(),
BukkitAdapter.adapt(player.getWorld(), region.getMinimumPoint()),
BukkitAdapter.adapt(player.getWorld(), region.getMaximumPoint()));
} catch (IncompleteRegionException e) {
return null;
}
}
Clipboard clipboard = reader.read();
if (clipboard.getDimensions().getY() != regionHeight
|| clipboard.getDimensions().getX() != regionWidth
|| clipboard.getDimensions().getZ() != regionDepth) {
pluginInterface.getLogger().warning(
"Size of the region " + regionName
+ " is not the same as the schematic to restore!");
pluginInterface.debugI(
"schematic|region, x:" + clipboard.getDimensions().getX() + "|"
+ regionWidth + ", y:" + clipboard.getDimensions().getY()
+ "|" + regionHeight + ", z:" + clipboard.getDimensions()
.getZ() + "|" + regionDepth);
}
clipboard.setOrigin(clipboard.getMinimumPoint());
ClipboardHolder clipboardHolder = new ClipboardHolder(clipboard);
session.setBlockChangeLimit((int) limit.MAX_CHANGES);
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 (regionType != RegionType.CUBOID) {
copy.setSourceMask(mask);
}
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"));
CompletableFuture.completedFuture(false);
} catch (IOException e) {
pluginInterface.getLogger().warning(
"An error occured while restoring schematic of " + regionInterface.getName()
+ ", enable debug to see the complete stacktrace");
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
CompletableFuture.completedFuture(false);
} catch (Exception e) {
pluginInterface.getLogger()
.warning("crashed during restore of " + regionInterface.getName());
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
CompletableFuture.completedFuture(false);
}
editSession.flushQueue();
CompletableFuture.completedFuture(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;
// 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 CompletableFuture.completedFuture(false);
}
final FaweLimit limit = new FaweLimit();
limit.MAX_CHANGES = pluginInterface.getConfig().getInt("maximumBlocks");
EditSession editSession = WorldEdit.getInstance().newEditSessionBuilder()
.world(world)
.relightMode(RelightMode.OPTIMAL)
.limit(limit)
.build();
final ProtectedRegion region = regionInterface.getRegion();
final BlockVector3 min = region.getMinimumPoint(), max = region.getMaximumPoint();
final String regionName = regionInterface.getName();
final World finalWorld = world;
final CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
final File finalFile = file;
FaweAPI.getTaskManager().async(() -> {
// Create a clipboard
CuboidRegion selection =
new CuboidRegion(finalWorld, min, max);
Clipboard clipboard = new MemoryOptimizedClipboard(selection);
clipboard.setOrigin(min);
ForwardExtentCopy copy = new ForwardExtentCopy(editSession,
selection.clone(), clipboard,
min);
try {
Operations.completeLegacy(copy);
} catch (MaxChangedBlocksException e) {
pluginInterface.getLogger().warning(
"Exceeded the block limit while saving schematic of " + regionName
+ ", limit in exception: " + e.getBlockLimit() + ", limit passed by AreaShop: "
+ pluginInterface.getConfig().getInt("maximumBlocks"));
completableFuture.complete(false);
}
try (Closer closer = Closer.create()) {
FileOutputStream fos = closer.register(new FileOutputStream(finalFile));
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 occured while saving schematic of " + regionName
+ ", enable debug to see the complete stacktrace");
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
completableFuture.complete(false);
} catch (Exception e) {
pluginInterface.getLogger()
.warning("Crashed during save of " + regionName);
pluginInterface.debugI(ExceptionUtils.getStackTrace(e));
completableFuture.complete(false);
}
completableFuture.complete(true);
});
return completableFuture;
}
@Override
public boolean saveRegionBlocks(File file, GeneralRegionInterface regionInterface) {
return saveRegionBlocksAsync(file, regionInterface).join();
}
@Override
public WorldEditSelection getPlayerSelection(Player player) {
try {
Region region = pluginInterface.getWorldEdit().getSession(player)
.getSelection(BukkitAdapter.adapt(player.getWorld()));
return new WorldEditSelection(player.getWorld(),
BukkitAdapter.adapt(player.getWorld(), region.getMinimumPoint()),
BukkitAdapter.adapt(player.getWorld(), region.getMaximumPoint()));
} catch (IncompleteRegionException e) {
return null;
}
}
private boolean failedClearEntities(World world, Region region, GeneralRegionInterface regionInterface) {
try (EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit().newEditSessionBuilder()
.world(world)
.build()) {
EntityFunction function = entity -> {
EntityType entityType = entity.getType();
if (entityType != null && (entityType.equals(EntityTypes.ITEM_FRAME)
|| entityType.equals(EntityTypes.PAINTING)
|| entityType.equals(EntityTypes.LEASH_KNOT)) && !entity.remove()) {
pluginInterface.debugI("Could not remove entity: " + entityType.getName());
}
return false;
};
EntityVisitor visitor = new EntityVisitor(editSession.getEntities(region).iterator(), function);
Operations.complete(visitor);
return false;
} catch (WorldEditException ex) {
pluginInterface.getLogger().warning("crashed during save of " + regionInterface.getName());
pluginInterface.debugI(ExceptionUtils.getStackTrace(ex));
return true;
}
}
}
@@ -2,27 +2,29 @@ package me.wiefferink.areashop.adapters.plugins;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
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;
import com.sk89q.worldedit.function.EntityFunction;
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.function.visitor.EntityVisitor;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.io.Closer;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionType;
import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
@@ -30,12 +32,13 @@ import me.wiefferink.areashop.interfaces.WorldEditSelection;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.entity.Player;
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.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
public class WorldEditHandler extends WorldEditInterface {
@@ -59,146 +62,139 @@ public class WorldEditHandler extends WorldEditInterface {
@Override
public boolean restoreRegionBlocks(File rawFile, GeneralRegionInterface regionInterface) {
File file = null;
ClipboardFormat format = null;
File targetFile = null;
for (ClipboardFormat formatOption : ClipboardFormats.getAll()) {
for (String extension : formatOption.getFileExtensions()) {
File fileOption = new File(rawFile.getAbsolutePath() + "." + extension);
if (fileOption.exists()) {
file = fileOption;
format = formatOption;
targetFile = fileOption;
break;
}
}
}
if(file == null) {
pluginInterface.getLogger().info("Did not restore region " + regionInterface.getName() + ", schematic file does not exist: " + rawFile.getAbsolutePath());
if (targetFile == null || !targetFile.exists() || !targetFile.isFile()) {
pluginInterface.getLogger().info(() -> "Not restoring region. Schematic not found: " + rawFile);
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());
File finalFile = targetFile;
ClipboardFormat format = ClipboardFormats.findByFile(targetFile);
if (format == null) {
pluginInterface.getLogger().warning(() -> "Could not find a clipboard format for file: " + finalFile.getAbsolutePath());
return false;
}
EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit().getEditSessionFactory().getEditSession(world, pluginInterface.getConfig().getInt("maximumBlocks"));
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()) {
FileInputStream fis = closer.register(new FileInputStream(file));
BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
ClipboardReader reader = format.getReader(bis);
//WorldData worldData = world.getWorldData();
LocalSession session = new LocalSession(pluginInterface.getWorldEdit().getLocalConfiguration());
BlockVector3 min = regionInterface.getRegion().getMinimumPoint();
final World world = BukkitAdapter.adapt(regionInterface.getWorld());
if (world == null) {
pluginInterface.getLogger().warning(() -> "Did not restore region " + regionInterface.getName() + ", world not found: " + regionInterface.getWorldName());
return false;
}
long volume = regionInterface.getRegion().volume();
int maxBlocks = pluginInterface.getConfig().getInt("maximumBlocks", Integer.MAX_VALUE);
if (volume > maxBlocks) {
pluginInterface.getLogger().warning((() -> "Region is bigger than the max allowed block change size! Volume: " + volume + " Limit: " + maxBlocks));
return false;
}
pluginInterface.debugI(() -> String.format("Attempting to restore using format: %s", format.getName()));
// Bug in which schematic pasting doesn't clear tile entities properly
// We manually remove tile entities in the destination before we paste the schematic
pluginInterface.debugI(() -> "Clearing entities for region: " + regionInterface.getName());
ProtectedRegion wgRegion = regionInterface.getRegion();
Region region = new CuboidRegion(wgRegion.getMinimumPoint(), wgRegion.getMaximumPoint());
if (pluginInterface.getConfig().getBoolean("forceClearEntities", false) && failedClearEntities(world, region, regionInterface)) {
pluginInterface.getLogger().warning(() -> "Failed to clear tile entities for region: " + regionInterface.getName() + ". Will attempt to past anyway");
}
BlockVector3 dimensions = regionInterface.computeDimensions();
try (InputStream is = new FileInputStream(finalFile);
ClipboardReader reader = format.getReader(is)) {
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!");
if (!clipboard.getDimensions().equals(dimensions)) {
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());
return false;
}
clipboard.setOrigin(clipboard.getMinimumPoint());
ClipboardHolder clipboardHolder = new ClipboardHolder(clipboard);
session.setBlockChangeLimit(pluginInterface.getConfig().getInt("maximumBlocks"));
session.setClipboard(clipboardHolder);
// Build operation
BlockTransformExtent extent = new BlockTransformExtent(clipboardHolder.getClipboard(), clipboardHolder.getTransform());
ForwardExtentCopy copy = new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(), editSession, origin);
copy.setCopyingEntities(false);
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 Mask() {
@Override
public boolean test(BlockVector3 vector) {
return region.contains(vector);
}
@Override
public Mask2D toMask2D() {
return null;
}
});
}
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(IOException e) {
pluginInterface.getLogger().warning("An error occured 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;
final Operation operation = new ClipboardHolder(clipboard).createPaste(world)
.to(min)
.copyEntities(true)
.build();
Operations.complete(operation);
return true;
} catch (IOException | WorldEditException ex) {
pluginInterface.getLogger().warning(() ->"An error occurred while restoring schematic of " + regionInterface.getName() + ", enable debug to see the complete stacktrace");
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
} catch (Exception ex) {
pluginInterface.getLogger().warning(() -> "crashed during restore of " + regionInterface.getName());
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
}
editSession.flushSession();
return true;
return false;
}
@Override
public boolean saveRegionBlocks(File file, GeneralRegionInterface regionInterface) {
ClipboardFormat format = ClipboardFormats.findByAlias("sponge");
if(format == null) {
// Sponge format does not exist, try to select another one
for(ClipboardFormat otherFormat : ClipboardFormats.getAll()) {
format = otherFormat;
}
if(format == null) {
pluginInterface.getLogger().warning("Cannot find a format to save a schematic in, no available formats!");
return false;
}
}
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());
final ClipboardFormat format = BuiltInClipboardFormat.SPONGE_SCHEMATIC;
final File targetFile = new File(file.getAbsolutePath() + "." + format.getPrimaryFileExtension());
ProtectedRegion wgRegion = regionInterface.getRegion();
Region region = new CuboidRegion(wgRegion.getMinimumPoint(), wgRegion.getMaximumPoint());
final World 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().getEditSessionFactory().getEditSession(world, pluginInterface.getConfig().getInt("maximumBlocks"));
// 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());
int maxBlocks = pluginInterface.getConfig().getInt("maximumBlocks", Integer.MAX_VALUE);
long volume = region.getVolume();
if (volume > maxBlocks) {
pluginInterface.getLogger().warning((() -> "Region is bigger than the max allowed block change size! Volume: " + volume + " Limit: " + maxBlocks));
return false;
}
pluginInterface.debugI(() -> String.format("Trying to save region %s to file %s with format %s", regionInterface.getName(), file.getName(), format.getName()));
Clipboard clipboard = new BlockArrayClipboard(region);
final ForwardExtentCopy copy = new ForwardExtentCopy(world, region, clipboard, region.getMinimumPoint());
copy.setCopyingEntities(true);
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;
Operations.complete(copy);
} catch (WorldEditException ex) {
pluginInterface.getLogger().warning(() -> "An error occurred while saving schematic of " + regionInterface.getName() + ", enable debug to see the complete stacktrace");
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
}
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));
try (OutputStream os = new FileOutputStream(targetFile);
ClipboardWriter writer = format.getWriter(os)) {
writer.write(clipboard);
} catch(IOException e) {
pluginInterface.getLogger().warning("An error occured 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;
} catch (IOException ex) {
pluginInterface.getLogger().warning(() -> "An error occurred while saving schematic of " + regionInterface.getName() + ", enable debug to see the complete stacktrace");
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
} catch (Exception ex) {
pluginInterface.getLogger().warning(() -> "crashed during save of " + regionInterface.getName());
pluginInterface.debugI(() -> ExceptionUtils.getStackTrace(ex));
}
return false;
}
private boolean failedClearEntities(World world, Region region, GeneralRegionInterface regionInterface) {
try (EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit().newEditSessionBuilder()
.world(world)
.build()) {
EntityFunction function = entity -> {
BaseEntity state = entity.getState();
if (state == null) {
return false;
}
EntityType entityType = state.getType();
if ((entityType.equals(EntityTypes.ITEM_FRAME)
|| entityType.equals(EntityTypes.PAINTING)
|| entityType.equals(EntityTypes.LEASH_KNOT))
&& !entity.remove()) {
pluginInterface.debugI("Could not remove entity: " + entityType.getName());
}
return false;
};
EntityVisitor visitor = new EntityVisitor(editSession.getEntities(region).iterator(), function);
Operations.complete(visitor);
return false;
} catch (WorldEditException ex) {
pluginInterface.getLogger().warning("crashed during save of " + regionInterface.getName());
pluginInterface.debugI(ExceptionUtils.getStackTrace(ex));
return true;
}
return true;
}
}
-6
View File
@@ -1,6 +0,0 @@
dependencies {
compileOnly(libs.spigot)
compileOnly(projects.areashopInterface)
}
description = "AreaShop Bukkit 1.13 and higher"
@@ -1,82 +0,0 @@
package me.wiefferink.areashop.handlers;
import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.BukkitInterface;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Sign;
import org.bukkit.block.data.type.WallSign;
/**
* Sign handler for 1.13+
* @deprecated Obsolete as we don't support pre-1.13 versions anyway
*/
@Deprecated(forRemoval = true)
public class BukkitHandler1_13 extends BukkitInterface {
public BukkitHandler1_13(AreaShopInterface pluginInterface) {
super(pluginInterface);
}
// Uses BlockData, which does not yet exist in 1.12-
@Override
public BlockFace getSignFacing(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if(blockData instanceof WallSign) {
return ((WallSign) blockData).getFacing();
} else if(blockData instanceof Sign) {
return ((Sign) blockData).getRotation();
}
return null;
}
// Uses BlockData, WallSign and Sign which don't exist in 1.12-
@Override
public boolean setSignFacing(Block block, BlockFace facing) {
if (block == null || facing == null) {
return false;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if(blockData instanceof WallSign) {
((WallSign) blockData).setFacing(facing);
} else if(blockData instanceof Sign) {
((Sign) blockData).setRotation(facing);
} else {
return false;
}
block.setBlockData(blockData);
return true;
}
@Override
public Block getSignAttachedTo(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if(blockData instanceof WallSign) {
return block.getRelative(((WallSign) blockData).getFacing().getOppositeFace());
} else if(blockData instanceof Sign) {
return block.getRelative(BlockFace.DOWN);
}
return null;
}
}
@@ -3,12 +3,16 @@ package me.wiefferink.areashop.interfaces;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import java.util.function.Supplier;
import java.util.logging.Logger;
public interface AreaShopInterface {
void debugI(Object... message);
void debugI(Supplier<String> message);
YamlConfiguration getConfig();
WorldGuardPlugin getWorldGuard();
@@ -16,4 +20,6 @@ public interface AreaShopInterface {
WorldEditPlugin getWorldEdit();
Logger getLogger();
Plugin pluginInstance();
}
@@ -2,34 +2,75 @@ package me.wiefferink.areashop.interfaces;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Sign;
import org.bukkit.block.data.type.WallSign;
public abstract class BukkitInterface {
protected final AreaShopInterface pluginInterface;
/**
* Sign handler for 1.13+
* @deprecated Obsolete as we don't support pre-1.13 versions anyway
*/
@Deprecated(forRemoval = true)
public class BukkitInterface {
public BukkitInterface(AreaShopInterface pluginInterface) {
this.pluginInterface = pluginInterface;
}
/**
* Get the direciton a sign is facing.
* @param block Sign block to get the facing from
* @return direction the sign is facing
*/
public abstract BlockFace getSignFacing(Block block);
// Uses BlockData, which does not yet exist in 1.12-
public BlockFace getSignFacing(Block block) {
if (block == null) {
return null;
}
/**
* Set the direction a sign is facing.
* @param block Sign block to update
* @param facing direction to let the sign face
* @return true when successful, otherwise false
*/
public abstract boolean setSignFacing(Block block, BlockFace facing);
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
/**
* Get the block a sign is attached to.
* @param block Sign block
* @return Block the sign is attached to, or null when not a sign or not attached
*/
public abstract Block getSignAttachedTo(Block block);
if(blockData instanceof WallSign) {
return ((WallSign) blockData).getFacing();
} else if(blockData instanceof Sign) {
return ((Sign) blockData).getRotation();
}
return null;
}
// Uses BlockData, WallSign and Sign which don't exist in 1.12-
public boolean setSignFacing(Block block, BlockFace facing) {
if (block == null || facing == null) {
return false;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if(blockData instanceof WallSign) {
((WallSign) blockData).setFacing(facing);
} else if(blockData instanceof Sign) {
((Sign) blockData).setRotation(facing);
} else {
return false;
}
block.setBlockData(blockData);
return true;
}
public Block getSignAttachedTo(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if(blockData instanceof WallSign) {
return block.getRelative(((WallSign) blockData).getFacing().getOppositeFace());
} else if(blockData instanceof Sign) {
return block.getRelative(BlockFace.DOWN);
}
return null;
}
}
@@ -1,5 +1,6 @@
package me.wiefferink.areashop.interfaces;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.World;
@@ -17,4 +18,8 @@ public interface GeneralRegionInterface {
int getDepth();
int getHeight();
default BlockVector3 computeDimensions() {
return BlockVector3.at(getWidth(), getHeight(), getDepth());
}
}
@@ -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
+3 -3
View File
@@ -2,13 +2,13 @@ plugins {
java
`java-library`
`maven-publish`
id("io.papermc.paperweight.userdev") version "1.3.3" apply false
id("io.papermc.paperweight.userdev") version "1.3.6" apply false
idea
eclipse
}
group = "me.wiefferink"
version = "2.7.4"
version = "2.7.8"
subprojects {
@@ -81,4 +81,4 @@ subprojects {
}
}
}
}
}
+5 -5
View File
@@ -4,12 +4,12 @@ minecraft = "1.17.1-R0.1-SNAPSHOT"
findbugs = "3.0.2"
# Minecraft Plugins
worldedit = "7.2.8"
worldguard = "7.0.6"
fawe = "2.0.0"
worldedit = "7.2.12"
worldguard = "7.0.7"
fawe = "2.4.5"
# Gradle plugins
paperweight = "1.3.3"
paperweight = "1.3.7"
[libraries]
# Platform
@@ -26,4 +26,4 @@ fastasyncworldeditCore = { group = "com.fastasyncworldedit", name = "FastAsyncWo
[plugins]
# Gradle plugins
paperweightUserdev = { id = "io.papermc.paperweight.userdev", version.ref = "paperweight" }
paperweightUserdev = { id = "io.papermc.paperweight.userdev", version.ref = "paperweight" }
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+3 -4
View File
@@ -11,20 +11,20 @@ pluginManagement {
buildCache {
local {
directory = File(rootDir, "build-cache")
removeUnusedEntriesAfterDays = 7
removeUnusedEntriesAfterDays = 30
}
}
rootProject.name = "areashop-parent"
// Interfaces
include(":areashop-bukkit-1_13")
include(":areashop-interface")
include(":areashop-nms")
// Adapters
include(":adapters:platform:bukkit-1-17")
include(":adapters:platform:bukkit-1-18")
include(":adapters:platform:bukkit-1-19")
include(":adapters:plugins:worldedit")
include(":adapters:plugins:worldguard")
include(":adapters:plugins:fastasyncworldedit")
@@ -34,5 +34,4 @@ include(":areashop")
project(":areashop").projectDir = file("AreaShop")
enableFeaturePreview("VERSION_CATALOGS")
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")