Compare commits

..
23 Commits
Author SHA1 Message Date
md5sha256 832d8967a3 Remove the use of script engine 2021-08-23 03:51:56 +08:00
md5sha256 c369d23f74 Don't throw an exception if there is an invalid version 2021-08-17 13:09:12 +02:00
Andrew Wong b50d57739f Bump version 2021-08-16 13:30:46 +02:00
Andrew Wong ce9438eaeb Fix compile errors in the fawe 1.17 module 2021-08-16 13:26:50 +02:00
Andrew Wong 47cc259c40 Fix startup errors, bump fawe version 2021-08-16 13:23:26 +02:00
Andrew Wong e6ae122b86 Fix missing version 2021-06-29 22:38:59 +02:00
Andrew Wong 2562075b90 Add fawe module for 1.17 2021-06-24 17:25:14 +02:00
Andrew Wong 9fc5d8a314 Add support for 1.17 2021-06-23 14:24:15 +02:00
Andrew Wong e96b179c48 Performance improvements and bug fixes to sign 2021-06-23 14:20:05 +02:00
Andrew Wong 49bed6f655 Use the updated method of making an edit session 2021-06-23 13:45:15 +02:00
Andrew Wong ffc5b03a75 Fix merge conflicts 2021-06-23 13:43:23 +02:00
Andrew Wong 69fea8ab7e Fix merge conflicts 2021-06-23 12:38:45 +02:00
Andrew Wong 29fc2c4205 Move maven things to gradle 2021-06-23 12:23:06 +02:00
Andrew Wong 2dd6d4ec4a Don't use deprecated methods in WorldGuard and WorldEdit handlers 2021-06-23 11:45:00 +02:00
Andrew Wong 789073f6d6 Bump worldedit and worldguard versions 2021-06-23 11:41:04 +02:00
Andrew Wong d211bf2f43 Move compat to 1.16 2021-06-23 11:16:02 +02:00
Andrew Wong a6659cb14d Remove bstats 2021-06-23 10:58:20 +02:00
Andrew Wong 880218cca0 Bump gradle to 7.1 and java version to 16 2021-06-23 10:47:05 +02:00
Andrew Wong 3426381273 Gradleise 2021-06-04 14:45:00 +02:00
Andrew Wong 80a73fecea Load invalid region files when trying to delete them 2021-06-04 13:24:33 +02:00
Andrew Wong 590d5a4988 Fix names and pom 2021-06-03 12:24:35 +02:00
Andrew Wong dda4a090fb Fix merge conflicts 2021-06-03 12:24:17 +02:00
Andrew Wong 3a415513dd Fix tab completions 2021-01-18 19:02:34 +01:00
56 changed files with 3826 additions and 3034 deletions

No files matched your search

+33 -27
View File
@@ -1,32 +1,38 @@
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name : "build"
name: Java CI with Maven
on : [ "pull_request", "push" ]
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs :
build :
strategy :
matrix :
java : [ 16 ]
# java: ["1.8", "11"]
os : [ "ubuntu-18.04" ]
runs-on : "${{ matrix.os }}"
steps :
- name : "Checkout Repository"
uses : "actions/checkout@v2.3.4"
jobs:
build:
- name : "Checkout submodules"
uses : "srt32/git-actions@v0.0.3"
with :
args : "git submodule update --init --recursive"
runs-on: ubuntu-latest
- name : "Restore Gradle cache"
uses : "actions/cache@v2"
with :
path : "~/.gradle/caches"
key : "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}"
restore-keys : |
${{ runner.os }}-gradle-
- name : "Setup JDK ${{ matrix.java }}"
uses : "actions/setup-java@v1.4.3"
with :
java-version : "${{ matrix.java }}"
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Cache local Maven repository
uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Build with Maven
run: mvn -B package --file pom.xml
- name : "Grant execute permission for gradlew"
run : "chmod +x gradlew"
- name : "Build with Gradle"
run : "./gradlew clean build"
+22 -3
View File
@@ -1,4 +1,4 @@
# Maven stuff
### Maven ###
target
.project
@@ -14,12 +14,31 @@ local.properties
.settings/
.loadpath
# Locally stored "Eclipse launch configurations"
### Locally stored "Eclipse launch configurations" ###
*.launch
# IntelliJ IDEA
### IntelliJ IDEA ###
*.iml
.idea
dependency-reduced-pom.xml
desktop.ini
### Gradle ###
.gradle
build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Cache of project
.gradletasknamecache
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties
### Gradle Patch ###
**/build/
+60
View File
@@ -0,0 +1,60 @@
import org.apache.tools.ant.filters.ReplaceTokens
plugins {
id 'java-library'
id 'com.github.johnrengelman.shadow' version '7.0.0'
}
description = 'AreaShop'
version = '2.6.5'
dependencies {
// Spigot api
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
// Libs
implementation 'com.github.NLthijs48:InteractiveMessenger:e7749258ca'
implementation 'co.aikar:taskchain-bukkit:3.7.2'
implementation 'io.papermc:paperlib:1.0.6'
// Hooks
implementation project(':areashop-interface')
implementation project(':areashop-worldguard-7')
implementation project(':areashop-worldedit-7')
implementation project(':areashop-fawe-1-16')
implementation project(':areashop-fawe-1-17')
implementation project(':areashop-nms-1-16-5')
implementation project(':areashop-nms-1-17')
// Runtime plugins
compileOnly 'com.sk89q.worldedit:worldedit-bukkit:7.2.5'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.5'
compileOnly 'com.github.MilkBowl:VaultAPI:1.7'
}
processResources {
from (sourceSets.main.resources) {
filter ReplaceTokens, tokens: [version: project.version]
duplicatesStrategy(DuplicatesStrategy.INCLUDE)
}
}
assemble {
dependsOn(shadowJar)
}
jar {
archiveBaseName.set('AreaShop')
classifier('original')
}
shadowJar {
archiveBaseName.set('AreaShop')
String relocationBase = 'me.wiefferink.areashop.shaded'
classifier('')
relocate('co.aikar.taskchain', "${relocationBase}.taskchain")
relocate('me.wiefferink.interactivemessenger', "${relocationBase}.interactivemessenger")
relocate('org.bstats', "${relocationBase}.bstats")
relocate('io.papermc', "${relocationBase}.papermc")
}
-285
View File
@@ -1,285 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>areashop</artifactId>
<packaging>jar</packaging>
<name>AreaShop</name>
<version>2.6.2</version> <!-- Main plugin version -->
<repositories>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>aikar</id>
<url>https://repo.aikar.co/content/groups/aikar/</url>
</repository>
</repositories>
<dependencies>
<!-- Bukkit, AreaShop aims to support 1.13.2+ -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- InteractiveMessenger library -->
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>interactivemessenger</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<!-- TaskChain library -->
<dependency>
<groupId>co.aikar</groupId>
<artifactId>taskchain-bukkit</artifactId>
<version>3.7.2</version>
</dependency>
<dependency>
<groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId>
<version>1.0.4</version>
</dependency>
<!-- WorldEdit/WorldGuard -->
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.3</version>
<scope>provided</scope>
</dependency>
<!-- Interfaces that specific WorldGuard and WorldEdit versions are built against -->
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-interface</artifactId>
<version>latest</version>
<scope>compile</scope>
</dependency>
<!-- WorldGuard implementations -->
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-worldguard-7</artifactId>
<version>latest</version>
<scope>compile</scope>
</dependency>
<!-- WorldEdit implementations -->
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-worldedit-7</artifactId>
<version>latest</version>
<scope>compile</scope>
</dependency>
<!-- FAWE compat -->
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-fawe-1-15</artifactId>
<version>latest</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- Vault -->
<dependency>
<groupId>net.milkbowl.vault</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
</dependency>
<!-- bStats -->
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>1.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<profiles>
<!-- Copy the jar file to a test server, activate by using -DcopyResult="/path/to/test/server" -->
<profile>
<id>test-locally</id>
<activation>
<property>
<name>copyResult</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<copy file="./target/${project.build.finalName}.jar"
tofile="${copyResult}\${project.build.finalName}.jar"/>
</target>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- Package the source files in a jar, activate by using -Dsources -->
<profile>
<id>package-sources</id>
<activation>
<property>
<name>sources</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- Produce javadoc files, activate by using -Djavadoc -->
<profile>
<id>generate-javadoc</id>
<activation>
<property>
<name>javadoc</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>package</phase>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<excludePackageNames>me.wiefferink.areashop.lib</excludePackageNames>
<destDir>${javadoc}</destDir>
<links>
<link>https://hub.spigotmc.org/javadocs/bukkit/</link>
<link>http://docs.sk89q.com/worldedit/apidocs/</link>
<link>http://docs.sk89q.com/worldguard/apidocs/</link>
</links>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<directory>target</directory>
<finalName>AreaShop</finalName>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources</directory>
<includes>
<include>plugin.yml</include>
<include>config.yml</include>
<include>hiddenConfig.yml</include>
<include>default.yml</include>
<include>README.md</include>
<include>lang/*.yml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<!-- Relocate TaskChain -->
<relocation>
<pattern>co.aikar.taskchain</pattern>
<shadedPattern>me.wiefferink.areashop.shaded.taskchain</shadedPattern>
</relocation>
<!-- Relocate messaging framework -->
<relocation>
<pattern>me.wiefferink.interactivemessenger</pattern>
<shadedPattern>me.wiefferink.areashop.shaded.interactivemessenger</shadedPattern>
</relocation>
<!-- Relocate bstats -->
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>me.wiefferink.areashop.shaded.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>io.papermc</pattern>
<shadedPattern>me.wiefferink.areashop.shaded.paperlib</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -5,11 +5,11 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.managers.RegionManager;
import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.NMS;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.listeners.PlayerLoginLogoutListener;
import me.wiefferink.areashop.managers.*;
import me.wiefferink.areashop.tools.Analytics;
import me.wiefferink.areashop.tools.GithubUpdateCheck;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.interactivemessenger.processing.Message;
@@ -111,7 +111,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
public static final String tagTeleportWorld = "tpworld";
// REGEX Matcher for Versions which follow a x.x.x format.
private static final Pattern VERSION_MATCHER_3 = Pattern.compile("([0-9]+)\\.([0-9]+)\\.([0-9]+)");
private static final Pattern VERSION_MATCHER_2 = Pattern.compile("([0-9]+)\\.([0-9]+)\\.([0-9]+)");
private static final Pattern VERSION_MATCHER_2 = Pattern.compile("([0-9]+)\\.([0-9]+)");
// Statically available instance
private static AreaShop instance = null;
// General variables
@@ -129,6 +129,8 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
private List<String> chatprefix = null;
private boolean ready = false;
private GithubUpdateCheck githubUpdateCheck = null;
private NMS nms;
private SignErrorLogger signErrorLogger;
public static AreaShop getInstance() {
return AreaShop.instance;
@@ -264,6 +266,14 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
this.chatprefix = chatprefix;
}
public NMS getNMSHelper() {
return this.nms;
}
public SignErrorLogger getSignErrorLogger() {
return this.signErrorLogger;
}
/**
* Function to get WorldGuardInterface for version dependent things.
*
@@ -563,6 +573,22 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
HandlerList.unregisterAll(this);
}
private void setupNMS() throws IllegalStateException {
final String packageName = Bukkit.getServer().getClass().getPackage().getName();
final String[] split = packageName.split("\\.");
final String nmsRevision = split[3];
try {
Class<?> rawClazz = Class.forName("me.wiefferink.areashop.nms." + nmsRevision + ".NMSImpl");
if (!NMS.class.isAssignableFrom(rawClazz)) {
throw new IllegalStateException("Invalid NMS Impl: " + rawClazz.getCanonicalName() + " does not implement the NMS!");
}
Class<? extends NMS> casted = rawClazz.asSubclass(NMS.class);
this.nms = casted.getConstructor().newInstance();
} catch (ReflectiveOperationException ex) {
throw new IllegalStateException("Failed to instantiate the NMS Helper!", ex);
}
}
/**
* Called on start or reload of the server.
*/
@@ -579,6 +605,9 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
error = true;
}
// Setup the NMS helper
setupNMS();
// Load all data from files and check versions
fileManager = new FileManager();
managers.add(fileManager);
@@ -607,11 +636,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
signLinkerManager = new SignLinkerManager();
managers.add(signLinkerManager);
// Enable Metrics if config allows it
if (getConfig().getBoolean("sendStats")) {
Analytics.start();
}
// Register dynamic permission (things declared in config)
registerDynamicPermissions();
@@ -622,9 +646,10 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
Matcher matcher0 = VERSION_MATCHER_3.matcher(latestVersion);
boolean dual0 = false;
if (!matcher0.find()) {
matcher0 = VERSION_MATCHER_3.matcher(latestVersion);
matcher0 = VERSION_MATCHER_2.matcher(latestVersion);
if (!matcher0.find()) {
throw new IllegalArgumentException("Invalid Versions Detected!");
// FIXME log invalid version
return false;
}
dual0 = true;
}
@@ -633,7 +658,8 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
if (!matcher1.find()) {
matcher1 = VERSION_MATCHER_2.matcher(currentVersion);
if (!matcher1.find()) {
throw new IllegalArgumentException("Invalid Versions Detected!");
// FIXME log invalid version
return false;
}
dual1 = true;
}
@@ -681,6 +707,32 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
return true;
}
final String packageName = "me.wiefferink.areashop.handlers.";
final Plugin fawe = getServer().getPluginManager().getPlugin("FastAsyncWorldEdit");
if (fawe != null && fawe.isEnabled()) {
final String version = fawe.getDescription().getVersion();
if (version.startsWith("1.16")) {
try {
this.worldEditInterface = (WorldEditInterface) Class.forName(packageName + "fawe.v1_16.FastAsyncWorldEditHandler")
.getDeclaredConstructor(AreaShopInterface.class)
.newInstance(this);
} catch (ReflectiveOperationException ex) {
getLogger().log(Level.SEVERE, "Failed to hook into FAWE!");
ex.printStackTrace();
}
} else if (version.startsWith("1.17")) {
try {
this.worldEditInterface = (WorldEditInterface) Class.forName(packageName + "fawe.v1_17.FastAsyncWorldEditHandler")
.getDeclaredConstructor(AreaShopInterface.class)
.newInstance(this);
} catch (ReflectiveOperationException ex) {
getLogger().log(Level.SEVERE, "Failed to hook into FAWE!");
ex.printStackTrace();
}
}
if (this.worldEditInterface == null) {
info("FAWE Version: " + version + " detected, no compatible handler found. Using the WorldEdit handler instead.");
}
}
if (this.worldEditInterface == null) {
final String version = worldEdit.getDescription().getVersion();
Matcher matcher = VERSION_MATCHER_3.matcher(version);
@@ -702,23 +754,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
return false;
}
}
this.worldEdit = (WorldEditPlugin) worldEdit;
final Plugin fawe = getServer().getPluginManager().getPlugin("FastAsyncWorldEdit");
if (fawe != null && fawe.isEnabled()) {
final String version = fawe.getDescription().getVersion();
if (version.startsWith("1.15") || version.startsWith("1.16")) {
try {
this.worldEditInterface = (WorldEditInterface) Class.forName(packageName + "fawe.v1_15.FastAsyncWorldEditHandler")
.getDeclaredConstructor(AreaShopInterface.class).newInstance(this);
} catch (ReflectiveOperationException ex) {
getLogger().log(Level.SEVERE, "Failed to hook into FAWE!");
ex.printStackTrace();
}
}
if (this.worldEditInterface == null) {
info("FAWE Version: " + version + " detected, no compatible handler found. Using the WorldEdit handler instead.");
}
}
final String wgVersion = worldGuard.getDescription().getVersion();
Matcher matcher = VERSION_MATCHER_3.matcher(wgVersion);
if (!matcher.find()) {
@@ -796,7 +831,3 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
}
}
@@ -6,10 +6,7 @@ import org.apache.commons.lang.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* Abstract class for generalising command classes.
@@ -46,7 +43,7 @@ public abstract class CommandAreaShop {
* @return A collection with all the possibilities for argument to complete
*/
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
return new ArrayList<>();
return Collections.emptyList();
}
/**
@@ -89,7 +86,7 @@ public abstract class CommandAreaShop {
return false;
}
private class CommandTime {
private static class CommandTime {
public final String command;
public final long time;
@@ -12,6 +12,7 @@ import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
public class DelCommand extends CommandAreaShop {
@@ -92,37 +93,41 @@ public class DelCommand extends CommandAreaShop {
plugin.message(sender, "del-cancelled", Utils.combinedMessage(regionsCancelled, "region"));
}
} else {
GeneralRegion region = plugin.getFileManager().getRegion(args[1]);
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[1]);
return;
}
boolean isLandlord = sender instanceof Player && region.isLandlord(((Player)sender).getUniqueId());
if(region instanceof RentRegion) {
// Remove the rent if the player has permission
if(sender.hasPermission("areashop.destroyrent") || (isLandlord && sender.hasPermission("areashop.destroyrent.landlord"))) {
DeletingRegionEvent event = plugin.getFileManager().deleteRegion(region, true);
if (event.isCancelled()) {
plugin.message(sender, "general-cancelled", event.getReason());
} else {
plugin.message(sender, "destroy-successRent", region);
}
} else {
plugin.message(sender, "destroy-noPermissionRent", region);
}
} else if(region instanceof BuyRegion) {
// Remove the buy if the player has permission
if(sender.hasPermission("areashop.destroybuy") || (isLandlord && sender.hasPermission("areashop.destroybuy.landlord"))) {
DeletingRegionEvent event = plugin.getFileManager().deleteRegion(region, true);
if (event.isCancelled()) {
plugin.message(sender, "general-cancelled", event.getReason());
} else {
plugin.message(sender, "destroy-successBuy", region);
}
} else {
plugin.message(sender, "destroy-noPermissionBuy", region);
}
}
CompletableFuture<GeneralRegion> future = plugin.getFileManager().getRegionUnsafe(args[1]);
Utils.newChain()
.future(future)
.syncLast(region -> {
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[1]);
return;
}
boolean isLandlord = sender instanceof Player && region.isLandlord(((Player)sender).getUniqueId());
if(region instanceof RentRegion) {
// Remove the rent if the player has permission
if(sender.hasPermission("areashop.destroyrent") || (isLandlord && sender.hasPermission("areashop.destroyrent.landlord"))) {
DeletingRegionEvent event = plugin.getFileManager().deleteRegion(region, true);
if (event.isCancelled()) {
plugin.message(sender, "general-cancelled", event.getReason());
} else {
plugin.message(sender, "destroy-successRent", region);
}
} else {
plugin.message(sender, "destroy-noPermissionRent", region);
}
} else if(region instanceof BuyRegion) {
// Remove the buy if the player has permission
if(sender.hasPermission("areashop.destroybuy") || (isLandlord && sender.hasPermission("areashop.destroybuy.landlord"))) {
DeletingRegionEvent event = plugin.getFileManager().deleteRegion(region, true);
if (event.isCancelled()) {
plugin.message(sender, "general-cancelled", event.getReason());
} else {
plugin.message(sender, "destroy-successBuy", region);
}
} else {
plugin.message(sender, "destroy-noPermissionBuy", region);
}
}
}).execute();
}
}
@@ -11,6 +11,7 @@ import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.areashop.tools.Value;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@@ -41,9 +42,9 @@ public class TeleportFeature extends RegionFeature {
*/
private static boolean isSafe(Location location) {
Block feet = location.getBlock();
BlockState head = PaperLib.getBlockState(feet.getRelative(BlockFace.UP), true).getState();
BlockState below = PaperLib.getBlockState(feet.getRelative(BlockFace.DOWN), true).getState();
BlockState above = PaperLib.getBlockState(head.getBlock().getRelative(BlockFace.UP), true).getState();
BlockState head = PaperLib.getBlockState(feet.getRelative(BlockFace.UP), false).getState();
BlockState below = PaperLib.getBlockState(feet.getRelative(BlockFace.DOWN), false).getState();
BlockState above = PaperLib.getBlockState(head.getBlock().getRelative(BlockFace.UP), false).getState();
// Check the block at the feet and head of the player
if ((feet.getType().isSolid() && !canSpawnIn(feet.getType())) || feet.isLiquid()) {
@@ -66,7 +67,7 @@ public class TeleportFeature extends RegionFeature {
continue;
}
around.add(PaperLib.getBlockState(below.getBlock().getRelative(x, y, z), true).getState().getType());
around.add(PaperLib.getBlockState(below.getBlock().getRelative(x, y, z), false).getState().getType());
}
}
}
@@ -101,17 +102,14 @@ public class TeleportFeature extends RegionFeature {
* @return true when it is safe to spawn on top of, otherwise false
*/
private static boolean cannotSpawnOn(Material material) {
String name = material.name();
return name.equals("CACTUS")
|| name.contains("PISTON")
|| name.contains("SIGN")
|| name.contains("DOOR")
|| name.contains("PLATE")
|| name.contains("REDSTONE_LAMP")
|| name.contains("FENCE")
|| name.contains("GLASS_PANE") || name.contains("THIN_GLASS")
|| name.equals("DRAGON_EGG")
|| name.contains("MAGMA");
return switch (material) {
case CACTUS, DRAGON_EGG, MAGMA_BLOCK -> false;
default -> !Tag.SIGNS.isTagged(material)
&& !Tag.FENCES.isTagged(material)
&& !Tag.FENCE_GATES.isTagged(material)
&& !Tag.WALL_SIGNS.isTagged(material)
&& !Tag.DOORS.isTagged(material);
};
}
/**
@@ -121,11 +119,10 @@ public class TeleportFeature extends RegionFeature {
* @return true when it is safe to spawn next to, otherwise false
*/
private static boolean cannotSpawnBeside(Material material) {
String name = material.name();
return name.contains("LAVA")
|| name.contains("CACTUS")
|| name.equals("FIRE")
|| name.contains("MAGMA");
return switch (material) {
case LAVA, CACTUS, FIRE, MAGMA_BLOCK -> false;
default -> true;
};
}
/**
@@ -288,7 +285,9 @@ public class TeleportFeature extends RegionFeature {
if (safeLocation.getBlockY() > 256 || safeLocation.getBlockY() < 0) {
continue;
}
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -306,7 +305,9 @@ public class TeleportFeature extends RegionFeature {
if (safeLocation.getBlockY() > 256 || safeLocation.getBlockY() < 0) {
continue;
}
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -324,7 +325,9 @@ public class TeleportFeature extends RegionFeature {
if (safeLocation.getBlockY() > 256 || safeLocation.getBlockY() < 0) {
continue;
}
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -342,7 +345,9 @@ public class TeleportFeature extends RegionFeature {
if (safeLocation.getBlockY() > 256 || safeLocation.getBlockY() < 0) {
continue;
}
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -360,7 +365,9 @@ public class TeleportFeature extends RegionFeature {
}
if (!done && !topDone) {
safeLocation = startLocation.clone().add(0, radius, 0);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -371,7 +378,9 @@ public class TeleportFeature extends RegionFeature {
// North
for (int x = -r + 1; x <= r && !done; x++) {
safeLocation = startLocation.clone().add(x, radius, -r);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -381,7 +390,9 @@ public class TeleportFeature extends RegionFeature {
// East
for (int z = -r + 1; z <= r && !done; z++) {
safeLocation = startLocation.clone().add(r, radius, z);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -391,7 +402,9 @@ public class TeleportFeature extends RegionFeature {
// South side
for (int x = r - 1; x >= -r && !done; x--) {
safeLocation = startLocation.clone().add(x, radius, r);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -401,7 +414,9 @@ public class TeleportFeature extends RegionFeature {
// West side
for (int z = r - 1; z >= -r && !done; z--) {
safeLocation = startLocation.clone().add(-r, radius, z);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -419,7 +434,9 @@ public class TeleportFeature extends RegionFeature {
}
if (!done && !bottomDone) {
safeLocation = startLocation.clone().add(0, -radius, 0);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -430,7 +447,9 @@ public class TeleportFeature extends RegionFeature {
// North
for (int x = -r + 1; x <= r && !done; x++) {
safeLocation = startLocation.clone().add(x, -radius, -r);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -440,7 +459,9 @@ public class TeleportFeature extends RegionFeature {
// East
for (int z = -r + 1; z <= r && !done; z++) {
safeLocation = startLocation.clone().add(r, -radius, z);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -450,7 +471,9 @@ public class TeleportFeature extends RegionFeature {
// South side
for (int x = r - 1; x >= -r && !done; x--) {
safeLocation = startLocation.clone().add(x, -radius, r);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -460,7 +483,9 @@ public class TeleportFeature extends RegionFeature {
// West side
for (int z = r - 1; z >= -r && !done; z--) {
safeLocation = startLocation.clone().add(-r, -radius, z);
if (worldguardRegion.contains(safeLocation.getBlockX(), safeLocation.getBlockY(), safeLocation.getBlockZ()) || !insideRegion) {
if (!insideRegion || worldguardRegion.contains(safeLocation.getBlockX(),
safeLocation.getBlockY(),
safeLocation.getBlockZ())) {
checked++;
done = isSafe(safeLocation) || checked > maxTries;
blocksInRegionCopy = true;
@@ -586,7 +611,7 @@ public class TeleportFeature extends RegionFeature {
AreaShop.warn("Could not parse general.teleportLocationY: '" + configSetting + "'");
}
}
startLocation = new Location(getRegion().getWorld(), middle.getX(), middle.getY(), middle.getZ(), player.getLocation().getYaw(), player.getLocation().getPitch());
startLocation = middle.toLocation(getRegion().getWorld(), player.getLocation().getYaw(), player.getLocation().getPitch());
}
// Set location in the center of the block
@@ -4,6 +4,8 @@ import com.google.common.base.Objects;
import io.papermc.lib.PaperLib;
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.managers.SignErrorLogger;
import me.wiefferink.areashop.interfaces.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.Utils;
@@ -11,6 +13,7 @@ import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
@@ -23,12 +26,51 @@ import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
/**
* Sign that is connected to a region to display information and interact with the region.
*/
public class RegionSign {
public static final BlockBehaviourHelper behaviourHelper = AreaShop.getInstance().getNMSHelper().behaviourHelper();
public static Level invalidSignLogLevel;
public static boolean removeInvalidSigns;
static {
YamlConfiguration configuration = AreaShop.getInstance().getConfig();
removeInvalidSigns = configuration.getBoolean("signs.removeInvalid");
final String rawLogLevel = configuration.getString("signs.invalidSignLogLevel", "WARNING");
try {
assert rawLogLevel != null;
invalidSignLogLevel = Level.parse(rawLogLevel);
} catch (IllegalArgumentException ex) {
AreaShop.warn("Invalid Logging Level: " + rawLogLevel);
invalidSignLogLevel = Level.WARNING;
}
}
private static boolean canLogSignError() {
return AreaShop.getInstance().getLogger().isLoggable(invalidSignLogLevel);
}
private static void logSignError(String... messages) {
if (invalidSignLogLevel == Level.OFF) {
return;
}
if (invalidSignLogLevel == Level.SEVERE) {
AreaShop.error((Object) messages);
} else if (invalidSignLogLevel == Level.WARNING) {
AreaShop.warn((Object) messages);
} else if (invalidSignLogLevel.intValue() >= Level.FINE.intValue()) {
AreaShop.debug((Object) messages);
} else {
AreaShop.info((Object) messages);
}
}
private final SignsFeature signsFeature;
private final String key;
@@ -109,7 +151,7 @@ public class RegionSign {
/**
* Get the material of the sign as saved in the config.
*
* @return Material of the sign, usually {@link Material#WALL_SIGN}, {@link Material#SIGN}, or one of the other wood types (different result for 1.13-), Material.AIR if none.
* @return Material of the sign, usually, a sign or {@link Material#AIR} if none.
*/
public Material getMaterial() {
String name = getRegion().getConfig().getString("general.signs." + key + ".signType");
@@ -156,30 +198,31 @@ public class RegionSign {
block.setType(Material.AIR);
return true;
}
final BlockStateSnapshotResult snapshotResult = PaperLib.getBlockState(block, true);
final BlockState blockState = snapshotResult.getState();
final BlockStateSnapshotResult snapshot = PaperLib.getBlockState(block, false);
final BlockState blockState = snapshot.getState();
final BlockData blockData = blockState.getBlockData();
final SignErrorLogger errorLogger = AreaShop.getInstance().getSignErrorLogger();
Material signType = getMaterial();
// Place the sign back (with proper rotation and type) after it has been hidden or (indirectly) destroyed
if (!Materials.isSign(block.getType())) {
Material signType = getMaterial();
if (signType.name().contains("SIGN")) {
final BlockData data = blockState.getBlockData();
// Don't do physics here, we first need to update the direction
blockState.setType(signType);
if (data instanceof WallSign) {
((WallSign) data).setFacing(getFacing());
} else if (data instanceof Sign) {
((org.bukkit.block.data.type.Sign) data).setRotation(getFacing());
}
blockState.setBlockData(data);
blockState.update(false, false);
// Check if the sign has popped
if (!Materials.isSign(block.getType())) {
AreaShop.warn("Setting sign", key, "of region", getRegion().getName(), "failed, could not set sign block back");
return false;
}
} else {
AreaShop.warn("Setting sign", key, "of region", getRegion().getName(), "failed, RegionSign material was: " + signType.name());
if (!Materials.isSign(blockState.getType())) {
// Don't do physics here, we first need to update the direction
blockState.setType(signType);
if (blockData instanceof WallSign) {
((WallSign) blockData).setFacing(getFacing());
} else if (blockData instanceof Sign) {
((org.bukkit.block.data.type.Sign) blockData).setRotation(getFacing());
}
blockState.setBlockData(blockData);
blockState.update(false, true);
// Check if the sign has popped
if (!Materials.isSign(block.getType())) {
final String message = String.format("Setting sign of $1%s of region $2%s failed, could not set sign block back", key, getRegion().getName());
errorLogger.submitWarning(message);
return false;
}
} else {
final String message = "Setting sign $1%s of region $2%s failed, RegionSign material was: $3%s";
errorLogger.submitWarning(String.format(message, key, getRegion().getName(), signType.name()));
}
// Save current rotation and type
@@ -214,7 +257,8 @@ public class RegionSign {
signLines[i] = Utils.applyColors(signLines[i]);
signState.setLine(i, signLines[i]);
}
return signState.update(false, false);
// BlockState#update *should* return true here.
return blockState.update(true, false);
}
/**
@@ -0,0 +1,121 @@
package me.wiefferink.areashop.features.signs;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.events.notify.UpdateRegionEvent;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SignCache implements Listener {
private final Map<String, RegionSign> allSigns = new HashMap<>();
private final Map<String, List<RegionSign>> signsByChunk = new HashMap<>();
public void registerListeners() {
Bukkit.getPluginManager().registerEvents(this, AreaShop.getInstance());
}
/**
* Convert a location to a string to use as map key.
*
* @param location The location to get the key for
* @return A string to use in a map for a location
*/
public static String locationToString(Location location) {
return location.getWorld().getName() + ";" + location.getBlockX() + ";" + location.getBlockY() + ";" + location.getBlockZ();
}
/**
* Convert a chunk to a string to use as map key.
*
* @param location The location to get the key for
* @return A string to use in a map for a chunk
*/
public static String chunkToString(Location location) {
return location.getWorld().getName() + ";" + (location.getBlockX() >> 4) + ";" + (location.getBlockZ() >> 4);
}
/**
* Convert a chunk to a string to use as map key.
* Use a Location argument to prevent chunk loading!
*
* @param chunk The location to get the key for
* @return A string to use in a map for a chunk
*/
public static String chunkToString(Chunk chunk) {
return chunk.getWorld().getName() + ";" + chunk.getX() + ";" + chunk.getZ();
}
/**
* Get a sign by a location.
*
* @param location The location to get the sign for
* @return The RegionSign that is at the location, or null if none
*/
public RegionSign getSignByLocation(Location location) {
return allSigns.get(locationToString(location));
}
/**
* Get the map with all signs.
*
* @return Map with all signs: locationString -&gt; RegionSign
*/
public Map<String, RegionSign> getAllSigns() {
return allSigns;
}
/**
* Get the map with signs by chunk.
*
* @return Map with signs by chunk: chunkString -&gt; List&lt;RegionSign&gt;
*/
public Map<String, List<RegionSign>> getSignsByChunk() {
return signsByChunk;
}
public void addSign(RegionSign regionSign) {
signsByChunk.computeIfAbsent(regionSign.getStringChunk(), (unused) -> new ArrayList<>()).add(regionSign);
}
public void removeSign(RegionSign regionSign) {
final List<RegionSign> signs = signsByChunk.get(regionSign.getStringChunk());
if (signs != null) {
signs.remove(regionSign);
}
allSigns.remove(regionSign.getStringLocation());
}
public void shutdown() {
HandlerList.unregisterAll(this);
signsByChunk.clear();
allSigns.clear();
}
@EventHandler
public void regionUpdate(UpdateRegionEvent event) {
event.getRegion().getSignsFeature().update();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onChunkLoad(ChunkLoadEvent event) {
List<RegionSign> chunkSigns = signsByChunk.get(chunkToString(event.getChunk()));
if (chunkSigns == null) {
return;
}
int batchSize = Math.max(chunkSigns.size() / 10, 10);
Utils.runAsBatches(chunkSigns, batchSize, RegionSign::update, false);
}
}
@@ -4,9 +4,10 @@ import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
import me.wiefferink.areashop.events.notify.UpdateRegionEvent;
import me.wiefferink.areashop.features.RegionFeature;
import me.wiefferink.areashop.interfaces.BlockBehaviourHelper;
import me.wiefferink.areashop.managers.FileManager;
import me.wiefferink.areashop.managers.SignErrorLogger;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
@@ -31,14 +32,22 @@ import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import java.util.*;
public class SignsFeature extends RegionFeature {
private static final Map<String, RegionSign> allSigns = Collections.synchronizedMap(new HashMap<>());
private static final Map<String, List<RegionSign>> signsByChunk = Collections.synchronizedMap(new HashMap<>());
public static final SignCache signCache = new SignCache();
private static final BlockBehaviourHelper behaviourHelper = AreaShop.getInstance().getNMSHelper().behaviourHelper();
static {
signCache.registerListeners();
}
public static void shutdownGlobalState() {
signCache.shutdown();
}
private Map<String, RegionSign> signs;
@@ -56,19 +65,19 @@ public class SignsFeature extends RegionFeature {
signs = new HashMap<>();
// Setup current signs
ConfigurationSection signSection = region.getConfig().getConfigurationSection("general.signs");
SignErrorLogger errorLogger = AreaShop.getInstance().getSignErrorLogger();
if (signSection != null) {
for (String signKey : signSection.getKeys(false)) {
RegionSign sign = new RegionSign(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");
final String message = "Sign with key $1%s of region $2%s does not have a proper location";
errorLogger.submitWarning(String.format(message, signKey, region.getName()));
continue;
}
signs.put(sign.getStringLocation(), sign);
signsByChunk.computeIfAbsent(sign.getStringChunk(), key -> new ArrayList<>())
.add(sign);
signCache.addSign(sign);
}
allSigns.putAll(signs);
}
}
@@ -110,7 +119,7 @@ public class SignsFeature extends RegionFeature {
* @return The RegionSign that is at the location, or null if none
*/
public static RegionSign getSignByLocation(Location location) {
return allSigns.get(locationToString(location));
return signCache.getSignByLocation(location);
}
/**
@@ -119,7 +128,7 @@ public class SignsFeature extends RegionFeature {
* @return Map with all signs: locationString -&gt; RegionSign
*/
public static Map<String, RegionSign> getAllSigns() {
return allSigns;
return signCache.getAllSigns();
}
/**
@@ -128,7 +137,7 @@ public class SignsFeature extends RegionFeature {
* @return Map with signs by chunk: chunkString -&gt; List&lt;RegionSign&gt;
*/
public static Map<String, List<RegionSign>> getSignsByChunk() {
return signsByChunk;
return signCache.getSignsByChunk();
}
@Override
@@ -136,24 +145,26 @@ public class SignsFeature extends RegionFeature {
// Deregister signs from the registry
if (signs != null) {
for (Map.Entry<String, RegionSign> entry : signs.entrySet()) {
allSigns.remove(entry.getKey());
signsByChunk.get(entry.getValue().getStringChunk()).remove(entry.getValue());
signCache.removeSign(entry.getValue());
}
}
}
@EventHandler(priority = EventPriority.HIGH)
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onSignBreak(BlockBreakEvent event) {
if (event.isCancelled()) {
Block block = event.getBlock();
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if (regionSign == null) {
return;
}
Block block = event.getBlock();
if (regionSign.getRegion().invalidated()) {
AreaShop.warn("SignsFeature: Sign feature for an invalidated region is still active!");
}
// Check if it is a sign
if (Materials.isSign(block.getType())) {
// Check if the rent sign is really the same as a saved rent
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if (regionSign == null) {
return;
if (regionSign.getRegion().invalidated()) {
AreaShop.warn("SignsFeature: Sign feature for an invalidated region object is still active!");
}
// Remove the sign of the rental region if the player has permission
if (event.getPlayer().hasPermission("areashop.delsign")) {
@@ -168,26 +179,7 @@ public class SignsFeature extends RegionFeature {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onIndirectSignBreak(BlockPhysicsEvent event) {
// Check if the block is a sign
if (!Materials.isSign(event.getBlock().getType())) {
return;
}
final Block block = event.getBlock();
final BlockData blockData = block.getBlockData();
final Block attachedBlock;
if (blockData instanceof WallSign) {
attachedBlock = block.getRelative(((WallSign) blockData).getFacing().getOppositeFace());
} else if (blockData instanceof Sign) {
attachedBlock = block.getRelative(BlockFace.DOWN);
} else {
attachedBlock = null;
}
// Check if still attached to a block
// TODO: signs cannot be placed on all blocks, improve this check to isSolid()?
if (attachedBlock == null || attachedBlock.getType() != Material.AIR) {
return;
}
// Check if the sign is really the same as a saved rent
RegionSign regionSign = SignsFeature.getSignByLocation(event.getBlock().getLocation());
@@ -195,6 +187,18 @@ public class SignsFeature extends RegionFeature {
return;
}
if (regionSign.getRegion().invalidated()) {
AreaShop.warn("SignsFeature: Sign feature for an invalidated region is still active!");
}
// Check if the block is a sign
if (!Materials.isSign(event.getBlock().getType())) {
return;
}
// If the block is in an invalid position then we remove the sign
if (!behaviourHelper.isBlockValid(block)) {
regionSign.remove();
}
// Remove the sign so that it does not fall on the floor as an item (next region update will place it back when possible)
AreaShop.debug("onIndirectSignBreak: Removed block of sign for", regionSign.getRegion().getName(), "at", regionSign.getStringLocation());
event.getBlock().setType(Material.AIR);
@@ -207,6 +211,15 @@ public class SignsFeature extends RegionFeature {
if (block == null) {
return;
}
// Check if this sign belongs to a region
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if (regionSign == null) {
return;
}
if (regionSign.getRegion().invalidated()) {
AreaShop.warn("SignsFeature: Sign feature for an invalidated region is still active!");
}
// Only listen to left and right clicks on blocks
if (!(event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK)) {
@@ -218,11 +231,6 @@ public class SignsFeature extends RegionFeature {
return;
}
// Check if this sign belongs to a region
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if (regionSign == null) {
return;
}
// Ignore players that are in sign link mode (which will handle the event itself)
Player player = event.getPlayer();
@@ -248,11 +256,17 @@ public class SignsFeature extends RegionFeature {
event.setCancelled(ran);
}
@EventHandler(priority = EventPriority.MONITOR)
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSignChange(SignChangeEvent event) {
if (event.isCancelled()) {
RegionSign regionSign = SignsFeature.getSignByLocation(event.getBlock().getLocation());
if (regionSign == null) {
return;
}
if (regionSign.getRegion().invalidated()) {
AreaShop.warn("SignsFeature: Sign feature for an invalidated region is still active!");
}
Player player = event.getPlayer();
if (!plugin.isReady()) {
plugin.message(player, "general-notReady");
@@ -532,21 +546,6 @@ public class SignsFeature extends RegionFeature {
}
}
@EventHandler
public void regionUpdate(UpdateRegionEvent event) {
event.getRegion().getSignsFeature().update();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onChunkLoad(ChunkLoadEvent event) {
List<RegionSign> chunkSigns = signsByChunk.get(chunkToString(event.getChunk()));
if (chunkSigns == null) {
return;
}
int batchSize = Math.max(chunkSigns.size() / 10, 10);
Utils.runAsBatches(chunkSigns, batchSize, RegionSign::update, false);
}
/**
* Update all signs connected to this region.
*
@@ -629,9 +628,7 @@ public class SignsFeature extends RegionFeature {
// Add to the map
RegionSign sign = new RegionSign(this, i + "");
signs.put(sign.getStringLocation(), sign);
allSigns.put(sign.getStringLocation(), sign);
signsByChunk.computeIfAbsent(sign.getStringChunk(), key -> new ArrayList<>())
.add(sign);
signCache.addSign(sign);
}
}
@@ -34,17 +34,11 @@ import me.wiefferink.areashop.commands.StackCommand;
import me.wiefferink.areashop.commands.StopresellCommand;
import me.wiefferink.areashop.commands.TeleportCommand;
import me.wiefferink.areashop.commands.UnrentCommand;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.command.*;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.*;
public class CommandManager extends Manager implements CommandExecutor, TabCompleter {
public class CommandManager extends Manager implements TabExecutor {
private final ArrayList<CommandAreaShop> commands;
/**
@@ -88,7 +82,6 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl
// Register commands in bukkit
plugin.getCommand("AreaShop").setExecutor(this);
plugin.getCommand("AreaShop").setTabCompleter(this);
}
/**
@@ -165,10 +158,10 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
List<String> result = new ArrayList<>();
if(!sender.hasPermission("areashop.tabcomplete")) {
return result;
return Collections.emptyList();
}
List<String> result = new ArrayList<>();
int toCompleteNumber = args.length;
String toCompletePrefix = args[args.length - 1].toLowerCase();
//AreaShop.debug("toCompleteNumber=" + toCompleteNumber + ", toCompletePrefix=" + toCompletePrefix + ", length=" + toCompletePrefix.length());
@@ -68,6 +68,8 @@ public class FeatureManager extends Manager {
for(RegionFeature feature : globalFeatures) {
feature.shutdown();
}
// FIXME make this system less hacky!
SignsFeature.shutdownGlobalState();
}
/**
@@ -154,6 +154,25 @@ public class FileManager extends Manager {
return allRegions.get(name.toLowerCase());
}
public CompletableFuture<GeneralRegion> getRegionUnsafe(String name) {
final GeneralRegion cached = allRegions.get(name);
if (cached != null) {
return CompletableFuture.completedFuture(cached);
}
final File file = new File(regionsPath, name + ".yml");
if (!file.exists()) {
return CompletableFuture.completedFuture(null);
}
CompletableFuture<GeneralRegion> completableFuture = new CompletableFuture<>();
Utils.newChain()
.async(() -> {
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file);
completableFuture.complete(loadRegion(configuration));
})
.execute();
return completableFuture;
}
/**
* Get a rental region.
*
@@ -292,10 +311,16 @@ public class FileManager extends Manager {
// Forcefully remove regions from cache.
buyRegions.remove(name);
rentRegions.remove(name);
final GeneralRegion existing;
if (region instanceof BuyRegion) {
buyRegions.put(region.getName().toLowerCase(), (BuyRegion) region);
existing = buyRegions.put(region.getName().toLowerCase(), (BuyRegion) region);
} else if (region instanceof RentRegion) {
rentRegions.put(region.getName().toLowerCase(), (RentRegion) region);
existing = rentRegions.put(region.getName().toLowerCase(), (RentRegion) region);
} else {
existing = null;
}
if (existing != null) {
AreaShop.debug("FileManager: Region ", existing.getName(), " was overwritten.");
}
allRegions.put(region.getName().toLowerCase(), region);
Bukkit.getPluginManager().callEvent(new AddedRegionEvent(region));
@@ -865,6 +890,9 @@ public class FileManager extends Manager {
* Load all region files.
*/
public void loadRegionFiles() {
buyRegions.values().forEach(GeneralRegion::invalidate);
buyRegions.clear();
rentRegions.values().forEach(GeneralRegion::invalidate);
rentRegions.clear();
buyRegions.clear();
allRegions.clear();
@@ -880,6 +908,20 @@ public class FileManager extends Manager {
}
}
private GeneralRegion loadRegion(YamlConfiguration config) {
// Construct the correct type of region
String type = config.getString("general.type");
GeneralRegion region;
if (RegionType.RENT.getValue().equals(type)) {
region = new RentRegion(config);
} else if (RegionType.BUY.getValue().equals(type)) {
region = new BuyRegion(config);
} else {
return null;
}
return region;
}
private void loadRegionFilesNow() {
File file = new File(regionsPath);
File[] regionFiles = file.listFiles();
@@ -911,17 +953,11 @@ public class FileManager extends Manager {
}
// Construct the correct type of region
String type = regionConfig.getString("general.type");
GeneralRegion region;
if (RegionType.RENT.getValue().equals(type)) {
region = new RentRegion(regionConfig);
} else if (RegionType.BUY.getValue().equals(type)) {
region = new BuyRegion(regionConfig);
} else {
GeneralRegion region = loadRegion(regionConfig);
if (region == null) {
noRegionType.add(regionFile.getPath());
continue;
}
// Check consistency
boolean added = false;
if (region.getName() == null) {
@@ -0,0 +1,79 @@
package me.wiefferink.areashop.managers;
import me.wiefferink.areashop.AreaShop;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicBoolean;
public class SignErrorLogger {
public static final String PREFIX_WARN = "[Warning] [Sign Feature] ";
public static final DateFormat FORMAT = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
private final List<String> cache = new LinkedList<>();
private final AtomicBoolean needsSaving = new AtomicBoolean(false);
private final File file;
public SignErrorLogger(File file) {
this.file = Objects.requireNonNull(file);
}
public void clearCache() {
synchronized (this.cache) {
this.cache.clear();
}
}
public SignErrorLogger submitWarning(String message) {
final String actual = FORMAT.format(Date.from(Instant.now())) + PREFIX_WARN + message;
synchronized (this.cache) {
this.cache.add(actual);
}
return this;
}
public void queueSave() {
this.needsSaving.set(true);
}
public void saveIfDirty() {
if (this.needsSaving.get()) {
save();
}
}
public synchronized void save() {
AreaShop.debugTask("[Sign Feature] Dumping sign errors to disk...");
final String[] copy;
synchronized (this.cache) {
copy = cache.toArray(new String[0]);
}
final StringJoiner joiner = new StringJoiner(System.lineSeparator());
for (String s : copy) {
joiner.add(s);
}
try (OutputStream os = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(os, StandardCharsets.UTF_8)) {
writer.write(joiner.toString());
} catch (IOException ex) {
ex.printStackTrace();
AreaShop.error("Failed to update the sign error log!");
} finally {
AreaShop.debugTask("[Sign Feature] Error dump complete.");
}
}
}
@@ -366,7 +366,7 @@ public class BuyRegion extends GeneralRegion {
r = null;
OfflinePlayer oldOwnerPlayer = Bukkit.getOfflinePlayer(oldOwner);
String oldOwnerName = getPlayerName();
if(oldOwnerPlayer != null && oldOwnerPlayer.getName() != null) {
if(oldOwnerPlayer.hasPlayedBefore() && oldOwnerPlayer.getName() != null) {
r = plugin.getEconomy().depositPlayer(oldOwnerPlayer, getWorldName(), getResellPrice());
oldOwnerName = oldOwnerPlayer.getName();
} else if(oldOwnerName != null) {
File diff suppressed because it is too large. Load diff
@@ -1,143 +0,0 @@
package me.wiefferink.areashop.tools;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import org.bstats.Metrics;
import java.util.HashMap;
public class Analytics {
private Analytics() {
}
/**
* Start analytics tracking.
*/
public static void start() {
// bStats statistics
try {
Metrics metrics = new Metrics(AreaShop.getInstance());
// Number of regions
metrics.addCustomChart(new Metrics.SingleLineChart("region_count") {
@Override
public int getValue() {
return AreaShop.getInstance().getFileManager().getRegions().size();
}
});
// Number of rental regions
metrics.addCustomChart(new Metrics.SingleLineChart("rental_region_count") {
@Override
public int getValue() {
return AreaShop.getInstance().getFileManager().getRents().size();
}
});
// Number of buy regions
metrics.addCustomChart(new Metrics.SingleLineChart("buy_region_count") {
@Override
public int getValue() {
return AreaShop.getInstance().getFileManager().getBuys().size();
}
});
// Language
metrics.addCustomChart(new Metrics.SimplePie("language") {
@Override
public String getValue() {
return AreaShop.getInstance().getConfig().getString("language");
}
});
// Pie with region states
metrics.addCustomChart(new Metrics.AdvancedPie("region_state") {
@Override
public HashMap<String, Integer> getValues(HashMap<String, Integer> result) {
RegionStateStats stats = getStateStats();
result.put("For Rent", stats.forrent);
result.put("Rented", stats.rented);
result.put("For Sale", stats.forsale);
result.put("Sold", stats.sold);
result.put("Reselling", stats.reselling);
return result;
}
});
// Time series of each region state
metrics.addCustomChart(new Metrics.SingleLineChart("forrent_region_count") {
@Override
public int getValue() {
return getStateStats().forrent;
}
});
metrics.addCustomChart(new Metrics.SingleLineChart("rented_region_count") {
@Override
public int getValue() {
return getStateStats().rented;
}
});
metrics.addCustomChart(new Metrics.SingleLineChart("forsale_region_count") {
@Override
public int getValue() {
return getStateStats().forsale;
}
});
metrics.addCustomChart(new Metrics.SingleLineChart("sold_region_count") {
@Override
public int getValue() {
return getStateStats().sold;
}
});
metrics.addCustomChart(new Metrics.SingleLineChart("reselling_region_count") {
@Override
public int getValue() {
return getStateStats().reselling;
}
});
// TODO track rent/buy/unrent/sell/resell actions (so that it can be reported per collection interval)
AreaShop.debug("Started bstats.org statistics service");
} catch(Exception e) {
AreaShop.debug("Could not start bstats.org statistics service");
}
}
private static class RegionStateStats {
int forrent = 0;
int forsale = 0;
int rented = 0;
int sold = 0;
int reselling = 0;
}
private static RegionStateStats getStateStats() {
RegionStateStats result = new RegionStateStats();
for(GeneralRegion region : AreaShop.getInstance().getFileManager().getRegions()) {
if(region instanceof RentRegion) {
RentRegion rent = (RentRegion)region;
if(rent.isAvailable()) {
result.forrent++;
} else {
result.rented++;
}
} else if(region instanceof BuyRegion) {
BuyRegion buy = (BuyRegion)region;
if(buy.isAvailable()) {
result.forsale++;
} else if(buy.isInResellingMode()) {
result.reselling++;
} else {
result.sold++;
}
}
}
return result;
}
}
@@ -1,11 +1,11 @@
package me.wiefferink.areashop.tools;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import java.io.BufferedReader;
import java.io.IOException;
@@ -18,234 +18,242 @@ import java.util.logging.Logger;
public class GithubUpdateCheck {
public static final String API_HOST = "https://api.github.com/repos";
public static final String API_LATEST_RELEASE = "releases/latest";
public static final String USER_AGENT = "GithubUpdateCheck by NLThijs48";
public static final boolean DEBUG = false;
public static final String API_HOST = "https://api.github.com/repos";
public static final String API_LATEST_RELEASE = "releases/latest";
public static final String USER_AGENT = "GithubUpdateCheck by NLThijs48";
public static final boolean DEBUG = false;
private static final Gson GSON = new GsonBuilder().create();
private final String author;
private final String repository;
private final Plugin plugin;
private final Logger logger;
private URL url;
private VersionComparator versionComparator;
private final String author;
private final String repository;
private final Plugin plugin;
private final Logger logger;
private final String currentVersion;
private URL url;
private VersionComparator versionComparator;
// Status
private boolean checking;
private boolean error;
private boolean hasUpdate;
private String latestVersion;
// Status
private boolean checking;
private boolean error;
private boolean hasUpdate;
private String latestVersion;
private final String currentVersion;
/**
* Create a new GithubUpdateCheck with the required information.
*
* @param plugin The plugin to create it for (used for logging and checking version)
* @param author The author of the plugin as used on Github
* @param repository The repository name of the plugin on Github
*/
public GithubUpdateCheck(Plugin plugin, String author, String repository) {
this.plugin = plugin;
this.logger = plugin.getLogger();
this.author = author;
this.repository = repository;
this.currentVersion = plugin.getDescription().getVersion();
this.versionComparator = (latest, current) ->
!latest.equalsIgnoreCase(current);
/**
* Create a new GithubUpdateCheck with the required information.
* @param plugin The plugin to create it for (used for logging and checking version)
* @param author The author of the plugin as used on Github
* @param repository The repository name of the plugin on Github
*/
public GithubUpdateCheck(Plugin plugin, String author, String repository) {
this.plugin = plugin;
this.logger = plugin.getLogger();
this.author = author;
this.repository = repository;
this.currentVersion = plugin.getDescription().getVersion();
this.versionComparator = (latest, current) ->
!latest.equalsIgnoreCase(current);
this.checking = false;
this.error = false;
this.hasUpdate = false;
}
this.checking = false;
this.error = false;
this.hasUpdate = false;
}
/**
* Change the version comparator.
*
* @param versionComparator VersionComparator to use for checking if one version is newer than the other
* @return this
*/
public GithubUpdateCheck withVersionComparator(VersionComparator versionComparator) {
this.versionComparator = versionComparator;
return this;
}
/**
* Change the version comparator.
* @param versionComparator VersionComparator to use for checking if one version is newer than the other
* @return this
*/
public GithubUpdateCheck withVersionComparator(VersionComparator versionComparator) {
this.versionComparator = versionComparator;
return this;
}
/**
* Check if an update is available.
*/
public void checkUpdate() {
checkUpdate(null);
}
/**
* Check if an update is available.
*/
public void checkUpdate() {
checkUpdate(null);
}
/**
* Check if an update is available.
*
* @param callback Callback to execute when the update check is done
* @return GithubUpdateCheck containing the status of the check
*/
public GithubUpdateCheck checkUpdate(UpdateCallback callback) {
checking = true;
final GithubUpdateCheck self = this;
// Check for update on async thread
Utils.newChain()
.async(() -> {
try {
try {
String rawUrl = API_HOST + "/" + author + "/" + repository + "/" + API_LATEST_RELEASE;
url = new URL(rawUrl);
} catch (MalformedURLException e) {
logger.severe("Invalid url: '" + url + "', are the author '" + author + "' and repository '" + repository + "' correct?");
error = true;
return;
}
/**
* Check if an update is available.
* @param callback Callback to execute when the update check is done
* @return GithubUpdateCheck containing the status of the check
*/
public GithubUpdateCheck checkUpdate(UpdateCallback callback) {
checking = true;
final GithubUpdateCheck self = this;
// Check for update on asyn thread
new BukkitRunnable() {
@Override
public void run() {
try {
try {
String rawUrl = API_HOST + "/" + author + "/" + repository + "/" + API_LATEST_RELEASE;
url = new URL(rawUrl);
} catch(MalformedURLException e) {
logger.severe("Invalid url: '" + url + "', are the author '" + author + "' and repository '" + repository + "' correct?");
error = true;
return;
}
try {
URLConnection conn = url.openConnection();
// Give up after 15 seconds
conn.setConnectTimeout(15000);
// Identify ourselves
conn.addRequestProperty("User-Agent", USER_AGENT);
// Make sure we access the correct api version
conn.addRequestProperty("Accept", "application/vnd.github.v3+json");
// We want to read the result
conn.setDoOutput(true);
// Open connection
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String response = reader.readLine();
debug("Response:", response);
try {
URLConnection conn = url.openConnection();
// Give up after 15 seconds
conn.setConnectTimeout(15000);
// Identify ourselves
conn.addRequestProperty("User-Agent", USER_AGENT);
// Make sure we access the correct api version
conn.addRequestProperty("Accept", "application/vnd.github.v3+json");
// We want to read the result
conn.setDoOutput(true);
// Open connection
try(BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String response = reader.readLine();
debug("Response:", response);
JsonObject latestRelease = GSON.fromJson(response, JsonObject.class);
JSONObject latestRelease = (JSONObject)JSONValue.parse(response);
if (latestRelease.isJsonNull()) {
logger.warning("Failed to get api response from " + url);
error = true;
return;
}
debug("json: " + latestRelease.toString());
if(latestRelease.isEmpty()) {
logger.warning("Failed to get api response from " + url);
error = true;
return;
}
debug("json: " + latestRelease.toJSONString());
// Latest version
latestVersion = latestRelease.get("tag_name").getAsString();
debug("Tag name:", latestVersion);
// Latest version
latestVersion = (String)latestRelease.get("tag_name");
debug("Tag name:", latestVersion);
// Current version
debug("Plugin version:", currentVersion);
// Current version
debug("Plugin version:", currentVersion);
// Compare version
hasUpdate = versionComparator.isNewer(latestVersion, currentVersion);
}
} catch (IOException e) {
logger.severe("Failed to get latest release:" + ExceptionUtils
.getStackTrace(e));
error = true;
} catch (ClassCastException e) {
logger.info("Unexpected structure of the result, failed to parse it");
error = true;
}
} finally {
checking = false;
debug("result:", self);
}
}
).syncLast(x -> {
if (callback != null) {
callback.run(this);
}
}).execute();
return this;
}
// Compare version
hasUpdate = versionComparator.isNewer(latestVersion, currentVersion);
}
} catch(IOException e) {
logger.severe("Failed to get latest release:" + ExceptionUtils.getStackTrace(e));
error = true;
} catch(ClassCastException e) {
logger.info("Unexpected structure of the result, failed to parse it");
error = true;
}
} finally {
checking = false;
debug("result:", self);
if(callback != null) {
// Switch back to main thread and call the callback
new BukkitRunnable() {
@Override
public void run() {
callback.run(self);
}
}.runTask(plugin);
}
}
}
}.runTaskAsynchronously(plugin);
return this;
}
/**
* Check if an update check is running.
*
* @return true if an update check is running
*/
public boolean isChecking() {
return checking;
}
/**
* Check if an update check is running.
* @return true if an update check is running
*/
public boolean isChecking() {
return checking;
}
/**
* Check if the update check failed.
*
* @return true if the update check failed (an error message has been logged)
*/
public boolean hasFailed() {
return error;
}
/**
* Check if the update check failed.
* @return true if the update check failed (an error message has been logged)
*/
public boolean hasFailed() {
return error;
}
/**
* Check if an update has been found.
*
* @return true if an update has been found
*/
public boolean hasUpdate() {
return hasUpdate;
}
/**
* Check if an update has been found.
* @return true if an update has been found
*/
public boolean hasUpdate() {
return hasUpdate;
}
/**
* Get the repository that this update checker is checking.
*
* @return Used repository
*/
public String getRepository() {
return repository;
}
/**
* Get the repository that this update checker is checking.
* @return Used repository
*/
public String getRepository() {
return repository;
}
/**
* Get the author that this update checker is checking.
*
* @return Used author
*/
public String getAuthor() {
return author;
}
/**
* Get the author that this update checker is checking.
* @return Used author
*/
public String getAuthor() {
return author;
}
/**
* Get the current version.
*
* @return Current version of the plugin
*/
public String getCurrentVersion() {
return currentVersion;
}
/**
* Get the current version.
* @return Current version of the plugin
*/
public String getCurrentVersion() {
return currentVersion;
}
/**
* Get the latest version.
*
* @return Latest version of the plugin (if checking is complete)
*/
public String getLatestVersion() {
return latestVersion;
}
/**
* Get the latest version.
* @return Latest version of the plugin (if checking is complete)
*/
public String getLatestVersion() {
return latestVersion;
}
/**
* Print a debug message if DEBUG is enabled.
*
* @param message Message to print
*/
private void debug(Object... message) {
if (DEBUG) {
logger.info("[" + this.getClass().getSimpleName() + "] [DEBUG] " + StringUtils
.join(message, " "));
}
}
public interface VersionComparator {
/**
* Check if a version should be considered 'newer' than another.
* @param latestVersion Version that is available on Github
* @param currentVersion Version of the current plugin
* @return true if the latestVersion is newer than the localVersion, otherwise false
*/
boolean isNewer(String latestVersion, String currentVersion);
}
@Override
public String toString() {
return "GithubUpdateCheck(" + StringUtils.join(Arrays.asList(
"author=" + author,
"repository=" + repository,
"plugin=" + plugin.getName(),
"checking=" + checking,
"hasUpdate=" + hasUpdate,
"error=" + error,
"currentVersion=" + currentVersion,
"latestVersion=" + latestVersion
), ", ") + ")";
}
public interface UpdateCallback {
void run(GithubUpdateCheck result);
}
public interface VersionComparator {
/**
* Check if a version should be considered 'newer' than another.
*
* @param latestVersion Version that is available on Github
* @param currentVersion Version of the current plugin
* @return true if the latestVersion is newer than the localVersion, otherwise false
*/
boolean isNewer(String latestVersion, String currentVersion);
}
/**
* Print a debug message if DEBUG is enabled.
* @param message Message to print
*/
private void debug(Object... message) {
if(DEBUG) {
logger.info("[" + this.getClass().getSimpleName() + "] [DEBUG] " + StringUtils.join(message, " "));
}
}
@Override
public String toString() {
return "GithubUpdateCheck(" + StringUtils.join(Arrays.asList(
"author=" + author,
"repository=" + repository,
"plugin=" + plugin.getName(),
"checking=" + checking,
"hasUpdate=" + hasUpdate,
"error=" + error,
"currentVersion=" + currentVersion,
"latestVersion=" + latestVersion
), ", ") + ")";
}
public interface UpdateCallback {
void run(GithubUpdateCheck result);
}
}
@@ -3,6 +3,7 @@ package me.wiefferink.areashop.tools;
import me.wiefferink.areashop.AreaShop;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Tag;
import java.util.Arrays;
import java.util.HashSet;
@@ -11,52 +12,6 @@ import java.util.List;
public class Materials {
private Materials() {
}
private static final HashSet<String> WALL_SIGN_TYPES = new HashSet<>(Arrays.asList(
// 1.14+ types
"ACACIA_WALL_SIGN",
"BIRCH_WALL_SIGN",
"DARK_OAK_WALL_SIGN",
"JUNGLE_WALL_SIGN",
"OAK_WALL_SIGN",
"SPRUCE_WALL_SIGN",
// Legacy types
"LEGACY_WALL_SIGN",
"WALL_SIGN"
));
private static final HashSet<String> FLOOR_SIGN_TYPES = new HashSet<>(Arrays.asList(
// 1.14+ types
"ACACIA_SIGN",
"BIRCH_SIGN",
"DARK_OAK_SIGN",
"JUNGLE_SIGN",
"OAK_SIGN",
"SPRUCE_SIGN",
// Legacy types
"LEGACY_SIGN",
"LEGACY_SIGN_POST",
"SIGN",
"SIGN_POST"
));
private static boolean legacyMaterials = false;
static {
List<String> legacyMaterialVersions = Arrays.asList("1.7", "1.8", "1.9", "1.10", "1.11", "1.12");
for(String legacyMaterialVersion : legacyMaterialVersions) {
String version = Bukkit.getBukkitVersion();
// Detects '1.8', '1.8.3', '1.8-pre1' style versions
if(version.equals(legacyMaterialVersion)
|| version.startsWith(legacyMaterialVersion + ".")
|| version.startsWith(legacyMaterialVersion + "-")) {
legacyMaterials = true;
break;
}
}
}
/**
@@ -69,46 +24,12 @@ public class Materials {
if (!isSign(name)) {
return null;
}
Material result = null;
if (legacyMaterials) {
// 1.12 and lower just know SIGN_POST, WALL_SIGN and SIGN
if (FLOOR_SIGN_TYPES.contains(name)) {
result = Material.getMaterial("SIGN_POST");
} else if (WALL_SIGN_TYPES.contains(name)) {
result = Material.getMaterial("WALL_SIGN");
if (result == null) {
result = Material.getMaterial("SIGN");
}
}
} else {
// Try saved name (works for wood types on 1.14, regular types for below)
result = Material.getMaterial(name);
if (result == null) {
// Cases for 1.13, which don't know wood types, but need new materials
if (FLOOR_SIGN_TYPES.contains(name)) {
// SIGN -> OAK_SIGN for 1.14
result = Material.getMaterial("OAK_SIGN");
// Fallback for 1.13
if (result == null) {
result = Material.getMaterial("SIGN");
}
} else if (WALL_SIGN_TYPES.contains(name)) {
// WALL_SIGN -> OAK_WALL_SIGN for 1.14
result = Material.getMaterial("OAK_WALL_SIGN");
// Fallback for 1.13
if (result == null) {
result = Material.getMaterial("WALL_SIGN");
}
}
}
try {
return Material.matchMaterial(name);
} catch (IllegalArgumentException ignored) {
AreaShop.debug("Materials.get() null result:", name);
return null;
}
if (result == null) {
AreaShop.debug("Materials.get() null result:", name, "legacyMaterials:", legacyMaterials);
}
return result;
}
/**
@@ -117,7 +38,7 @@ public class Materials {
* @return true if the given material is a sign
*/
public static boolean isSign(Material material) {
return isSign(material.name());
return Tag.SIGNS.isTagged(material) || Tag.WALL_SIGNS.isTagged(material);
}
/**
@@ -126,7 +47,12 @@ public class Materials {
* @return true if the given material is a sign
*/
public static boolean isSign(String name) {
return name != null && (FLOOR_SIGN_TYPES.contains(name) || WALL_SIGN_TYPES.contains(name));
try {
return isSign(Material.matchMaterial(name));
} catch (IllegalArgumentException ex) {
AreaShop.debug("Invalid Material: " + name + " passed when performing sign check.");
return false;
}
}
}
@@ -0,0 +1,152 @@
package me.wiefferink.areashop.tools;
/**
* Parse math from a string
* Adapted from:
* https://stackoverflow.com/questions/3422673/how-to-evaluate-a-math-expression-given-in-string-form
*/
public final class OperandParser {
private final String str;
private OperandParser(final String str) {
this.str = str;
}
public static double parse(final String str) throws ParseException {
return new OperandParser(str).parse();
}
private int pos = -1, ch;
private void nextChar() {
ch = (++pos < str.length()) ? str.charAt(pos) : -1;
}
private boolean eat(int charToEat) {
while (ch == ' ') nextChar();
if (ch == charToEat) {
nextChar();
return true;
}
return false;
}
private double parse() throws ParseException {
nextChar();
double x = parseExpression();
if (pos < str.length())
{
throw new ParseException("Unexpected: " + (char) ch);
}
return x;
}
// Grammar:
// expression = term | expression `+` term | expression `-` term
// term = factor | term `*` factor | term `/` factor
// factor = `+` factor | `-` factor | `(` expression `)`
// | number | functionName factor | factor `^` factor
private double parseExpression() throws ParseException {
double x = parseTerm();
for (; ; ) {
if (eat('+')) {
// addition
x += parseTerm();
}
else if (eat('-')) {
// subtraction
x -= parseTerm();
}
else return x;
}
}
private double parseTerm() throws ParseException {
double x = parseFactor();
for (; ; ) {
if (eat('*')) {
// multiplication
x *= parseFactor();
}
else if (eat('/')) {
// division
x /= parseFactor();
}
else return x;
}
}
private double parseFactor() throws ParseException {
if (eat('+')) {
// unary plus
return parseFactor();
}
if (eat('-')) {
// unary minus
return -parseFactor();
}
double x;
int startPos = this.pos;
if (eat('(')) {
// parentheses
x = parseExpression();
eat(')');
} else if ((ch >= '0' && ch <= '9') || ch == '.') {
// numbers
while ((ch >= '0' && ch <= '9') || ch == '.') {
nextChar();
}
x = Double.parseDouble(str.substring(startPos, this.pos));
} else if (ch >= 'a' && ch <= 'z') {
// functions
while (ch >= 'a' && ch <= 'z') {
nextChar();
}
String func = str.substring(startPos, this.pos);
x = parseFactor();
x = switch (func) {
case "sqrt" -> Math.sqrt(x);
case "sin" -> Math.sin(Math.toRadians(x));
case "cos" -> Math.cos(Math.toRadians(x));
case "tan" -> Math.tan(Math.toRadians(x));
default -> throw new ParseException("Unknown function: " + func);
};
} else {
throw new ParseException("Unexpected: " + (char) ch);
}
if (eat('^')) {
// exponentiation
x = Math.pow(x, parseFactor());
}
return x;
}
public static class ParseException extends Exception {
public ParseException() {
}
public ParseException(String message) {
super(message);
}
public ParseException(String message, Throwable cause) {
super(message, cause);
}
public ParseException(Throwable cause) {
super(cause);
}
public ParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
}
@@ -12,7 +12,10 @@ import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.interactivemessenger.Log;
import me.wiefferink.interactivemessenger.processing.Message;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.*;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
@@ -22,10 +25,6 @@ import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
@@ -46,7 +45,6 @@ public class Utils {
private static Set<String> weeks;
private static Set<String> months;
private static Set<String> years;
private static ScriptEngine scriptEngine;
private static Map<Double, String> suffixes;
// Not used
@@ -156,19 +154,8 @@ public class Utils {
*
* @return Online players
*/
@SuppressWarnings("unchecked")
public static Collection<? extends Player> getOnlinePlayers() {
try {
Method onlinePlayerMethod = Server.class.getMethod("getOnlinePlayers");
if (onlinePlayerMethod.getReturnType().equals(Collection.class)) {
return ((Collection<? extends Player>) onlinePlayerMethod.invoke(Bukkit.getServer()));
} else {
return Arrays.asList((Player[]) onlinePlayerMethod.invoke(Bukkit.getServer()));
}
} catch (Exception ex) {
AreaShop.debug("getOnlinePlayers error: " + ex.getMessage());
}
return new HashSet<>();
return Bukkit.getOnlinePlayers();
}
/**
@@ -779,16 +766,11 @@ public class Utils {
return Double.parseDouble(input);
}
// Lazy init scriptEngine
if (scriptEngine == null) {
scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
}
// Evaluate expression
Object result;
try {
result = scriptEngine.eval(input);
} catch (ScriptException e) {
result = OperandParser.parse(input);
} catch (OperandParser.ParseException e) {
AreaShop.warn("Price of region", region.getName(), "is set with an invalid expression: '" + input + "', exception:", ExceptionUtils.getStackTrace(e));
return 99999999999.0; // High fallback for safety
}
+1 -1
View File
@@ -1,6 +1,6 @@
name: AreaShop
main: me.wiefferink.areashop.AreaShop
version: "${project.version}"
version: "@version@"
description: "Selling and renting WorldGuard regions to your players, highly configurable."
depend: [Vault, WorldGuard, WorldEdit]
softdepend: [Multiverse-Core, FastAsyncWorldEdit]
+50
View File
@@ -0,0 +1,50 @@
plugins {
id 'java'
}
group = "me.wiefferink.areashop"
version = '2.6.5'
subprojects {
plugins.apply('java')
repositories {
mavenCentral()
maven {
name = 'paper-repo'
url = uri('https://papermc.io/repo/repository/maven-public/')
}
maven {
name = 'spigot-repo'
url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/')
}
maven {
name = 'jitpack'
url = uri('https://jitpack.io')
content {
includeGroupByRegex("com\\.github.*")
}
}
maven {
name = 'aikar-repo'
url = uri('https://repo.aikar.co/content/groups/aikar/')
}
maven {
name = 'enginehub-repo'
url = uri('https://maven.enginehub.org/repo/')
}
}
tasks.withType(JavaCompile) {
tasks.withType(JavaCompile) {
javaToolchains.compilerFor {
JavaLanguageVersion.of(16)
}
options.release.set(16)
options.encoding = 'UTF-8'
options.fork = true
options.deprecation = true
}
}
}
+2
View File
@@ -0,0 +1,2 @@
org.gradle.parallel=true
org.gradle.java.installations.auto-download=false
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+185
View File
@@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
Vendored
+89
View File
@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
-53
View File
@@ -1,53 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>areashop-fawe-1-15</artifactId>
<packaging>jar</packaging>
<name>AreaShop FastAsyncWorldEdit 1.15+</name>
<version>latest</version>
<parent>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-parent</artifactId>
<version>1.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<repositories>
<repository>
<id>IS-Repo</id>
<url>https://mvn.intellectualsites.com/content/repositories/releases/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.15.2-R0.1-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.intellectualsites.fawe</groupId>
<artifactId>FAWE-Bukkit</artifactId>
<version>1.16-380</version> <!-- Equivalent to WE 7.0.2? -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-interface</artifactId>
<version>latest</version>
<type>jar</type>
</dependency>
</dependencies>
</project>
@@ -1,242 +0,0 @@
package me.wiefferink.areashop.handlers.fawe.v1_15;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.RelightMode;
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.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.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
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.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.entity.Player;
import java.io.*;
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);
}
private Mask newMask(final ProtectedRegion region) {
return new Mask() {
@Override
public boolean test(BlockVector3 vector) {
return region.contains(vector);
}
@Override
public Mask2D toMask2D() {
return null;
}
@Override
public Mask copy() {
return this;
}
};
}
@Override
public boolean restoreRegionBlocks(File rawFile, GeneralRegionInterface regionInterface) {
// TODO implement using the FastAsyncWorldEdit api to paste async
File file = null;
ClipboardFormat format = null;
for (ClipboardFormat formatOption : BuiltInClipboardFormat.values()) {
if (new File(rawFile.getAbsolutePath() + "." + formatOption.getPrimaryFileExtension())
.exists()) {
file = new File(
rawFile.getAbsolutePath() + "." + formatOption.getPrimaryFileExtension());
format = formatOption;
break;
}
}
if (file == null) {
pluginInterface.getLogger().info("Did not restore region " + regionInterface.getName()
+ ", schematic file does not exist: " + rawFile.getAbsolutePath());
return false;
}
pluginInterface.debugI("Trying to restore region", regionInterface.getName(), " from file",
file.getAbsolutePath(), "with format", format.getName());
com.sk89q.worldedit.world.World world = null;
if (regionInterface.getName() != null) {
world = BukkitAdapter.adapt(regionInterface.getWorld());
}
if (world == null) {
pluginInterface.getLogger().info(
"Did not restore region " + regionInterface.getName() + ", world not found: "
+ regionInterface.getWorldName());
return false;
}
final FaweLimit limit = new FaweLimit();
limit.MAX_CHANGES = pluginInterface.getConfig().getInt("maximumBlocks");
EditSession editSession = FaweAPI.getEditSessionBuilder(world).limit(limit).build();
editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE);
ProtectedRegion region = regionInterface.getRegion();
// Get the origin and size of the region
BlockVector3 origin = BlockVector3
.at(region.getMinimumPoint().getBlockX(), region.getMinimumPoint().getBlockY(),
region.getMinimumPoint().getBlockZ());
// Read the schematic and paste it into the world
try (Closer closer = Closer.create(); FileInputStream fis = closer.register(new FileInputStream(file));
BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
NBTInputStream nbtStream = new NBTInputStream(new GZIPInputStream(bis));
ClipboardReader reader = new FastSchematicReader(nbtStream)) {
LocalSession session =
new LocalSession(pluginInterface.getWorldEdit().getLocalConfiguration());
Clipboard clipboard = reader.read();
if (clipboard.getDimensions().getY() != regionInterface.getHeight()
|| clipboard.getDimensions().getX() != regionInterface.getWidth()
|| clipboard.getDimensions().getZ() != regionInterface.getDepth()) {
pluginInterface.getLogger().warning(
"Size of the region " + regionInterface.getName()
+ " is not the same as the schematic to restore!");
pluginInterface.debugI(
"schematic|region, x:" + clipboard.getDimensions().getX() + "|"
+ regionInterface.getWidth() + ", y:" + clipboard.getDimensions().getY()
+ "|" + regionInterface.getHeight() + ", z:" + clipboard.getDimensions()
.getZ() + "|" + regionInterface.getDepth());
}
clipboard.setOrigin(clipboard.getMinimumPoint());
ClipboardHolder clipboardHolder = new ClipboardHolder(clipboard);
session.setBlockChangeLimit(pluginInterface.getConfig().getInt("maximumBlocks"));
session.setClipboard(clipboardHolder);
// Build operation
BlockTransformExtent extent = new BlockTransformExtent(clipboard);
ForwardExtentCopy copy =
new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(),
editSession, origin);
copy.setTransform(clipboardHolder.getTransform());
// Mask to region (for polygon and other weird shaped regions)
// TODO make this more efficient (especially for polygon regions)
if (region.getType() != RegionType.CUBOID) {
copy.setSourceMask(newMask(region));
}
Operations.completeLegacy(copy);
} catch (MaxChangedBlocksException e) {
pluginInterface.getLogger().warning(
"exceeded the block limit while restoring schematic of " + regionInterface.getName()
+ ", limit in exception: " + e.getBlockLimit() + ", limit passed by AreaShop: "
+ pluginInterface.getConfig().getInt("maximumBlocks"));
return false;
} catch (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;
}
editSession.flushQueue();
return true;
}
@Override public boolean saveRegionBlocks(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 false;
}
final FaweLimit limit = new FaweLimit();
limit.MAX_CHANGES = pluginInterface.getConfig().getInt("maximumBlocks");
EditSession editSession = FaweAPI.getEditSessionBuilder(world).limit(limit).relightMode(RelightMode.OPTIMAL).build();
// Create a clipboard
CuboidRegion selection =
new CuboidRegion(world, regionInterface.getRegion().getMinimumPoint(),
regionInterface.getRegion().getMaximumPoint());
BlockArrayClipboard clipboard = new BlockArrayClipboard(selection);
clipboard.setOrigin(regionInterface.getRegion().getMinimumPoint());
ForwardExtentCopy copy = new ForwardExtentCopy(editSession,
new CuboidRegion(world, regionInterface.getRegion().getMinimumPoint(),
regionInterface.getRegion().getMaximumPoint()), clipboard,
regionInterface.getRegion().getMinimumPoint());
try {
Operations.completeLegacy(copy);
} catch (MaxChangedBlocksException e) {
pluginInterface.getLogger().warning(
"Exceeded the block limit while saving schematic of " + regionInterface.getName()
+ ", limit in exception: " + e.getBlockLimit() + ", limit passed by AreaShop: "
+ pluginInterface.getConfig().getInt("maximumBlocks"));
return false;
}
try (Closer closer = Closer.create();
FileOutputStream fos = closer.register(new FileOutputStream(file));
BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos))) {
ClipboardWriter writer = closer.register(format.getWriter(bos));
writer.write(clipboard);
} catch (IOException e) {
pluginInterface.getLogger().warning(
"An error 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;
}
@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;
}
}
}
+16
View File
@@ -0,0 +1,16 @@
repositories {
maven {
name = 'IS-Repo'
url = uri('https://mvn.intellectualsites.com/content/repositories/releases/')
}
}
dependencies {
compileOnly project(':areashop-interface')
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
compileOnly ('com.intellectualsites.fawe:FAWE-Core:1.16-725')
compileOnly ('com.intellectualsites.fawe:FAWE-Bukkit:1.16-725')
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.5'
}
description = 'AreaShop FastAsyncWorldEdit 1.16'
@@ -0,0 +1,289 @@
package me.wiefferink.areashop.handlers.fawe.v1_16;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.RelightMode;
import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
import com.boydti.fawe.util.EditSessionBuilder;
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.bukkit.BukkitAdapter;
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.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
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.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.entity.Player;
import org.bukkit.util.BoundingBox;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.zip.GZIPInputStream;
// Future: this class could use the schematic save/paste api of FAWE: https://github.com/boy0001/FastAsyncWorldedit/wiki/Pasting-a-schematic
// This would not allow for shaping the schematic to a polygon region though
public class FastAsyncWorldEditHandler extends WorldEditInterface {
public FastAsyncWorldEditHandler(AreaShopInterface pluginInterface) {
super(pluginInterface);
}
private static class RegionBoundMask implements Mask {
private final BoundingBox boundingBox;
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());
}
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 Mask2D toMask2D() {
return null;
}
@Override
public Mask copy() {
return new RegionBoundMask(boundingBox);
}
}
@Override
@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());
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 = new EditSessionBuilder(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);
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(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();
}
@Override
@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 = new EditSessionBuilder(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;
}
}
}
+16
View File
@@ -0,0 +1,16 @@
repositories {
maven {
name = 'IS-Repo'
url = uri('https://mvn.intellectualsites.com/content/repositories/releases/')
}
}
dependencies {
compileOnly project(':areashop-interface')
compileOnly('org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT')
compileOnly("com.fastasyncworldedit:FAWE-Core:1.17-138")
compileOnly("com.fastasyncworldedit:FAWE-Bukkit:1.17-138")
compileOnly('com.sk89q.worldguard:worldguard-bukkit:7.0.5')
}
description = 'AreaShop FastAsyncWorldEdit 1.17'
@@ -0,0 +1,290 @@
package me.wiefferink.areashop.handlers.fawe.v1_17;
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.object.FaweLimit;
import com.fastasyncworldedit.core.util.EditSessionBuilder;
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.bukkit.BukkitAdapter;
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.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
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.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.entity.Player;
import org.bukkit.util.BoundingBox;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.zip.GZIPInputStream;
// Future: this class could use the schematic save/paste api of FAWE: https://github.com/boy0001/FastAsyncWorldedit/wiki/Pasting-a-schematic
// This would not allow for shaping the schematic to a polygon region though
public class FastAsyncWorldEditHandler extends WorldEditInterface {
public FastAsyncWorldEditHandler(AreaShopInterface pluginInterface) {
super(pluginInterface);
}
private static class RegionBoundMask implements Mask {
private final BoundingBox boundingBox;
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());
}
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 Mask2D toMask2D() {
return null;
}
@Override
public Mask copy() {
return new RegionBoundMask(boundingBox);
}
}
@Override
@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());
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 = new EditSessionBuilder(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);
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(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();
}
@Override
@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 = new EditSessionBuilder(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;
}
}
}
+7
View File
@@ -0,0 +1,7 @@
dependencies {
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
compileOnly 'com.sk89q.worldedit:worldedit-bukkit:7.2.5-SNAPSHOT'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.5'
}
description = 'AreaShop Interface'
-38
View File
@@ -1,38 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>areashop-interface</artifactId>
<packaging>jar</packaging>
<name>AreaShop Interface</name>
<version>latest</version>
<parent>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-parent</artifactId>
<version>1.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -3,10 +3,11 @@ 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.logging.Logger;
public interface AreaShopInterface {
public interface AreaShopInterface extends Plugin {
void debugI(Object... message);
YamlConfiguration getConfig();
@@ -0,0 +1,27 @@
package me.wiefferink.areashop.interfaces;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
public interface BlockBehaviourHelper {
default boolean canPlace(Location location, Material material) {
return canPlace(location, material.createBlockData());
}
boolean canPlace(Location location, BlockData blockData);
/**
* Check if a sign is valid.
*
* @param block The block
* @return Returns true if the sign can exist in that location, false otherwise.
*/
boolean isBlockValid(Block block);
boolean isBlockStateValid(BlockState blockState);
}
@@ -0,0 +1,7 @@
package me.wiefferink.areashop.interfaces;
public interface NMS {
BlockBehaviourHelper behaviourHelper();
}
@@ -51,9 +51,9 @@ public class RegionAccessSet {
* Get this access set as a list of player UUIDs.
* @return List of player UUIDs, first players already added by UUID, then players added by name, groups are not in the list
*/
@SuppressWarnings("deprecation")
public List<UUID> asUniqueIdList() {
List<UUID> result = new ArrayList<>();
result.addAll(playerUniqueIds);
List<UUID> result = new ArrayList<>(playerUniqueIds);
for(String playerName : playerNames) {
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName);
if (offlinePlayer.hasPlayedBefore()) {
@@ -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;
@@ -20,6 +21,10 @@ public abstract class WorldEditInterface {
*/
public abstract boolean restoreRegionBlocks(File file, GeneralRegionInterface regionInterface);
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 +34,10 @@ public abstract class WorldEditInterface {
*/
public abstract boolean saveRegionBlocks(File file, GeneralRegionInterface regionInterface);
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
@@ -9,7 +9,7 @@ public class WorldEditSelection {
private final Location maximum;
/**
* Craete a WorldEditSelection.
* Create a WorldEditSelection.
* @param world World the selection is in
* @param a Primary selection location
* @param b Secondary selection location
+8
View File
@@ -0,0 +1,8 @@
repositories {
mavenLocal()
}
dependencies {
compileOnly project(':areashop-interface')
compileOnly 'org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT'
}
@@ -0,0 +1,46 @@
package me.wiefferink.areashop.nms.v1_16_R3;
import me.wiefferink.areashop.interfaces.BlockBehaviourHelper;
import net.minecraft.server.v1_16_R3.BlockPosition;
import net.minecraft.server.v1_16_R3.IBlockData;
import net.minecraft.server.v1_16_R3.World;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_16_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_16_R3.block.CraftBlock;
import org.bukkit.craftbukkit.v1_16_R3.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_16_R3.block.data.CraftBlockData;
import java.util.Objects;
public class BlockBehaviourHelperImpl implements BlockBehaviourHelper {
@Override
public boolean canPlace(Location location, BlockData blockData) {
Objects.requireNonNull(location.getWorld(), "Null World!");
final BlockPosition blockPosition = new BlockPosition(location.getX(), location.getY(), location.getZ());
final CraftWorld craftWorld = (CraftWorld) location.getWorld();
final World world = craftWorld.getHandle();
final CraftBlockData craftBlockData = (CraftBlockData) blockData;
final IBlockData ibd = craftBlockData.getState();
return ibd.canPlace(world, blockPosition);
}
@Override
public boolean isBlockValid(Block block) {
final CraftBlock craftBlock = (CraftBlock) block;
final CraftWorld craftWorld = (CraftWorld) craftBlock.getWorld();
final World world = craftWorld.getHandle();
final IBlockData ibd = craftBlock.getNMS();
return ibd.canPlace(world, craftBlock.getPosition());
}
@Override
public boolean isBlockStateValid(BlockState blockState) {
final CraftBlockState craftBlockState = (CraftBlockState) blockState;
final IBlockData ibd = craftBlockState.getHandle();
return ibd.canPlace(craftBlockState.getBlock().getCraftWorld().getHandle(), craftBlockState.getPosition());
}
}
@@ -0,0 +1,15 @@
package me.wiefferink.areashop.nms.v1_16_R3;
import me.wiefferink.areashop.interfaces.BlockBehaviourHelper;
import me.wiefferink.areashop.interfaces.NMS;
public final class NMSImpl implements NMS {
private BlockBehaviourHelper signHelper = new BlockBehaviourHelperImpl();
@Override
public BlockBehaviourHelper behaviourHelper() {
return this.signHelper;
}
}
+8
View File
@@ -0,0 +1,8 @@
repositories {
mavenLocal()
}
dependencies {
compileOnly project(':areashop-interface')
compileOnly 'org.spigotmc:spigot:1.17.1-R0.1-SNAPSHOT'
}
@@ -0,0 +1,46 @@
package me.wiefferink.areashop.nms.v1_17_R1;
import me.wiefferink.areashop.interfaces.BlockBehaviourHelper;
import net.minecraft.core.BlockPosition;
import net.minecraft.world.level.World;
import net.minecraft.world.level.block.state.IBlockData;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData;
import java.util.Objects;
public class BlockBehaviourHelperImpl implements BlockBehaviourHelper {
@Override
public boolean canPlace(Location location, BlockData blockData) {
Objects.requireNonNull(location.getWorld(), "Null World!");
final BlockPosition blockPosition = new BlockPosition(location.getX(), location.getY(), location.getZ());
final CraftWorld craftWorld = (CraftWorld) location.getWorld();
final World world = craftWorld.getHandle();
final CraftBlockData craftBlockData = (CraftBlockData) blockData;
final IBlockData ibd = craftBlockData.getState();
return ibd.canPlace(world, blockPosition);
}
@Override
public boolean isBlockValid(Block block) {
final CraftBlock craftBlock = (CraftBlock) block;
final CraftWorld craftWorld = (CraftWorld) craftBlock.getWorld();
final World world = craftWorld.getHandle();
final IBlockData ibd = craftBlock.getNMS();
return ibd.canPlace(world, craftBlock.getPosition());
}
@Override
public boolean isBlockStateValid(BlockState blockState) {
final CraftBlockState craftBlockState = (CraftBlockState) blockState;
final IBlockData ibd = craftBlockState.getHandle();
return ibd.canPlace(craftBlockState.getBlock().getCraftWorld().getHandle(), craftBlockState.getPosition());
}
}
@@ -0,0 +1,15 @@
package me.wiefferink.areashop.nms.v1_17_R1;
import me.wiefferink.areashop.interfaces.BlockBehaviourHelper;
import me.wiefferink.areashop.interfaces.NMS;
public final class NMSImpl implements NMS {
private BlockBehaviourHelper signHelper = new BlockBehaviourHelperImpl();
@Override
public BlockBehaviourHelper behaviourHelper() {
return this.signHelper;
}
}
+8
View File
@@ -0,0 +1,8 @@
dependencies {
implementation project(':areashop-interface')
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
compileOnly 'com.sk89q.worldedit:worldedit-bukkit:7.2.5'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.5'
}
description = 'AreaShop WorldEdit 7'
-52
View File
@@ -1,52 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>areashop-worldedit-7</artifactId>
<packaging>jar</packaging>
<name>AreaShop WorldEdit 7</name>
<version>latest</version>
<description>
World Edit compatibility handler
- Deprecated usages on 7.2.0
- Compiles against 7.0.1, 7.1.0-SNAPSHOT, 7.2.0-SNAPSHOT
</description>
<parent>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-parent</artifactId>
<version>1.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.4-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-interface</artifactId>
<version>latest</version>
<type>jar</type>
</dependency>
</dependencies>
</project>
@@ -91,9 +91,12 @@ public class WorldEditHandler extends WorldEditInterface {
pluginInterface.getLogger().info("Did not restore region " + regionInterface.getName() + ", world not found: " + regionInterface.getWorldName());
return false;
}
EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit() // WARNING Deprecated in 7.2.0!
.getEditSessionFactory()
.getEditSession(world, pluginInterface.getConfig().getInt("maximumBlocks"));
EditSession editSession = pluginInterface.getWorldEdit()
.getWorldEdit()
.newEditSessionBuilder()
.world(world)
.maxBlocks(pluginInterface.getConfig().getInt("maximumBlocks"))
.build();
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());
@@ -179,9 +182,12 @@ public class WorldEditHandler extends WorldEditInterface {
pluginInterface.getLogger().warning("Did not save region " + regionInterface.getName() + ", world not found: " + regionInterface.getWorldName());
return false;
}
EditSession editSession = pluginInterface.getWorldEdit().getWorldEdit() // WARNING Deprecated in 7.2.0!
.getEditSessionFactory()
.getEditSession(world, pluginInterface.getConfig().getInt("maximumBlocks"));
EditSession editSession = pluginInterface.getWorldEdit()
.getWorldEdit()
.newEditSessionBuilder()
.world(world)
.maxBlocks(pluginInterface.getConfig().getInt("maximumBlocks"))
.build();
// Create a clipboard
CuboidRegion selection = new CuboidRegion(world, regionInterface.getRegion().getMinimumPoint(), regionInterface.getRegion().getMaximumPoint());
+8
View File
@@ -0,0 +1,8 @@
dependencies {
implementation project(':areashop-interface')
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
compileOnly 'com.sk89q.worldedit:worldedit-bukkit:7.2.5'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.5'
}
description = 'AreaShop WorldGuard 7'
-47
View File
@@ -1,47 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>areashop-worldguard-7</artifactId>
<packaging>jar</packaging>
<name>AreaShop WorldGuard 7</name>
<version>latest</version>
<parent>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-parent</artifactId>
<version>1.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<scope>provided</scope>
<version>7.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.4-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-interface</artifactId>
<version>latest</version>
<type>jar</type>
</dependency>
</dependencies>
</project>
-116
View File
@@ -1,116 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>AreaShop Parent</name>
<url>https://github.com/NLthijs48/AreaShop</url>
<licenses>
<license>
<name>GNU General Public License v3.0</name>
<url>https://www.gnu.org/licenses/gpl-3.0.en.html</url>
<distribution>repo</distribution>
</license>
</licenses>
<issueManagement>
<url>https://github.com/NLthijs48/AreaShop/issues</url>
<system>GitHub Issues</system>
</issueManagement>
<ciManagement>
<system>Jenkins</system>
<url>http://jenkins.wiefferink.me/job/AreaShop</url>
</ciManagement>
<repositories>
<repository>
<id>vault-repo</id>
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
</repository>
<repository>
<id>wiefferink-repo</id>
<url>http://maven.wiefferink.me</url>
</repository>
<repository>
<id>bstats-repo</id>
<url>http://repo.bstats.org/content/repositories/releases/</url>
</repository>
<repository>
<id>mvn-repo</id>
<url>https://mvnrepository.com/artifact/org.bstats/bstats-bukkit</url>
</repository>
<repository>
<id>sk89q-repo</id>
<url>https://maven.enginehub.org/repo/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!--build.number>#CUSTOM</build.number-->
</properties>
<modules>
<module>hooks/areashop-interface</module>
<!-- FAWE Compat -->
<module>hooks/areashop-fawe-1-15</module>
<!-- World Edit Compat -->
<module>hooks/areashop-worldedit-7</module>
<!-- World Guard Compat -->
<module>hooks/areashop-worldguard-7</module>
<module>AreaShop</module>
</modules>
<build>
<defaultGoal>clean package</defaultGoal>
<!--plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.0</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.29</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<configuration>
<configLocation>config/checkstyle.xml</configLocation>
<suppressionsLocation>config/checkstyle-suppressions.xml</suppressionsLocation>
<suppressionsFileExpression>config/checkstyle.suppressions.file
</suppressionsFileExpression>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<violationSeverity>error</violationSeverity>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins-->
</build>
</project>
+17
View File
@@ -0,0 +1,17 @@
rootProject.name = 'areashop-parent'
include(':areashop-worldguard-7')
include(':areashop-interface')
include(':areashop-fawe-1-16')
include(':areashop-fawe-1-17')
include(':areashop-worldedit-7')
include(':areashop-nms-1-16-5')
include(':areashop-nms-1-17')
include(':areashop')
project(":areashop-worldguard-7").projectDir = file('hooks/areashop-worldguard-7')
project(":areashop-interface").projectDir = file('hooks/areashop-interface')
project(":areashop-fawe-1-16").projectDir = file('hooks/areashop-fawe-1-16')
project(":areashop-fawe-1-17").projectDir = file('hooks/areashop-fawe-1-17')
project(":areashop-worldedit-7").projectDir = file('hooks/areashop-worldedit-7')
project(":areashop-nms-1-16-5").projectDir = file('hooks/areashop-nms-1-16-5')
project(":areashop-nms-1-17").projectDir = file('hooks/areashop-nms-1-17')
project(":areashop").projectDir = file('AreaShop')