From ef6a9db9f0cd0875795d39039202414beba70513 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Mon, 29 Jul 2024 11:52:52 +0900 Subject: [PATCH] feat: backup item tag before warping to lifetown --- build.gradle.kts | 3 +- .../com/github/mori01231/lifecore/LifeCore.kt | 2 +- .../lifecore/command/LifeCoreUtilCommand.kt | 6 ++-- .../lifecore/command/TownServerCommand.kt | 24 ++++++++++++++ .../lifecore/listener/PlayerJoinListener.java | 31 +++++++++++++++++++ .../mori01231/lifecore/util/ItemUtil.java | 31 +++++++++++++++++-- .../lifecore/util/JoinFilterUtil.java | 17 ++++++++++ .../util/external/JoinFilterBridge.java | 12 +++++++ src/main/resources/config.yml | 3 ++ src/main/resources/plugin.yml | 1 + 10 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/github/mori01231/lifecore/command/TownServerCommand.kt create mode 100644 src/main/java/com/github/mori01231/lifecore/util/JoinFilterUtil.java create mode 100644 src/main/java/com/github/mori01231/lifecore/util/external/JoinFilterBridge.java diff --git a/build.gradle.kts b/build.gradle.kts index 66534f9..14ec35d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ plugins { } group = "net.azisaba" -version = "1.15.2+6.16.3" +version = "1.15.2+6.16.4" java { toolchain.languageVersion.set(JavaLanguageVersion.of(8)) @@ -63,6 +63,7 @@ dependencies { implementation("org.mariadb.jdbc:mariadb-java-client:3.0.6") implementation("org.yaml:snakeyaml:2.0") implementation("xyz.acrylicstyle.java-util:expression:2.0.0-SNAPSHOT") + compileOnly("net.azisaba:JoinFilter:1.0.0") compileOnly("net.azisaba.ballotbox:receiver:1.0.1") compileOnly("net.azisaba.azipluginmessaging:api:4.0.3") compileOnly("net.azisaba:RyuZUPluginChat:4.2.0") diff --git a/src/main/java/com/github/mori01231/lifecore/LifeCore.kt b/src/main/java/com/github/mori01231/lifecore/LifeCore.kt index 1e1bcd7..bc121c5 100644 --- a/src/main/java/com/github/mori01231/lifecore/LifeCore.kt +++ b/src/main/java/com/github/mori01231/lifecore/LifeCore.kt @@ -130,7 +130,7 @@ class LifeCore : JavaPlugin() { registerCommand("life", TransferCommand(this, "life")) registerCommand("resource", TransferCommand(this, "liferesource")) registerCommand("event", TransferCommand(this, "lifeevent")) - registerCommand("townserver", TransferCommand(this, "lifetown")) + registerCommand("townserver", TownServerCommand(this)) registerCommand("rank", RankCommand(this)) registerCommand("trash", TrashCommand()) registerCommand("kiai", KiaiCommand()) diff --git a/src/main/java/com/github/mori01231/lifecore/command/LifeCoreUtilCommand.kt b/src/main/java/com/github/mori01231/lifecore/command/LifeCoreUtilCommand.kt index db8ae35..d2f2982 100644 --- a/src/main/java/com/github/mori01231/lifecore/command/LifeCoreUtilCommand.kt +++ b/src/main/java/com/github/mori01231/lifecore/command/LifeCoreUtilCommand.kt @@ -233,7 +233,7 @@ class LifeCoreUtilCommand(val plugin: LifeCore) : TabExecutor { val item = CraftItemStack.asNMSCopy((player as Player).inventory.itemInMainHand) val tag = item.tag ?: NBTTagCompound() tag.a(MojangsonParser.parse(args.joinToString(" "))) - (player as Player).inventory.setItemInMainHand(CraftItemStack.asBukkitCopy(item)) + player.inventory.setItemInMainHand(CraftItemStack.asBukkitCopy(item)) } }, SetTag { @@ -244,7 +244,7 @@ class LifeCoreUtilCommand(val plugin: LifeCore) : TabExecutor { } val item = CraftItemStack.asNMSCopy((player as Player).inventory.itemInMainHand) item.tag = MojangsonParser.parse(args.joinToString(" ")) - (player as Player).inventory.setItemInMainHand(CraftItemStack.asBukkitCopy(item)) + player.inventory.setItemInMainHand(CraftItemStack.asBukkitCopy(item)) } }, GetBlock { @@ -300,7 +300,7 @@ class LifeCoreUtilCommand(val plugin: LifeCore) : TabExecutor { ClearPlot("イマサラタウンのplotを消し飛ばします") { override fun execute(plugin: LifeCore, player: CommandSender, args: Array) { val minX = (player as Player).chunk.x * 16 - val minZ = (player as Player).chunk.z * 16 + val minZ = player.chunk.z * 16 val maxX = minX + 15 val maxZ = minZ + 15 scheduleLater(plugin, 0) { Bukkit.dispatchCommand(player, "/chunk") } diff --git a/src/main/java/com/github/mori01231/lifecore/command/TownServerCommand.kt b/src/main/java/com/github/mori01231/lifecore/command/TownServerCommand.kt new file mode 100644 index 0000000..b551d0d --- /dev/null +++ b/src/main/java/com/github/mori01231/lifecore/command/TownServerCommand.kt @@ -0,0 +1,24 @@ +package com.github.mori01231.lifecore.command + +import com.github.mori01231.lifecore.LifeCore +import com.github.mori01231.lifecore.util.ItemUtil +import com.github.mori01231.lifecore.util.JoinFilterUtil +import org.bukkit.command.Command +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +class TownServerCommand(private val plugin: LifeCore) : TransferCommand(plugin, "lifetown") { + override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array): Boolean { + val player = sender as? Player ?: return false + if (plugin.config.getBoolean("enable-backup-item-tag", true)) { + val size = player.inventory.size + for (i in 0.. { + Player player = Bukkit.getPlayer(e.getPlayer().getUniqueId()); + if (player == null || !player.isOnline()) { + return; + } + + // restore item tags + if (plugin.getConfig().getBoolean("enable-backup-item-tag", true)) { + int size = player.getInventory().getSize(); + for (int i = 0; i < size; i++) { + player.getInventory().setItem(i, ItemUtil.restoreTag(player.getInventory().getItem(i))); + } + } + }, 20 * 2); // 2 seconds + Bukkit.getScheduler().runTaskLater(plugin, () -> { + Player player = Bukkit.getPlayer(e.getPlayer().getUniqueId()); + if (player == null || !player.isOnline()) { + return; + } + + // restore item tags + if (plugin.getConfig().getBoolean("enable-backup-item-tag", true)) { + int size = player.getInventory().getSize(); + for (int i = 0; i < size; i++) { + player.getInventory().setItem(i, ItemUtil.restoreTag(player.getInventory().getItem(i))); + } + } + }, 20 * 10); // 10 seconds } @EventHandler diff --git a/src/main/java/com/github/mori01231/lifecore/util/ItemUtil.java b/src/main/java/com/github/mori01231/lifecore/util/ItemUtil.java index cd6af3d..ad0da1e 100644 --- a/src/main/java/com/github/mori01231/lifecore/util/ItemUtil.java +++ b/src/main/java/com/github/mori01231/lifecore/util/ItemUtil.java @@ -68,11 +68,18 @@ public static boolean isProbablyAdminSword(@Nullable ItemStack stack) { return CraftItemStack.asBukkitCopy(nms); } - public static @NotNull ItemStack setTag(@Nullable ItemStack stack, @NotNull String key, @NotNull NBTBase nbt) { + public static @NotNull ItemStack setTag(@Nullable ItemStack stack, @Nullable String key, @NotNull NBTBase nbt) { if (stack == null || stack.getType().isAir()) return new ItemStack(Material.AIR); net.minecraft.server.v1_15_R1.ItemStack nms = CraftItemStack.asNMSCopy(stack); - NBTTagCompound tag = nms.getOrCreateTag(); - tag.set(key, nbt); + if (key == null) { + if (!(nbt instanceof NBTTagCompound)) { + throw new IllegalArgumentException("key is null, but nbt is not NBTTagCompound"); + } + nms.setTag((NBTTagCompound) nbt); + } else { + NBTTagCompound tag = nms.getOrCreateTag(); + tag.set(key, nbt); + } return CraftItemStack.asBukkitCopy(nms); } @@ -134,4 +141,22 @@ public static boolean isEquippedInAnySlot(@NotNull Player player, @NotNull Strin } return false; } + + @Contract("null -> null") + public static ItemStack backupTag(@Nullable ItemStack stack) { + if (stack == null || stack.getType().isAir()) return null; + NBTTagCompound tag = CraftItemStack.asNMSCopy(stack).getTag(); + if (tag == null || tag.isEmpty()) return stack; + return setTag(stack, "backup", tag); + } + + @Contract("null -> null") + public static ItemStack restoreTag(@Nullable ItemStack stack) { + if (stack == null || stack.getType().isAir()) return null; + NBTTagCompound tag = CraftItemStack.asNMSCopy(stack).getTag(); + if (tag == null) return stack; + NBTTagCompound backup = tag.getCompound("backup"); + if (backup == null || backup.isEmpty()) return stack; + return setTag(stack, null, backup); + } } diff --git a/src/main/java/com/github/mori01231/lifecore/util/JoinFilterUtil.java b/src/main/java/com/github/mori01231/lifecore/util/JoinFilterUtil.java new file mode 100644 index 0000000..5e59748 --- /dev/null +++ b/src/main/java/com/github/mori01231/lifecore/util/JoinFilterUtil.java @@ -0,0 +1,17 @@ +package com.github.mori01231.lifecore.util; + +import com.github.mori01231.lifecore.util.external.JoinFilterBridge; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class JoinFilterUtil { + public static boolean addPlayerWithExpire(@NotNull UUID uuid, @NotNull String server, long expireSeconds) { + if (Bukkit.getPluginManager().isPluginEnabled("JoinFilter")) { + JoinFilterBridge.addPlayerWithExpire(uuid, server, expireSeconds); + return true; + } + return false; + } +} diff --git a/src/main/java/com/github/mori01231/lifecore/util/external/JoinFilterBridge.java b/src/main/java/com/github/mori01231/lifecore/util/external/JoinFilterBridge.java new file mode 100644 index 0000000..7ea6c99 --- /dev/null +++ b/src/main/java/com/github/mori01231/lifecore/util/external/JoinFilterBridge.java @@ -0,0 +1,12 @@ +package com.github.mori01231.lifecore.util.external; + +import net.azisaba.joinfilter.JoinFilter; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class JoinFilterBridge { + public static void addPlayerWithExpire(@NotNull UUID uuid, @NotNull String server, long expireSeconds) { + JoinFilter.getPlugin(JoinFilter.class).addPlayerWithExpire(uuid, server, expireSeconds); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 2ad0393..0f080a3 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -2,6 +2,9 @@ lp-server-name: life +# enable backup of item tag when executing /townserver, and restore when joining. +enable-backup-item-tag: true + use-pve-command-as-teleport: true website-url: https://azisaba.net/ diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0218f77..66beb51 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -12,6 +12,7 @@ softdepend: - Towny - MythicMobs - ItemStash + - JoinFilter api-version: 1.13 commands: