From 9b9a31de1bfa818749d422e2c97e8d25169eefd3 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sat, 12 Nov 2022 17:44:15 -0500 Subject: [PATCH 01/59] Allow running "commands" that aren't registered --- .../spigot/common/handler/SpigotHandler.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java index 14ea2148..57403ae9 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java @@ -125,7 +125,6 @@ public void unregisterPermission(String key) { @Override public void dispatchCommand(DispatchableCommand command) { - Logger.get().debug("Executing [" + command + "] as console"); server.dispatchCommand(console, command.getCommand()); } @@ -154,18 +153,24 @@ private void dispatchCommand(Player player, DispatchableCommand command) { // only temporarily op the player if the command requires op and the player is not opped player.setOp(true); try { - server.dispatchCommand(player, command.getCommand()); + chatCommand(player, command.getCommand()); } finally { player.setOp(false); // ensure player is deopped even if the command dispatch throws an exception } } else { - server.dispatchCommand(player, command.getCommand()); + chatCommand(player, command.getCommand()); } } else { server.dispatchCommand(console, command.getCommand()); } } + private void chatCommand(Player player, String command) { + // https://github.com/kejonaMC/CrossplatForms/issues/129 + // Using chat makes it so that "commands" that are not registered can still be run. + player.chat('/' + command); + } + @EventHandler(priority = EventPriority.LOWEST) // Same as DeluxeMenus public void onPreProcessCommand(PlayerCommandPreprocessEvent event) { String input = event.getMessage().substring(1); // remove command slash From 0ad221ea3cad00d3bf160c03b62e00fe5ad9dca9 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sat, 12 Nov 2022 23:47:31 -0500 Subject: [PATCH 02/59] Optimize permission registration --- .../accessitem/AccessItemRegistry.java | 33 +++---- .../bungeecord/CrossplatFormsBungeeCord.java | 12 ++- .../bungeecord/handler/BungeeCordHandler.java | 8 +- core/build.gradle.kts | 4 + .../kejona/crossplatforms/CrossplatForms.java | 8 +- .../crossplatforms/handler/ServerHandler.java | 11 --- .../bedrock/BedrockFormRegistry.java | 39 ++++---- .../interfacing/java/JavaMenuRegistry.java | 39 ++++---- .../permission/EmptyPermissions.java | 17 ++++ .../permission}/LuckPermsHook.java | 37 ++++---- .../permission/Permissions.java | 16 ++++ .../dev/kejona/crossplatforms/TestModule.java | 10 --- proxy/build.gradle.kts | 1 - .../crossplatforms/proxy/PermissionHook.java | 23 ----- .../crossplatforms/proxy/ProxyHandler.java | 30 ------- .../spigot/common/SpigotAccessItemsBase.java | 6 +- .../spigot/common/SpigotBase.java | 19 +++- .../spigot/common/handler/SpigotHandler.java | 35 +------- .../common/handler/SpigotPermissions.java | 89 +++++++++++++++++++ .../spigot/CrossplatFormsSpigotLegacy.java | 4 +- .../spigot/LegacySpigotAccessItems.java | 7 +- spigot-legacy/src/main/resources/plugin.yml | 2 + .../spigot/CrossplatFormsSpigot.java | 4 +- .../spigot/SpigotAccessItems.java | 6 +- spigot/src/main/resources/plugin.yml | 1 + .../velocity/CrossplatFormsVelocity.java | 11 ++- .../velocity/handler/VelocityHandler.java | 8 +- 27 files changed, 250 insertions(+), 230 deletions(-) create mode 100644 core/src/main/java/dev/kejona/crossplatforms/permission/EmptyPermissions.java rename {proxy/src/main/java/dev/kejona/crossplatforms/proxy => core/src/main/java/dev/kejona/crossplatforms/permission}/LuckPermsHook.java (61%) create mode 100644 core/src/main/java/dev/kejona/crossplatforms/permission/Permissions.java delete mode 100644 proxy/src/main/java/dev/kejona/crossplatforms/proxy/PermissionHook.java delete mode 100644 proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProxyHandler.java create mode 100644 spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPermissions.java diff --git a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/AccessItemRegistry.java b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/AccessItemRegistry.java index 404f7b22..5209fe87 100644 --- a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/AccessItemRegistry.java +++ b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/AccessItemRegistry.java @@ -3,9 +3,9 @@ import dev.kejona.crossplatforms.config.ConfigManager; import dev.kejona.crossplatforms.handler.FormPlayer; -import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.permission.Permission; import dev.kejona.crossplatforms.permission.PermissionDefault; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.reloadable.Reloadable; import dev.kejona.crossplatforms.reloadable.ReloadableRegistry; import lombok.Getter; @@ -15,12 +15,17 @@ import javax.annotation.Nullable; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; public abstract class AccessItemRegistry implements Reloadable { private final ConfigManager configManager; - private final ServerHandler serverHandler; + private final Permissions permissions; + + @Getter + private final Map items = new HashMap<>(); @Getter private boolean enabled = false; @@ -35,12 +40,9 @@ public abstract class AccessItemRegistry implements Reloadable { @Getter private Map globalPermissionDefaults = Collections.emptyMap(); - @Getter - private final Map items = new HashMap<>(); - - public AccessItemRegistry(ConfigManager configManager, ServerHandler serverHandler) { + public AccessItemRegistry(ConfigManager configManager, Permissions permissions) { this.configManager = configManager; - this.serverHandler = serverHandler; + this.permissions = permissions; ReloadableRegistry.register(this); load(); } @@ -63,30 +65,23 @@ private void load() { setHeldSlot = config.isSetHeldSlot(); globalPermissionDefaults = config.getGlobalPermissionDefaults(); + Set permissions = new HashSet<>(); + for (String identifier : config.getItems().keySet()) { AccessItem item = config.getItems().get(identifier); items.put(identifier, item); // Register permissions with the server item.generatePermissions(this); - for (Permission entry : item.getPermissions().values()) { - serverHandler.registerPermission(entry); - } + permissions.addAll(item.getPermissions().values()); } + + this.permissions.registerPermissions(permissions); } } @Override public boolean reload() { - // Unregister permissions - if (enabled) { - for (AccessItem accessItem : items.values()) { - for (Permission permission : accessItem.getPermissions().values()) { - serverHandler.unregisterPermission(permission.key()); - } - } - } - load(); return true; } diff --git a/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/CrossplatFormsBungeeCord.java b/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/CrossplatFormsBungeeCord.java index f7644bad..3be75311 100644 --- a/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/CrossplatFormsBungeeCord.java +++ b/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/CrossplatFormsBungeeCord.java @@ -18,9 +18,9 @@ import dev.kejona.crossplatforms.handler.Placeholders; import dev.kejona.crossplatforms.interfacing.Interfacer; import dev.kejona.crossplatforms.interfacing.NoMenusInterfacer; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.proxy.CloseMenuAction; -import dev.kejona.crossplatforms.proxy.LuckPermsHook; -import dev.kejona.crossplatforms.proxy.PermissionHook; +import dev.kejona.crossplatforms.permission.LuckPermsHook; import dev.kejona.crossplatforms.proxy.ProtocolizeInterfacer; import net.kyori.adventure.platform.bungeecord.BungeeAudiences; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; @@ -54,11 +54,8 @@ public void onEnable() { metrics = new Metrics(this, BSTATS_ID); audiences = BungeeAudiences.create(this); - BungeeCordHandler serverHandler = new BungeeCordHandler( - this, - audiences, - pluginPresent("LuckPerms") ? new LuckPermsHook() : PermissionHook.empty() - ); + BungeeCordHandler serverHandler = new BungeeCordHandler(this, audiences); + Permissions permissions = pluginPresent("LuckPerms") ? new LuckPermsHook() : Permissions.empty(); BungeeCommandManager commandManager; try { @@ -83,6 +80,7 @@ public void onEnable() { logger, getDataFolder().toPath(), serverHandler, + permissions, "formsb", commandManager, placeholders, diff --git a/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/handler/BungeeCordHandler.java b/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/handler/BungeeCordHandler.java index 5b8aa9ae..99a4640d 100644 --- a/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/handler/BungeeCordHandler.java +++ b/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/handler/BungeeCordHandler.java @@ -6,11 +6,10 @@ import dev.kejona.crossplatforms.command.CommandType; import dev.kejona.crossplatforms.command.DispatchableCommand; import dev.kejona.crossplatforms.command.custom.InterceptCommand; +import dev.kejona.crossplatforms.command.custom.InterceptCommandCache; import dev.kejona.crossplatforms.handler.BedrockHandler; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.handler.ServerHandler; -import dev.kejona.crossplatforms.proxy.PermissionHook; -import dev.kejona.crossplatforms.proxy.ProxyHandler; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.platform.bungeecord.BungeeAudiences; import net.md_5.bungee.api.CommandSender; @@ -29,7 +28,7 @@ import java.util.UUID; import java.util.stream.Stream; -public class BungeeCordHandler extends ProxyHandler implements ServerHandler, Listener { +public class BungeeCordHandler extends InterceptCommandCache implements ServerHandler, Listener { private static final String OP_GROUP = "op"; @@ -38,8 +37,7 @@ public class BungeeCordHandler extends ProxyHandler implements ServerHandler, Li private final BungeeAudiences audiences; private final CommandSender console; - public BungeeCordHandler(Plugin plugin, BungeeAudiences audiences, PermissionHook permissionHook) { - super(permissionHook); + public BungeeCordHandler(Plugin plugin, BungeeAudiences audiences) { this.server = plugin.getProxy(); this.pluginManager = server.getPluginManager(); this.audiences = audiences; diff --git a/core/build.gradle.kts b/core/build.gradle.kts index b032a130..af6f1986 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -27,6 +27,10 @@ dependencies { exclude(group = "com.google.code.gson", module = "gson") } + compileOnly("net.luckperms:api:5.4") { + isTransitive = false + } + api("cloud.commandframework:cloud-core:1.7.1") api("cloud.commandframework:cloud-minecraft-extras:1.7.1") api("net.kyori:adventure-api:4.11.0") diff --git a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java index 85faa9a1..f75147bf 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java +++ b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java @@ -29,6 +29,7 @@ import dev.kejona.crossplatforms.interfacing.bedrock.custom.ComponentSerializer; import dev.kejona.crossplatforms.interfacing.bedrock.custom.CustomComponent; import dev.kejona.crossplatforms.interfacing.java.JavaMenuRegistry; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.reloadable.ReloadableRegistry; import lombok.Getter; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -48,6 +49,7 @@ public class CrossplatForms { private final ConfigManager configManager; private final ServerHandler serverHandler; + private final Permissions permissions; private final BedrockHandler bedrockHandler; private final boolean bedrockSupport; @@ -65,6 +67,7 @@ public class CrossplatForms { public CrossplatForms(Logger logger, Path dataFolder, ServerHandler serverHandler, + Permissions permissions, String defaultCommand, CommandManager commandManager, Placeholders placeholders, @@ -75,6 +78,7 @@ public CrossplatForms(Logger logger, } INSTANCE = this; this.serverHandler = serverHandler; + this.permissions = permissions; this.commandManager = commandManager; this.placeholders = placeholders; ReloadableRegistry.clear(); @@ -137,8 +141,8 @@ public CrossplatForms(Logger logger, // Load forms and menus from the configs into registries long registryTime = System.currentTimeMillis(); interfacer.load( - new BedrockFormRegistry(configManager, serverHandler), - new JavaMenuRegistry(configManager, serverHandler) + new BedrockFormRegistry(configManager, permissions), + new JavaMenuRegistry(configManager, permissions) ); logger.debug("Took " + (System.currentTimeMillis() - registryTime) + "ms to setup registries."); diff --git a/core/src/main/java/dev/kejona/crossplatforms/handler/ServerHandler.java b/core/src/main/java/dev/kejona/crossplatforms/handler/ServerHandler.java index 85d5c263..35074d2c 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/handler/ServerHandler.java +++ b/core/src/main/java/dev/kejona/crossplatforms/handler/ServerHandler.java @@ -5,8 +5,6 @@ import dev.kejona.crossplatforms.command.DispatchableCommand; import dev.kejona.crossplatforms.command.custom.CustomCommand; import dev.kejona.crossplatforms.command.custom.InterceptCommand; -import dev.kejona.crossplatforms.permission.Permission; -import dev.kejona.crossplatforms.permission.PermissionDefault; import net.kyori.adventure.audience.Audience; import javax.annotation.Nonnull; @@ -54,15 +52,6 @@ default Stream getPlayerNames() { boolean isGeyserEnabled(); boolean isFloodgateEnabled(); - // todo: move permission stuff to a separate interface. easier for hooking into plugins such as LuckPerms - void registerPermission(String key, @Nullable String description, PermissionDefault def); - - default void registerPermission(Permission permission) { - registerPermission(permission.key(), permission.description(), permission.defaultPermission()); - } - - void unregisterPermission(String key); - /** * Execute a command as the server console * @param command The command string to execute diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockFormRegistry.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockFormRegistry.java index f1f10ec7..6c6aa95f 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockFormRegistry.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockFormRegistry.java @@ -2,32 +2,35 @@ import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.config.ConfigManager; -import dev.kejona.crossplatforms.handler.ServerHandler; -import dev.kejona.crossplatforms.interfacing.Interface; import dev.kejona.crossplatforms.permission.Permission; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.reloadable.Reloadable; import dev.kejona.crossplatforms.reloadable.ReloadableRegistry; import lombok.Getter; import javax.annotation.Nullable; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; -@Getter public class BedrockFormRegistry implements Reloadable { + private final ConfigManager configManager; + private final Permissions permissions; + + @Getter + private final Map forms = new HashMap<>(); + /** * If bedrock forms are enabled. may be false if disabled in the config or if all forms failed to load. */ + @Getter private boolean enabled = false; - private final Map forms = new HashMap<>(); - - private final ConfigManager configManager; - private final ServerHandler serverHandler; - public BedrockFormRegistry(ConfigManager configManager, ServerHandler serverHandler) { + public BedrockFormRegistry(ConfigManager configManager, Permissions permissions) { this.configManager = configManager; - this.serverHandler = serverHandler; + this.permissions = permissions; ReloadableRegistry.register(this); load(); } @@ -44,30 +47,22 @@ private void load() { FormConfig config = configManager.getConfig(FormConfig.class).get(); enabled = config.isEnable(); if (enabled) { + Set permissions = new HashSet<>(); + for (String identifier : config.getForms().keySet()) { BedrockForm form = config.getForms().get(identifier); forms.put(identifier, form); form.generatePermissions(config); - for (Permission entry : form.getPermissions().values()) { - serverHandler.registerPermission(entry); - } + permissions.addAll(form.getPermissions().values()); } + + this.permissions.registerPermissions(permissions); } } @Override public boolean reload() { - - // Unregister permissions - if (enabled) { - for (Interface form : forms.values()) { - for (Permission permission : form.getPermissions().values()) { - serverHandler.unregisterPermission(permission.key()); - } - } - } - load(); return true; } diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenuRegistry.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenuRegistry.java index ed62e952..f3502900 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenuRegistry.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenuRegistry.java @@ -2,32 +2,36 @@ import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.config.ConfigManager; -import dev.kejona.crossplatforms.handler.ServerHandler; -import dev.kejona.crossplatforms.interfacing.Interface; import dev.kejona.crossplatforms.permission.Permission; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.reloadable.Reloadable; import dev.kejona.crossplatforms.reloadable.ReloadableRegistry; import lombok.Getter; import javax.annotation.Nullable; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; -@Getter public class JavaMenuRegistry implements Reloadable { + + private final ConfigManager configManager; + private final Permissions permissions; + + @Getter + private final Map menus = new HashMap<>(); + /** * If java menus are enabled. may be false if disabled in the config or if all forms failed to load. */ + @Getter private boolean enabled = false; - private final Map menus = new HashMap<>(); - - private final ConfigManager configManager; - private final ServerHandler serverHandler; - public JavaMenuRegistry(ConfigManager configManager, ServerHandler serverHandler) { + public JavaMenuRegistry(ConfigManager configManager, Permissions permissions) { this.configManager = configManager; - this.serverHandler = serverHandler; + this.permissions = permissions; ReloadableRegistry.register(this); load(); } @@ -44,29 +48,22 @@ private void load() { MenuConfig config = configManager.getConfig(MenuConfig.class).get(); enabled = config.isEnable(); if (enabled) { + Set permissions = new HashSet<>(); + for (String identifier : config.getMenus().keySet()) { JavaMenu menu = config.getMenus().get(identifier); menus.put(identifier, menu); menu.generatePermissions(config); - for (Permission entry : menu.getPermissions().values()) { - serverHandler.registerPermission(entry); - } + permissions.addAll(menu.getPermissions().values()); } + + this.permissions.registerPermissions(permissions); } } @Override public boolean reload() { - // Unregister permissions - if (enabled) { - for (Interface menu : menus.values()) { - for (Permission permission : menu.getPermissions().values()) { - serverHandler.unregisterPermission(permission.key()); - } - } - } - load(); return true; } diff --git a/core/src/main/java/dev/kejona/crossplatforms/permission/EmptyPermissions.java b/core/src/main/java/dev/kejona/crossplatforms/permission/EmptyPermissions.java new file mode 100644 index 00000000..3702ddee --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/permission/EmptyPermissions.java @@ -0,0 +1,17 @@ +package dev.kejona.crossplatforms.permission; + +import java.util.Collection; + +class EmptyPermissions implements Permissions { + + static Permissions INSTANCE = new EmptyPermissions(); + + private EmptyPermissions() { + + } + + @Override + public void registerPermissions(Collection permissions) { + + } +} diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/LuckPermsHook.java b/core/src/main/java/dev/kejona/crossplatforms/permission/LuckPermsHook.java similarity index 61% rename from proxy/src/main/java/dev/kejona/crossplatforms/proxy/LuckPermsHook.java rename to core/src/main/java/dev/kejona/crossplatforms/permission/LuckPermsHook.java index 8c5d6bc8..48836f09 100644 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/LuckPermsHook.java +++ b/core/src/main/java/dev/kejona/crossplatforms/permission/LuckPermsHook.java @@ -1,17 +1,17 @@ -package dev.kejona.crossplatforms.proxy; +package dev.kejona.crossplatforms.permission; import dev.kejona.crossplatforms.Logger; -import dev.kejona.crossplatforms.permission.PermissionDefault; import net.luckperms.api.LuckPermsProvider; import net.luckperms.api.model.group.Group; import net.luckperms.api.model.group.GroupManager; import net.luckperms.api.node.types.PermissionNode; import net.luckperms.api.node.types.WeightNode; -import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; -public class LuckPermsHook implements PermissionHook { +public class LuckPermsHook implements Permissions { private static final String DEFAULT_NAME = "default"; private static final WeightNode DEFAULT_WEIGHT = WeightNode.builder(0).build(); @@ -20,16 +20,10 @@ public class LuckPermsHook implements PermissionHook { private final Logger logger = Logger.get(); @Override - public void registerPermission(String key, @Nullable String description, PermissionDefault def) { + public void registerPermissions(Collection permissions) { groupManager.loadGroup(DEFAULT_NAME).thenAcceptAsync(defaultGroup -> { Group group = defaultGroup.orElse(null); if (group == null) { - if (def == PermissionDefault.OP) { - // We clear any permissions with a default of OP. - // If the group doesn't exist, there is nothing to clear. - return; - } - try { group = groupManager.createAndLoadGroup(DEFAULT_NAME).get(); group.data().add(DEFAULT_WEIGHT); @@ -41,19 +35,26 @@ public void registerPermission(String key, @Nullable String description, Permiss } } - clearPermission(group, key); - if (def != PermissionDefault.OP) { - // we simply clear for OP. TRUE and FALSE should have any existing permissions with the same key - // cleared and then re-added with the correct values - setPermission(group, key, def.asBoolean()); + // Clear existing keys + clearPermissions(group, permissions.stream().map(Permission::key).collect(Collectors.toSet())); + + logger.debug("Registering permissions to LP:"); + for (Permission perm : permissions) { + String key = perm.key(); + PermissionDefault def = perm.defaultPermission(); + + logger.debug("\t" + key + " : " + def); + if (def != PermissionDefault.OP) { + setPermission(group, perm.key(), def.asBoolean()); + } } groupManager.saveGroup(group); }); } - private void clearPermission(Group group, String key) { - group.data().clear(node -> node.getKey().equals(key)); + private void clearPermissions(Group group, Collection keys) { + group.data().clear(node -> keys.contains(node.getKey())); } private void setPermission(Group group, String key, boolean value) { diff --git a/core/src/main/java/dev/kejona/crossplatforms/permission/Permissions.java b/core/src/main/java/dev/kejona/crossplatforms/permission/Permissions.java new file mode 100644 index 00000000..291b18e8 --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/permission/Permissions.java @@ -0,0 +1,16 @@ +package dev.kejona.crossplatforms.permission; + +import java.util.Collection; + +public interface Permissions { + + void registerPermissions(Collection permissions); + + default void notifyPluginLoaded() { + + } + + static Permissions empty() { + return EmptyPermissions.INSTANCE; + } +} diff --git a/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java b/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java index 6205174d..ef201377 100644 --- a/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java +++ b/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java @@ -68,16 +68,6 @@ public boolean isFloodgateEnabled() { return false; } - @Override - public void registerPermission(String key, @Nullable String description, PermissionDefault def) { - - } - - @Override - public void unregisterPermission(String key) { - - } - @Override public void dispatchCommand(DispatchableCommand command) { diff --git a/proxy/build.gradle.kts b/proxy/build.gradle.kts index d6f2d17c..12f20b5d 100644 --- a/proxy/build.gradle.kts +++ b/proxy/build.gradle.kts @@ -3,6 +3,5 @@ description = "proxy" dependencies { compileOnly("dev.simplix:protocolize-api:2.1.2") - compileOnly("net.luckperms:api:5.4") compileOnly(projects.core) } diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/PermissionHook.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/PermissionHook.java deleted file mode 100644 index 56727fc0..00000000 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/PermissionHook.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.kejona.crossplatforms.proxy; - -import dev.kejona.crossplatforms.permission.PermissionDefault; -import org.jetbrains.annotations.Nullable; - -public interface PermissionHook { - - static PermissionHook empty() { - return Empty.INSTANCE; - } - - void registerPermission(String key, @Nullable String description, PermissionDefault def); - - final class Empty implements PermissionHook { - - private static final PermissionHook INSTANCE = new Empty(); - - @Override - public void registerPermission(String key, @Nullable String description, PermissionDefault def) { - //no-op - } - } -} diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProxyHandler.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProxyHandler.java deleted file mode 100644 index ab7ce18f..00000000 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProxyHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package dev.kejona.crossplatforms.proxy; - -import dev.kejona.crossplatforms.Logger; -import dev.kejona.crossplatforms.command.custom.InterceptCommandCache; -import dev.kejona.crossplatforms.handler.ServerHandler; -import dev.kejona.crossplatforms.permission.PermissionDefault; -import org.jetbrains.annotations.Nullable; - -public abstract class ProxyHandler extends InterceptCommandCache implements ServerHandler { - - private final PermissionHook permissionHook; - - public ProxyHandler(PermissionHook permissionHook) { - this.permissionHook = permissionHook; - if (permissionHook instanceof PermissionHook.Empty) { - Logger.get().warn("Install LuckPerms in order for permission defaults to take effect."); - } - } - - @Override - public void registerPermission(String key, @Nullable String description, PermissionDefault def) { - permissionHook.registerPermission(key, description, def); - } - - @Override - public void unregisterPermission(String key) { - // this will only have to be implemented if we had a hook for some permission system that - // complains about registering the same permission twice - } -} diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItemsBase.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItemsBase.java index 27fed96d..aa5e696b 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItemsBase.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItemsBase.java @@ -7,8 +7,8 @@ import dev.kejona.crossplatforms.handler.BedrockHandler; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.handler.Placeholders; -import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.interfacing.Interfacer; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.spigot.common.handler.SpigotPlayer; import lombok.AllArgsConstructor; import org.bukkit.Bukkit; @@ -53,11 +53,11 @@ public abstract class SpigotAccessItemsBase extends AccessItemRegistry implement public SpigotAccessItemsBase(JavaPlugin plugin, ConfigManager configManager, - ServerHandler serverHandler, + Permissions permissions, Interfacer interfacer, BedrockHandler bedrockHandler, Placeholders placeholders) { - super(configManager, serverHandler); + super(configManager, permissions); this.interfacer = interfacer; this.bedrockHandler = bedrockHandler; this.placeholders = placeholders; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java index 3e51fe1f..371d18f6 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java @@ -18,11 +18,13 @@ import dev.kejona.crossplatforms.config.ConfigManager; import dev.kejona.crossplatforms.handler.BasicPlaceholders; import dev.kejona.crossplatforms.handler.Placeholders; -import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.interfacing.Interfacer; +import dev.kejona.crossplatforms.permission.LuckPermsHook; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.spigot.common.handler.PlaceholderAPIHandler; import dev.kejona.crossplatforms.spigot.common.handler.SpigotCommandOrigin; import dev.kejona.crossplatforms.spigot.common.handler.SpigotHandler; +import dev.kejona.crossplatforms.spigot.common.handler.SpigotPermissions; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -63,7 +65,9 @@ public void onEnable() { metrics = new Metrics(this, METRICS_ID); server = getServer(); audiences = BukkitAudiences.create(this); - ServerHandler serverHandler = new SpigotHandler(this, audiences); + + SpigotHandler serverHandler = new SpigotHandler(this, audiences); + Permissions permissions = pluginEnabled("LuckPerms") ? new LuckPermsHook() : new SpigotPermissions(this); convertGeyserHubConfig(); @@ -106,6 +110,7 @@ public void onEnable() { logger, getDataFolder().toPath(), serverHandler, + permissions, "forms", commandManager, placeholders, @@ -116,12 +121,14 @@ public void onEnable() { return; } - SpigotAccessItemsBase accessItems = accessItems(crossplatForms); + SpigotAccessItemsBase accessItems = createAccessItems(crossplatForms); server.getPluginManager().registerEvents(accessItems, this); // Commands added by access items new GiveCommand(crossplatForms, accessItems).register(commandManager, crossplatForms.getCommandBuilder()); new InspectItemCommand(crossplatForms, accessItems).register(commandManager, crossplatForms.getCommandBuilder()); + + permissions.notifyPluginLoaded(); } @Override @@ -154,6 +161,10 @@ public void addCustomChart(CustomChart chart) { metrics.addCustomChart(chart); } + public boolean pluginEnabled(String id) { + return server.getPluginManager().isPluginEnabled(id); + } + private void convertGeyserHubConfig() { File selector = new File(getDataFolder(), "selector.yml"); if (selector.exists()) { @@ -172,7 +183,7 @@ private void convertGeyserHubConfig() { public abstract boolean attemptBrigadier(); - public abstract SpigotAccessItemsBase accessItems(CrossplatForms crossplatForms); + public abstract SpigotAccessItemsBase createAccessItems(CrossplatForms crossplatForms); public static SpigotBase getInstance() { return INSTANCE; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java index 57403ae9..3273accd 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java @@ -1,7 +1,6 @@ package dev.kejona.crossplatforms.spigot.common.handler; import dev.kejona.crossplatforms.CrossplatForms; -import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.command.CommandOrigin; import dev.kejona.crossplatforms.command.CommandType; import dev.kejona.crossplatforms.command.DispatchableCommand; @@ -12,6 +11,7 @@ import dev.kejona.crossplatforms.handler.ServerHandler; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; @@ -20,12 +20,9 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.permissions.Permission; -import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.java.JavaPlugin; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.List; import java.util.UUID; import java.util.stream.Stream; @@ -97,32 +94,6 @@ public boolean isFloodgateEnabled() { return server.getPluginManager().isPluginEnabled("floodgate"); } - @Override - public void registerPermission(String key, @Nullable String description, dev.kejona.crossplatforms.permission.PermissionDefault def) { - ensurePrimaryThread(); - PermissionDefault perm; - switch (def) { - case TRUE: - perm = PermissionDefault.TRUE; - break; - case OP: - perm = PermissionDefault.OP; - break; - default: - perm = PermissionDefault.FALSE; - break; - } - - Logger.get().debug("Registering permission " + key + " : " + perm); - server.getPluginManager().addPermission(new Permission(key, description, perm)); - } - - @Override - public void unregisterPermission(String key) { - ensurePrimaryThread(); - server.getPluginManager().removePermission(new Permission(key)); - } - @Override public void dispatchCommand(DispatchableCommand command) { server.dispatchCommand(console, command.getCommand()); @@ -198,8 +169,8 @@ public void executeSafely(Runnable runnable) { server.getScheduler().runTask(plugin, runnable); } - private void ensurePrimaryThread() { - if (!server.isPrimaryThread()) { + public static void ensurePrimaryThread() { + if (!Bukkit.isPrimaryThread()) { throw new IllegalStateException("Method not called from primary thread, instead: " + Thread.currentThread()); } } diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPermissions.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPermissions.java new file mode 100644 index 00000000..592ac587 --- /dev/null +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPermissions.java @@ -0,0 +1,89 @@ +package dev.kejona.crossplatforms.spigot.common.handler; + +import dev.kejona.crossplatforms.Logger; +import dev.kejona.crossplatforms.permission.Permission; +import dev.kejona.crossplatforms.permission.PermissionDefault; +import dev.kejona.crossplatforms.permission.Permissions; +import lombok.RequiredArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.Queue; + +@RequiredArgsConstructor +public class SpigotPermissions implements Permissions { + + private final JavaPlugin plugin; + private final Server server = Bukkit.getServer(); + + private boolean booting = true; + + protected void registerPermission(Permission permission) { + org.bukkit.permissions.Permission perm = toBukkit(permission); + Logger.get().debug("Registering permission " + perm.getName() + " : " + perm.getDefault()); + server.getPluginManager().removePermission(perm); + server.getPluginManager().addPermission(perm); + } + + @Override + public void registerPermissions(Collection permissions) { + SpigotHandler.ensurePrimaryThread(); + if (permissions.isEmpty()) { + return; + } + + if (booting) { + // Server hasn't started yet, just block until we are done + for (Permission perm : permissions) { + registerPermission(perm); + } + } else { + // Register a handful of permissions every tick: https://github.com/kejonaMC/CrossplatForms/issues/128 + new RegisterTask(permissions).runTaskTimer(plugin, 1L, 1L); + } + } + + @Override + public void notifyPluginLoaded() { + booting = false; + } + + public static org.bukkit.permissions.Permission toBukkit(Permission p) { + return new org.bukkit.permissions.Permission(p.key(), p.description(), toBukkit(p.defaultPermission())); + } + + public static org.bukkit.permissions.PermissionDefault toBukkit(PermissionDefault def) { + switch (def) { + case TRUE: + return org.bukkit.permissions.PermissionDefault.TRUE; + case OP: + return org.bukkit.permissions.PermissionDefault.OP; + default: + return org.bukkit.permissions.PermissionDefault.FALSE; + } + } + + class RegisterTask extends BukkitRunnable { + + private final Queue queue; + + public RegisterTask(Collection permissions) { + queue = new LinkedList<>(permissions); + } + + @Override + public void run() { + for (int i = 0; i < 5 && !queue.isEmpty(); i++) { + registerPermission(queue.remove()); + } + + if (queue.isEmpty()) { + cancel(); + } + } + } +} diff --git a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigotLegacy.java b/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigotLegacy.java index 5a33eb11..a34bf63a 100644 --- a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigotLegacy.java +++ b/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigotLegacy.java @@ -19,11 +19,11 @@ public boolean attemptBrigadier() { } @Override - public SpigotAccessItemsBase accessItems(CrossplatForms crossplatForms) { + public SpigotAccessItemsBase createAccessItems(CrossplatForms crossplatForms) { return new LegacySpigotAccessItems( this, crossplatForms.getConfigManager(), - crossplatForms.getServerHandler(), + crossplatForms.getPermissions(), crossplatForms.getInterfacer(), crossplatForms.getBedrockHandler(), crossplatForms.getPlaceholders() diff --git a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/LegacySpigotAccessItems.java b/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/LegacySpigotAccessItems.java index f073da19..6df561e2 100644 --- a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/LegacySpigotAccessItems.java +++ b/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/LegacySpigotAccessItems.java @@ -4,10 +4,9 @@ import dev.kejona.crossplatforms.config.ConfigManager; import dev.kejona.crossplatforms.handler.BedrockHandler; import dev.kejona.crossplatforms.handler.Placeholders; -import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.interfacing.Interfacer; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.spigot.common.SpigotAccessItemsBase; -import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.inventory.ItemStack; @@ -22,11 +21,11 @@ public class LegacySpigotAccessItems extends SpigotAccessItemsBase { public LegacySpigotAccessItems(JavaPlugin plugin, ConfigManager configManager, - ServerHandler serverHandler, + Permissions permissions, Interfacer interfacer, BedrockHandler bedrockHandler, Placeholders placeholders) { - super(plugin, configManager, serverHandler, interfacer, bedrockHandler, placeholders); + super(plugin, configManager, permissions, interfacer, bedrockHandler, placeholders); } @Override diff --git a/spigot-legacy/src/main/resources/plugin.yml b/spigot-legacy/src/main/resources/plugin.yml index 6a87f66e..627abf77 100644 --- a/spigot-legacy/src/main/resources/plugin.yml +++ b/spigot-legacy/src/main/resources/plugin.yml @@ -1,6 +1,7 @@ main: dev.kejona.crossplatforms.spigot.CrossplatFormsSpigotLegacy name: CrossplatForms version: ${project_version} + description: ${project_description} prefix: CForms authors: @@ -10,6 +11,7 @@ softdepend: - Geyser-Spigot - floodgate - PlaceholderAPI + - LuckPerms # Register our PlayerCommandPreprocessEvent listener before DM so that ours is called first (Since DM uses EventPriority.LOWEST) loadbefore: diff --git a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java index d2fef3a3..e21f2b86 100644 --- a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java +++ b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java @@ -19,11 +19,11 @@ public boolean attemptBrigadier() { } @Override - public SpigotAccessItemsBase accessItems(CrossplatForms crossplatForms) { + public SpigotAccessItemsBase createAccessItems(CrossplatForms crossplatForms) { return new SpigotAccessItems( this, crossplatForms.getConfigManager(), - crossplatForms.getServerHandler(), + crossplatForms.getPermissions(), crossplatForms.getInterfacer(), crossplatForms.getBedrockHandler(), crossplatForms.getPlaceholders() diff --git a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java index b4aaeed1..1ad44e8d 100644 --- a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java +++ b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java @@ -4,8 +4,8 @@ import dev.kejona.crossplatforms.config.ConfigManager; import dev.kejona.crossplatforms.handler.BedrockHandler; import dev.kejona.crossplatforms.handler.Placeholders; -import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.interfacing.Interfacer; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.spigot.common.SpigotAccessItemsBase; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; @@ -26,11 +26,11 @@ public class SpigotAccessItems extends SpigotAccessItemsBase { public SpigotAccessItems(JavaPlugin plugin, ConfigManager configManager, - ServerHandler serverHandler, + Permissions permissions, Interfacer interfacer, BedrockHandler bedrockHandler, Placeholders placeholders) { - super(plugin, configManager, serverHandler, interfacer, bedrockHandler, placeholders); + super(plugin, configManager, permissions, interfacer, bedrockHandler, placeholders); } @Override diff --git a/spigot/src/main/resources/plugin.yml b/spigot/src/main/resources/plugin.yml index b3dc7dea..65abd113 100644 --- a/spigot/src/main/resources/plugin.yml +++ b/spigot/src/main/resources/plugin.yml @@ -11,6 +11,7 @@ softdepend: - Geyser-Spigot - floodgate - PlaceholderAPI + - LuckPerms # Register our PlayerCommandPreprocessEvent listener before DM so that ours is called first (Since DM uses EventPriority.LOWEST) loadbefore: diff --git a/velocity/src/main/java/dev/kejona/crossplatforms/velocity/CrossplatFormsVelocity.java b/velocity/src/main/java/dev/kejona/crossplatforms/velocity/CrossplatFormsVelocity.java index 43e6538e..19279efc 100644 --- a/velocity/src/main/java/dev/kejona/crossplatforms/velocity/CrossplatFormsVelocity.java +++ b/velocity/src/main/java/dev/kejona/crossplatforms/velocity/CrossplatFormsVelocity.java @@ -24,9 +24,9 @@ import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.interfacing.Interfacer; import dev.kejona.crossplatforms.interfacing.NoMenusInterfacer; +import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.proxy.CloseMenuAction; -import dev.kejona.crossplatforms.proxy.LuckPermsHook; -import dev.kejona.crossplatforms.proxy.PermissionHook; +import dev.kejona.crossplatforms.permission.LuckPermsHook; import dev.kejona.crossplatforms.proxy.ProtocolizeInterfacer; import dev.kejona.crossplatforms.velocity.handler.VelocityCommandOrigin; import dev.kejona.crossplatforms.velocity.handler.VelocityHandler; @@ -75,10 +75,8 @@ public void load(ProxyInitializeEvent event) { } metrics = metricsFactory.make(this, BSTATS_ID); - ServerHandler serverHandler = new VelocityHandler( - server, - pluginPresent("luckperms") ? new LuckPermsHook() : PermissionHook.empty() - ); + ServerHandler serverHandler = new VelocityHandler(server); + Permissions permissions = pluginPresent("luckperms") ? new LuckPermsHook() : Permissions.empty(); VelocityCommandManager commandManager; try { @@ -104,6 +102,7 @@ public void load(ProxyInitializeEvent event) { logger, dataFolder, serverHandler, + permissions, "formsv", commandManager, placeholders, diff --git a/velocity/src/main/java/dev/kejona/crossplatforms/velocity/handler/VelocityHandler.java b/velocity/src/main/java/dev/kejona/crossplatforms/velocity/handler/VelocityHandler.java index 1868f6f2..948d8be2 100644 --- a/velocity/src/main/java/dev/kejona/crossplatforms/velocity/handler/VelocityHandler.java +++ b/velocity/src/main/java/dev/kejona/crossplatforms/velocity/handler/VelocityHandler.java @@ -13,11 +13,10 @@ import dev.kejona.crossplatforms.command.CommandType; import dev.kejona.crossplatforms.command.DispatchableCommand; import dev.kejona.crossplatforms.command.custom.InterceptCommand; +import dev.kejona.crossplatforms.command.custom.InterceptCommandCache; import dev.kejona.crossplatforms.handler.BedrockHandler; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.handler.ServerHandler; -import dev.kejona.crossplatforms.proxy.PermissionHook; -import dev.kejona.crossplatforms.proxy.ProxyHandler; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.identity.Identity; @@ -27,14 +26,13 @@ import java.util.UUID; import java.util.stream.Stream; -public class VelocityHandler extends ProxyHandler implements ServerHandler { +public class VelocityHandler extends InterceptCommandCache implements ServerHandler { private final ProxyServer server; private final CommandManager commandManager; private final ConsoleCommandSource console; - public VelocityHandler(ProxyServer server, PermissionHook permissionHook) { - super(permissionHook); + public VelocityHandler(ProxyServer server) { this.server = server; this.commandManager = server.getCommandManager(); this.console = server.getConsoleCommandSource(); From 56001cea45b9ec292ed0e861cda45686c97cb960 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 13 Nov 2022 15:57:14 -0500 Subject: [PATCH 03/59] Cleanup dependency versions --- core/build.gradle.kts | 50 ++++++++++++------- spigot-common/build.gradle.kts | 2 +- .../spigot/common/SpigotBase.java | 4 +- .../spigot/CrossplatFormsSpigot.java | 9 ++++ 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index af6f1986..1f81995e 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -23,36 +23,50 @@ dependencies { testImplementation("org.geysermc.cumulus:cumulus:1.1.1-SNAPSHOT") // needed for testing button components testImplementation("com.google.code.gson:gson:2.8.6") // needed for cumulus - compileOnly("org.geysermc.floodgate:api:2.2.0-SNAPSHOT") { - exclude(group = "com.google.code.gson", module = "gson") - } + // Nullability annotations. todo: move to something else + testImplementation("com.google.code.findbugs:jsr305:3.0.2") + api("com.google.code.findbugs:jsr305:3.0.2") - compileOnly("net.luckperms:api:5.4") { - isTransitive = false - } + compileOnly("org.geysermc.floodgate:api:2.2.0-SNAPSHOT") { isTransitive = false } + compileOnly("net.luckperms:api:5.4") { isTransitive = false } + api("org.bstats:bstats-base:3.0.0") api("cloud.commandframework:cloud-core:1.7.1") api("cloud.commandframework:cloud-minecraft-extras:1.7.1") api("net.kyori:adventure-api:4.11.0") api("net.kyori:adventure-text-serializer-legacy:4.11.0") - api("net.kyori:adventure-text-serializer-gson:4.11.0") + api("net.kyori:adventure-text-serializer-gson:4.11.0") { + // This is required or else it overrides the version we explicitly define below + exclude(group = "com.google.code.gson", module = "gson") + } + api("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT") api("org.spongepowered:configurate-extra-guice:4.2.0-SNAPSHOT") - api("com.google.code.gson:gson:2.3.1") // version provided by spigot 1.8.8 - api("com.google.inject:guice:5.1.0") - api("org.bstats:bstats-base:3.0.0") + + api("com.google.inject:guice:5.0.1") { + exclude(group = "com.google.guava", module = "guava") // Provides a newer version than provided by server platforms + } + + api("com.google.guava:guava") { + version { + prefer("21.0") // Provided by Spigot 1.14, Velocity, BungeeCord. On 1.13 and below, guava is shaded. + } + } + api("com.google.code.gson:gson") { + version { + prefer("2.3.1") // lowest version, provided by spigot 1.8.8 + } + } // Required because source and unshaded jars are all mixed up on the opencollab repo currently - val baseApi = "2.1.0-20221012.212632-20" - val geyserApi = "2.1.0-20221012.212634-20" - val geyserCore = "2.1.0-20221012.212644-20" + val baseApi = "2.1.0-20221111.161532-35" + val geyserApi = "2.1.0-20221111.161541-35" + val geyserCore = "2.1.0-20221111.161551-35" // dependencies for java16 sources (optionally used at runtime) - java16Implementation("org.geysermc:api:$baseApi") - java16Implementation("org.geysermc.geyser:api:$geyserApi") - java16Implementation("org.geysermc.geyser:core:$geyserCore") { - isTransitive = false - } + java16Implementation("org.geysermc:api:$baseApi") { isTransitive = false} + java16Implementation("org.geysermc.geyser:api:$geyserApi") { isTransitive = false} + java16Implementation("org.geysermc.geyser:core:$geyserCore") { isTransitive = false} } description = "core" diff --git a/spigot-common/build.gradle.kts b/spigot-common/build.gradle.kts index 7d03e417..b5c19606 100644 --- a/spigot-common/build.gradle.kts +++ b/spigot-common/build.gradle.kts @@ -2,7 +2,7 @@ dependencies { testImplementation(testFixtures(projects.core)) - // 1.8.8 is supported but we target 1.9.4 to use PlayerSwapItemEvent if necessary + // 1.8.8 is supported but we target 1.9.4 to use PlayerSwapItemEvent if on 1.9.4 or above compileOnly("org.spigotmc:spigot-api:1.9.4-R0.1-SNAPSHOT") compileOnly("com.mojang:authlib:1.5.21") compileOnly("me.clip:placeholderapi:2.11.1") diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java index 371d18f6..edf512c9 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java @@ -30,6 +30,7 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bstats.bukkit.Metrics; import org.bstats.charts.CustomChart; +import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.plugin.java.JavaPlugin; @@ -153,7 +154,8 @@ public void onDisable() { if (audiences != null) { audiences.close(); } - server.getMessenger().unregisterOutgoingPluginChannel(this); + // note: server var might be null here in case plugin is disabled early + Bukkit.getMessenger().unregisterOutgoingPluginChannel(this); } @Override diff --git a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java index e21f2b86..7b7c0d25 100644 --- a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java +++ b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java @@ -9,6 +9,15 @@ public class CrossplatFormsSpigot extends SpigotBase { @Override public void onEnable() { + try { + // Only available on 1.14 and above, which CrossplatForms-Spigot targets. SpigotLegacy is for less than 1.13 + Class.forName("org.bukkit.persistence.PersistentDataContainer"); + } catch (ClassNotFoundException e) { + getLogger().severe("CrossplatForms-SpigotLegacy must be used for 1.13 and below."); + getPluginLoader().disablePlugin(this); + return; + } + super.onEnable(); addCustomChart(new SimplePie(PIE_CHART_LEGACY, () -> "false")); // not legacy } From 5dac3bf94dfbffce8ffa7a175b283af2dd42c74f Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 13 Nov 2022 17:53:54 -0500 Subject: [PATCH 04/59] Allow decimal steps for Slider, return int when there is no loss of precision --- .../bedrock/custom/CustomComponent.java | 12 ++++---- .../interfacing/bedrock/custom/Slider.java | 9 +++++- .../crossplatforms/resolver/MapResolver.java | 5 ++++ .../crossplatforms/utils/ParseUtils.java | 26 +++++++++++++++++ .../kejona/crossplatforms/ParseUtilsTest.java | 29 +++++++++++++++++++ 5 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 core/src/test/java/dev/kejona/crossplatforms/ParseUtilsTest.java diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/custom/CustomComponent.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/custom/CustomComponent.java index 15e79902..9f83173d 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/custom/CustomComponent.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/custom/CustomComponent.java @@ -41,15 +41,16 @@ protected CustomComponent(@Nonnull String text) { this.text = Objects.requireNonNull(text); } + public void parser(Parser parser) { + parsers.add(parser); + } + public abstract CustomComponent copy(); public abstract CustomComponent preparedCopy(Resolver resolver); public abstract Component cumulusComponent() throws IllegalValueException; - @Nonnull - public abstract String resultIfHidden(); - /** * Copies data in a source {@link CustomComponent} or any of its parent classes into a target. */ @@ -83,9 +84,8 @@ public String parse(FormPlayer player, String result) { return value; } - public void parser(Parser parser) { - parsers.add(parser); - } + @Nonnull + public abstract String resultIfHidden(); @Override public boolean equals(Object o) { diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/custom/Slider.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/custom/Slider.java index 40af39bc..6a015764 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/custom/Slider.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/custom/Slider.java @@ -2,6 +2,7 @@ import com.google.inject.Inject; import dev.kejona.crossplatforms.IllegalValueException; +import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.resolver.Resolver; import dev.kejona.crossplatforms.utils.ParseUtils; import lombok.Getter; @@ -46,7 +47,7 @@ public Component cumulusComponent() throws IllegalValueException { text, ParseUtils.getFloat(min, "min"), ParseUtils.getFloat(max, "max"), - ParseUtils.getUnsignedInt(step, "step"), + ParseUtils.getPositiveFloat(step, "step"), ParseUtils.getFloat(defaultValue, "default-value") ); } @@ -67,6 +68,12 @@ public Slider preparedCopy(Resolver resolver) { return copy; } + @Nonnull + @Override + public String parse(FormPlayer player, String result) { + return super.parse(player, ParseUtils.downSize(result)); + } + @Nonnull @Override public String resultIfHidden() { diff --git a/core/src/main/java/dev/kejona/crossplatforms/resolver/MapResolver.java b/core/src/main/java/dev/kejona/crossplatforms/resolver/MapResolver.java index b4a08eb2..6433d566 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/resolver/MapResolver.java +++ b/core/src/main/java/dev/kejona/crossplatforms/resolver/MapResolver.java @@ -1,5 +1,7 @@ package dev.kejona.crossplatforms.resolver; +import dev.kejona.crossplatforms.Logger; + import java.util.HashMap; import java.util.Map; @@ -25,6 +27,9 @@ public String apply(final String s) { for (String key : map.keySet()) { result = result.replace(key, map.get(key)); } + if (Logger.get().isDebug()) { + Logger.get().info("Result of map resolver: " + result); + } return result; } diff --git a/core/src/main/java/dev/kejona/crossplatforms/utils/ParseUtils.java b/core/src/main/java/dev/kejona/crossplatforms/utils/ParseUtils.java index e23f1853..7eb89476 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/utils/ParseUtils.java +++ b/core/src/main/java/dev/kejona/crossplatforms/utils/ParseUtils.java @@ -41,6 +41,21 @@ public static int getUnsignedInt(@Nullable String value, String identifier) thro } } + /** + * Converts a float to an integer if it can be done without loss of precision. + * @param floaty The float, in string representation. + * @return the integer as a string if conversion was possible, otherwise the floaty parameter + * @throws NumberFormatException if the parameter could not be parsed to a float + */ + public static String downSize(String floaty) throws NumberFormatException { + float value = Float.parseFloat(floaty); + if ((int) value == value) { + return Integer.toString((int) value); + } else { + return floaty; + } + } + public static float getFloat(@Nullable String value, String identifier) throws IllegalValueException { if (value == null) { throw new IllegalValueException(null, "decimal number", identifier); @@ -54,6 +69,17 @@ public static float getFloat(@Nullable String value, String identifier) throws I } } + /** + * Requires the string value to be a float, that is positive. It must not be zero or negative. + */ + public static float getPositiveFloat(@Nullable String value, String identifier) throws IllegalValueException { + float f = getFloat(value, identifier); + if (f <= 0) { + throw new IllegalValueException(value, "positive decimal number", identifier); + } + return f; + } + public static boolean getBoolean(@Nullable String value, String identifier) throws IllegalValueException { if (value == null) { throw new IllegalValueException(null, "boolean", identifier); diff --git a/core/src/test/java/dev/kejona/crossplatforms/ParseUtilsTest.java b/core/src/test/java/dev/kejona/crossplatforms/ParseUtilsTest.java new file mode 100644 index 00000000..5991ee0d --- /dev/null +++ b/core/src/test/java/dev/kejona/crossplatforms/ParseUtilsTest.java @@ -0,0 +1,29 @@ +package dev.kejona.crossplatforms; + +import org.junit.jupiter.api.Test; + +import static dev.kejona.crossplatforms.utils.ParseUtils.downSize; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ParseUtilsTest { + + @Test + public void testDownSize() { + assertEquals("1.2", downSize("1.2")); + assertEquals("3.14", downSize("3.14")); + assertEquals("-5.56", downSize("-5.56")); + + assertEquals("3", downSize("3.0")); + assertEquals("14", downSize("14.00")); + assertEquals("-16", downSize("-16.000000000")); + assertEquals("256", downSize("256.0000000000000000000")); + + assertEquals("165", downSize("165")); + assertEquals("-100", downSize("-100")); + + assertThrows(Exception.class, () -> downSize(null)); + assertThrows(Exception.class, () -> downSize("")); + assertThrows(Exception.class, () -> downSize(" ")); + } +} From 11c37f435c904a6c7874d9442c8d9c4977411747 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 13 Nov 2022 18:03:10 -0500 Subject: [PATCH 05/59] Update to Gradle 7.5.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 00e33ede..ae04661e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2ab4a6ceb660dd470bccc33b0f1da690477ae7b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Nov 2022 18:04:15 -0500 Subject: [PATCH 06/59] Bump net.kyori.indra.git from 2.1.1 to 2.2.0 (#120) (#127) Bumps net.kyori.indra.git from 2.1.1 to 2.2.0. --- updated-dependencies: - dependency-name: net.kyori.indra.git dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 0d532ac9..7b724137 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,7 +16,7 @@ pluginManagement { gradlePluginPortal() } plugins { - id("net.kyori.indra.git") version "2.2.0" + id("net.kyori.indra.git") version "3.0.1" id("net.kyori.indra") version "2.2.0" // multi-release jar id("com.github.johnrengelman.shadow") version "7.1.2" // shadowing dependencies } From 8c2dd94e2f089e2dc6f2f7255880eb95fe029c1f Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Tue, 13 Dec 2022 19:45:48 -0500 Subject: [PATCH 07/59] Support for 1.19.3 --- bungeecord/build.gradle.kts | 8 +++---- core/build.gradle.kts | 22 +++++++++---------- .../command/defaults/IdentifyCommand.java | 2 +- .../command/defaults/InspectCommand.java | 4 ++-- .../command/defaults/OpenCommand.java | 6 ++--- proxy/build.gradle.kts | 2 +- spigot-common/build.gradle.kts | 8 +++---- velocity/build.gradle.kts | 2 +- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/bungeecord/build.gradle.kts b/bungeecord/build.gradle.kts index 50b73632..a759a9f5 100644 --- a/bungeecord/build.gradle.kts +++ b/bungeecord/build.gradle.kts @@ -5,10 +5,10 @@ plugins { } dependencies { - compileOnly("net.md-5:bungeecord-api:1.18-R0.1-SNAPSHOT") - compileOnly("com.github.SpigotMC.BungeeCord:bungeecord-proxy:2d369e8") // through jitpack - api("cloud.commandframework:cloud-bungee:1.7.1") - api("net.kyori:adventure-platform-bungeecord:4.1.2") + compileOnly("net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT") + compileOnly("com.github.SpigotMC.BungeeCord:bungeecord-proxy:e717676") // For getting skins (dependency through jitpack) + api("cloud.commandframework:cloud-bungee:1.8.0") + api("net.kyori:adventure-platform-bungeecord:4.2.0") implementation("org.bstats:bstats-bungeecord:3.0.0") api(projects.proxy) api(projects.core) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 1f81995e..c2029fdb 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -31,11 +31,11 @@ dependencies { compileOnly("net.luckperms:api:5.4") { isTransitive = false } api("org.bstats:bstats-base:3.0.0") - api("cloud.commandframework:cloud-core:1.7.1") - api("cloud.commandframework:cloud-minecraft-extras:1.7.1") - api("net.kyori:adventure-api:4.11.0") - api("net.kyori:adventure-text-serializer-legacy:4.11.0") - api("net.kyori:adventure-text-serializer-gson:4.11.0") { + api("cloud.commandframework:cloud-core:1.8.0") + api("cloud.commandframework:cloud-minecraft-extras:1.8.0") + api("net.kyori:adventure-api:4.12.0") + api("net.kyori:adventure-text-serializer-legacy:4.12.0") + api("net.kyori:adventure-text-serializer-gson:4.12.0") { // This is required or else it overrides the version we explicitly define below exclude(group = "com.google.code.gson", module = "gson") } @@ -59,14 +59,14 @@ dependencies { } // Required because source and unshaded jars are all mixed up on the opencollab repo currently - val baseApi = "2.1.0-20221111.161532-35" - val geyserApi = "2.1.0-20221111.161541-35" - val geyserCore = "2.1.0-20221111.161551-35" + val baseApi = "2.1.0-20221211.182143-60" + val geyserApi = "2.1.0-20221211.182145-60" + val geyserCore = "2.1.0-20221211.182157-60" // dependencies for java16 sources (optionally used at runtime) - java16Implementation("org.geysermc:api:$baseApi") { isTransitive = false} - java16Implementation("org.geysermc.geyser:api:$geyserApi") { isTransitive = false} - java16Implementation("org.geysermc.geyser:core:$geyserCore") { isTransitive = false} + java16Implementation("org.geysermc:api:$baseApi") { isTransitive = false } + java16Implementation("org.geysermc.geyser:api:$geyserApi") { isTransitive = false } + java16Implementation("org.geysermc.geyser:core:$geyserCore") { isTransitive = false } } description = "core" diff --git a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/IdentifyCommand.java b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/IdentifyCommand.java index 7fa5cea2..ffbe1d0a 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/IdentifyCommand.java +++ b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/IdentifyCommand.java @@ -43,7 +43,7 @@ public void register(CommandManager manager, Command.BuildernewBuilder("player") + .argument(StringArgument.builder("player") .withSuggestionsProvider((context, s) -> serverHandler.getPlayerNames().collect(Collectors.toList())) .build()) .permission(PERMISSION_OTHER) diff --git a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/InspectCommand.java b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/InspectCommand.java index e6dae568..0ac4d50e 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/InspectCommand.java +++ b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/InspectCommand.java @@ -36,7 +36,7 @@ public void register(CommandManager manager, Command.BuildernewBuilder("form") + .argument(StringArgument.builder("form") .withSuggestionsProvider(((context, s) -> bedrockRegistry.getForms().values() .stream() .map(Interface::getIdentifier) @@ -56,7 +56,7 @@ public void register(CommandManager manager, Command.BuildernewBuilder("menu") + .argument(StringArgument.builder("menu") .withSuggestionsProvider(((context, s) -> javaRegistry.getMenus().values() .stream() .map(Interface::getIdentifier) diff --git a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/OpenCommand.java b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/OpenCommand.java index 45dca9ae..06d40e04 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/OpenCommand.java +++ b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/OpenCommand.java @@ -67,7 +67,7 @@ public void register(CommandManager manager, Command.Builder origin.hasPermission(PERMISSION) && origin.isPlayer()) - .argument(StringArgument.newBuilder(INTERFACE_ARG) + .argument(StringArgument.builder(INTERFACE_ARG) .withSuggestionsProvider((context, s) -> openSuggestions(context)) .build()) .argument(extrasArgument()) @@ -98,12 +98,12 @@ public void register(CommandManager manager, Command.BuildernewBuilder("player") + .argument(StringArgument.builder("player") .withSuggestionsProvider((context, s) -> serverHandler.getPlayers() .map(FormPlayer::getName) .collect(Collectors.toList())) .build()) - .argument(StringArgument.newBuilder(INTERFACE_ARG) + .argument(StringArgument.builder(INTERFACE_ARG) .withSuggestionsProvider((context, s) -> sendSuggestions(context)) .build()) .argument(extrasArgument()) diff --git a/proxy/build.gradle.kts b/proxy/build.gradle.kts index 12f20b5d..ae41951e 100644 --- a/proxy/build.gradle.kts +++ b/proxy/build.gradle.kts @@ -2,6 +2,6 @@ description = "proxy" dependencies { - compileOnly("dev.simplix:protocolize-api:2.1.2") + compileOnly("dev.simplix:protocolize-api:2.2.3") compileOnly(projects.core) } diff --git a/spigot-common/build.gradle.kts b/spigot-common/build.gradle.kts index b5c19606..2eae1db1 100644 --- a/spigot-common/build.gradle.kts +++ b/spigot-common/build.gradle.kts @@ -4,13 +4,13 @@ dependencies { // 1.8.8 is supported but we target 1.9.4 to use PlayerSwapItemEvent if on 1.9.4 or above compileOnly("org.spigotmc:spigot-api:1.9.4-R0.1-SNAPSHOT") - compileOnly("com.mojang:authlib:1.5.21") - compileOnly("me.clip:placeholderapi:2.11.1") + compileOnly("com.mojang:authlib:1.5.21") // Mirrored from floodgate-spigot - probably the version from 1.8.8 + compileOnly("me.clip:placeholderapi:2.11.2") api(projects.core) api(projects.accessItem) - api("cloud.commandframework:cloud-paper:1.7.1") + api("cloud.commandframework:cloud-paper:1.8.0") api("me.lucko:commodore:2.2") - api("net.kyori:adventure-platform-bukkit:4.1.2") + api("net.kyori:adventure-platform-bukkit:4.2.0") api("org.bstats:bstats-bukkit:3.0.0") } diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index e896f1f2..0b86ac1d 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -7,7 +7,7 @@ plugins { dependencies { //annotationProcessor("com.velocitypowered:velocity-api:3.1.0") compileOnly("com.velocitypowered:velocity-api:3.1.0") - api("cloud.commandframework:cloud-velocity:1.7.1") + api("cloud.commandframework:cloud-velocity:1.8.0") api("org.bstats:bstats-velocity:3.0.0") api(projects.proxy) api(projects.core) From 941ec3be661775218407a4e86c2e12e9945167c0 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Wed, 14 Dec 2022 01:16:48 -0500 Subject: [PATCH 08/59] Update indra --- core/build.gradle.kts | 2 +- settings.gradle.kts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index c2029fdb..9d0558a2 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("net.kyori.indra") - id("java-test-fixtures") + id("java-test-fixtures") // used for the testFixtures source set, which is available for other test sources } sourceSets { diff --git a/settings.gradle.kts b/settings.gradle.kts index 7b724137..47f5783e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,8 +16,8 @@ pluginManagement { gradlePluginPortal() } plugins { - id("net.kyori.indra.git") version "3.0.1" - id("net.kyori.indra") version "2.2.0" // multi-release jar + id("net.kyori.indra.git") version "3.0.1" // getting branch and commit info at compile time + id("net.kyori.indra") version "3.0.1" // multi-release jar for referencing Java 16 geyser api id("com.github.johnrengelman.shadow") version "7.1.2" // shadowing dependencies } } From 5f0fe339b8a26893a83666de2d30ce17b47d1067 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 15 Dec 2022 00:21:36 -0500 Subject: [PATCH 09/59] LuckPerms: Only register default perms of TRUE and don't create default group if there are no perms to register --- .../crossplatforms/permission/LuckPermsHook.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/dev/kejona/crossplatforms/permission/LuckPermsHook.java b/core/src/main/java/dev/kejona/crossplatforms/permission/LuckPermsHook.java index 48836f09..c47565f9 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/permission/LuckPermsHook.java +++ b/core/src/main/java/dev/kejona/crossplatforms/permission/LuckPermsHook.java @@ -21,6 +21,11 @@ public class LuckPermsHook implements Permissions { @Override public void registerPermissions(Collection permissions) { + if (permissions.stream().map(Permission::defaultPermission).noneMatch(PermissionDefault::asBoolean)) { + // None of the permission defaults are TRUE - nothing needs to be done + return; + } + groupManager.loadGroup(DEFAULT_NAME).thenAcceptAsync(defaultGroup -> { Group group = defaultGroup.orElse(null); if (group == null) { @@ -29,7 +34,7 @@ public void registerPermissions(Collection permissions) { group.data().add(DEFAULT_WEIGHT); logger.debug("Created LuckPerms group: " + DEFAULT_NAME); } catch (InterruptedException | ExecutionException e) { - Logger.get().severe("Failed to register create and load group: " + DEFAULT_NAME); + Logger.get().severe("Failed to create and load group: " + DEFAULT_NAME); e.printStackTrace(); return; } @@ -43,8 +48,8 @@ public void registerPermissions(Collection permissions) { String key = perm.key(); PermissionDefault def = perm.defaultPermission(); - logger.debug("\t" + key + " : " + def); - if (def != PermissionDefault.OP) { + if (def == PermissionDefault.TRUE) { + logger.debug("\t" + key + " : " + def); setPermission(group, perm.key(), def.asBoolean()); } } From 379ec724924aa4be1880573d0bf130aca8bffee7 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 19 Dec 2022 00:52:02 -0500 Subject: [PATCH 10/59] Remove unused permission fallback default --- .../crossplatforms/accessitem/AccessItem.java | 12 ------------ .../crossplatforms/interfacing/Interface.java | 13 ------------- 2 files changed, 25 deletions(-) diff --git a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/AccessItem.java b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/AccessItem.java index 1a4885eb..ff539226 100644 --- a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/AccessItem.java +++ b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/AccessItem.java @@ -142,18 +142,6 @@ public enum Limit { PRESERVE(".preserve", "Stop the Access Item from being destroyed when it is dropped. This includes death, regardless of drop permission.", PermissionDefault.FALSE), MOVE(".move", "Ability to move the Access Item around and to inventories", PermissionDefault.FALSE); - /** - * Map of {@link PermissionDefault} to fallback to if the user does not define their own. - */ - public static final Map FALLBACK_DEFAULTS; - - static { - FALLBACK_DEFAULTS = new HashMap<>(); - for (Limit limit : Limit.values()) { - FALLBACK_DEFAULTS.put(limit, limit.fallbackDefault); - } - } - public final String permissionSuffix; public final String description; public final PermissionDefault fallbackDefault; diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java index abd64169..8a270fb6 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java @@ -134,19 +134,6 @@ public enum Limit { USE(".use", "Base permission to use the form or menu", PermissionDefault.TRUE), COMMAND(".command", "Open the form or menu through the open command", PermissionDefault.OP); - /** - * Map of {@link PermissionDefault} to fallback to if the user does not define their own. - */ - public static final Map FALLBACK_DEFAULTS; - - static { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (Interface.Limit limit : Interface.Limit.values()) { - builder.put(limit, limit.fallbackDefault); - } - FALLBACK_DEFAULTS = builder.build(); - } - public final String permissionSuffix; public final String description; public final PermissionDefault fallbackDefault; From 8012598212accbb72e81daa7757edc739c472074 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sat, 7 Jan 2023 19:42:28 -0500 Subject: [PATCH 11/59] A start on inventory/item refactor --- .../interfacing/Interfacer.java | 3 +- .../interfacing/NoMenusInterfacer.java | 3 +- .../interfacing/java/ItemButton.java | 29 ++++---- .../interfacing/java/JavaMenu.java | 33 ++++++++- .../kejona/crossplatforms/item/Inventory.java | 13 ++++ .../crossplatforms/item/InventoryFactory.java | 17 +++++ .../crossplatforms/item/InventoryLayout.java | 7 ++ .../dev/kejona/crossplatforms/item/Item.java | 11 +++ .../dev/kejona/crossplatforms/TestModule.java | 6 +- .../proxy/ProtocolizeInterfacer.java | 54 +++----------- .../proxy/item/ProtocolizeInventory.java | 21 ++++++ .../item/ProtocolizeInventoryFactory.java | 37 ++++++++++ .../proxy/item/ProtocolizeItem.java | 45 +++++++++++ .../spigot/common/SpigotInterfacer.java | 57 ++------------ .../spigot/common/item/SpigotInventory.java | 52 +++++++++++++ .../common/item/SpigotInventoryFactory.java | 74 +++++++++++++++++++ .../spigot/common/item/SpigotItem.java | 16 ++++ 17 files changed, 365 insertions(+), 113 deletions(-) create mode 100644 core/src/main/java/dev/kejona/crossplatforms/item/Inventory.java create mode 100644 core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java create mode 100644 core/src/main/java/dev/kejona/crossplatforms/item/InventoryLayout.java create mode 100644 core/src/main/java/dev/kejona/crossplatforms/item/Item.java create mode 100644 proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventory.java create mode 100644 proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java create mode 100644 proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java create mode 100644 spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java create mode 100644 spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java create mode 100644 spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interfacer.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interfacer.java index 4fcf2c2b..10df9ff8 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interfacer.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interfacer.java @@ -5,6 +5,7 @@ import dev.kejona.crossplatforms.interfacing.bedrock.BedrockFormRegistry; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; import dev.kejona.crossplatforms.interfacing.java.JavaMenuRegistry; +import dev.kejona.crossplatforms.item.Inventory; import dev.kejona.crossplatforms.resolver.Resolver; import lombok.Getter; @@ -71,5 +72,5 @@ public List getInterfaces(boolean bedrock) { return list; } - public abstract void sendMenu(FormPlayer player, JavaMenu menu, Resolver resolver); + public abstract void openInventory(FormPlayer recipient, JavaMenu menu, Inventory inventory, Resolver resolver); } diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/NoMenusInterfacer.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/NoMenusInterfacer.java index 4b48a857..b3f6a651 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/NoMenusInterfacer.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/NoMenusInterfacer.java @@ -2,12 +2,13 @@ import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; +import dev.kejona.crossplatforms.item.Inventory; import dev.kejona.crossplatforms.resolver.Resolver; public class NoMenusInterfacer extends Interfacer { @Override - public void sendMenu(FormPlayer player, JavaMenu menu, Resolver resolver) { + public void openInventory(FormPlayer recipient, JavaMenu menu, Inventory inventory, Resolver resolver) { throw new UnsupportedOperationException("Inventory menus are not supported."); } } diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java index 16465b3f..85fa83f6 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java @@ -11,6 +11,7 @@ import java.util.Collections; import java.util.List; +import java.util.OptionalInt; @ToString @NoArgsConstructor @@ -36,9 +37,9 @@ public class ItemButton { @Nullable private transient FormPlayer targetPlayer; - // todo: - //private Integer customModelData; - //private ConfigurationNode nbt; + private OptionalInt customModelData; + + //private ConfigurationNode nbt; todo: possible support private List lore = Collections.emptyList(); @@ -46,6 +47,17 @@ public class ItemButton { private List> leftClick = Collections.emptyList(); private List> rightClick = Collections.emptyList(); + public String getDisplayName() { + if (displayName == null) { + return ""; + } + return displayName; + } + + public boolean isPlayerHead() { + return skullOwner != null; + } + public static ItemButton fillEntry(String displayName, FormPlayer skullOwner) { ItemButton item = new ItemButton(); item.displayName = displayName; @@ -59,15 +71,4 @@ public static ItemButton fillEntry(String displayName) { item.displayName = displayName; return item; } - - public String getDisplayName() { - if (displayName == null) { - return ""; - } - return displayName; - } - - public boolean isPlayerHead() { - return skullOwner != null; - } } diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenu.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenu.java index 89cf1645..1666b1a8 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenu.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenu.java @@ -1,9 +1,14 @@ package dev.kejona.crossplatforms.interfacing.java; +import com.google.inject.Inject; import dev.kejona.crossplatforms.Constants; import dev.kejona.crossplatforms.action.Action; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.interfacing.Interface; +import dev.kejona.crossplatforms.item.Inventory; +import dev.kejona.crossplatforms.item.InventoryFactory; +import dev.kejona.crossplatforms.item.InventoryLayout; +import dev.kejona.crossplatforms.item.Item; import dev.kejona.crossplatforms.resolver.Resolver; import lombok.Getter; import lombok.ToString; @@ -26,9 +31,14 @@ public class JavaMenu extends Interface { protected final transient String permissionBase = Constants.Id() + ".menu."; + @Inject + protected transient InventoryFactory factory; + private boolean allowBedrock = false; private int size = 5; // Hopper size by default + private InventoryLayout type = InventoryLayout.CHEST; + private Map buttons = Collections.emptyMap(); /** @@ -41,7 +51,28 @@ public boolean isButton(int slot) { @Override public void send(@Nonnull FormPlayer recipient, @Nonnull Resolver resolver) { - interfacer.sendMenu(recipient, this, resolver); + Inventory inventory; + if (type == InventoryLayout.CHEST) { + inventory = factory.chest(title, size); + } else { + inventory = factory.inventory(title, type); + } + + for (Integer slot : buttons.keySet()) { + ItemButton button = buttons.get(slot); + + String material = button.getMaterial(); + Item item = factory.item( + resolver.apply(button.getDisplayName()), + material, + resolver.apply(button.getLore()), + button.getCustomModelData() + ); + + inventory.setSlot(slot, item); + } + + interfacer.openInventory(recipient, this, inventory, resolver); } /** diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/Inventory.java b/core/src/main/java/dev/kejona/crossplatforms/item/Inventory.java new file mode 100644 index 00000000..9b2021df --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/item/Inventory.java @@ -0,0 +1,13 @@ +package dev.kejona.crossplatforms.item; + +public interface Inventory { + + Object handle(); + + @SuppressWarnings("unchecked") + default T castedHandle() { + return (T) handle(); + } + + void setSlot(int index, Item item); +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java new file mode 100644 index 00000000..4bc55aac --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java @@ -0,0 +1,17 @@ +package dev.kejona.crossplatforms.item; + +import dev.kejona.crossplatforms.handler.FormPlayer; + +import java.util.List; +import java.util.OptionalInt; + +public interface InventoryFactory { + + Inventory chest(String title, int chestSize); + Inventory inventory(String title, InventoryLayout layout); + + Item item(String displayName, String material, List lore, OptionalInt customModelData); + + Item skullItem(String owner, String displayName, List lore); + Item skullItem(FormPlayer owner, String displayName, List lore); +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryLayout.java b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryLayout.java new file mode 100644 index 00000000..b8e47424 --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryLayout.java @@ -0,0 +1,7 @@ +package dev.kejona.crossplatforms.item; + +public enum InventoryLayout { + CHEST, + HOPPER, + DISPENSER +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/Item.java b/core/src/main/java/dev/kejona/crossplatforms/item/Item.java new file mode 100644 index 00000000..54c4087d --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/item/Item.java @@ -0,0 +1,11 @@ +package dev.kejona.crossplatforms.item; + +public interface Item { + + Object handle(); + + @SuppressWarnings("unchecked") + default T castedHandle() { + return (T) handle(); + } +} diff --git a/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java b/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java index ef201377..fe2a3cfb 100644 --- a/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java +++ b/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java @@ -11,6 +11,7 @@ import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.interfacing.Interfacer; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; +import dev.kejona.crossplatforms.item.Inventory; import dev.kejona.crossplatforms.permission.PermissionDefault; import dev.kejona.crossplatforms.resolver.Resolver; import net.kyori.adventure.audience.Audience; @@ -26,9 +27,10 @@ public class TestModule extends AbstractModule { @Override protected void configure() { bind(Interfacer.class).toInstance(new Interfacer() { - @Override - public void sendMenu(FormPlayer player, JavaMenu menu, @Nonnull Resolver resolver) { + @Override + public void openInventory(FormPlayer recipient, JavaMenu menu, Inventory inventory, Resolver resolver) { + //no-op } }); diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java index cdce4c00..7d73bce4 100644 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java @@ -30,50 +30,18 @@ public ProtocolizeInterfacer() { } @Override - public void sendMenu(FormPlayer player, JavaMenu source, @Nonnull Resolver resolver) { - // construct the inventory. todo: validate size - // todo: apply placeholders and use args - InventoryType inventoryType; - int size = source.getSize(); - if (size == 5) { - inventoryType = InventoryType.HOPPER; - } else { - inventoryType = InventoryType.chestInventoryWithSize(size); - } - - Inventory inventory = new Inventory(inventoryType); - inventory.title(source.getTitle()); - - Map buttons = source.getButtons(); - for (Map.Entry entry : buttons.entrySet()) { - Integer slot = entry.getKey(); - ItemButton button = entry.getValue(); - // determine the material for this button - String material = button.getMaterial(); - ItemType type; - if (material == null) { - type = ItemType.STONE; - } else { - material = material.toUpperCase(Locale.ROOT).trim(); - try { - type = ItemType.valueOf(material); - } catch (IllegalArgumentException e) { - logger.severe("Java Button: " + source.getIdentifier() + "." + slot + " will be stone because '" + material + "' failed to map to a valid Spigot Material."); - type = ItemType.STONE; - } - } + public void openInventory(FormPlayer recipient, JavaMenu source, dev.kejona.crossplatforms.item.Inventory container, Resolver resolver) { + ProtocolizePlayer player = playerProvider.player(recipient.getUuid()); + Inventory inventory = container.castedHandle(); - // construct itemstack - final ItemStack item = new ItemStack(type); - item.displayName(button.getDisplayName()); - button.getLore().forEach(item::addToLore); - inventory.item(slot, item); // add itemstack to inventory + if (!inventory.clickConsumers().isEmpty()) { + Logger.get().severe("Cannot send menu '" + source.getIdentifier() + "' to " + recipient.getName() + " because the backing Protocolize inventory has already been shown to a different player."); + Thread.dumpStack(); + return; } - ProtocolizePlayer protocolizePlayer = playerProvider.player(player.getUuid()); - inventory.onClick(click -> { - int realSize = inventory.type().getTypicalSize(protocolizePlayer.protocolVersion()); + int realSize = inventory.type().getTypicalSize(player.protocolVersion()); // Clicks are cancelled by default, so we don't have to do it explicitly. ClickType clickType = click.clickType(); @@ -81,16 +49,16 @@ public void sendMenu(FormPlayer player, JavaMenu source, @Nonnull Resolver resol switch (clickType) { case RIGHT_CLICK: case SHIFT_RIGHT_CLICK: - source.process(click.slot(), true, player, resolver); + source.process(click.slot(), true, recipient, resolver); break; case LEFT_CLICK: case SHIFT_LEFT_CLICK: - source.process(click.slot(), false, player, resolver); + source.process(click.slot(), false, recipient, resolver); break; } } }); - protocolizePlayer.openInventory(inventory); + player.openInventory(inventory); } } diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventory.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventory.java new file mode 100644 index 00000000..d46685f1 --- /dev/null +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventory.java @@ -0,0 +1,21 @@ +package dev.kejona.crossplatforms.proxy.item; + +import dev.kejona.crossplatforms.item.Item; +import dev.simplix.protocolize.api.inventory.Inventory; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class ProtocolizeInventory implements dev.kejona.crossplatforms.item.Inventory { + + private final Inventory inventory; + + @Override + public Object handle() { + return inventory; + } + + @Override + public void setSlot(int index, Item item) { + inventory.item(index, item.castedHandle()); + } +} diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java new file mode 100644 index 00000000..dc0e6c46 --- /dev/null +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java @@ -0,0 +1,37 @@ +package dev.kejona.crossplatforms.proxy.item; + +import dev.kejona.crossplatforms.handler.FormPlayer; +import dev.kejona.crossplatforms.item.Inventory; +import dev.kejona.crossplatforms.item.InventoryFactory; +import dev.kejona.crossplatforms.item.InventoryLayout; +import dev.kejona.crossplatforms.item.Item; + +import java.util.List; +import java.util.OptionalInt; + +public class ProtocolizeInventoryFactory implements InventoryFactory { + @Override + public Inventory chest(String title, int chestSize) { + return null; + } + + @Override + public Inventory inventory(String title, InventoryLayout layout) { + return null; + } + + @Override + public Item item(String displayName, String material, List lore, OptionalInt customModelData) { + return null; + } + + @Override + public Item skullItem(String owner, String displayName, List lore) { + return null; + } + + @Override + public Item skullItem(FormPlayer owner, String displayName, List lore) { + return null; + } +} diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java new file mode 100644 index 00000000..71b563a8 --- /dev/null +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java @@ -0,0 +1,45 @@ +package dev.kejona.crossplatforms.proxy.item; + +import dev.kejona.crossplatforms.item.Item; +import dev.simplix.protocolize.api.item.BaseItemStack; +import lombok.RequiredArgsConstructor; +import net.querz.nbt.tag.CompoundTag; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.Objects; +import java.util.OptionalInt; + +@RequiredArgsConstructor +public class ProtocolizeItem implements Item { + + private static final String CUSTOM_MODEL_DATA_KEY = "CustomModelData"; + + private final BaseItemStack item; + + @Override + public Object handle() { + return item; + } + + @Override + public void displayName(@Nonnull String name) { + item.displayName(Objects.requireNonNull(name, "name")); + } + + @Override + public void lore(@Nonnull List lore) { + item.lore(lore, true); + } + + @Override + public void customModelData(OptionalInt id) { + CompoundTag nbt = item.nbtData(); + + if (id.isPresent()) { + nbt.putInt(CUSTOM_MODEL_DATA_KEY, id.getAsInt()); + } else { + nbt.remove(CUSTOM_MODEL_DATA_KEY); + } + } +} diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java index 97ab0995..8fa5d2b0 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java @@ -1,25 +1,18 @@ package dev.kejona.crossplatforms.spigot.common; -import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.interfacing.Interfacer; -import dev.kejona.crossplatforms.interfacing.java.ItemButton; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; import dev.kejona.crossplatforms.resolver.Resolver; import dev.kejona.crossplatforms.spigot.common.handler.SpigotPlayer; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import javax.annotation.Nonnull; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -32,51 +25,13 @@ public class SpigotInterfacer extends Interfacer implements Listener { private final Map resolverCache = new HashMap<>(); @Override - public void sendMenu(FormPlayer formPlayer, JavaMenu menu, @Nonnull Resolver resolver) { - Logger logger = Logger.get(); - Player player = Objects.requireNonNull(Bukkit.getPlayer(formPlayer.getUuid())); + public void openInventory(FormPlayer recipient, JavaMenu menu, dev.kejona.crossplatforms.item.Inventory inventory, Resolver resolver) { + Player player = Objects.requireNonNull(Bukkit.getPlayer(recipient.getUuid()), "player lookup"); + Inventory bukkitInventory = inventory.castedHandle(); - Inventory selectorGUI; // todo: better size validation? - if (menu.getSize() == JavaMenu.HOPPER_SIZE) { - selectorGUI = Bukkit.createInventory(player, InventoryType.HOPPER, resolver.apply(menu.getTitle())); - } else { - selectorGUI = Bukkit.createInventory(player, menu.getSize(), resolver.apply(menu.getTitle())); - } - - Map buttons = menu.getButtons(); - for (Integer slot : buttons.keySet()) { - ItemButton button = buttons.get(slot); - - String material = button.getMaterial(); - Material type; - if (material != null) { - type = Material.matchMaterial(button.getMaterial()); - if (type == null) { - logger.severe("Java Button: " + menu.getIdentifier() + "." + slot + " will be stone because '" + button.getMaterial() +"' failed to map to a valid Spigot Material."); - type = Material.STONE; - } - } else { - type = Material.STONE; - } - - // todo: merge item construction logic with stuff from access items - // Construct the item - ItemStack item = new ItemStack(type); - - ItemMeta meta = item.getItemMeta(); - if (meta == null) { - logger.severe("Java Button: " + menu.getIdentifier() + "." + slot + " with Material: " + button.getMaterial() + " returned null ItemMeta, not adding the button!"); - } else { - meta.setDisplayName(resolver.apply(button.getDisplayName())); - meta.setLore(resolver.apply(button.getLore())); - item.setItemMeta(meta); - selectorGUI.setItem(slot, item); - } - } - - player.openInventory(selectorGUI); - menuCache.put(selectorGUI, menu); - resolverCache.put(selectorGUI, resolver); + player.openInventory(bukkitInventory); + menuCache.put(bukkitInventory, menu); + resolverCache.put(bukkitInventory, resolver); } @EventHandler diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java new file mode 100644 index 00000000..7ea9c56a --- /dev/null +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java @@ -0,0 +1,52 @@ +package dev.kejona.crossplatforms.spigot.common.item; + +import dev.kejona.crossplatforms.item.Inventory; +import dev.kejona.crossplatforms.item.InventoryLayout; +import dev.kejona.crossplatforms.item.Item; +import lombok.RequiredArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.ItemStack; + +@RequiredArgsConstructor +public class SpigotInventory implements Inventory { + + private final org.bukkit.inventory.Inventory handle; + + public SpigotInventory(String title, int chestSize) { + handle = Bukkit.createInventory(null, chestSize, title); + } + + public SpigotInventory(String title, InventoryLayout layout) { + handle = Bukkit.createInventory(null, convertType(layout), title); + } + + @Override + public Object handle() { + return handle; + } + + @Override + public Item getSlot(int index) { + ItemStack item = handle.getItem(index); + return new SpigotItem(item); + } + + @Override + public void setSlot(int index, Item item) { + handle.setItem(index, item.castedHandle()); + } + + public static InventoryType convertType(InventoryLayout layout) { + switch (layout) { + case CHEST: + return InventoryType.CHEST; + case HOPPER: + return InventoryType.HOPPER; + case DISPENSER: + return InventoryType.DISPENSER; + } + + throw new AssertionError("Unhandled InventoryLayout: " + layout.name()); + } +} diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java new file mode 100644 index 00000000..2e835372 --- /dev/null +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java @@ -0,0 +1,74 @@ +package dev.kejona.crossplatforms.spigot.common.item; + +import dev.kejona.crossplatforms.Logger; +import dev.kejona.crossplatforms.handler.FormPlayer; +import dev.kejona.crossplatforms.item.Inventory; +import dev.kejona.crossplatforms.item.InventoryFactory; +import dev.kejona.crossplatforms.item.InventoryLayout; +import dev.kejona.crossplatforms.item.Item; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.List; +import java.util.Objects; +import java.util.OptionalInt; + +public class SpigotInventoryFactory implements InventoryFactory { + + private static final Material PLAYER_HEAD_MATERIAL; + + static { + Material modern = Material.getMaterial("PLAYER_HEAD"); + if (modern != null) { + PLAYER_HEAD_MATERIAL = modern; + } else { + Logger.get().debug("Using legacy SKULL_ITEM material for player heads"); + PLAYER_HEAD_MATERIAL = Objects.requireNonNull(Material.getMaterial("SKULL_ITEM"), "SKULL_ITEM material lookup"); + } + } + + @Override + public Inventory chest(String title, int chestSize) { + return new SpigotInventory(title, chestSize); + } + + @Override + public Inventory inventory(String title, InventoryLayout layout) { + return new SpigotInventory(title, layout); + } + + @Override + public Item item(String displayName, String material, List lore, OptionalInt customModelData) { + ItemStack item = new ItemStack(Material.matchMaterial(material)); + + ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(displayName); + meta.setLore(lore); + item.setItemMeta(meta); + + return new SpigotItem(item); + } + + @Override + public Item skullItem(String owner, String displayName, List lore) { + return null; + } + + @Override + public Item skullItem(FormPlayer player, @Nullable String displayName, List lore) { + ItemStack item = new ItemStack(PLAYER_HEAD_MATERIAL); + + SkullMeta meta = (SkullMeta) item.getItemMeta(); + if (displayName != null) { + meta.setDisplayName(displayName); + } + meta.setLore(lore); + + + item.setItemMeta(meta); + return new SpigotItem(item); + } +} diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java new file mode 100644 index 00000000..13847278 --- /dev/null +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java @@ -0,0 +1,16 @@ +package dev.kejona.crossplatforms.spigot.common.item; + +import dev.kejona.crossplatforms.item.Item; +import lombok.RequiredArgsConstructor; +import org.bukkit.inventory.ItemStack; + +@RequiredArgsConstructor +public class SpigotItem implements Item { + + private final ItemStack handle; + + @Override + public Object handle() { + return handle; + } +} From 404019a2ab77b4e4f3ef3335091ae785dad2d9fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Jan 2023 23:08:46 +0000 Subject: [PATCH 12/59] Bump junit-jupiter from 5.9.1 to 5.9.2 Bumps [junit-jupiter](https://github.com/junit-team/junit5) from 5.9.1 to 5.9.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.1...r5.9.2) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4385d351..456770a9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -59,7 +59,7 @@ subprojects { dependencies { testAnnotationProcessor("org.projectlombok:lombok:1.18.24") testCompileOnly("org.projectlombok:lombok:1.18.22") - testImplementation("org.junit.jupiter:junit-jupiter:5.9.1") + testImplementation("org.junit.jupiter:junit-jupiter:5.9.2") annotationProcessor("org.projectlombok:lombok:1.18.22") compileOnly("org.projectlombok:lombok:1.18.22") From 021ca9bcb92b9a27a3d9dfce6186836c9f835d9c Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Tue, 10 Jan 2023 21:14:09 -0500 Subject: [PATCH 13/59] More progress on inventory refactor --- .../interfacing/Interfacer.java | 3 +- .../interfacing/NoMenusInterfacer.java | 3 +- .../interfacing/java/ItemButton.java | 29 +++---- .../interfacing/java/JavaMenu.java | 33 +++++++- .../kejona/crossplatforms/item/Inventory.java | 13 +++ .../crossplatforms/item/InventoryFactory.java | 17 ++++ .../crossplatforms/item/InventoryLayout.java | 7 ++ .../dev/kejona/crossplatforms/item/Item.java | 11 +++ .../dev/kejona/crossplatforms/TestModule.java | 6 +- .../proxy/ProtocolizeInterfacer.java | 54 +++---------- .../proxy/item/ProtocolizeInventory.java | 21 +++++ .../item/ProtocolizeInventoryFactory.java | 79 +++++++++++++++++++ .../proxy/item/ProtocolizeItem.java | 17 ++++ .../spigot/common/SpigotInterfacer.java | 57 ++----------- .../spigot/common/item/SpigotInventory.java | 45 +++++++++++ .../common/item/SpigotInventoryFactory.java | 74 +++++++++++++++++ .../spigot/common/item/SpigotItem.java | 16 ++++ 17 files changed, 372 insertions(+), 113 deletions(-) create mode 100644 core/src/main/java/dev/kejona/crossplatforms/item/Inventory.java create mode 100644 core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java create mode 100644 core/src/main/java/dev/kejona/crossplatforms/item/InventoryLayout.java create mode 100644 core/src/main/java/dev/kejona/crossplatforms/item/Item.java create mode 100644 proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventory.java create mode 100644 proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java create mode 100644 proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java create mode 100644 spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java create mode 100644 spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java create mode 100644 spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interfacer.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interfacer.java index 4fcf2c2b..10df9ff8 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interfacer.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interfacer.java @@ -5,6 +5,7 @@ import dev.kejona.crossplatforms.interfacing.bedrock.BedrockFormRegistry; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; import dev.kejona.crossplatforms.interfacing.java.JavaMenuRegistry; +import dev.kejona.crossplatforms.item.Inventory; import dev.kejona.crossplatforms.resolver.Resolver; import lombok.Getter; @@ -71,5 +72,5 @@ public List getInterfaces(boolean bedrock) { return list; } - public abstract void sendMenu(FormPlayer player, JavaMenu menu, Resolver resolver); + public abstract void openInventory(FormPlayer recipient, JavaMenu menu, Inventory inventory, Resolver resolver); } diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/NoMenusInterfacer.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/NoMenusInterfacer.java index 4b48a857..b3f6a651 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/NoMenusInterfacer.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/NoMenusInterfacer.java @@ -2,12 +2,13 @@ import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; +import dev.kejona.crossplatforms.item.Inventory; import dev.kejona.crossplatforms.resolver.Resolver; public class NoMenusInterfacer extends Interfacer { @Override - public void sendMenu(FormPlayer player, JavaMenu menu, Resolver resolver) { + public void openInventory(FormPlayer recipient, JavaMenu menu, Inventory inventory, Resolver resolver) { throw new UnsupportedOperationException("Inventory menus are not supported."); } } diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java index 16465b3f..85fa83f6 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java @@ -11,6 +11,7 @@ import java.util.Collections; import java.util.List; +import java.util.OptionalInt; @ToString @NoArgsConstructor @@ -36,9 +37,9 @@ public class ItemButton { @Nullable private transient FormPlayer targetPlayer; - // todo: - //private Integer customModelData; - //private ConfigurationNode nbt; + private OptionalInt customModelData; + + //private ConfigurationNode nbt; todo: possible support private List lore = Collections.emptyList(); @@ -46,6 +47,17 @@ public class ItemButton { private List> leftClick = Collections.emptyList(); private List> rightClick = Collections.emptyList(); + public String getDisplayName() { + if (displayName == null) { + return ""; + } + return displayName; + } + + public boolean isPlayerHead() { + return skullOwner != null; + } + public static ItemButton fillEntry(String displayName, FormPlayer skullOwner) { ItemButton item = new ItemButton(); item.displayName = displayName; @@ -59,15 +71,4 @@ public static ItemButton fillEntry(String displayName) { item.displayName = displayName; return item; } - - public String getDisplayName() { - if (displayName == null) { - return ""; - } - return displayName; - } - - public boolean isPlayerHead() { - return skullOwner != null; - } } diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenu.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenu.java index 89cf1645..1666b1a8 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenu.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/JavaMenu.java @@ -1,9 +1,14 @@ package dev.kejona.crossplatforms.interfacing.java; +import com.google.inject.Inject; import dev.kejona.crossplatforms.Constants; import dev.kejona.crossplatforms.action.Action; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.interfacing.Interface; +import dev.kejona.crossplatforms.item.Inventory; +import dev.kejona.crossplatforms.item.InventoryFactory; +import dev.kejona.crossplatforms.item.InventoryLayout; +import dev.kejona.crossplatforms.item.Item; import dev.kejona.crossplatforms.resolver.Resolver; import lombok.Getter; import lombok.ToString; @@ -26,9 +31,14 @@ public class JavaMenu extends Interface { protected final transient String permissionBase = Constants.Id() + ".menu."; + @Inject + protected transient InventoryFactory factory; + private boolean allowBedrock = false; private int size = 5; // Hopper size by default + private InventoryLayout type = InventoryLayout.CHEST; + private Map buttons = Collections.emptyMap(); /** @@ -41,7 +51,28 @@ public boolean isButton(int slot) { @Override public void send(@Nonnull FormPlayer recipient, @Nonnull Resolver resolver) { - interfacer.sendMenu(recipient, this, resolver); + Inventory inventory; + if (type == InventoryLayout.CHEST) { + inventory = factory.chest(title, size); + } else { + inventory = factory.inventory(title, type); + } + + for (Integer slot : buttons.keySet()) { + ItemButton button = buttons.get(slot); + + String material = button.getMaterial(); + Item item = factory.item( + resolver.apply(button.getDisplayName()), + material, + resolver.apply(button.getLore()), + button.getCustomModelData() + ); + + inventory.setSlot(slot, item); + } + + interfacer.openInventory(recipient, this, inventory, resolver); } /** diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/Inventory.java b/core/src/main/java/dev/kejona/crossplatforms/item/Inventory.java new file mode 100644 index 00000000..9b2021df --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/item/Inventory.java @@ -0,0 +1,13 @@ +package dev.kejona.crossplatforms.item; + +public interface Inventory { + + Object handle(); + + @SuppressWarnings("unchecked") + default T castedHandle() { + return (T) handle(); + } + + void setSlot(int index, Item item); +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java new file mode 100644 index 00000000..4bc55aac --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java @@ -0,0 +1,17 @@ +package dev.kejona.crossplatforms.item; + +import dev.kejona.crossplatforms.handler.FormPlayer; + +import java.util.List; +import java.util.OptionalInt; + +public interface InventoryFactory { + + Inventory chest(String title, int chestSize); + Inventory inventory(String title, InventoryLayout layout); + + Item item(String displayName, String material, List lore, OptionalInt customModelData); + + Item skullItem(String owner, String displayName, List lore); + Item skullItem(FormPlayer owner, String displayName, List lore); +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryLayout.java b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryLayout.java new file mode 100644 index 00000000..b8e47424 --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryLayout.java @@ -0,0 +1,7 @@ +package dev.kejona.crossplatforms.item; + +public enum InventoryLayout { + CHEST, + HOPPER, + DISPENSER +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/Item.java b/core/src/main/java/dev/kejona/crossplatforms/item/Item.java new file mode 100644 index 00000000..54c4087d --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/item/Item.java @@ -0,0 +1,11 @@ +package dev.kejona.crossplatforms.item; + +public interface Item { + + Object handle(); + + @SuppressWarnings("unchecked") + default T castedHandle() { + return (T) handle(); + } +} diff --git a/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java b/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java index ef201377..fe2a3cfb 100644 --- a/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java +++ b/core/src/testFixtures/java/dev/kejona/crossplatforms/TestModule.java @@ -11,6 +11,7 @@ import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.interfacing.Interfacer; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; +import dev.kejona.crossplatforms.item.Inventory; import dev.kejona.crossplatforms.permission.PermissionDefault; import dev.kejona.crossplatforms.resolver.Resolver; import net.kyori.adventure.audience.Audience; @@ -26,9 +27,10 @@ public class TestModule extends AbstractModule { @Override protected void configure() { bind(Interfacer.class).toInstance(new Interfacer() { - @Override - public void sendMenu(FormPlayer player, JavaMenu menu, @Nonnull Resolver resolver) { + @Override + public void openInventory(FormPlayer recipient, JavaMenu menu, Inventory inventory, Resolver resolver) { + //no-op } }); diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java index cdce4c00..7d73bce4 100644 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java @@ -30,50 +30,18 @@ public ProtocolizeInterfacer() { } @Override - public void sendMenu(FormPlayer player, JavaMenu source, @Nonnull Resolver resolver) { - // construct the inventory. todo: validate size - // todo: apply placeholders and use args - InventoryType inventoryType; - int size = source.getSize(); - if (size == 5) { - inventoryType = InventoryType.HOPPER; - } else { - inventoryType = InventoryType.chestInventoryWithSize(size); - } - - Inventory inventory = new Inventory(inventoryType); - inventory.title(source.getTitle()); - - Map buttons = source.getButtons(); - for (Map.Entry entry : buttons.entrySet()) { - Integer slot = entry.getKey(); - ItemButton button = entry.getValue(); - // determine the material for this button - String material = button.getMaterial(); - ItemType type; - if (material == null) { - type = ItemType.STONE; - } else { - material = material.toUpperCase(Locale.ROOT).trim(); - try { - type = ItemType.valueOf(material); - } catch (IllegalArgumentException e) { - logger.severe("Java Button: " + source.getIdentifier() + "." + slot + " will be stone because '" + material + "' failed to map to a valid Spigot Material."); - type = ItemType.STONE; - } - } + public void openInventory(FormPlayer recipient, JavaMenu source, dev.kejona.crossplatforms.item.Inventory container, Resolver resolver) { + ProtocolizePlayer player = playerProvider.player(recipient.getUuid()); + Inventory inventory = container.castedHandle(); - // construct itemstack - final ItemStack item = new ItemStack(type); - item.displayName(button.getDisplayName()); - button.getLore().forEach(item::addToLore); - inventory.item(slot, item); // add itemstack to inventory + if (!inventory.clickConsumers().isEmpty()) { + Logger.get().severe("Cannot send menu '" + source.getIdentifier() + "' to " + recipient.getName() + " because the backing Protocolize inventory has already been shown to a different player."); + Thread.dumpStack(); + return; } - ProtocolizePlayer protocolizePlayer = playerProvider.player(player.getUuid()); - inventory.onClick(click -> { - int realSize = inventory.type().getTypicalSize(protocolizePlayer.protocolVersion()); + int realSize = inventory.type().getTypicalSize(player.protocolVersion()); // Clicks are cancelled by default, so we don't have to do it explicitly. ClickType clickType = click.clickType(); @@ -81,16 +49,16 @@ public void sendMenu(FormPlayer player, JavaMenu source, @Nonnull Resolver resol switch (clickType) { case RIGHT_CLICK: case SHIFT_RIGHT_CLICK: - source.process(click.slot(), true, player, resolver); + source.process(click.slot(), true, recipient, resolver); break; case LEFT_CLICK: case SHIFT_LEFT_CLICK: - source.process(click.slot(), false, player, resolver); + source.process(click.slot(), false, recipient, resolver); break; } } }); - protocolizePlayer.openInventory(inventory); + player.openInventory(inventory); } } diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventory.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventory.java new file mode 100644 index 00000000..d46685f1 --- /dev/null +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventory.java @@ -0,0 +1,21 @@ +package dev.kejona.crossplatforms.proxy.item; + +import dev.kejona.crossplatforms.item.Item; +import dev.simplix.protocolize.api.inventory.Inventory; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class ProtocolizeInventory implements dev.kejona.crossplatforms.item.Inventory { + + private final Inventory inventory; + + @Override + public Object handle() { + return inventory; + } + + @Override + public void setSlot(int index, Item item) { + inventory.item(index, item.castedHandle()); + } +} diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java new file mode 100644 index 00000000..2077dbfb --- /dev/null +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java @@ -0,0 +1,79 @@ +package dev.kejona.crossplatforms.proxy.item; + +import dev.kejona.crossplatforms.handler.FormPlayer; +import dev.kejona.crossplatforms.item.Inventory; +import dev.kejona.crossplatforms.item.InventoryFactory; +import dev.kejona.crossplatforms.item.InventoryLayout; +import dev.kejona.crossplatforms.item.Item; +import dev.simplix.protocolize.api.item.ItemStack; +import dev.simplix.protocolize.data.ItemType; +import dev.simplix.protocolize.data.inventory.InventoryType; +import net.querz.nbt.tag.CompoundTag; + +import java.util.List; +import java.util.Locale; +import java.util.OptionalInt; + +public class ProtocolizeInventoryFactory implements InventoryFactory { + + private static final String CUSTOM_MODEL_DATA_KEY = "CustomModelData"; + + @Override + public Inventory chest(String title, int chestSize) { + InventoryType type = InventoryType.chestInventoryWithSize(chestSize); + dev.simplix.protocolize.api.inventory.Inventory inventory = new dev.simplix.protocolize.api.inventory.Inventory(type); + + inventory.title(title); + + return new ProtocolizeInventory(inventory); + } + + @Override + public Inventory inventory(String title, InventoryLayout layout) { + InventoryType type = convertType(layout); + dev.simplix.protocolize.api.inventory.Inventory inventory = new dev.simplix.protocolize.api.inventory.Inventory(type); + + inventory.title(title); + + return new ProtocolizeInventory(inventory); + } + + @Override + public Item item(String displayName, String material, List lore, OptionalInt customModelData) { + + ItemStack item = new ItemStack(ItemType.valueOf(material.toUpperCase(Locale.ROOT).trim())); + + CompoundTag nbt = item.nbtData(); + + if (customModelData.isPresent()) { + nbt.putInt(CUSTOM_MODEL_DATA_KEY, customModelData.getAsInt()); + } else { + nbt.remove(CUSTOM_MODEL_DATA_KEY); + } + + return new ProtocolizeItem(item); + } + + @Override + public Item skullItem(String owner, String displayName, List lore) { + return null; + } + + @Override + public Item skullItem(FormPlayer owner, String displayName, List lore) { + return null; + } + + private static InventoryType convertType(InventoryLayout layout) { + switch (layout) { + case CHEST: + return InventoryType.GENERIC_9X6; + case HOPPER: + return InventoryType.HOPPER; + case DISPENSER: + return InventoryType.GENERIC_3X3; + } + + throw new AssertionError("Unhandled InventoryLayout: " + layout.name()); + } +} diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java new file mode 100644 index 00000000..d5364742 --- /dev/null +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java @@ -0,0 +1,17 @@ +package dev.kejona.crossplatforms.proxy.item; + +import dev.kejona.crossplatforms.item.Item; +import dev.simplix.protocolize.api.item.BaseItemStack; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class ProtocolizeItem implements Item { + + + private final BaseItemStack item; + + @Override + public Object handle() { + return item; + } +} diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java index 97ab0995..8fa5d2b0 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java @@ -1,25 +1,18 @@ package dev.kejona.crossplatforms.spigot.common; -import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.interfacing.Interfacer; -import dev.kejona.crossplatforms.interfacing.java.ItemButton; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; import dev.kejona.crossplatforms.resolver.Resolver; import dev.kejona.crossplatforms.spigot.common.handler.SpigotPlayer; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import javax.annotation.Nonnull; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -32,51 +25,13 @@ public class SpigotInterfacer extends Interfacer implements Listener { private final Map resolverCache = new HashMap<>(); @Override - public void sendMenu(FormPlayer formPlayer, JavaMenu menu, @Nonnull Resolver resolver) { - Logger logger = Logger.get(); - Player player = Objects.requireNonNull(Bukkit.getPlayer(formPlayer.getUuid())); + public void openInventory(FormPlayer recipient, JavaMenu menu, dev.kejona.crossplatforms.item.Inventory inventory, Resolver resolver) { + Player player = Objects.requireNonNull(Bukkit.getPlayer(recipient.getUuid()), "player lookup"); + Inventory bukkitInventory = inventory.castedHandle(); - Inventory selectorGUI; // todo: better size validation? - if (menu.getSize() == JavaMenu.HOPPER_SIZE) { - selectorGUI = Bukkit.createInventory(player, InventoryType.HOPPER, resolver.apply(menu.getTitle())); - } else { - selectorGUI = Bukkit.createInventory(player, menu.getSize(), resolver.apply(menu.getTitle())); - } - - Map buttons = menu.getButtons(); - for (Integer slot : buttons.keySet()) { - ItemButton button = buttons.get(slot); - - String material = button.getMaterial(); - Material type; - if (material != null) { - type = Material.matchMaterial(button.getMaterial()); - if (type == null) { - logger.severe("Java Button: " + menu.getIdentifier() + "." + slot + " will be stone because '" + button.getMaterial() +"' failed to map to a valid Spigot Material."); - type = Material.STONE; - } - } else { - type = Material.STONE; - } - - // todo: merge item construction logic with stuff from access items - // Construct the item - ItemStack item = new ItemStack(type); - - ItemMeta meta = item.getItemMeta(); - if (meta == null) { - logger.severe("Java Button: " + menu.getIdentifier() + "." + slot + " with Material: " + button.getMaterial() + " returned null ItemMeta, not adding the button!"); - } else { - meta.setDisplayName(resolver.apply(button.getDisplayName())); - meta.setLore(resolver.apply(button.getLore())); - item.setItemMeta(meta); - selectorGUI.setItem(slot, item); - } - } - - player.openInventory(selectorGUI); - menuCache.put(selectorGUI, menu); - resolverCache.put(selectorGUI, resolver); + player.openInventory(bukkitInventory); + menuCache.put(bukkitInventory, menu); + resolverCache.put(bukkitInventory, resolver); } @EventHandler diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java new file mode 100644 index 00000000..94d0615f --- /dev/null +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java @@ -0,0 +1,45 @@ +package dev.kejona.crossplatforms.spigot.common.item; + +import dev.kejona.crossplatforms.item.Inventory; +import dev.kejona.crossplatforms.item.InventoryLayout; +import dev.kejona.crossplatforms.item.Item; +import lombok.RequiredArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.ItemStack; + +public class SpigotInventory implements Inventory { + + private final org.bukkit.inventory.Inventory handle; + + public SpigotInventory(String title, int chestSize) { + handle = Bukkit.createInventory(null, chestSize, title); + } + + public SpigotInventory(String title, InventoryLayout layout) { + handle = Bukkit.createInventory(null, convertType(layout), title); + } + + @Override + public Object handle() { + return handle; + } + + @Override + public void setSlot(int index, Item item) { + handle.setItem(index, item.castedHandle()); + } + + public static InventoryType convertType(InventoryLayout layout) { + switch (layout) { + case CHEST: + return InventoryType.CHEST; + case HOPPER: + return InventoryType.HOPPER; + case DISPENSER: + return InventoryType.DISPENSER; + } + + throw new AssertionError("Unhandled InventoryLayout: " + layout.name()); + } +} diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java new file mode 100644 index 00000000..2e835372 --- /dev/null +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java @@ -0,0 +1,74 @@ +package dev.kejona.crossplatforms.spigot.common.item; + +import dev.kejona.crossplatforms.Logger; +import dev.kejona.crossplatforms.handler.FormPlayer; +import dev.kejona.crossplatforms.item.Inventory; +import dev.kejona.crossplatforms.item.InventoryFactory; +import dev.kejona.crossplatforms.item.InventoryLayout; +import dev.kejona.crossplatforms.item.Item; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.List; +import java.util.Objects; +import java.util.OptionalInt; + +public class SpigotInventoryFactory implements InventoryFactory { + + private static final Material PLAYER_HEAD_MATERIAL; + + static { + Material modern = Material.getMaterial("PLAYER_HEAD"); + if (modern != null) { + PLAYER_HEAD_MATERIAL = modern; + } else { + Logger.get().debug("Using legacy SKULL_ITEM material for player heads"); + PLAYER_HEAD_MATERIAL = Objects.requireNonNull(Material.getMaterial("SKULL_ITEM"), "SKULL_ITEM material lookup"); + } + } + + @Override + public Inventory chest(String title, int chestSize) { + return new SpigotInventory(title, chestSize); + } + + @Override + public Inventory inventory(String title, InventoryLayout layout) { + return new SpigotInventory(title, layout); + } + + @Override + public Item item(String displayName, String material, List lore, OptionalInt customModelData) { + ItemStack item = new ItemStack(Material.matchMaterial(material)); + + ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(displayName); + meta.setLore(lore); + item.setItemMeta(meta); + + return new SpigotItem(item); + } + + @Override + public Item skullItem(String owner, String displayName, List lore) { + return null; + } + + @Override + public Item skullItem(FormPlayer player, @Nullable String displayName, List lore) { + ItemStack item = new ItemStack(PLAYER_HEAD_MATERIAL); + + SkullMeta meta = (SkullMeta) item.getItemMeta(); + if (displayName != null) { + meta.setDisplayName(displayName); + } + meta.setLore(lore); + + + item.setItemMeta(meta); + return new SpigotItem(item); + } +} diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java new file mode 100644 index 00000000..13847278 --- /dev/null +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java @@ -0,0 +1,16 @@ +package dev.kejona.crossplatforms.spigot.common.item; + +import dev.kejona.crossplatforms.item.Item; +import lombok.RequiredArgsConstructor; +import org.bukkit.inventory.ItemStack; + +@RequiredArgsConstructor +public class SpigotItem implements Item { + + private final ItemStack handle; + + @Override + public Object handle() { + return handle; + } +} From 8172c99c38b7da14f26d07c890ce448930822152 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Wed, 11 Jan 2023 01:03:52 -0500 Subject: [PATCH 14/59] A start on spigot version adapters --- settings.gradle.kts | 8 +++ spigot-legacy/build.gradle.kts | 2 +- spigotcompat/adapter/build.gradle.kts | 4 ++ .../spigot/adapter/NbtAccessor.java | 24 +++++++ .../spigot/adapter/VersionAdapter.java | 10 +++ spigotcompat/all/build.gradle.kts | 6 ++ .../spigot/adapter/VersionAdapters.java | 26 ++++++++ spigotcompat/v1_14_R1/build.gradle.kts | 5 ++ .../spigot/v1_14_R1/Adapter_v1_14_R1.java | 18 ++++++ .../spigot/v1_14_R1/ModernNbtAccessor.java | 47 ++++++++++++++ spigotcompat/v1_8_R3/build.gradle.kts | 6 ++ .../spigot/v1_8_R3/Adapter_v1_8_R3.java | 18 ++++++ .../spigot/v1_8_R3/LegacyNbtAccessor.java | 62 +++++++++++++++++++ 13 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 spigotcompat/adapter/build.gradle.kts create mode 100644 spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java create mode 100644 spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java create mode 100644 spigotcompat/all/build.gradle.kts create mode 100644 spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapters.java create mode 100644 spigotcompat/v1_14_R1/build.gradle.kts create mode 100644 spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java create mode 100644 spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java create mode 100644 spigotcompat/v1_8_R3/build.gradle.kts create mode 100644 spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java create mode 100644 spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java diff --git a/settings.gradle.kts b/settings.gradle.kts index 47f5783e..065cd728 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,3 +39,11 @@ dependencyResolutionManagement { maven("https://nexus.velocitypowered.com/repository/maven-public/") // velocity } } +include("spigotcompat:v1_8_R3") +findProject(":spigotcompat:v1_8_R3")?.name = "v1_8_R3" +include("spigotcompat:adapter") +findProject(":spigotcompat:adapter")?.name = "adapter" +include("spigotcompat:all") +findProject(":spigotcompat:all")?.name = "all" +include("spigotcompat:v1_14_R1") +findProject(":spigotcompat:v1_14_R1")?.name = "v1_14_R1" diff --git a/spigot-legacy/build.gradle.kts b/spigot-legacy/build.gradle.kts index 6a320ffb..47d5e40e 100644 --- a/spigot-legacy/build.gradle.kts +++ b/spigot-legacy/build.gradle.kts @@ -6,7 +6,7 @@ plugins { dependencies { compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") - api("de.tr7zw:item-nbt-api:2.10.0") + api("de.tr7zw:item-nbt-api:2.11.1") api(projects.spigotCommon) } diff --git a/spigotcompat/adapter/build.gradle.kts b/spigotcompat/adapter/build.gradle.kts new file mode 100644 index 00000000..0a592efd --- /dev/null +++ b/spigotcompat/adapter/build.gradle.kts @@ -0,0 +1,4 @@ + +dependencies { + compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") +} \ No newline at end of file diff --git a/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java b/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java new file mode 100644 index 00000000..54f428ac --- /dev/null +++ b/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java @@ -0,0 +1,24 @@ +package dev.kejona.crossplatforms.spigot.adapter; + +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface NbtAccessor { + + @Nullable + String getCustomString(@Nonnull ItemStack stack, @Nonnull String key); + void setCustomString(@Nonnull ItemStack stack, @Nonnull String key, @Nonnull String value); + + void setCustomModelData(@Nonnull ItemStack stack, @Nullable Integer value); + + @Nonnull + default ItemMeta requireItemMeta(ItemStack stack) { + if (!stack.hasItemMeta()) { + throw new IllegalArgumentException("ItemStack does not have ItemMeta: " + stack); + } + return stack.getItemMeta(); + } +} diff --git a/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java b/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java new file mode 100644 index 00000000..4936f89c --- /dev/null +++ b/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java @@ -0,0 +1,10 @@ +package dev.kejona.crossplatforms.spigot.adapter; + +import org.bukkit.plugin.Plugin; + +public interface VersionAdapter { + + boolean customModelData(); + + NbtAccessor nbtAccessor(Plugin plugin); +} diff --git a/spigotcompat/all/build.gradle.kts b/spigotcompat/all/build.gradle.kts new file mode 100644 index 00000000..52585509 --- /dev/null +++ b/spigotcompat/all/build.gradle.kts @@ -0,0 +1,6 @@ + +dependencies { + compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") + api(projects.spigotcompat.adapter) + api(projects.spigotcompat.v114R1) +} \ No newline at end of file diff --git a/spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapters.java b/spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapters.java new file mode 100644 index 00000000..04ea3700 --- /dev/null +++ b/spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapters.java @@ -0,0 +1,26 @@ +package dev.kejona.crossplatforms.spigot.adapter; + +import dev.kejonamc.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; +import dev.kejonamc.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +public final class VersionAdapters { + + private static final Map> ADAPTERS = new HashMap<>(); + + static { + ADAPTERS.put("1_8_R3", Adapter_v1_8_R3::new); + ADAPTERS.put("1_14_R1", Adapter_v1_14_R1::new); + } + + public static VersionAdapter adapterForVersion(String version) { + if (!ADAPTERS.containsKey(version)) { + return new Adapter_v1_14_R1(); + } + + return ADAPTERS.get(version).get(); + } +} diff --git a/spigotcompat/v1_14_R1/build.gradle.kts b/spigotcompat/v1_14_R1/build.gradle.kts new file mode 100644 index 00000000..008cada5 --- /dev/null +++ b/spigotcompat/v1_14_R1/build.gradle.kts @@ -0,0 +1,5 @@ + +dependencies { + compileOnly("org.spigotmc:spigot-api:1.14.4-R0.1-SNAPSHOT") + api(projects.spigotcompat.v18R3) +} \ No newline at end of file diff --git a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java b/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java new file mode 100644 index 00000000..fe3be8a4 --- /dev/null +++ b/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java @@ -0,0 +1,18 @@ +package dev.kejonamc.crossplatforms.spigot.v1_14_R1; + +import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import org.bukkit.plugin.Plugin; + +public class Adapter_v1_14_R1 implements VersionAdapter { + + @Override + public boolean customModelData() { + return true; + } + + @Override + public NbtAccessor nbtAccessor(Plugin plugin) { + return new ModernNbtAccessor(plugin); + } +} diff --git a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java b/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java new file mode 100644 index 00000000..0ec9bfc5 --- /dev/null +++ b/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java @@ -0,0 +1,47 @@ +package dev.kejonamc.crossplatforms.spigot.v1_14_R1; + +import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; +import lombok.AllArgsConstructor; +import org.bukkit.NamespacedKey; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.plugin.Plugin; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Uses the Spigot Persistent Data Container api + */ +@AllArgsConstructor +public class ModernNbtAccessor implements NbtAccessor { + + private final Plugin plugin; + + @Nullable + @Override + public String getCustomString(@Nonnull ItemStack stack, @Nonnull String key) { + if (!stack.hasItemMeta()) { + return null; + } + + return stack.getItemMeta().getPersistentDataContainer().get( + new NamespacedKey(plugin, key), + PersistentDataType.STRING + ); + } + + @Override + public void setCustomString(@Nonnull ItemStack stack, @Nonnull String key, @Nonnull String value) { + requireItemMeta(stack).getPersistentDataContainer().set( + new NamespacedKey(plugin, key), + PersistentDataType.STRING, + value + ); + } + + @Override + public void setCustomModelData(@Nonnull ItemStack stack, @Nullable Integer value) { + requireItemMeta(stack).setCustomModelData(value); + } +} diff --git a/spigotcompat/v1_8_R3/build.gradle.kts b/spigotcompat/v1_8_R3/build.gradle.kts new file mode 100644 index 00000000..640663a0 --- /dev/null +++ b/spigotcompat/v1_8_R3/build.gradle.kts @@ -0,0 +1,6 @@ + +dependencies { + compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") + implementation("de.tr7zw:item-nbt-api:2.11.1") + api(projects.spigotcompat.adapter) +} \ No newline at end of file diff --git a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java new file mode 100644 index 00000000..f4abbbb2 --- /dev/null +++ b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java @@ -0,0 +1,18 @@ +package dev.kejonamc.crossplatforms.spigot.v1_8_R3; + +import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import org.bukkit.plugin.Plugin; + +public class Adapter_v1_8_R3 implements VersionAdapter { + + @Override + public boolean customModelData() { + return false; + } + + @Override + public NbtAccessor nbtAccessor(Plugin plugin) { + return new LegacyNbtAccessor(plugin); + } +} diff --git a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java new file mode 100644 index 00000000..8a2ca438 --- /dev/null +++ b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java @@ -0,0 +1,62 @@ +package dev.kejonamc.crossplatforms.spigot.v1_8_R3; + +import de.tr7zw.changeme.nbtapi.NBTCompound; +import de.tr7zw.changeme.nbtapi.NBTItem; +import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Locale; + +/** + * Uses the 3rd party NBT api + */ +public class LegacyNbtAccessor implements NbtAccessor { + + /** + * NBTCompound name that the NBT of PersistentDataContainers in 1.14+ is stored in. We store it in the same place on + * legacy versions in order for existing things to not break when switching server versions. + */ + private static final String BUKKIT_COMPOUND = "PublicBukkitValues"; + + private final String namespacePrefix; + + /** + * @param plugin The plugin whose namespace should be used for writing/reading custom data + */ + public LegacyNbtAccessor(Plugin plugin) { + namespacePrefix = plugin.getName().toLowerCase(Locale.ROOT) + ":"; + } + + private String applyNamespace(String key) { + return namespacePrefix + key; + } + + @Override + public @Nullable String getCustomString(@Nonnull ItemStack stack, @Nonnull String key) { + if (stack.getItemMeta() == null) { + // Check against air + return null; + } + NBTCompound bukkitValues = new NBTItem(stack).getCompound(BUKKIT_COMPOUND); + if (bukkitValues == null) { + return null; + } else { + return bukkitValues.getString(applyNamespace(key)); + } + } + + @Override + public void setCustomString(@Nonnull ItemStack stack, @Nonnull String key, @Nonnull String value) { + // get existing or add empty compound for PublicBukkitValues + // then set string with our namespace applied + new NBTItem(stack, true).addCompound(BUKKIT_COMPOUND).setString(applyNamespace(key), value); + } + + @Override + public void setCustomModelData(@Nonnull ItemStack stack, @Nullable Integer value) { + throw new UnsupportedOperationException("CustomModelData only supported on 1.14.4 and above (current version is 1.18.3)"); + } +} From 5aad6a4662135a5f00aff0880185e90d6d6f0e3e Mon Sep 17 00:00:00 2001 From: Konicai <71294714+konicai@users.noreply.github.com> Date: Thu, 12 Jan 2023 17:15:41 -0500 Subject: [PATCH 15/59] Major progress on better Spigot version compatibility --- .../crossplatforms/item/InventoryFactory.java | 1 - .../item/ProtocolizeInventoryFactory.java | 5 -- settings.gradle.kts | 11 ++- ...sItemsBase.java => SpigotAccessItems.java} | 45 +++++------ .../spigot/common/SpigotBase.java | 22 +++++- .../spigot/common}/adapter/NbtAccessor.java | 2 +- .../spigot/common/adapter/VersionAdapter.java | 16 ++++ .../common/item/SpigotInventoryFactory.java | 14 ++-- spigot-legacy/build.gradle.kts | 47 ------------ .../spigot/CrossplatFormsSpigotLegacy.java | 32 -------- .../spigot/LegacySpigotAccessItems.java | 49 ------------ .../crossplatforms/spigot/NbtUtils.java | 66 ----------------- spigot-legacy/src/main/resources/plugin.yml | 53 ------------- .../spigot/CrossplatFormsSpigot.java | 31 +------- .../spigot/SpigotAccessItems.java | 74 ------------------- spigot/src/main/resources/plugin.yml | 2 +- spigotcompat/adapter/build.gradle.kts | 4 - .../spigot/adapter/VersionAdapter.java | 10 --- spigotcompat/all/build.gradle.kts | 2 +- .../VersionAdapters.java | 14 +++- spigotcompat/v1_12_R1/build.gradle.kts | 5 ++ .../spigot/v1_12_R1/Adapter_v1_12_R1.java | 15 ++++ .../EntityPlayerPickupItemListener.java | 21 ++++++ spigotcompat/v1_13_R2/build.gradle.kts | 5 ++ .../spigot/v1_13_R2/Adapter_v1_13_R2.java | 15 ++++ spigotcompat/v1_14_R1/build.gradle.kts | 2 +- .../spigot/v1_14_R1/Adapter_v1_14_R1.java | 10 ++- .../spigot/v1_14_R1/ModernNbtAccessor.java | 2 +- spigotcompat/v1_8_R3/build.gradle.kts | 2 +- .../spigot/v1_8_R3/Adapter_v1_8_R3.java | 17 ++++- .../spigot/v1_8_R3/LegacyNbtAccessor.java | 2 +- .../v1_8_R3/PlayerPickupItemListener.java | 18 +++++ spigotcompat/v1_9_R2/build.gradle.kts | 5 ++ .../spigot/v1_9_R2/Adapter_v1_9_R2.java | 17 +++++ .../v1_9_R2}/SwapHandItemsListener.java | 5 +- 35 files changed, 222 insertions(+), 419 deletions(-) rename spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/{SpigotAccessItemsBase.java => SpigotAccessItems.java} (92%) rename {spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot => spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common}/adapter/NbtAccessor.java (92%) create mode 100644 spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/VersionAdapter.java delete mode 100644 spigot-legacy/build.gradle.kts delete mode 100644 spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigotLegacy.java delete mode 100644 spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/LegacySpigotAccessItems.java delete mode 100644 spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/NbtUtils.java delete mode 100644 spigot-legacy/src/main/resources/plugin.yml delete mode 100644 spigot/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java delete mode 100644 spigotcompat/adapter/build.gradle.kts delete mode 100644 spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java rename spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/{adapter => v1_13_R2}/VersionAdapters.java (52%) create mode 100644 spigotcompat/v1_12_R1/build.gradle.kts create mode 100644 spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java create mode 100644 spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java create mode 100644 spigotcompat/v1_13_R2/build.gradle.kts create mode 100644 spigotcompat/v1_13_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/Adapter_v1_13_R2.java create mode 100644 spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java create mode 100644 spigotcompat/v1_9_R2/build.gradle.kts create mode 100644 spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java rename {spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common => spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2}/SwapHandItemsListener.java (79%) diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java index 4bc55aac..c29c6909 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java +++ b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java @@ -12,6 +12,5 @@ public interface InventoryFactory { Item item(String displayName, String material, List lore, OptionalInt customModelData); - Item skullItem(String owner, String displayName, List lore); Item skullItem(FormPlayer owner, String displayName, List lore); } diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java index 2077dbfb..3da83552 100644 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java @@ -54,11 +54,6 @@ public Item item(String displayName, String material, List lore, Optiona return new ProtocolizeItem(item); } - @Override - public Item skullItem(String owner, String displayName, List lore) { - return null; - } - @Override public Item skullItem(FormPlayer owner, String displayName, List lore) { return null; diff --git a/settings.gradle.kts b/settings.gradle.kts index 065cd728..efc49a15 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,7 +9,6 @@ include(":velocity") include(":access-item") include(":spigot-common") include(":spigot") -include(":spigot-legacy") pluginManagement { repositories { @@ -41,9 +40,15 @@ dependencyResolutionManagement { } include("spigotcompat:v1_8_R3") findProject(":spigotcompat:v1_8_R3")?.name = "v1_8_R3" -include("spigotcompat:adapter") -findProject(":spigotcompat:adapter")?.name = "adapter" +include("spigotcompat:common") +findProject(":spigotcompat:common")?.name = "common" include("spigotcompat:all") findProject(":spigotcompat:all")?.name = "all" include("spigotcompat:v1_14_R1") findProject(":spigotcompat:v1_14_R1")?.name = "v1_14_R1" +include("spigotcompat:v1_13_R2") +findProject(":spigotcompat:v1_13_R2")?.name = "v1_13_R2" +include("spigotcompat:v1_12_R1") +findProject(":spigotcompat:v1_12_R1")?.name = "v1_12_R1" +include("spigotcompat:v1_9_R2") +findProject(":spigotcompat:v1_9_R2")?.name = "v1_9_R2" diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItemsBase.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItems.java similarity index 92% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItemsBase.java rename to spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItems.java index aa5e696b..4e14fcf8 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItemsBase.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItems.java @@ -9,13 +9,15 @@ import dev.kejona.crossplatforms.handler.Placeholders; import dev.kejona.crossplatforms.interfacing.Interfacer; import dev.kejona.crossplatforms.permission.Permissions; +import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; import dev.kejona.crossplatforms.spigot.common.handler.SpigotPlayer; import lombok.AllArgsConstructor; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Item; import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; @@ -37,37 +39,34 @@ import java.util.Iterator; import java.util.List; import java.util.Objects; -import java.util.function.Consumer; import java.util.function.Predicate; -/** - * Abstract AccessItemRegistry for spigot platforms. Automatically registers {@link SwapHandItemsListener} if - * the class is event is available on the current server version. - */ -public abstract class SpigotAccessItemsBase extends AccessItemRegistry implements Listener { +public class SpigotAccessItems extends AccessItemRegistry implements Listener { private final Logger logger = Logger.get(); + + protected final NbtAccessor nbt; protected final Interfacer interfacer; protected final BedrockHandler bedrockHandler; protected final Placeholders placeholders; - public SpigotAccessItemsBase(JavaPlugin plugin, - ConfigManager configManager, - Permissions permissions, - Interfacer interfacer, - BedrockHandler bedrockHandler, - Placeholders placeholders) { + public SpigotAccessItems(JavaPlugin plugin, + VersionAdapter adapter, + ConfigManager configManager, + Permissions permissions, + Interfacer interfacer, + BedrockHandler bedrockHandler, + Placeholders placeholders) { super(configManager, permissions); + this.nbt = adapter.nbtAccessor(plugin); this.interfacer = interfacer; this.bedrockHandler = bedrockHandler; this.placeholders = placeholders; - - if (!Bukkit.getVersion().contains("1.8")) { // Older versions not supported, 1.9 and newer has offhand - Bukkit.getPluginManager().registerEvents(new SwapHandItemsListener(this), plugin); - } } - public abstract void setItemId(@Nonnull ItemStack itemStack, @Nonnull String identifier); + public void setItemId(@Nonnull ItemStack itemStack, @Nonnull String identifier) { + nbt.setCustomString(itemStack, AccessItem.STATIC_IDENTIFIER, identifier); + } /** * Attempt to retrieve the Access Item ID that an ItemStack points to. The Access Item ID may or may not refer @@ -76,7 +75,9 @@ public SpigotAccessItemsBase(JavaPlugin plugin, * @return The AccessItem ID if the ItemStack contained the name, null if not. */ @Nullable - public abstract String getItemId(@Nonnull ItemStack itemStack); + public String getItemId(@Nonnull ItemStack itemStack) { + return nbt.getCustomString(itemStack, AccessItem.STATIC_IDENTIFIER); + } public ItemStack createItemStack(AccessItem accessItem, Player player) { FormPlayer formPlayer = new SpigotPlayer(player); @@ -242,16 +243,16 @@ public void onPlayerLeave(PlayerQuitEvent event) { } } - protected final void handlePlayerPickupItem(Player player, Item item, Consumer canceller) { + public void handlePlayerPickupItem(Player player, Item item, Cancellable event) { String id = getItemId(item.getItemStack()); if (id != null) { AccessItem access = getItem(id); if (access == null) { // the item no longer exists, don't allow picking it up - canceller.accept(true); + event.setCancelled(true); } else if (!player.hasPermission(access.permission(AccessItem.Limit.POSSESS))) { // they don't have permission to have it - canceller.accept(true); + event.setCancelled(true); } } } diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java index edf512c9..6f9d7542 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java @@ -21,6 +21,7 @@ import dev.kejona.crossplatforms.interfacing.Interfacer; import dev.kejona.crossplatforms.permission.LuckPermsHook; import dev.kejona.crossplatforms.permission.Permissions; +import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; import dev.kejona.crossplatforms.spigot.common.handler.PlaceholderAPIHandler; import dev.kejona.crossplatforms.spigot.common.handler.SpigotCommandOrigin; import dev.kejona.crossplatforms.spigot.common.handler.SpigotHandler; @@ -40,7 +41,6 @@ public abstract class SpigotBase extends JavaPlugin implements CrossplatFormsBootstrap { - protected static final String PIE_CHART_LEGACY = "legacy"; protected static final int METRICS_ID = 14707; public static final LegacyComponentSerializer LEGACY_SERIALIZER = BukkitComponentSerializer.legacy(); @@ -122,7 +122,7 @@ public void onEnable() { return; } - SpigotAccessItemsBase accessItems = createAccessItems(crossplatForms); + SpigotAccessItems accessItems = createAccessItems(crossplatForms); server.getPluginManager().registerEvents(accessItems, this); // Commands added by access items @@ -183,9 +183,23 @@ private void convertGeyserHubConfig() { } } - public abstract boolean attemptBrigadier(); + public boolean attemptBrigadier() { + return true; // todo: determine if registering brig should be attempted + } - public abstract SpigotAccessItemsBase createAccessItems(CrossplatForms crossplatForms); + public SpigotAccessItems createAccessItems(CrossplatForms crossplatForms) { + return new SpigotAccessItems( + this, + createVersionAdapter(this), + crossplatForms.getConfigManager(), + crossplatForms.getPermissions(), + crossplatForms.getInterfacer(), + crossplatForms.getBedrockHandler(), + crossplatForms.getPlaceholders() + ); + } + + public abstract VersionAdapter createVersionAdapter(JavaPlugin plugin); public static SpigotBase getInstance() { return INSTANCE; diff --git a/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/NbtAccessor.java similarity index 92% rename from spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java rename to spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/NbtAccessor.java index 54f428ac..60a6f4d4 100644 --- a/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/NbtAccessor.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.adapter; +package dev.kejona.crossplatforms.spigot.common.adapter; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/VersionAdapter.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/VersionAdapter.java new file mode 100644 index 00000000..25d5ff16 --- /dev/null +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/VersionAdapter.java @@ -0,0 +1,16 @@ +package dev.kejona.crossplatforms.spigot.common.adapter; + +import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import org.bukkit.Material; +import org.bukkit.plugin.Plugin; + +public interface VersionAdapter { + + boolean customModelData(); + + Material playerHeadMaterial(); + + NbtAccessor nbtAccessor(Plugin plugin); + + void registerAuxiliaryEvents(Plugin plugin, SpigotAccessItems items); +} diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java index 2e835372..998af5f7 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java +++ b/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java @@ -6,6 +6,7 @@ import dev.kejona.crossplatforms.item.InventoryFactory; import dev.kejona.crossplatforms.item.InventoryLayout; import dev.kejona.crossplatforms.item.Item; +import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -30,6 +31,12 @@ public class SpigotInventoryFactory implements InventoryFactory { } } + private final Material playerHeadMaterial; + + public SpigotInventoryFactory(VersionAdapter adapter) { + playerHeadMaterial = adapter.playerHeadMaterial(); + } + @Override public Inventory chest(String title, int chestSize) { return new SpigotInventory(title, chestSize); @@ -52,14 +59,9 @@ public Item item(String displayName, String material, List lore, Optiona return new SpigotItem(item); } - @Override - public Item skullItem(String owner, String displayName, List lore) { - return null; - } - @Override public Item skullItem(FormPlayer player, @Nullable String displayName, List lore) { - ItemStack item = new ItemStack(PLAYER_HEAD_MATERIAL); + ItemStack item = new ItemStack(playerHeadMaterial); SkullMeta meta = (SkullMeta) item.getItemMeta(); if (displayName != null) { diff --git a/spigot-legacy/build.gradle.kts b/spigot-legacy/build.gradle.kts deleted file mode 100644 index 47d5e40e..00000000 --- a/spigot-legacy/build.gradle.kts +++ /dev/null @@ -1,47 +0,0 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar - -plugins { - id("com.github.johnrengelman.shadow") -} - -dependencies { - compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") - api("de.tr7zw:item-nbt-api:2.11.1") - api(projects.spigotCommon) -} - -tasks.withType { - dependencies { - shadow { - relocate("com.google.inject", "dev.kejona.crossplatforms.shaded.guice") - // older versions of Spigot have a Guava that is too old for the used Guice - relocate("com.google.common", "dev.kejona.crossplatforms.shaded.google.common") // i.e. Guava - relocate("cloud.commandframework", "dev.kejona.crossplatforms.shaded.cloud") - relocate("me.lucko.commodore", "dev.kejona.crossplatforms.shaded.commodore") - relocate("net.kyori", "dev.kejona.crossplatforms.shaded.kyori") - relocate("org.spongepowered.configurate", "dev.kejona.crossplatforms.shaded.configurate") - relocate("io.leangen.geantyref", "dev.kejona.crossplatforms.shaded.typetoken") - relocate("org.bstats", "dev.kejona.crossplatforms.shaded.bstats") - // Only used on spigot-legacy - legacy versions don't contain a version acceptable for configurate - relocate("org.yaml.snakeyaml", "dev.kejona.crossplatforms.shaded.snakeyaml") - relocate("de.tr7zw.changeme.nbtapi", "dev.kejona.crossplatforms.shaded.nbtapi") - relocate("de.tr7zw.annotations", "dev.kejona.crossplatforms.shaded.tr7zw.annotations") - } - exclude { - e -> - val name = e.name - (name.startsWith("com.google") - && !name.startsWith("com.google.inject") - && !name.startsWith("com.google.guava")) // contains package name of com.google.common - || name.startsWith("javax.inject") - } - } - - archiveFileName.set("CrossplatForms-SpigotLegacy.jar") -} - -tasks.named("build") { - dependsOn(tasks.named("shadowJar")) -} - -description = "spigot-legacy" diff --git a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigotLegacy.java b/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigotLegacy.java deleted file mode 100644 index a34bf63a..00000000 --- a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigotLegacy.java +++ /dev/null @@ -1,32 +0,0 @@ -package dev.kejona.crossplatforms.spigot; - -import dev.kejona.crossplatforms.CrossplatForms; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItemsBase; -import dev.kejona.crossplatforms.spigot.common.SpigotBase; -import org.bstats.charts.SimplePie; - -public class CrossplatFormsSpigotLegacy extends SpigotBase { - - @Override - public void onEnable() { - super.onEnable(); - addCustomChart(new SimplePie(PIE_CHART_LEGACY, () -> "true")); // this is legacy - } - - @Override - public boolean attemptBrigadier() { - return server.getVersion().contains("1.13"); // Spigot-Legacy supports 1.8 -> 1.13 and Brigadier was introduced in 1.13 - } - - @Override - public SpigotAccessItemsBase createAccessItems(CrossplatForms crossplatForms) { - return new LegacySpigotAccessItems( - this, - crossplatForms.getConfigManager(), - crossplatForms.getPermissions(), - crossplatForms.getInterfacer(), - crossplatForms.getBedrockHandler(), - crossplatForms.getPlaceholders() - ); - } -} diff --git a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/LegacySpigotAccessItems.java b/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/LegacySpigotAccessItems.java deleted file mode 100644 index 6df561e2..00000000 --- a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/LegacySpigotAccessItems.java +++ /dev/null @@ -1,49 +0,0 @@ -package dev.kejona.crossplatforms.spigot; - -import dev.kejona.crossplatforms.accessitem.AccessItem; -import dev.kejona.crossplatforms.config.ConfigManager; -import dev.kejona.crossplatforms.handler.BedrockHandler; -import dev.kejona.crossplatforms.handler.Placeholders; -import dev.kejona.crossplatforms.interfacing.Interfacer; -import dev.kejona.crossplatforms.permission.Permissions; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItemsBase; -import org.bukkit.event.EventHandler; -import org.bukkit.event.player.PlayerPickupItemEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.java.JavaPlugin; -import org.jetbrains.annotations.Nullable; - -import javax.annotation.Nonnull; - -public class LegacySpigotAccessItems extends SpigotAccessItemsBase { - - private static final String ITEM_IDENTIFIER = AccessItem.STATIC_IDENTIFIER; - - public LegacySpigotAccessItems(JavaPlugin plugin, - ConfigManager configManager, - Permissions permissions, - Interfacer interfacer, - BedrockHandler bedrockHandler, - Placeholders placeholders) { - super(plugin, configManager, permissions, interfacer, bedrockHandler, placeholders); - } - - @Override - public void setItemId(@Nonnull ItemStack itemStack, @Nonnull String identifier) { - NbtUtils.setCustomString(itemStack, ITEM_IDENTIFIER, identifier); - } - - @Nullable - @Override - public String getItemId(@Nonnull ItemStack itemStack) { - return NbtUtils.getString(itemStack, ITEM_IDENTIFIER); - } - - /** - * Implemented individually here because this event is deprecated on newer versions - */ - @EventHandler - public void onPlayerPickupItem(PlayerPickupItemEvent event) { // Stop players without possession permission to pickup items - handlePlayerPickupItem(event.getPlayer(), event.getItem(), event::setCancelled); - } -} diff --git a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/NbtUtils.java b/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/NbtUtils.java deleted file mode 100644 index a3657579..00000000 --- a/spigot-legacy/src/main/java/dev/kejona/crossplatforms/spigot/NbtUtils.java +++ /dev/null @@ -1,66 +0,0 @@ -package dev.kejona.crossplatforms.spigot; - -import de.tr7zw.changeme.nbtapi.NBTCompound; -import de.tr7zw.changeme.nbtapi.NBTItem; -import dev.kejona.crossplatforms.Constants; -import org.bukkit.inventory.ItemStack; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class NbtUtils { - - /** - * This needs to match the plugin identifier in plugin.yml. - */ - private static final String NAMESPACE_PREFIX = Constants.Id() + ":"; - - /** - * NBTCompound name that the NBT of PersistentDataContainers in 1.14+ is stored in. We store it in the same place on - * legacy versions in order for existing things to not break when switching from SpigotLegacy to Spigot or vice versa. - */ - private static final String BUKKIT_COMPOUND = "PublicBukkitValues"; - - private NbtUtils() { - - } - - /** - * Get the string value at a key within this plugins namespace. ItemStack may be air. - * @param stack The itemstack to get the NBT from - * @param key The key to get the value at, resolved within this plugins namespace - * @return The string value, if present. - */ - @Nullable - public static String getString(@Nonnull ItemStack stack, @Nonnull String key) { - if (stack.getItemMeta() == null) { - // Check against air - return null; - } - NBTCompound bukkitValues = new NBTItem(stack).getCompound(BUKKIT_COMPOUND); - if (bukkitValues == null) { - return null; - } else { - return bukkitValues.getString(applyNamespace(key)); - } - } - - /** - * Set a custom NBT tag on the itemstack. Vanilla tags will not be placed on the item. Tags are placed within this - * plugin's namespace. - * @param stack The ItemStack whose NBT to put the tag on - * @param key The key of the tag - * @param value The value of the tag - * @throws NullPointerException If NBT cannot be written to the stack (i.e. is air) - * @see NBTItem#mergeCustomNBT(ItemStack) - */ - public static void setCustomString(@Nonnull ItemStack stack, @Nonnull String key, @Nonnull String value) { - // get existing or add empty compound for PublicBukkitValues - // then set string with our namespace applied - new NBTItem(stack, true).addCompound(BUKKIT_COMPOUND).setString(applyNamespace(key), value); - } - - private static String applyNamespace(String key) { - return NAMESPACE_PREFIX + key; - } -} diff --git a/spigot-legacy/src/main/resources/plugin.yml b/spigot-legacy/src/main/resources/plugin.yml deleted file mode 100644 index 627abf77..00000000 --- a/spigot-legacy/src/main/resources/plugin.yml +++ /dev/null @@ -1,53 +0,0 @@ -main: dev.kejona.crossplatforms.spigot.CrossplatFormsSpigotLegacy -name: CrossplatForms -version: ${project_version} - -description: ${project_description} -prefix: CForms -authors: - - Konicai - - Jens -softdepend: - - Geyser-Spigot - - floodgate - - PlaceholderAPI - - LuckPerms - -# Register our PlayerCommandPreprocessEvent listener before DM so that ours is called first (Since DM uses EventPriority.LOWEST) -loadbefore: - - DeluxeMenus - -permissions: - crossplatforms.command.base: - description: Access to the base command /forms - default: true - crossplatforms.command.help: - description: Access to /forms help - default: true - crossplatforms.command.list: - description: Access to /forms list - default: true - crossplatforms.command.open: - description: Access to /forms open
- default: true - crossplatforms.command.send: - description: Access to /forms send - default: op - crossplatforms.command.give: - description: Access to /forms give - default: op - crossplatforms.command.give.others: - description: Access to /forms give - default: op - crossplatforms.command.inspect: - description: Access to /forms inspect - default: op - crossplatforms.command.identify: - description: Access to /forms identify - default: op - crossplatforms.command.version: - description: Access to /forms version - default: op - crossplatforms.command.reload: - description: Access to /forms reload - default: op diff --git a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java index 7b7c0d25..7def9ede 100644 --- a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java +++ b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java @@ -1,41 +1,18 @@ package dev.kejona.crossplatforms.spigot; -import dev.kejona.crossplatforms.CrossplatForms; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItemsBase; import dev.kejona.crossplatforms.spigot.common.SpigotBase; -import org.bstats.charts.SimplePie; +import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; +import org.bukkit.plugin.java.JavaPlugin; public class CrossplatFormsSpigot extends SpigotBase { @Override public void onEnable() { - try { - // Only available on 1.14 and above, which CrossplatForms-Spigot targets. SpigotLegacy is for less than 1.13 - Class.forName("org.bukkit.persistence.PersistentDataContainer"); - } catch (ClassNotFoundException e) { - getLogger().severe("CrossplatForms-SpigotLegacy must be used for 1.13 and below."); - getPluginLoader().disablePlugin(this); - return; - } - super.onEnable(); - addCustomChart(new SimplePie(PIE_CHART_LEGACY, () -> "false")); // not legacy } @Override - public boolean attemptBrigadier() { - return true; - } - - @Override - public SpigotAccessItemsBase createAccessItems(CrossplatForms crossplatForms) { - return new SpigotAccessItems( - this, - crossplatForms.getConfigManager(), - crossplatForms.getPermissions(), - crossplatForms.getInterfacer(), - crossplatForms.getBedrockHandler(), - crossplatForms.getPlaceholders() - ); + public VersionAdapter createVersionAdapter(JavaPlugin plugin) { + return null; } } diff --git a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java deleted file mode 100644 index 1ad44e8d..00000000 --- a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java +++ /dev/null @@ -1,74 +0,0 @@ -package dev.kejona.crossplatforms.spigot; - -import dev.kejona.crossplatforms.accessitem.AccessItem; -import dev.kejona.crossplatforms.config.ConfigManager; -import dev.kejona.crossplatforms.handler.BedrockHandler; -import dev.kejona.crossplatforms.handler.Placeholders; -import dev.kejona.crossplatforms.interfacing.Interfacer; -import dev.kejona.crossplatforms.permission.Permissions; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItemsBase; -import org.bukkit.NamespacedKey; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.entity.EntityPickupItemEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.persistence.PersistentDataType; -import org.bukkit.plugin.java.JavaPlugin; -import org.jetbrains.annotations.Nullable; - -import javax.annotation.Nonnull; - -public class SpigotAccessItems extends SpigotAccessItemsBase { - - public static final NamespacedKey ACCESS_ITEM_KEY = new NamespacedKey(CrossplatFormsSpigot.getInstance(), AccessItem.STATIC_IDENTIFIER); - public static final PersistentDataType ACCESS_ITEM_KEY_TYPE = PersistentDataType.STRING; - - public SpigotAccessItems(JavaPlugin plugin, - ConfigManager configManager, - Permissions permissions, - Interfacer interfacer, - BedrockHandler bedrockHandler, - Placeholders placeholders) { - super(plugin, configManager, permissions, interfacer, bedrockHandler, placeholders); - } - - @Override - public void setItemId(@Nonnull ItemStack itemStack, @Nonnull String identifier) { - ItemMeta meta = itemStack.getItemMeta(); - if (meta == null) { - throw new IllegalArgumentException("ItemStack " + itemStack + " does not have ItemMeta"); - } else { - meta.getPersistentDataContainer().set(ACCESS_ITEM_KEY, ACCESS_ITEM_KEY_TYPE, identifier); - itemStack.setItemMeta(meta); - } - } - - /** - * Attempt to retrieve the Access Item ID that an ItemStack points to. The Access Item ID may or may not refer - * to an actual AccessItem - * @param itemStack The ItemStack to check - * @return The AccessItem ID if the ItemStack contained the name, null if not. - */ - @Nullable - @Override - public String getItemId(@Nonnull ItemStack itemStack) { - ItemMeta meta = itemStack.getItemMeta(); - if (meta == null) { - return null; - } else { - return meta.getPersistentDataContainer().get(ACCESS_ITEM_KEY, ACCESS_ITEM_KEY_TYPE); - } - } - - /** - * Implemented individually here because PlayerPickupItemEvent is deprecated on newer versions but this event - * doesn't exist on older versions - */ - @EventHandler - public void onEntityPickupItem(EntityPickupItemEvent event) { // Stop players without possession permission to pickup items - if (event.getEntity() instanceof Player) { - handlePlayerPickupItem((Player) event.getEntity(), event.getItem(), event::setCancelled); - } - } -} diff --git a/spigot/src/main/resources/plugin.yml b/spigot/src/main/resources/plugin.yml index 65abd113..45fbaddc 100644 --- a/spigot/src/main/resources/plugin.yml +++ b/spigot/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ main: dev.kejona.crossplatforms.spigot.CrossplatFormsSpigot name: CrossplatForms version: ${project_version} -api-version: 1.14 +api-version: 1.13 description: ${project_description} prefix: CForms authors: diff --git a/spigotcompat/adapter/build.gradle.kts b/spigotcompat/adapter/build.gradle.kts deleted file mode 100644 index 0a592efd..00000000 --- a/spigotcompat/adapter/build.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ - -dependencies { - compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") -} \ No newline at end of file diff --git a/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java b/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java deleted file mode 100644 index 4936f89c..00000000 --- a/spigotcompat/adapter/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java +++ /dev/null @@ -1,10 +0,0 @@ -package dev.kejona.crossplatforms.spigot.adapter; - -import org.bukkit.plugin.Plugin; - -public interface VersionAdapter { - - boolean customModelData(); - - NbtAccessor nbtAccessor(Plugin plugin); -} diff --git a/spigotcompat/all/build.gradle.kts b/spigotcompat/all/build.gradle.kts index 52585509..1a7829bd 100644 --- a/spigotcompat/all/build.gradle.kts +++ b/spigotcompat/all/build.gradle.kts @@ -1,6 +1,6 @@ dependencies { compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") - api(projects.spigotcompat.adapter) + api(projects.spigotcompat.common) api(projects.spigotcompat.v114R1) } \ No newline at end of file diff --git a/spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapters.java b/spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java similarity index 52% rename from spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapters.java rename to spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java index 04ea3700..95de7108 100644 --- a/spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapters.java +++ b/spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java @@ -1,5 +1,8 @@ -package dev.kejona.crossplatforms.spigot.adapter; +package dev.kejona.crossplatforms.spigot.v1_13_R2; +import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; +import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; import dev.kejonamc.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; import dev.kejonamc.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; @@ -13,12 +16,19 @@ public final class VersionAdapters { static { ADAPTERS.put("1_8_R3", Adapter_v1_8_R3::new); + + ADAPTERS.put("1_9_R2", Adapter_v1_9_R2::new); + ADAPTERS.put("1_10_R1", Adapter_v1_9_R2::new); + ADAPTERS.put("1_11_R1", Adapter_v1_9_R2::new); + + ADAPTERS.put("1_12_R1", Adapter_v1_12_R1::new); + ADAPTERS.put("1_13_R2", Adapter_v1_13_R2::new); ADAPTERS.put("1_14_R1", Adapter_v1_14_R1::new); } public static VersionAdapter adapterForVersion(String version) { if (!ADAPTERS.containsKey(version)) { - return new Adapter_v1_14_R1(); + return new Adapter_v1_14_R1(); // todo: improve this } return ADAPTERS.get(version).get(); diff --git a/spigotcompat/v1_12_R1/build.gradle.kts b/spigotcompat/v1_12_R1/build.gradle.kts new file mode 100644 index 00000000..f5a977e3 --- /dev/null +++ b/spigotcompat/v1_12_R1/build.gradle.kts @@ -0,0 +1,5 @@ + +dependencies { + compileOnly("org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT") + api(projects.spigotcompat.v19R2) +} \ No newline at end of file diff --git a/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java b/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java new file mode 100644 index 00000000..a69bf789 --- /dev/null +++ b/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java @@ -0,0 +1,15 @@ +package dev.kejona.crossplatforms.spigot.v1_12_R1; + +import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; +import dev.kejona.crossplatforms.spigot.v1_9_R2.SwapHandItemsListener; +import org.bukkit.plugin.Plugin; + +public class Adapter_v1_12_R1 extends Adapter_v1_9_R2 { + + @Override + public void registerAuxiliaryEvents(Plugin plugin, SpigotAccessItems items) { + plugin.getServer().getPluginManager().registerEvents(new EntityPlayerPickupItemListener(items), plugin); + plugin.getServer().getPluginManager().registerEvents(new SwapHandItemsListener(items), plugin); + } +} diff --git a/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java b/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java new file mode 100644 index 00000000..345b9af9 --- /dev/null +++ b/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java @@ -0,0 +1,21 @@ +package dev.kejona.crossplatforms.spigot.v1_12_R1; + +import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import lombok.AllArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPickupItemEvent; + +@AllArgsConstructor +public class EntityPlayerPickupItemListener implements Listener { + + private final SpigotAccessItems items; + + @EventHandler + public void onEntityPickupItem(EntityPickupItemEvent event) { + if (event.getEntity() instanceof Player) { + items.handlePlayerPickupItem((Player) event.getEntity(), event.getItem(), event); + } + } +} diff --git a/spigotcompat/v1_13_R2/build.gradle.kts b/spigotcompat/v1_13_R2/build.gradle.kts new file mode 100644 index 00000000..2fe75352 --- /dev/null +++ b/spigotcompat/v1_13_R2/build.gradle.kts @@ -0,0 +1,5 @@ + +dependencies { + compileOnly("org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT") + api(projects.spigotcompat.v112R1) +} \ No newline at end of file diff --git a/spigotcompat/v1_13_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/Adapter_v1_13_R2.java b/spigotcompat/v1_13_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/Adapter_v1_13_R2.java new file mode 100644 index 00000000..b8d73998 --- /dev/null +++ b/spigotcompat/v1_13_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/Adapter_v1_13_R2.java @@ -0,0 +1,15 @@ +package dev.kejona.crossplatforms.spigot.v1_13_R2; + +import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; +import org.bukkit.Material; + +public class Adapter_v1_13_R2 extends Adapter_v1_12_R1 { + + /** + * The flattening occurred during 1.13. This returns a different enum constant than previous versions. + */ + @Override + public Material playerHeadMaterial() { + return Material.PLAYER_HEAD; + } +} diff --git a/spigotcompat/v1_14_R1/build.gradle.kts b/spigotcompat/v1_14_R1/build.gradle.kts index 008cada5..153c9238 100644 --- a/spigotcompat/v1_14_R1/build.gradle.kts +++ b/spigotcompat/v1_14_R1/build.gradle.kts @@ -1,5 +1,5 @@ dependencies { compileOnly("org.spigotmc:spigot-api:1.14.4-R0.1-SNAPSHOT") - api(projects.spigotcompat.v18R3) + api(projects.spigotcompat.v113R2) } \ No newline at end of file diff --git a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java b/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java index fe3be8a4..32f6e3c9 100644 --- a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java +++ b/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java @@ -1,11 +1,15 @@ package dev.kejonamc.crossplatforms.spigot.v1_14_R1; -import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; -import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; import org.bukkit.plugin.Plugin; -public class Adapter_v1_14_R1 implements VersionAdapter { +public class Adapter_v1_14_R1 extends Adapter_v1_13_R2 { + /** + * Custom model data was added in 1.14 + * @return true + */ @Override public boolean customModelData() { return true; diff --git a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java b/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java index 0ec9bfc5..e86a97b7 100644 --- a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java +++ b/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java @@ -1,6 +1,6 @@ package dev.kejonamc.crossplatforms.spigot.v1_14_R1; -import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; import lombok.AllArgsConstructor; import org.bukkit.NamespacedKey; import org.bukkit.inventory.ItemStack; diff --git a/spigotcompat/v1_8_R3/build.gradle.kts b/spigotcompat/v1_8_R3/build.gradle.kts index 640663a0..0dbab374 100644 --- a/spigotcompat/v1_8_R3/build.gradle.kts +++ b/spigotcompat/v1_8_R3/build.gradle.kts @@ -2,5 +2,5 @@ dependencies { compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") implementation("de.tr7zw:item-nbt-api:2.11.1") - api(projects.spigotcompat.adapter) + api(projects.spigotCommon) } \ No newline at end of file diff --git a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java index f4abbbb2..ec137dff 100644 --- a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java +++ b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java @@ -1,7 +1,9 @@ package dev.kejonamc.crossplatforms.spigot.v1_8_R3; -import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; -import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; +import org.bukkit.Material; import org.bukkit.plugin.Plugin; public class Adapter_v1_8_R3 implements VersionAdapter { @@ -11,8 +13,19 @@ public boolean customModelData() { return false; } + @Override + public Material playerHeadMaterial() { + return Material.SKULL_ITEM; + } + @Override public NbtAccessor nbtAccessor(Plugin plugin) { return new LegacyNbtAccessor(plugin); } + + @Override + public void registerAuxiliaryEvents(Plugin plugin, SpigotAccessItems items) { + PlayerPickupItemListener listener = new PlayerPickupItemListener(items); + plugin.getServer().getPluginManager().registerEvents(listener, plugin); + } } diff --git a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java index 8a2ca438..80033a96 100644 --- a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java +++ b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java @@ -2,7 +2,7 @@ import de.tr7zw.changeme.nbtapi.NBTCompound; import de.tr7zw.changeme.nbtapi.NBTItem; -import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; diff --git a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java new file mode 100644 index 00000000..eec2759c --- /dev/null +++ b/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java @@ -0,0 +1,18 @@ +package dev.kejonamc.crossplatforms.spigot.v1_8_R3; + +import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import lombok.AllArgsConstructor; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerPickupItemEvent; + +@AllArgsConstructor +public class PlayerPickupItemListener implements Listener { + + private final SpigotAccessItems items; + + @EventHandler + public void onPlayerPickupItem(PlayerPickupItemEvent event) { + items.handlePlayerPickupItem(event.getPlayer(), event.getItem(), event); + } +} diff --git a/spigotcompat/v1_9_R2/build.gradle.kts b/spigotcompat/v1_9_R2/build.gradle.kts new file mode 100644 index 00000000..36a5ae3a --- /dev/null +++ b/spigotcompat/v1_9_R2/build.gradle.kts @@ -0,0 +1,5 @@ + +dependencies { + compileOnly("org.spigotmc:spigot-api:1.9.4-R0.1-SNAPSHOT") + api(projects.spigotcompat.v18R3) +} \ No newline at end of file diff --git a/spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java b/spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java new file mode 100644 index 00000000..4f618344 --- /dev/null +++ b/spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java @@ -0,0 +1,17 @@ +package dev.kejona.crossplatforms.spigot.v1_9_R2; + +import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import dev.kejonamc.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; +import org.bukkit.plugin.Plugin; + +public class Adapter_v1_9_R2 extends Adapter_v1_8_R3 { + + @Override + public void registerAuxiliaryEvents(Plugin plugin, SpigotAccessItems items) { + super.registerAuxiliaryEvents(plugin, items); + // register the PlayerPickupItemListener + + // Offhand was introduced in 1.9 + plugin.getServer().getPluginManager().registerEvents(new SwapHandItemsListener(items), plugin); + } +} diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SwapHandItemsListener.java b/spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java similarity index 79% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SwapHandItemsListener.java rename to spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java index 8c791e3f..b60fa5cb 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SwapHandItemsListener.java +++ b/spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java @@ -1,5 +1,6 @@ -package dev.kejona.crossplatforms.spigot.common; +package dev.kejona.crossplatforms.spigot.v1_9_R2; +import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; import lombok.AllArgsConstructor; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -12,7 +13,7 @@ public class SwapHandItemsListener implements Listener { @Nonnull - private final SpigotAccessItemsBase accessItems; + private final SpigotAccessItems accessItems; @EventHandler public void PlayerSwapHandItemsEvent(PlayerSwapHandItemsEvent event) { // Don't allow putting it in the offhand From 97ff9d0664d9064b803095d9d7690b5945cceb1e Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 12 Jan 2023 19:24:46 -0500 Subject: [PATCH 16/59] Cleanup modules/packages --- .../accessitem/InspectItemCommand.java | 8 +-- .../kejona/crossplatforms/CrossplatForms.java | 2 +- .../filler/InventoryFiller.java | 2 +- .../handler/BedrockHandler.java | 2 +- .../crossplatforms/interfacing/Interface.java | 2 +- .../interfacing/bedrock/BedrockForm.java | 8 +-- settings.gradle.kts | 52 ++++++++------ spigot-common/all/build.gradle.kts | 6 ++ .../spigot/v1_13_R2/VersionAdapters.java | 2 +- spigot-common/{ => common}/build.gradle.kts | 3 +- .../crossplatforms/spigot}/ClassNames.java | 2 +- .../spigot}/CloseMenuAction.java | 2 +- .../spigot}/GeyserHubConverter.java | 2 +- .../spigot}/SpigotAccessItems.java | 70 +++++++++---------- .../crossplatforms/spigot}/SpigotBase.java | 12 ++-- .../spigot}/SpigotInterfacer.java | 4 +- .../spigot}/adapter/NbtAccessor.java | 2 +- .../spigot}/adapter/VersionAdapter.java | 4 +- .../handler/PlaceholderAPIHandler.java | 2 +- .../spigot}/handler/SpigotCommandOrigin.java | 4 +- .../spigot}/handler/SpigotHandler.java | 2 +- .../spigot}/handler/SpigotPermissions.java | 2 +- .../spigot}/handler/SpigotPlayer.java | 6 +- .../spigot}/item/SpigotInventory.java | 4 +- .../spigot}/item/SpigotInventoryFactory.java | 4 +- .../spigot}/item/SpigotItem.java | 2 +- .../spigot}/GeyserHubConvertTest.java | 3 +- .../src/test/resources/access-items.yml | 1 - .../src/test/resources/bedrock-forms.yml | 0 .../src/test/resources/java-menus.yml | 2 +- .../src/test/resources/selector.yml | 1 - .../v1_12_R1/build.gradle.kts | 2 +- .../spigot/v1_12_R1/Adapter_v1_12_R1.java | 2 +- .../EntityPlayerPickupItemListener.java | 2 +- .../v1_13_R2/build.gradle.kts | 2 +- .../spigot/v1_13_R2/Adapter_v1_13_R2.java | 0 .../v1_14_R1/build.gradle.kts | 2 +- .../spigot/v1_14_R1/Adapter_v1_14_R1.java | 2 +- .../spigot/v1_14_R1/ModernNbtAccessor.java | 2 +- .../v1_8_R3/build.gradle.kts | 2 +- .../spigot/v1_8_R3/Adapter_v1_8_R3.java | 6 +- .../spigot/v1_8_R3/LegacyNbtAccessor.java | 2 +- .../v1_8_R3/PlayerPickupItemListener.java | 2 +- .../v1_9_R2/build.gradle.kts | 2 +- .../spigot/v1_9_R2/Adapter_v1_9_R2.java | 2 +- .../spigot/v1_9_R2/SwapHandItemsListener.java | 2 +- spigot/build.gradle.kts | 2 +- .../spigot/CrossplatFormsSpigot.java | 4 +- spigot/src/main/resources/plugin.yml | 6 +- spigotcompat/all/build.gradle.kts | 6 -- 50 files changed, 136 insertions(+), 132 deletions(-) create mode 100644 spigot-common/all/build.gradle.kts rename {spigotcompat => spigot-common}/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java (94%) rename spigot-common/{ => common}/build.gradle.kts (75%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/ClassNames.java (94%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/CloseMenuAction.java (94%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/GeyserHubConverter.java (99%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/SpigotAccessItems.java (79%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/SpigotBase.java (94%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/SpigotInterfacer.java (96%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/adapter/NbtAccessor.java (92%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/adapter/VersionAdapter.java (70%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/handler/PlaceholderAPIHandler.java (96%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/handler/SpigotCommandOrigin.java (91%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/handler/SpigotHandler.java (99%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/handler/SpigotPermissions.java (98%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/handler/SpigotPlayer.java (94%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/item/SpigotInventory.java (90%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/item/SpigotInventoryFactory.java (95%) rename spigot-common/{src/main/java/dev/kejona/crossplatforms/spigot/common => common/src/main/java/dev/kejona/crossplatforms/spigot}/item/SpigotItem.java (84%) rename spigot-common/{src/test/java => common/src/test/java/dev/kejona/crossplatforms/spigot}/GeyserHubConvertTest.java (97%) rename spigot-common/{ => common}/src/test/resources/access-items.yml (99%) rename spigot-common/{ => common}/src/test/resources/bedrock-forms.yml (100%) rename spigot-common/{ => common}/src/test/resources/java-menus.yml (98%) rename spigot-common/{ => common}/src/test/resources/selector.yml (99%) rename {spigotcompat => spigot-common}/v1_12_R1/build.gradle.kts (68%) rename {spigotcompat => spigot-common}/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java (90%) rename {spigotcompat => spigot-common}/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java (90%) rename {spigotcompat => spigot-common}/v1_13_R2/build.gradle.kts (68%) rename {spigotcompat => spigot-common}/v1_13_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/Adapter_v1_13_R2.java (100%) rename {spigotcompat => spigot-common}/v1_14_R1/build.gradle.kts (68%) rename {spigotcompat => spigot-common}/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java (87%) rename {spigotcompat => spigot-common}/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java (95%) rename {spigotcompat => spigot-common}/v1_8_R3/build.gradle.kts (77%) rename {spigotcompat => spigot-common}/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java (78%) rename {spigotcompat => spigot-common}/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java (96%) rename {spigotcompat => spigot-common}/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java (88%) rename {spigotcompat => spigot-common}/v1_9_R2/build.gradle.kts (68%) rename {spigotcompat => spigot-common}/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java (89%) rename {spigotcompat => spigot-common}/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java (91%) delete mode 100644 spigotcompat/all/build.gradle.kts diff --git a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java index f5ce45de..3ecd3e74 100644 --- a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java +++ b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java @@ -25,20 +25,20 @@ public void register(CommandManager manager, Command.BuildernewBuilder("item") + .literal("dev.kejona.crossplatforms.spigot.item") + .argument(StringArgument.newBuilder("dev.kejona.crossplatforms.spigot.item") .withSuggestionsProvider(((context, s) -> itemRegistry.getItems().values() .stream() .map(AccessItem::getIdentifier) .collect(Collectors.toList())))) .handler(context -> { CommandOrigin origin = context.getSender(); - String name = context.get("item"); + String name = context.get("dev.kejona.crossplatforms.spigot.item"); AccessItem item = itemRegistry.getItems().get(name); if (item == null) { origin.warn("That Access Item doesn't exist!"); } else { - origin.sendMessage("Inspection of access item: " + name); + origin.sendMessage("Inspection of access dev.kejona.crossplatforms.spigot.item: " + name); origin.sendMessage(item.toString()); } }) diff --git a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java index f75147bf..449060d4 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java +++ b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java @@ -168,7 +168,7 @@ public CrossplatForms(Logger logger, // The top of our command tree commandBuilder = commandManager.commandBuilder(rootCommand); - // The handler for the root /forms command + // The dev.kejona.crossplatforms.spigot.handler for the root /forms command commandManager.command(commandBuilder .permission(FormsCommand.PERMISSION_BASE + "base") .handler((context -> { diff --git a/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java b/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java index 88964d8b..f78805cc 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java +++ b/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java @@ -19,7 +19,7 @@ default List generateItems(Resolver resolver) { } throw new IllegalStateException("Item generation not implemented yet"); - // return rawItems(resolver).map(item -> item.format(format)).collect(Collectors.toList()); + // return rawItems(resolver).map(dev.kejona.crossplatforms.spigot.item -> dev.kejona.crossplatforms.spigot.item.format(format)).collect(Collectors.toList()); } @Nonnull diff --git a/core/src/main/java/dev/kejona/crossplatforms/handler/BedrockHandler.java b/core/src/main/java/dev/kejona/crossplatforms/handler/BedrockHandler.java index a2ee5a40..ca22b4b4 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/handler/BedrockHandler.java +++ b/core/src/main/java/dev/kejona/crossplatforms/handler/BedrockHandler.java @@ -14,7 +14,7 @@ public interface BedrockHandler { /** * Determines if this BedrockHandler executes Form response handlers in a way that allows for thread safe access to the - * server API of the given implementation. For example, Floodgate executes response handler on Bukkit's main thread, + * server API of the given implementation. For example, Floodgate executes response dev.kejona.crossplatforms.spigot.handler on Bukkit's main thread, * but Geyser doesn't. On proxy implementations like BungeeCord or Velocity where there is no "main thread", this method * is not as meaningful. * diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java index 8a270fb6..5f8cb295 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java @@ -120,7 +120,7 @@ public void generatePermissions(InterfaceConfig registry) { ImmutableMap.Builder builder = ImmutableMap.builder(); for (Interface.Limit limit : Interface.Limit.values()) { // Alright this is a bit janky. 1st, attempt to retrieve the permission default from this specific config. - // If it is not specified for this item, then we check the global permission defaults. + // If it is not specified for this dev.kejona.crossplatforms.spigot.item, then we check the global permission defaults. // If the user has not specified anything in the globals, then we use fallback values PermissionDefault permissionDefault = permissionDefaults.getOrDefault(limit, registry.getGlobalPermissionDefaults().getOrDefault(limit, limit.fallbackDefault)); builder.put(limit, new Permission(mainPermission + limit.permissionSuffix, limit.description, permissionDefault)); diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockForm.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockForm.java index 533275f4..cc353da7 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockForm.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockForm.java @@ -37,17 +37,17 @@ public abstract class BedrockForm extends Interface implements ValuedType { private List> incorrectActions = Collections.emptyList(); /** - * Properly execute the response handler of a form, taking into account thread safety - * @param runnable The response handler to execute + * Properly execute the response dev.kejona.crossplatforms.spigot.handler of a form, taking into account thread safety + * @param runnable The response dev.kejona.crossplatforms.spigot.handler to execute * @see Runnable#run() */ protected final void executeHandler(Runnable runnable) { if (bedrockHandler.executesResponseHandlersSafely()) { - Logger.get().debug("Executing response handler on this thread: " + Thread.currentThread().getName()); + Logger.get().debug("Executing response dev.kejona.crossplatforms.spigot.handler on this thread: " + Thread.currentThread().getName()); runnable.run(); } else { serverHandler.executeSafely(() -> { - Logger.get().debug("Executing response handler on thread: " + Thread.currentThread().getName()); + Logger.get().debug("Executing response dev.kejona.crossplatforms.spigot.handler on thread: " + Thread.currentThread().getName()); runnable.run(); }); } diff --git a/settings.gradle.kts b/settings.gradle.kts index efc49a15..6e4d345e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,14 +2,6 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") rootProject.name = "CrossplatForms" -include(":core") -include(":proxy") -include(":bungeecord") -include(":velocity") -include(":access-item") -include(":spigot-common") -include(":spigot") - pluginManagement { repositories { gradlePluginPortal() @@ -38,17 +30,33 @@ dependencyResolutionManagement { maven("https://nexus.velocitypowered.com/repository/maven-public/") // velocity } } -include("spigotcompat:v1_8_R3") -findProject(":spigotcompat:v1_8_R3")?.name = "v1_8_R3" -include("spigotcompat:common") -findProject(":spigotcompat:common")?.name = "common" -include("spigotcompat:all") -findProject(":spigotcompat:all")?.name = "all" -include("spigotcompat:v1_14_R1") -findProject(":spigotcompat:v1_14_R1")?.name = "v1_14_R1" -include("spigotcompat:v1_13_R2") -findProject(":spigotcompat:v1_13_R2")?.name = "v1_13_R2" -include("spigotcompat:v1_12_R1") -findProject(":spigotcompat:v1_12_R1")?.name = "v1_12_R1" -include("spigotcompat:v1_9_R2") -findProject(":spigotcompat:v1_9_R2")?.name = "v1_9_R2" + +include(":core") +include(":access-item") + +include(":proxy") +include(":bungeecord") +include(":velocity") + +include(":spigot") + +include(":spigot-common:all") +findProject(":spigot-common:all")?.name = "all" + +include(":spigot-common:common") +findProject(":spigot-common:common")?.name = "common" + +include(":spigot-common:v1_8_R3") +findProject(":spigot-common:v1_8_R3")?.name = "v1_8_R3" + +include(":spigot-common:v1_9_R2") +findProject(":spigot-common:v1_9_R2")?.name = "v1_9_R2" + +include(":spigot-common:v1_12_R1") +findProject(":spigot-common:v1_12_R1")?.name = "v1_12_R1" + +include(":spigot-common:v1_13_R2") +findProject(":spigot-common:v1_13_R2")?.name = "v1_13_R2" + +include(":spigot-common:v1_14_R1") +findProject(":spigot-common:v1_14_R1")?.name = "v1_14_R1" diff --git a/spigot-common/all/build.gradle.kts b/spigot-common/all/build.gradle.kts new file mode 100644 index 00000000..9333a61f --- /dev/null +++ b/spigot-common/all/build.gradle.kts @@ -0,0 +1,6 @@ + +dependencies { + compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") + api(projects.spigotCommon.common) + implementation(projects.spigotCommon.v114R1) +} \ No newline at end of file diff --git a/spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java similarity index 94% rename from spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java rename to spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java index 95de7108..55ae27e9 100644 --- a/spigotcompat/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java +++ b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java @@ -1,6 +1,6 @@ package dev.kejona.crossplatforms.spigot.v1_13_R2; -import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; import dev.kejonamc.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; diff --git a/spigot-common/build.gradle.kts b/spigot-common/common/build.gradle.kts similarity index 75% rename from spigot-common/build.gradle.kts rename to spigot-common/common/build.gradle.kts index 2eae1db1..e6528232 100644 --- a/spigot-common/build.gradle.kts +++ b/spigot-common/common/build.gradle.kts @@ -2,8 +2,7 @@ dependencies { testImplementation(testFixtures(projects.core)) - // 1.8.8 is supported but we target 1.9.4 to use PlayerSwapItemEvent if on 1.9.4 or above - compileOnly("org.spigotmc:spigot-api:1.9.4-R0.1-SNAPSHOT") + compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") compileOnly("com.mojang:authlib:1.5.21") // Mirrored from floodgate-spigot - probably the version from 1.8.8 compileOnly("me.clip:placeholderapi:2.11.2") api(projects.core) diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/ClassNames.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/ClassNames.java similarity index 94% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/ClassNames.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/ClassNames.java index f3ba1c84..38eb8528 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/ClassNames.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/ClassNames.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common; +package dev.kejona.crossplatforms.spigot; import dev.kejona.crossplatforms.utils.ReflectionUtils; import org.bukkit.Bukkit; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/CloseMenuAction.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/CloseMenuAction.java similarity index 94% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/CloseMenuAction.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/CloseMenuAction.java index bdd59d83..6d866c46 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/CloseMenuAction.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/CloseMenuAction.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common; +package dev.kejona.crossplatforms.spigot; import dev.kejona.crossplatforms.action.ActionSerializer; import dev.kejona.crossplatforms.action.GenericAction; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/GeyserHubConverter.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/GeyserHubConverter.java similarity index 99% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/GeyserHubConverter.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/GeyserHubConverter.java index 72d3819a..7ead7bda 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/GeyserHubConverter.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/GeyserHubConverter.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common; +package dev.kejona.crossplatforms.spigot; import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.permission.PermissionDefault; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItems.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java similarity index 79% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItems.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java index 4e14fcf8..fd36ee20 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotAccessItems.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common; +package dev.kejona.crossplatforms.spigot; import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.accessitem.AccessItem; @@ -9,9 +9,9 @@ import dev.kejona.crossplatforms.handler.Placeholders; import dev.kejona.crossplatforms.interfacing.Interfacer; import dev.kejona.crossplatforms.permission.Permissions; -import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; -import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; -import dev.kejona.crossplatforms.spigot.common.handler.SpigotPlayer; +import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.handler.SpigotPlayer; import lombok.AllArgsConstructor; import org.bukkit.Material; import org.bukkit.entity.HumanEntity; @@ -85,14 +85,14 @@ public ItemStack createItemStack(AccessItem accessItem, Player player) { // Have not checked any other versions Material material = Material.matchMaterial(accessItem.getMaterial()); if (material == null) { - logger.severe(String.format("Failed to get access item from '%s' for access item '%s'", accessItem.getMaterial(), accessItem.getIdentifier())); + logger.severe(String.format("Failed to get access dev.kejona.crossplatforms.spigot.item from '%s' for access dev.kejona.crossplatforms.spigot.item '%s'", accessItem.getMaterial(), accessItem.getIdentifier())); material = Material.COMPASS; } ItemStack item = new ItemStack(material); ItemMeta meta = item.getItemMeta(); if (meta == null) { - logger.severe(String.format("Itemstack from material %s for access item %s has null item meta!", material, accessItem.getIdentifier())); + logger.severe(String.format("Itemstack from material %s for access dev.kejona.crossplatforms.spigot.item %s has null dev.kejona.crossplatforms.spigot.item meta!", material, accessItem.getIdentifier())); item = new ItemStack(Material.COMPASS); meta = Objects.requireNonNull(item.getItemMeta()); } @@ -111,26 +111,26 @@ public void onInteract(PlayerInteractEvent event) { // opening menus through acc if (item != null) { String id = getItemId(item); if (id != null) { - // Don't allow using the item to break blocks - // If it was a right click, using the access item should be the only behaviour + // Don't allow using the dev.kejona.crossplatforms.spigot.item to break blocks + // If it was a right click, using the access dev.kejona.crossplatforms.spigot.item should be the only behaviour event.setCancelled(true); Player player = event.getPlayer(); if (isEnabled()) { AccessItem access = getItem(id); if (access == null) { - // item not longer exists + // dev.kejona.crossplatforms.spigot.item not longer exists remove(player, item, RemoveReason.ITEM_REMOVED); } else if (player.hasPermission(access.permission(AccessItem.Limit.POSSESS))) { if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) { access.trigger(new SpigotPlayer(player)); } } else { - // player no longer has permission to have the item + // player no longer has permission to have the dev.kejona.crossplatforms.spigot.item remove(player, item, RemoveReason.IMPERMISSIBLE); } } else { - // item no longer exists because the registry has been disabled + // dev.kejona.crossplatforms.spigot.item no longer exists because the registry has been disabled remove(player, item, RemoveReason.ITEMS_DISABLED); } } @@ -145,7 +145,7 @@ public void onInventoryClick(InventoryClickEvent event) { // keep the access ite if (item != null) { String id = getItemId(item); if (id != null) { - // the item is or was an access item + // the dev.kejona.crossplatforms.spigot.item is or was an access dev.kejona.crossplatforms.spigot.item HumanEntity human = event.getWhoClicked(); if (isEnabled()) { @@ -176,12 +176,12 @@ public void onPlayerDropItem(PlayerDropItemEvent event) { // restricting droppin AccessItem access = getItem(id); Player player = event.getPlayer(); if (access == null) { - // access item no longer exists + // access dev.kejona.crossplatforms.spigot.item no longer exists player.sendMessage(RemoveReason.ITEM_REMOVED.message); event.getItemDrop().remove(); } else if (player.hasPermission(access.permission(AccessItem.Limit.DROP))) { if (!player.hasPermission(access.permission(AccessItem.Limit.PRESERVE))) { - // has permission to "drop" it but the item is destroyed + // has permission to "drop" it but the dev.kejona.crossplatforms.spigot.item is destroyed event.getItemDrop().remove(); } } else { @@ -200,8 +200,8 @@ public void onPlayerDeath(PlayerDeathEvent event) { // restricting dropping if (id != null) { AccessItem access = getItem(id); if (access == null || !player.hasPermission(access.permission(AccessItem.Limit.PRESERVE))) { - // the access item no longer exists and should be removed - // OR the player no longer has permission for it, so the item should be removed. + // the access dev.kejona.crossplatforms.spigot.item no longer exists and should be removed + // OR the player no longer has permission for it, so the dev.kejona.crossplatforms.spigot.item should be removed. iterator.remove(); } } @@ -209,12 +209,12 @@ public void onPlayerDeath(PlayerDeathEvent event) { // restricting dropping } @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { // give the access item when the player joins + public void onPlayerJoin(PlayerJoinEvent event) { // give the access dev.kejona.crossplatforms.spigot.item when the player joins regive(event.getPlayer(), AccessItem::isOnJoin); } @EventHandler - public void onPlayerRespawn(PlayerRespawnEvent event) { // give the access item when the player respawns + public void onPlayerRespawn(PlayerRespawnEvent event) { // give the access dev.kejona.crossplatforms.spigot.item when the player respawns regive(event.getPlayer(), AccessItem::isOnRespawn); } @@ -232,8 +232,8 @@ public void onPlayerLeave(PlayerQuitEvent event) { if (id != null) { AccessItem access = getItem(id); if (access == null || !access.isPersist()) { - // the access item no longer exists and should be removed - // OR the access item is not allowed to be persisted + // the access dev.kejona.crossplatforms.spigot.item no longer exists and should be removed + // OR the access dev.kejona.crossplatforms.spigot.item is not allowed to be persisted // we could check for permission to have it here, but that'll happen when they join again player.getInventory().remove(item); @@ -248,7 +248,7 @@ public void handlePlayerPickupItem(Player player, Item item, Cancellable event) if (id != null) { AccessItem access = getItem(id); if (access == null) { - // the item no longer exists, don't allow picking it up + // the dev.kejona.crossplatforms.spigot.item no longer exists, don't allow picking it up event.setCancelled(true); } else if (!player.hasPermission(access.permission(AccessItem.Limit.POSSESS))) { // they don't have permission to have it @@ -272,12 +272,12 @@ private void regive(Player player, Predicate give) { if (id != null) { AccessItem access = getItem(id); if (access == null) { - // access item no longer exists + // access dev.kejona.crossplatforms.spigot.item no longer exists player.getInventory().remove(item); } else { if (player.hasPermission(access.permission(AccessItem.Limit.POSSESS))) { contained.add(access.getIdentifier()); - logger.debug(String.format("%s is keeping access item %s", player.getName(), access.getIdentifier())); + logger.debug(String.format("%s is keeping access dev.kejona.crossplatforms.spigot.item %s", player.getName(), access.getIdentifier())); } else { player.getInventory().remove(item); logger.debug(String.format("Removed %s from %s because they don't have permission for it", access.getIdentifier(), player.getName())); @@ -288,7 +288,7 @@ private void regive(Player player, Predicate give) { } // Give any access items that should be given - boolean changedHand = false; // If we have changed the item the player is holding + boolean changedHand = false; // If we have changed the dev.kejona.crossplatforms.spigot.item the player is holding for (AccessItem access : getItems().values()) { if (give.test(access) && access.getPlatform().matches(player.getUniqueId(), bedrockHandler) && player.hasPermission(access.permission(AccessItem.Limit.EVENT))) { if (!contained.contains(access.getIdentifier())) { @@ -300,9 +300,9 @@ private void regive(Player player, Predicate give) { giveAccessItem(new SpigotPlayer(player), access, false); } - logger.debug(String.format("Gave access item %s to %s", access.getIdentifier(), player.getName())); + logger.debug(String.format("Gave access dev.kejona.crossplatforms.spigot.item %s to %s", access.getIdentifier(), player.getName())); } else { - logger.debug(String.format("%s has permission for access item %s, but they already have it", player.getName(), access.getIdentifier())); + logger.debug(String.format("%s has permission for access dev.kejona.crossplatforms.spigot.item %s, but they already have it", player.getName(), access.getIdentifier())); } } } @@ -314,11 +314,11 @@ public boolean giveAccessItem(FormPlayer player, AccessItem accessItem, boolean } /** - * Gives a player an access item - * @param player The player to give the access item to - * @param accessItem The access item to give - * @param setHeldSlot True if the player's selected item should be forced to the access item - * @return True if the access item was successfully given. False if the inventory was too full. + * Gives a player an access dev.kejona.crossplatforms.spigot.item + * @param player The player to give the access dev.kejona.crossplatforms.spigot.item to + * @param accessItem The access dev.kejona.crossplatforms.spigot.item to give + * @param setHeldSlot True if the player's selected dev.kejona.crossplatforms.spigot.item should be forced to the access dev.kejona.crossplatforms.spigot.item + * @return True if the access dev.kejona.crossplatforms.spigot.item was successfully given. False if the inventory was too full. */ public boolean giveAccessItem(Player player, AccessItem accessItem, boolean setHeldSlot) { ItemStack accessItemStack = createItemStack(accessItem, player); // todo update placeholders after the fact. but when? @@ -327,7 +327,7 @@ public boolean giveAccessItem(Player player, AccessItem accessItem, boolean setH ItemStack blockingItem = player.getInventory().getItem(desiredSlot); boolean success = false; if (blockingItem == null || blockingItem.getType() == Material.AIR) { - // put the item in the desired place + // put the dev.kejona.crossplatforms.spigot.item in the desired place player.getInventory().setItem(desiredSlot, accessItemStack); success = true; } else { @@ -336,9 +336,9 @@ public boolean giveAccessItem(Player player, AccessItem accessItem, boolean setH ItemStack otherItem = player.getInventory().getItem(i); if (otherItem == null || otherItem.getType() == Material.AIR) { - // slot is empty, move the item that is blocking us to it + // slot is empty, move the dev.kejona.crossplatforms.spigot.item that is blocking us to it player.getInventory().setItem(i, blockingItem); - // put the access item in the slot that is no longer blocked + // put the access dev.kejona.crossplatforms.spigot.item in the slot that is no longer blocked player.getInventory().setItem(desiredSlot, accessItemStack); success = true; break; @@ -349,7 +349,7 @@ public boolean giveAccessItem(Player player, AccessItem accessItem, boolean setH if (success) { if (setHeldSlot) { - // Set the held item to the slot of the access item + // Set the held dev.kejona.crossplatforms.spigot.item to the slot of the access dev.kejona.crossplatforms.spigot.item player.getInventory().setHeldItemSlot(accessItem.getSlot()); } return true; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java similarity index 94% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java index 6f9d7542..dae9c605 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotBase.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common; +package dev.kejona.crossplatforms.spigot; import cloud.commandframework.bukkit.BukkitCommandManager; import cloud.commandframework.execution.CommandExecutionCoordinator; @@ -21,11 +21,11 @@ import dev.kejona.crossplatforms.interfacing.Interfacer; import dev.kejona.crossplatforms.permission.LuckPermsHook; import dev.kejona.crossplatforms.permission.Permissions; -import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; -import dev.kejona.crossplatforms.spigot.common.handler.PlaceholderAPIHandler; -import dev.kejona.crossplatforms.spigot.common.handler.SpigotCommandOrigin; -import dev.kejona.crossplatforms.spigot.common.handler.SpigotHandler; -import dev.kejona.crossplatforms.spigot.common.handler.SpigotPermissions; +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.handler.PlaceholderAPIHandler; +import dev.kejona.crossplatforms.spigot.handler.SpigotCommandOrigin; +import dev.kejona.crossplatforms.spigot.handler.SpigotHandler; +import dev.kejona.crossplatforms.spigot.handler.SpigotPermissions; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotInterfacer.java similarity index 96% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotInterfacer.java index 8fa5d2b0..b19967a4 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/SpigotInterfacer.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotInterfacer.java @@ -1,10 +1,10 @@ -package dev.kejona.crossplatforms.spigot.common; +package dev.kejona.crossplatforms.spigot; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.interfacing.Interfacer; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; import dev.kejona.crossplatforms.resolver.Resolver; -import dev.kejona.crossplatforms.spigot.common.handler.SpigotPlayer; +import dev.kejona.crossplatforms.spigot.handler.SpigotPlayer; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/NbtAccessor.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java similarity index 92% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/NbtAccessor.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java index 60a6f4d4..54f428ac 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/NbtAccessor.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common.adapter; +package dev.kejona.crossplatforms.spigot.adapter; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/VersionAdapter.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java similarity index 70% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/VersionAdapter.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java index 25d5ff16..88f38672 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/adapter/VersionAdapter.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java @@ -1,6 +1,6 @@ -package dev.kejona.crossplatforms.spigot.common.adapter; +package dev.kejona.crossplatforms.spigot.adapter; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import org.bukkit.Material; import org.bukkit.plugin.Plugin; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/PlaceholderAPIHandler.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/PlaceholderAPIHandler.java similarity index 96% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/PlaceholderAPIHandler.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/PlaceholderAPIHandler.java index 7fdbed25..d419a114 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/PlaceholderAPIHandler.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/PlaceholderAPIHandler.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common.handler; +package dev.kejona.crossplatforms.spigot.handler; import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.handler.FormPlayer; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotCommandOrigin.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotCommandOrigin.java similarity index 91% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotCommandOrigin.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotCommandOrigin.java index 77901ce6..be84914a 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotCommandOrigin.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotCommandOrigin.java @@ -1,7 +1,7 @@ -package dev.kejona.crossplatforms.spigot.common.handler; +package dev.kejona.crossplatforms.spigot.handler; import dev.kejona.crossplatforms.command.CommandOrigin; -import dev.kejona.crossplatforms.spigot.common.SpigotBase; +import dev.kejona.crossplatforms.spigot.SpigotBase; import lombok.AllArgsConstructor; import lombok.Getter; import net.kyori.adventure.text.TextComponent; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotHandler.java similarity index 99% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotHandler.java index 3273accd..652b0768 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotHandler.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotHandler.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common.handler; +package dev.kejona.crossplatforms.spigot.handler; import dev.kejona.crossplatforms.CrossplatForms; import dev.kejona.crossplatforms.command.CommandOrigin; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPermissions.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPermissions.java similarity index 98% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPermissions.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPermissions.java index 592ac587..a9b1bcf2 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPermissions.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPermissions.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common.handler; +package dev.kejona.crossplatforms.spigot.handler; import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.permission.Permission; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPlayer.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPlayer.java similarity index 94% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPlayer.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPlayer.java index 0040ff15..373bda4a 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/handler/SpigotPlayer.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPlayer.java @@ -1,11 +1,11 @@ -package dev.kejona.crossplatforms.spigot.common.handler; +package dev.kejona.crossplatforms.spigot.handler; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.handler.FormPlayer; -import dev.kejona.crossplatforms.spigot.common.ClassNames; -import dev.kejona.crossplatforms.spigot.common.SpigotBase; +import dev.kejona.crossplatforms.spigot.ClassNames; +import dev.kejona.crossplatforms.spigot.SpigotBase; import dev.kejona.crossplatforms.utils.ReflectionUtils; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventory.java similarity index 90% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventory.java index 94d0615f..1a9b1c0d 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventory.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventory.java @@ -1,12 +1,10 @@ -package dev.kejona.crossplatforms.spigot.common.item; +package dev.kejona.crossplatforms.spigot.item; import dev.kejona.crossplatforms.item.Inventory; import dev.kejona.crossplatforms.item.InventoryLayout; import dev.kejona.crossplatforms.item.Item; -import lombok.RequiredArgsConstructor; import org.bukkit.Bukkit; import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.ItemStack; public class SpigotInventory implements Inventory { diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java similarity index 95% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java index 998af5f7..4017c54d 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotInventoryFactory.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common.item; +package dev.kejona.crossplatforms.spigot.item; import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.handler.FormPlayer; @@ -6,7 +6,7 @@ import dev.kejona.crossplatforms.item.InventoryFactory; import dev.kejona.crossplatforms.item.InventoryLayout; import dev.kejona.crossplatforms.item.Item; -import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; diff --git a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotItem.java similarity index 84% rename from spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotItem.java index 13847278..f43c17aa 100644 --- a/spigot-common/src/main/java/dev/kejona/crossplatforms/spigot/common/item/SpigotItem.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotItem.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot.common.item; +package dev.kejona.crossplatforms.spigot.item; import dev.kejona.crossplatforms.item.Item; import lombok.RequiredArgsConstructor; diff --git a/spigot-common/src/test/java/GeyserHubConvertTest.java b/spigot-common/common/src/test/java/dev/kejona/crossplatforms/spigot/GeyserHubConvertTest.java similarity index 97% rename from spigot-common/src/test/java/GeyserHubConvertTest.java rename to spigot-common/common/src/test/java/dev/kejona/crossplatforms/spigot/GeyserHubConvertTest.java index 7966d0c6..f0c551ea 100644 --- a/spigot-common/src/test/java/GeyserHubConvertTest.java +++ b/spigot-common/common/src/test/java/dev/kejona/crossplatforms/spigot/GeyserHubConvertTest.java @@ -1,6 +1,7 @@ +package dev.kejona.crossplatforms.spigot; + import dev.kejona.crossplatforms.TestLogger; import dev.kejona.crossplatforms.config.PrettyPrinter; -import dev.kejona.crossplatforms.spigot.common.GeyserHubConverter; import dev.kejona.crossplatforms.utils.FileUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; diff --git a/spigot-common/src/test/resources/access-items.yml b/spigot-common/common/src/test/resources/access-items.yml similarity index 99% rename from spigot-common/src/test/resources/access-items.yml rename to spigot-common/common/src/test/resources/access-items.yml index c912d5f8..8e5f3bc3 100644 --- a/spigot-common/src/test/resources/access-items.yml +++ b/spigot-common/common/src/test/resources/access-items.yml @@ -29,4 +29,3 @@ items: form: minigames config-version: 3 - diff --git a/spigot-common/src/test/resources/bedrock-forms.yml b/spigot-common/common/src/test/resources/bedrock-forms.yml similarity index 100% rename from spigot-common/src/test/resources/bedrock-forms.yml rename to spigot-common/common/src/test/resources/bedrock-forms.yml diff --git a/spigot-common/src/test/resources/java-menus.yml b/spigot-common/common/src/test/resources/java-menus.yml similarity index 98% rename from spigot-common/src/test/resources/java-menus.yml rename to spigot-common/common/src/test/resources/java-menus.yml index 265318f0..690b90c4 100644 --- a/spigot-common/src/test/resources/java-menus.yml +++ b/spigot-common/common/src/test/resources/java-menus.yml @@ -53,4 +53,4 @@ menus: any-click: server: "hideseek" -config-version: 1 \ No newline at end of file +config-version: 1 diff --git a/spigot-common/src/test/resources/selector.yml b/spigot-common/common/src/test/resources/selector.yml similarity index 99% rename from spigot-common/src/test/resources/selector.yml rename to spigot-common/common/src/test/resources/selector.yml index b57bec25..54f59f21 100644 --- a/spigot-common/src/test/resources/selector.yml +++ b/spigot-common/common/src/test/resources/selector.yml @@ -154,4 +154,3 @@ Bedrock-Selector: # Don't touch this Config-Version: 2 - diff --git a/spigotcompat/v1_12_R1/build.gradle.kts b/spigot-common/v1_12_R1/build.gradle.kts similarity index 68% rename from spigotcompat/v1_12_R1/build.gradle.kts rename to spigot-common/v1_12_R1/build.gradle.kts index f5a977e3..7d138b08 100644 --- a/spigotcompat/v1_12_R1/build.gradle.kts +++ b/spigot-common/v1_12_R1/build.gradle.kts @@ -1,5 +1,5 @@ dependencies { compileOnly("org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT") - api(projects.spigotcompat.v19R2) + api(projects.spigotCommon.v19R2) } \ No newline at end of file diff --git a/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java b/spigot-common/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java similarity index 90% rename from spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java rename to spigot-common/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java index a69bf789..45651ddc 100644 --- a/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java +++ b/spigot-common/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/Adapter_v1_12_R1.java @@ -1,6 +1,6 @@ package dev.kejona.crossplatforms.spigot.v1_12_R1; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; import dev.kejona.crossplatforms.spigot.v1_9_R2.SwapHandItemsListener; import org.bukkit.plugin.Plugin; diff --git a/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java b/spigot-common/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java similarity index 90% rename from spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java rename to spigot-common/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java index 345b9af9..0b4d9144 100644 --- a/spigotcompat/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java +++ b/spigot-common/v1_12_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_12_R1/EntityPlayerPickupItemListener.java @@ -1,6 +1,6 @@ package dev.kejona.crossplatforms.spigot.v1_12_R1; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import lombok.AllArgsConstructor; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; diff --git a/spigotcompat/v1_13_R2/build.gradle.kts b/spigot-common/v1_13_R2/build.gradle.kts similarity index 68% rename from spigotcompat/v1_13_R2/build.gradle.kts rename to spigot-common/v1_13_R2/build.gradle.kts index 2fe75352..ee309565 100644 --- a/spigotcompat/v1_13_R2/build.gradle.kts +++ b/spigot-common/v1_13_R2/build.gradle.kts @@ -1,5 +1,5 @@ dependencies { compileOnly("org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT") - api(projects.spigotcompat.v112R1) + api(projects.spigotCommon.v112R1) } \ No newline at end of file diff --git a/spigotcompat/v1_13_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/Adapter_v1_13_R2.java b/spigot-common/v1_13_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/Adapter_v1_13_R2.java similarity index 100% rename from spigotcompat/v1_13_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/Adapter_v1_13_R2.java rename to spigot-common/v1_13_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/Adapter_v1_13_R2.java diff --git a/spigotcompat/v1_14_R1/build.gradle.kts b/spigot-common/v1_14_R1/build.gradle.kts similarity index 68% rename from spigotcompat/v1_14_R1/build.gradle.kts rename to spigot-common/v1_14_R1/build.gradle.kts index 153c9238..9a21a654 100644 --- a/spigotcompat/v1_14_R1/build.gradle.kts +++ b/spigot-common/v1_14_R1/build.gradle.kts @@ -1,5 +1,5 @@ dependencies { compileOnly("org.spigotmc:spigot-api:1.14.4-R0.1-SNAPSHOT") - api(projects.spigotcompat.v113R2) + api(projects.spigotCommon.v113R2) } \ No newline at end of file diff --git a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java b/spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java similarity index 87% rename from spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java rename to spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java index 32f6e3c9..57658a93 100644 --- a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java +++ b/spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java @@ -1,6 +1,6 @@ package dev.kejonamc.crossplatforms.spigot.v1_14_R1; -import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; import org.bukkit.plugin.Plugin; diff --git a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java b/spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java similarity index 95% rename from spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java rename to spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java index e86a97b7..0ec9bfc5 100644 --- a/spigotcompat/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java +++ b/spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java @@ -1,6 +1,6 @@ package dev.kejonamc.crossplatforms.spigot.v1_14_R1; -import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; import lombok.AllArgsConstructor; import org.bukkit.NamespacedKey; import org.bukkit.inventory.ItemStack; diff --git a/spigotcompat/v1_8_R3/build.gradle.kts b/spigot-common/v1_8_R3/build.gradle.kts similarity index 77% rename from spigotcompat/v1_8_R3/build.gradle.kts rename to spigot-common/v1_8_R3/build.gradle.kts index 0dbab374..a64ac23d 100644 --- a/spigotcompat/v1_8_R3/build.gradle.kts +++ b/spigot-common/v1_8_R3/build.gradle.kts @@ -2,5 +2,5 @@ dependencies { compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") implementation("de.tr7zw:item-nbt-api:2.11.1") - api(projects.spigotCommon) + api(projects.spigotCommon.common) } \ No newline at end of file diff --git a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java b/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java similarity index 78% rename from spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java rename to spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java index ec137dff..ef1ea7b5 100644 --- a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java +++ b/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java @@ -1,8 +1,8 @@ package dev.kejonamc.crossplatforms.spigot.v1_8_R3; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; -import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; -import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.SpigotAccessItems; +import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; import org.bukkit.Material; import org.bukkit.plugin.Plugin; diff --git a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java b/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java similarity index 96% rename from spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java rename to spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java index 80033a96..8a2ca438 100644 --- a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java +++ b/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java @@ -2,7 +2,7 @@ import de.tr7zw.changeme.nbtapi.NBTCompound; import de.tr7zw.changeme.nbtapi.NBTItem; -import dev.kejona.crossplatforms.spigot.common.adapter.NbtAccessor; +import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; diff --git a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java b/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java similarity index 88% rename from spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java rename to spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java index eec2759c..c3700235 100644 --- a/spigotcompat/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java +++ b/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java @@ -1,6 +1,6 @@ package dev.kejonamc.crossplatforms.spigot.v1_8_R3; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import lombok.AllArgsConstructor; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/spigotcompat/v1_9_R2/build.gradle.kts b/spigot-common/v1_9_R2/build.gradle.kts similarity index 68% rename from spigotcompat/v1_9_R2/build.gradle.kts rename to spigot-common/v1_9_R2/build.gradle.kts index 36a5ae3a..b3f672a9 100644 --- a/spigotcompat/v1_9_R2/build.gradle.kts +++ b/spigot-common/v1_9_R2/build.gradle.kts @@ -1,5 +1,5 @@ dependencies { compileOnly("org.spigotmc:spigot-api:1.9.4-R0.1-SNAPSHOT") - api(projects.spigotcompat.v18R3) + api(projects.spigotCommon.v18R3) } \ No newline at end of file diff --git a/spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java b/spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java similarity index 89% rename from spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java rename to spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java index 4f618344..69409534 100644 --- a/spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java +++ b/spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java @@ -1,6 +1,6 @@ package dev.kejona.crossplatforms.spigot.v1_9_R2; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import dev.kejonamc.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; import org.bukkit.plugin.Plugin; diff --git a/spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java b/spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java similarity index 91% rename from spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java rename to spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java index b60fa5cb..f0b84353 100644 --- a/spigotcompat/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java +++ b/spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/SwapHandItemsListener.java @@ -1,6 +1,6 @@ package dev.kejona.crossplatforms.spigot.v1_9_R2; -import dev.kejona.crossplatforms.spigot.common.SpigotAccessItems; +import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import lombok.AllArgsConstructor; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index c94e0f01..a14fa96d 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -6,7 +6,7 @@ plugins { dependencies { compileOnly("org.spigotmc:spigot-api:1.14.4-R0.1-SNAPSHOT") - api(projects.spigotCommon) { + api(projects.spigotCommon.common) { // this should be overridden by the version specified here, but just making sure exclude(group = "org.spigotmc", module = "spigot-api") } diff --git a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java index 7def9ede..32974282 100644 --- a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java +++ b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java @@ -1,7 +1,7 @@ package dev.kejona.crossplatforms.spigot; -import dev.kejona.crossplatforms.spigot.common.SpigotBase; -import dev.kejona.crossplatforms.spigot.common.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.SpigotBase; +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; import org.bukkit.plugin.java.JavaPlugin; public class CrossplatFormsSpigot extends SpigotBase { diff --git a/spigot/src/main/resources/plugin.yml b/spigot/src/main/resources/plugin.yml index 45fbaddc..d2d692bf 100644 --- a/spigot/src/main/resources/plugin.yml +++ b/spigot/src/main/resources/plugin.yml @@ -34,13 +34,13 @@ permissions: description: Access to /forms send default: op crossplatforms.command.give: - description: Access to /forms give + description: Access to /forms give default: op crossplatforms.command.give.others: - description: Access to /forms give + description: Access to /forms give default: op crossplatforms.command.inspect: - description: Access to /forms inspect + description: Access to /forms inspect default: op crossplatforms.command.identify: description: Access to /forms identify diff --git a/spigotcompat/all/build.gradle.kts b/spigotcompat/all/build.gradle.kts deleted file mode 100644 index 1a7829bd..00000000 --- a/spigotcompat/all/build.gradle.kts +++ /dev/null @@ -1,6 +0,0 @@ - -dependencies { - compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") - api(projects.spigotcompat.common) - api(projects.spigotcompat.v114R1) -} \ No newline at end of file From c3e4d6aef37f927a96e797cf77daac604d932d83 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 12 Jan 2023 19:37:48 -0500 Subject: [PATCH 17/59] oops --- .../accessitem/InspectItemCommand.java | 8 +-- .../kejona/crossplatforms/CrossplatForms.java | 2 +- .../filler/InventoryFiller.java | 2 +- .../handler/BedrockHandler.java | 2 +- .../crossplatforms/interfacing/Interface.java | 2 +- .../interfacing/bedrock/BedrockForm.java | 8 +-- .../spigot/SpigotAccessItems.java | 62 +++++++++---------- spigot/src/main/resources/plugin.yml | 6 +- 8 files changed, 46 insertions(+), 46 deletions(-) diff --git a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java index 3ecd3e74..f5ce45de 100644 --- a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java +++ b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java @@ -25,20 +25,20 @@ public void register(CommandManager manager, Command.BuildernewBuilder("dev.kejona.crossplatforms.spigot.item") + .literal("item") + .argument(StringArgument.newBuilder("item") .withSuggestionsProvider(((context, s) -> itemRegistry.getItems().values() .stream() .map(AccessItem::getIdentifier) .collect(Collectors.toList())))) .handler(context -> { CommandOrigin origin = context.getSender(); - String name = context.get("dev.kejona.crossplatforms.spigot.item"); + String name = context.get("item"); AccessItem item = itemRegistry.getItems().get(name); if (item == null) { origin.warn("That Access Item doesn't exist!"); } else { - origin.sendMessage("Inspection of access dev.kejona.crossplatforms.spigot.item: " + name); + origin.sendMessage("Inspection of access item: " + name); origin.sendMessage(item.toString()); } }) diff --git a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java index 449060d4..f75147bf 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java +++ b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java @@ -168,7 +168,7 @@ public CrossplatForms(Logger logger, // The top of our command tree commandBuilder = commandManager.commandBuilder(rootCommand); - // The dev.kejona.crossplatforms.spigot.handler for the root /forms command + // The handler for the root /forms command commandManager.command(commandBuilder .permission(FormsCommand.PERMISSION_BASE + "base") .handler((context -> { diff --git a/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java b/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java index f78805cc..88964d8b 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java +++ b/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java @@ -19,7 +19,7 @@ default List generateItems(Resolver resolver) { } throw new IllegalStateException("Item generation not implemented yet"); - // return rawItems(resolver).map(dev.kejona.crossplatforms.spigot.item -> dev.kejona.crossplatforms.spigot.item.format(format)).collect(Collectors.toList()); + // return rawItems(resolver).map(item -> item.format(format)).collect(Collectors.toList()); } @Nonnull diff --git a/core/src/main/java/dev/kejona/crossplatforms/handler/BedrockHandler.java b/core/src/main/java/dev/kejona/crossplatforms/handler/BedrockHandler.java index ca22b4b4..a2ee5a40 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/handler/BedrockHandler.java +++ b/core/src/main/java/dev/kejona/crossplatforms/handler/BedrockHandler.java @@ -14,7 +14,7 @@ public interface BedrockHandler { /** * Determines if this BedrockHandler executes Form response handlers in a way that allows for thread safe access to the - * server API of the given implementation. For example, Floodgate executes response dev.kejona.crossplatforms.spigot.handler on Bukkit's main thread, + * server API of the given implementation. For example, Floodgate executes response handler on Bukkit's main thread, * but Geyser doesn't. On proxy implementations like BungeeCord or Velocity where there is no "main thread", this method * is not as meaningful. * diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java index 5f8cb295..8a270fb6 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/Interface.java @@ -120,7 +120,7 @@ public void generatePermissions(InterfaceConfig registry) { ImmutableMap.Builder builder = ImmutableMap.builder(); for (Interface.Limit limit : Interface.Limit.values()) { // Alright this is a bit janky. 1st, attempt to retrieve the permission default from this specific config. - // If it is not specified for this dev.kejona.crossplatforms.spigot.item, then we check the global permission defaults. + // If it is not specified for this item, then we check the global permission defaults. // If the user has not specified anything in the globals, then we use fallback values PermissionDefault permissionDefault = permissionDefaults.getOrDefault(limit, registry.getGlobalPermissionDefaults().getOrDefault(limit, limit.fallbackDefault)); builder.put(limit, new Permission(mainPermission + limit.permissionSuffix, limit.description, permissionDefault)); diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockForm.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockForm.java index cc353da7..533275f4 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockForm.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/bedrock/BedrockForm.java @@ -37,17 +37,17 @@ public abstract class BedrockForm extends Interface implements ValuedType { private List> incorrectActions = Collections.emptyList(); /** - * Properly execute the response dev.kejona.crossplatforms.spigot.handler of a form, taking into account thread safety - * @param runnable The response dev.kejona.crossplatforms.spigot.handler to execute + * Properly execute the response handler of a form, taking into account thread safety + * @param runnable The response handler to execute * @see Runnable#run() */ protected final void executeHandler(Runnable runnable) { if (bedrockHandler.executesResponseHandlersSafely()) { - Logger.get().debug("Executing response dev.kejona.crossplatforms.spigot.handler on this thread: " + Thread.currentThread().getName()); + Logger.get().debug("Executing response handler on this thread: " + Thread.currentThread().getName()); runnable.run(); } else { serverHandler.executeSafely(() -> { - Logger.get().debug("Executing response dev.kejona.crossplatforms.spigot.handler on thread: " + Thread.currentThread().getName()); + Logger.get().debug("Executing response handler on thread: " + Thread.currentThread().getName()); runnable.run(); }); } diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java index fd36ee20..68f0c9ec 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java @@ -85,14 +85,14 @@ public ItemStack createItemStack(AccessItem accessItem, Player player) { // Have not checked any other versions Material material = Material.matchMaterial(accessItem.getMaterial()); if (material == null) { - logger.severe(String.format("Failed to get access dev.kejona.crossplatforms.spigot.item from '%s' for access dev.kejona.crossplatforms.spigot.item '%s'", accessItem.getMaterial(), accessItem.getIdentifier())); + logger.severe(String.format("Failed to get access item from '%s' for access item '%s'", accessItem.getMaterial(), accessItem.getIdentifier())); material = Material.COMPASS; } ItemStack item = new ItemStack(material); ItemMeta meta = item.getItemMeta(); if (meta == null) { - logger.severe(String.format("Itemstack from material %s for access dev.kejona.crossplatforms.spigot.item %s has null dev.kejona.crossplatforms.spigot.item meta!", material, accessItem.getIdentifier())); + logger.severe(String.format("Itemstack from material %s for access item %s has null item meta!", material, accessItem.getIdentifier())); item = new ItemStack(Material.COMPASS); meta = Objects.requireNonNull(item.getItemMeta()); } @@ -111,26 +111,26 @@ public void onInteract(PlayerInteractEvent event) { // opening menus through acc if (item != null) { String id = getItemId(item); if (id != null) { - // Don't allow using the dev.kejona.crossplatforms.spigot.item to break blocks - // If it was a right click, using the access dev.kejona.crossplatforms.spigot.item should be the only behaviour + // Don't allow using the item to break blocks + // If it was a right click, using the access item should be the only behaviour event.setCancelled(true); Player player = event.getPlayer(); if (isEnabled()) { AccessItem access = getItem(id); if (access == null) { - // dev.kejona.crossplatforms.spigot.item not longer exists + // item not longer exists remove(player, item, RemoveReason.ITEM_REMOVED); } else if (player.hasPermission(access.permission(AccessItem.Limit.POSSESS))) { if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) { access.trigger(new SpigotPlayer(player)); } } else { - // player no longer has permission to have the dev.kejona.crossplatforms.spigot.item + // player no longer has permission to have the item remove(player, item, RemoveReason.IMPERMISSIBLE); } } else { - // dev.kejona.crossplatforms.spigot.item no longer exists because the registry has been disabled + // item no longer exists because the registry has been disabled remove(player, item, RemoveReason.ITEMS_DISABLED); } } @@ -145,7 +145,7 @@ public void onInventoryClick(InventoryClickEvent event) { // keep the access ite if (item != null) { String id = getItemId(item); if (id != null) { - // the dev.kejona.crossplatforms.spigot.item is or was an access dev.kejona.crossplatforms.spigot.item + // the item is or was an access item HumanEntity human = event.getWhoClicked(); if (isEnabled()) { @@ -176,12 +176,12 @@ public void onPlayerDropItem(PlayerDropItemEvent event) { // restricting droppin AccessItem access = getItem(id); Player player = event.getPlayer(); if (access == null) { - // access dev.kejona.crossplatforms.spigot.item no longer exists + // access item no longer exists player.sendMessage(RemoveReason.ITEM_REMOVED.message); event.getItemDrop().remove(); } else if (player.hasPermission(access.permission(AccessItem.Limit.DROP))) { if (!player.hasPermission(access.permission(AccessItem.Limit.PRESERVE))) { - // has permission to "drop" it but the dev.kejona.crossplatforms.spigot.item is destroyed + // has permission to "drop" it but the item is destroyed event.getItemDrop().remove(); } } else { @@ -200,8 +200,8 @@ public void onPlayerDeath(PlayerDeathEvent event) { // restricting dropping if (id != null) { AccessItem access = getItem(id); if (access == null || !player.hasPermission(access.permission(AccessItem.Limit.PRESERVE))) { - // the access dev.kejona.crossplatforms.spigot.item no longer exists and should be removed - // OR the player no longer has permission for it, so the dev.kejona.crossplatforms.spigot.item should be removed. + // the access item no longer exists and should be removed + // OR the player no longer has permission for it, so the item should be removed. iterator.remove(); } } @@ -209,12 +209,12 @@ public void onPlayerDeath(PlayerDeathEvent event) { // restricting dropping } @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { // give the access dev.kejona.crossplatforms.spigot.item when the player joins + public void onPlayerJoin(PlayerJoinEvent event) { // give the access item when the player joins regive(event.getPlayer(), AccessItem::isOnJoin); } @EventHandler - public void onPlayerRespawn(PlayerRespawnEvent event) { // give the access dev.kejona.crossplatforms.spigot.item when the player respawns + public void onPlayerRespawn(PlayerRespawnEvent event) { // give the access item when the player respawns regive(event.getPlayer(), AccessItem::isOnRespawn); } @@ -232,8 +232,8 @@ public void onPlayerLeave(PlayerQuitEvent event) { if (id != null) { AccessItem access = getItem(id); if (access == null || !access.isPersist()) { - // the access dev.kejona.crossplatforms.spigot.item no longer exists and should be removed - // OR the access dev.kejona.crossplatforms.spigot.item is not allowed to be persisted + // the access item no longer exists and should be removed + // OR the access item is not allowed to be persisted // we could check for permission to have it here, but that'll happen when they join again player.getInventory().remove(item); @@ -248,7 +248,7 @@ public void handlePlayerPickupItem(Player player, Item item, Cancellable event) if (id != null) { AccessItem access = getItem(id); if (access == null) { - // the dev.kejona.crossplatforms.spigot.item no longer exists, don't allow picking it up + // the item no longer exists, don't allow picking it up event.setCancelled(true); } else if (!player.hasPermission(access.permission(AccessItem.Limit.POSSESS))) { // they don't have permission to have it @@ -272,12 +272,12 @@ private void regive(Player player, Predicate give) { if (id != null) { AccessItem access = getItem(id); if (access == null) { - // access dev.kejona.crossplatforms.spigot.item no longer exists + // access item no longer exists player.getInventory().remove(item); } else { if (player.hasPermission(access.permission(AccessItem.Limit.POSSESS))) { contained.add(access.getIdentifier()); - logger.debug(String.format("%s is keeping access dev.kejona.crossplatforms.spigot.item %s", player.getName(), access.getIdentifier())); + logger.debug(String.format("%s is keeping access item %s", player.getName(), access.getIdentifier())); } else { player.getInventory().remove(item); logger.debug(String.format("Removed %s from %s because they don't have permission for it", access.getIdentifier(), player.getName())); @@ -288,7 +288,7 @@ private void regive(Player player, Predicate give) { } // Give any access items that should be given - boolean changedHand = false; // If we have changed the dev.kejona.crossplatforms.spigot.item the player is holding + boolean changedHand = false; // If we have changed the item the player is holding for (AccessItem access : getItems().values()) { if (give.test(access) && access.getPlatform().matches(player.getUniqueId(), bedrockHandler) && player.hasPermission(access.permission(AccessItem.Limit.EVENT))) { if (!contained.contains(access.getIdentifier())) { @@ -300,9 +300,9 @@ private void regive(Player player, Predicate give) { giveAccessItem(new SpigotPlayer(player), access, false); } - logger.debug(String.format("Gave access dev.kejona.crossplatforms.spigot.item %s to %s", access.getIdentifier(), player.getName())); + logger.debug(String.format("Gave access item %s to %s", access.getIdentifier(), player.getName())); } else { - logger.debug(String.format("%s has permission for access dev.kejona.crossplatforms.spigot.item %s, but they already have it", player.getName(), access.getIdentifier())); + logger.debug(String.format("%s has permission for access item %s, but they already have it", player.getName(), access.getIdentifier())); } } } @@ -314,11 +314,11 @@ public boolean giveAccessItem(FormPlayer player, AccessItem accessItem, boolean } /** - * Gives a player an access dev.kejona.crossplatforms.spigot.item - * @param player The player to give the access dev.kejona.crossplatforms.spigot.item to - * @param accessItem The access dev.kejona.crossplatforms.spigot.item to give - * @param setHeldSlot True if the player's selected dev.kejona.crossplatforms.spigot.item should be forced to the access dev.kejona.crossplatforms.spigot.item - * @return True if the access dev.kejona.crossplatforms.spigot.item was successfully given. False if the inventory was too full. + * Gives a player an access item + * @param player The player to give the access item to + * @param accessItem The access item to give + * @param setHeldSlot True if the player's selected item should be forced to the access item + * @return True if the access item was successfully given. False if the inventory was too full. */ public boolean giveAccessItem(Player player, AccessItem accessItem, boolean setHeldSlot) { ItemStack accessItemStack = createItemStack(accessItem, player); // todo update placeholders after the fact. but when? @@ -327,7 +327,7 @@ public boolean giveAccessItem(Player player, AccessItem accessItem, boolean setH ItemStack blockingItem = player.getInventory().getItem(desiredSlot); boolean success = false; if (blockingItem == null || blockingItem.getType() == Material.AIR) { - // put the dev.kejona.crossplatforms.spigot.item in the desired place + // put the item in the desired place player.getInventory().setItem(desiredSlot, accessItemStack); success = true; } else { @@ -336,9 +336,9 @@ public boolean giveAccessItem(Player player, AccessItem accessItem, boolean setH ItemStack otherItem = player.getInventory().getItem(i); if (otherItem == null || otherItem.getType() == Material.AIR) { - // slot is empty, move the dev.kejona.crossplatforms.spigot.item that is blocking us to it + // slot is empty, move the item that is blocking us to it player.getInventory().setItem(i, blockingItem); - // put the access dev.kejona.crossplatforms.spigot.item in the slot that is no longer blocked + // put the access item in the slot that is no longer blocked player.getInventory().setItem(desiredSlot, accessItemStack); success = true; break; @@ -349,7 +349,7 @@ public boolean giveAccessItem(Player player, AccessItem accessItem, boolean setH if (success) { if (setHeldSlot) { - // Set the held dev.kejona.crossplatforms.spigot.item to the slot of the access dev.kejona.crossplatforms.spigot.item + // Set the held item to the slot of the access item player.getInventory().setHeldItemSlot(accessItem.getSlot()); } return true; diff --git a/spigot/src/main/resources/plugin.yml b/spigot/src/main/resources/plugin.yml index d2d692bf..45fbaddc 100644 --- a/spigot/src/main/resources/plugin.yml +++ b/spigot/src/main/resources/plugin.yml @@ -34,13 +34,13 @@ permissions: description: Access to /forms send default: op crossplatforms.command.give: - description: Access to /forms give + description: Access to /forms give default: op crossplatforms.command.give.others: - description: Access to /forms give + description: Access to /forms give default: op crossplatforms.command.inspect: - description: Access to /forms inspect + description: Access to /forms inspect default: op crossplatforms.command.identify: description: Access to /forms identify From 6055274c8bfb92661f68baa4aff8daf55bc4a48b Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 12 Jan 2023 21:53:35 -0500 Subject: [PATCH 18/59] Cleanup some command stuff --- .../kejona/crossplatforms/accessitem/InspectItemCommand.java | 2 +- .../dev/kejona/crossplatforms/command/defaults/HelpCommand.java | 1 - .../kejona/crossplatforms/command/defaults/InspectCommand.java | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java index f5ce45de..b83a27e4 100644 --- a/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java +++ b/access-item/src/main/java/dev/kejona/crossplatforms/accessitem/InspectItemCommand.java @@ -26,7 +26,7 @@ public void register(CommandManager manager, Command.BuildernewBuilder("item") + .argument(StringArgument.builder("item") .withSuggestionsProvider(((context, s) -> itemRegistry.getItems().values() .stream() .map(AccessItem::getIdentifier) diff --git a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/HelpCommand.java b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/HelpCommand.java index 54599f36..af8ef25d 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/HelpCommand.java +++ b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/HelpCommand.java @@ -20,7 +20,6 @@ public HelpCommand(CrossplatForms crossplatForms, MinecraftHelp m this.minecraftHelp = minecraftHelp; } - @SuppressWarnings("ConstantConditions") // CommandContext#getOrDefault will not return null if given nonnull default @Override public void register(CommandManager manager, Command.Builder defaultBuilder) { manager.command(defaultBuilder diff --git a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/InspectCommand.java b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/InspectCommand.java index 0ac4d50e..43de8097 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/command/defaults/InspectCommand.java +++ b/core/src/main/java/dev/kejona/crossplatforms/command/defaults/InspectCommand.java @@ -6,7 +6,6 @@ import dev.kejona.crossplatforms.CrossplatForms; import dev.kejona.crossplatforms.command.CommandOrigin; import dev.kejona.crossplatforms.command.FormsCommand; -import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.interfacing.Interface; import dev.kejona.crossplatforms.interfacing.bedrock.BedrockForm; import dev.kejona.crossplatforms.interfacing.bedrock.BedrockFormRegistry; @@ -26,7 +25,6 @@ public InspectCommand(CrossplatForms crossplatForms) { @Override public void register(CommandManager manager, Command.Builder defaultBuilder) { - ServerHandler serverHandler = crossplatForms.getServerHandler(); BedrockFormRegistry bedrockRegistry = crossplatForms.getInterfacer().getBedrockRegistry(); JavaMenuRegistry javaRegistry = crossplatForms.getInterfacer().getJavaRegistry(); From 25352d3ad5430946e9edf2fe29735035d02181fb Mon Sep 17 00:00:00 2001 From: Konicai <71294714+konicai@users.noreply.github.com> Date: Sun, 15 Jan 2023 16:55:08 -0500 Subject: [PATCH 19/59] Make VersionAdapters more dynamic --- .../kejona/crossplatforms/spigot/Version.java | 56 +++++++++++++ .../spigot/VersionAdapters.java | 83 +++++++++++++++++++ .../spigot/v1_13_R2/VersionAdapters.java | 36 -------- 3 files changed, 139 insertions(+), 36 deletions(-) create mode 100644 spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/Version.java create mode 100644 spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/VersionAdapters.java delete mode 100644 spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/Version.java b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/Version.java new file mode 100644 index 00000000..5dc2f087 --- /dev/null +++ b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/Version.java @@ -0,0 +1,56 @@ +package dev.kejona.crossplatforms.spigot; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.experimental.Accessors; +import org.jetbrains.annotations.NotNull; + +@Accessors(fluent = true) +@Getter +@EqualsAndHashCode +public class Version implements Comparable { + private final int major; + private final int minor; + private final int patch; + + public Version(String nmsVersion) throws IllegalArgumentException { + try { + String[] split = nmsVersion.split("_", 3); + + major = Integer.parseUnsignedInt(split[0]); + minor = Integer.parseUnsignedInt(split[1]); + patch = Integer.parseUnsignedInt(split[2].substring(1)); // substring to remove the R + } catch (Exception e) { + throw new IllegalArgumentException("Failed to parse NMS version: " + nmsVersion, e); + } + } + + public String nmsVersion() { + return major + "_" + minor + "_R" + patch; + } + + @Override + public int compareTo(@NotNull Version other) { + if (major < other.major) { + return -1; + } else if (major > other.major) { + return 1; + } + // major version the same + + if (minor < other.minor) { + return -1; + } else if (minor > other.minor) { + return 1; + } + // minor the same + + if (patch < other.patch) { + return -1; + } else if (patch > other.patch) { + return 1; + } + + return 0; // the same + } +} diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/VersionAdapters.java b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/VersionAdapters.java new file mode 100644 index 00000000..84a0cf82 --- /dev/null +++ b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/VersionAdapters.java @@ -0,0 +1,83 @@ +package dev.kejona.crossplatforms.spigot; + +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; +import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; +import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; +import dev.kejonamc.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; +import dev.kejonamc.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; +import lombok.RequiredArgsConstructor; + +import java.util.Objects; +import java.util.TreeMap; +import java.util.function.Supplier; +import java.util.logging.Logger; + +@RequiredArgsConstructor +public class VersionAdapters { + + private static final int SUPPORTED_MAJOR_VERSION = 1; + private static final TreeMap> ADAPTERS = new TreeMap<>(); + + static { + ADAPTERS.put(new Version("1_8_R3"), Adapter_v1_8_R3::new); + ADAPTERS.put(new Version("1_9_R2"), Adapter_v1_9_R2::new); + ADAPTERS.put(new Version("1_12_R1"), Adapter_v1_12_R1::new); + ADAPTERS.put(new Version("1_13_R2"), Adapter_v1_13_R2::new); + ADAPTERS.put(new Version("1_14_R1"), Adapter_v1_14_R1::new); + } + + private final Logger logger; + + private VersionAdapter adapter(Version version) { + return Objects.requireNonNull(ADAPTERS.get(version)).get(); + } + + /** + * @param nmsVersion x_y_Rz + */ + public VersionAdapter adapterForVersion(String nmsVersion) throws IllegalArgumentException { + Version version = new Version(nmsVersion); + + if (version.major() != SUPPORTED_MAJOR_VERSION) { + throw new IllegalArgumentException("Unsupported major version " + version.major() + " for: " + nmsVersion); + } + + if (ADAPTERS.containsKey(version)) { + // Direct support for this version + return ADAPTERS.get(version).get(); + } + + // Find adapter versions below and above the given version + Version lower = ADAPTERS.floorKey(version); + Version higher = ADAPTERS.ceilingKey(version); + + if (lower == null) { + // Given version is lower than lowest adapter version + throw new IllegalArgumentException("Unsupported server version. " + higher.nmsVersion() + " or higher required."); + } + if (higher == null) { + // Given version is higher than highest adapter version + return adapter(lower); + } + + if (lower.minor() != version.minor()) { + // Lower version is not the same "game version". eg 1.13 vs 1.14 + + if (higher.minor() == version.minor()) { + // The given version and adapter version only differ in patch version + // eg 1.13 < 1.14.1 < 1.14.2 + // lower version higher + logger.warning("You should update from " + version.nmsVersion() + " to " + higher.nmsVersion()); + return adapter(higher); + } else { + // eg 1.13 < 1.14 < 1.15 + // lower version higher + return adapter(lower); + } + } + + // There is an adapter for the same minor version, but a lower patch version + return adapter(lower); + } +} diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java deleted file mode 100644 index 55ae27e9..00000000 --- a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/v1_13_R2/VersionAdapters.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.kejona.crossplatforms.spigot.v1_13_R2; - -import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; -import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; -import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; -import dev.kejonamc.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; -import dev.kejonamc.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Supplier; - -public final class VersionAdapters { - - private static final Map> ADAPTERS = new HashMap<>(); - - static { - ADAPTERS.put("1_8_R3", Adapter_v1_8_R3::new); - - ADAPTERS.put("1_9_R2", Adapter_v1_9_R2::new); - ADAPTERS.put("1_10_R1", Adapter_v1_9_R2::new); - ADAPTERS.put("1_11_R1", Adapter_v1_9_R2::new); - - ADAPTERS.put("1_12_R1", Adapter_v1_12_R1::new); - ADAPTERS.put("1_13_R2", Adapter_v1_13_R2::new); - ADAPTERS.put("1_14_R1", Adapter_v1_14_R1::new); - } - - public static VersionAdapter adapterForVersion(String version) { - if (!ADAPTERS.containsKey(version)) { - return new Adapter_v1_14_R1(); // todo: improve this - } - - return ADAPTERS.get(version).get(); - } -} From 29a401d35e0b5b94a1be8e1a06afbd8acc8c13e4 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 15 Jan 2023 19:15:03 -0500 Subject: [PATCH 20/59] Add unit tests for finding server version adapters --- spigot-common/all/build.gradle.kts | 2 + ...rsionAdapters.java => AdapterIndexer.java} | 32 ++++---- .../crossplatforms/spigot/IndexResult.java | 36 +++++++++ .../spigot/AdapterIndexerTest.java | 79 +++++++++++++++++++ .../spigot/v1_14_R1/Adapter_v1_14_R1.java | 2 +- .../spigot/v1_14_R1/ModernNbtAccessor.java | 2 +- .../spigot/v1_8_R3/Adapter_v1_8_R3.java | 2 +- .../spigot/v1_8_R3/LegacyNbtAccessor.java | 2 +- .../v1_8_R3/PlayerPickupItemListener.java | 2 +- .../spigot/v1_9_R2/Adapter_v1_9_R2.java | 2 +- 10 files changed, 137 insertions(+), 24 deletions(-) rename spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/{VersionAdapters.java => AdapterIndexer.java} (68%) create mode 100644 spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/IndexResult.java create mode 100644 spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/AdapterIndexerTest.java rename spigot-common/v1_14_R1/src/main/java/dev/{kejonamc => kejona}/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java (90%) rename spigot-common/v1_14_R1/src/main/java/dev/{kejonamc => kejona}/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java (96%) rename spigot-common/v1_8_R3/src/main/java/dev/{kejonamc => kejona}/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java (94%) rename spigot-common/v1_8_R3/src/main/java/dev/{kejonamc => kejona}/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java (97%) rename spigot-common/v1_8_R3/src/main/java/dev/{kejonamc => kejona}/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java (90%) diff --git a/spigot-common/all/build.gradle.kts b/spigot-common/all/build.gradle.kts index 9333a61f..be9045be 100644 --- a/spigot-common/all/build.gradle.kts +++ b/spigot-common/all/build.gradle.kts @@ -1,5 +1,7 @@ dependencies { + testImplementation("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") + compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") api(projects.spigotCommon.common) implementation(projects.spigotCommon.v114R1) diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/VersionAdapters.java b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/AdapterIndexer.java similarity index 68% rename from spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/VersionAdapters.java rename to spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/AdapterIndexer.java index 84a0cf82..71a0fc26 100644 --- a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/VersionAdapters.java +++ b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/AdapterIndexer.java @@ -4,17 +4,15 @@ import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; -import dev.kejonamc.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; -import dev.kejonamc.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; -import lombok.RequiredArgsConstructor; +import dev.kejona.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; +import dev.kejona.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; +import javax.annotation.Nonnull; import java.util.Objects; import java.util.TreeMap; import java.util.function.Supplier; -import java.util.logging.Logger; -@RequiredArgsConstructor -public class VersionAdapters { +public class AdapterIndexer { private static final int SUPPORTED_MAJOR_VERSION = 1; private static final TreeMap> ADAPTERS = new TreeMap<>(); @@ -27,8 +25,7 @@ public class VersionAdapters { ADAPTERS.put(new Version("1_14_R1"), Adapter_v1_14_R1::new); } - private final Logger logger; - + @Nonnull private VersionAdapter adapter(Version version) { return Objects.requireNonNull(ADAPTERS.get(version)).get(); } @@ -36,16 +33,16 @@ private VersionAdapter adapter(Version version) { /** * @param nmsVersion x_y_Rz */ - public VersionAdapter adapterForVersion(String nmsVersion) throws IllegalArgumentException { + public IndexResult findLenientAdapter(String nmsVersion) throws IllegalArgumentException { Version version = new Version(nmsVersion); if (version.major() != SUPPORTED_MAJOR_VERSION) { - throw new IllegalArgumentException("Unsupported major version " + version.major() + " for: " + nmsVersion); + return new IndexResult(ADAPTERS.firstKey().nmsVersion()); } if (ADAPTERS.containsKey(version)) { // Direct support for this version - return ADAPTERS.get(version).get(); + return new IndexResult(adapter(version)); } // Find adapter versions below and above the given version @@ -54,30 +51,29 @@ public VersionAdapter adapterForVersion(String nmsVersion) throws IllegalArgumen if (lower == null) { // Given version is lower than lowest adapter version - throw new IllegalArgumentException("Unsupported server version. " + higher.nmsVersion() + " or higher required."); + return new IndexResult(higher.nmsVersion()); } if (higher == null) { // Given version is higher than highest adapter version - return adapter(lower); + return new IndexResult(adapter(lower)); } if (lower.minor() != version.minor()) { // Lower version is not the same "game version". eg 1.13 vs 1.14 if (higher.minor() == version.minor()) { - // The given version and adapter version only differ in patch version + // The given version and higher adapter version only differ in patch version. The server should be updated. // eg 1.13 < 1.14.1 < 1.14.2 // lower version higher - logger.warning("You should update from " + version.nmsVersion() + " to " + higher.nmsVersion()); - return adapter(higher); + return new IndexResult(adapter(higher), higher.nmsVersion()); } else { // eg 1.13 < 1.14 < 1.15 // lower version higher - return adapter(lower); + return new IndexResult(adapter(lower)); } } // There is an adapter for the same minor version, but a lower patch version - return adapter(lower); + return new IndexResult(adapter(lower)); } } diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/IndexResult.java b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/IndexResult.java new file mode 100644 index 00000000..3175b5af --- /dev/null +++ b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/IndexResult.java @@ -0,0 +1,36 @@ +package dev.kejona.crossplatforms.spigot; + +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; + +import javax.annotation.Nonnull; +import java.util.Objects; +import java.util.Optional; + +public class IndexResult { + + private final VersionAdapter adapter; + private final String betterVersion; + + protected IndexResult(@Nonnull VersionAdapter adapter, @Nonnull String betterVersion) { + this.adapter = Objects.requireNonNull(adapter, "adapter"); + this.betterVersion = Objects.requireNonNull(betterVersion, "betterVersion"); + } + + protected IndexResult(@Nonnull VersionAdapter adapter) { + this.adapter = Objects.requireNonNull(adapter, "adapter"); + this.betterVersion = null; + } + + protected IndexResult(@Nonnull String betterVersion) { + this.adapter = null; + this.betterVersion = Objects.requireNonNull(betterVersion, "betterVersion"); + } + + public Optional adapter() { + return Optional.ofNullable(adapter); + } + + public Optional betterVersion() { + return Optional.ofNullable(betterVersion); + } +} diff --git a/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/AdapterIndexerTest.java b/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/AdapterIndexerTest.java new file mode 100644 index 00000000..89913ab4 --- /dev/null +++ b/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/AdapterIndexerTest.java @@ -0,0 +1,79 @@ +package dev.kejona.crossplatforms.spigot; + +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; +import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; +import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; +import dev.kejona.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; +import dev.kejona.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class AdapterIndexerTest { + + private static AdapterIndexer adapters; + private static final String[] UNSUPPORTED_VERSIONS = {"1_7_R4", "1_8_R1", "1_8_R2"}; + private static final String[] UNDESIRED_VERSIONS = {"1_9_R1", "1_13_R1"}; + private static final Map> EXPECTATIONS = new HashMap<>(); + + @BeforeAll + public static void setup() { + adapters = new AdapterIndexer(); + + Class latestAdapter = Adapter_v1_14_R1.class; + + EXPECTATIONS.put("1_8_R3", Adapter_v1_8_R3.class); + EXPECTATIONS.put("1_9_R1", Adapter_v1_9_R2.class); // yikes + EXPECTATIONS.put("1_9_R2", Adapter_v1_9_R2.class); + EXPECTATIONS.put("1_10_R1", Adapter_v1_9_R2.class); + EXPECTATIONS.put("1_11_R1", Adapter_v1_9_R2.class); + EXPECTATIONS.put("1_12_R1", Adapter_v1_12_R1.class); + EXPECTATIONS.put("1_13_R1", Adapter_v1_13_R2.class); // yikes + EXPECTATIONS.put("1_13_R2", Adapter_v1_13_R2.class); + EXPECTATIONS.put("1_14_R1", Adapter_v1_14_R1.class); + EXPECTATIONS.put("1_15_R1", latestAdapter); + EXPECTATIONS.put("1_16_R1", latestAdapter); + EXPECTATIONS.put("1_16_R2", latestAdapter); + EXPECTATIONS.put("1_16_R3", latestAdapter); + EXPECTATIONS.put("1_17_R1", latestAdapter); + EXPECTATIONS.put("1_18_R1", latestAdapter); + EXPECTATIONS.put("1_18_R2", latestAdapter); + EXPECTATIONS.put("1_19_R1", latestAdapter); + EXPECTATIONS.put("1_19_R2", latestAdapter); + } + + @Test + public void testSupportedVersions() { + for (Map.Entry> entry : EXPECTATIONS.entrySet()) { + String version = entry.getKey(); + Class clazz = entry.getValue(); + + Assertions.assertInstanceOf( + clazz, + adapters.findLenientAdapter(version).adapter().orElse(null), + "Unexpected adapter for version " + version + ); + } + } + + @Test + public void testUndesiredVersions() { + for (String version : UNDESIRED_VERSIONS) { + Assertions.assertNotNull(adapters.findLenientAdapter(version).betterVersion().orElse(null)); + } + } + + @Test + public void testUnsupportedVersions() { + for (String version : UNSUPPORTED_VERSIONS) { + IndexResult index = adapters.findLenientAdapter(version); + + Assertions.assertNull(index.adapter().orElse(null)); + Assertions.assertNotNull(index.betterVersion().orElse(null)); + } + } +} diff --git a/spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java b/spigot-common/v1_14_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java similarity index 90% rename from spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java rename to spigot-common/v1_14_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java index 57658a93..16efd44e 100644 --- a/spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java +++ b/spigot-common/v1_14_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_14_R1/Adapter_v1_14_R1.java @@ -1,4 +1,4 @@ -package dev.kejonamc.crossplatforms.spigot.v1_14_R1; +package dev.kejona.crossplatforms.spigot.v1_14_R1; import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; diff --git a/spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java b/spigot-common/v1_14_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java similarity index 96% rename from spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java rename to spigot-common/v1_14_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java index 0ec9bfc5..7a53f7a7 100644 --- a/spigot-common/v1_14_R1/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java +++ b/spigot-common/v1_14_R1/src/main/java/dev/kejona/crossplatforms/spigot/v1_14_R1/ModernNbtAccessor.java @@ -1,4 +1,4 @@ -package dev.kejonamc.crossplatforms.spigot.v1_14_R1; +package dev.kejona.crossplatforms.spigot.v1_14_R1; import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; import lombok.AllArgsConstructor; diff --git a/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java similarity index 94% rename from spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java rename to spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java index ef1ea7b5..5ed1c60e 100644 --- a/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java +++ b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java @@ -1,4 +1,4 @@ -package dev.kejonamc.crossplatforms.spigot.v1_8_R3; +package dev.kejona.crossplatforms.spigot.v1_8_R3; import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; diff --git a/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java similarity index 97% rename from spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java rename to spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java index 8a2ca438..ef03aa27 100644 --- a/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java +++ b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/LegacyNbtAccessor.java @@ -1,4 +1,4 @@ -package dev.kejonamc.crossplatforms.spigot.v1_8_R3; +package dev.kejona.crossplatforms.spigot.v1_8_R3; import de.tr7zw.changeme.nbtapi.NBTCompound; import de.tr7zw.changeme.nbtapi.NBTItem; diff --git a/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java similarity index 90% rename from spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java rename to spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java index c3700235..8a8423b6 100644 --- a/spigot-common/v1_8_R3/src/main/java/dev/kejonamc/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java +++ b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java @@ -1,4 +1,4 @@ -package dev.kejonamc.crossplatforms.spigot.v1_8_R3; +package dev.kejona.crossplatforms.spigot.v1_8_R3; import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import lombok.AllArgsConstructor; diff --git a/spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java b/spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java index 69409534..d927fd3a 100644 --- a/spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java +++ b/spigot-common/v1_9_R2/src/main/java/dev/kejona/crossplatforms/spigot/v1_9_R2/Adapter_v1_9_R2.java @@ -1,7 +1,7 @@ package dev.kejona.crossplatforms.spigot.v1_9_R2; import dev.kejona.crossplatforms.spigot.SpigotAccessItems; -import dev.kejonamc.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; +import dev.kejona.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; import org.bukkit.plugin.Plugin; public class Adapter_v1_9_R2 extends Adapter_v1_8_R3 { From 9cc83976ca8c4ecf29d26c69acd9c8cf77e0ea0d Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 15 Jan 2023 21:23:56 -0500 Subject: [PATCH 21/59] New spigot is tied together and booting --- .../bungeecord/CrossplatFormsBungeeCord.java | 2 + .../kejona/crossplatforms/CrossplatForms.java | 4 + .../CrossplatFormsBootstrap.java | 2 + .../crossplatforms/config/ConfigId.java | 1 + .../config/ConfigurationModule.java | 7 +- .../VersionIndexer.java} | 21 +++--- ...dexerTest.java => VersionIndexerTest.java} | 10 ++- .../spigot/SpigotAccessItems.java | 2 +- .../crossplatforms/spigot/SpigotBase.java | 73 +++++++++++-------- .../spigot/adapter}/Version.java | 2 +- .../spigot/adapter/VersionIndexResult.java} | 12 ++- spigot/build.gradle.kts | 24 ++++-- .../spigot/CrossplatFormsSpigot.java | 18 ++--- .../velocity/CrossplatFormsVelocity.java | 2 + 14 files changed, 108 insertions(+), 72 deletions(-) rename spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/{AdapterIndexer.java => adapter/VersionIndexer.java} (78%) rename spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/{AdapterIndexerTest.java => VersionIndexerTest.java} (90%) rename spigot-common/{all/src/main/java/dev/kejona/crossplatforms/spigot => common/src/main/java/dev/kejona/crossplatforms/spigot/adapter}/Version.java (96%) rename spigot-common/{all/src/main/java/dev/kejona/crossplatforms/spigot/IndexResult.java => common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexResult.java} (68%) diff --git a/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/CrossplatFormsBungeeCord.java b/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/CrossplatFormsBungeeCord.java index 90fc341a..24fa9763 100644 --- a/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/CrossplatFormsBungeeCord.java +++ b/bungeecord/src/main/java/dev/kejona/crossplatforms/bungeecord/CrossplatFormsBungeeCord.java @@ -22,6 +22,7 @@ import dev.kejona.crossplatforms.proxy.CloseMenuAction; import dev.kejona.crossplatforms.permission.LuckPermsHook; import dev.kejona.crossplatforms.proxy.ProtocolizeInterfacer; +import dev.kejona.crossplatforms.proxy.item.ProtocolizeInventoryFactory; import net.kyori.adventure.platform.bungeecord.BungeeAudiences; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; import net.md_5.bungee.api.CommandSender; @@ -84,6 +85,7 @@ public void onEnable() { "formsb", commandManager, placeholders, + new ProtocolizeInventoryFactory(), this ); diff --git a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java index f75147bf..c77611bc 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java +++ b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java @@ -29,6 +29,7 @@ import dev.kejona.crossplatforms.interfacing.bedrock.custom.ComponentSerializer; import dev.kejona.crossplatforms.interfacing.bedrock.custom.CustomComponent; import dev.kejona.crossplatforms.interfacing.java.JavaMenuRegistry; +import dev.kejona.crossplatforms.item.InventoryFactory; import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.reloadable.ReloadableRegistry; import lombok.Getter; @@ -62,6 +63,7 @@ public class CrossplatForms { private final Placeholders placeholders; + @Deprecated private final boolean success = true; public CrossplatForms(Logger logger, @@ -71,6 +73,7 @@ public CrossplatForms(Logger logger, String defaultCommand, CommandManager commandManager, Placeholders placeholders, + InventoryFactory inventoryFactory, CrossplatFormsBootstrap bootstrap) { long start = System.currentTimeMillis(); if (INSTANCE != null) { @@ -112,6 +115,7 @@ public CrossplatForms(Logger logger, Injector injector = Guice.createInjector( new ConfigurationModule( interfacer, + inventoryFactory, bedrockHandler, serverHandler, placeholders diff --git a/core/src/main/java/dev/kejona/crossplatforms/CrossplatFormsBootstrap.java b/core/src/main/java/dev/kejona/crossplatforms/CrossplatFormsBootstrap.java index bcccffdf..a390c290 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/CrossplatFormsBootstrap.java +++ b/core/src/main/java/dev/kejona/crossplatforms/CrossplatFormsBootstrap.java @@ -16,6 +16,8 @@ public interface CrossplatFormsBootstrap { /** * Construct an {@link Interfacer} implementation with the given parameters. This method will be called only once * during the construction of {@link CrossplatForms}. This method exists + * + * todo: this can just be moved to CrossplatForms constructor */ Interfacer interfaceManager(); diff --git a/core/src/main/java/dev/kejona/crossplatforms/config/ConfigId.java b/core/src/main/java/dev/kejona/crossplatforms/config/ConfigId.java index 98f27ea8..236372d3 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/config/ConfigId.java +++ b/core/src/main/java/dev/kejona/crossplatforms/config/ConfigId.java @@ -59,6 +59,7 @@ public class ConfigId { @Nullable public final Supplier updater; + // todo: can be removed and substituted for Configurate's new post processing feature @Nullable public final Consumer postProcessor; diff --git a/core/src/main/java/dev/kejona/crossplatforms/config/ConfigurationModule.java b/core/src/main/java/dev/kejona/crossplatforms/config/ConfigurationModule.java index 79854b1c..dd071417 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/config/ConfigurationModule.java +++ b/core/src/main/java/dev/kejona/crossplatforms/config/ConfigurationModule.java @@ -7,21 +7,26 @@ import dev.kejona.crossplatforms.handler.Placeholders; import dev.kejona.crossplatforms.handler.ServerHandler; import dev.kejona.crossplatforms.interfacing.Interfacer; +import dev.kejona.crossplatforms.item.InventoryFactory; import lombok.AllArgsConstructor; @AllArgsConstructor public class ConfigurationModule extends AbstractModule { private final Interfacer interfacer; + private final InventoryFactory inventoryFactory; private final BedrockHandler bedrockHandler; private final ServerHandler serverHandler; private final Placeholders placeholders; @Override protected void configure() { - // remember: explicit bindings cannot be required because this module is used for creating configs + // remember: explicit bindings cannot be set as required using binder().requireExplicitBindings() + // because this module is used for creating configs - bindings are created on the fly (just in time) bind(Interfacer.class).toInstance(interfacer); + bind(InventoryFactory.class).toInstance(inventoryFactory); + // Hack to stop the instance from having its members being injected // which causes a ClassDefNotFound error if Cumulus is not present (EmptyBedrockHandler) bind(BedrockHandler.class).toProvider(Providers.of(bedrockHandler)); diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/AdapterIndexer.java b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java similarity index 78% rename from spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/AdapterIndexer.java rename to spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java index 71a0fc26..0680bf11 100644 --- a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/AdapterIndexer.java +++ b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java @@ -1,6 +1,5 @@ -package dev.kejona.crossplatforms.spigot; +package dev.kejona.crossplatforms.spigot.adapter; -import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; @@ -12,7 +11,7 @@ import java.util.TreeMap; import java.util.function.Supplier; -public class AdapterIndexer { +public class VersionIndexer { private static final int SUPPORTED_MAJOR_VERSION = 1; private static final TreeMap> ADAPTERS = new TreeMap<>(); @@ -33,16 +32,16 @@ private VersionAdapter adapter(Version version) { /** * @param nmsVersion x_y_Rz */ - public IndexResult findLenientAdapter(String nmsVersion) throws IllegalArgumentException { + public VersionIndexResult findLenientAdapter(String nmsVersion) throws IllegalArgumentException { Version version = new Version(nmsVersion); if (version.major() != SUPPORTED_MAJOR_VERSION) { - return new IndexResult(ADAPTERS.firstKey().nmsVersion()); + return new VersionIndexResult(ADAPTERS.firstKey().nmsVersion()); } if (ADAPTERS.containsKey(version)) { // Direct support for this version - return new IndexResult(adapter(version)); + return new VersionIndexResult(adapter(version)); } // Find adapter versions below and above the given version @@ -51,11 +50,11 @@ public IndexResult findLenientAdapter(String nmsVersion) throws IllegalArgumentE if (lower == null) { // Given version is lower than lowest adapter version - return new IndexResult(higher.nmsVersion()); + return new VersionIndexResult(higher.nmsVersion()); } if (higher == null) { // Given version is higher than highest adapter version - return new IndexResult(adapter(lower)); + return new VersionIndexResult(adapter(lower)); } if (lower.minor() != version.minor()) { @@ -65,15 +64,15 @@ public IndexResult findLenientAdapter(String nmsVersion) throws IllegalArgumentE // The given version and higher adapter version only differ in patch version. The server should be updated. // eg 1.13 < 1.14.1 < 1.14.2 // lower version higher - return new IndexResult(adapter(higher), higher.nmsVersion()); + return new VersionIndexResult(adapter(higher), higher.nmsVersion()); } else { // eg 1.13 < 1.14 < 1.15 // lower version higher - return new IndexResult(adapter(lower)); + return new VersionIndexResult(adapter(lower)); } } // There is an adapter for the same minor version, but a lower patch version - return new IndexResult(adapter(lower)); + return new VersionIndexResult(adapter(lower)); } } diff --git a/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/AdapterIndexerTest.java b/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/VersionIndexerTest.java similarity index 90% rename from spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/AdapterIndexerTest.java rename to spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/VersionIndexerTest.java index 89913ab4..5fa5ab48 100644 --- a/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/AdapterIndexerTest.java +++ b/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/VersionIndexerTest.java @@ -1,6 +1,8 @@ package dev.kejona.crossplatforms.spigot; +import dev.kejona.crossplatforms.spigot.adapter.VersionIndexer; import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.adapter.VersionIndexResult; import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; @@ -13,16 +15,16 @@ import java.util.HashMap; import java.util.Map; -public class AdapterIndexerTest { +public class VersionIndexerTest { - private static AdapterIndexer adapters; + private static VersionIndexer adapters; private static final String[] UNSUPPORTED_VERSIONS = {"1_7_R4", "1_8_R1", "1_8_R2"}; private static final String[] UNDESIRED_VERSIONS = {"1_9_R1", "1_13_R1"}; private static final Map> EXPECTATIONS = new HashMap<>(); @BeforeAll public static void setup() { - adapters = new AdapterIndexer(); + adapters = new VersionIndexer(); Class latestAdapter = Adapter_v1_14_R1.class; @@ -70,7 +72,7 @@ public void testUndesiredVersions() { @Test public void testUnsupportedVersions() { for (String version : UNSUPPORTED_VERSIONS) { - IndexResult index = adapters.findLenientAdapter(version); + VersionIndexResult index = adapters.findLenientAdapter(version); Assertions.assertNull(index.adapter().orElse(null)); Assertions.assertNotNull(index.betterVersion().orElse(null)); diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java index 68f0c9ec..e9713e8e 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotAccessItems.java @@ -41,7 +41,7 @@ import java.util.Objects; import java.util.function.Predicate; -public class SpigotAccessItems extends AccessItemRegistry implements Listener { +public final class SpigotAccessItems extends AccessItemRegistry implements Listener { private final Logger logger = Logger.get(); diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java index dae9c605..13492630 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java @@ -22,10 +22,12 @@ import dev.kejona.crossplatforms.permission.LuckPermsHook; import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.adapter.VersionIndexResult; import dev.kejona.crossplatforms.spigot.handler.PlaceholderAPIHandler; import dev.kejona.crossplatforms.spigot.handler.SpigotCommandOrigin; import dev.kejona.crossplatforms.spigot.handler.SpigotHandler; import dev.kejona.crossplatforms.spigot.handler.SpigotPermissions; +import dev.kejona.crossplatforms.spigot.item.SpigotInventoryFactory; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -41,7 +43,7 @@ public abstract class SpigotBase extends JavaPlugin implements CrossplatFormsBootstrap { - protected static final int METRICS_ID = 14707; + private static final int METRICS_ID = 14707; public static final LegacyComponentSerializer LEGACY_SERIALIZER = BukkitComponentSerializer.legacy(); private static SpigotBase INSTANCE; @@ -51,10 +53,11 @@ public abstract class SpigotBase extends JavaPlugin implements CrossplatFormsBoo Constants.fetch(); } - private Logger logger; - protected Server server; - protected BukkitAudiences audiences; + protected Logger logger; + private Server server; + private BukkitAudiences audiences; private Metrics metrics; + private VersionAdapter versionAdapter; protected SpigotBase() { INSTANCE = this; @@ -63,12 +66,20 @@ protected SpigotBase() { @Override public void onEnable() { logger = new JavaUtilLogger(getLogger()); - metrics = new Metrics(this, METRICS_ID); server = getServer(); audiences = BukkitAudiences.create(this); + metrics = new Metrics(this, METRICS_ID); + + VersionIndexResult result = findVersionAdapter(); + result.betterVersion().ifPresent(v -> logger.warn("Consider using server version " + v + " instead.")); + if (result.adapter().isPresent()) { + versionAdapter = result.adapter().get(); + } else { + logger.severe("This server version is unsupported. If you believe this is incorrect, please contact us."); + } SpigotHandler serverHandler = new SpigotHandler(this, audiences); - Permissions permissions = pluginEnabled("LuckPerms") ? new LuckPermsHook() : new SpigotPermissions(this); + Permissions permissions = server.getPluginManager().isPluginEnabled("LuckPerms") ? new LuckPermsHook() : new SpigotPermissions(this); convertGeyserHubConfig(); @@ -93,6 +104,10 @@ public void onEnable() { commandManager.registerBrigadier(); } catch (BukkitCommandManager.BrigadierFailureException e) { logger.warn("Failed to initialize Brigadier support: " + e.getMessage()); + if (e.getReason() == BukkitCommandManager.BrigadierFailureReason.VERSION_TOO_HIGH) { + // Commodore brig only supports Spigot 1.13 - 1.18.2 + logger.warn("Using Paper instead of Spigot will likely fix this."); + } } } @@ -115,15 +130,21 @@ public void onEnable() { "forms", commandManager, placeholders, + new SpigotInventoryFactory(versionAdapter), this ); - if (!crossplatForms.isSuccess()) { - return; - } - - SpigotAccessItems accessItems = createAccessItems(crossplatForms); + SpigotAccessItems accessItems = new SpigotAccessItems( + this, + versionAdapter, + crossplatForms.getConfigManager(), + crossplatForms.getPermissions(), + crossplatForms.getInterfacer(), + crossplatForms.getBedrockHandler(), + crossplatForms.getPlaceholders() + ); server.getPluginManager().registerEvents(accessItems, this); + versionAdapter.registerAuxiliaryEvents(this, accessItems); // Events for versions above 1.8 // Commands added by access items new GiveCommand(crossplatForms, accessItems).register(commandManager, crossplatForms.getCommandBuilder()); @@ -163,10 +184,6 @@ public void addCustomChart(CustomChart chart) { metrics.addCustomChart(chart); } - public boolean pluginEnabled(String id) { - return server.getPluginManager().isPluginEnabled(id); - } - private void convertGeyserHubConfig() { File selector = new File(getDataFolder(), "selector.yml"); if (selector.exists()) { @@ -183,23 +200,19 @@ private void convertGeyserHubConfig() { } } - public boolean attemptBrigadier() { - return true; // todo: determine if registering brig should be attempted - } - - public SpigotAccessItems createAccessItems(CrossplatForms crossplatForms) { - return new SpigotAccessItems( - this, - createVersionAdapter(this), - crossplatForms.getConfigManager(), - crossplatForms.getPermissions(), - crossplatForms.getInterfacer(), - crossplatForms.getBedrockHandler(), - crossplatForms.getPlaceholders() - ); + private boolean attemptBrigadier() { + try { + // Brigadier is available on 1.13 and above + Class.forName("org.bukkit.entity.Dolphin"); + return true; + } catch (ClassNotFoundException ignored) { + // no-op + } + + return false; } - public abstract VersionAdapter createVersionAdapter(JavaPlugin plugin); + public abstract VersionIndexResult findVersionAdapter(); public static SpigotBase getInstance() { return INSTANCE; diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/Version.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/Version.java similarity index 96% rename from spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/Version.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/Version.java index 5dc2f087..8ec91964 100644 --- a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/Version.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/Version.java @@ -1,4 +1,4 @@ -package dev.kejona.crossplatforms.spigot; +package dev.kejona.crossplatforms.spigot.adapter; import lombok.EqualsAndHashCode; import lombok.Getter; diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/IndexResult.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexResult.java similarity index 68% rename from spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/IndexResult.java rename to spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexResult.java index 3175b5af..e05ae581 100644 --- a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/IndexResult.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexResult.java @@ -1,27 +1,25 @@ -package dev.kejona.crossplatforms.spigot; - -import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +package dev.kejona.crossplatforms.spigot.adapter; import javax.annotation.Nonnull; import java.util.Objects; import java.util.Optional; -public class IndexResult { +public class VersionIndexResult { private final VersionAdapter adapter; private final String betterVersion; - protected IndexResult(@Nonnull VersionAdapter adapter, @Nonnull String betterVersion) { + protected VersionIndexResult(@Nonnull VersionAdapter adapter, @Nonnull String betterVersion) { this.adapter = Objects.requireNonNull(adapter, "adapter"); this.betterVersion = Objects.requireNonNull(betterVersion, "betterVersion"); } - protected IndexResult(@Nonnull VersionAdapter adapter) { + protected VersionIndexResult(@Nonnull VersionAdapter adapter) { this.adapter = Objects.requireNonNull(adapter, "adapter"); this.betterVersion = null; } - protected IndexResult(@Nonnull String betterVersion) { + protected VersionIndexResult(@Nonnull String betterVersion) { this.adapter = null; this.betterVersion = Objects.requireNonNull(betterVersion, "betterVersion"); } diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index a14fa96d..5ab4c5a2 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -5,30 +5,38 @@ plugins { } dependencies { - compileOnly("org.spigotmc:spigot-api:1.14.4-R0.1-SNAPSHOT") - api(projects.spigotCommon.common) { - // this should be overridden by the version specified here, but just making sure - exclude(group = "org.spigotmc", module = "spigot-api") - } + compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") + api("de.tr7zw:item-nbt-api:2.10.0") + api(projects.spigotCommon.all) } tasks.withType { dependencies { shadow { relocate("com.google.inject", "dev.kejona.crossplatforms.shaded.guice") + + // older versions of Spigot have a Guava that is too old for Guice + relocate("com.google.common", "dev.kejona.crossplatforms.shaded.google.common") // i.e. Guava + relocate("cloud.commandframework", "dev.kejona.crossplatforms.shaded.cloud") relocate("me.lucko.commodore", "dev.kejona.crossplatforms.shaded.commodore") relocate("net.kyori", "dev.kejona.crossplatforms.shaded.kyori") relocate("org.spongepowered.configurate", "dev.kejona.crossplatforms.shaded.configurate") relocate("io.leangen.geantyref", "dev.kejona.crossplatforms.shaded.typetoken") relocate("org.bstats", "dev.kejona.crossplatforms.shaded.bstats") + + // Because of old spigot versions having ancient yaml and not having an NBT api + relocate("org.yaml.snakeyaml", "dev.kejona.crossplatforms.shaded.snakeyaml") + relocate("de.tr7zw.changeme.nbtapi", "dev.kejona.crossplatforms.shaded.nbtapi") + relocate("de.tr7zw.annotations", "dev.kejona.crossplatforms.shaded.tr7zw.annotations") } exclude { e -> val name = e.name - name.startsWith("org.yaml") // Available on Spigot - || (name.startsWith("com.google") && !name.startsWith("com.google.inject")) - || name.startsWith("javax.inject") + (name.startsWith("com.google") + && !name.startsWith("com.google.inject") + && !name.startsWith("com.google.guava")) // contains package name of com.google.common + || name.startsWith("javax.inject") } } diff --git a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java index 32974282..6ab6a342 100644 --- a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java +++ b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java @@ -1,18 +1,18 @@ package dev.kejona.crossplatforms.spigot; -import dev.kejona.crossplatforms.spigot.SpigotBase; -import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; -import org.bukkit.plugin.java.JavaPlugin; +import dev.kejona.crossplatforms.spigot.adapter.VersionIndexer; +import dev.kejona.crossplatforms.spigot.adapter.VersionIndexResult; public class CrossplatFormsSpigot extends SpigotBase { @Override - public void onEnable() { + public VersionIndexResult findVersionAdapter() { + String serverPackage = getServer().getClass().getPackage().getName(); + logger.debug("Server package: " + serverPackage); + // +2 to remove the ".v" + String version = serverPackage.substring(serverPackage.lastIndexOf('.') + 2); + logger.debug("NMS version: " + version); - } - - @Override - public VersionAdapter createVersionAdapter(JavaPlugin plugin) { - return null; + return new VersionIndexer().findLenientAdapter(version); } } diff --git a/velocity/src/main/java/dev/kejona/crossplatforms/velocity/CrossplatFormsVelocity.java b/velocity/src/main/java/dev/kejona/crossplatforms/velocity/CrossplatFormsVelocity.java index 4b3fa44f..89de611e 100644 --- a/velocity/src/main/java/dev/kejona/crossplatforms/velocity/CrossplatFormsVelocity.java +++ b/velocity/src/main/java/dev/kejona/crossplatforms/velocity/CrossplatFormsVelocity.java @@ -28,6 +28,7 @@ import dev.kejona.crossplatforms.proxy.CloseMenuAction; import dev.kejona.crossplatforms.permission.LuckPermsHook; import dev.kejona.crossplatforms.proxy.ProtocolizeInterfacer; +import dev.kejona.crossplatforms.proxy.item.ProtocolizeInventoryFactory; import dev.kejona.crossplatforms.velocity.handler.VelocityCommandOrigin; import dev.kejona.crossplatforms.velocity.handler.VelocityHandler; import lombok.Getter; @@ -106,6 +107,7 @@ public void load(ProxyInitializeEvent event) { "formsv", commandManager, placeholders, + new ProtocolizeInventoryFactory(), this ); From 85f524bbdb32f6885e3fbd2bd8f7041e4efebb73 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 19 Jan 2023 03:25:11 -0500 Subject: [PATCH 22/59] CustomModelData implementations --- .../crossplatforms/item/InventoryFactory.java | 3 +- .../crossplatforms/utils/ReflectionUtils.java | 28 ++++++ .../item/ProtocolizeInventoryFactory.java | 54 +++++++++-- .../proxy/item/ProtocolizeItem.java | 4 +- .../spigot/adapter/VersionIndexer.java | 1 + .../crossplatforms/spigot/SpigotBase.java | 4 +- .../spigot/adapter/NbtAccessor.java | 12 +-- .../spigot/adapter/VersionAdapter.java | 10 ++ .../spigot/item/SpigotInventory.java | 43 --------- .../spigot/item/SpigotInventoryFactory.java | 91 +++++++++++++++---- .../spigot/item/SpigotItem.java | 16 ---- .../spigot/utils/InventoryUtils.java | 21 +++++ .../spigot/v1_14_R1/Adapter_v1_14_R1.java | 10 ++ .../spigot/v1_14_R1/ModernNbtAccessor.java | 7 +- spigot-common/v1_8_R3/build.gradle.kts | 1 + .../spigot/v1_8_R3/Adapter_v1_8_R3.java | 34 +++++++ .../spigot/v1_8_R3/LegacyNbtAccessor.java | 5 - .../v1_8_R3/PlayerPickupItemListener.java | 1 + 18 files changed, 239 insertions(+), 106 deletions(-) delete mode 100644 spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventory.java delete mode 100644 spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotItem.java create mode 100644 spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/utils/InventoryUtils.java diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java index c29c6909..940acb25 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java +++ b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java @@ -2,6 +2,7 @@ import dev.kejona.crossplatforms.handler.FormPlayer; +import javax.annotation.Nullable; import java.util.List; import java.util.OptionalInt; @@ -12,5 +13,5 @@ public interface InventoryFactory { Item item(String displayName, String material, List lore, OptionalInt customModelData); - Item skullItem(FormPlayer owner, String displayName, List lore); + Item skullItem(FormPlayer owner, @Nullable String displayName, List lore); } diff --git a/core/src/main/java/dev/kejona/crossplatforms/utils/ReflectionUtils.java b/core/src/main/java/dev/kejona/crossplatforms/utils/ReflectionUtils.java index ba64ac94..4513e61c 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/utils/ReflectionUtils.java +++ b/core/src/main/java/dev/kejona/crossplatforms/utils/ReflectionUtils.java @@ -59,6 +59,19 @@ public static T castedInvoke(Object instance, Method method, Object... argum return (T) invoke(instance, method, arguments); } + @Nullable + public static Field getField(Class clazz, String name, boolean declared) { + try { + if (declared) { + return clazz.getDeclaredField(name); + } else { + return clazz.getField(name); + } + } catch (NoSuchFieldException ignored) { + return null; + } + } + @Nullable public static Object getValue(Object instance, Field field) { field.setAccessible(true); @@ -68,4 +81,19 @@ public static Object getValue(Object instance, Field field) { throw new IllegalStateException("Failed to set " + field.getName() + " on " + instance.getClass() + " accessible", e); } } + + public static void setValue(Object instance, Field field, Object value) { + field.setAccessible(true); + try { + field.set(instance, value); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + @SuppressWarnings("unchecked") + @Nullable + public static T getValue(Object instance, Field field, Class type) { + return (T) getValue(instance, field); + } } diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java index 3da83552..d04be09e 100644 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java @@ -5,14 +5,18 @@ import dev.kejona.crossplatforms.item.InventoryFactory; import dev.kejona.crossplatforms.item.InventoryLayout; import dev.kejona.crossplatforms.item.Item; +import dev.simplix.protocolize.api.Protocolize; import dev.simplix.protocolize.api.item.ItemStack; import dev.simplix.protocolize.data.ItemType; import dev.simplix.protocolize.data.inventory.InventoryType; import net.querz.nbt.tag.CompoundTag; +import net.querz.nbt.tag.ListTag; +import javax.annotation.Nullable; import java.util.List; import java.util.Locale; import java.util.OptionalInt; +import java.util.UUID; public class ProtocolizeInventoryFactory implements InventoryFactory { @@ -40,11 +44,11 @@ public Inventory inventory(String title, InventoryLayout layout) { @Override public Item item(String displayName, String material, List lore, OptionalInt customModelData) { - ItemStack item = new ItemStack(ItemType.valueOf(material.toUpperCase(Locale.ROOT).trim())); + item.displayName(displayName); + item.lore(lore, true); CompoundTag nbt = item.nbtData(); - if (customModelData.isPresent()) { nbt.putInt(CUSTOM_MODEL_DATA_KEY, customModelData.getAsInt()); } else { @@ -55,18 +59,56 @@ public Item item(String displayName, String material, List lore, Optiona } @Override - public Item skullItem(FormPlayer owner, String displayName, List lore) { - return null; + public Item skullItem(FormPlayer owner, @Nullable String displayName, List lore) { + ItemStack item = new ItemStack(ItemType.PLAYER_HEAD); + if (displayName != null) { + item.displayName(displayName); + } + item.lore(lore, true); + + // https://minecraft.fandom.com/wiki/Head#Item_data + CompoundTag skullOwner = new CompoundTag(); + skullOwner.putIntArray("Id", uuidToArray(owner.getUuid())); // todo: different for below 1.16 apparently + skullOwner.putString("Name", owner.getName()); + skullOwner.put("Properties", propertiesForTextures(owner.getEncodedSkinData())); + + item.nbtData().put("SkullOwner", skullOwner); + + return new ProtocolizeItem(item); + } + + private CompoundTag propertiesForTextures(String encodedTexture) { + CompoundTag properties = new CompoundTag(); + ListTag textures = new ListTag<>(CompoundTag.class); + CompoundTag texture = new CompoundTag(); + + properties.put("textures", textures); + textures.add(texture); + texture.putString("Value", encodedTexture); + + return properties; + } + + private static int[] uuidToArray(UUID uuid) { + long least = uuid.getLeastSignificantBits(); + long most = uuid.getMostSignificantBits(); + + return new int[] { + (int) (least >> 32), + (int) least, + (int) (most >> 32), + (int) most + }; } private static InventoryType convertType(InventoryLayout layout) { switch (layout) { - case CHEST: - return InventoryType.GENERIC_9X6; case HOPPER: return InventoryType.HOPPER; case DISPENSER: return InventoryType.GENERIC_3X3; + case CHEST: + throw new IllegalArgumentException("Chest inventories should be created directly"); } throw new AssertionError("Unhandled InventoryLayout: " + layout.name()); diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java index d5364742..587f663a 100644 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeItem.java @@ -2,13 +2,13 @@ import dev.kejona.crossplatforms.item.Item; import dev.simplix.protocolize.api.item.BaseItemStack; +import dev.simplix.protocolize.api.item.ItemStack; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class ProtocolizeItem implements Item { - - private final BaseItemStack item; + private final ItemStack item; @Override public Object handle() { diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java index 0680bf11..1cfafe9e 100644 --- a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java +++ b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java @@ -15,6 +15,7 @@ public class VersionIndexer { private static final int SUPPORTED_MAJOR_VERSION = 1; private static final TreeMap> ADAPTERS = new TreeMap<>(); + // todo: probably need to make the value generic so that this can be unit tested (some adapters rely on craft classes) static { ADAPTERS.put(new Version("1_8_R3"), Adapter_v1_8_R3::new); diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java index 13492630..ef3347e3 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java @@ -76,6 +76,8 @@ public void onEnable() { versionAdapter = result.adapter().get(); } else { logger.severe("This server version is unsupported. If you believe this is incorrect, please contact us."); + getServer().getPluginManager().disablePlugin(this); + return; } SpigotHandler serverHandler = new SpigotHandler(this, audiences); @@ -130,7 +132,7 @@ public void onEnable() { "forms", commandManager, placeholders, - new SpigotInventoryFactory(versionAdapter), + new SpigotInventoryFactory(versionAdapter, logger), this ); diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java index 54f428ac..5f789091 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/NbtAccessor.java @@ -1,7 +1,6 @@ package dev.kejona.crossplatforms.spigot.adapter; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -10,15 +9,6 @@ public interface NbtAccessor { @Nullable String getCustomString(@Nonnull ItemStack stack, @Nonnull String key); - void setCustomString(@Nonnull ItemStack stack, @Nonnull String key, @Nonnull String value); - - void setCustomModelData(@Nonnull ItemStack stack, @Nullable Integer value); - @Nonnull - default ItemMeta requireItemMeta(ItemStack stack) { - if (!stack.hasItemMeta()) { - throw new IllegalArgumentException("ItemStack does not have ItemMeta: " + stack); - } - return stack.getItemMeta(); - } + void setCustomString(@Nonnull ItemStack stack, @Nonnull String key, @Nonnull String value); } diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java index 88f38672..caea9f32 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java @@ -1,15 +1,25 @@ package dev.kejona.crossplatforms.spigot.adapter; +import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.Plugin; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public interface VersionAdapter { boolean customModelData(); + void setCustomModelData(@Nonnull ItemStack stack, @Nullable Integer value); + Material playerHeadMaterial(); + void setSkullProfile(SkullMeta meta, FormPlayer player); + NbtAccessor nbtAccessor(Plugin plugin); void registerAuxiliaryEvents(Plugin plugin, SpigotAccessItems items); diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventory.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventory.java deleted file mode 100644 index 1a9b1c0d..00000000 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventory.java +++ /dev/null @@ -1,43 +0,0 @@ -package dev.kejona.crossplatforms.spigot.item; - -import dev.kejona.crossplatforms.item.Inventory; -import dev.kejona.crossplatforms.item.InventoryLayout; -import dev.kejona.crossplatforms.item.Item; -import org.bukkit.Bukkit; -import org.bukkit.event.inventory.InventoryType; - -public class SpigotInventory implements Inventory { - - private final org.bukkit.inventory.Inventory handle; - - public SpigotInventory(String title, int chestSize) { - handle = Bukkit.createInventory(null, chestSize, title); - } - - public SpigotInventory(String title, InventoryLayout layout) { - handle = Bukkit.createInventory(null, convertType(layout), title); - } - - @Override - public Object handle() { - return handle; - } - - @Override - public void setSlot(int index, Item item) { - handle.setItem(index, item.castedHandle()); - } - - public static InventoryType convertType(InventoryLayout layout) { - switch (layout) { - case CHEST: - return InventoryType.CHEST; - case HOPPER: - return InventoryType.HOPPER; - case DISPENSER: - return InventoryType.DISPENSER; - } - - throw new AssertionError("Unhandled InventoryLayout: " + layout.name()); - } -} diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java index 4017c54d..9341c2f4 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java @@ -7,44 +7,48 @@ import dev.kejona.crossplatforms.item.InventoryLayout; import dev.kejona.crossplatforms.item.Item; import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import lombok.RequiredArgsConstructor; +import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.SkullMeta; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; -import java.util.Objects; import java.util.OptionalInt; public class SpigotInventoryFactory implements InventoryFactory { - private static final Material PLAYER_HEAD_MATERIAL; + private static final int MAX_CHEST_SIZE = 9 * 5; - static { - Material modern = Material.getMaterial("PLAYER_HEAD"); - if (modern != null) { - PLAYER_HEAD_MATERIAL = modern; - } else { - Logger.get().debug("Using legacy SKULL_ITEM material for player heads"); - PLAYER_HEAD_MATERIAL = Objects.requireNonNull(Material.getMaterial("SKULL_ITEM"), "SKULL_ITEM material lookup"); - } - } + private static boolean warnedForCustomModelData = false; + private final VersionAdapter adapter; private final Material playerHeadMaterial; + private final Logger logger; - public SpigotInventoryFactory(VersionAdapter adapter) { - playerHeadMaterial = adapter.playerHeadMaterial(); + public SpigotInventoryFactory(VersionAdapter adapter, Logger logger) { + this.adapter = adapter; + this.playerHeadMaterial = adapter.playerHeadMaterial(); + this.logger = logger; } @Override public Inventory chest(String title, int chestSize) { - return new SpigotInventory(title, chestSize); + org.bukkit.inventory.Inventory inventory = Bukkit.createInventory(null, chestSize, title); + return new SpigotInventory(inventory); } @Override public Inventory inventory(String title, InventoryLayout layout) { - return new SpigotInventory(title, layout); + if (layout == InventoryLayout.CHEST) { + return chest(title, MAX_CHEST_SIZE); + } + + org.bukkit.inventory.Inventory inventory = Bukkit.createInventory(null, convertType(layout), title); + return new SpigotInventory(inventory); } @Override @@ -56,6 +60,20 @@ public Item item(String displayName, String material, List lore, Optiona meta.setLore(lore); item.setItemMeta(meta); + if (customModelData.isPresent()) { + if (adapter.customModelData()) { + // On a version that supports CustomModelData + adapter.setCustomModelData(item, customModelData.getAsInt()); + } else { + // Not supported, warn about it + if (!warnedForCustomModelData) { + logger.warn("Cannot set CustomModelData of " + customModelData.getAsInt() + " on item with name " + displayName); + logger.warn("Custom model data is not supported below 1.14"); + warnedForCustomModelData = true; + } + } + } + return new SpigotItem(item); } @@ -68,9 +86,50 @@ public Item skullItem(FormPlayer player, @Nullable String displayName, List Date: Thu, 19 Jan 2023 03:26:06 -0500 Subject: [PATCH 23/59] Remove stray import --- .../crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java index 7387c1bb..8a8423b6 100644 --- a/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java +++ b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/PlayerPickupItemListener.java @@ -1,6 +1,5 @@ package dev.kejona.crossplatforms.spigot.v1_8_R3; -import de.tr7zw.changeme.nbtapi.NBT; import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import lombok.AllArgsConstructor; import org.bukkit.event.EventHandler; From 33344fc7fcd6da3a6e501540f66958fb02595a6d Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 20 Jan 2023 01:19:42 -0500 Subject: [PATCH 24/59] Refactor Spigot version map and reflection --- .../kejona/crossplatforms/CrossplatForms.java | 2 - .../crossplatforms/utils/ReflectionUtils.java | 42 +++++++-- settings.gradle.kts | 3 - spigot-common/all/build.gradle.kts | 8 -- .../spigot/adapter/VersionIndexer.java | 79 ---------------- .../spigot/VersionIndexerTest.java | 81 ---------------- .../crossplatforms/spigot/ClassNames.java | 21 +++-- .../crossplatforms/spigot/SpigotBase.java | 14 ++- .../spigot/adapter/VersionIndexResult.java | 34 ------- .../spigot/adapter/VersionMap.java | 70 ++++++++++++++ .../spigot/adapter/VersionValue.java | 55 +++++++++++ .../spigot/handler/SpigotPlayer.java | 2 +- .../crossplatforms/spigot/VersionMapTest.java | 92 +++++++++++++++++++ .../spigot/v1_8_R3/Adapter_v1_8_R3.java | 14 +-- spigot/build.gradle.kts | 2 +- .../spigot/CrossplatFormsSpigot.java | 35 +++++-- 16 files changed, 303 insertions(+), 251 deletions(-) delete mode 100644 spigot-common/all/build.gradle.kts delete mode 100644 spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java delete mode 100644 spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/VersionIndexerTest.java delete mode 100644 spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexResult.java create mode 100644 spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionMap.java create mode 100644 spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionValue.java create mode 100644 spigot-common/common/src/test/java/dev/kejona/crossplatforms/spigot/VersionMapTest.java diff --git a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java index c77611bc..5aeee28e 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java +++ b/core/src/main/java/dev/kejona/crossplatforms/CrossplatForms.java @@ -143,12 +143,10 @@ public CrossplatForms(Logger logger, logger.debug("Took " + (System.currentTimeMillis() - configTime) + "ms to load config files."); // Load forms and menus from the configs into registries - long registryTime = System.currentTimeMillis(); interfacer.load( new BedrockFormRegistry(configManager, permissions), new JavaMenuRegistry(configManager, permissions) ); - logger.debug("Took " + (System.currentTimeMillis() - registryTime) + "ms to setup registries."); // Command defined in config or default provided by implementation rootCommand = generalConfig.map(GeneralConfig::getRootCommand).orElse(defaultCommand); diff --git a/core/src/main/java/dev/kejona/crossplatforms/utils/ReflectionUtils.java b/core/src/main/java/dev/kejona/crossplatforms/utils/ReflectionUtils.java index 4513e61c..00f1294e 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/utils/ReflectionUtils.java +++ b/core/src/main/java/dev/kejona/crossplatforms/utils/ReflectionUtils.java @@ -1,9 +1,12 @@ package dev.kejona.crossplatforms.utils; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Objects; public final class ReflectionUtils { @@ -16,11 +19,15 @@ public static Class getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { - e.printStackTrace(); return null; } } + @Nonnull + public static Class requireClass(String name) { + return Objects.requireNonNull(getClass(name), "Class for name " + name); + } + @Nullable public static Method getMethod(Class clazz, String method, boolean declared, Class... arguments) { try { @@ -42,13 +49,21 @@ public static Method getMethod(Class clazz, String methodName, Class... ar return getMethod(clazz, methodName, false, arguments); } + @Nonnull + public static Method requireMethod(Class clazz, String methodName, Class... arguments) { + return Objects.requireNonNull( + getMethod(clazz, methodName, arguments), + () -> methodName + " method of " + clazz.getName() + " with arguments " + Arrays.toString(arguments) + ); + } + @Nullable public static Object invoke(Object instance, Method method, Object... arguments) { method.setAccessible(true); try { return method.invoke(instance, arguments); - } catch (IllegalAccessException | InvocationTargetException exception) { - exception.printStackTrace(); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); return null; } } @@ -72,6 +87,21 @@ public static Field getField(Class clazz, String name, boolean declared) { } } + @Nullable + public static Field getField(Class clazz, String name) { + Field field = getField(clazz, name, true); // try declared fields, private or public + if (field == null) { + field = getField(clazz, name, false); // try public inherited fields + } + + return field; + } + + @Nonnull + public static Field requireField(Class clazz, String name) { + return Objects.requireNonNull(getField(clazz, name), () -> name + " field of " + clazz.getName()); + } + @Nullable public static Object getValue(Object instance, Field field) { field.setAccessible(true); @@ -90,10 +120,4 @@ public static void setValue(Object instance, Field field, Object value) { e.printStackTrace(); } } - - @SuppressWarnings("unchecked") - @Nullable - public static T getValue(Object instance, Field field, Class type) { - return (T) getValue(instance, field); - } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 6e4d345e..082dd7ec 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,9 +40,6 @@ include(":velocity") include(":spigot") -include(":spigot-common:all") -findProject(":spigot-common:all")?.name = "all" - include(":spigot-common:common") findProject(":spigot-common:common")?.name = "common" diff --git a/spigot-common/all/build.gradle.kts b/spigot-common/all/build.gradle.kts deleted file mode 100644 index be9045be..00000000 --- a/spigot-common/all/build.gradle.kts +++ /dev/null @@ -1,8 +0,0 @@ - -dependencies { - testImplementation("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") - - compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") - api(projects.spigotCommon.common) - implementation(projects.spigotCommon.v114R1) -} \ No newline at end of file diff --git a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java b/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java deleted file mode 100644 index 1cfafe9e..00000000 --- a/spigot-common/all/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexer.java +++ /dev/null @@ -1,79 +0,0 @@ -package dev.kejona.crossplatforms.spigot.adapter; - -import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; -import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; -import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; -import dev.kejona.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; -import dev.kejona.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; - -import javax.annotation.Nonnull; -import java.util.Objects; -import java.util.TreeMap; -import java.util.function.Supplier; - -public class VersionIndexer { - - private static final int SUPPORTED_MAJOR_VERSION = 1; - private static final TreeMap> ADAPTERS = new TreeMap<>(); - // todo: probably need to make the value generic so that this can be unit tested (some adapters rely on craft classes) - - static { - ADAPTERS.put(new Version("1_8_R3"), Adapter_v1_8_R3::new); - ADAPTERS.put(new Version("1_9_R2"), Adapter_v1_9_R2::new); - ADAPTERS.put(new Version("1_12_R1"), Adapter_v1_12_R1::new); - ADAPTERS.put(new Version("1_13_R2"), Adapter_v1_13_R2::new); - ADAPTERS.put(new Version("1_14_R1"), Adapter_v1_14_R1::new); - } - - @Nonnull - private VersionAdapter adapter(Version version) { - return Objects.requireNonNull(ADAPTERS.get(version)).get(); - } - - /** - * @param nmsVersion x_y_Rz - */ - public VersionIndexResult findLenientAdapter(String nmsVersion) throws IllegalArgumentException { - Version version = new Version(nmsVersion); - - if (version.major() != SUPPORTED_MAJOR_VERSION) { - return new VersionIndexResult(ADAPTERS.firstKey().nmsVersion()); - } - - if (ADAPTERS.containsKey(version)) { - // Direct support for this version - return new VersionIndexResult(adapter(version)); - } - - // Find adapter versions below and above the given version - Version lower = ADAPTERS.floorKey(version); - Version higher = ADAPTERS.ceilingKey(version); - - if (lower == null) { - // Given version is lower than lowest adapter version - return new VersionIndexResult(higher.nmsVersion()); - } - if (higher == null) { - // Given version is higher than highest adapter version - return new VersionIndexResult(adapter(lower)); - } - - if (lower.minor() != version.minor()) { - // Lower version is not the same "game version". eg 1.13 vs 1.14 - - if (higher.minor() == version.minor()) { - // The given version and higher adapter version only differ in patch version. The server should be updated. - // eg 1.13 < 1.14.1 < 1.14.2 - // lower version higher - return new VersionIndexResult(adapter(higher), higher.nmsVersion()); - } else { - // eg 1.13 < 1.14 < 1.15 - // lower version higher - return new VersionIndexResult(adapter(lower)); - } - } - - // There is an adapter for the same minor version, but a lower patch version - return new VersionIndexResult(adapter(lower)); - } -} diff --git a/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/VersionIndexerTest.java b/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/VersionIndexerTest.java deleted file mode 100644 index 5fa5ab48..00000000 --- a/spigot-common/all/src/test/java/dev/kejona/crossplatforms/spigot/VersionIndexerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package dev.kejona.crossplatforms.spigot; - -import dev.kejona.crossplatforms.spigot.adapter.VersionIndexer; -import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; -import dev.kejona.crossplatforms.spigot.adapter.VersionIndexResult; -import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; -import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; -import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; -import dev.kejona.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; -import dev.kejona.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.Map; - -public class VersionIndexerTest { - - private static VersionIndexer adapters; - private static final String[] UNSUPPORTED_VERSIONS = {"1_7_R4", "1_8_R1", "1_8_R2"}; - private static final String[] UNDESIRED_VERSIONS = {"1_9_R1", "1_13_R1"}; - private static final Map> EXPECTATIONS = new HashMap<>(); - - @BeforeAll - public static void setup() { - adapters = new VersionIndexer(); - - Class latestAdapter = Adapter_v1_14_R1.class; - - EXPECTATIONS.put("1_8_R3", Adapter_v1_8_R3.class); - EXPECTATIONS.put("1_9_R1", Adapter_v1_9_R2.class); // yikes - EXPECTATIONS.put("1_9_R2", Adapter_v1_9_R2.class); - EXPECTATIONS.put("1_10_R1", Adapter_v1_9_R2.class); - EXPECTATIONS.put("1_11_R1", Adapter_v1_9_R2.class); - EXPECTATIONS.put("1_12_R1", Adapter_v1_12_R1.class); - EXPECTATIONS.put("1_13_R1", Adapter_v1_13_R2.class); // yikes - EXPECTATIONS.put("1_13_R2", Adapter_v1_13_R2.class); - EXPECTATIONS.put("1_14_R1", Adapter_v1_14_R1.class); - EXPECTATIONS.put("1_15_R1", latestAdapter); - EXPECTATIONS.put("1_16_R1", latestAdapter); - EXPECTATIONS.put("1_16_R2", latestAdapter); - EXPECTATIONS.put("1_16_R3", latestAdapter); - EXPECTATIONS.put("1_17_R1", latestAdapter); - EXPECTATIONS.put("1_18_R1", latestAdapter); - EXPECTATIONS.put("1_18_R2", latestAdapter); - EXPECTATIONS.put("1_19_R1", latestAdapter); - EXPECTATIONS.put("1_19_R2", latestAdapter); - } - - @Test - public void testSupportedVersions() { - for (Map.Entry> entry : EXPECTATIONS.entrySet()) { - String version = entry.getKey(); - Class clazz = entry.getValue(); - - Assertions.assertInstanceOf( - clazz, - adapters.findLenientAdapter(version).adapter().orElse(null), - "Unexpected adapter for version " + version - ); - } - } - - @Test - public void testUndesiredVersions() { - for (String version : UNDESIRED_VERSIONS) { - Assertions.assertNotNull(adapters.findLenientAdapter(version).betterVersion().orElse(null)); - } - } - - @Test - public void testUnsupportedVersions() { - for (String version : UNSUPPORTED_VERSIONS) { - VersionIndexResult index = adapters.findLenientAdapter(version); - - Assertions.assertNull(index.adapter().orElse(null)); - Assertions.assertNotNull(index.betterVersion().orElse(null)); - } - } -} diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/ClassNames.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/ClassNames.java index 38eb8528..ccf5e649 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/ClassNames.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/ClassNames.java @@ -3,8 +3,8 @@ import dev.kejona.crossplatforms.utils.ReflectionUtils; import org.bukkit.Bukkit; +import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.Objects; /** * Thanks to Floodgate @@ -12,14 +12,23 @@ */ public final class ClassNames { - public static final Method GET_PROFILE_METHOD; + /** + * Includes the v at the front + */ + public static final String NMS_VERSION; + private static final String CRAFTBUKKIT_PACKAGE; + + public static final Method PLAYER_GET_PROFILE; + public static final Field META_SKULL_PROFILE; static { - String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + NMS_VERSION = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + CRAFTBUKKIT_PACKAGE = "org.bukkit.craftbukkit." + NMS_VERSION; - Class craftPlayerClass = ReflectionUtils.getClass("org.bukkit.craftbukkit." + version + ".entity.CraftPlayer"); + Class craftPlayer = ReflectionUtils.requireClass(CRAFTBUKKIT_PACKAGE + ".entity.CraftPlayer"); + PLAYER_GET_PROFILE = ReflectionUtils.requireMethod(craftPlayer, "getProfile"); - GET_PROFILE_METHOD = ReflectionUtils.getMethod(craftPlayerClass, "getProfile"); - Objects.requireNonNull(GET_PROFILE_METHOD, "Get profile method"); + Class craftMetaSkull = ReflectionUtils.requireClass(CRAFTBUKKIT_PACKAGE + ".inventory.CraftMetaSkull"); + META_SKULL_PROFILE = ReflectionUtils.requireField(craftMetaSkull, "profile"); } } diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java index ef3347e3..883d0eed 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java @@ -22,7 +22,7 @@ import dev.kejona.crossplatforms.permission.LuckPermsHook; import dev.kejona.crossplatforms.permission.Permissions; import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; -import dev.kejona.crossplatforms.spigot.adapter.VersionIndexResult; +import dev.kejona.crossplatforms.spigot.adapter.VersionValue; import dev.kejona.crossplatforms.spigot.handler.PlaceholderAPIHandler; import dev.kejona.crossplatforms.spigot.handler.SpigotCommandOrigin; import dev.kejona.crossplatforms.spigot.handler.SpigotHandler; @@ -70,10 +70,10 @@ public void onEnable() { audiences = BukkitAudiences.create(this); metrics = new Metrics(this, METRICS_ID); - VersionIndexResult result = findVersionAdapter(); + VersionValue result = findVersionAdapter(); result.betterVersion().ifPresent(v -> logger.warn("Consider using server version " + v + " instead.")); - if (result.adapter().isPresent()) { - versionAdapter = result.adapter().get(); + if (result.value().isPresent()) { + versionAdapter = result.value().get(); } else { logger.severe("This server version is unsupported. If you believe this is incorrect, please contact us."); getServer().getPluginManager().disablePlugin(this); @@ -104,6 +104,7 @@ public void onEnable() { try { // Brigadier is ideal if possible. Allows for much more readable command options, especially on BE. commandManager.registerBrigadier(); + logger.info("Successfully registered Brigadier mappings"); } catch (BukkitCommandManager.BrigadierFailureException e) { logger.warn("Failed to initialize Brigadier support: " + e.getMessage()); if (e.getReason() == BukkitCommandManager.BrigadierFailureReason.VERSION_TOO_HIGH) { @@ -136,6 +137,9 @@ public void onEnable() { this ); + // Wait for debug to be set or not + logger.info("Using " + versionAdapter.getClass().getSimpleName() + " for server version " + ClassNames.NMS_VERSION); + SpigotAccessItems accessItems = new SpigotAccessItems( this, versionAdapter, @@ -214,7 +218,7 @@ private boolean attemptBrigadier() { return false; } - public abstract VersionIndexResult findVersionAdapter(); + public abstract VersionValue findVersionAdapter(); public static SpigotBase getInstance() { return INSTANCE; diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexResult.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexResult.java deleted file mode 100644 index e05ae581..00000000 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionIndexResult.java +++ /dev/null @@ -1,34 +0,0 @@ -package dev.kejona.crossplatforms.spigot.adapter; - -import javax.annotation.Nonnull; -import java.util.Objects; -import java.util.Optional; - -public class VersionIndexResult { - - private final VersionAdapter adapter; - private final String betterVersion; - - protected VersionIndexResult(@Nonnull VersionAdapter adapter, @Nonnull String betterVersion) { - this.adapter = Objects.requireNonNull(adapter, "adapter"); - this.betterVersion = Objects.requireNonNull(betterVersion, "betterVersion"); - } - - protected VersionIndexResult(@Nonnull VersionAdapter adapter) { - this.adapter = Objects.requireNonNull(adapter, "adapter"); - this.betterVersion = null; - } - - protected VersionIndexResult(@Nonnull String betterVersion) { - this.adapter = null; - this.betterVersion = Objects.requireNonNull(betterVersion, "betterVersion"); - } - - public Optional adapter() { - return Optional.ofNullable(adapter); - } - - public Optional betterVersion() { - return Optional.ofNullable(betterVersion); - } -} diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionMap.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionMap.java new file mode 100644 index 00000000..4d6d1519 --- /dev/null +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionMap.java @@ -0,0 +1,70 @@ +package dev.kejona.crossplatforms.spigot.adapter; + +import javax.annotation.Nonnull; +import java.util.Objects; +import java.util.TreeMap; + +public class VersionMap extends TreeMap { + + private final int supportedMajorVersion; + + public VersionMap(int supportedMajorVersion) { + this.supportedMajorVersion = supportedMajorVersion; + } + + @Nonnull + private T adapter(Version version) { + return Objects.requireNonNull(get(version)); + } + + /** + * @param nmsVersion x_y_Rz + */ + public VersionValue findLenientAdapter(String nmsVersion) throws IllegalArgumentException { + if (isEmpty()) { + throw new IllegalStateException("The map is empty"); + } + + Version version = new Version(nmsVersion); + + if (version.major() != supportedMajorVersion) { + return new VersionValue<>(firstKey().nmsVersion()); + } + + if (containsKey(version)) { + // Direct support for this version + return new VersionValue<>(adapter(version)); + } + + // Find adapter versions below and above the given version + Version lower = floorKey(version); + Version higher = ceilingKey(version); + + if (lower == null) { + // Given version is lower than lowest adapter version + return new VersionValue<>(higher.nmsVersion()); + } + if (higher == null) { + // Given version is higher than highest adapter version + return new VersionValue<>(adapter(lower)); + } + + if (lower.minor() != version.minor()) { + // Lower version is not the same "game version". eg 1.13 vs 1.14 + + if (higher.minor() == version.minor()) { + // The given version and higher adapter version only differ in patch version. The server should be updated. + // eg 1.13 < 1.14.1 < 1.14.2 + // lower version higher + return new VersionValue<>(adapter(higher), higher.nmsVersion()); + } else { + // eg 1.13 < 1.14 < 1.15 + // lower version higher + return new VersionValue<>(adapter(lower)); + } + } + + // There is an adapter for the same minor version, but a lower patch version + return new VersionValue<>(adapter(lower)); + } +} diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionValue.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionValue.java new file mode 100644 index 00000000..e756765e --- /dev/null +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionValue.java @@ -0,0 +1,55 @@ +package dev.kejona.crossplatforms.spigot.adapter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Optional; +import java.util.function.Supplier; + +public class VersionValue { + + /** + * The value found for a version + */ + private final T value; + + /** + * A version that would be more ideal than the one used to find this value + */ + private final String betterVersion; + + public VersionValue(@Nullable T value, @Nullable String betterVersion) { + this.value = value; + this.betterVersion = betterVersion; + } + + public VersionValue(@Nonnull T value) { + this(value, null); + } + + public VersionValue(@Nonnull String betterVersion) { + this(null, betterVersion); + } + + public Optional value() { + return Optional.ofNullable(value); + } + + public Optional betterVersion() { + return Optional.ofNullable(betterVersion); + } + + /** + * Converts the given {@link Supplier} type {@link VersionValue} by calling {@link Supplier#get()} if the value is + * present, otherwise using null for the new VersionValue. + * + * @param value The Supplier type VersionValue to convert + * @param The type that the Supplier provides, that will be the type of the converted VersionValue + * @return A new {@link VersionValue} with the Supplier intermediary removed + */ + public static VersionValue convertSupplierType(VersionValue> value) { + return new VersionValue<>( + value.value().map(Supplier::get).orElse(null), + value.betterVersion().orElse(null) + ); + } +} diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPlayer.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPlayer.java index 373bda4a..4e5367e9 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPlayer.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/handler/SpigotPlayer.java @@ -50,7 +50,7 @@ public boolean hasPermission(String permission) { @Nullable @Override public String getEncodedSkinData() { - GameProfile profile = ReflectionUtils.castedInvoke(handle, ClassNames.GET_PROFILE_METHOD); + GameProfile profile = ReflectionUtils.castedInvoke(handle, ClassNames.PLAYER_GET_PROFILE); Objects.requireNonNull(profile, "game profile"); // Need to be careful here - getProperties() returns an authlib PropertyMap, which extends diff --git a/spigot-common/common/src/test/java/dev/kejona/crossplatforms/spigot/VersionMapTest.java b/spigot-common/common/src/test/java/dev/kejona/crossplatforms/spigot/VersionMapTest.java new file mode 100644 index 00000000..10b80c53 --- /dev/null +++ b/spigot-common/common/src/test/java/dev/kejona/crossplatforms/spigot/VersionMapTest.java @@ -0,0 +1,92 @@ +package dev.kejona.crossplatforms.spigot; + +import dev.kejona.crossplatforms.spigot.adapter.Version; +import dev.kejona.crossplatforms.spigot.adapter.VersionMap; +import dev.kejona.crossplatforms.spigot.adapter.VersionValue; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class VersionMapTest { + + private static VersionMap map; + private static final String[] UNSUPPORTED_VERSIONS = {"1_7_R4", "1_8_R1", "1_8_R2"}; + private static final String[] UNDESIRED_VERSIONS = {"1_9_R1", "1_13_R1"}; + private static final Map EXPECTATIONS = new HashMap<>(); + + @BeforeAll + public static void setup() { + // Mirrored from the actual version indexer in the plugin + map = new VersionMap<>(1); + map.put(new Version("1_8_R3"), "1_8_R3"); + map.put(new Version("1_9_R2"), "1_9_R2"); + map.put(new Version("1_12_R1"), "1_12_R1"); + map.put(new Version("1_13_R2"), "1_13_R2"); + map.put(new Version("1_14_R1"), "1_14_R1"); + + String latestAdapter = "1_14_R1"; + EXPECTATIONS.put("1_8_R3", "1_8_R3"); + EXPECTATIONS.put("1_9_R1", "1_9_R2"); // yikes + EXPECTATIONS.put("1_9_R2", "1_9_R2"); + EXPECTATIONS.put("1_10_R1", "1_9_R2"); + EXPECTATIONS.put("1_11_R1", "1_9_R2"); + EXPECTATIONS.put("1_12_R1", "1_12_R1"); + EXPECTATIONS.put("1_13_R1", "1_13_R2"); // yikes + EXPECTATIONS.put("1_13_R2", "1_13_R2"); + EXPECTATIONS.put("1_14_R1", "1_14_R1"); + EXPECTATIONS.put("1_15_R1", latestAdapter); + EXPECTATIONS.put("1_16_R1", latestAdapter); + EXPECTATIONS.put("1_16_R2", latestAdapter); + EXPECTATIONS.put("1_16_R3", latestAdapter); + EXPECTATIONS.put("1_17_R1", latestAdapter); + EXPECTATIONS.put("1_18_R1", latestAdapter); + EXPECTATIONS.put("1_18_R2", latestAdapter); + EXPECTATIONS.put("1_19_R1", latestAdapter); + EXPECTATIONS.put("1_19_R2", latestAdapter); + } + + @Test + public void testSupportedVersions() { + for (Map.Entry entry : EXPECTATIONS.entrySet()) { + String version = entry.getKey(); + String expected = entry.getValue(); + + Assertions.assertEquals( + expected, + map.findLenientAdapter(version).value().orElse(null), + "Failed to find the right version for a supported version" + ); + } + } + + @Test + public void testUndesiredVersions() { + for (String version : UNDESIRED_VERSIONS) { + Assertions.assertNotNull( + map.findLenientAdapter(version).betterVersion().orElse(null), + "Expected undesired version " + version + " to still result in a version" + ); + } + } + + @Test + public void testUnsupportedVersions() { + for (String version : UNSUPPORTED_VERSIONS) { + VersionValue index = map.findLenientAdapter(version); + + // The value + Assertions.assertNull(index.value().orElse(null), + "Expected version " + version + " to provide a null version (unsupported)" + ); + + // The version recommendation + Assertions.assertNotNull( + index.betterVersion().orElse(null), + "Expected version " + version + " to result in a recommendation for a better version" + ); + } + } +} diff --git a/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java index d51e6df5..c450a9b2 100644 --- a/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java +++ b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java @@ -3,6 +3,7 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import dev.kejona.crossplatforms.handler.FormPlayer; +import dev.kejona.crossplatforms.spigot.ClassNames; import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; @@ -15,20 +16,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.lang.reflect.Field; -import java.util.Objects; public class Adapter_v1_8_R3 implements VersionAdapter { - private static final Field PROFILE_FIELD; - - static { - PROFILE_FIELD = Objects.requireNonNull( - ReflectionUtils.getField(SkullMeta.class, "profile", true), - "Field 'profile' of GameProfile" - ); - } - @Override public boolean customModelData() { return false; @@ -49,7 +39,7 @@ public void setSkullProfile(SkullMeta meta, FormPlayer player) { GameProfile profile = new GameProfile(player.getUuid(), player.getName()); profile.getProperties().put("textures", new Property("textures", player.getEncodedSkinData())); - ReflectionUtils.setValue(meta, PROFILE_FIELD, profile); + ReflectionUtils.setValue(meta, ClassNames.META_SKULL_PROFILE, profile); } @Override diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index 5ab4c5a2..ebf2612e 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -7,7 +7,7 @@ plugins { dependencies { compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") api("de.tr7zw:item-nbt-api:2.10.0") - api(projects.spigotCommon.all) + api(projects.spigotCommon.v114R1) } tasks.withType { diff --git a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java index 6ab6a342..71cb59a2 100644 --- a/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java +++ b/spigot/src/main/java/dev/kejona/crossplatforms/spigot/CrossplatFormsSpigot.java @@ -1,18 +1,33 @@ package dev.kejona.crossplatforms.spigot; -import dev.kejona.crossplatforms.spigot.adapter.VersionIndexer; -import dev.kejona.crossplatforms.spigot.adapter.VersionIndexResult; +import dev.kejona.crossplatforms.spigot.adapter.Version; +import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; +import dev.kejona.crossplatforms.spigot.adapter.VersionMap; +import dev.kejona.crossplatforms.spigot.adapter.VersionValue; +import dev.kejona.crossplatforms.spigot.v1_12_R1.Adapter_v1_12_R1; +import dev.kejona.crossplatforms.spigot.v1_13_R2.Adapter_v1_13_R2; +import dev.kejona.crossplatforms.spigot.v1_14_R1.Adapter_v1_14_R1; +import dev.kejona.crossplatforms.spigot.v1_8_R3.Adapter_v1_8_R3; +import dev.kejona.crossplatforms.spigot.v1_9_R2.Adapter_v1_9_R2; + +import java.util.function.Supplier; public class CrossplatFormsSpigot extends SpigotBase { - @Override - public VersionIndexResult findVersionAdapter() { - String serverPackage = getServer().getClass().getPackage().getName(); - logger.debug("Server package: " + serverPackage); - // +2 to remove the ".v" - String version = serverPackage.substring(serverPackage.lastIndexOf('.') + 2); - logger.debug("NMS version: " + version); + private static final int SUPPORTED_MAJOR_VERSION = 1; + private static final VersionMap> INDEXER = new VersionMap<>(SUPPORTED_MAJOR_VERSION); - return new VersionIndexer().findLenientAdapter(version); + static { + INDEXER.put(new Version("1_8_R3"), Adapter_v1_8_R3::new); + INDEXER.put(new Version("1_9_R2"), Adapter_v1_9_R2::new); + INDEXER.put(new Version("1_12_R1"), Adapter_v1_12_R1::new); + INDEXER.put(new Version("1_13_R2"), Adapter_v1_13_R2::new); + INDEXER.put(new Version("1_14_R1"), Adapter_v1_14_R1::new); + } + + @Override + public VersionValue findVersionAdapter() { + // substring to remove the v + return VersionValue.convertSupplierType(INDEXER.findLenientAdapter(ClassNames.NMS_VERSION.substring(1))); } } From fc09e3a2ca4a83ae76d4b086a092591e16d54560 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 20 Jan 2023 15:04:25 -0500 Subject: [PATCH 25/59] Cleanup Spigot, ProtocolizeInterfacer --- .../crossplatforms/handler/FormPlayer.java | 3 ++- .../proxy/ProtocolizeInterfacer.java | 19 +++---------------- .../crossplatforms/spigot/SpigotBase.java | 6 +++--- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/dev/kejona/crossplatforms/handler/FormPlayer.java b/core/src/main/java/dev/kejona/crossplatforms/handler/FormPlayer.java index b5717461..51f87bb7 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/handler/FormPlayer.java +++ b/core/src/main/java/dev/kejona/crossplatforms/handler/FormPlayer.java @@ -60,10 +60,11 @@ default void warn(String message) { * Switch this player to a different backend server behind a proxy like BungeeCord or Velocity. If no proxy is * present, this method should fail silently and return true. This method should only return false if no backend * server is found by the given server name. + * * @param server The identifier of the backend server to switch the player to * @return false if and only if there is no backend server by the given name. */ - boolean switchBackendServer(String server); + boolean switchBackendServer(String server); // todo: probably would be better in ServerHandler T getHandle(Class asType) throws ClassCastException; } diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java index 7d73bce4..98cad47d 100644 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/ProtocolizeInterfacer.java @@ -3,31 +3,18 @@ import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.interfacing.Interfacer; -import dev.kejona.crossplatforms.interfacing.java.ItemButton; import dev.kejona.crossplatforms.interfacing.java.JavaMenu; import dev.kejona.crossplatforms.resolver.Resolver; import dev.simplix.protocolize.api.ClickType; import dev.simplix.protocolize.api.Protocolize; import dev.simplix.protocolize.api.inventory.Inventory; -import dev.simplix.protocolize.api.item.ItemStack; import dev.simplix.protocolize.api.player.ProtocolizePlayer; import dev.simplix.protocolize.api.providers.ProtocolizePlayerProvider; -import dev.simplix.protocolize.data.ItemType; -import dev.simplix.protocolize.data.inventory.InventoryType; - -import javax.annotation.Nonnull; -import java.util.Locale; -import java.util.Map; public class ProtocolizeInterfacer extends Interfacer { - private final Logger logger; - private final ProtocolizePlayerProvider playerProvider; - - public ProtocolizeInterfacer() { - this.logger = Logger.get(); - this.playerProvider = Protocolize.playerProvider(); - } + private final Logger logger = Logger.get(); + private final ProtocolizePlayerProvider playerProvider = Protocolize.playerProvider(); @Override public void openInventory(FormPlayer recipient, JavaMenu source, dev.kejona.crossplatforms.item.Inventory container, Resolver resolver) { @@ -35,7 +22,7 @@ public void openInventory(FormPlayer recipient, JavaMenu source, dev.kejona.cros Inventory inventory = container.castedHandle(); if (!inventory.clickConsumers().isEmpty()) { - Logger.get().severe("Cannot send menu '" + source.getIdentifier() + "' to " + recipient.getName() + " because the backing Protocolize inventory has already been shown to a different player."); + logger.severe("Cannot send menu '" + source.getIdentifier() + "' to " + recipient.getName() + " because the backing Protocolize inventory has already been shown to a different player."); Thread.dumpStack(); return; } diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java index 883d0eed..70228a39 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/SpigotBase.java @@ -100,7 +100,7 @@ public void onEnable() { return; } - if (attemptBrigadier()) { + if (brigadierAvailable()) { try { // Brigadier is ideal if possible. Allows for much more readable command options, especially on BE. commandManager.registerBrigadier(); @@ -138,7 +138,7 @@ public void onEnable() { ); // Wait for debug to be set or not - logger.info("Using " + versionAdapter.getClass().getSimpleName() + " for server version " + ClassNames.NMS_VERSION); + logger.debug("Using " + versionAdapter.getClass().getSimpleName() + " for server version " + ClassNames.NMS_VERSION); SpigotAccessItems accessItems = new SpigotAccessItems( this, @@ -206,7 +206,7 @@ private void convertGeyserHubConfig() { } } - private boolean attemptBrigadier() { + private boolean brigadierAvailable() { try { // Brigadier is available on 1.13 and above Class.forName("org.bukkit.entity.Dolphin"); From cf015e41b803594dc99ceb6e36d3fa620996ec8e Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 20 Jan 2023 22:06:35 -0500 Subject: [PATCH 26/59] More work on skulls, supporting more than just online players --- .../dev/kejona/crossplatforms/SkinCache.java | 64 +++-------- .../crossplatforms/config/ConfigManager.java | 2 + .../filler/UniversalFiller.java | 2 + .../interfacing/java/ItemButton.java | 26 ++--- .../crossplatforms/item/InventoryFactory.java | 13 ++- .../crossplatforms/item/SkullProfile.java | 94 +++++++++++++++ .../crossplatforms/utils/SkinUtils.java | 76 ++++++++++++ .../item/ProtocolizeInventoryFactory.java | 108 +++++++++++++++--- .../spigot/adapter/VersionAdapter.java | 9 +- .../spigot/item/SpigotInventoryFactory.java | 48 ++++++-- .../spigot/v1_8_R3/Adapter_v1_8_R3.java | 15 ++- 11 files changed, 359 insertions(+), 98 deletions(-) create mode 100644 core/src/main/java/dev/kejona/crossplatforms/item/SkullProfile.java create mode 100644 core/src/main/java/dev/kejona/crossplatforms/utils/SkinUtils.java diff --git a/core/src/main/java/dev/kejona/crossplatforms/SkinCache.java b/core/src/main/java/dev/kejona/crossplatforms/SkinCache.java index 13c404d2..66bd89bb 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/SkinCache.java +++ b/core/src/main/java/dev/kejona/crossplatforms/SkinCache.java @@ -2,30 +2,22 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import com.google.gson.Gson; -import com.google.gson.JsonObject; import dev.kejona.crossplatforms.handler.FormPlayer; +import dev.kejona.crossplatforms.utils.SkinUtils; import org.checkerframework.checker.nullness.qual.Nullable; -import java.nio.charset.StandardCharsets; -import java.util.Base64; +import javax.annotation.Nonnull; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class SkinCache { - private static final Gson GSON = new Gson(); - // See https://mc-heads.net/ private static final String AVATAR_ENDPOINT = "https://mc-heads.net/avatar/"; // See https://mc-heads.net/minecraft/mhf private static final String STEVE = "MHF_Steve"; - private static final String ALEX = "MHF_Alex"; - private static final Pattern URL_PATTERN = Pattern.compile("(http|https)://textures\\.minecraft\\.net/texture/([a-zA-Z0-9]+)"); private static final Logger LOGGER = Logger.get(); private final Cache avatars = CacheBuilder.newBuilder() @@ -36,7 +28,7 @@ public class SkinCache { public String getAvatarUrl(FormPlayer player) { UUID uuid = player.getUuid(); try { - return avatars.get(uuid, () -> readAvatarUrl(uuid, player.getEncodedSkinData())); + return avatars.get(uuid, () -> getAvatarUrl(uuid, player.getEncodedSkinData())); } catch (ExecutionException e) { LOGGER.warn("Exception while computing avatar url of " + player.getName()); e.printStackTrace(); @@ -44,44 +36,26 @@ public String getAvatarUrl(FormPlayer player) { } } - public static String readAvatarUrl(UUID uuid, @Nullable String encodedData) { - String url = AVATAR_ENDPOINT + readSkinId(uuid, encodedData); - LOGGER.debug("Avatar URL for " + uuid + ": " + url); - return url; - } - - public static String readSkinId(UUID uuid, @Nullable String encodedData) { + @Nonnull + public static String getAvatarUrl(UUID uuid, @Nullable String encodedData) { if (encodedData == null) { - LOGGER.debug("textures property (encoded) missing or empty for " + uuid + ", falling back to steve"); - return STEVE; - } - - // See https://wiki.vg/Mojang_API#UUID_to_Profile_and_Skin.2FCape - String decoded = new String(Base64.getDecoder().decode(encodedData), StandardCharsets.UTF_8); - JsonObject textures = GSON.fromJson(decoded, JsonObject.class).getAsJsonObject("textures"); - if (textures == null) { - LOGGER.debug("textures member missing for " + uuid + ", falling back to steve"); - return STEVE; + return AVATAR_ENDPOINT + STEVE; } + // todo: calculate default skin if no encoded data or failed to read - JsonObject skin = textures.getAsJsonObject("SKIN"); - if (skin == null) { - LOGGER.debug(uuid + " does not have custom skin, using steve or alex"); - // no custom skin - if ((uuid.hashCode() & 1) == 0) { - return STEVE; // even hashcode - } else { - return ALEX; // odd hashcode + try { + String skinUrl = SkinUtils.readSkinUrl(encodedData); + String skinId = SkinUtils.getSkinId(skinUrl); + String avatarUrl = AVATAR_ENDPOINT + skinId; + + LOGGER.debug("Avatar URL for " + uuid + ": " + avatarUrl); + return avatarUrl; + } catch (Exception e) { + if (LOGGER.isDebug()) { + LOGGER.debug("Failed to get avatar url for " + uuid); + e.printStackTrace(); } - } - - String url = skin.get("url").getAsString(); - Matcher matcher = URL_PATTERN.matcher(url); - if (matcher.matches()) { - return matcher.group(2); - } else { - LOGGER.debug("Skin url of " + uuid + " has unexpected format: " + url); - return STEVE; + return AVATAR_ENDPOINT + STEVE; } } } diff --git a/core/src/main/java/dev/kejona/crossplatforms/config/ConfigManager.java b/core/src/main/java/dev/kejona/crossplatforms/config/ConfigManager.java index 61c2f48c..e77a3c13 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/config/ConfigManager.java +++ b/core/src/main/java/dev/kejona/crossplatforms/config/ConfigManager.java @@ -18,6 +18,7 @@ import dev.kejona.crossplatforms.interfacing.Argument; import dev.kejona.crossplatforms.interfacing.bedrock.custom.Option; import dev.kejona.crossplatforms.interfacing.bedrock.custom.OptionSerializer; +import dev.kejona.crossplatforms.item.SkullProfile; import dev.kejona.crossplatforms.parser.Parser; import dev.kejona.crossplatforms.parser.ParserSerializer; import dev.kejona.crossplatforms.serialize.PathNodeResolver; @@ -91,6 +92,7 @@ public ConfigManager(Path directory, Logger logger, Injector injector) { builder.registerExact(Argument.class, new Argument.Serializer()); builder.registerExact(Option.class, new OptionSerializer()); builder.registerExact(Literals.class, new Literals.Serializer()); + builder.registerExact(SkullProfile.class, new SkullProfile.Serializer()); // serializers for abstract classes builder.registerExact(CustomCommand.class, new CustomCommandSerializer()); diff --git a/core/src/main/java/dev/kejona/crossplatforms/filler/UniversalFiller.java b/core/src/main/java/dev/kejona/crossplatforms/filler/UniversalFiller.java index ec06d0bc..7c266d09 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/filler/UniversalFiller.java +++ b/core/src/main/java/dev/kejona/crossplatforms/filler/UniversalFiller.java @@ -18,6 +18,8 @@ @ConfigSerializable public abstract class UniversalFiller implements OptionFiller, SimpleFormFiller, InventoryFiller { + // todo: this REALLY needs to be done in a better way... at least the formatting + /** * OptionFormat is used here since Option is deserialized as a scalar, and the format node is a map. */ diff --git a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java index 85fa83f6..3e6468cd 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java +++ b/core/src/main/java/dev/kejona/crossplatforms/interfacing/java/ItemButton.java @@ -3,6 +3,7 @@ import dev.kejona.crossplatforms.action.Action; import dev.kejona.crossplatforms.handler.FormPlayer; +import dev.kejona.crossplatforms.item.SkullProfile; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.ToString; @@ -11,7 +12,6 @@ import java.util.Collections; import java.util.List; -import java.util.OptionalInt; @ToString @NoArgsConstructor @@ -22,27 +22,22 @@ public class ItemButton { public static final String STATIC_IDENTIFIER = "crossplatformsbutton"; - @Nullable - private String displayName; - @Nullable private String material; @Nullable - private String skullOwner; + private String displayName; + + private List lore = Collections.emptyList(); - /** - * Only used internally for fillers - */ @Nullable - private transient FormPlayer targetPlayer; + private Integer customModelData; - private OptionalInt customModelData; + @Nullable + private SkullProfile skull; //private ConfigurationNode nbt; todo: possible support - private List lore = Collections.emptyList(); - private List> anyClick = Collections.emptyList(); private List> leftClick = Collections.emptyList(); private List> rightClick = Collections.emptyList(); @@ -54,15 +49,10 @@ public String getDisplayName() { return displayName; } - public boolean isPlayerHead() { - return skullOwner != null; - } - public static ItemButton fillEntry(String displayName, FormPlayer skullOwner) { ItemButton item = new ItemButton(); item.displayName = displayName; - item.skullOwner = skullOwner.getName(); - item.targetPlayer = skullOwner; + item.skull = new SkullProfile(skullOwner.getName(), skullOwner.getUuid(), skullOwner.getEncodedSkinData()); return item; } diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java index 940acb25..6c0ca122 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java +++ b/core/src/main/java/dev/kejona/crossplatforms/item/InventoryFactory.java @@ -2,16 +2,23 @@ import dev.kejona.crossplatforms.handler.FormPlayer; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; -import java.util.OptionalInt; public interface InventoryFactory { + /* + todo: This could be generified, along with config classes. this would allow for Configurate to directly serialize + implementation-specific classes, such as material enums. Additionally, if Interface#openInventory was moved to this + interface, then the usage of generics would mean that implementations would not have to cast Inventory/Item to get + their implementation back + */ Inventory chest(String title, int chestSize); Inventory inventory(String title, InventoryLayout layout); - Item item(String displayName, String material, List lore, OptionalInt customModelData); + Item item(@Nonnull String displayName, @Nullable String material, @Nonnull List lore, @Nullable Integer customModelData); - Item skullItem(FormPlayer owner, @Nullable String displayName, List lore); + Item skullItem(FormPlayer viewer, FormPlayer owner, @Nullable String displayName, List lore); + Item skullItem(FormPlayer viewer, SkullProfile owner, @Nullable String displayName, List lore); } diff --git a/core/src/main/java/dev/kejona/crossplatforms/item/SkullProfile.java b/core/src/main/java/dev/kejona/crossplatforms/item/SkullProfile.java new file mode 100644 index 00000000..18209694 --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/item/SkullProfile.java @@ -0,0 +1,94 @@ +package dev.kejona.crossplatforms.item; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import lombok.Getter; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.jetbrains.annotations.Contract; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.serialize.TypeSerializer; + +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.UUID; + +@Getter +@ConfigSerializable +public class SkullProfile { + + private static final int MIN_USERNAME_LENGTH = 3; + private static final int MAX_USERNAME_LENGTH = 16; + private static final String OWNER = "owner"; + private static final String TEXTURES = "textures"; + + private static final Gson GSON = new Gson(); + + @Nullable + private final String ownerName; + @Nullable + private final UUID ownerId; + @Nullable + private final String texturesValue; + + @Contract("null, null, null -> fail") + public SkullProfile(String ownerName, UUID ownerId, String texturesValue) { + if (ownerName == null && ownerId == null && texturesValue == null) { + throw new IllegalArgumentException("At least one of ownerName, ownerId, and texturesValue must be non null"); + } + + this.ownerName = ownerName; + this.ownerId = ownerId; + this.texturesValue = texturesValue; + } + + public static class Serializer implements TypeSerializer { + + @Override + public SkullProfile deserialize(Type type, ConfigurationNode node) throws SerializationException { + if (!node.isMap()) { + throw new SerializationException("Skull must be a config section containing 'owner' or 'textures'"); + } + + String textures = node.node(TEXTURES).getString(); + if (textures != null) { + // Do this just to make sure it is valid + String decoded = new String(Base64.getDecoder().decode(textures), StandardCharsets.UTF_8); + GSON.fromJson(decoded, JsonObject.class).getAsJsonObject("textures"); + + return new SkullProfile(null, null, textures); + } + + try { + UUID uuid = node.node(OWNER).get(UUID.class); + return new SkullProfile(null, uuid, null); + } catch (Exception ignored) { + String name = node.node(OWNER).getString(); + if (name == null || name.isEmpty()) { + throw new SerializationException("'owner' is empty or not present"); + } + + if (name.length() < MIN_USERNAME_LENGTH || name.length() > MAX_USERNAME_LENGTH) { + throw new SerializationException("'owner' is not a valid UUID and the length is too short or too long to be a valid username"); + } + + return new SkullProfile(name, null, null); + } + } + + @Override + public void serialize(Type type, @Nullable SkullProfile skull, ConfigurationNode node) throws SerializationException { + if (skull != null) { + if (skull.texturesValue != null) { + node.node(TEXTURES).set(skull.texturesValue); + } else if (skull.ownerId != null) { + node.node(OWNER).set(skull.ownerId); + } else if (skull.ownerName != null) { + node.node(OWNER).set(skull.ownerName); + } + } + } + } +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/utils/SkinUtils.java b/core/src/main/java/dev/kejona/crossplatforms/utils/SkinUtils.java new file mode 100644 index 00000000..63aa49cf --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/utils/SkinUtils.java @@ -0,0 +1,76 @@ +package dev.kejona.crossplatforms.utils; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import javax.annotation.Nonnull; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class SkinUtils { + + private static final Gson GSON = new Gson(); + private static final Pattern URL_PATTERN = Pattern.compile("(http|https)://textures\\.minecraft\\.net/texture/([a-zA-Z0-9]+)"); + + private SkinUtils() { + + } + + @Nonnull + public static String readSkinUrl(@Nonnull String encodedData) throws IllegalArgumentException { + + // See https://wiki.vg/Mojang_API#UUID_to_Profile_and_Skin.2FCape + JsonObject json; + try { + String decoded = new String(Base64.getDecoder().decode(encodedData), StandardCharsets.UTF_8); + json = GSON.fromJson(decoded, JsonObject.class); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to decode base64 textures value: " + encodedData, e); + } + + JsonObject textures = json.getAsJsonObject("textures"); + if (textures == null) { + throw new IllegalArgumentException("textures member missing in " + encodedData); + } + + JsonObject skin = textures.getAsJsonObject("SKIN"); + if (skin == null) { + throw new IllegalArgumentException("SKIN member missing in " + encodedData); + } + + JsonElement url = skin.get("url"); + if (url == null) { + throw new IllegalArgumentException("url member missing in " + encodedData); + } + + try { + return Objects.requireNonNull(url.getAsString(), "url as string"); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to get url element in " + encodedData, e); + } + } + + public static boolean isValidUrl(String skinUrl) { + return URL_PATTERN.matcher(skinUrl).matches(); + } + + public static void requireValidUrl(String skinUrl) { + if (!isValidUrl(skinUrl)) { + throw new IllegalArgumentException("Skin url has unexpected format: " + skinUrl); + } + } + + @Nonnull + public static String getSkinId(String skinUrl) { + Matcher matcher = URL_PATTERN.matcher(skinUrl); + if (matcher.matches()) { + return matcher.group(2); + } else { + throw new IllegalArgumentException("Skin url has unexpected format: " + skinUrl); + } + } +} diff --git a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java index d04be09e..f15ee56a 100644 --- a/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java +++ b/proxy/src/main/java/dev/kejona/crossplatforms/proxy/item/ProtocolizeInventoryFactory.java @@ -1,27 +1,34 @@ package dev.kejona.crossplatforms.proxy.item; +import dev.kejona.crossplatforms.Logger; import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.item.Inventory; import dev.kejona.crossplatforms.item.InventoryFactory; import dev.kejona.crossplatforms.item.InventoryLayout; import dev.kejona.crossplatforms.item.Item; +import dev.kejona.crossplatforms.item.SkullProfile; import dev.simplix.protocolize.api.Protocolize; import dev.simplix.protocolize.api.item.ItemStack; +import dev.simplix.protocolize.api.player.ProtocolizePlayer; +import dev.simplix.protocolize.api.providers.ProtocolizePlayerProvider; import dev.simplix.protocolize.data.ItemType; import dev.simplix.protocolize.data.inventory.InventoryType; import net.querz.nbt.tag.CompoundTag; import net.querz.nbt.tag.ListTag; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.Locale; -import java.util.OptionalInt; import java.util.UUID; public class ProtocolizeInventoryFactory implements InventoryFactory { + private static final int PROTOCOL_1_16 = 735; private static final String CUSTOM_MODEL_DATA_KEY = "CustomModelData"; + private final ProtocolizePlayerProvider players = Protocolize.playerProvider(); + @Override public Inventory chest(String title, int chestSize) { InventoryType type = InventoryType.chestInventoryWithSize(chestSize); @@ -43,14 +50,26 @@ public Inventory inventory(String title, InventoryLayout layout) { } @Override - public Item item(String displayName, String material, List lore, OptionalInt customModelData) { - ItemStack item = new ItemStack(ItemType.valueOf(material.toUpperCase(Locale.ROOT).trim())); + public Item item(@Nonnull String displayName, @Nullable String material, @Nonnull List lore, @Nullable Integer customModelData) { + ItemType type; + if (material == null || material.isEmpty()) { + type = ItemType.STONE; + } else { + try { + type = ItemType.valueOf(material.toUpperCase(Locale.ROOT).trim()); + } catch (IllegalArgumentException ignored) { + Logger.get().warn("Material '" + material + "' is not a valid material on BungeeCord/Velocity (Protocolize)"); + type = ItemType.STONE; + } + } + + ItemStack item = new ItemStack(type); item.displayName(displayName); item.lore(lore, true); CompoundTag nbt = item.nbtData(); - if (customModelData.isPresent()) { - nbt.putInt(CUSTOM_MODEL_DATA_KEY, customModelData.getAsInt()); + if (customModelData != null) { + nbt.putInt(CUSTOM_MODEL_DATA_KEY, customModelData); } else { nbt.remove(CUSTOM_MODEL_DATA_KEY); } @@ -59,36 +78,91 @@ public Item item(String displayName, String material, List lore, Optiona } @Override - public Item skullItem(FormPlayer owner, @Nullable String displayName, List lore) { + public Item skullItem(FormPlayer viewer, FormPlayer owner, @Nullable String displayName, List lore) { + ItemStack item = skullBase(displayName, lore); + setSkullOwner(viewer, item.nbtData(), owner.getUuid(), owner.getName(), owner.getEncodedSkinData()); + return new ProtocolizeItem(item); + } + + @Override + public Item skullItem(FormPlayer viewer, SkullProfile owner, @org.jetbrains.annotations.Nullable String displayName, List lore) { + ItemStack item = skullBase(displayName, lore); + setSkullOwner(viewer, + item.nbtData(), + owner.getOwnerId(), + owner.getOwnerName(), + owner.getTexturesValue() + ); + + return new ProtocolizeItem(item); + } + + private ItemStack skullBase(@Nullable String displayName, List lore) { ItemStack item = new ItemStack(ItemType.PLAYER_HEAD); if (displayName != null) { item.displayName(displayName); } item.lore(lore, true); - // https://minecraft.fandom.com/wiki/Head#Item_data + return item; + } + + private void setSkullOwner(FormPlayer itemReceiver, CompoundTag tag, UUID id, String name, String textures) { + if (id == null && name == null && textures == null) { + throw new IllegalArgumentException("id, name, textures cannot all be null"); + } + + if (id == null && textures == null) { + // old cruddy format of only the name + tag.putString("SkullOwner", name); + return; + } + + if (id == null && name == null) { + // only textures provided - use random UUID + id = UUID.randomUUID(); + } + CompoundTag skullOwner = new CompoundTag(); - skullOwner.putIntArray("Id", uuidToArray(owner.getUuid())); // todo: different for below 1.16 apparently - skullOwner.putString("Name", owner.getName()); - skullOwner.put("Properties", propertiesForTextures(owner.getEncodedSkinData())); + if (id != null) { + setSkullId(itemReceiver, skullOwner, id); + } + if (name != null) { + skullOwner.putString("Name", name); + } + if (textures != null) { + skullOwner.put("Properties", propertiesWithTextures(textures)); + } - item.nbtData().put("SkullOwner", skullOwner); + tag.put("SkullOwner", skullOwner); + } - return new ProtocolizeItem(item); + private void setSkullId(FormPlayer itemReceiver, CompoundTag skullOwner, UUID id) { + ProtocolizePlayer player = players.player(itemReceiver.getUuid()); + + // UUID storage was changed in 1.16 + if (player.protocolVersion() < PROTOCOL_1_16) { + skullOwner.putString("Id", id.toString()); + } else { + skullOwner.putIntArray("Id", uuidToArray(id)); + } } - private CompoundTag propertiesForTextures(String encodedTexture) { - CompoundTag properties = new CompoundTag(); - ListTag textures = new ListTag<>(CompoundTag.class); + private CompoundTag propertiesWithTextures(String encodedTexture) { CompoundTag texture = new CompoundTag(); + texture.putString("Value", encodedTexture); - properties.put("textures", textures); + ListTag textures = new ListTag<>(CompoundTag.class); textures.add(texture); - texture.putString("Value", encodedTexture); + CompoundTag properties = new CompoundTag(); + properties.put("textures", textures); return properties; } + /** + * Returns the format for storing UUIDs in NBT, for 1.16 and later + */ private static int[] uuidToArray(UUID uuid) { long least = uuid.getLeastSignificantBits(); long most = uuid.getMostSignificantBits(); diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java index caea9f32..fc5e56f2 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/adapter/VersionAdapter.java @@ -6,9 +6,11 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.Contract; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.UUID; public interface VersionAdapter { @@ -18,7 +20,12 @@ public interface VersionAdapter { Material playerHeadMaterial(); - void setSkullProfile(SkullMeta meta, FormPlayer player); + @Contract("_, null, null, null -> fail") + void setSkullProfile(SkullMeta meta, UUID id, String name, String textures); + + default void setSkullProfile(SkullMeta meta, FormPlayer player) { + setSkullProfile(meta, player.getUuid(), player.getName(), player.getEncodedSkinData()); + } NbtAccessor nbtAccessor(Plugin plugin); diff --git a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java index 9341c2f4..a6585135 100644 --- a/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java +++ b/spigot-common/common/src/main/java/dev/kejona/crossplatforms/spigot/item/SpigotInventoryFactory.java @@ -6,6 +6,7 @@ import dev.kejona.crossplatforms.item.InventoryFactory; import dev.kejona.crossplatforms.item.InventoryLayout; import dev.kejona.crossplatforms.item.Item; +import dev.kejona.crossplatforms.item.SkullProfile; import dev.kejona.crossplatforms.spigot.adapter.VersionAdapter; import lombok.RequiredArgsConstructor; import org.bukkit.Bukkit; @@ -16,8 +17,8 @@ import org.bukkit.inventory.meta.SkullMeta; import org.checkerframework.checker.nullness.qual.Nullable; +import javax.annotation.Nonnull; import java.util.List; -import java.util.OptionalInt; public class SpigotInventoryFactory implements InventoryFactory { @@ -52,22 +53,34 @@ public Inventory inventory(String title, InventoryLayout layout) { } @Override - public Item item(String displayName, String material, List lore, OptionalInt customModelData) { - ItemStack item = new ItemStack(Material.matchMaterial(material)); + public Item item(@Nonnull String displayName, @Nullable String material, @Nonnull List lore, Integer customModelData) { + Material type; + if (material == null || material.isEmpty()) { + type = Material.STONE; + } else { + try { + type = Material.matchMaterial(material); + } catch (IllegalArgumentException ignored) { + Logger.get().warn("Material '" + material + "' is not a valid material on BungeeCord/Velocity (Protocolize)"); + type = Material.STONE; + } + } + + ItemStack item = new ItemStack(type); ItemMeta meta = item.getItemMeta(); meta.setDisplayName(displayName); meta.setLore(lore); item.setItemMeta(meta); - if (customModelData.isPresent()) { + if (customModelData != null) { if (adapter.customModelData()) { // On a version that supports CustomModelData - adapter.setCustomModelData(item, customModelData.getAsInt()); + adapter.setCustomModelData(item, customModelData); } else { // Not supported, warn about it if (!warnedForCustomModelData) { - logger.warn("Cannot set CustomModelData of " + customModelData.getAsInt() + " on item with name " + displayName); + logger.warn("Cannot set CustomModelData of " + customModelData + " on item with name " + displayName); logger.warn("Custom model data is not supported below 1.14"); warnedForCustomModelData = true; } @@ -78,19 +91,34 @@ public Item item(String displayName, String material, List lore, Optiona } @Override - public Item skullItem(FormPlayer player, @Nullable String displayName, List lore) { - ItemStack item = new ItemStack(playerHeadMaterial); + public Item skullItem(FormPlayer viewer, FormPlayer owner, @Nullable String displayName, List lore) { + ItemStack item = skullBase(displayName, lore); + adapter.setSkullProfile(skullMeta(item), owner); + return new SpigotItem(item); + } + + @Override + public Item skullItem(FormPlayer viewer, SkullProfile owner, @Nullable String displayName, List lore) { + ItemStack item = skullBase(displayName, lore); + adapter.setSkullProfile(skullMeta(item), owner.getOwnerId(), owner.getOwnerName(), owner.getTexturesValue()); + return new SpigotItem(item); + } + private ItemStack skullBase(String displayName, List lore) { + ItemStack item = new ItemStack(playerHeadMaterial); SkullMeta meta = (SkullMeta) item.getItemMeta(); + if (displayName != null) { meta.setDisplayName(displayName); } meta.setLore(lore); item.setItemMeta(meta); - adapter.setSkullProfile(meta, player); + return item; + } - return new SpigotItem(item); + private SkullMeta skullMeta(ItemStack skullItem) { + return (SkullMeta) skullItem; } private static InventoryType convertType(InventoryLayout layout) { diff --git a/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java index c450a9b2..372b9823 100644 --- a/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java +++ b/spigot-common/v1_8_R3/src/main/java/dev/kejona/crossplatforms/spigot/v1_8_R3/Adapter_v1_8_R3.java @@ -2,7 +2,6 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import dev.kejona.crossplatforms.handler.FormPlayer; import dev.kejona.crossplatforms.spigot.ClassNames; import dev.kejona.crossplatforms.spigot.SpigotAccessItems; import dev.kejona.crossplatforms.spigot.adapter.NbtAccessor; @@ -16,6 +15,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.UUID; public class Adapter_v1_8_R3 implements VersionAdapter { @@ -35,9 +35,16 @@ public Material playerHeadMaterial() { } @Override - public void setSkullProfile(SkullMeta meta, FormPlayer player) { - GameProfile profile = new GameProfile(player.getUuid(), player.getName()); - profile.getProperties().put("textures", new Property("textures", player.getEncodedSkinData())); + public void setSkullProfile(SkullMeta meta, @Nullable UUID id, @Nullable String name, @Nullable String textures) { + if (id == null && name == null) { + id = UUID.randomUUID(); + } + + GameProfile profile = new GameProfile(id, name); + + if (textures != null) { + profile.getProperties().put("textures", new Property("textures", textures)); + } ReflectionUtils.setValue(meta, ClassNames.META_SKULL_PROFILE, profile); } From 7cf540ca626aaadb82f242da011f2cc90b8f7e67 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sat, 21 Jan 2023 22:09:59 -0500 Subject: [PATCH 27/59] Refactor fillers --- .../crossplatforms/context/Context.java | 8 ++++ .../crossplatforms/context/PlayerContext.java | 16 ++++++++ .../crossplatforms/filler/FillerUtils.java | 37 +++++++++++++++---- .../filler/InventoryFiller.java | 29 +++++++++------ .../crossplatforms/filler/OptionFiller.java | 24 +++++++----- .../crossplatforms/filler/PlayerFiller.java | 12 +++--- .../filler/SimpleFormFiller.java | 19 ++++++---- .../crossplatforms/filler/SplitterFiller.java | 6 +-- .../filler/UniversalFiller.java | 36 +++++++++++------- .../bedrock/custom/CustomBedrockForm.java | 4 +- .../bedrock/custom/CustomComponent.java | 16 ++++---- .../interfacing/bedrock/custom/Dropdown.java | 20 +++------- .../interfacing/bedrock/custom/Input.java | 17 +++------ .../interfacing/bedrock/custom/Label.java | 8 ---- .../interfacing/bedrock/custom/Option.java | 4 +- .../interfacing/bedrock/custom/Slider.java | 13 ++----- .../bedrock/custom/StepSlider.java | 20 +++------- .../interfacing/bedrock/custom/Toggle.java | 15 ++------ .../bedrock/simple/SimpleBedrockForm.java | 9 ++--- .../interfacing/java/ItemButton.java | 11 +++--- .../component/ResolvePlaceholdersTest.java | 11 ++++-- 21 files changed, 183 insertions(+), 152 deletions(-) create mode 100644 core/src/main/java/dev/kejona/crossplatforms/context/Context.java create mode 100644 core/src/main/java/dev/kejona/crossplatforms/context/PlayerContext.java diff --git a/core/src/main/java/dev/kejona/crossplatforms/context/Context.java b/core/src/main/java/dev/kejona/crossplatforms/context/Context.java new file mode 100644 index 00000000..f429d407 --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/context/Context.java @@ -0,0 +1,8 @@ +package dev.kejona.crossplatforms.context; + +import dev.kejona.crossplatforms.resolver.Resolver; + +public interface Context { + + Resolver resolver(); +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/context/PlayerContext.java b/core/src/main/java/dev/kejona/crossplatforms/context/PlayerContext.java new file mode 100644 index 00000000..aae878e6 --- /dev/null +++ b/core/src/main/java/dev/kejona/crossplatforms/context/PlayerContext.java @@ -0,0 +1,16 @@ +package dev.kejona.crossplatforms.context; + +import dev.kejona.crossplatforms.handler.FormPlayer; +import dev.kejona.crossplatforms.resolver.Resolver; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class PlayerContext implements Context { + + private final FormPlayer player; + private final Resolver resolver; +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/filler/FillerUtils.java b/core/src/main/java/dev/kejona/crossplatforms/filler/FillerUtils.java index 65bdaa8b..95d4172a 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/filler/FillerUtils.java +++ b/core/src/main/java/dev/kejona/crossplatforms/filler/FillerUtils.java @@ -4,19 +4,42 @@ import org.jetbrains.annotations.Contract; import javax.annotation.Nonnull; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Stream; public final class FillerUtils { + /** + * Replaces part(s) of a "template" string with a given value. This is primarily meant for formatting defaultValue + * with the optional template. + * + * @param template the template string to apply the key Pattern to + * @param key the Pattern used for doing replacement in the template String + * @param defaultValue The String that matches will be replaced with + * @return a new string with the replacements performed if both template and default value are not null. + * If defaultValue is null, template is returned. If template is null, it is considered that + * not formatting required, so defaultValue is returned. + */ @Nullable @Contract("_, _, null -> param1; null, _, !null -> param3; !null, _, !null -> !null") - public static String replace(@Nullable String base, @Nonnull Pattern key, @Nullable String replacement) { - if (replacement == null) { - return base; // value is not present. return either an override the user specified, or null. - } else if (base == null) { - return replacement; // user did not specify formatting, still use the raw value + public static String replace(@Nullable String template, @Nonnull Pattern key, @Nullable String defaultValue) { + if (defaultValue == null) { + return template; // value is not present. return either an override the user specified, or null. + } else if (template == null) { + return defaultValue; // user did not specify formatting, still use the raw value } - return key.matcher(base).replaceAll(Matcher.quoteReplacement(replacement)); - }} + return key.matcher(template).replaceAll(Matcher.quoteReplacement(defaultValue)); + } + + protected static void addAtIndex(Stream src, List dest, int index) { + if (index < 0) { + // index invalid or not set - silently ignore for config purposes + src.forEachOrdered(dest::add); + } else { + src.forEachOrdered(e -> dest.add(index, e)); + } + } +} diff --git a/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java b/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java index 88964d8b..7193f011 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java +++ b/core/src/main/java/dev/kejona/crossplatforms/filler/InventoryFiller.java @@ -1,30 +1,35 @@ package dev.kejona.crossplatforms.filler; -import dev.kejona.crossplatforms.resolver.Resolver; +import dev.kejona.crossplatforms.context.PlayerContext; import dev.kejona.crossplatforms.interfacing.java.ItemButton; import dev.kejona.crossplatforms.serialize.ValuedType; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.Map; public interface InventoryFiller extends ValuedType { - default List generateItems(Resolver resolver) { - ItemButton format = itemFormat(); - if (format == null) { - return rawItems(resolver).collect(Collectors.toList()); + default void fillItems(Map container, PlayerContext context) { + ItemButton template = itemTemplate(); + + Map buttons = rawItems(context); + if (template != null) { + // Apply formatting + for (Map.Entry entry : buttons.entrySet()) { + ItemButton value = entry.getValue(); + entry.setValue(template.withReplacementsFromFiller(value)); + } } - throw new IllegalStateException("Item generation not implemented yet"); - // return rawItems(resolver).map(item -> item.format(format)).collect(Collectors.toList()); + // todo: actually need to be aware of inventory shape/size ... + + container.putAll(buttons); } @Nonnull - Stream rawItems(Resolver resolver); + Map rawItems(PlayerContext context); @Nullable - ItemButton itemFormat(); + ItemButton itemTemplate(); } diff --git a/core/src/main/java/dev/kejona/crossplatforms/filler/OptionFiller.java b/core/src/main/java/dev/kejona/crossplatforms/filler/OptionFiller.java index 2aa25ad4..30be8aaa 100644 --- a/core/src/main/java/dev/kejona/crossplatforms/filler/OptionFiller.java +++ b/core/src/main/java/dev/kejona/crossplatforms/filler/OptionFiller.java @@ -1,11 +1,12 @@ package dev.kejona.crossplatforms.filler; -import dev.kejona.crossplatforms.resolver.Resolver; +import dev.kejona.crossplatforms.context.PlayerContext; import dev.kejona.crossplatforms.interfacing.bedrock.custom.Option; import dev.kejona.crossplatforms.serialize.ValuedType; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; import java.util.regex.Pattern; import java.util.stream.Stream; @@ -13,20 +14,25 @@ public interface OptionFiller extends ValuedType { Pattern PLACEHOLDER = Pattern.compile("%raw_text%"); - default Stream