Compare commits

..
52 changed files with 1305 additions and 411 deletions

No files matched your search

+12 -3
View File
@@ -34,6 +34,9 @@ dependencies {
implementation("com.google.inject.extensions:guice-assistedinject:7.0.0") {
exclude("com.google.guava", "guava")
}
implementation("net.kyori:adventure-platform-bukkit:4.3.0")
implementation("net.kyori:adventure-text-minimessage:4.14.0")
implementation("org.spongepowered:configurate-yaml:4.0.0")
// Project submodules
implementation(projects.areashopInterface)
@@ -47,8 +50,11 @@ dependencies {
// Adapters
if (!providers.environmentVariable("JITPACK").isPresent) {
runtimeOnly(project(":adapters:platform:bukkit-1-17", "reobf"))
runtimeOnly(project(":adapters:platform:bukkit-1-18", "reobf"))
runtimeOnly(project(":adapters:platform:bukkit-1-19", "reobf"))
runtimeOnly(project(":adapters:platform:bukkit-1-20", "reobf"))
}
runtimeOnly(projects.adapters.platform.bukkitModern)
testImplementation("com.github.seeseemelk:MockBukkit-v1.20:3.9.0")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
@@ -81,6 +87,10 @@ tasks {
withSourcesJar()
}
test {
useJUnitPlatform()
}
val javaComponent = project.components["java"] as AdhocComponentWithVariants
javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) {
skip()
@@ -97,9 +107,8 @@ tasks {
relocate("io.papermc.lib", "${base}.paperlib")
relocate("io.github.bakedlibs.dough", "${base}.dough")
relocate("com.google.inject", "${base}.inject")
relocate("com.google.errorprone", "${base}.errorprone")
relocate("org.aopalliance", "${base}.aopalliance")
relocate("javax.annotation", "${base}.javax.annotation")
relocate("jakarta.inject", "${base}.jakarta.inject")
relocate("javax.inject", "${base}.javax.inject")
}
}
@@ -0,0 +1,145 @@
package io.github.md5sha256.areashop;
import me.wiefferink.areashop.managers.AdventureLanguageManager;
import me.wiefferink.interactivemessenger.processing.ReplacementProvider;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import java.text.NumberFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AdventureMessageRenderer {
/**
* Lang pattern used by the old mechanism
* Equivalent REGEX: \Q%\E\Qlang:\E([a-zA-Z-]+?)\|(.+?)\|\Q%\E
* Group 1 is the message key for substitution
* Group 2 is the replacement arguments
* NOTE: A properly formatted key should have a trailing '|' char.
*/
private static final Pattern LANG_PATTERN = Pattern.compile(
Pattern.quote("%") + "lang:([a-zA-Z-]+?)\\|(.+)\\|+" + Pattern.quote("%")
);
private static final Pattern POSITIONAL_ARGUMENT_PATTERN = Pattern.compile(
Pattern.quote("%") + "(\\d+)" + Pattern.quote("%")
);
private static final Pattern NAMED_ARGUMENT_PATTERN = Pattern.compile(Pattern.quote(
"%") + "(?<name>[a-zA-Z]+)" + Pattern.quote("%"));
private static final Pattern VARIABLE_DELIMITER = Pattern.compile("\\|");
private final AdventureLanguageManager adventureLanguageManager;
public AdventureMessageRenderer(AdventureLanguageManager languageManager) {
this.adventureLanguageManager = languageManager;
}
public String chatPrefix() {
return this.adventureLanguageManager.chatPrefix();
}
public Component renderedChatPrefix() {
return renderMessage(this.adventureLanguageManager.chatPrefix());
}
public Component renderMessageFromKey(String key, Object... replacements) {
String message = this.adventureLanguageManager.messageFor(key);
if (message.isEmpty()) {
return Component.empty();
}
return renderMessage(message, replacements);
}
public String performReplacementsFromKey(String key, Object... replacements) {
String message = this.adventureLanguageManager.messageFor(key);
if (message.isEmpty()) {
return message;
}
return performReplacements(message, replacements);
}
public String performReplacements(String message, Object... replacements) {
String result = processPositionalArgumentReplacement(message, replacements);
return processLanguageReplacements(result, replacements);
}
public Component renderMessage(String message, Object... replacements) {
MiniMessage miniMessage = MiniMessage
.builder()
.preProcessor(string -> performReplacements(string, replacements))
.build();
return miniMessage.deserialize(message);
}
private void processNamedArguments(String[] arguments, Object... replacements) {
for (int i = 0; i < arguments.length; i++) {
if (i >= replacements.length) {
continue;
}
String argument = arguments[i];
Matcher namedMatcher = NAMED_ARGUMENT_PATTERN.matcher(argument);
if (!namedMatcher.matches()) {
continue;
}
Object rawReplacement = replacements[i];
if (!(rawReplacement instanceof ReplacementProvider provider)) {
continue;
}
String replacement = parseString(provider.provideReplacement(argument));
arguments[i] = replacement;
}
}
private String processLanguageReplacements(String text, Object... replacements) {
Matcher langMatcher = LANG_PATTERN.matcher(text);
return langMatcher.replaceAll(result -> {
String langKey = result.group(1);
String rawArguments = result.group(2);
String[] arguments = VARIABLE_DELIMITER.split(rawArguments);
processNamedArguments(arguments, replacements);
String innerMessage = this.adventureLanguageManager.messageFor(langKey);
return processInnerPositionalArgumentReplacements(innerMessage, arguments);
});
}
private String processInnerPositionalArgumentReplacements(String text, String[] replacements) {
final Matcher matcher = POSITIONAL_ARGUMENT_PATTERN.matcher(text);
return matcher.replaceAll(result -> {
int position = Integer.parseInt(result.group(1));
if (position < 0 || position > replacements.length - 1) {
return "";
}
return replacements[position];
});
}
private String processPositionalArgumentReplacement(String text, Object... replacements) {
final Matcher matcher = POSITIONAL_ARGUMENT_PATTERN.matcher(text);
return matcher.replaceAll(result -> {
int position = Integer.parseInt(result.group(1));
if (position < 0 || position > replacements.length - 1) {
return "";
}
Object replacement = replacements[position];
if (!(replacement instanceof ReplacementProvider)) {
return replacement.toString();
}
return "";
});
}
private String parseString(Object replacementResult) {
if (replacementResult instanceof String s) {
return s;
}
if (replacementResult instanceof Component component) {
return MiniMessage.miniMessage().serialize(component);
}
if (replacementResult instanceof Number number) {
return NumberFormat.getNumberInstance().format(number);
}
return replacementResult.toString();
}
}
@@ -0,0 +1,51 @@
package io.github.md5sha256.areashop;
import me.wiefferink.interactivemessenger.processing.Message;
import java.util.ArrayList;
import java.util.List;
public class CompositeMessage implements MessageWrapper {
private final List<MessageWrapper> children = new ArrayList<>();
@Override
public Message toLegacyMessage() {
Message message = Message.empty();
for (MessageWrapper wrapper : children) {
message.append(wrapper.toLegacyMessage());
}
return message;
}
@Override
public String toMiniMessage(AdventureMessageRenderer messageRenderer) {
StringBuilder message = new StringBuilder();
for (MessageWrapper wrapper : children) {
message.append(wrapper.toMiniMessage(messageRenderer));
}
return message.toString();
}
public CompositeMessage appendMessage(MessageWrapper wrapper) {
children.add(wrapper);
return this;
}
public CompositeMessage appendText(String text) {
this.children.add(new TextMessage(text));
return this;
}
public CompositeMessage appendMessage(String key, boolean prefix, Object... replacements) {
this.children.add(new KeyedMessage(key, prefix, replacements));
return this;
}
public CompositeMessage appendMessage(String key, Object... replacements) {
this.children.add(new KeyedMessage(key, replacements));
return this;
}
}
@@ -0,0 +1,20 @@
package io.github.md5sha256.areashop;
import me.wiefferink.interactivemessenger.processing.Message;
public record KeyedMessage(String messageKey, boolean prefix, Object... replacements) implements MessageWrapper{
public KeyedMessage(String messageKey, Object... replacements) {
this(messageKey, false, replacements);
}
@Override
public Message toLegacyMessage() {
return Message.fromKey(messageKey).prefix(prefix).replacements(replacements);
}
@Override
public String toMiniMessage(AdventureMessageRenderer messageRenderer) {
String chatPrefix = messageRenderer.chatPrefix();
return chatPrefix + messageRenderer.renderMessageFromKey(messageKey);
}
}
@@ -0,0 +1,89 @@
package io.github.md5sha256.areashop;
import me.wiefferink.interactivemessenger.generators.TellrawGenerator;
import me.wiefferink.interactivemessenger.parsers.YamlParser;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.loader.HeaderMode;
import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class LanguageConverter {
public static void performConversion(ConfigurationNode root) throws ConfigurateException {
if (!root.isMap()) {
convertNode(root);
return;
}
Map<Object, ? extends ConfigurationNode> map = root.childrenMap();
for (Map.Entry<Object, ? extends ConfigurationNode> entry : map.entrySet()) {
ConfigurationNode node = entry.getValue();
if (node.isMap()) {
performConversion(node);
} else {
convertNode(node);
}
}
}
public static void performConversion(File toConvert, File output) throws IOException {
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
.source(() -> new BufferedReader(new FileReader(toConvert, StandardCharsets.UTF_8)))
.sink(() -> new BufferedWriter(new FileWriter(output, StandardCharsets.UTF_8)))
.headerMode(HeaderMode.PRESERVE)
.nodeStyle(NodeStyle.BLOCK)
.build();
ConfigurationNode root = loader.load();
performConversion(root);
loader.save(root);
}
public static List<String> convertRawList(List<String> messages) {
List<String> jsonMessages = TellrawGenerator.generate(YamlParser.parse(messages));
List<String> converted = new ArrayList<>();
for (String json : jsonMessages) {
BaseComponent[] bungeeComponents = ComponentSerializer.parse(json);
Component convertedComponent = BungeeComponentSerializer.get()
.deserialize(bungeeComponents);
String miniMessage = MiniMessage.miniMessage()
.serialize(convertedComponent);
converted.add(miniMessage);
}
return converted;
}
private static void convertNode(ConfigurationNode node) throws ConfigurateException {
boolean isList = node.isList();
List<String> messages;
if (isList) {
messages = node.getList(String.class, Collections.emptyList());
} else {
messages = Collections.singletonList(node.getString());
}
List<String> converted = convertRawList(messages);
if (converted.size() == 1) {
node.set(String.class, converted.get(0));
} else {
node.setList(String.class, converted);
}
}
}
@@ -0,0 +1,11 @@
package io.github.md5sha256.areashop;
import me.wiefferink.interactivemessenger.processing.Message;
public interface MessageWrapper {
Message toLegacyMessage();
String toMiniMessage(AdventureMessageRenderer messageRenderer);
}
@@ -0,0 +1,22 @@
package io.github.md5sha256.areashop;
import me.wiefferink.interactivemessenger.processing.Message;
public class TextMessage implements MessageWrapper {
private final String text;
public TextMessage(String text) {
this.text = text;
}
@Override
public Message toLegacyMessage() {
return Message.empty().append(text);
}
@Override
public String toMiniMessage(AdventureMessageRenderer messageRenderer) {
return messageRenderer.performReplacements(text);
}
}
@@ -2,10 +2,13 @@ package me.wiefferink.areashop;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.Stage;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.managers.RegionManager;
import io.github.md5sha256.areashop.AdventureMessageRenderer;
import io.github.md5sha256.areashop.LanguageConverter;
import io.papermc.lib.PaperLib;
import me.wiefferink.areashop.adapters.platform.MinecraftPlatform;
import me.wiefferink.areashop.adapters.platform.paper.PaperPlatform;
@@ -14,6 +17,7 @@ import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.listeners.PlayerLoginLogoutListener;
import me.wiefferink.areashop.managers.AdventureLanguageManager;
import me.wiefferink.areashop.managers.CommandManager;
import me.wiefferink.areashop.managers.FeatureManager;
import me.wiefferink.areashop.managers.IFileManager;
@@ -25,14 +29,13 @@ import me.wiefferink.areashop.modules.AreaShopModule;
import me.wiefferink.areashop.modules.BukkitModule;
import me.wiefferink.areashop.modules.DependencyModule;
import me.wiefferink.areashop.modules.PlatformModule;
import me.wiefferink.areashop.platform.adapter.PlatformAdapter;
import me.wiefferink.areashop.nms.NMS;
import me.wiefferink.areashop.tools.AdventureMessageBridge;
import me.wiefferink.areashop.tools.ForwardingMessageBridge;
import me.wiefferink.areashop.tools.GithubUpdateCheck;
import me.wiefferink.areashop.tools.SimpleMessageBridge;
import me.wiefferink.areashop.tools.LegacyMessageBridge;
import me.wiefferink.areashop.tools.SpigotPlatform;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.areashop.tools.version.Version;
import me.wiefferink.areashop.tools.version.VersionData;
import me.wiefferink.areashop.tools.version.VersionUtil;
import me.wiefferink.bukkitdo.Do;
import me.wiefferink.interactivemessenger.source.LanguageManager;
import net.milkbowl.vault.economy.Economy;
@@ -50,14 +53,26 @@ import org.bukkit.permissions.Permission;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.ConfigurationVisitor;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.logging.Level;
/**
* Main class for the AreaShop plugin.
@@ -73,7 +88,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
private WorldGuardInterface worldGuardInterface = null;
private WorldEditPlugin worldEdit = null;
private WorldEditInterface worldEditInterface = null;
private PlatformAdapter platformAdapter;
private NMS nms;
private MessageBridge messageBridge;
private IFileManager fileManager = null;
private LanguageManager languageManager = null;
@@ -171,38 +186,22 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
AreaShop.instance = this;
Do.init(this);
managers = new HashSet<>();
messageBridge = new SimpleMessageBridge();
messageBridge = new LegacyMessageBridge();
signErrorLogger = new SignErrorLogger(new File(getDataFolder(), signLogFile));
// Setup NMS Impl
Version currentServerVersion = VersionUtil.parseMinecraftVersion(Bukkit.getBukkitVersion());
if (currentServerVersion.versionData().isOlderThan(VersionUtil.MC_1_17_1)) {
error("Unsupported minecraft version: " + currentServerVersion + "! Minimum is 1.17.1");
String rawServerVersion = Bukkit.getServer().getClass().getPackageName();
String[] split = rawServerVersion.split("\\.");
String serverVersion = split[3];
try {
Class<?> nmsImpl = Class.forName("me.wiefferink.areashop.adapters.platform." + serverVersion + ".NMSImpl");
this.nms = nmsImpl.asSubclass(NMS.class).getConstructor().newInstance();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
error("Failed to initialize NMS implementation!");
shutdownOnError();
return;
}
if (currentServerVersion.versionData().equals(VersionUtil.MC_1_17_1)) {
try {
Class<?> adapterImpl = Class.forName("me.wiefferink.areashop.adapters.platform.legacy.LegacyPlatformAdapter");
this.platformAdapter = adapterImpl.asSubclass(PlatformAdapter.class).getConstructor().newInstance();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
error("Failed to initialize legacy PlatformAdapter implementation!");
shutdownOnError();
return;
}
} else {
try {
Class<?> adapterImpl = Class.forName("me.wiefferink.areashop.adapters.platform.modern.ModernPlatformAdapter");
this.platformAdapter = adapterImpl.asSubclass(PlatformAdapter.class).getConstructor().newInstance();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
error("Failed to initialize modern PlatformAdapter implementation!");
shutdownOnError();
return;
}
}
final MinecraftPlatform platform;
if (PaperLib.isPaper()) {
platform = new PaperPlatform(this);
@@ -211,7 +210,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
platform = new SpigotPlatform(this);
info("Detected Spigot; using the SpigotPlatform impl");
}
final PlatformModule platformModule = new PlatformModule(platform, this.platformAdapter);
final PlatformModule platformModule = new PlatformModule(platform, this.nms);
// Check if Vault is present
if(getServer().getPluginManager().getPlugin("Vault") == null) {
@@ -273,8 +272,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
return;
}
AreaShopModule asModule = new AreaShopModule(this, messageBridge,
platformAdapter, worldEditInterface, worldGuardInterface, signErrorLogger, platformModule, dependencyModule);
AreaShopModule asModule = new AreaShopModule(this, nms, worldEditInterface, worldGuardInterface, signErrorLogger, platformModule, dependencyModule);
injector = Guice.createInjector(Stage.PRODUCTION, new BukkitModule(getServer()), asModule);
// Load all data from files and check versions
@@ -287,11 +285,13 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
}
setupLanguageManager();
performLanguageMigrations();
setupNewLanguageSystem((ForwardingMessageBridge) injector.getInstance(MessageBridge.class), fileManager);
featureManager = injector.getInstance(FeatureManager.class);
featureManager.initializeFeatures(injector);
managers.add(featureManager);
signManager = injector.getInstance(SignManager.class);
signManager = new SignManager();
managers.add(signManager);
// Register the event listeners
@@ -316,18 +316,15 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
this,
"md5sha256",
"AreaShop"
).withVersionComparator((latestVersion, currentVersion) -> {
Version latest = Version.parse(cleanVersion(latestVersion));
Version current = Version.parse(cleanVersion(currentVersion));
return latest.versionData().isNewerThan(current.versionData());
}
).withVersionComparator((latestVersion, currentVersion) ->
!cleanVersion(latestVersion).equals(cleanVersion(currentVersion))
).checkUpdate(result -> {
AreaShop.debug("Update check result:", result);
if(!result.hasUpdate()) {
return;
}
AreaShop.info("Update from AreaShop V" + cleanVersion(result.getCurrentVersion()) + " to AreaShop V" + cleanVersion(result.getLatestVersion()) + " available, get the latest version at https://github.com/md5sha256/AreaShop/releases");
AreaShop.info("Update from AreaShop V" + cleanVersion(result.getCurrentVersion()) + " to AreaShop V" + cleanVersion(result.getLatestVersion()) + " available, get the latest version at https://github.com/md5sha256/releases");
for(Player player : Utils.getOnlinePlayers()) {
notifyUpdate(player);
}
@@ -411,19 +408,135 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
this.debug = debug;
}
private void performLanguageMigrations() {
boolean migrateExisting = this.getConfig().getBoolean("migrateLanguages", false);
if (!migrateExisting) {
return;
}
getLogger().info("Performing language migration");
List<String> chatPrefix = getConfig().getStringList("chatPrefix");
List<String> convertedChatPrefix = LanguageConverter.convertRawList(chatPrefix);
if (convertedChatPrefix.size() == 1) {
getConfig().set("chatPrefixMigrated", convertedChatPrefix.get(0));
} else {
getConfig().set("chatPrefixMigrated", convertedChatPrefix);
}
saveConfig();
File existingLanguages = getDataFolder().toPath().resolve(languageFolder).toFile();
File[] langFiles = existingLanguages.listFiles(file -> file.getName().endsWith(".yml"));
if (langFiles == null) {
return;
}
Path migrationPath = getDataFolder().toPath().resolve("lang-migrated");
migrationPath.toFile().mkdir();
for (File file : langFiles) {
File toMigrate = migrationPath.resolve(file.getName()).toFile();
try {
LanguageConverter.performConversion(file, toMigrate);
} catch (IOException ex) {
getLogger().log(Level.SEVERE, "Failed to perform migration for lang: " + file.getName(), ex);
}
}
getLogger().info("Language migration complete!");
}
/**
* Setup a new LanguageManager.
*/
private void setupLanguageManager() {
String language = getConfig().getString("language");
languageManager = new LanguageManager(
this,
languageFolder,
getConfig().getString("language"),
language,
"EN",
chatprefix
);
}
private void setupNewLanguageSystem(ForwardingMessageBridge messageBridge, IFileManager fileManager) {
AdventureLanguageManager languageManager = setupAdventureLanguageManager(fileManager);
AdventureMessageRenderer messageRenderer = new AdventureMessageRenderer(languageManager);
MessageBridge delegate = provideMessageBridge(fileManager, messageRenderer);
messageBridge.delegate(delegate);
}
private MessageBridge provideMessageBridge(IFileManager fileManager, AdventureMessageRenderer messageRenderer) {
YamlConfiguration config = fileManager.getConfig();
if (!config.getBoolean("useMiniMessage", false)) {
return new LegacyMessageBridge();
}
return new AdventureMessageBridge(messageRenderer);
}
private AdventureLanguageManager setupAdventureLanguageManager(IFileManager fileManager) {
YamlConfiguration config = fileManager.getConfig();
String selectedLang = config.getString("language");
String fallbackLang = "EN";
AdventureLanguageManager languageManager = new AdventureLanguageManager(selectedLang, fallbackLang);
String rawPrefix = config.getString("chatPrefixMigrated", "");
if (!rawPrefix.isEmpty()) {
languageManager.chatPrefix(rawPrefix);
}
File migratedRoot = getDataFolder().toPath().resolve("lang-migrated").toFile();
if (!migratedRoot.isDirectory()) {
return languageManager;
}
File[] langFiles = migratedRoot.listFiles(file -> file.getName().endsWith(".yml"));
if (langFiles == null) {
return languageManager;
}
for (File langFile : langFiles) {
String language = langFile.getName().substring(0, 2);
Map<String, String> values;
try {
ConfigurationNode root = YamlConfigurationLoader.builder().file(langFile).build().load();
values = loadAdventureLanguage(root);
} catch (IOException ex) {
ex.printStackTrace();
error("Failed to setup adventure language manager");
getServer().getPluginManager().disablePlugin(this);
return languageManager;
}
languageManager.loadValues(language, values);
}
return languageManager;
}
private Map<String, String> loadAdventureLanguage(ConfigurationNode root) throws ConfigurateException {
Map<String, String> values = new HashMap<>();
root.visit((ConfigurationVisitor.Stateless<ConfigurateException>)(node) -> {
if (node.isMap()) {
return;
}
Object key = node.key();
if (key == null) {
return;
}
if (node.isList()) {
List<String> list = node.getList(String.class);
if (list == null) {
return;
}
StringJoiner joiner = new StringJoiner("\n");
for (String s : list) {
joiner.add(s);
}
values.put(key.toString(),joiner.toString());
}
String message = node.getString();
if (message == null) {
return;
}
values.put(key.toString(), message);
});
return values;
}
public boolean useMiniMessage() {
return getConfig().getBoolean("useMiniMessage", false);
}
/**
* Set the chatprefix to use in the chat (loaded from config normally).
* @param chatprefix The string to use in front of chat messages (supports formatting codes)
@@ -432,8 +545,8 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
this.chatprefix = chatprefix;
}
public PlatformAdapter getPlatformAdapter() {
return platformAdapter;
public NMS getNms() {
return nms;
}
public SignErrorLogger getSignErrorLogger() {
@@ -700,6 +813,10 @@ public final class AreaShop extends JavaPlugin implements AreaShopApi {
}
}
public @NotNull MessageBridge messageBridge() {
return this.messageBridge;
}
/**
* Return the config.
@@ -1,5 +1,7 @@
package me.wiefferink.areashop;
import io.github.md5sha256.areashop.MessageWrapper;
public interface MessageBridge {
/**
* Send a message to a target without a prefix.
@@ -18,4 +20,6 @@ public interface MessageBridge {
* @param replacements The replacements to insert in the message
*/
void message(Object target, String key, Object... replacements);
void message(Object target, MessageWrapper message);
}
@@ -18,7 +18,6 @@ import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
@Singleton
public class FindCommand extends CommandAreaShop {
@@ -97,7 +96,7 @@ public class FindCommand extends CommandAreaShop {
}
if(!results.isEmpty()) {
// Draw a random one
BuyRegion region = results.get(ThreadLocalRandom.current().nextInt(results.size()));
BuyRegion region = results.get(new Random().nextInt(results.size()));
Message onlyInGroup = Message.empty();
if(group != null) {
onlyInGroup = Message.fromKey("find-onlyInGroup").replacements(args[3]);
@@ -137,7 +136,7 @@ public class FindCommand extends CommandAreaShop {
}
if(!results.isEmpty()) {
// Draw a random one
RentRegion region = results.get(ThreadLocalRandom.current().nextInt(results.size()));
RentRegion region = results.get(new Random().nextInt(results.size()));
Message onlyInGroup = Message.empty();
if(group != null) {
onlyInGroup = Message.fromKey("find-onlyInGroup").replacements(args[3]);
@@ -1,6 +1,9 @@
package me.wiefferink.areashop.commands;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import io.github.md5sha256.areashop.CompositeMessage;
import io.github.md5sha256.areashop.KeyedMessage;
import io.github.md5sha256.areashop.MessageWrapper;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
@@ -10,13 +13,13 @@ import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionGroup;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -80,11 +83,12 @@ public class InfoCommand extends CommandAreaShop {
}
});
// Header
Message limitedToGroup = Message.empty();
if(filterGroup != null) {
limitedToGroup = Message.fromKey("info-limitedToGroup").replacements(filterGroup.getName());
KeyedMessage limitedToGroup = new KeyedMessage("info-limitedToGroup", filterGroup.getName());
messageBridge.message(sender, keyHeader, limitedToGroup);
} else {
messageBridge.message(sender, keyHeader);
}
messageBridge.message(sender, keyHeader, limitedToGroup);
// Page entries
int totalPages = (int)Math.ceil(regions.size() / (double)itemsPerPage); // Clip page to correct boundaries, not much need to tell the user
if(regions.size() == itemsPerPage + 1) { // 19 total items is mapped to 1 page of 19
@@ -114,31 +118,36 @@ public class InfoCommand extends CommandAreaShop {
messageBridge.messageNoPrefix(sender, "info-entry" + state, region);
linesPrinted++;
}
Message footer = Message.empty();
CompositeMessage footer = new CompositeMessage();
// Previous button
if(page > 1) {
footer.append(Message.fromKey("info-pagePrevious").replacements(baseCommand + " " + (page - 1)));
} else {
footer.append(Message.fromKey("info-pageNoPrevious"));
}
// Page status
MessageWrapper infoPage;
if(page > 1) {
infoPage = new KeyedMessage("info-pagePrevious",
baseCommand + " " + (page - 1));
} else {
infoPage = new KeyedMessage("info-pageNoPrevious");
}
footer.appendMessage(infoPage);
// Page status
if(totalPages > 1) {
StringBuilder pageString = new StringBuilder("" + page);
for(int i = pageString.length(); i < (totalPages + "").length(); i++) {
pageString.insert(0, "0");
}
footer.append(Message.fromKey("info-pageStatus").replacements(page, totalPages));
if(page < totalPages) {
footer.append(Message.fromKey("info-pageNext").replacements(baseCommand + " " + (page + 1)));
} else {
footer.append(Message.fromKey("info-pageNoNext"));
}
// Fill up space if the page is not full (aligns header nicely)
for(int i = linesPrinted; i < maximumItems - 1; i++) {
sender.sendMessage(" ");
}
footer.send(sender);
MessageWrapper status = new KeyedMessage("info-pageStatus", page, totalPages);
footer.appendMessage(status);
MessageWrapper info;
if(page < totalPages) {
info = new KeyedMessage("info-pageNext", baseCommand + " " + (page + 1));
} else {
info = new KeyedMessage("info-pageNoNext");
}
footer.appendMessage(info);
// Fill up space if the page is not full (aligns header nicely)
String padding = " ".repeat(maximumItems - 1 - linesPrinted);
footer.appendText(padding);
}
messageBridge.message(sender, footer);
}
}
@@ -317,31 +326,36 @@ public class InfoCommand extends CommandAreaShop {
messageBridge.messageNoPrefix(sender, "info-regionInactiveUnrent", rent);
}
// Teleport
Message tp = Message.fromKey("info-prefix");
CompositeMessage tp = new CompositeMessage();
tp.appendMessage("info-prefix");
boolean foundSomething = false;
if(TeleportCommand.canUse(sender, rent)) {
foundSomething = true;
tp.append(Message.fromKey("info-regionTeleport").replacements(rent));
tp.appendMessage("info-regionTeleport", rent);
}
if(SetteleportCommand.canUse(sender, rent)) {
if(foundSomething) {
tp.append(", ");
tp.appendText(", ");
}
foundSomething = true;
tp.append(Message.fromKey("info-setRegionTeleport").replacements(rent));
tp.appendMessage("info-setRegionTeleport", rent);
}
if(foundSomething) {
tp.append(".");
tp.send(sender);
tp.appendText(".");
messageBridge.message(sender, tp);
}
// Signs
List<String> signLocations = new ArrayList<>();
for(BlockPosition location : rent.getSignsFeature().signManager().allSignLocations()) {
signLocations.add(Message.fromKey("info-regionSignLocation").replacements(location.getWorld().getName(), location.getX(), location.getY(), location.getZ()).getPlain());
}
if(!signLocations.isEmpty()) {
messageBridge.messageNoPrefix(sender, "info-regionSigns", Utils.createCommaSeparatedList(signLocations));
CompositeMessage signLocations = new CompositeMessage();
Iterator<BlockPosition> signPositions = rent.getSignsFeature().signManager().allSignLocations().iterator();
while (signPositions.hasNext()) {
BlockPosition location = signPositions.next();
MessageWrapper signInfo = new KeyedMessage("info-regionSignLocation", location.getWorld().getName(), location.getX(), location.getY(), location.getZ());
signLocations.appendMessage(signInfo);
if (signPositions.hasNext()) {
signLocations.appendText(", ");
}
}
messageBridge.message(sender, "info-regionSigns", signLocations);
// Groups
if(sender.hasPermission("areashop.groupinfo") && !rent.getGroupNames().isEmpty()) {
messageBridge.messageNoPrefix(sender, "info-regionGroups", Utils.createCommaSeparatedList(rent.getGroupNames()));
@@ -394,31 +408,35 @@ public class InfoCommand extends CommandAreaShop {
messageBridge.messageNoPrefix(sender, "info-regionInactiveSell", buy);
}
// Teleport
Message tp = Message.fromKey("info-prefix");
CompositeMessage tp = new CompositeMessage();
tp.appendMessage("info-prefix");
boolean foundSomething = false;
if(TeleportCommand.canUse(sender, buy)) {
foundSomething = true;
tp.append(Message.fromKey("info-regionTeleport").replacements(buy));
tp.appendMessage("info-regionTeleport",buy);
}
if(SetteleportCommand.canUse(sender, buy)) {
if(foundSomething) {
tp.append(", ");
tp.appendText(", ");
}
foundSomething = true;
tp.append(Message.fromKey("info-setRegionTeleport").replacements(buy));
tp.appendMessage("info-setRegionTeleport", buy);
}
if(foundSomething) {
tp.append(".");
tp.send(sender);
tp.appendText(".");
messageBridge.message(sender, tp);
}
// Signs
List<String> signLocations = new ArrayList<>();
for(BlockPosition location : buy.getSignsFeature().signManager().allSignLocations()) {
signLocations.add(Message.fromKey("info-regionSignLocation").replacements(location.getWorld().getName(), location.getX(), location.getY(), location.getZ()).getPlain());
}
if(!signLocations.isEmpty()) {
messageBridge.messageNoPrefix(sender, "info-regionSigns", Utils.createCommaSeparatedList(signLocations));
CompositeMessage signLocations = new CompositeMessage();
Iterator<BlockPosition> signPositions = buy.getSignsFeature().signManager().allSignLocations().iterator();
while (signPositions.hasNext()) {
BlockPosition location = signPositions.next();
signLocations.appendMessage("info-regionSignLocation", location.getWorld().getName(), location.getX(), location.getY(), location.getZ());
if (signPositions.hasNext()) {
signLocations.appendText(", ");
}
}
messageBridge.messageNoPrefix(sender, "info-regionSigns", signLocations);
// Groups
if(sender.hasPermission("areashop.groupinfo") && !buy.getGroupNames().isEmpty()) {
messageBridge.messageNoPrefix(sender, "info-regionGroups", Utils.createCommaSeparatedList(buy.getGroupNames()));
@@ -7,7 +7,7 @@ import io.github.bakedlibs.dough.blocks.BlockPosition;
import io.papermc.lib.PaperLib;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.managers.SignErrorLogger;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
@@ -3,7 +3,6 @@ package me.wiefferink.areashop.features.signs;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import io.github.bakedlibs.dough.blocks.ChunkPosition;
import org.bukkit.Location;
import org.bukkit.World;
import java.util.ArrayList;
import java.util.Collection;
@@ -53,9 +52,8 @@ public class SignCache {
public Optional<RegionSign> removeSign(BlockPosition position) {
RegionSign removed = this.allSigns.remove(position.getPosition());
if (removed != null) {
World world = position.getWorld();
ChunkPosition chunkPosition = new ChunkPosition(world, position.getChunkX(), position.getChunkZ());
this.signsByChunk.remove(chunkPosition.getPosition());
Location location = position.toLocation();
this.signsByChunk.remove(new ChunkPosition(location).getPosition());
// Remove the sign from the region
}
return Optional.ofNullable(removed);
@@ -10,7 +10,7 @@ import me.wiefferink.areashop.events.notify.UpdateRegionEvent;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionFactory;
@@ -36,6 +36,7 @@ import org.bukkit.event.world.ChunkLoadEvent;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -72,8 +73,8 @@ public class SignListener implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void regionUpdate(UpdateRegionEvent event) {
SignsFeature signsFeature = event.getRegion().getSignsFeature();
signsFeature.signManager().update();
Optional<SignsFeature> signsFeature = event.getRegion().getFeature(SignsFeature.class);
signsFeature.map(SignsFeature::signManager).ifPresent(SignManager::update);
}
@@ -64,11 +64,7 @@ public class SignManager extends Manager {
if (location == null || location.getWorld() == null) {
return Optional.empty();
}
return removeSign(new BlockPosition(location));
}
public Optional<RegionSign> removeSign(BlockPosition blockPosition) {
return getCacheForWorld(blockPosition.getWorld()).flatMap(cache -> cache.removeSign(blockPosition));
return getCacheForWorld(location.getWorld()).flatMap(cache -> cache.removeSign(location));
}
/**
@@ -77,10 +73,9 @@ public class SignManager extends Manager {
*/
public boolean update() {
boolean result = true;
for (SignCache signCache : this.signCacheMap.values()) {
for (RegionSign sign : signCache.allSigns()) {
result &= sign.update();
}
for (SignCache signCache : this.signCacheMap.values())
for(RegionSign sign : signCache.allSigns()) {
result &= sign.update();
}
return result;
}
@@ -9,7 +9,7 @@ import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.RegionFactory;
import javax.annotation.Nonnull;
@@ -0,0 +1,82 @@
package me.wiefferink.areashop.managers;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
public class AdventureLanguageManager {
private final Map<String, LanguageRegistry> languageRegistryMap = new HashMap<>();
private String currentLanguage;
private String fallbackLanguage;
private String chatPrefix = "";
public AdventureLanguageManager(String currentLanguage, String fallbackLanguage) {
this.currentLanguage = currentLanguage;
this.fallbackLanguage = fallbackLanguage;
}
public AdventureLanguageManager currentLanguage(@NotNull String language) {
this.currentLanguage = language;
return this;
}
public AdventureLanguageManager fallbackLanguage(@NotNull String language) {
this.fallbackLanguage = language;
return this;
}
public AdventureLanguageManager loadValues(@NotNull String language,
@NotNull Map<String, String> values) {
this.languageRegistryMap.put(language, new LanguageRegistry(values));
return this;
}
public String messageFor(String key, String lang) {
LanguageRegistry registry = this.languageRegistryMap.get(lang);
if (registry == null) {
return "";
}
return registry.messageFor(key);
}
public String messageFor(String key) {
String message = messageFor(key, this.currentLanguage);
if (message.isEmpty() && !this.currentLanguage.equals(fallbackLanguage)) {
message = messageFor(key, this.fallbackLanguage);
}
return message;
}
public void chatPrefix(String prefix) {
this.chatPrefix = prefix;
}
public String chatPrefix() {
return this.chatPrefix;
}
private static class LanguageRegistry {
private final Map<String, String> messages = new HashMap<>();
public LanguageRegistry(Map<String, String> messages) {
this.messages.putAll(messages);
}
public void messageFor(String key, String message) {
this.messages.put(key, message);
}
public String messageFor(String key) {
return this.messages.getOrDefault(key, "");
}
public boolean isEmpty() {
return this.messages.isEmpty();
}
}
}
@@ -12,8 +12,6 @@ import me.wiefferink.areashop.events.ask.AddingRegionEvent;
import me.wiefferink.areashop.events.ask.DeletingRegionEvent;
import me.wiefferink.areashop.events.notify.AddedRegionEvent;
import me.wiefferink.areashop.events.notify.DeletedRegionEvent;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.features.signs.SignsFeature;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
@@ -54,7 +52,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -80,8 +77,6 @@ public class FileManager extends Manager implements IFileManager {
private HashMap<String, Integer> versions = null;
private final String versionPath;
private final String schemFolder;
private final SignManager signManager;
private final WorldGuardInterface worldGuardInterface;
private final MessageBridge messageBridge;
private final RegionFactory regionFactory;
@@ -94,14 +89,12 @@ public class FileManager extends Manager implements IFileManager {
@Nonnull AreaShop plugin,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull MessageBridge messageBridge,
@Nonnull RegionFactory regionFactory,
@Nonnull SignManager signManager
@Nonnull RegionFactory regionFactory
) {
this.plugin = plugin;
this.worldGuardInterface = worldGuardInterface;
this.messageBridge = messageBridge;
this.regionFactory = regionFactory;
this.signManager = signManager;
regions = new HashMap<>();
buys = new HashMap<>();
rents = new HashMap<>();
@@ -124,11 +117,11 @@ public class FileManager extends Manager implements IFileManager {
public void shutdown() {
// Update lastactive time for players that are online now
for(GeneralRegion region : this.regions.values()) {
UUID ownerUuid = region.getOwner();
if (ownerUuid == null) {
if (region.getOwner() == null) {
AreaShop.warn(String.format("%s has no owner", region.getName()));
continue;
}
Player player = Bukkit.getPlayer(ownerUuid);
Player player = Bukkit.getPlayer(region.getOwner());
if(player != null) {
region.updateLastActiveTime();
}
@@ -476,11 +469,8 @@ public class FileManager extends Manager implements IFileManager {
// Delete the signs
if(region.getWorld() != null) {
SignManager regionSignManager = region.getSignsFeature().signManager();
for(BlockPosition sign : regionSignManager.allSignLocations()) {
for(BlockPosition sign : region.getSignsFeature().signManager().allSignLocations()) {
sign.getBlock().setType(Material.AIR);
regionSignManager.removeSign(sign);
this.signManager.removeSign(sign);
}
}
@@ -953,9 +943,7 @@ public class FileManager extends Manager implements IFileManager {
*/
@Override
public void loadRegionFiles() {
this.regions.clear();
this.buys.clear();
this.rents.clear();
regions.clear();
final File file = new File(regionsPath);
if(!file.exists()) {
if(!file.mkdirs()) {
@@ -1,28 +1,34 @@
package me.wiefferink.areashop.modules;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.features.FeatureFactory;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.features.signs.SignsModule;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.AdventureLanguageManager;
import me.wiefferink.areashop.managers.CommandManager;
import me.wiefferink.areashop.managers.FeatureManager;
import me.wiefferink.areashop.managers.FileManager;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignErrorLogger;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.areashop.platform.adapter.PlatformAdapter;
import me.wiefferink.areashop.nms.NMS;
import me.wiefferink.areashop.regions.ImportJobFactory;
import me.wiefferink.areashop.regions.RegionModule;
import me.wiefferink.areashop.tools.AdventureMessageBridge;
import me.wiefferink.areashop.tools.ForwardingMessageBridge;
import me.wiefferink.areashop.tools.LegacyMessageBridge;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import javax.annotation.Nonnull;
import java.io.File;
import java.util.Arrays;
public class AreaShopModule extends AbstractModule {
@@ -30,22 +36,19 @@ public class AreaShopModule extends AbstractModule {
private final AreaShop instance;
private final WorldGuardInterface worldGuardInterface;
private final WorldEditInterface worldEditInterface;
private final PlatformAdapter platformAdapter;
private final MessageBridge messageBridge;
private final NMS nms;
private final SignErrorLogger signErrorLogger;
private final AbstractModule[] extras;
public AreaShopModule(@Nonnull AreaShop instance,
@Nonnull MessageBridge messageBridge,
@Nonnull PlatformAdapter platformAdapter,
@Nonnull NMS nms,
@Nonnull WorldEditInterface worldEditInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull SignErrorLogger signErrorLogger,
@Nonnull AbstractModule... extras
) {
this.instance = instance;
this.messageBridge = messageBridge;
this.platformAdapter = platformAdapter;
this.nms = nms;
this.signErrorLogger = signErrorLogger;
this.worldEditInterface = worldEditInterface;
this.worldGuardInterface = worldGuardInterface;
@@ -57,9 +60,8 @@ public class AreaShopModule extends AbstractModule {
Arrays.stream(this.extras).forEach(this::install);
bind(Plugin.class).toInstance(this.instance);
bind(AreaShop.class).toInstance(this.instance);
bind(MessageBridge.class).toInstance(this.messageBridge);
bind(MessageBridge.class).to(ForwardingMessageBridge.class).asEagerSingleton();
bind(WorldGuardInterface.class).toInstance(this.worldGuardInterface);
bind(SignManager.class).asEagerSingleton();
bind(WorldEditInterface.class).toInstance(this.worldEditInterface);
bind(SignErrorLogger.class).toInstance(this.signErrorLogger);
// Setup managers
@@ -3,27 +3,27 @@ package me.wiefferink.areashop.modules;
import com.google.inject.AbstractModule;
import me.wiefferink.areashop.adapters.platform.MinecraftPlatform;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.platform.adapter.PlatformAdapter;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.NMS;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.jetbrains.annotations.NotNull;
public class PlatformModule extends AbstractModule {
private final MinecraftPlatform minecraftPlatform;
private final PlatformAdapter platformAdapter;
private final NMS nms;
public PlatformModule(@NotNull MinecraftPlatform platform,
@NotNull PlatformAdapter platformAdapter) {
@NotNull NMS nms) {
this.minecraftPlatform = platform;
this.platformAdapter = platformAdapter;
this.nms = nms;
}
@Override
protected void configure() {
bind(MinecraftPlatform.class).toInstance(this.minecraftPlatform);
bind(OfflinePlayerHelper.class).toInstance(this.minecraftPlatform.offlinePlayerHelper());
bind(PlatformAdapter.class).toInstance(this.platformAdapter);
bind(BlockBehaviourHelper.class).toInstance(this.platformAdapter.blockBehaviourHelper());
bind(NMS.class).toInstance(this.nms);
bind(BlockBehaviourHelper.class).toInstance(this.nms.blockBehaviourHelper());
bind(BukkitSchedulerExecutor.class).asEagerSingleton();
}
}
@@ -408,6 +408,8 @@ public class BuyRegion extends GeneralRegion {
if(r == null || !r.transactionSuccess()) {
AreaShop.warn("Something went wrong with paying '" + oldOwnerName + "' " + getFormattedPrice() + " for his resell of region " + getName() + " to " + offlinePlayer.getName());
}
// Resell is done, disable that now
disableReselling();
// Set the owner
setBuyer(offlinePlayer.getUniqueId());
@@ -419,9 +421,6 @@ public class BuyRegion extends GeneralRegion {
// Notify about updates
this.notifyAndUpdate(new ResoldRegionEvent(this, oldOwner));
// Resell is done, disable that now
disableReselling();
// Send message to the player
message(offlinePlayer, "buy-successResale", oldOwnerName);
Player seller = Bukkit.getPlayer(oldOwner);
@@ -43,7 +43,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@@ -518,8 +517,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* @return true if the player is the landlord, otherwise false
*/
public boolean isLandlord(UUID landlord) {
UUID ourLandlord = getLandlord();
return Objects.equals(landlord, ourLandlord);
return landlord != null && getLandlord() != null && getLandlord().equals(landlord);
}
/**
@@ -0,0 +1,45 @@
package me.wiefferink.areashop.tools;
import io.github.md5sha256.areashop.AdventureMessageRenderer;
import io.github.md5sha256.areashop.MessageWrapper;
import me.wiefferink.areashop.MessageBridge;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
public class AdventureMessageBridge implements MessageBridge {
private final AdventureMessageRenderer messageRenderer;
public AdventureMessageBridge(AdventureMessageRenderer messageRenderer) {
this.messageRenderer = messageRenderer;
}
@Override
public void message(Object target, MessageWrapper message) {
if (!(target instanceof Audience audience)) {
return;
}
String miniMessage = message.toMiniMessage(this.messageRenderer);
audience.sendMessage(MiniMessage.miniMessage().deserialize(miniMessage));
}
@Override
public void messageNoPrefix(Object target, String key, Object... replacements) {
if (!(target instanceof Audience audience)) {
return;
}
audience.sendMessage(this.messageRenderer.renderMessageFromKey(key, replacements));
}
@Override
public void message(Object target, String key, Object... replacements) {
if (!(target instanceof Audience audience)) {
return;
}
Component message = this.messageRenderer.renderMessageFromKey(key, replacements);
Component prefix = this.messageRenderer.renderedChatPrefix();
Component prefixedMessage = prefix.append(message);
audience.sendMessage(prefixedMessage);
}
}
@@ -0,0 +1,40 @@
package me.wiefferink.areashop.tools;
import io.github.md5sha256.areashop.MessageWrapper;
import me.wiefferink.areashop.MessageBridge;
public class ForwardingMessageBridge implements MessageBridge {
private MessageBridge delegate;
public ForwardingMessageBridge() {
}
public void delegate(MessageBridge messageBridge) {
this.delegate = messageBridge;
}
@Override
public void messageNoPrefix(Object target, String key, Object... replacements) {
if (this.delegate == null) {
return;
}
this.delegate.messageNoPrefix(target, key, replacements);
}
@Override
public void message(Object target, String key, Object... replacements) {
if (this.delegate == null) {
return;
}
this.delegate.message(target, key, replacements);
}
@Override
public void message(Object target, MessageWrapper message) {
if (this.delegate == null) {
return;
}
this.delegate.message(target, message);
}
}
@@ -20,7 +20,7 @@ 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 = "md5sha256 AreaShop GithubUpdateCheck";
public static final String USER_AGENT = "GithubUpdateCheck by NLThijs48";
public static final boolean DEBUG = false;
private final String author;
@@ -1,11 +1,13 @@
package me.wiefferink.areashop.tools;
import com.google.inject.Singleton;
import io.github.md5sha256.areashop.KeyedMessage;
import io.github.md5sha256.areashop.MessageWrapper;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.interactivemessenger.processing.Message;
@Singleton
public class SimpleMessageBridge implements MessageBridge {
public class LegacyMessageBridge implements MessageBridge {
/**
* Send a message to a target without a prefix.
@@ -15,6 +17,7 @@ public class SimpleMessageBridge implements MessageBridge {
*/
@Override
public void messageNoPrefix(Object target, String key, Object... replacements) {
unwrapMessages(replacements);
Message.fromKey(key).replacements(replacements).send(target);
}
@@ -26,7 +29,24 @@ public class SimpleMessageBridge implements MessageBridge {
*/
@Override
public void message(Object target, String key, Object... replacements) {
unwrapMessages(replacements);
Message.fromKey(key).prefix().replacements(replacements).send(target);
}
@Override
public void message(Object target, MessageWrapper message) {
message.toLegacyMessage().send(target);
}
private void unwrapMessages(Object... replacements) {
for (int i = 0; i < replacements.length; i++) {
Object repl = replacements[i];
if (repl instanceof KeyedMessage wrapper) {
replacements[i] = Message.fromKey(wrapper.messageKey())
.replacements(wrapper.replacements())
.prefix(wrapper.prefix());
}
}
}
}
@@ -1,40 +0,0 @@
package me.wiefferink.areashop.tools.version;
import javax.annotation.Nullable;
import java.util.Locale;
public enum PreReleaseType {
UNKNOWN("unknown"),
ALPHA("alpha"),
BETA("beta"),
SNAPSHOT("snapshot"),
RELEASE_CANDIDATE("rc");
private static final PreReleaseType[] VALUES = values();
private final String asString;
PreReleaseType(String asString) {
this.asString = asString;
}
@Nullable
public static PreReleaseType parse(String release) {
if (release.isEmpty()) {
return null;
}
String sanitized = release.toLowerCase(Locale.ENGLISH);
for (PreReleaseType preReleaseType : VALUES) {
if (preReleaseType.asString.equals(sanitized)) {
return preReleaseType;
}
}
return UNKNOWN;
}
public String asString() {
return this.asString;
}
}
@@ -1,54 +0,0 @@
package me.wiefferink.areashop.tools.version;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public record Version(String original, VersionData versionData) {
/**
* Semver pattern, cg1 = major, cg2 = minor, cg3 = patch, cg4 = prerelease and cg5 = buildmetadata
* Taken from https://semver.org/ and https://regex101.com/r/vkijKf/1/
*/
public static final Pattern SEMVER_PATTERN = Pattern.compile(
"^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
public static Version parse(String version) {
Matcher matcher = SEMVER_PATTERN.matcher(version);
if (!matcher.find()) {
throw new IllegalArgumentException("Invalid version: " + version);
}
String majorRaw = matcher.group(1);
String minorRaw = matcher.group(2);
String patchRaw = matcher.group(3);
String preReleaseRaw = matcher.group(4);
int major;
int minor;
try {
major = Integer.parseInt(majorRaw);
minor = Integer.parseInt(minorRaw);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException("Invalid version: " + version);
}
if (patchRaw == null || patchRaw.isEmpty()) {
return new Version(version, new VersionData(major, minor, 0, null));
}
int patch;
try {
patch = Integer.parseInt(patchRaw);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException("Invalid version: " + version);
}
if (preReleaseRaw == null || preReleaseRaw.isEmpty()) {
return new Version(version, new VersionData(major, minor, patch, null));
}
PreReleaseType releaseType = PreReleaseType.parse(preReleaseRaw);
return new Version(version, new VersionData(major, minor, patch, releaseType));
}
@Override
public String toString() {
return this.original;
}
}
@@ -1,54 +0,0 @@
package me.wiefferink.areashop.tools.version;
import org.jetbrains.annotations.NotNull;
public record VersionData(int major, int minor, int patch, PreReleaseType preReleaseType)
implements Comparable<VersionData> {
public VersionData(int major, int minor, int patch) {
this(major, minor, patch, null);
}
public VersionData(int major, int minor) {
this(major, minor, 0);
}
@Override
public String toString() {
return String.format("%d.%d.%d", major, minor, patch);
}
public boolean isNewerThan(VersionData other) {
return compareTo(other) > 0;
}
public boolean isOlderThan(VersionData other) {
return compareTo(other) < 0;
}
@Override
public int compareTo(@NotNull VersionData o) {
int majorComp = Integer.compare(this.major, o.major);
if (majorComp != 0) {
return majorComp;
}
int minorComp = Integer.compare(this.minor, o.minor);
if (minorComp != 0) {
return minorComp;
}
int patchComp = Integer.compare(this.patch, o.patch);
if (patchComp != 0) {
return patchComp;
}
if (this.preReleaseType == null && o.preReleaseType == null) {
return 0;
}
if (this.preReleaseType == null) {
return 1;
}
return this.preReleaseType.compareTo(o.preReleaseType);
}
}
@@ -1,22 +0,0 @@
package me.wiefferink.areashop.tools.version;
public class VersionUtil {
public static VersionData MC_1_17_1 = new VersionData(1, 17, 1);
public static Version parseMinecraftVersion(String minecraftVersion) {
// Expecting 1.X.X-R0.1-SNAPSHOT
int stripLength = "-R0.1-SNAPSHOT".length();
int length = minecraftVersion.length();
if (length <= stripLength) {
throw new IllegalArgumentException("Invalid minecraft version: " + minecraftVersion);
}
String strippedVersion = minecraftVersion.substring(0, length - stripLength);
try {
return Version.parse(strippedVersion);
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("Invalid minecraft version: " + minecraftVersion, ex);
}
}
}
+9
View File
@@ -13,9 +13,18 @@ chatPrefix:
- ' hover: %lang:action|Click to check the available commands|%'
- ' command: /areashop help'
- ' '
chatPrefixMigrated: ''
# The language file that should be used, check the 'lang' folder for build-in languages (use the filename without .yml here).
# More information can be found here: https://github.com/NLthijs48/AreaShop/wiki/Language-support.
language: EN
# Whether to use MiniMessage for languages
# the new lang files will be under lang-migrated
useMiniMessage: false
# Whether to migrate existing language files to adventure MiniMessage
migrateLanguages: false
# The tags that need to be written on the first line of a sign to add it to AreaShop.
signTags:
# Add a rental region.
@@ -0,0 +1,209 @@
package io.github.md5sha256.areashop;
import be.seeseemelk.mockbukkit.MockBukkit;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.interactivemessenger.generators.TellrawGenerator;
import me.wiefferink.interactivemessenger.parsers.YamlParser;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class TestLanguageConverter {
@BeforeAll
public static void setup() {
MockBukkit.mock();
}
@AfterAll
public static void teardown() {
MockBukkit.unmock();
}
private static void performTransformation(ConfigurationNode root) throws ConfigurateException {
if (!root.isMap()) {
return;
}
Map<Object, ? extends ConfigurationNode> map = root.childrenMap();
for (Map.Entry<Object, ? extends ConfigurationNode> entry : map.entrySet()) {
ConfigurationNode node = entry.getValue();
if (node.isMap()) {
performTransformation(node);
} else {
convertNode(node);
}
}
}
private static void serializeModernToBungee(ConfigurationNode node) throws ConfigurateException {
List<String> messages;
if (node.isList()) {
messages = node.getList(String.class, Collections.emptyList());
} else {
messages = Collections.singletonList(node.getString());
}
List<String> converted = new ArrayList<>(messages.size());
for (String miniMessage : messages) {
Component component = MiniMessage.miniMessage().deserialize(miniMessage);
BaseComponent[] baseComponents = BungeeComponentSerializer.get().serialize(component);
String serial = ComponentSerializer.toString(baseComponents);
converted.add(serial);
}
if (converted.size() == 1) {
node.set(converted.get(0));
} else {
node.setList(String.class, converted);
}
}
private static void convertNode(ConfigurationNode node) throws ConfigurateException {
List<String> messages;
if (node.isList()) {
messages = node.getList(String.class, Collections.emptyList());
} else {
messages = Collections.singletonList(node.getString());
}
List<String> raw = TellrawGenerator.generate(YamlParser.parse(messages));
List<String> converted = new ArrayList<>(raw.size());
for (String json : raw) {
BaseComponent[] components = ComponentSerializer.parse(json);
String serialized = ComponentSerializer.toString(components);
converted.add(serialized);
}
if (converted.size() == 1) {
node.set(converted.get(0));
} else {
node.setList(String.class, converted);
}
}
private static void compareRoot(ConfigurationNode legacy,
ConfigurationNode modern) throws ConfigurateException {
if (!legacy.isMap() && !modern.isMap()) {
return;
}
Map<Object, ? extends ConfigurationNode> map = legacy.childrenMap();
for (Map.Entry<Object, ? extends ConfigurationNode> entry : map.entrySet()) {
ConfigurationNode node = entry.getValue();
if (node.isMap()) {
compareRoot(node, modern.node(node.path()));
} else {
compare(node, modern.node(node.path()));
}
}
}
private static void compare(ConfigurationNode legacy,
ConfigurationNode modern) throws ConfigurateException {
List<String> legacyStrings;
List<String> modernStrings;
if (legacy.isList()) {
Assertions.assertTrue(modern.isList());
legacyStrings = legacy.getList(String.class, Collections.emptyList());
modernStrings = modern.getList(String.class, Collections.emptyList());
} else {
legacyStrings = Collections.singletonList(legacy.getString());
modernStrings = Collections.singletonList(modern.getString());
}
for (int i = 0; i < legacyStrings.size(); i++) {
String legacySerial = legacyStrings.get(i);
String modernSerial = modernStrings.get(i);
BaseComponent[] legacyComponents = ComponentSerializer.parse(legacySerial);
Component modernComponent = MiniMessage.miniMessage().deserialize(modernSerial);
String legacySection = LegacyComponentSerializer.legacySection().serialize(modernComponent);
Assertions.assertEquals(BaseComponent.toLegacyText(legacyComponents), legacySection);
}
}
private File[] getLangFiles() {
URL langRoot = AreaShop.class.getClassLoader().getResource("lang");
if (langRoot == null) {
throw new RuntimeException("Cannot find lang files!");
}
URI uri;
try {
uri = langRoot.toURI();
} catch (URISyntaxException ex) {
throw new RuntimeException("URI syntax!", ex);
}
File file = new File(uri);
return file.listFiles(sub -> sub.getName().endsWith(".yml"));
}
private List<ConfigurationNode> loadLangFiles() throws IOException {
File[] files = getLangFiles();
if (files == null) {
throw new RuntimeException("Could not find any lang files!");
}
List<ConfigurationNode> nodes = new ArrayList<>(files.length);
for (File langFile : files) {
ConfigurationNode node = YamlConfigurationLoader.builder()
.file(langFile)
.build()
.load();
nodes.add(node);
}
return nodes;
}
private String serializeNode(ConfigurationNode node) {
StringWriter writer = new StringWriter();
try {
YamlConfigurationLoader.builder().sink(() -> new BufferedWriter(writer)).build()
.save(node);
} catch (ConfigurateException e) {
throw new RuntimeException(e);
}
return writer.getBuffer().toString();
}
public void testConversion() {
List<ConfigurationNode> langFiles;
try {
langFiles = loadLangFiles();
} catch (IOException ex) {
Assertions.fail(ex);
return;
}
for (ConfigurationNode node : langFiles) {
ConfigurationNode legacy = node.copy();
ConfigurationNode modern = node.copy();
try {
performTransformation(legacy);
LanguageConverter.performConversion(modern);
compareRoot(legacy, modern);
} catch (IOException ex) {
Assertions.fail(ex);
break;
}
}
}
}
@@ -1,15 +0,0 @@
package me.wiefferink.areashop.adapters.platform.legacy;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.platform.adapter.PlatformAdapter;
public class LegacyPlatformAdapter implements PlatformAdapter {
private final BlockBehaviourImpl blockBehaviourHelper = new BlockBehaviourImpl();
@Override
public BlockBehaviourHelper blockBehaviourHelper() {
return this.blockBehaviourHelper;
}
}
@@ -1,6 +1,6 @@
package me.wiefferink.areashop.adapters.platform.legacy;
package me.wiefferink.areashop.adapters.platform.v1_17_R1;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.state.BlockState;
@@ -0,0 +1,15 @@
package me.wiefferink.areashop.adapters.platform.v1_17_R1;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.NMS;
public class NMSImpl implements NMS {
private final BlockBehaviourImpl blockBehaviourHelper = new BlockBehaviourImpl();
@Override
public BlockBehaviourHelper blockBehaviourHelper() {
return this.blockBehaviourHelper;
}
}
@@ -0,0 +1,21 @@
plugins.apply("io.papermc.paperweight.userdev")
dependencies {
paperDevBundle("1.18.2-R0.1-SNAPSHOT")
compileOnly(projects.areashopInterface)
compileOnly(projects.areashopNms)
}
description = "AreaShop NMS Helper 1-18"
tasks {
assemble {
dependsOn("reobfJar")
}
named("reobfJar", io.papermc.paperweight.tasks.RemapJar::class) {
outputJar.set(file("build/libs/${project.name}-${project.version}.jar"))
}
}
@@ -0,0 +1,46 @@
package me.wiefferink.areashop.adapters.platform.v1_18_R2;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock;
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
import java.util.Objects;
public class BlockBehaviourImpl implements BlockBehaviourHelper {
@Override
public boolean canPlace(Location location, BlockData blockData) {
Objects.requireNonNull(location.getWorld(), "Null World!");
final BlockPos blockPosition = new BlockPos(location.getX(), location.getY(), location.getZ());
final CraftWorld craftWorld = (CraftWorld) location.getWorld();
final ServerLevel world = craftWorld.getHandle();
final CraftBlockData craftBlockData = (CraftBlockData) blockData;
final BlockState ibd = craftBlockData.getState();
return ibd.canSurvive(world, blockPosition);
}
@Override
public boolean isBlockValid(Block block) {
final CraftBlock craftBlock = (CraftBlock) block;
final CraftWorld craftWorld = (CraftWorld) craftBlock.getWorld();
final ServerLevel world = craftWorld.getHandle();
final BlockState ibd = craftBlock.getNMS();
return ibd.canSurvive(world, craftBlock.getPosition());
}
@Override
public boolean isBlockStateValid(org.bukkit.block.BlockState blockState) {
final CraftBlockState craftBlockState = (CraftBlockState) blockState;
final BlockState ibd = craftBlockState.getHandle();
return ibd.canSurvive(craftBlockState.getBlock().getCraftWorld().getHandle(), craftBlockState.getPosition());
}
}
@@ -0,0 +1,15 @@
package me.wiefferink.areashop.adapters.platform.v1_18_R2;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.NMS;
public class NMSImpl implements NMS {
private final BlockBehaviourImpl blockBehaviourHelper = new BlockBehaviourImpl();
@Override
public BlockBehaviourHelper blockBehaviourHelper() {
return this.blockBehaviourHelper;
}
}
@@ -0,0 +1,21 @@
plugins.apply("io.papermc.paperweight.userdev")
dependencies {
paperDevBundle("1.19.4-R0.1-SNAPSHOT")
compileOnly(projects.areashopInterface)
compileOnly(projects.areashopNms)
}
description = "AreaShop NMS Helper 1-19"
tasks {
assemble {
dependsOn("reobfJar")
}
named("reobfJar", io.papermc.paperweight.tasks.RemapJar::class) {
outputJar.set(file("build/libs/${project.name}-${project.version}.jar"))
}
}
@@ -0,0 +1,46 @@
package me.wiefferink.areashop.adapters.platform.v1_19_R3;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
import java.util.Objects;
public class BlockBehaviourImpl implements BlockBehaviourHelper {
@Override
public boolean canPlace(Location location, BlockData blockData) {
Objects.requireNonNull(location.getWorld(), "Null World!");
final BlockPos blockPosition = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
final CraftWorld craftWorld = (CraftWorld) location.getWorld();
final ServerLevel world = craftWorld.getHandle();
final CraftBlockData craftBlockData = (CraftBlockData) blockData;
final BlockState ibd = craftBlockData.getState();
return ibd.canSurvive(world, blockPosition);
}
@Override
public boolean isBlockValid(Block block) {
final CraftBlock craftBlock = (CraftBlock) block;
final CraftWorld craftWorld = (CraftWorld) craftBlock.getWorld();
final ServerLevel world = craftWorld.getHandle();
final BlockState ibd = craftBlock.getNMS();
return ibd.canSurvive(world, craftBlock.getPosition());
}
@Override
public boolean isBlockStateValid(org.bukkit.block.BlockState blockState) {
final CraftBlockState craftBlockState = (CraftBlockState) blockState;
final BlockState ibd = craftBlockState.getHandle();
return ibd.canSurvive(craftBlockState.getBlock().getCraftWorld().getHandle(), craftBlockState.getPosition());
}
}
@@ -0,0 +1,15 @@
package me.wiefferink.areashop.adapters.platform.v1_19_R3;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.NMS;
public class NMSImpl implements NMS {
private final BlockBehaviourImpl blockBehaviourHelper = new BlockBehaviourImpl();
@Override
public BlockBehaviourHelper blockBehaviourHelper() {
return this.blockBehaviourHelper;
}
}
@@ -0,0 +1,21 @@
plugins.apply("io.papermc.paperweight.userdev")
dependencies {
paperDevBundle("1.20.1-R0.1-SNAPSHOT")
compileOnly(projects.areashopInterface)
compileOnly(projects.areashopNms)
}
description = "AreaShop NMS Helper 1-19"
tasks {
assemble {
dependsOn("reobfJar")
}
named("reobfJar", io.papermc.paperweight.tasks.RemapJar::class) {
outputJar.set(file("build/libs/${project.name}-${project.version}.jar"))
}
}
@@ -0,0 +1,46 @@
package me.wiefferink.areashop.adapters.platform.v1_20_R1;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
import java.util.Objects;
public class BlockBehaviourImpl implements BlockBehaviourHelper {
@Override
public boolean canPlace(Location location, BlockData blockData) {
Objects.requireNonNull(location.getWorld(), "Null World!");
final BlockPos blockPosition = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
final CraftWorld craftWorld = (CraftWorld) location.getWorld();
final ServerLevel world = craftWorld.getHandle();
final CraftBlockData craftBlockData = (CraftBlockData) blockData;
final BlockState ibd = craftBlockData.getState();
return ibd.canSurvive(world, blockPosition);
}
@Override
public boolean isBlockValid(Block block) {
final CraftBlock craftBlock = (CraftBlock) block;
final CraftWorld craftWorld = (CraftWorld) craftBlock.getWorld();
final ServerLevel world = craftWorld.getHandle();
final BlockState ibd = craftBlock.getNMS();
return ibd.canSurvive(world, craftBlock.getPosition());
}
@Override
public boolean isBlockStateValid(org.bukkit.block.BlockState blockState) {
final CraftBlockState craftBlockState = (CraftBlockState) blockState;
final BlockState ibd = craftBlockState.getHandle();
return ibd.canSurvive(craftBlockState.getBlock().getCraftWorld().getHandle(), craftBlockState.getPosition());
}
}
@@ -0,0 +1,15 @@
package me.wiefferink.areashop.adapters.platform.v1_20_R1;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.NMS;
public class NMSImpl implements NMS {
private final BlockBehaviourImpl blockBehaviourHelper = new BlockBehaviourImpl();
@Override
public BlockBehaviourHelper blockBehaviourHelper() {
return this.blockBehaviourHelper;
}
}
@@ -1,11 +0,0 @@
dependencies {
compileOnly("io.papermc.paper:paper-api:1.18.2-R0.1-SNAPSHOT")
compileOnly(projects.areashopInterface)
compileOnly(projects.areashopNms)
}
description = "AreaShop NMS Helper 1-18"
tasks {
}
@@ -1,28 +0,0 @@
package me.wiefferink.areashop.adapters.platform.modern;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import java.util.Objects;
public class BlockBehaviourImpl implements BlockBehaviourHelper {
@Override
public boolean canPlace(Location location, BlockData blockData) {
Objects.requireNonNull(location.getWorld(), "Null World!");
return location.getBlock().canPlace(blockData);
}
@Override
public boolean isBlockValid(Block block) {
return block.canPlace(block.getBlockData());
}
@Override
public boolean isBlockStateValid(BlockState blockState) {
return blockState.getBlock().canPlace(blockState.getBlockData());
}
}
@@ -1,15 +0,0 @@
package me.wiefferink.areashop.adapters.platform.modern;
import me.wiefferink.areashop.platform.adapter.BlockBehaviourHelper;
import me.wiefferink.areashop.platform.adapter.PlatformAdapter;
public class ModernPlatformAdapter implements PlatformAdapter {
private final BlockBehaviourImpl blockBehaviourHelper = new BlockBehaviourImpl();
@Override
public BlockBehaviourHelper blockBehaviourHelper() {
return this.blockBehaviourHelper;
}
}
@@ -1,4 +1,4 @@
package me.wiefferink.areashop.platform.adapter;
package me.wiefferink.areashop.nms;
import org.bukkit.Location;
import org.bukkit.block.Block;
@@ -0,0 +1,7 @@
package me.wiefferink.areashop.nms;
public interface NMS {
BlockBehaviourHelper blockBehaviourHelper();
}
@@ -1,7 +0,0 @@
package me.wiefferink.areashop.platform.adapter;
public interface PlatformAdapter {
BlockBehaviourHelper blockBehaviourHelper();
}
+1 -1
View File
@@ -12,7 +12,7 @@ plugins {
}
group = "me.wiefferink"
version = "2.7.15"
version = "2.7.13-SNAPSHOT"
java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
+4 -3
View File
@@ -27,11 +27,12 @@ include(":adapters:plugins:fastasyncworldedit")
if (!providers.environmentVariable("JITPACK").isPresent) {
include(":adapters:platform:bukkit-1-17")
include(":adapters:platform:bukkit-1-18")
include(":adapters:platform:bukkit-1-19")
include(":adapters:platform:bukkit-1-20")
}
include(":adapters:platform:bukkit-modern")
// Main project
include(":areashop")