From 98d9eb8e1f7280960bcc9cc79304d260f106464f Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 20:01:36 +0900 Subject: [PATCH 01/44] write vote listener --- build.gradle.kts | 1 + .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 5 +- .../listeners/other/VoteListener.java | 81 ++++++++++++++++++- .../afnw/afnwcore2/util/item/AfnwTicket.java | 4 +- .../afnw/afnwcore2/util/item/ItemUtil.java | 21 +++++ src/main/resources/config.yml | 42 +++++----- src/main/resources/plugin.yml | 4 +- 7 files changed, 131 insertions(+), 27 deletions(-) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java diff --git a/build.gradle.kts b/build.gradle.kts index 0f5ba63..64d7e9f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -39,6 +39,7 @@ dependencies { compileOnly("io.papermc.paper:paper-api:1.20.2-R0.1-SNAPSHOT") compileOnly("org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT") compileOnly("net.azisaba.ballotbox:receiver:1.0.1") + compileOnly("net.azisaba:ItemStash:1.0.0-SNAPSHOT") compileOnly("net.essentialsx:EssentialsX:2.19.7") } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 429001e..020300e 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -41,6 +41,9 @@ public void onEnable() { // コンフィグのロード saveDefaultConfig(); + if (getConfig().getBoolean("settings.require-item-stash", false) && Bukkit.getPluginManager().isPluginEnabled("ItemStash")) { + throw new RuntimeException("ItemStashプラグインがインストールされていません。settings > require-item-stashをfalseにするか、ItemStashをインストール、またはエラーを確認してください。"); + } getLogger().info("コンフィグ ロード完了"); // プレイヤーデータのロード @@ -67,7 +70,7 @@ public void onEnable() { /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); /* その他 */ - pluginEvent.registerEvents(new VoteListener(), this); + pluginEvent.registerEvents(new VoteListener(this, data), this); getLogger().info("Listener 設定完了"); /* ブロックリスナー */ pluginEvent.registerEvents(new CropsBreakCanceller(), this); diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java index 9031549..a5f4095 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java @@ -1,12 +1,89 @@ package net.azisaba.afnw.afnwcore2.listeners.other; import com.vexsoftware.votifier.model.VotifierEvent; +import net.azisaba.afnw.afnwcore2.AfnwCore2; +import net.azisaba.afnw.afnwcore2.util.data.PlayerData; +import net.azisaba.afnw.afnwcore2.util.item.AfnwTicket; +import net.azisaba.afnw.afnwcore2.util.item.ItemUtil; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; -public class VoteListener implements Listener { +public record VoteListener(AfnwCore2 plugin, PlayerData playerData) implements Listener { @EventHandler public void onVote(VotifierEvent e) { - // + FileConfiguration config = plugin.getConfig(); + int ticketSize = config.getInt("vote.send-ticket-size", 1); + int bonusLine = config.getInt("vote.bonus-line", 9); + Player sendTarget = Bukkit.getPlayerExact(e.getVote().getUsername()); + + ItemStack ticketItem = AfnwTicket.afnwTicket.clone(); + ticketItem.setAmount(ticketSize); + + if (sendTarget != null) { + Inventory inv = sendTarget.getInventory(); + + for (ItemStack stack : inv.addItem(ticketItem).values()) { + ItemUtil.addToStashIfEnabledAsync(plugin, sendTarget.getUniqueId(), stack); + } + + FileConfiguration dataFile = playerData.getPlayerData(); + int voteCount = dataFile.getInt((sendTarget.getUniqueId().toString())); + voteCount++; + if (voteCount >= bonusLine) { + for (int i = 0; i < 10; i++) { + for (ItemStack value : inv.addItem(AfnwTicket.afnwTicket).values()) { + ItemUtil.addToStashIfEnabledAsync(plugin, sendTarget.getUniqueId(), value); + } + } + for (ItemStack value : inv.addItem(new ItemStack(Material.NETHER_STAR)).values()) { + ItemUtil.addToStashIfEnabledAsync(plugin, sendTarget.getUniqueId(), value); + } + sendTarget.sendMessage(Component.text("* 投票ボーナスとしてチケット10枚とネザースターを獲得しました。") + .color(NamedTextColor.YELLOW)); + sendTarget.sendMessage( + Component.text("* 投票ボーナスがリセットされました。次回以降の投票から有効です。").color(NamedTextColor.YELLOW)); + plugin.getSLF4JLogger().info(sendTarget.getName() + "が投票ボーナスを獲得しました。"); + voteCount = 0; + } + dataFile.set(sendTarget.getUniqueId().toString(), voteCount); + playerData.savePlayerData(); + + // 成功した趣旨の情報送信 + plugin.getSLF4JLogger().info(sendTarget.getName() + "へのチケット送信に成功しました。配布数:" + ticketSize); + // 通知 + sendTarget.sendMessage(Component.text("チケットを入手しました。/afnwを実行することでアイテムと交換することができます。", + NamedTextColor.LIGHT_PURPLE)); + sendTarget.sendMessage(Component.text("投票ボーナスまで: " + voteCount + "/" + config.getInt("vote.bonus-line", 10), NamedTextColor.YELLOW)); + } else { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + OfflinePlayer player = Bukkit.getOfflinePlayer(e.getVote().getUsername()); + ItemUtil.addToStashIfEnabled(player.getUniqueId(), ticketItem); + FileConfiguration dataFile = playerData.getPlayerData(); + int voteCount = dataFile.getInt((player.getUniqueId().toString())); + voteCount++; + if (voteCount >= bonusLine) { + for (int i = 0; i < 10; i++) { + ItemUtil.addToStashIfEnabled(player.getUniqueId(), ticketItem); + } + ItemUtil.addToStashIfEnabled(player.getUniqueId(), new ItemStack(Material.NETHER_STAR)); + plugin.getSLF4JLogger().info(player.getName() + " (" + player.getUniqueId() + ")が投票ボーナスを獲得しました。"); + voteCount = 0; + } + dataFile.set(player.getUniqueId().toString(), voteCount); + playerData.savePlayerData(); + + // 成功した趣旨の情報送信 + plugin.getSLF4JLogger().info(player.getName() + " (" + player.getUniqueId() + ")へのチケット送信に成功しました。配布数:" + ticketSize); + }); + } } } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/AfnwTicket.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/AfnwTicket.java index 2dba6ca..e6ed996 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/AfnwTicket.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/AfnwTicket.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; -import net.azisaba.afnw.afnwcore2.AfnwCore2; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Material; @@ -12,10 +11,9 @@ /** * AfnwTicketを生成します。 * - * @param plugin メインクラス * @author m2en */ -public record AfnwTicket(AfnwCore2 plugin) { +public record AfnwTicket() { public static ItemStack afnwTicket = new ItemStack(Material.PAPER, 1); diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java new file mode 100644 index 0000000..10fe910 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java @@ -0,0 +1,21 @@ +package net.azisaba.afnw.afnwcore2.util.item; + +import net.azisaba.itemstash.ItemStash; +import org.bukkit.Bukkit; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class ItemUtil { + public static void addToStashIfEnabled(@NotNull UUID uuid, @NotNull ItemStack stack) { + if (Bukkit.getPluginManager().isPluginEnabled("ItemStash")) { + ItemStash.getInstance().addItemToStash(uuid, stack); + } + } + + public static void addToStashIfEnabledAsync(@NotNull Plugin plugin, @NotNull UUID uuid, @NotNull ItemStack stack) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> addToStashIfEnabled(uuid, stack)); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ba6064d..511cd58 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -2,51 +2,53 @@ # AfnwCore2に関するいろんな設定を変更できるファイルです。パーミッションの設定はここでは行えません。 # 編集した後はサーバーを再起動するか、プラグインを再リロードするか、コマンド "/config_reload" を実行してください。 # デフォルト値は万が一指定されていないときにAfnwCore2が代入する値です。(World名のConfigではデフォルト値が入ってもワールドが見つからない場合はNullPointerException(例外)としてクラッシュします。) - -vote: # 投票周りの設定 - item-size: 1 +# 投票周りの設定 +vote: # /afnwで交換できるアイテムの数を指定してください。int(数)ではない場合はエラーが発生します。デフォルト: 1 - scaffold-size: 8 + item-size: 1 # /afnwで交換時に一緒に配布される足場の数を指定してください。int(数)ではない場合はエラーが発生します。デフォルト: 8 - send-ticket-size: 1 + scaffold-size: 8 # 投票時に受け取れるチケットの数を指定してください。int(数)ではない場合はエラーが発生します。デフォルト: 1 - bonus-line: 10 + send-ticket-size: 1 # 投票ボーナスの回数を指定します。指定された数以上の回数と一致したらチケット10枚とネザースターが配布されます。int(数)ではない場合はエラーが発生します。デフォルト: 10 + bonus-line: 10 tp: - standby: 10 # TPコマンド(not /tp)を使用した際の待機時間を秒で指定します。int(数)ではない場合はエラーが発生します。デフォルト: 10 - lobby_world_name: "lobby" + standby: 10 # ロビーワールドの名前を指定します。デフォルト:lobby - void_world_name: "afnw" + lobby_world_name: "lobby" # Voidワールドの名前を指定します。デフォルト:afnw - tutorial_world_name: "tutorial" + void_world_name: "afnw" # チュートリアルワールドの名前を指定します。デフォルト:tutorial + tutorial_world_name: "tutorial" afk: - afk_world_name: "afk" # AFKポイントとして利用するワールド名を指定します。デフォルト:afk + afk_world_name: "afk" + # AFKポイントとして利用する座標をそれぞれ指定します。int(数)ではない場合はエラーが発生します。窒息を防ぐため、Y座標のみ一つ足された数値で利用されるので注意してください。 + # デフォルト値は0です。必ず指定することをおすすめします。 afk_point_x: 0 afk_point_y: 0 afk_point_z: 0 - # AFKポイントとして利用する座標をそれぞれ指定します。int(数)ではない場合はエラーが発生します。窒息を防ぐため、Y座標のみ一つ足された数値で利用されるので注意してください。 - # デフォルト値は0です。必ず指定することをおすすめします。 trash: - name: "ゴミ箱" # ゴミ箱の名前を指定します。"春猫"って指定しちゃダメだよ。デフォルト:ゴミ箱 - size: 54 + name: "ゴミ箱" # ゴミ箱のスロット数を指定します。int(数)ではない場合はエラーが発生します。デフォルト: 54 # Spigot(Paper) 、どっちかというとMinecraft自身の仕様で9の倍数である必要があります。9の倍数ではない場合はデフォルト値に変更されます。 + size: 54 settings: - player-save-period: 120 # プレイヤーデータの自動セーブ間隔を秒で指定します。int(数)ではない場合はエラーが発生します。デフォルト: 120 - allow-bedrock-player: ['.Meru92a'] + player-save-period: 120 # Bedrock Blockerを除外するプレイヤーのMCIDを入力します。必ず先頭には "." を入れ、コンマで区切ってください。 - allow-wither-spawn: true + allow-bedrock-player: ['.Meru92a'] # ウィザーのスポーン(召喚)を許可するか, booleanで指定します。 true: 許可します。召喚されてもキャンセルしません。 / false: 許可しません。召喚されてもキャンセルします。 - notification-wither-spawn: true + allow-wither-spawn: true # ウィザーの召喚通知を行うか, booleanで指定します。true: 通知します / false: 通知しません。 - maintenance-mode-toggle: false + notification-wither-spawn: true # メンテナンスモードで起動するか, booleanで指定します。true: 起動します / false: 起動しません。 + maintenance-mode-toggle: false + # ItemStashプラグインが有効ではない場合はクラッシュします。 + require-item-stash: false diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index fed73e4..7cc8ec8 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -6,7 +6,9 @@ prefix: AfnwCore2 load: STARTUP authors: [ merunno, afnwteam ] description: That world, once again. -depend: [ Essentials ] +depend: [ Essentials, Votifier ] +softdepend: + - ItemStash website: https://github.com/AfnwTeam/AfnwCore2 permissions: From 42253e58ac6e3dd803e6d37fa2f8bd56e98fe0ec Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 20:04:36 +0900 Subject: [PATCH 02/44] feat: add VillagerInteractListener --- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 1 + .../player/VillagerInteractListener.java | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerInteractListener.java diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 020300e..cb745a3 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -67,6 +67,7 @@ public void onEnable() { pluginEvent.registerEvents(new AFKListener(this), this); pluginEvent.registerEvents(new RespawnEnvironment(this), this); pluginEvent.registerEvents(new SuperAfnwTicketListener(), this); + pluginEvent.registerEvents(new VillagerInteractListener(), this); /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); /* その他 */ diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerInteractListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerInteractListener.java new file mode 100644 index 0000000..a00c174 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerInteractListener.java @@ -0,0 +1,26 @@ +package net.azisaba.afnw.afnwcore2.listeners.player; + +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; + +/** + * 製図家に対するクリックを無効化するクラス + */ +public record VillagerInteractListener() implements Listener { + @EventHandler + public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent e) { + onPlayerInteractEntity(e); + } + + @EventHandler + public void onPlayerInteractEntity(PlayerInteractEntityEvent e) { + if (e.getRightClicked() instanceof Villager villager) { + if (villager.getProfession() == Villager.Profession.CARTOGRAPHER) { + e.setCancelled(true); + } + } + } +} From ba819c8457c07546f51060bff699aee2b0bc0ef4 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 21:21:41 +0900 Subject: [PATCH 03/44] feat: add super afnw ticket handler --- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 2 +- .../afnw/afnwcore2/commands/AfnwCommand.java | 28 ++++--------------- .../player/SuperAfnwTicketListener.java | 27 ++++++++++++++++-- .../afnw/afnwcore2/util/item/ItemUtil.java | 15 ++++++++++ 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index cb745a3..94603d4 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -66,7 +66,7 @@ public void onEnable() { pluginEvent.registerEvents(new FirstPlayerJoinListener(this, data), this); pluginEvent.registerEvents(new AFKListener(this), this); pluginEvent.registerEvents(new RespawnEnvironment(this), this); - pluginEvent.registerEvents(new SuperAfnwTicketListener(), this); + pluginEvent.registerEvents(new SuperAfnwTicketListener(this), this); pluginEvent.registerEvents(new VillagerInteractListener(), this); /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java index 6650702..7a7a919 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java @@ -34,28 +34,12 @@ private static boolean isAllowed(Material type) { if (!type.isItem()) { return false; } - switch (type) { - case BEDROCK: - case STRUCTURE_BLOCK: - case STRUCTURE_VOID: - case COMMAND_BLOCK: - case CHAIN_COMMAND_BLOCK: - case COMMAND_BLOCK_MINECART: - case REPEATING_COMMAND_BLOCK: - case BARRIER: - case LIGHT: - case JIGSAW: - case END_PORTAL: - case KNOWLEDGE_BOOK: - case DEBUG_STICK: - case AIR: - case VOID_AIR: - case CAVE_AIR: - case BUNDLE: - return false; - default: - return true; - } + return switch (type) { + case BEDROCK, STRUCTURE_BLOCK, STRUCTURE_VOID, COMMAND_BLOCK, CHAIN_COMMAND_BLOCK, COMMAND_BLOCK_MINECART, + REPEATING_COMMAND_BLOCK, BARRIER, LIGHT, JIGSAW, END_PORTAL, KNOWLEDGE_BOOK, DEBUG_STICK, + AIR, VOID_AIR, CAVE_AIR, BUNDLE -> false; + default -> true; + }; } @Contract("_ -> new") diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java index 30f00d0..e856d95 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java @@ -1,13 +1,36 @@ package net.azisaba.afnw.afnwcore2.listeners.player; +import net.azisaba.afnw.afnwcore2.commands.AfnwCommand; +import net.azisaba.afnw.afnwcore2.util.item.ItemUtil; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Sound; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; -public class SuperAfnwTicketListener implements Listener { +/** + * Super Afnw Ticketの実際の動作 + */ +public record SuperAfnwTicketListener(Plugin plugin) implements Listener { @EventHandler public void onPlayerInteract(PlayerInteractEvent e) { - if (e.getAction() != Action.LEFT_CLICK_AIR && e.getAction() != Action.LEFT_CLICK_BLOCK) return; + if (e.getAction() != Action.RIGHT_CLICK_AIR && e.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if (e.getPlayer().getGameMode() != GameMode.SURVIVAL) return; + if (!"Super_Afnw_Ticket".equals(ItemUtil.getMythicType(e.getItem()))) return; + e.getItem().setAmount(e.getItem().getAmount() - 1); + e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 1.5f); + Bukkit.getScheduler().runTaskLater(plugin, () -> e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 1.75f), 3); + Bukkit.getScheduler().runTaskLater(plugin, () -> e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 2.0f), 6); + for (Player player : Bukkit.getOnlinePlayers()) { + for (ItemStack value : player.getInventory().addItem(AfnwCommand.getRandomItem(1)).values()) { + ItemUtil.addToStashIfEnabledAsync(plugin, player.getUniqueId(), value); + } + player.sendMessage("§d" + e.getPlayer().getName() + "§eが§aSuper Afnw Ticket§eを使用し、アイテムが配布されました!"); + } } } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java index 10fe910..05fd7c2 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java @@ -2,9 +2,12 @@ import net.azisaba.itemstash.ItemStash; import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.UUID; @@ -18,4 +21,16 @@ public static void addToStashIfEnabled(@NotNull UUID uuid, @NotNull ItemStack st public static void addToStashIfEnabledAsync(@NotNull Plugin plugin, @NotNull UUID uuid, @NotNull ItemStack stack) { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> addToStashIfEnabled(uuid, stack)); } + + public static @NotNull String getStringTag(@NotNull ItemStack stack, @NotNull String name) { + return CraftItemStack.asNMSCopy(stack).w().l(name); + } + + @Contract("null -> null") + public static @Nullable String getMythicType(@Nullable ItemStack stack) { + if (stack == null) return null; + String s = getStringTag(stack, "MYTHIC_TYPE"); + if (s.isBlank()) return null; + return s; + } } From 6713c09ae182ce4ec37790da1c1e27cc407ae8d9 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 21:55:28 +0900 Subject: [PATCH 04/44] feat: add villager protector --- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 1 + .../player/VillagerProtectorListener.java | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 94603d4..53674d4 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -68,6 +68,7 @@ public void onEnable() { pluginEvent.registerEvents(new RespawnEnvironment(this), this); pluginEvent.registerEvents(new SuperAfnwTicketListener(this), this); pluginEvent.registerEvents(new VillagerInteractListener(), this); + pluginEvent.registerEvents(new VillagerProtectorListener(), this); /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); /* その他 */ diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java new file mode 100644 index 0000000..ce87d96 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java @@ -0,0 +1,24 @@ +package net.azisaba.afnw.afnwcore2.listeners.player; + +import org.bukkit.GameMode; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Player; +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; + +public class VillagerProtectorListener implements Listener { + @EventHandler + public void onPlayerAttack(EntityDamageByEntityEvent e) { + if (!(e.getEntity() instanceof Villager)) return; + if (e.getDamager() instanceof Player player) { + if (player.getGameMode() != GameMode.CREATIVE) { + e.setCancelled(true); + } + } + if (e.getDamager() instanceof Arrow arrow && arrow.getShooter() instanceof Player) { + e.setCancelled(true); + } + } +} From 65f0dd7f996d8c4e45c1c928ce9e5c662ad3266e Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 22:00:14 +0900 Subject: [PATCH 05/44] feat: add bed listener and ender dragon disable listener --- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 2 + .../listeners/player/BedListener.java | 41 +++++++++++++++++++ .../player/EnderDragonDisableListener.java | 27 ++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BedListener.java create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/EnderDragonDisableListener.java diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 53674d4..8e85cfc 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -69,6 +69,8 @@ public void onEnable() { pluginEvent.registerEvents(new SuperAfnwTicketListener(this), this); pluginEvent.registerEvents(new VillagerInteractListener(), this); pluginEvent.registerEvents(new VillagerProtectorListener(), this); + pluginEvent.registerEvents(new BedListener(this), this); + pluginEvent.registerEvents(new EnderDragonDisableListener(), this); /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); /* その他 */ diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BedListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BedListener.java new file mode 100644 index 0000000..3c8f6bd --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BedListener.java @@ -0,0 +1,41 @@ +package net.azisaba.afnw.afnwcore2.listeners.player; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class BedListener implements Listener { + private final Map clicks = new HashMap<>(); + private final Plugin plugin; + + public BedListener(@NotNull Plugin plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onInteract(PlayerInteractEvent e) { + if (e.getClickedBlock() == null) return; + if (e.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if (e.getClickedBlock().getType().name().contains("_BED")) { + int current = clicks.getOrDefault(e.getPlayer().getUniqueId(), 0); + if (current < 2) { + e.getPlayer().sendMessage(Component.text("あと" + (2 - current) + "回クリックしてください...", NamedTextColor.YELLOW)); + e.setCancelled(true); + clicks.put(e.getPlayer().getUniqueId(), current + 1); + Bukkit.getScheduler().runTaskLater(plugin, () -> clicks.remove(e.getPlayer().getUniqueId()), 20 * 3); + } else { + clicks.remove(e.getPlayer().getUniqueId()); + } + } + } +} diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/EnderDragonDisableListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/EnderDragonDisableListener.java new file mode 100644 index 0000000..ddb48fd --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/EnderDragonDisableListener.java @@ -0,0 +1,27 @@ +package net.azisaba.afnw.afnwcore2.listeners.player; + +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +public class EnderDragonDisableListener implements Listener { + @EventHandler + public void onPlayerInteract(PlayerInteractEvent e) { + if (e.getItem() == null) return; + Material inHand = e.getItem().getType(); + if ((inHand == Material.ENDER_DRAGON_SPAWN_EGG/* || inHand == Material.WITHER_SPAWN_EGG*/) + && !e.getPlayer().getWorld().getName().equals("afnw_the_end")) { + e.setCancelled(true); + } + } + + @EventHandler + public void onEntitySpawn(EntitySpawnEvent e) { + if (e.getEntity().getType() == EntityType.ENDER_DRAGON && !e.getEntity().getWorld().getName().equals("afnw_the_end")) { + e.setCancelled(true); + } + } +} From 708884b571b40792c83558604abf9db6084772fe Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 22:13:50 +0900 Subject: [PATCH 06/44] update: disable "find treasure" ai on dolphin --- src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 8e85cfc..32454f3 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -23,6 +23,7 @@ import net.azisaba.afnw.afnwcore2.util.data.PlayerDataSave; import org.bukkit.Bukkit; import org.bukkit.World; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftDolphin; import org.bukkit.entity.Dolphin; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; @@ -106,10 +107,10 @@ public void onEnable() { Bukkit.getScheduler().runTaskTimer(this, () -> { for (World world : Bukkit.getWorlds()) { for (Dolphin entity : world.getEntitiesByClass(Dolphin.class)) { - entity.remove(); + ((CraftDolphin) entity).getHandle().bO.a(goal -> goal.getClass().getTypeName().equals("net.minecraft.world.entity.animal.EntityDolphin$a")); } } - }, 1, 1); + }, 10, 10); getLogger().info("正常に起動しました。"); } From dff4c86ab20680b461b4dafe80c1a1aa7750fa0b Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 22:26:28 +0900 Subject: [PATCH 07/44] update: remove native-util dependency they are not needed for now --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 64d7e9f..7e76a7d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,7 +35,7 @@ repositories { } dependencies { - implementation("net.blueberrymc:native-util:2.1.0") +// implementation("net.blueberrymc:native-util:2.1.0") compileOnly("io.papermc.paper:paper-api:1.20.2-R0.1-SNAPSHOT") compileOnly("org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT") compileOnly("net.azisaba.ballotbox:receiver:1.0.1") From e625ea0841e890fd8a618afa6b241072f4dcad26 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 22:33:35 +0900 Subject: [PATCH 08/44] feat: keep inventory if play time is <5 hours --- .../listeners/player/DeathListener.java | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/DeathListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/DeathListener.java index 83cf953..5314596 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/DeathListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/DeathListener.java @@ -2,6 +2,8 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.GameMode; +import org.bukkit.Statistic; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -16,22 +18,35 @@ */ public class DeathListener implements Listener { - /** - * 死んだプレイヤーに失った経験治療を通知する - * - * @param e イベント発火原因のプレイヤー - */ - @EventHandler(priority = EventPriority.HIGH) - public void onDeath(PlayerDeathEvent e) { - Player p = e.getPlayer(); + /** + * 死んだプレイヤーに失った経験治療を通知する + * + * @param e イベント発火原因のプレイヤー + */ + @EventHandler(priority = EventPriority.HIGH) + public void onDeath(PlayerDeathEvent e) { + Player p = e.getPlayer(); - // ドロップした経験値量を通知 - int dropExp = e.getDroppedExp(); - if (dropExp == 0) { - p.sendMessage(Component.text("死亡しました。経験値の消費はありません。", NamedTextColor.RED)); - return; + String inventoryMessage; + if (e.getPlayer().getGameMode() != GameMode.SURVIVAL) { + e.setKeepInventory(true); + inventoryMessage = "サバイバルモード以外のため、インベントリの中身は失いません。"; + } else { + if (e.getPlayer().getStatistic(Statistic.PLAY_ONE_MINUTE) >= 20 * 60 * 60 * 5) { // 5 hours + e.setKeepInventory(false); + inventoryMessage = "プレイ時間が5時間以上のため、インベントリの中身を失いました。"; + } else { + e.setKeepInventory(true); + inventoryMessage = "プレイ時間が5時間未満のため、インベントリの中身は失いません。"; + } + } + + // ドロップした経験値量を通知 + if (e.getDroppedExp() == 0) { + p.sendMessage(Component.text("死亡しました。経験値の消費はありません。" + inventoryMessage, NamedTextColor.RED)); + } else { + p.sendMessage( + Component.text("死亡したため、" + e.getDroppedExp() + " Expを失いました。" + inventoryMessage, NamedTextColor.RED)); + } } - p.sendMessage( - Component.text("死亡したため、" + e.getDroppedExp() + " Expを失いました。", NamedTextColor.RED)); - } } From 2cfbfee2c0f55ab5e389a1901cc6a947ec622b54 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 22:55:33 +0900 Subject: [PATCH 09/44] feat: pvp mode --- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 31 ++++++++++------- .../afnw/afnwcore2/commands/PvPCommand.java | 34 +++++++++++++++++++ .../listeners/player/PvPListener.java | 18 ++++++++++ src/main/resources/plugin.yml | 2 ++ 4 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/commands/PvPCommand.java create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/PvPListener.java diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 32454f3..5ce1836 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -1,19 +1,11 @@ package net.azisaba.afnw.afnwcore2; +import java.util.HashSet; import java.util.Objects; -import net.azisaba.afnw.afnwcore2.commands.AfnwCommand; -import net.azisaba.afnw.afnwcore2.commands.BedCommand; -import net.azisaba.afnw.afnwcore2.commands.BonusCommand; -import net.azisaba.afnw.afnwcore2.commands.ConfigReloadCommand; -import net.azisaba.afnw.afnwcore2.commands.EnderchestCommand; -import net.azisaba.afnw.afnwcore2.commands.LobbyCommand; -import net.azisaba.afnw.afnwcore2.commands.MaintenanceCommand; -import net.azisaba.afnw.afnwcore2.commands.RespawnCommand; -import net.azisaba.afnw.afnwcore2.commands.TicketCommand; -import net.azisaba.afnw.afnwcore2.commands.TrashCommand; -import net.azisaba.afnw.afnwcore2.commands.TutorialCommand; -import net.azisaba.afnw.afnwcore2.commands.VoidCommand; -import net.azisaba.afnw.afnwcore2.commands.VoteCommand; +import java.util.Set; +import java.util.UUID; + +import net.azisaba.afnw.afnwcore2.commands.*; import net.azisaba.afnw.afnwcore2.listeners.block.CropsBreakCanceller; import net.azisaba.afnw.afnwcore2.listeners.block.SaplingBreakCanceller; import net.azisaba.afnw.afnwcore2.listeners.entity.WitherSpawn; @@ -21,10 +13,13 @@ import net.azisaba.afnw.afnwcore2.listeners.player.*; import net.azisaba.afnw.afnwcore2.util.data.PlayerData; import net.azisaba.afnw.afnwcore2.util.data.PlayerDataSave; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftDolphin; import org.bukkit.entity.Dolphin; +import org.bukkit.entity.Player; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; @@ -35,6 +30,7 @@ * @see org.bukkit.plugin.java.JavaPlugin */ public class AfnwCore2 extends JavaPlugin { + public final Set pvpEnabled = new HashSet<>(); @Override public void onEnable() { @@ -72,6 +68,7 @@ public void onEnable() { pluginEvent.registerEvents(new VillagerProtectorListener(), this); pluginEvent.registerEvents(new BedListener(this), this); pluginEvent.registerEvents(new EnderDragonDisableListener(), this); + pluginEvent.registerEvents(new PvPListener(this), this); /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); /* その他 */ @@ -96,6 +93,7 @@ public void onEnable() { Objects.requireNonNull(getCommand("trash")).setExecutor(new TrashCommand(this)); Objects.requireNonNull(getCommand("maintenance")).setExecutor(new MaintenanceCommand()); Objects.requireNonNull(getCommand("bonus")).setExecutor(new BonusCommand(this, data)); + Objects.requireNonNull(getCommand("pvp")).setExecutor(new PvPCommand(this)); getLogger().info("コマンド 設定完了"); if(getConfig().getBoolean("settings.maintenance-mode-toggle", false)) { @@ -110,6 +108,13 @@ public void onEnable() { ((CraftDolphin) entity).getHandle().bO.a(goal -> goal.getClass().getTypeName().equals("net.minecraft.world.entity.animal.EntityDolphin$a")); } } + for (Player player : Bukkit.getOnlinePlayers()) { + boolean pvp = pvpEnabled.contains(player.getUniqueId()); + player.sendActionBar( + Component.text("⚔ PvP: ") + .append(Component.text(pvp ? "有効" : "無効", pvp ? NamedTextColor.RED : NamedTextColor.GREEN)) + ); + } }, 10, 10); getLogger().info("正常に起動しました。"); } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/PvPCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/PvPCommand.java new file mode 100644 index 0000000..c63f166 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/PvPCommand.java @@ -0,0 +1,34 @@ +package net.azisaba.afnw.afnwcore2.commands; + +import net.azisaba.afnw.afnwcore2.AfnwCore2; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public record PvPCommand(@NotNull AfnwCore2 plugin) implements TabExecutor { + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (!(sender instanceof Player player)) { + return true; + } + if (plugin.pvpEnabled.remove(player.getUniqueId())) { + player.sendMessage(Component.text("⚔ PvPを無効にしました。", NamedTextColor.GOLD)); + } else { + plugin.pvpEnabled.add(player.getUniqueId()); + player.sendMessage(Component.text("⚔ PvPを有効にしました。", NamedTextColor.GOLD)); + } + return true; + } + + @Override + public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/PvPListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/PvPListener.java new file mode 100644 index 0000000..35fd84b --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/PvPListener.java @@ -0,0 +1,18 @@ +package net.azisaba.afnw.afnwcore2.listeners.player; + +import net.azisaba.afnw.afnwcore2.AfnwCore2; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; + +public record PvPListener(AfnwCore2 plugin) implements Listener { + @EventHandler + public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent e) { + if (!(e.getDamager() instanceof Player killer)) return; + if (!(e.getEntity() instanceof Player player)) return; + if (!plugin.pvpEnabled.contains(killer.getUniqueId()) || !plugin.pvpEnabled.contains(player.getUniqueId())) { + e.setCancelled(true); + } + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7cc8ec8..95093f6 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -95,3 +95,5 @@ commands: aliases: - mente - debug + pvp: + description: PvPの可否を設定します。 From 14d7618f27fe22478e4d675d10ddd9e3ac709f3d Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 23:00:54 +0900 Subject: [PATCH 10/44] update: more villager protection --- .../listeners/player/VillagerProtectorListener.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java index ce87d96..2fd7a06 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java @@ -1,11 +1,14 @@ package net.azisaba.afnw.afnwcore2.listeners.player; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.GameMode; import org.bukkit.entity.Arrow; import org.bukkit.entity.Player; import org.bukkit.entity.Villager; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; public class VillagerProtectorListener implements Listener { @@ -21,4 +24,13 @@ public void onPlayerAttack(EntityDamageByEntityEvent e) { e.setCancelled(true); } } + + @EventHandler + public void onBlockBreak(BlockBreakEvent e) { + if (e.getPlayer().getGameMode() == GameMode.CREATIVE) return; + if (!e.getBlock().getLocation().getNearbyEntitiesByType(Villager.class, 1, 2).isEmpty()) { + e.setCancelled(true); + e.getPlayer().sendMessage(Component.text("このブロックは破壊できません!", NamedTextColor.RED)); + } + } } From c31fd7f62503c4914a91688683aafde2c6e59001 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 23:05:07 +0900 Subject: [PATCH 11/44] update: better villager protection --- .../afnwcore2/listeners/player/VillagerProtectorListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java index 2fd7a06..92f626d 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/VillagerProtectorListener.java @@ -28,7 +28,7 @@ public void onPlayerAttack(EntityDamageByEntityEvent e) { @EventHandler public void onBlockBreak(BlockBreakEvent e) { if (e.getPlayer().getGameMode() == GameMode.CREATIVE) return; - if (!e.getBlock().getLocation().getNearbyEntitiesByType(Villager.class, 1, 2).isEmpty()) { + if (!e.getBlock().getLocation().add(0.5, 0, 0.5).getNearbyEntitiesByType(Villager.class, 0.2, 2).isEmpty()) { e.setCancelled(true); e.getPlayer().sendMessage(Component.text("このブロックは破壊できません!", NamedTextColor.RED)); } From 014606af166e14b7890db2ab97d83241e4f78ea8 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 23:29:55 +0900 Subject: [PATCH 12/44] feat: add /mmgive --- build.gradle.kts | 5 ++ .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 1 + .../afnwcore2/commands/MMGiveCommand.java | 60 +++++++++++++++++++ src/main/resources/plugin.yml | 2 + 4 files changed, 68 insertions(+) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java diff --git a/build.gradle.kts b/build.gradle.kts index 7e76a7d..0d8585a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,6 +24,10 @@ repositories { name = "essentialsx" url = uri("https://repo.essentialsx.net/releases/") } + maven { + name = "lumine" + url = uri("https://mvn.lumine.io/repository/maven-public/") + } if (properties["azisabaNmsUsername"] != null && properties["azisabaNmsPassword"] != null) { maven { name = "azisabaNms" @@ -41,6 +45,7 @@ dependencies { compileOnly("net.azisaba.ballotbox:receiver:1.0.1") compileOnly("net.azisaba:ItemStash:1.0.0-SNAPSHOT") compileOnly("net.essentialsx:EssentialsX:2.19.7") + compileOnly("io.lumine:Mythic-Dist:5.4.0") } java.toolchain.languageVersion.set(JavaLanguageVersion.of(17)) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 5ce1836..0fc0cd5 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -94,6 +94,7 @@ public void onEnable() { Objects.requireNonNull(getCommand("maintenance")).setExecutor(new MaintenanceCommand()); Objects.requireNonNull(getCommand("bonus")).setExecutor(new BonusCommand(this, data)); Objects.requireNonNull(getCommand("pvp")).setExecutor(new PvPCommand(this)); + Objects.requireNonNull(getCommand("mmgive")).setExecutor(new MMGiveCommand(this)); getLogger().info("コマンド 設定完了"); if(getConfig().getBoolean("settings.maintenance-mode-toggle", false)) { diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java new file mode 100644 index 0000000..4b0c952 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java @@ -0,0 +1,60 @@ +package net.azisaba.afnw.afnwcore2.commands; + +import io.lumine.mythic.bukkit.MythicBukkit; +import io.lumine.mythic.core.items.MythicItem; +import net.azisaba.afnw.afnwcore2.util.item.ItemUtil; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public record MMGiveCommand(@NotNull Plugin plugin) implements TabExecutor { + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + Player player = Bukkit.getPlayerExact(args[0]); + if (player == null) { + sender.sendMessage(Component.text("Player " + args[0] + " is offline (tried to give " + args[1] + " (extra: " + String.join(", ", args) + "))", NamedTextColor.RED)); + return true; + } + String mythicType = args[1]; + int amount = args.length == 2 ? 1 : Integer.parseInt(args[2]); + for (ItemStack value : player.getInventory().addItem(MythicBukkit.inst().getItemManager().getItemStack(mythicType, amount)).values()) { + ItemUtil.addToStashIfEnabledAsync(plugin, player.getUniqueId(), value); + sender.sendMessage(Component.text("インベントリがいっぱいのため、Stashに入りました。", NamedTextColor.RED)); + sender.sendMessage( + Component.text("/pickupstashで受け取れます。", NamedTextColor.RED) + .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/pickupstash")) + .hoverEvent(HoverEvent.showText(Component.text("クリックでStashの画面を開く"))) + ); + } + return true; + } + + @NotNull + @Override + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length == 1) { + return Bukkit.getOnlinePlayers().stream().map(Player::getName).filter(s -> s.startsWith(args[0])).toList(); + } + if (args.length == 2) { + return MythicBukkit.inst() + .getItemManager() + .getItems() + .stream() + .map(MythicItem::getInternalName).filter(s -> s.startsWith(args[1])) + .toList(); + } + return Collections.emptyList(); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 95093f6..5f1f223 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -97,3 +97,5 @@ commands: - debug pvp: description: PvPの可否を設定します。 + mmgive: + permission: afnw.command.mmgive From 285d48f1ea4f645e2f4f53bfa830cc04c0b628f3 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Wed, 1 Nov 2023 23:38:27 +0900 Subject: [PATCH 13/44] fix: message target --- .../net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java index 4b0c952..914cbc5 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java @@ -31,8 +31,8 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command int amount = args.length == 2 ? 1 : Integer.parseInt(args[2]); for (ItemStack value : player.getInventory().addItem(MythicBukkit.inst().getItemManager().getItemStack(mythicType, amount)).values()) { ItemUtil.addToStashIfEnabledAsync(plugin, player.getUniqueId(), value); - sender.sendMessage(Component.text("インベントリがいっぱいのため、Stashに入りました。", NamedTextColor.RED)); - sender.sendMessage( + player.sendMessage(Component.text("インベントリがいっぱいのため、Stashに入りました。", NamedTextColor.RED)); + player.sendMessage( Component.text("/pickupstashで受け取れます。", NamedTextColor.RED) .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/pickupstash")) .hoverEvent(HoverEvent.showText(Component.text("クリックでStashの画面を開く"))) From 6238cfe2d76fa295df619d273bae97a0212b9d2d Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 2 Nov 2023 11:07:18 +0900 Subject: [PATCH 14/44] fix: require-item-stash --- src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 0fc0cd5..30ba5c5 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -38,7 +38,7 @@ public void onEnable() { // コンフィグのロード saveDefaultConfig(); - if (getConfig().getBoolean("settings.require-item-stash", false) && Bukkit.getPluginManager().isPluginEnabled("ItemStash")) { + if (getConfig().getBoolean("settings.require-item-stash", false) && !Bukkit.getPluginManager().isPluginEnabled("ItemStash")) { throw new RuntimeException("ItemStashプラグインがインストールされていません。settings > require-item-stashをfalseにするか、ItemStashをインストール、またはエラーを確認してください。"); } getLogger().info("コンフィグ ロード完了"); From 22ae70357e470da6b2928979b44c735fd0eef698 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 2 Nov 2023 11:42:03 +0900 Subject: [PATCH 15/44] feat: expressions in mmgive --- build.gradle.kts | 6 + .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 8 + .../afnwcore2/commands/MMGiveCommand.java | 31 ++- .../afnwcore2/commands/MMGiveEvalCommand.java | 46 ++++ .../net/azisaba/afnw/afnwcore2/util/Expr.java | 233 ++++++++++++++++++ src/main/resources/plugin.yml | 2 + 6 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveEvalCommand.java create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/util/Expr.java diff --git a/build.gradle.kts b/build.gradle.kts index 0d8585a..cab077e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,6 +40,8 @@ repositories { dependencies { // implementation("net.blueberrymc:native-util:2.1.0") + implementation("xyz.acrylicstyle.java-util:common:2.0.0-SNAPSHOT") + implementation("xyz.acrylicstyle.java-util:expression:2.0.0-SNAPSHOT") compileOnly("io.papermc.paper:paper-api:1.20.2-R0.1-SNAPSHOT") compileOnly("org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT") compileOnly("net.azisaba.ballotbox:receiver:1.0.1") @@ -63,4 +65,8 @@ tasks { filteringCharset = "UTF-8" } } + + shadowJar { + relocate("xyz.acrylicstyle.util", "net.azisaba.afnwcore2.lib.xyz.acrylicstyle.util") + } } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 30ba5c5..6f4db5a 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -22,6 +22,8 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; /** * AfnwCore2 のメインクラス @@ -95,6 +97,7 @@ public void onEnable() { Objects.requireNonNull(getCommand("bonus")).setExecutor(new BonusCommand(this, data)); Objects.requireNonNull(getCommand("pvp")).setExecutor(new PvPCommand(this)); Objects.requireNonNull(getCommand("mmgive")).setExecutor(new MMGiveCommand(this)); + Objects.requireNonNull(getCommand("mmgiveeval")).setExecutor(new MMGiveEvalCommand()); getLogger().info("コマンド 設定完了"); if(getConfig().getBoolean("settings.maintenance-mode-toggle", false)) { @@ -128,4 +131,9 @@ public void onDisable() { } getLogger().info("正常に終了しました。"); } + + @NotNull + public static Logger getPluginLogger() { + return getPlugin(AfnwCore2.class).getSLF4JLogger(); + } } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java index 914cbc5..4063b43 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveCommand.java @@ -2,8 +2,10 @@ import io.lumine.mythic.bukkit.MythicBukkit; import io.lumine.mythic.core.items.MythicItem; +import net.azisaba.afnw.afnwcore2.util.Expr; import net.azisaba.afnw.afnwcore2.util.item.ItemUtil; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.format.NamedTextColor; @@ -13,11 +15,14 @@ import org.bukkit.command.TabExecutor; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.function.BiFunction; public record MMGiveCommand(@NotNull Plugin plugin) implements TabExecutor { @Override @@ -29,7 +34,31 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command } String mythicType = args[1]; int amount = args.length == 2 ? 1 : Integer.parseInt(args[2]); - for (ItemStack value : player.getInventory().addItem(MythicBukkit.inst().getItemManager().getItemStack(mythicType, amount)).values()) { + ItemStack stack = MythicBukkit.inst().getItemManager().getItemStack(mythicType, amount); + if (stack.hasItemMeta()) { + BiFunction modify = new BiFunction<>() { + @NotNull + @Override + public Component apply(Component component, String description) { + if (component instanceof TextComponent text) { + String replaced = Expr.evalAndReplace(player, text.content(), description); + if (replaced != null) { + component = text.content(replaced); + } + } + return component.children(component.children().stream().map(c -> apply(c, description)).toList()); + } + }; + ItemMeta meta = Objects.requireNonNull(stack.getItemMeta()); + if (meta.hasLore()) { + meta.lore(Objects.requireNonNull(meta.lore()).stream().map(line -> modify.apply(line, mythicType + " (lore)")).toList()); + } + if (meta.hasDisplayName()) { + meta.displayName(modify.apply(meta.displayName(), mythicType + " (name)")); + } + stack.setItemMeta(meta); + } + for (ItemStack value : player.getInventory().addItem(stack).values()) { ItemUtil.addToStashIfEnabledAsync(plugin, player.getUniqueId(), value); player.sendMessage(Component.text("インベントリがいっぱいのため、Stashに入りました。", NamedTextColor.RED)); player.sendMessage( diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveEvalCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveEvalCommand.java new file mode 100644 index 0000000..bedfb27 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/MMGiveEvalCommand.java @@ -0,0 +1,46 @@ +package net.azisaba.afnw.afnwcore2.commands; + +import net.azisaba.afnw.afnwcore2.AfnwCore2; +import net.azisaba.afnw.afnwcore2.util.Expr; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class MMGiveEvalCommand implements TabExecutor { + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (!(sender instanceof Player player)) { + return true; + } + String src = String.join(" ", args); + try { + sender.sendMessage(String.valueOf(Expr.eval(player, src))); + } catch (Exception e) { + sender.sendMessage(Component.text(e.getClass().getName() + ": " + e.getMessage(), NamedTextColor.RED)); + AfnwCore2.getPluginLogger().error("Failed to evaluate script", e); + } + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (!(sender instanceof Player)) { + return Collections.emptyList(); + } + try { + return Expr.getSuggestions(sender, String.join(" ", args)).collect(Collectors.toList()); + } catch (Exception e) { + String message = e.getMessage(); + return Collections.singletonList("§c" + message.substring(0, Math.min(150, message.length()))); + } + } +} diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/Expr.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/Expr.java new file mode 100644 index 0000000..792dba6 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/Expr.java @@ -0,0 +1,233 @@ +package net.azisaba.afnw.afnwcore2.util; + +import net.azisaba.afnw.afnwcore2.AfnwCore2; +import org.bukkit.BanEntry; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import xyz.acrylicstyle.util.expression.CompileData; +import xyz.acrylicstyle.util.expression.ExpressionParser; +import xyz.acrylicstyle.util.expression.RuntimeData; +import xyz.acrylicstyle.util.expression.instruction.DummyInstTypeInfo; +import xyz.acrylicstyle.util.expression.instruction.Instruction; +import xyz.acrylicstyle.util.expression.instruction.InstructionSet; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.SecureRandom; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +@SuppressWarnings("unused") +public final class Expr { + public static final Expr INSTANCE = new Expr(); + private static final Set> DISALLOWED_RETURN_TYPES = new HashSet<>(Arrays.asList( + void.class, ConsoleCommandSender.class, Class.class, Field.class, Method.class, Constructor.class, + BanEntry.class + )); + private static final SecureRandom SECURE_RANDOM = new SecureRandom(); + private static final Pattern SCRIPT_PATTERN = Pattern.compile("\\$\\{(.+)}"); + + @Nullable + public static String evalAndReplace(Player player, String line, String description) { + AtomicBoolean modified = new AtomicBoolean(false); + Matcher matcher = SCRIPT_PATTERN.matcher(line); + StringBuilder sb = new StringBuilder(); + while (matcher.find()) { + modified.set(true); + try { + matcher.appendReplacement(sb, String.valueOf(Expr.eval(player, matcher.group(1)))); + } catch (Exception e) { + matcher.appendReplacement(sb, ""); + AfnwCore2.getPluginLogger().error("Error evaluating script (description: {})\nLine: {}", description, line, e); + } + } + matcher.appendTail(sb); + return modified.get() ? sb.toString() : null; + } + + @NotNull + public static Stream getSuggestions(Object sender, String src) { + try { + CompileData compileData = + CompileData.builder() + .allowPrivate(true) + .addVariable("player", sender.getClass()) + .addVariable("expr", Expr.class) + .build(); + return getSuggestionsPartial(Stream.of("player", "expr"), compileData, src); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static @NotNull Stream getSuggestionsFull(@NotNull Stream variables, @NotNull CompileData compileData, @NotNull String input) throws Exception { + if (!input.contains(".")) { + return variables; + } + InstructionSet instructionSet = ExpressionParser.compile(input.substring(0, input.lastIndexOf('.')), compileData); + Instruction instruction = instructionSet.lastOrNull(); + if (instruction instanceof DummyInstTypeInfo typeInfo) { + return getTokens(typeInfo.getClazz()).map(s -> input.substring(0, input.lastIndexOf('.') + 1) + s); + } + return Stream.empty(); + } + + public static @NotNull Stream getSuggestionsPartial(@NotNull Stream variables, @NotNull CompileData compileData, @NotNull String input) throws Exception { + if (!input.contains(".")) { + return variables.filter(s -> s.startsWith(input)); + } + String token = input.substring(input.lastIndexOf('.') + 1); + String[] args = input.split(" "); + String last = args[args.length - 1]; + InstructionSet instructionSet = ExpressionParser.compile(input.substring(0, input.lastIndexOf('.')), compileData); + Instruction instruction = instructionSet.lastOrNull(); + if (instruction instanceof DummyInstTypeInfo typeInfo) { + return getTokens(typeInfo.getClazz()) + .filter(s -> s.toLowerCase(Locale.ROOT).startsWith(token.toLowerCase(Locale.ROOT))) + .map(s -> last.substring(0, last.lastIndexOf('.') + 1) + s); + } + return Stream.empty(); + } + + private static Stream getTokens(@NotNull Class type) { + List tokens = new ArrayList<>(); + for (Class clazz : getSupers(type)) { + for (Field field : clazz.getDeclaredFields()) { + tokens.add(field.getName()); + } + for (Method method : clazz.getDeclaredMethods()) { + if (DISALLOWED_RETURN_TYPES.contains(method.getReturnType())) continue; + if (method.getName().length() >= 4 + && method.getName().startsWith("get") + && Character.isUpperCase(method.getName().charAt(3)) + && method.getParameterCount() == 0) { + tokens.add(method.getName().substring(3, 4).toLowerCase(Locale.ROOT) + method.getName().substring(4)); + } + if (method.getParameterCount() == 0) { + tokens.add(method.getName() + "()"); + tokens.add(method.getName()); + } else { + tokens.add(method.getName() + "("); + } + } + } + tokens.add("?as("); + return tokens.stream().distinct(); + } + + private static @NotNull Set> getSupers(@NotNull Class type) { + Set> list = new LinkedHashSet<>(); + list.add(type); + if (type.getSuperclass() != null) { + list.add(type.getSuperclass()); + list.addAll(getSupers(type.getSuperclass())); + } + list.addAll(Arrays.asList(type.getInterfaces())); + for (Class anInterface : type.getInterfaces()) { + list.addAll(getSupers(anInterface)); + } + return list; + } + + public static @Nullable Object eval(@NotNull Player player, @NotNull String src) { + try { + CompileData compileData = + CompileData.builder() + .allowPrivate(true) + .addVariable("player", player.getClass()) + .addVariable("expr", Expr.class) + .build(); + InstructionSet instructionSet = ExpressionParser.compile(src, compileData); + instructionSet.forEach(instruction -> { + if (instruction instanceof DummyInstTypeInfo) { + Class clazz = ((DummyInstTypeInfo) instruction).getClazz(); + if (DISALLOWED_RETURN_TYPES.contains(clazz)) { + throw new RuntimeException("Disallowed return type: " + clazz); + } + } + }); + return instructionSet.execute( + RuntimeData.builder() + .allowPrivate(true) + .addVariable("player", player) + .addVariable("expr", INSTANCE) + .build() + ); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public long round(double d) { + return Math.round(d); + } + + public double round1(double d) { + return round(d, 1); + } + + public double round2(double d) { + return round(d, 2); + } + + public double round3(double d) { + return round(d, 3); + } + + public double round4(double d) { + return round(d, 4); + } + + public double round5(double d) { + return round(d, 5); + } + + public double round(double d, int points) { + return Math.round(d * Math.pow(10, points)) / Math.pow(10, points); + } + + public double randomDouble(double min, double max) { + return Math.random() * (max - min) + min; + } + + public double secureRandomDouble(double min, double max) { + return SECURE_RANDOM.nextDouble() * (max - min) + min; + } + + public double randomDouble(int min, int max) { + return Math.random() * (max - min) + min; + } + + public double secureRandomDouble(int min, int max) { + return SECURE_RANDOM.nextDouble() * (max - min) + min; + } + + public long randomLong(long min, long max) { + return Math.round(randomDouble(min, max)); + } + + public long secureRandomLong(long min, long max) { + return Math.round(secureRandomDouble(min, max)); + } + + public int randomInt(int min, int max) { + return Math.toIntExact(Math.round(randomDouble(min, max))); + } + + public int secureRandomInt(int min, int max) { + return Math.toIntExact(Math.round(secureRandomDouble(min, max))); + } + + @NotNull + @Contract(pure = true) + public static String longToHex(long l) { + return Long.toString(l, 16); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 5f1f223..7439f45 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -99,3 +99,5 @@ commands: description: PvPの可否を設定します。 mmgive: permission: afnw.command.mmgive + mmgiveeval: + permission: afnw.command.mmgiveeval From cf6d4f7ac25f8fe372753743f77eb5099f4a4322 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 2 Nov 2023 12:28:20 +0900 Subject: [PATCH 16/44] fix: ItemStash check --- src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 6f4db5a..0ef48ab 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -40,7 +40,7 @@ public void onEnable() { // コンフィグのロード saveDefaultConfig(); - if (getConfig().getBoolean("settings.require-item-stash", false) && !Bukkit.getPluginManager().isPluginEnabled("ItemStash")) { + if (getConfig().getBoolean("settings.require-item-stash", false) && Bukkit.getPluginManager().getPlugin("ItemStash") == null) { throw new RuntimeException("ItemStashプラグインがインストールされていません。settings > require-item-stashをfalseにするか、ItemStashをインストール、またはエラーを確認してください。"); } getLogger().info("コンフィグ ロード完了"); From 58f5edf80a116daa047a88de85e20f21ef22775f Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 2 Nov 2023 12:29:13 +0900 Subject: [PATCH 17/44] update: play sound to everyone when using super afnw ticket --- .../afnwcore2/listeners/player/SuperAfnwTicketListener.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java index e856d95..46951dc 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java @@ -23,10 +23,10 @@ public void onPlayerInteract(PlayerInteractEvent e) { if (e.getPlayer().getGameMode() != GameMode.SURVIVAL) return; if (!"Super_Afnw_Ticket".equals(ItemUtil.getMythicType(e.getItem()))) return; e.getItem().setAmount(e.getItem().getAmount() - 1); - e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 1.5f); - Bukkit.getScheduler().runTaskLater(plugin, () -> e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 1.75f), 3); - Bukkit.getScheduler().runTaskLater(plugin, () -> e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 2.0f), 6); for (Player player : Bukkit.getOnlinePlayers()) { + player.playSound(e.getPlayer().getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 1.5f); + Bukkit.getScheduler().runTaskLater(plugin, () -> player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 1.75f), 3); + Bukkit.getScheduler().runTaskLater(plugin, () -> player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 2.0f), 6); for (ItemStack value : player.getInventory().addItem(AfnwCommand.getRandomItem(1)).values()) { ItemUtil.addToStashIfEnabledAsync(plugin, player.getUniqueId(), value); } From 0c9485e2e0ba9c24cb4ef5e2615c858b214ea98a Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 2 Nov 2023 12:42:26 +0900 Subject: [PATCH 18/44] fix: teleport to tutorial world on first join --- .../afnwcore2/listeners/player/FirstPlayerJoinListener.java | 4 +++- .../azisaba/afnw/afnwcore2/listeners/player/JoinListener.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FirstPlayerJoinListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FirstPlayerJoinListener.java index b865db1..a19a635 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FirstPlayerJoinListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FirstPlayerJoinListener.java @@ -54,7 +54,9 @@ public void onJoin(PlayerJoinEvent e) { playerData.savePlayerData(); // テレポートとプレイヤーデータ作成通知 - p.teleport(tutorial.getSpawnLocation()); + Bukkit.getScheduler().runTaskLater(plugin, () -> { + p.teleport(tutorial.getSpawnLocation()); + }, 5); p.sendMessage(Component.text("プレイヤーデータが作成されました。", NamedTextColor.YELLOW)); } } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java index 555a0fb..c6cefd4 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java @@ -72,7 +72,7 @@ public void run() { @Deprecated public void sendPlayerTitle(@NonNull Player p) { // タイトルの表示時間の設定 - final Title.Times times = Title.Times.of(Duration.ofMillis(500), Duration.ofMillis(3000), + final Title.Times times = Title.Times.times(Duration.ofMillis(500), Duration.ofMillis(3000), Duration.ofMillis(1000)); // タイトルの設定 From 4b7eb8e80f6aeae8922ab93247449676e38935e1 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 2 Nov 2023 18:15:08 +0900 Subject: [PATCH 19/44] feat: add /safeteleport --- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 1 + .../commands/SafeTeleportCommand.java | 39 +++++++++++++++++++ src/main/resources/plugin.yml | 2 + 3 files changed, 42 insertions(+) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/commands/SafeTeleportCommand.java diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 0ef48ab..fd7325c 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -98,6 +98,7 @@ public void onEnable() { Objects.requireNonNull(getCommand("pvp")).setExecutor(new PvPCommand(this)); Objects.requireNonNull(getCommand("mmgive")).setExecutor(new MMGiveCommand(this)); Objects.requireNonNull(getCommand("mmgiveeval")).setExecutor(new MMGiveEvalCommand()); + Objects.requireNonNull(getCommand("safeteleport")).setExecutor(new SafeTeleportCommand()); getLogger().info("コマンド 設定完了"); if(getConfig().getBoolean("settings.maintenance-mode-toggle", false)) { diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/SafeTeleportCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/SafeTeleportCommand.java new file mode 100644 index 0000000..3acbb03 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/SafeTeleportCommand.java @@ -0,0 +1,39 @@ +package net.azisaba.afnw.afnwcore2.commands; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +public class SafeTeleportCommand implements TabExecutor { + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + Player player = Bukkit.getPlayerExact(args[0]); + if (player == null) { + sender.sendMessage(Component.text("Player was not found", NamedTextColor.RED)); + return true; + } + Location location = new Location(player.getWorld(), Integer.parseInt(args[1]) + 0.5, Integer.parseInt(args[2]), Integer.parseInt(args[3]) + 0.5); + player.teleport(location); + location.subtract(0, 1, 0).getBlock().setType(Material.HONEYCOMB_BLOCK); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length == 1) { + return null; + } + return Collections.emptyList(); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7439f45..48b7ce6 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -101,3 +101,5 @@ commands: permission: afnw.command.mmgive mmgiveeval: permission: afnw.command.mmgiveeval + safeteleport: + permission: afnw.command.safeteleport From c8fb15647b41e06deb9924e5ca5137ef72b9ebb7 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 2 Nov 2023 19:54:00 +0900 Subject: [PATCH 20/44] feat: blessed random teleporter --- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 1 + .../commands/SafeTeleportCommand.java | 22 ++++++++- .../BlessedRandomTeleporterListener.java | 45 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BlessedRandomTeleporterListener.java diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index fd7325c..9262b8f 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -71,6 +71,7 @@ public void onEnable() { pluginEvent.registerEvents(new BedListener(this), this); pluginEvent.registerEvents(new EnderDragonDisableListener(), this); pluginEvent.registerEvents(new PvPListener(this), this); + pluginEvent.registerEvents(new BlessedRandomTeleporterListener(), this); /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); /* その他 */ diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/SafeTeleportCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/SafeTeleportCommand.java index 3acbb03..163b16c 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/SafeTeleportCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/SafeTeleportCommand.java @@ -1,5 +1,6 @@ package net.azisaba.afnw.afnwcore2.commands; +import net.azisaba.afnw.afnwcore2.util.Expr; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; @@ -14,6 +15,7 @@ import java.util.Collections; import java.util.List; +import java.util.Objects; public class SafeTeleportCommand implements TabExecutor { @Override @@ -23,7 +25,25 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command sender.sendMessage(Component.text("Player was not found", NamedTextColor.RED)); return true; } - Location location = new Location(player.getWorld(), Integer.parseInt(args[1]) + 0.5, Integer.parseInt(args[2]), Integer.parseInt(args[3]) + 0.5); + int x; + try { + x = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + x = (int) Objects.requireNonNull(Expr.eval(player, args[1])); + } + int y; + try { + y = Integer.parseInt(args[2]); + } catch (NumberFormatException e) { + y = (int) Objects.requireNonNull(Expr.eval(player, args[2])); + } + int z; + try { + z = Integer.parseInt(args[3]); + } catch (NumberFormatException e) { + z = (int) Objects.requireNonNull(Expr.eval(player, args[3])); + } + Location location = new Location(player.getWorld(), x + 0.5, y, z + 0.5); player.teleport(location); location.subtract(0, 1, 0).getBlock().setType(Material.HONEYCOMB_BLOCK); return true; diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BlessedRandomTeleporterListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BlessedRandomTeleporterListener.java new file mode 100644 index 0000000..78ff81e --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BlessedRandomTeleporterListener.java @@ -0,0 +1,45 @@ +package net.azisaba.afnw.afnwcore2.listeners.player; + +import net.azisaba.afnw.afnwcore2.util.Expr; +import net.azisaba.afnw.afnwcore2.util.item.ItemUtil; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerItemConsumeEvent; + +/** + * Blessed Random Teleporterの実際の動作 + */ +public record BlessedRandomTeleporterListener() implements Listener { + @EventHandler + public void onPlayerItemConsume(PlayerItemConsumeEvent e) { + if (!"Blessed_Random_Teleporter".equals(ItemUtil.getMythicType(e.getItem()))) return; + String worldName = e.getPlayer().getWorld().getName(); + if (!worldName.equals("afnw") && !worldName.equals("afnw_nether") && !worldName.equals("afnw_the_end")) { + e.getPlayer().sendMessage(Component.text("このワールドでは使えません!", NamedTextColor.RED)); + return; + } + Location location; + do { + location = new Location(e.getPlayer().getWorld(), Expr.INSTANCE.randomInt(-100000, 100000) + 0.5, 100, Expr.INSTANCE.randomInt(-100000, 100000) + 0.5); + } while (location.distance(e.getPlayer().getWorld().getSpawnLocation()) < 15000); + location.clone().subtract(0, 1, 0).getBlock().setType(Material.HONEYCOMB_BLOCK); + for (Entity entity : e.getPlayer().getNearbyEntities(2, 2, 2)) { + if (entity instanceof Player) { + entity.sendMessage( + Component.text(e.getPlayer().getName() + "の", NamedTextColor.YELLOW) + .append(Component.text("Blessed Random Teleporter", NamedTextColor.GREEN).decorate(TextDecoration.BOLD)) + .append(Component.text("の効果でテレポートされました!", NamedTextColor.YELLOW)) + ); + entity.teleport(location); + } + } + e.getPlayer().teleport(location); + } +} From 1af4254e957de21a659183361444752f6fb0b7e4 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 2 Nov 2023 20:01:25 +0900 Subject: [PATCH 21/44] fix: cancel event --- .../listeners/player/BlessedRandomTeleporterListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BlessedRandomTeleporterListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BlessedRandomTeleporterListener.java index 78ff81e..47ab94e 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BlessedRandomTeleporterListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/BlessedRandomTeleporterListener.java @@ -23,6 +23,7 @@ public void onPlayerItemConsume(PlayerItemConsumeEvent e) { String worldName = e.getPlayer().getWorld().getName(); if (!worldName.equals("afnw") && !worldName.equals("afnw_nether") && !worldName.equals("afnw_the_end")) { e.getPlayer().sendMessage(Component.text("このワールドでは使えません!", NamedTextColor.RED)); + e.setCancelled(true); return; } Location location; From d4e8d39583305b1ffd7564247a3cb5e15d2ac4fa Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 3 Nov 2023 16:07:37 +0900 Subject: [PATCH 22/44] fix: item duplication --- .../azisaba/afnw/afnwcore2/listeners/player/DeathListener.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/DeathListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/DeathListener.java index 5314596..2236b97 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/DeathListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/DeathListener.java @@ -30,6 +30,7 @@ public void onDeath(PlayerDeathEvent e) { String inventoryMessage; if (e.getPlayer().getGameMode() != GameMode.SURVIVAL) { e.setKeepInventory(true); + e.getDrops().clear(); inventoryMessage = "サバイバルモード以外のため、インベントリの中身は失いません。"; } else { if (e.getPlayer().getStatistic(Statistic.PLAY_ONE_MINUTE) >= 20 * 60 * 60 * 5) { // 5 hours @@ -37,6 +38,7 @@ public void onDeath(PlayerDeathEvent e) { inventoryMessage = "プレイ時間が5時間以上のため、インベントリの中身を失いました。"; } else { e.setKeepInventory(true); + e.getDrops().clear(); inventoryMessage = "プレイ時間が5時間未満のため、インベントリの中身は失いません。"; } } From 0bba00f81092387b86849081776183e504be0aa4 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Sat, 4 Nov 2023 09:30:45 +0900 Subject: [PATCH 23/44] feat: broadcast votes --- .../afnw/afnwcore2/listeners/other/VoteListener.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java index a5f4095..27fbf5d 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java @@ -28,6 +28,12 @@ public void onVote(VotifierEvent e) { ItemStack ticketItem = AfnwTicket.afnwTicket.clone(); ticketItem.setAmount(ticketSize); + Bukkit.broadcast( + Component.text("[", NamedTextColor.GOLD) + .append(Component.text("Broadcast", NamedTextColor.DARK_RED)) + .append(Component.text("] ", NamedTextColor.GOLD)) + .append(Component.text(e.getVote().getUsername(), NamedTextColor.RED)) + .append(Component.text("が" + e.getVote().getServiceName() + "で投票しました!", NamedTextColor.DARK_GREEN))); if (sendTarget != null) { Inventory inv = sendTarget.getInventory(); From a8fc1da268476aa7a4a23808aee0e8d9247e6076 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Sat, 4 Nov 2023 12:01:10 +0900 Subject: [PATCH 24/44] fix: damages to non-pvp-enabled players --- .../afnwcore2/listeners/player/PvPListener.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/PvPListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/PvPListener.java index 35fd84b..4754053 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/PvPListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/PvPListener.java @@ -2,6 +2,7 @@ import net.azisaba.afnw.afnwcore2.AfnwCore2; import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; @@ -9,10 +10,16 @@ public record PvPListener(AfnwCore2 plugin) implements Listener { @EventHandler public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent e) { - if (!(e.getDamager() instanceof Player killer)) return; if (!(e.getEntity() instanceof Player player)) return; - if (!plugin.pvpEnabled.contains(killer.getUniqueId()) || !plugin.pvpEnabled.contains(player.getUniqueId())) { - e.setCancelled(true); + if (e.getDamager() instanceof Player killer) { + if (!plugin.pvpEnabled.contains(killer.getUniqueId()) || !plugin.pvpEnabled.contains(player.getUniqueId())) { + e.setCancelled(true); + } + } + if (e.getDamager() instanceof Projectile projectile && projectile.getShooter() instanceof Player shooter) { + if (shooter != e.getEntity() && !plugin.pvpEnabled.contains(shooter.getUniqueId()) || !plugin.pvpEnabled.contains(player.getUniqueId())) { + e.setCancelled(true); + } } } } From b69ec0874ece916555c51678dbf7a52697e42ee7 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 26 Jul 2024 18:35:25 +0900 Subject: [PATCH 25/44] update gradle --- README.md | 8 +++++--- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 19088fa..d9ff50c 100644 --- a/README.md +++ b/README.md @@ -11,18 +11,20 @@ - [Intellij IDEA Ultimate](https://www.jetbrains.com/idea/) - [Java SE Development Kit 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) - Java 17 -- Gradle 7.3 -- Paper 1.17.1 (gh 411) +- Gradle 8.9 +- Paper 1.20.2 ## 前提プラグイン AfnwCore2を導入したPaperを起動するには以下のプラグインが `plugins/` に導入されている必要があります。 - [EssentialsX](https://essentialsx.net/downloads.html) +- Votifier +- [ItemStash](https://github.com/AzisabaNetwork/ItemStash) ## 使用API -- [paper-api:1.17.1-R0.1-SNAPSHOT](https://papermc.io/repo/repository/maven-public/) +- [paper-api:1.20.2-R0.1-SNAPSHOT](https://papermc.io/repo/repository/maven-public/) - [JavaDoc](https://papermc.io/repo/repository/maven-public/) - [EssentialsX API](https://repo.essentialsx.net/releases/) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e411586..19cfad9 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-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From cb4830530793ee8a3ba5c16413cc9985774a6375 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 26 Jul 2024 18:40:45 +0900 Subject: [PATCH 26/44] update EssentialsX --- build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index cab077e..0e7d971 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,6 +7,7 @@ group = "net.azisaba.afnw" version = "1.5.0-SNAPSHOT" repositories { + mavenLocal() mavenCentral() maven { name = "papermc-repo" @@ -46,7 +47,7 @@ dependencies { compileOnly("org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT") compileOnly("net.azisaba.ballotbox:receiver:1.0.1") compileOnly("net.azisaba:ItemStash:1.0.0-SNAPSHOT") - compileOnly("net.essentialsx:EssentialsX:2.19.7") + compileOnly("net.essentialsx:EssentialsX:2.20.1") compileOnly("io.lumine:Mythic-Dist:5.4.0") } From 2212aa282ebeed12ceb61d121b42ef70b93da7ae Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 26 Jul 2024 19:44:38 +0900 Subject: [PATCH 27/44] feat: TAB integration --- build.gradle.kts | 2 +- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 17 ++++---- .../azisaba/afnw/afnwcore2/util/TheTAB.java | 41 +++++++++++++++++++ src/main/resources/plugin.yml | 1 + 4 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java diff --git a/build.gradle.kts b/build.gradle.kts index 0e7d971..bcc98fa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,6 +29,7 @@ repositories { name = "lumine" url = uri("https://mvn.lumine.io/repository/maven-public/") } + maven { url = uri("https://jitpack.io") } if (properties["azisabaNmsUsername"] != null && properties["azisabaNmsPassword"] != null) { maven { name = "azisabaNms" @@ -36,7 +37,6 @@ repositories { url = uri("https://repo.azisaba.net/repository/nms/") } } - mavenLocal() } dependencies { diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 9262b8f..8fff0a0 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -11,6 +11,7 @@ import net.azisaba.afnw.afnwcore2.listeners.entity.WitherSpawn; import net.azisaba.afnw.afnwcore2.listeners.other.VoteListener; import net.azisaba.afnw.afnwcore2.listeners.player.*; +import net.azisaba.afnw.afnwcore2.util.TheTAB; import net.azisaba.afnw.afnwcore2.util.data.PlayerData; import net.azisaba.afnw.afnwcore2.util.data.PlayerDataSave; import net.kyori.adventure.text.Component; @@ -102,6 +103,15 @@ public void onEnable() { Objects.requireNonNull(getCommand("safeteleport")).setExecutor(new SafeTeleportCommand()); getLogger().info("コマンド 設定完了"); + Bukkit.getScheduler().runTask(this, () -> { + if (Bukkit.getPluginManager().isPluginEnabled("TAB")) { + TheTAB.enable(); + getLogger().info("TABの連携が有効になりました。"); + } else { + getLogger().info("TABの連携は無効です。"); + } + }); + if(getConfig().getBoolean("settings.maintenance-mode-toggle", false)) { getServer().setWhitelist(true); getLogger().info("正常に起動しました。(メンテナンスモード)"); @@ -114,13 +124,6 @@ public void onEnable() { ((CraftDolphin) entity).getHandle().bO.a(goal -> goal.getClass().getTypeName().equals("net.minecraft.world.entity.animal.EntityDolphin$a")); } } - for (Player player : Bukkit.getOnlinePlayers()) { - boolean pvp = pvpEnabled.contains(player.getUniqueId()); - player.sendActionBar( - Component.text("⚔ PvP: ") - .append(Component.text(pvp ? "有効" : "無効", pvp ? NamedTextColor.RED : NamedTextColor.GREEN)) - ); - } }, 10, 10); getLogger().info("正常に起動しました。"); } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java new file mode 100644 index 0000000..9654ddd --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java @@ -0,0 +1,41 @@ +package net.azisaba.afnw.afnwcore2.util; + +import net.azisaba.afnw.afnwcore2.AfnwCore2; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; +import java.util.function.Function; + +public class TheTAB { + private static boolean enabled = false; + + public static void enable() { + try { + registerPlaceholder("%pvp_enabled%", 1000, player -> AfnwCore2.getPlugin(AfnwCore2.class).pvpEnabled.contains(player.getUniqueId())); + Class.forName("me.neznamy.tab.shared.placeholders.conditions.Condition").getMethod("finishSetups").invoke(null); + if (enabled) return; + Object tabAPI = Class.forName("me.neznamy.tab.api.TabAPI").getMethod("getInstance").invoke(null); + Class.forName("me.neznamy.tab.api.event.EventBus") + .getMethod("register", Class.class, Consumer.class) + .invoke(tabAPI, Class.forName("me.neznamy.tab.api.event.plugin.TabLoadEvent"), (Consumer) (e) -> enable()); + enabled = true; + } catch (ReflectiveOperationException e) { + AfnwCore2.getPluginLogger().warn("Failed to execute Condition#finishSetups", e); + } + } + + private static void registerPlaceholder(String identifier, int refreshInterval, @NotNull Function function) throws ReflectiveOperationException { + Object tabAPI = Class.forName("me.neznamy.tab.api.TabAPI").getMethod("getInstance").invoke(null); + Object placeholderManager = Class.forName("me.neznamy.tab.api.TabAPI").getMethod("getPlaceholderManager").invoke(tabAPI); + Class.forName("me.neznamy.tab.api.placeholder.PlaceholderManager") + .getMethod("registerPlayerPlaceholder", String.class, int.class, Function.class) + .invoke(placeholderManager, identifier, refreshInterval, (Function) (obj) -> { + try { + return function.apply((Player) Class.forName("me.neznamy.tab.api.TabPlayer").getMethod("getPlayer").invoke(obj)); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + }); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 48b7ce6..e203edf 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -9,6 +9,7 @@ description: That world, once again. depend: [ Essentials, Votifier ] softdepend: - ItemStash + - TAB website: https://github.com/AfnwTeam/AfnwCore2 permissions: From 3598922df4128ca82369a53abb15a81506235db6 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 26 Jul 2024 20:26:27 +0900 Subject: [PATCH 28/44] feat: give super afnw ticket upon first join --- .../afnw/afnwcore2/listeners/player/JoinListener.java | 7 +++++++ src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java | 1 + 2 files changed, 8 insertions(+) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java index c6cefd4..f739d83 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java @@ -36,6 +36,13 @@ public record JoinListener(JavaPlugin plugin, PlayerData playerData) implements public void onJoin(PlayerJoinEvent e) { Player p = e.getPlayer(); + // 初参加の場合はSuper Afnw Ticketを渡す + if (!playerData.getPlayerData().getBoolean("players." + p.getUniqueId() + ".first-join", false)) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mmgive " + p.getName() + " Super_Afnw_Ticket"); + playerData.getPlayerData().set("players." + p.getUniqueId() + ".first-join", true); + Bukkit.getScheduler().runTaskAsynchronously(plugin, playerData::savePlayerData); + } + // プレイヤーがサーバーに参加したらタイトルとログインメッセージを送信する sendPlayerTitle(p); e.joinMessage(Component.text("* " + p.getName() + "がログインしました").color(NamedTextColor.AQUA)); diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java index 9654ddd..5d7221f 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java @@ -18,6 +18,7 @@ public static void enable() { Object tabAPI = Class.forName("me.neznamy.tab.api.TabAPI").getMethod("getInstance").invoke(null); Class.forName("me.neznamy.tab.api.event.EventBus") .getMethod("register", Class.class, Consumer.class) + // TODO: me.neznamy.tab.api.event.EventHandler .invoke(tabAPI, Class.forName("me.neznamy.tab.api.event.plugin.TabLoadEvent"), (Consumer) (e) -> enable()); enabled = true; } catch (ReflectiveOperationException e) { From d4f1c38ea69a27f4139b7bd6d78ca06bcc14e429 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 26 Jul 2024 20:55:46 +0900 Subject: [PATCH 29/44] suppress player data save messages --- .../net/azisaba/afnw/afnwcore2/util/data/PlayerDataSave.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/data/PlayerDataSave.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/data/PlayerDataSave.java index 15b4569..ea480e7 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/util/data/PlayerDataSave.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/data/PlayerDataSave.java @@ -24,10 +24,8 @@ public PlayerData playerData() { new BukkitRunnable() { @Override public void run() { - Bukkit.getServer().broadcast(Component.text("プレイヤーデータ: セーブ中....", NamedTextColor.YELLOW)); playerData.savePlayerData(); playerData.reloadPlayerData(); - Bukkit.getServer().broadcast(Component.text("プレイヤーデータ: セーブ完了", NamedTextColor.YELLOW)); } }.runTaskTimer(plugin, 0, 20L * setPeriod); return playerData; From 21badf0c14f6a86abe198253b0c3c3b137b68471 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 1 Aug 2024 08:52:58 +0900 Subject: [PATCH 30/44] use paperweight instead of spigot --- README.md | 2 +- build.gradle.kts | 8 ++++---- src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java | 3 ++- .../net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d9ff50c..96af4c1 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ AfnwCore2を導入したPaperを起動するには以下のプラグインが `p ```sh git clone https://github.com/AfnwTeam/AfnwCore2.git -gradle build +gradlew reobfJar ``` なお、Intellij IDEAを使用している場合はすべてGUI上で使用可能です。 diff --git a/build.gradle.kts b/build.gradle.kts index bcc98fa..46ccdab 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,13 +1,13 @@ plugins { + id("io.papermc.paperweight.userdev") version "1.7.1" java id("com.github.johnrengelman.shadow") version "8.1.1" } group = "net.azisaba.afnw" -version = "1.5.0-SNAPSHOT" +version = "2.0.0-SNAPSHOT" repositories { - mavenLocal() mavenCentral() maven { name = "papermc-repo" @@ -43,12 +43,12 @@ dependencies { // implementation("net.blueberrymc:native-util:2.1.0") implementation("xyz.acrylicstyle.java-util:common:2.0.0-SNAPSHOT") implementation("xyz.acrylicstyle.java-util:expression:2.0.0-SNAPSHOT") - compileOnly("io.papermc.paper:paper-api:1.20.2-R0.1-SNAPSHOT") - compileOnly("org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT") compileOnly("net.azisaba.ballotbox:receiver:1.0.1") compileOnly("net.azisaba:ItemStash:1.0.0-SNAPSHOT") compileOnly("net.essentialsx:EssentialsX:2.20.1") compileOnly("io.lumine:Mythic-Dist:5.4.0") + compileOnly("io.papermc.paper:paper-api:1.20.2-R0.1-SNAPSHOT") + paperweight.paperDevBundle("1.20.2-R0.1-SNAPSHOT") } java.toolchain.languageVersion.set(JavaLanguageVersion.of(17)) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 8fff0a0..d68cd89 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -121,7 +121,8 @@ public void onEnable() { Bukkit.getScheduler().runTaskTimer(this, () -> { for (World world : Bukkit.getWorlds()) { for (Dolphin entity : world.getEntitiesByClass(Dolphin.class)) { - ((CraftDolphin) entity).getHandle().bO.a(goal -> goal.getClass().getTypeName().equals("net.minecraft.world.entity.animal.EntityDolphin$a")); + // Prevent DolphinSwimToTreasureGoal from being triggered + ((CraftDolphin) entity).getHandle().goalSelector.removeAllGoals(goal -> goal.getClass().getTypeName().equals("net.minecraft.world.entity.animal.EntityDolphin$a")); } } }, 10, 10); diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java index 05fd7c2..b8ee3b7 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java @@ -23,7 +23,7 @@ public static void addToStashIfEnabledAsync(@NotNull Plugin plugin, @NotNull UUI } public static @NotNull String getStringTag(@NotNull ItemStack stack, @NotNull String name) { - return CraftItemStack.asNMSCopy(stack).w().l(name); + return CraftItemStack.asNMSCopy(stack).getOrCreateTag().getString(name); } @Contract("null -> null") From 4d1c94d94bf9a511e684d5708a1bd2f0376ef9fd Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 1 Aug 2024 09:25:45 +0900 Subject: [PATCH 31/44] add DropShardListener --- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 5 ++-- .../listeners/entity/DropShardListener.java | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/listeners/entity/DropShardListener.java diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index d68cd89..42bef02 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -8,19 +8,17 @@ import net.azisaba.afnw.afnwcore2.commands.*; import net.azisaba.afnw.afnwcore2.listeners.block.CropsBreakCanceller; import net.azisaba.afnw.afnwcore2.listeners.block.SaplingBreakCanceller; +import net.azisaba.afnw.afnwcore2.listeners.entity.DropShardListener; import net.azisaba.afnw.afnwcore2.listeners.entity.WitherSpawn; import net.azisaba.afnw.afnwcore2.listeners.other.VoteListener; import net.azisaba.afnw.afnwcore2.listeners.player.*; import net.azisaba.afnw.afnwcore2.util.TheTAB; import net.azisaba.afnw.afnwcore2.util.data.PlayerData; import net.azisaba.afnw.afnwcore2.util.data.PlayerDataSave; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftDolphin; import org.bukkit.entity.Dolphin; -import org.bukkit.entity.Player; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -75,6 +73,7 @@ public void onEnable() { pluginEvent.registerEvents(new BlessedRandomTeleporterListener(), this); /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); + pluginEvent.registerEvents(new DropShardListener(), this); /* その他 */ pluginEvent.registerEvents(new VoteListener(this, data), this); getLogger().info("Listener 設定完了"); diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/entity/DropShardListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/entity/DropShardListener.java new file mode 100644 index 0000000..adb4a2f --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/entity/DropShardListener.java @@ -0,0 +1,29 @@ +package net.azisaba.afnw.afnwcore2.listeners.entity; + +import io.lumine.mythic.bukkit.MythicBukkit; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDeathEvent; + +import java.util.Optional; + +public class DropShardListener implements Listener { + @EventHandler + public void onEntityDeath(EntityDeathEvent e) { + if (e.getEntity().getKiller() == null) { + return; + } + Player killer = e.getEntity().getKiller(); + double baseChance = 0.001; // 0.1% + double playerLuck = Optional.ofNullable(killer.getAttribute(Attribute.GENERIC_LUCK)).map(AttributeInstance::getValue).orElse(0.0); + double chance = baseChance + playerLuck * 0.0001; // 0.01% per luck level + // calculate chance + if (Math.random() < chance) { + // drop shard + killer.getInventory().addItem(MythicBukkit.inst().getItemManager().getItemStack("Rare_Lootbox_Shard")); + } + } +} From 26f043f9194c4b38219b440306ca1ce7d2f308a7 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 1 Aug 2024 13:40:46 +0900 Subject: [PATCH 32/44] set max luck value to Double.MAX_VALUE --- src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 42bef02..d29eee9 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -15,6 +15,8 @@ import net.azisaba.afnw.afnwcore2.util.TheTAB; import net.azisaba.afnw.afnwcore2.util.data.PlayerData; import net.azisaba.afnw.afnwcore2.util.data.PlayerDataSave; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.attributes.RangedAttribute; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftDolphin; @@ -125,6 +127,8 @@ public void onEnable() { } } }, 10, 10); + + ((RangedAttribute) Attributes.LUCK).maxValue = Double.MAX_VALUE; getLogger().info("正常に起動しました。"); } From 8ffb6d6123fa92557680449031e7241052212e0b Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 2 Aug 2024 13:11:11 +0900 Subject: [PATCH 33/44] buff (super) afnw ticket and nerf join bonus --- .../afnw/afnwcore2/commands/AfnwCommand.java | 36 ++++++++++++++++++- .../listeners/player/JoinListener.java | 1 - .../player/SuperAfnwTicketListener.java | 2 +- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java index 7a7a919..227daa4 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java @@ -5,12 +5,16 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Optional; + import net.azisaba.afnw.afnwcore2.util.data.PlayerData; import net.azisaba.afnw.afnwcore2.util.item.AfnwScaffold; import net.azisaba.afnw.afnwcore2.util.item.AfnwTicket; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Material; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -44,10 +48,39 @@ private static boolean isAllowed(Material type) { @Contract("_ -> new") public static @NotNull ItemStack getRandomItem(int amount) { + return getRandomItem(0, amount); + } + + @Contract("_, _ -> new") + public static @NotNull ItemStack getRandomItem(int luck, int amount) { try { SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); List itemList = new ArrayList<>(Arrays.asList(Material.values())); itemList.removeIf(type -> !isAllowed(type)); + if (luck > 0) { + for (int i = 0; i < luck; i++) { + itemList.add(Material.DRIPSTONE_BLOCK); + itemList.add(Material.POINTED_DRIPSTONE); + itemList.add(Material.LAVA_BUCKET); + itemList.add(Material.DIRT); + itemList.add(Material.NETHERITE_BLOCK); + itemList.add(Material.DIAMOND_BLOCK); + itemList.add(Material.GOLD_BLOCK); + itemList.add(Material.ELYTRA); + itemList.add(Material.END_PORTAL_FRAME); + itemList.add(Material.ENDER_PEARL); + itemList.add(Material.ENDER_EYE); + itemList.add(Material.TRIDENT); + itemList.add(Material.ENCHANTED_GOLDEN_APPLE); + itemList.add(Material.NETHER_STAR); + itemList.add(Material.ANCIENT_DEBRIS); + itemList.add(Material.BLAZE_POWDER); + itemList.add(Material.SPAWNER); + itemList.add(Material.NETHERITE_INGOT); + itemList.add(Material.DIAMOND); + itemList.add(Material.GOLD_INGOT); + } + } return new ItemStack(itemList.get(random.nextInt(itemList.size() - 1)), amount); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); @@ -95,7 +128,8 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command int itemSize = config.getInt("vote.item-size", 1); int scaffoldSize = config.getInt("vote.scaffold-size", 8); - ItemStack afnwItem = getRandomItem(itemSize); + int luck = (int) Math.ceil(Optional.ofNullable(((Player) sender).getAttribute(Attribute.GENERIC_LUCK)).map(AttributeInstance::getValue).orElse(0.0)); + ItemStack afnwItem = getRandomItem(luck, itemSize); inv.removeItem(AfnwTicket.afnwTicket); inv.addItem(afnwItem); diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java index f739d83..6051602 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java @@ -38,7 +38,6 @@ public void onJoin(PlayerJoinEvent e) { // 初参加の場合はSuper Afnw Ticketを渡す if (!playerData.getPlayerData().getBoolean("players." + p.getUniqueId() + ".first-join", false)) { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mmgive " + p.getName() + " Super_Afnw_Ticket"); playerData.getPlayerData().set("players." + p.getUniqueId() + ".first-join", true); Bukkit.getScheduler().runTaskAsynchronously(plugin, playerData::savePlayerData); } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java index 46951dc..ac82016 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/SuperAfnwTicketListener.java @@ -27,7 +27,7 @@ public void onPlayerInteract(PlayerInteractEvent e) { player.playSound(e.getPlayer().getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 1.5f); Bukkit.getScheduler().runTaskLater(plugin, () -> player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 1.75f), 3); Bukkit.getScheduler().runTaskLater(plugin, () -> player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1000f, 2.0f), 6); - for (ItemStack value : player.getInventory().addItem(AfnwCommand.getRandomItem(1)).values()) { + for (ItemStack value : player.getInventory().addItem(AfnwCommand.getRandomItem(50, 1)).values()) { ItemUtil.addToStashIfEnabledAsync(plugin, player.getUniqueId(), value); } player.sendMessage("§d" + e.getPlayer().getName() + "§eが§aSuper Afnw Ticket§eを使用し、アイテムが配布されました!"); From c1c5d409558595f5c1de19bcdf34ba792677555f Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 2 Aug 2024 13:49:53 +0900 Subject: [PATCH 34/44] add netherite upgrade smithing template --- .../java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java index 227daa4..fcd13f9 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java @@ -79,6 +79,7 @@ private static boolean isAllowed(Material type) { itemList.add(Material.NETHERITE_INGOT); itemList.add(Material.DIAMOND); itemList.add(Material.GOLD_INGOT); + itemList.add(Material.NETHERITE_UPGRADE_SMITHING_TEMPLATE); } } return new ItemStack(itemList.get(random.nextInt(itemList.size() - 1)), amount); From 5522a5241b14abb15b4a0a5b5007158f7f2e7d49 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 2 Aug 2024 13:50:09 +0900 Subject: [PATCH 35/44] fishing gives shard --- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 1 + .../listeners/player/FishingListener.java | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index d29eee9..f239ffd 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -73,6 +73,7 @@ public void onEnable() { pluginEvent.registerEvents(new EnderDragonDisableListener(), this); pluginEvent.registerEvents(new PvPListener(this), this); pluginEvent.registerEvents(new BlessedRandomTeleporterListener(), this); + pluginEvent.registerEvents(new FishingListener(), this); /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); pluginEvent.registerEvents(new DropShardListener(), this); diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java new file mode 100644 index 0000000..bc46976 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java @@ -0,0 +1,24 @@ +package net.azisaba.afnw.afnwcore2.listeners.player; + +import io.lumine.mythic.bukkit.MythicBukkit; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerFishEvent; + +import java.util.Optional; + +public class FishingListener implements Listener { + @EventHandler + public void on(PlayerFishEvent e) { + double baseChance = 0.01; // 1% + double playerLuck = Optional.ofNullable(e.getPlayer().getAttribute(Attribute.GENERIC_LUCK)).map(AttributeInstance::getValue).orElse(0.0); + double chance = baseChance + playerLuck * 0.001; // 0.1% per luck level + // calculate chance + if (Math.random() < chance) { + // drop shard + e.getPlayer().getInventory().addItem(MythicBukkit.inst().getItemManager().getItemStack("Rare_Lootbox_Shard")); + } + } +} From 26bd637d05a50a61048ac5830af7ede0ca1c8207 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 2 Aug 2024 14:48:07 +0900 Subject: [PATCH 36/44] fix fish listener --- .../listeners/player/FishingListener.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java index bc46976..a9b919e 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java @@ -12,13 +12,15 @@ public class FishingListener implements Listener { @EventHandler public void on(PlayerFishEvent e) { - double baseChance = 0.01; // 1% - double playerLuck = Optional.ofNullable(e.getPlayer().getAttribute(Attribute.GENERIC_LUCK)).map(AttributeInstance::getValue).orElse(0.0); - double chance = baseChance + playerLuck * 0.001; // 0.1% per luck level - // calculate chance - if (Math.random() < chance) { - // drop shard - e.getPlayer().getInventory().addItem(MythicBukkit.inst().getItemManager().getItemStack("Rare_Lootbox_Shard")); + if (e.getCaught() != null) { + double baseChance = 0.01; // 1% + double playerLuck = Optional.ofNullable(e.getPlayer().getAttribute(Attribute.GENERIC_LUCK)).map(AttributeInstance::getValue).orElse(0.0); + double chance = baseChance + playerLuck * 0.001; // 0.1% per luck level + // calculate chance + if (Math.random() < chance) { + // drop shard + e.getPlayer().getInventory().addItem(MythicBukkit.inst().getItemManager().getItemStack("Rare_Lootbox_Shard")); + } } } } From a7d6b18c2cb23a8f3b40f2a6dc02e04be3bd6664 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Sun, 4 Aug 2024 13:18:07 +0900 Subject: [PATCH 37/44] add reinforced deepslate --- .../java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java index fcd13f9..73ca4ac 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java @@ -80,6 +80,7 @@ private static boolean isAllowed(Material type) { itemList.add(Material.DIAMOND); itemList.add(Material.GOLD_INGOT); itemList.add(Material.NETHERITE_UPGRADE_SMITHING_TEMPLATE); + itemList.add(Material.REINFORCED_DEEPSLATE); } } return new ItemStack(itemList.get(random.nextInt(itemList.size() - 1)), amount); From a63eb41fba1d9baaeae0dadb7d8750b49bc57340 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Mon, 5 Aug 2024 10:31:30 +0900 Subject: [PATCH 38/44] fix vote bonus --- .../azisaba/afnw/afnwcore2/listeners/other/VoteListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java index 27fbf5d..52c24cb 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java @@ -78,7 +78,7 @@ public void onVote(VotifierEvent e) { voteCount++; if (voteCount >= bonusLine) { for (int i = 0; i < 10; i++) { - ItemUtil.addToStashIfEnabled(player.getUniqueId(), ticketItem); + ItemUtil.addToStashIfEnabled(player.getUniqueId(), AfnwTicket.afnwTicket); } ItemUtil.addToStashIfEnabled(player.getUniqueId(), new ItemStack(Material.NETHER_STAR)); plugin.getSLF4JLogger().info(player.getName() + " (" + player.getUniqueId() + ")が投票ボーナスを獲得しました。"); From 4d03628d7d350501b143a31a0f4b6d1726a2be53 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Mon, 5 Aug 2024 16:32:46 +0900 Subject: [PATCH 39/44] add spawn egg --- .../java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java index 73ca4ac..d03d897 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java @@ -81,6 +81,7 @@ private static boolean isAllowed(Material type) { itemList.add(Material.GOLD_INGOT); itemList.add(Material.NETHERITE_UPGRADE_SMITHING_TEMPLATE); itemList.add(Material.REINFORCED_DEEPSLATE); + Arrays.stream(Material.values()).filter(m -> m.name().endsWith("_SPAWN_EGG")).forEach(itemList::add); } } return new ItemStack(itemList.get(random.nextInt(itemList.size() - 1)), amount); From 49b1a698a08ec3e7e4da0cbd592f1868c58f87d0 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 22 Nov 2024 00:03:07 +0900 Subject: [PATCH 40/44] Update to 1.21.1 --- build.gradle.kts | 10 +++-- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 4 +- .../azisaba/afnw/afnwcore2/util/TheTAB.java | 40 +++++-------------- .../afnw/afnwcore2/util/item/ItemUtil.java | 23 +++++++++-- src/main/resources/plugin.yml | 2 +- 5 files changed, 40 insertions(+), 39 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 46ccdab..0ad98b2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("io.papermc.paperweight.userdev") version "1.7.1" java - id("com.github.johnrengelman.shadow") version "8.1.1" + id("com.gradleup.shadow") version "8.3.3" } group = "net.azisaba.afnw" @@ -47,11 +47,13 @@ dependencies { compileOnly("net.azisaba:ItemStash:1.0.0-SNAPSHOT") compileOnly("net.essentialsx:EssentialsX:2.20.1") compileOnly("io.lumine:Mythic-Dist:5.4.0") - compileOnly("io.papermc.paper:paper-api:1.20.2-R0.1-SNAPSHOT") - paperweight.paperDevBundle("1.20.2-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT") + compileOnly("net.azisaba:TAB-BukkitBridge:3.1.0") + compileOnly("org.jetbrains:annotations:26.0.1") + paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") } -java.toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +java.toolchain.languageVersion.set(JavaLanguageVersion.of(21)) tasks { compileJava { diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index f239ffd..419f061 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -19,7 +19,7 @@ import net.minecraft.world.entity.ai.attributes.RangedAttribute; import org.bukkit.Bukkit; import org.bukkit.World; -import org.bukkit.craftbukkit.v1_20_R2.entity.CraftDolphin; +import org.bukkit.craftbukkit.entity.CraftDolphin; import org.bukkit.entity.Dolphin; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; @@ -108,7 +108,7 @@ public void onEnable() { Bukkit.getScheduler().runTask(this, () -> { if (Bukkit.getPluginManager().isPluginEnabled("TAB")) { TheTAB.enable(); - getLogger().info("TABの連携が有効になりました。"); + getLogger().info("TABの連携が有効です。"); } else { getLogger().info("TABの連携は無効です。"); } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java index 5d7221f..744d545 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/TheTAB.java @@ -1,42 +1,24 @@ package net.azisaba.afnw.afnwcore2.util; import net.azisaba.afnw.afnwcore2.AfnwCore2; +import net.azisaba.tabbukkitbridge.data.DataKey; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Consumer; -import java.util.function.Function; public class TheTAB { private static boolean enabled = false; public static void enable() { + if (enabled) return; + enabled = true; try { - registerPlaceholder("%pvp_enabled%", 1000, player -> AfnwCore2.getPlugin(AfnwCore2.class).pvpEnabled.contains(player.getUniqueId())); - Class.forName("me.neznamy.tab.shared.placeholders.conditions.Condition").getMethod("finishSetups").invoke(null); - if (enabled) return; - Object tabAPI = Class.forName("me.neznamy.tab.api.TabAPI").getMethod("getInstance").invoke(null); - Class.forName("me.neznamy.tab.api.event.EventBus") - .getMethod("register", Class.class, Consumer.class) - // TODO: me.neznamy.tab.api.event.EventHandler - .invoke(tabAPI, Class.forName("me.neznamy.tab.api.event.plugin.TabLoadEvent"), (Consumer) (e) -> enable()); - enabled = true; - } catch (ReflectiveOperationException e) { - AfnwCore2.getPluginLogger().warn("Failed to execute Condition#finishSetups", e); + DataKey pvpEnabled = new DataKey<>(false); + pvpEnabled.register(p -> true, player -> { + if (player == null) return false; + return AfnwCore2.getPlugin(AfnwCore2.class).pvpEnabled.contains(player.getUniqueId()); + }); + pvpEnabled.getPlaceholders().add("pvp_enabled"); + } catch (Exception | NoClassDefFoundError e) { + e.printStackTrace(); } } - - private static void registerPlaceholder(String identifier, int refreshInterval, @NotNull Function function) throws ReflectiveOperationException { - Object tabAPI = Class.forName("me.neznamy.tab.api.TabAPI").getMethod("getInstance").invoke(null); - Object placeholderManager = Class.forName("me.neznamy.tab.api.TabAPI").getMethod("getPlaceholderManager").invoke(tabAPI); - Class.forName("me.neznamy.tab.api.placeholder.PlaceholderManager") - .getMethod("registerPlayerPlaceholder", String.class, int.class, Function.class) - .invoke(placeholderManager, identifier, refreshInterval, (Function) (obj) -> { - try { - return function.apply((Player) Class.forName("me.neznamy.tab.api.TabPlayer").getMethod("getPlayer").invoke(obj)); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - }); - } } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java index b8ee3b7..058689f 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java @@ -1,8 +1,11 @@ package net.azisaba.afnw.afnwcore2.util.item; import net.azisaba.itemstash.ItemStash; +import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.component.CustomData; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.Contract; @@ -22,14 +25,28 @@ public static void addToStashIfEnabledAsync(@NotNull Plugin plugin, @NotNull UUI Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> addToStashIfEnabled(uuid, stack)); } + public static @Nullable CompoundTag getCustomData(@NotNull ItemStack stack) { + CustomData customData = CraftItemStack.asNMSCopy(stack).get(DataComponents.CUSTOM_DATA); + if (customData == null) return null; + return customData.copyTag(); + } + public static @NotNull String getStringTag(@NotNull ItemStack stack, @NotNull String name) { - return CraftItemStack.asNMSCopy(stack).getOrCreateTag().getString(name); + CompoundTag tag = getCustomData(stack); + if (tag == null) return ""; + return tag.getString(name); + } + + public static @NotNull CompoundTag getCompoundTag(@NotNull ItemStack stack, @NotNull String name) { + CompoundTag tag = getCustomData(stack); + if (tag == null) return new CompoundTag(); + return tag.getCompound(name); } @Contract("null -> null") public static @Nullable String getMythicType(@Nullable ItemStack stack) { if (stack == null) return null; - String s = getStringTag(stack, "MYTHIC_TYPE"); + String s = getCompoundTag(stack, "PublicBukkitValues").getString("mythicmobs:type"); if (s.isBlank()) return null; return s; } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index e203edf..77e5068 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -9,7 +9,7 @@ description: That world, once again. depend: [ Essentials, Votifier ] softdepend: - ItemStash - - TAB + - TAB-BukkitBridge website: https://github.com/AfnwTeam/AfnwCore2 permissions: From efc86d6d16e58121de0e8cae2fce80bf66792bc6 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Fri, 22 Nov 2024 20:58:12 +0900 Subject: [PATCH 41/44] bug fix --- src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java | 6 ++++-- .../afnw/afnwcore2/listeners/player/QuitListener.java | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 419f061..acb18a5 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -15,6 +15,7 @@ import net.azisaba.afnw.afnwcore2.util.TheTAB; import net.azisaba.afnw.afnwcore2.util.data.PlayerData; import net.azisaba.afnw.afnwcore2.util.data.PlayerDataSave; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.attributes.RangedAttribute; import org.bukkit.Bukkit; @@ -61,7 +62,7 @@ public void onEnable() { getLogger().info("Listener 設定中...."); /* プレイヤーリスナー */ pluginEvent.registerEvents(new JoinListener(this, data), this); - pluginEvent.registerEvents(new QuitListener(), this); + pluginEvent.registerEvents(new QuitListener(this), this); pluginEvent.registerEvents(new DeathListener(), this); pluginEvent.registerEvents(new FirstPlayerJoinListener(this, data), this); pluginEvent.registerEvents(new AFKListener(this), this); @@ -129,7 +130,8 @@ public void onEnable() { } }, 10, 10); - ((RangedAttribute) Attributes.LUCK).maxValue = Double.MAX_VALUE; + ((RangedAttribute) Objects.requireNonNull(BuiltInRegistries.ATTRIBUTE.get(Attributes.LUCK.unwrap().left().orElseThrow()))) + .maxValue = Double.MAX_VALUE; getLogger().info("正常に起動しました。"); } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/QuitListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/QuitListener.java index 1654036..0c38be9 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/QuitListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/QuitListener.java @@ -1,5 +1,6 @@ package net.azisaba.afnw.afnwcore2.listeners.player; +import net.azisaba.afnw.afnwcore2.AfnwCore2; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; @@ -7,6 +8,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; +import org.jetbrains.annotations.NotNull; /** * ログアウトしたプレイヤーに関するクラス @@ -15,6 +17,11 @@ * @see org.bukkit.event.Listener */ public class QuitListener implements Listener { + private final @NotNull AfnwCore2 plugin; + + public QuitListener(@NotNull AfnwCore2 plugin) { + this.plugin = plugin; + } /** * ログアウト通知を行います。 @@ -27,5 +34,6 @@ public void onQuit(PlayerQuitEvent e) { Player p = e.getPlayer(); e.quitMessage(Component.text("* " + p.getName() + "がログアウトしました。").color(NamedTextColor.AQUA)); + plugin.pvpEnabled.remove(p.getUniqueId()); } } From dce68de9dfc5efe2b4fa00b5ab01c941186c9e48 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Sun, 28 Dec 2025 19:42:50 +0900 Subject: [PATCH 42/44] Update to 1.21.11 --- build.gradle.kts | 48 ++++++------------- gradle/wrapper/gradle-wrapper.properties | 2 +- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 16 +++++-- .../afnw/afnwcore2/commands/AfnwCommand.java | 2 +- .../listeners/entity/DropShardListener.java | 2 +- .../listeners/player/FishingListener.java | 2 +- .../afnw/afnwcore2/util/item/ItemUtil.java | 6 +-- 7 files changed, 32 insertions(+), 46 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0ad98b2..968b357 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("io.papermc.paperweight.userdev") version "1.7.1" + id("io.papermc.paperweight.userdev") version "2.0.0-beta.19" java id("com.gradleup.shadow") version "8.3.3" } @@ -9,48 +9,28 @@ version = "2.0.0-SNAPSHOT" repositories { mavenCentral() - maven { - name = "papermc-repo" - url = uri("https://papermc.io/repo/repository/maven-public/") - } - maven { - name = "sonatype" - url = uri("https://oss.sonatype.org/content/groups/public/") - } - maven { - name = "azisaba" - url = uri("https://repo.azisaba.net/repository/maven-public/") - } - maven { - name = "essentialsx" - url = uri("https://repo.essentialsx.net/releases/") - } - maven { - name = "lumine" - url = uri("https://mvn.lumine.io/repository/maven-public/") - } - maven { url = uri("https://jitpack.io") } - if (properties["azisabaNmsUsername"] != null && properties["azisabaNmsPassword"] != null) { - maven { - name = "azisabaNms" - credentials(PasswordCredentials::class) - url = uri("https://repo.azisaba.net/repository/nms/") - } - } + maven("https://repo.papermc.io/repository/maven-public/") + maven("https://oss.sonatype.org/content/groups/public/") + maven("https://repo.azisaba.net/repository/maven-public/") + maven("https://repo.essentialsx.net/releases/") + maven("https://mvn.lumine.io/repository/maven-public/") + maven("https://jitpack.io") } dependencies { // implementation("net.blueberrymc:native-util:2.1.0") - implementation("xyz.acrylicstyle.java-util:common:2.0.0-SNAPSHOT") - implementation("xyz.acrylicstyle.java-util:expression:2.0.0-SNAPSHOT") + implementation("xyz.acrylicstyle.java-util:common:2.1.1") + implementation("xyz.acrylicstyle.java-util:expression:2.1.1") compileOnly("net.azisaba.ballotbox:receiver:1.0.1") compileOnly("net.azisaba:ItemStash:1.0.0-SNAPSHOT") - compileOnly("net.essentialsx:EssentialsX:2.20.1") + compileOnly("net.essentialsx:EssentialsX:2.20.1") { + exclude("org.spigotmc", "spigot-api") + } compileOnly("io.lumine:Mythic-Dist:5.4.0") - compileOnly("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT") compileOnly("net.azisaba:TAB-BukkitBridge:3.1.0") compileOnly("org.jetbrains:annotations:26.0.1") - paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") + paperweight.paperDevBundle("1.21.11-R0.1-SNAPSHOT") } java.toolchain.languageVersion.set(JavaLanguageVersion.of(21)) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 19cfad9..ac57dd1 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-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index acb18a5..0ac6069 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -107,7 +107,7 @@ public void onEnable() { getLogger().info("コマンド 設定完了"); Bukkit.getScheduler().runTask(this, () -> { - if (Bukkit.getPluginManager().isPluginEnabled("TAB")) { + if (Bukkit.getPluginManager().isPluginEnabled("TAB-BukkitBridge")) { TheTAB.enable(); getLogger().info("TABの連携が有効です。"); } else { @@ -115,7 +115,7 @@ public void onEnable() { } }); - if(getConfig().getBoolean("settings.maintenance-mode-toggle", false)) { + if (getConfig().getBoolean("settings.maintenance-mode-toggle", false)) { getServer().setWhitelist(true); getLogger().info("正常に起動しました。(メンテナンスモード)"); return; @@ -128,10 +128,16 @@ public void onEnable() { ((CraftDolphin) entity).getHandle().goalSelector.removeAllGoals(goal -> goal.getClass().getTypeName().equals("net.minecraft.world.entity.animal.EntityDolphin$a")); } } - }, 10, 10); + }, 5, 5); - ((RangedAttribute) Objects.requireNonNull(BuiltInRegistries.ATTRIBUTE.get(Attributes.LUCK.unwrap().left().orElseThrow()))) - .maxValue = Double.MAX_VALUE; + var optionalAttributeReference = Objects.requireNonNull(BuiltInRegistries.ATTRIBUTE.get(Attributes.LUCK.unwrap().left().orElseThrow())); + optionalAttributeReference.ifPresent(attributeReference -> { + var optional = attributeReference.unwrap().right(); + optional.ifPresent(attribute -> { + ((RangedAttribute) attribute).maxValue = Double.MAX_VALUE; + getLogger().info("Luck attribute max value set to Double.MAX_VALUE"); + }); + }); getLogger().info("正常に起動しました。"); } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java index d03d897..3838a64 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java @@ -131,7 +131,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command int itemSize = config.getInt("vote.item-size", 1); int scaffoldSize = config.getInt("vote.scaffold-size", 8); - int luck = (int) Math.ceil(Optional.ofNullable(((Player) sender).getAttribute(Attribute.GENERIC_LUCK)).map(AttributeInstance::getValue).orElse(0.0)); + int luck = (int) Math.ceil(Optional.ofNullable(((Player) sender).getAttribute(Attribute.LUCK)).map(AttributeInstance::getValue).orElse(0.0)); ItemStack afnwItem = getRandomItem(luck, itemSize); inv.removeItem(AfnwTicket.afnwTicket); diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/entity/DropShardListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/entity/DropShardListener.java index adb4a2f..cbe298a 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/entity/DropShardListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/entity/DropShardListener.java @@ -18,7 +18,7 @@ public void onEntityDeath(EntityDeathEvent e) { } Player killer = e.getEntity().getKiller(); double baseChance = 0.001; // 0.1% - double playerLuck = Optional.ofNullable(killer.getAttribute(Attribute.GENERIC_LUCK)).map(AttributeInstance::getValue).orElse(0.0); + double playerLuck = Optional.ofNullable(killer.getAttribute(Attribute.LUCK)).map(AttributeInstance::getValue).orElse(0.0); double chance = baseChance + playerLuck * 0.0001; // 0.01% per luck level // calculate chance if (Math.random() < chance) { diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java index a9b919e..d448807 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/FishingListener.java @@ -14,7 +14,7 @@ public class FishingListener implements Listener { public void on(PlayerFishEvent e) { if (e.getCaught() != null) { double baseChance = 0.01; // 1% - double playerLuck = Optional.ofNullable(e.getPlayer().getAttribute(Attribute.GENERIC_LUCK)).map(AttributeInstance::getValue).orElse(0.0); + double playerLuck = Optional.ofNullable(e.getPlayer().getAttribute(Attribute.LUCK)).map(AttributeInstance::getValue).orElse(0.0); double chance = baseChance + playerLuck * 0.001; // 0.1% per luck level // calculate chance if (Math.random() < chance) { diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java index 058689f..022c0d8 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java @@ -34,19 +34,19 @@ public static void addToStashIfEnabledAsync(@NotNull Plugin plugin, @NotNull UUI public static @NotNull String getStringTag(@NotNull ItemStack stack, @NotNull String name) { CompoundTag tag = getCustomData(stack); if (tag == null) return ""; - return tag.getString(name); + return tag.getString(name).orElse(""); } public static @NotNull CompoundTag getCompoundTag(@NotNull ItemStack stack, @NotNull String name) { CompoundTag tag = getCustomData(stack); if (tag == null) return new CompoundTag(); - return tag.getCompound(name); + return tag.getCompound(name).orElseGet(CompoundTag::new); } @Contract("null -> null") public static @Nullable String getMythicType(@Nullable ItemStack stack) { if (stack == null) return null; - String s = getCompoundTag(stack, "PublicBukkitValues").getString("mythicmobs:type"); + String s = getCompoundTag(stack, "PublicBukkitValues").getString("mythicmobs:type").orElse(""); if (s.isBlank()) return null; return s; } From 46ddbca3d0fc8e2c96c3bfba0023f26d7d4f8c57 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Tue, 30 Dec 2025 14:15:26 +0900 Subject: [PATCH 43/44] updates --- build.gradle.kts | 4 +- .../net/azisaba/afnw/afnwcore2/AfnwCore2.java | 16 +++- .../afnw/afnwcore2/commands/AfnwCommand.java | 10 ++- .../afnw/afnwcore2/commands/TrashCommand.java | 17 +---- .../afnw/afnwcore2/commands/VoteCommand.java | 2 - .../afnw/afnwcore2/gui/TrashInventory.java | 32 ++++++++ .../listeners/other/VoteListener.java | 12 ++- .../player/EnderDragonDisableListener.java | 2 +- .../listeners/player/JoinListener.java | 7 +- .../listeners/player/TrashListener.java | 73 +++++++++++++++++++ .../afnw/afnwcore2/util/item/ItemUtil.java | 19 +++++ 11 files changed, 167 insertions(+), 27 deletions(-) create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/gui/TrashInventory.java create mode 100644 src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/TrashListener.java diff --git a/build.gradle.kts b/build.gradle.kts index 968b357..b8ee7df 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,11 @@ plugins { id("io.papermc.paperweight.userdev") version "2.0.0-beta.19" java - id("com.gradleup.shadow") version "8.3.3" + id("com.gradleup.shadow") version "9.3.0" } group = "net.azisaba.afnw" -version = "2.0.0-SNAPSHOT" +version = "2.1.0-SNAPSHOT" repositories { mavenCentral() diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java index 0ac6069..f77cd3c 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/AfnwCore2.java @@ -15,6 +15,8 @@ import net.azisaba.afnw.afnwcore2.util.TheTAB; import net.azisaba.afnw.afnwcore2.util.data.PlayerData; import net.azisaba.afnw.afnwcore2.util.data.PlayerDataSave; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.attributes.RangedAttribute; @@ -22,6 +24,7 @@ import org.bukkit.World; import org.bukkit.craftbukkit.entity.CraftDolphin; import org.bukkit.entity.Dolphin; +import org.bukkit.entity.Player; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -75,6 +78,7 @@ public void onEnable() { pluginEvent.registerEvents(new PvPListener(this), this); pluginEvent.registerEvents(new BlessedRandomTeleporterListener(), this); pluginEvent.registerEvents(new FishingListener(), this); + pluginEvent.registerEvents(new TrashListener(this), this); /* エンティティリスナー */ pluginEvent.registerEvents(new WitherSpawn(this), this); pluginEvent.registerEvents(new DropShardListener(), this); @@ -125,10 +129,18 @@ public void onEnable() { for (World world : Bukkit.getWorlds()) { for (Dolphin entity : world.getEntitiesByClass(Dolphin.class)) { // Prevent DolphinSwimToTreasureGoal from being triggered - ((CraftDolphin) entity).getHandle().goalSelector.removeAllGoals(goal -> goal.getClass().getTypeName().equals("net.minecraft.world.entity.animal.EntityDolphin$a")); + ((CraftDolphin) entity).getHandle().goalSelector.removeAllGoals(goal -> goal.getClass().getTypeName().equals("net.minecraft.world.entity.animal.EntityDolphin$a") || + goal.getClass().getTypeName().equals("net.minecraft.world.entity.animal.dolphin.Dolphin$DolphinSwimToTreasureGoal")); } } - }, 5, 5); + for (Player player : Bukkit.getOnlinePlayers()) { + boolean pvp = pvpEnabled.contains(player.getUniqueId()); + player.sendActionBar( + Component.text("⚔ PvP: ") + .append(Component.text(pvp ? "有効" : "無効", pvp ? NamedTextColor.RED : NamedTextColor.GREEN)) + ); + } + }, 10, 10); var optionalAttributeReference = Objects.requireNonNull(BuiltInRegistries.ATTRIBUTE.get(Attributes.LUCK.unwrap().left().orElseThrow())); optionalAttributeReference.ifPresent(attributeReference -> { diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java index 3838a64..8049789 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/AfnwCommand.java @@ -10,6 +10,7 @@ import net.azisaba.afnw.afnwcore2.util.data.PlayerData; import net.azisaba.afnw.afnwcore2.util.item.AfnwScaffold; import net.azisaba.afnw.afnwcore2.util.item.AfnwTicket; +import net.azisaba.afnw.afnwcore2.util.item.ItemUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Material; @@ -41,7 +42,8 @@ private static boolean isAllowed(Material type) { return switch (type) { case BEDROCK, STRUCTURE_BLOCK, STRUCTURE_VOID, COMMAND_BLOCK, CHAIN_COMMAND_BLOCK, COMMAND_BLOCK_MINECART, REPEATING_COMMAND_BLOCK, BARRIER, LIGHT, JIGSAW, END_PORTAL, KNOWLEDGE_BOOK, DEBUG_STICK, - AIR, VOID_AIR, CAVE_AIR, BUNDLE -> false; + TEST_INSTANCE_BLOCK, TEST_BLOCK, + AIR, VOID_AIR, CAVE_AIR -> false; default -> true; }; } @@ -135,14 +137,16 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command ItemStack afnwItem = getRandomItem(luck, itemSize); inv.removeItem(AfnwTicket.afnwTicket); - inv.addItem(afnwItem); + for (ItemStack value : inv.addItem(afnwItem).values()) { + ItemUtil.addToStashIfEnabledAsync(plugin, ((Player) sender).getUniqueId(), value); + } for (int i = 0; i < scaffoldSize; i++) { inv.addItem(AfnwScaffold.afnwScaffold); } sender.sendMessage(Component.text("アイテムと交換しました。").color(NamedTextColor.GOLD)); sender.sendMessage(Component.text( - "交換内容: " + afnwItem.getType() + " ×" + afnwItem.getAmount() + ", 足場ブロック ×" + scaffoldSize) + "交換内容: " + afnwItem.getType() + " ×" + itemSize + "、足場ブロック ×" + scaffoldSize) .color(NamedTextColor.GOLD)); return true; } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/TrashCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/TrashCommand.java index 31b1fd5..e37e719 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/TrashCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/TrashCommand.java @@ -1,12 +1,11 @@ package net.azisaba.afnw.afnwcore2.commands; +import net.azisaba.afnw.afnwcore2.gui.TrashInventory; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -29,19 +28,7 @@ public boolean onCommand(@NotNull CommandSender sender, Command command, @NotNul return false; } - FileConfiguration config = plugin.getConfig(); - String trashName = config.getString("trash.name", "ゴミ箱"); - int trashSize = config.getInt("trash.size", 54); - if (trashSize % 9 == 0) { - config.set("trash.size", 54); - } - - trashGUI(p, trashSize, trashName); + p.openInventory(new TrashInventory().getInventory()); return true; } - - public void trashGUI(Player p, int size, String name) { - p.openInventory( - Bukkit.createInventory(null, size, Component.text(name, NamedTextColor.DARK_PURPLE))); - } } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/commands/VoteCommand.java b/src/main/java/net/azisaba/afnw/afnwcore2/commands/VoteCommand.java index 714f20b..c7e2d49 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/commands/VoteCommand.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/commands/VoteCommand.java @@ -37,8 +37,6 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command ChatColor.GOLD + """ 投票よろしくお願いします! - ・monocraft - https://monocraft.net/servers/xWBVrf1nqB2P0LxlMm2v ・JMS https://minecraft.jp/servers/azisaba.net """ diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/gui/TrashInventory.java b/src/main/java/net/azisaba/afnw/afnwcore2/gui/TrashInventory.java new file mode 100644 index 0000000..c2399af --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/gui/TrashInventory.java @@ -0,0 +1,32 @@ +package net.azisaba.afnw.afnwcore2.gui; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; + +public class TrashInventory implements InventoryHolder { + public static final ItemStack trashItem = new ItemStack(Material.BARRIER); + private final Inventory inventory = Bukkit.createInventory(this, 54, Component.text("ゴミ箱", NamedTextColor.RED)); + + static { + ItemMeta meta = trashItem.getItemMeta(); + meta.displayName(Component.text("ゴミを捨てる", NamedTextColor.RED)); + trashItem.setItemMeta(meta); + } + + public TrashInventory() { + inventory.setItem(53, trashItem); + } + + @NotNull + @Override + public Inventory getInventory() { + return inventory; + } +} diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java index 52c24cb..e9223ef 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/other/VoteListener.java @@ -16,10 +16,16 @@ import org.bukkit.event.Listener; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; public record VoteListener(AfnwCore2 plugin, PlayerData playerData) implements Listener { @EventHandler public void onVote(VotifierEvent e) { + handleVote(e); + handleVote(e); + } + + public void handleVote(VotifierEvent e) { FileConfiguration config = plugin.getConfig(); int ticketSize = config.getInt("vote.send-ticket-size", 1); int bonusLine = config.getInt("vote.bonus-line", 9); @@ -50,7 +56,11 @@ public void onVote(VotifierEvent e) { ItemUtil.addToStashIfEnabledAsync(plugin, sendTarget.getUniqueId(), value); } } - for (ItemStack value : inv.addItem(new ItemStack(Material.NETHER_STAR)).values()) { + ItemStack netherStar = new ItemStack(Material.NETHER_STAR); + ItemMeta meta = netherStar.getItemMeta(); + meta.displayName(Component.text("投票ボーナス", NamedTextColor.YELLOW)); + netherStar.setItemMeta(meta); + for (ItemStack value : inv.addItem(netherStar).values()) { ItemUtil.addToStashIfEnabledAsync(plugin, sendTarget.getUniqueId(), value); } sendTarget.sendMessage(Component.text("* 投票ボーナスとしてチケット10枚とネザースターを獲得しました。") diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/EnderDragonDisableListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/EnderDragonDisableListener.java index ddb48fd..333a18d 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/EnderDragonDisableListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/EnderDragonDisableListener.java @@ -12,7 +12,7 @@ public class EnderDragonDisableListener implements Listener { public void onPlayerInteract(PlayerInteractEvent e) { if (e.getItem() == null) return; Material inHand = e.getItem().getType(); - if ((inHand == Material.ENDER_DRAGON_SPAWN_EGG/* || inHand == Material.WITHER_SPAWN_EGG*/) + if ((inHand == Material.ENDER_DRAGON_SPAWN_EGG || inHand == Material.WITHER_SPAWN_EGG) && !e.getPlayer().getWorld().getName().equals("afnw_the_end")) { e.setCancelled(true); } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java index 6051602..b37061c 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/JoinListener.java @@ -4,6 +4,7 @@ import java.util.Arrays; import net.azisaba.afnw.afnwcore2.AfnwCore2; import net.azisaba.afnw.afnwcore2.util.data.PlayerData; +import net.azisaba.afnw.afnwcore2.util.item.AfnwTicket; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.title.Title; @@ -36,9 +37,13 @@ public record JoinListener(JavaPlugin plugin, PlayerData playerData) implements public void onJoin(PlayerJoinEvent e) { Player p = e.getPlayer(); - // 初参加の場合はSuper Afnw Ticketを渡す + // 初参加の場合 if (!playerData.getPlayerData().getBoolean("players." + p.getUniqueId() + ".first-join", false)) { playerData.getPlayerData().set("players." + p.getUniqueId() + ".first-join", true); + e.getPlayer().getInventory().addItem(AfnwTicket.afnwTicket); + e.getPlayer().getInventory().addItem(AfnwTicket.afnwTicket); + e.getPlayer().getInventory().addItem(AfnwTicket.afnwTicket); + e.getPlayer().getInventory().addItem(AfnwTicket.afnwTicket); Bukkit.getScheduler().runTaskAsynchronously(plugin, playerData::savePlayerData); } diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/TrashListener.java b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/TrashListener.java new file mode 100644 index 0000000..7498223 --- /dev/null +++ b/src/main/java/net/azisaba/afnw/afnwcore2/listeners/player/TrashListener.java @@ -0,0 +1,73 @@ +package net.azisaba.afnw.afnwcore2.listeners.player; + +import net.azisaba.afnw.afnwcore2.AfnwCore2; +import net.azisaba.afnw.afnwcore2.gui.TrashInventory; +import net.azisaba.afnw.afnwcore2.util.item.ItemUtil; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +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.InventoryDragEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public record TrashListener(@NotNull AfnwCore2 plugin) implements Listener { + @EventHandler + public void onInventoryClick(InventoryClickEvent e) { + if (e.getClickedInventory() == null || !(e.getClickedInventory().getHolder() instanceof TrashInventory)) { + return; + } + if (e.getSlot() != 53) { + return; + } + e.getInventory().setItem(53, null); + int count = 0; + List items = new ArrayList<>(); + for (ItemStack item : e.getInventory().getContents()) { + if (item == null || item.getAmount() <= 0) continue; + count += item.getAmount(); + items.add(item.clone()); + item.setAmount(0); + } + e.getWhoClicked().sendMessage(Component.text("ゴミ箱に" + count + "個のアイテムを捨てました。", NamedTextColor.YELLOW)); + plugin.getSLF4JLogger().info("Player {} has trashed {} items:", e.getWhoClicked().getName(), count); + for (ItemStack item : items) { + plugin.getSLF4JLogger().info(" {}", ItemUtil.toString(item)); + e.getWhoClicked().sendMessage(Component.text(" " + ItemUtil.toString(item), NamedTextColor.GRAY)); + } + e.getClickedInventory().clear(); + e.getWhoClicked().closeInventory(); + } + + @EventHandler + public void onInventoryDrag(InventoryDragEvent e) { + if (e.getInventory().getHolder() instanceof TrashInventory) { + e.setCancelled(true); + } + } + + @EventHandler + public void onInventoryClose(InventoryCloseEvent e) { + if (!(e.getInventory().getHolder() instanceof TrashInventory)) { + return; + } + e.getInventory().setItem(53, null); + boolean stash = false; + for (ItemStack item : e.getInventory().getContents()) { + if (item == null || item.getAmount() <= 0) continue; + for (ItemStack value : e.getPlayer().getInventory().addItem(item).values()) { + ItemUtil.addToStashIfEnabledAsync(plugin, e.getPlayer().getUniqueId(), value); + stash = true; + } + } + if (stash) { + e.getPlayer().sendMessage(Component.text("インベントリがいっぱいのため、Stashに保管されました。", NamedTextColor.RED)); + e.getPlayer().sendMessage(Component.text("/pickupstash", NamedTextColor.AQUA).append(Component.text("で回収できます。", NamedTextColor.RED))); + } + } +} diff --git a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java index 022c0d8..16b5070 100644 --- a/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java +++ b/src/main/java/net/azisaba/afnw/afnwcore2/util/item/ItemUtil.java @@ -7,11 +7,15 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; import java.util.UUID; public class ItemUtil { @@ -50,4 +54,19 @@ public static void addToStashIfEnabledAsync(@NotNull Plugin plugin, @NotNull UUI if (s.isBlank()) return null; return s; } + + public static @NotNull String toString(@NotNull ItemStack stack) { + List props = new ArrayList<>(); + props.add("[Type: " + stack.getType().name() + "]"); + props.add("[Amount: " + stack.getAmount() + "]"); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + if (meta.hasDisplayName()) props.add("[Name: " + meta.getDisplayName() + "]"); + if (meta.hasLore()) props.add("[Lore: " + Objects.requireNonNull(meta.getLore()).size() + " entries]"); + if (meta.hasCustomModelData()) props.add("[CustomModelData: " + meta.getCustomModelData() + "]"); + if (getMythicType(stack) != null) props.add("[MMID: " + getMythicType(stack) + "]"); + if (meta.hasEnchants()) meta.getEnchants().forEach((enchant, level) -> props.add("[Enchant: " + enchant.getKey() + " " + level + "]")); + } + return String.join("", props); + } } From 2254b7f581d61e9a4169b6d542d0bbd43ce6fcb4 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Tue, 30 Dec 2025 15:52:21 +0900 Subject: [PATCH 44/44] Add deploy workflow --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .github/codeql-config.yml | 4 -- .github/labeler.yml | 2 - .github/labels.yml | 52 ----------------------- .github/renovate.json | 6 --- .github/workflows/auto-labeler.yml | 14 ------ .github/workflows/build.yml | 31 -------------- .github/workflows/codeql.yml | 41 ------------------ .github/workflows/deploy.yml | 16 +++++++ .github/workflows/label-sync.yml | 22 ---------- 11 files changed, 18 insertions(+), 174 deletions(-) delete mode 100644 .github/codeql-config.yml delete mode 100644 .github/labeler.yml delete mode 100644 .github/labels.yml delete mode 100644 .github/renovate.json delete mode 100644 .github/workflows/auto-labeler.yml delete mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/deploy.yml delete mode 100644 .github/workflows/label-sync.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index ffb6e98..174f9df 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -3,7 +3,7 @@ name: Bug report about: 不具合を報告するIssueを作成します。 title: '' labels: 👮security -assignees: m2en +assignees: acrylic-style --- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 13d0c1d..3d7efa8 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -3,7 +3,7 @@ name: Feature request about: 機能のリクエストなどを送信します。 title: '' labels: ✨enhancement -assignees: m2en +assignees: acrylic-style --- diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml deleted file mode 100644 index 1095a04..0000000 --- a/.github/codeql-config.yml +++ /dev/null @@ -1,4 +0,0 @@ -paths: - - src -paths-ignore: - - '/**/*.md' diff --git a/.github/labeler.yml b/.github/labeler.yml deleted file mode 100644 index d8d3c03..0000000 --- a/.github/labeler.yml +++ /dev/null @@ -1,2 +0,0 @@ -🔮workflow (gh-actions): - - .github/workflows/*.yml diff --git a/.github/labels.yml b/.github/labels.yml deleted file mode 100644 index efd43c9..0000000 --- a/.github/labels.yml +++ /dev/null @@ -1,52 +0,0 @@ -# AfnwCore2 Label - b5f0aa - -- name: '🔒not compatible' - color: 'd4d4d4' -- name: '📡help wanted' - color: 'f0dc59' -- name: '📡duplicate' - description: 'This issue or pull request already exists' - color: 'f0dc59' -- name: '📡invalid' - description: 'This issue or pull request is invalid' - color: 'f0dc59' -- name: '📡wrong' - description: 'This issue or pull request is wrong' - color: 'f0dc59' -- name: '🏃high' - color: 'fc032c' -- name: '🚶low' - color: 'f7b2bd' -- name: '🐛bug' - color: 'ff0026' -- name: '🐛bug(JE v1.17.x)' - color: 'ff0026' -- name: '🐛bug(Not JE v1.17.x)' - color: 'ff0026' -- name: '👮security' - color: 'ff0026' -- name: '👮security(CVE)' - color: 'ff0026' -- name: '✨design' - color: 'ee9cff' -- name: '✨improvement' - color: 'ee9cff' -- name: '✨enhancement' - color: 'ee9cff' -- name: '✨documentation' - color: 'ee9cff' -- name: '🔮workflow (gh-actions)' - color: 'ee9cff' -- name: '🔮renovate: update' - color: 'ee9cff' -- name: '🔮renovate: security' - color: 'ee9cff' -- name: '💃feature request' - description: '鯖民からの要望' - color: 'f0dc59' -- name: '💃no context' - description: 'No Context, 内容が薄いもう少し詳しいものがほしいものに付与' - color: 'f0dc59' -- name: '💃feature request' - description: 'This issue or pull request is invalid' - color: 'f0dc59' diff --git a/.github/renovate.json b/.github/renovate.json deleted file mode 100644 index b0f6723..0000000 --- a/.github/renovate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": [ - "github>m2en/renovate-config" - ], - "labels": ["\uD83D\uDD2Erenovate: update"] -} diff --git a/.github/workflows/auto-labeler.yml b/.github/workflows/auto-labeler.yml deleted file mode 100644 index ab1d8f8..0000000 --- a/.github/workflows/auto-labeler.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Auto Labeler -on: - - pull_request_target - -jobs: - auto-label: - permissions: - contents: read - pull-requests: write - runs-on: ubuntu-latest - steps: - - uses: actions/labeler@v4 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index d38f469..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Java17 Build - -on: - pull_request: - paths-ignore: - - '**.md' - -jobs: - build: - name: Build with Java17 - - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - contents: read - - steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: '17' - cache: 'gradle' - - - name: Prepare gradle.properties - run: | - mkdir -p $HOME/.gradle - echo "azisabaNmsUsername=${{ secrets.REPO_USERNAME }}" >> $HOME/.gradle/gradle.properties - echo "azisabaNmsPassword=${{ secrets.REPO_PASSWORD }}" >> $HOME/.gradle/gradle.properties - - run: ./gradlew build diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 5626c1a..0000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: CodeQL - -on: - push: - branches: - - main - pull_request: - branches: - - main - schedule: - - cron: '32 6 * * 5' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'java' ] - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - config-file: ./.github/codeql-config.yml - - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..50e6bfe --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,16 @@ +name: Deploy +on: + push: + branches: [ main ] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'adoptium' + java-version: '21' + - run: ./gradlew shadowJar + - run: 'curl -X PUT --data-binary @build/libs/AfnwCore2-*-all.jar "https://saba8-deploy.azisaba.dev/deploy?secret={{ secrets.DEPLOYMAN_SECRET_SABA8 }}&token={{ secrets.DEPLOYMAN_TOKEN }}&filename=AfnwCore2.jar"' diff --git a/.github/workflows/label-sync.yml b/.github/workflows/label-sync.yml deleted file mode 100644 index 6ca8de9..0000000 --- a/.github/workflows/label-sync.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: label sync - -on: - push: - branches: - - main - paths: - - '.github/labels.yml' - - '.github/workflows/label-sync.yml' - -jobs: - label-sync: - runs-on: ubuntu-latest - steps: - - name: checkout - uses: actions/checkout@v3 - - - name: label sync - if: success() - uses: crazy-max/ghaction-github-labeler@v4 - with: - github-token: ${{ secrets.GITHUB_TOKEN }}