From febeebb2fa67e23c8fb6573e38c6602ea3508997 Mon Sep 17 00:00:00 2001 From: AburaAgeTarou Date: Sat, 25 Jan 2025 11:13:30 +0900 Subject: [PATCH] =?UTF-8?q?=E9=9F=B3=E5=86=8D=E7=94=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yatchayatcha/YYConfigUtil.java | 133 +++++++++++++++++- .../yatchayatcha/YatchaYatcha.java | 5 +- .../yatchayatcha/auction/AdminAuction.java | 100 +++++++------ .../yatchayatcha/auction/SidebarManager.java | 2 - .../commands/AdminAuctionCommand.java | 6 +- .../yatchayatcha/utils/EnhancedTask.java | 117 +++++++++++++++ .../yatchayatcha/utils/SyncEnhancedTask.java | 60 ++++++++ .../yatchayatcha/utils/Utilities.java | 41 +++++- src/main/resources/config.yml | 18 +++ 9 files changed, 429 insertions(+), 53 deletions(-) create mode 100644 src/main/java/com/github/aburaagearou/yatchayatcha/utils/EnhancedTask.java create mode 100644 src/main/java/com/github/aburaagearou/yatchayatcha/utils/SyncEnhancedTask.java diff --git a/src/main/java/com/github/aburaagearou/yatchayatcha/YYConfigUtil.java b/src/main/java/com/github/aburaagearou/yatchayatcha/YYConfigUtil.java index 040e71f..c2569ea 100644 --- a/src/main/java/com/github/aburaagearou/yatchayatcha/YYConfigUtil.java +++ b/src/main/java/com/github/aburaagearou/yatchayatcha/YYConfigUtil.java @@ -1,6 +1,11 @@ package com.github.aburaagearou.yatchayatcha; -import java.util.List; +import org.bukkit.Sound; + +import javax.annotation.Nullable; +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; /** * 設定ファイルユーティリティクラス @@ -14,6 +19,32 @@ public class YYConfigUtil { public static final String BID_MIN_PRICE_AD = "bid-min-price-add"; public static final String LUNACHAT_AUCTION_CHANNEL = "lc-auction-channel"; + // 効果音設定 + public static final String SOUND_EFFECTS = "sound-effects"; + public static final String SE_START = "start"; + public static final String SE_BID_SELF = "bid-self"; + public static final String SE_BID_RIVAL = "bid-rival"; + public static final String SE_COUNTDOWN = "countdown"; + public static final String SE_SUCCESS = "success"; + + // 効果音リスト + private static final Map sounds = new HashMap<>(); + static { + Arrays.stream(Sound.values()).forEach(sound -> sounds.put(sound.name().replace(".", "_"), sound)); + } + + // 効果音設定 + private static final Map> soundSettings = new HashMap<>(); + + /** + * 再読み込み + */ + public static void reload() { + YatchaYatcha.getInstance().saveDefaultConfig(); + YatchaYatcha.getInstance().reloadConfig(); + soundSettings.clear(); + } + /** * カウントダウン秒数を取得 * @return 秒数(int) @@ -53,4 +84,104 @@ public static int getBidMinPriceAdd() { public static String getLunaChatAuctionChannel() { return YatchaYatcha.getInstance().getConfig().getString(LUNACHAT_AUCTION_CHANNEL); } + + /** + * 効果音設定を取得 + * @param seKey sound-effects配下のキー名 + * @return 効果音設定リスト + */ + @Nullable + public static List getSoundSetting(String seKey) { + String key = SOUND_EFFECTS + "." + seKey; + if(!soundSettings.containsKey(seKey)) { + if(!YatchaYatcha.getInstance().getConfig().isString(key)) { + return null; + } + List settings = Arrays.stream(YatchaYatcha.getInstance().getConfig().getString(key).split(",")) + .map(YYConfigUtil::parseSoundSetting) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + soundSettings.put(seKey, settings); + } + return soundSettings.get(seKey); + } + + /** + * 効果音設定の分解 + * @param key 設定キー("SOUND_NAME-VOLUME-PITCH(-DELAY)") + */ + @Nullable + public static SoundSetting parseSoundSetting(String key) { + // 設定の分解("SOUND_NAME-VOLUME-PITCH(-DELAY)") + String[] soundSetting = key.split("-"); + if(soundSetting.length < 3) { + return null; + } + + // 効果音の取得 + Sound sound = sounds.get(soundSetting[0].toUpperCase()); + if(sound == null) return null; + BigDecimal volume = new BigDecimal(soundSetting[1]); + BigDecimal pitch = new BigDecimal(soundSetting[2]); + BigDecimal delay = new BigDecimal(0); + if(soundSetting.length >= 4) { + delay = new BigDecimal(soundSetting[3]); + } + return new SoundSetting(sound, volume.floatValue(), pitch.floatValue(), delay.intValue()); + } + + /** + * 効果音設定 + */ + public static class SoundSetting { + private final Sound sound; + private final float volume; + private final float pitch; + private final int delay; + + /** + * コンストラクタ + * @param sound 効果音 + * @param volume 音量 + * @param pitch ピッチ + */ + public SoundSetting(Sound sound, float volume, float pitch, int delay) { + this.sound = sound; + this.volume = volume; + this.pitch = pitch; + this.delay = delay; + } + + /** + * 効果音を取得 + * @return 効果音 + */ + public Sound getSound() { + return sound; + } + + /** + * 音量を取得 + * @return 音量 + */ + public float getVolume() { + return volume; + } + + /** + * ピッチを取得 + * @return ピッチ + */ + public float getPitch() { + return pitch; + } + + /** + * 遅延時間を取得 + * @return 遅延時間 + */ + public int getDelay() { + return delay; + } + } } diff --git a/src/main/java/com/github/aburaagearou/yatchayatcha/YatchaYatcha.java b/src/main/java/com/github/aburaagearou/yatchayatcha/YatchaYatcha.java index 277e618..24d7c53 100644 --- a/src/main/java/com/github/aburaagearou/yatchayatcha/YatchaYatcha.java +++ b/src/main/java/com/github/aburaagearou/yatchayatcha/YatchaYatcha.java @@ -4,13 +4,13 @@ import co.aikar.commands.MessageKeys; import co.aikar.commands.MessageType; import co.aikar.commands.PaperCommandManager; +import com.github.aburaagearou.yatchayatcha.auction.AdminAuction; import com.github.aburaagearou.yatchayatcha.commands.AdminAuctionCommand; import com.github.aburaagearou.yatchayatcha.commands.BidCommand; import com.github.aburaagearou.yatchayatcha.log.AuctionInfo; import com.github.aburaagearou.yatchayatcha.log.FileLogger; import com.github.aburaagearou.yatchayatcha.log.IAuctionLogger; import com.github.aburaagearou.yatchayatcha.log.MemoryLogger; -import com.github.ucchyocean.lc.channel.Channel; import net.milkbowl.vault.economy.Economy; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; @@ -101,6 +101,9 @@ public void onEnable() { public void onDisable() { getLogger().info("YatchaYatchaを無効化します。"); + // オークションの中断 + AdminAuction.getInstance().end(true); + // コマンドの登録解除 commands.forEach(manager::unregisterCommand); manager.unregisterCommands(); diff --git a/src/main/java/com/github/aburaagearou/yatchayatcha/auction/AdminAuction.java b/src/main/java/com/github/aburaagearou/yatchayatcha/auction/AdminAuction.java index 75ef391..c42febf 100644 --- a/src/main/java/com/github/aburaagearou/yatchayatcha/auction/AdminAuction.java +++ b/src/main/java/com/github/aburaagearou/yatchayatcha/auction/AdminAuction.java @@ -121,6 +121,9 @@ public void start(ItemStack item, int start, boolean isDebug) { // 表示 sidebar.showAll(); sidebar.show(); + + // 効果音 + Utilities.playSound(YYConfigUtil.getSoundSetting(YYConfigUtil.SE_START)); } /** @@ -132,10 +135,55 @@ private void cancelTask() { } } + /** + * カウントダウンによる自動終了 + */ + public void countdown() { + int countdown = YYConfigUtil.getCountdown(); + + // カウントダウン + final int price = bidPrice; + countdownTask = Bukkit.getScheduler().runTaskTimer(YatchaYatcha.getInstance(), new Runnable() { + int count = countdown; + + @Override + public void run() { + if(!isAuctioning) { + cancelTask(); + return; + } + if(count-- <= 0) { + end(false); + cancelTask(); + return; + } + + // 入札があった場合 + if(price != bidPrice) { + cancelTask(); + return; + } + + // 10秒前 + if(count == 10) { + Utilities.broadcastColoredMessage("&a&l入札がない場合、あと&e&n" + count + "&a&l秒でオークションが終了します!"); + } + else if(count < 5) { + Utilities.playSound(YYConfigUtil.getSoundSetting(YYConfigUtil.SE_COUNTDOWN)); + Utilities.broadcastColoredMessage("&e&n" + (count+1) + "..."); + } + + // サイドバー更新 + sidebar.setLine(7, "&b落札まであと&e" + (count+1) + "秒"); + } + }, 20L, 20L); + } + /** * オークションを終了する */ public void end(boolean cancel) { + if(!isAuctioning) return; isAuctioning = false; if(isDebug) Utilities.broadcastColoredMessage("&c!!!!!!!!!!!!!!!!Debug!!!!!!!!!!!!!!!!"); else Utilities.broadcastColoredMessage("&e====================================="); @@ -181,55 +229,15 @@ public void end(boolean cancel) { if(isDebug) Utilities.broadcastColoredMessage("&c!!!!!!!!!!!!!!!!Debug!!!!!!!!!!!!!!!!"); else Utilities.broadcastColoredMessage("&e====================================="); - // ロギング - YatchaYatcha.log(new AuctionInfo(bidPlayer, bidPrice, item)); - // スコアボード使用終了 sidebar.clear(); sidebar.hide(); - } - - /** - * カウントダウンによる自動終了 - */ - public void countdown() { - int countdown = YYConfigUtil.getCountdown(); - // カウントダウン - final int price = bidPrice; - countdownTask = Bukkit.getScheduler().runTaskTimer(YatchaYatcha.getInstance(), new Runnable() { - int count = countdown; + // 効果音 + Utilities.playSound(YYConfigUtil.getSoundSetting(YYConfigUtil.SE_SUCCESS)); - @Override - public void run() { - if(!isAuctioning) { - cancelTask(); - return; - } - if(count-- <= 0) { - end(false); - cancelTask(); - return; - } - - // 入札があった場合 - if(price != bidPrice) { - cancelTask(); - return; - } - - // 10秒前 - if(count == 10) { - Utilities.broadcastColoredMessage("&a&l入札がない場合、あと&e&n" + count + "&a&l秒でオークションが終了します!"); - } - else if(count < 5) { - Utilities.broadcastColoredMessage("&e&n" + (count+1) + "..."); - } - - // サイドバー更新 - sidebar.setLine(7, "&b落札まであと&e" + (count+1) + "秒"); - } - }, 20L, 20L); + // ロギング + YatchaYatcha.log(new AuctionInfo(bidPlayer, bidPrice, item)); } /** @@ -265,6 +273,10 @@ public void bid(Player player, int price) { sidebar.setLine(4, "&7最高入札額: &e$" + bidPrice); sidebar.setLine(5, "&e$" + (minPrice.intValue()+1) + "&fから入札可能"); + // 効果音 + Utilities.playSound(YYConfigUtil.getSoundSetting(YYConfigUtil.SE_BID_SELF), bidPlayer); + Utilities.playSound(YYConfigUtil.getSoundSetting(YYConfigUtil.SE_BID_RIVAL), Bukkit.getOnlinePlayers().stream().filter(p -> !p.equals(bidPlayer)).toArray(Player[]::new)); + // カウントダウン開始 cancelTask(); countdown(); diff --git a/src/main/java/com/github/aburaagearou/yatchayatcha/auction/SidebarManager.java b/src/main/java/com/github/aburaagearou/yatchayatcha/auction/SidebarManager.java index c367754..ca049c8 100644 --- a/src/main/java/com/github/aburaagearou/yatchayatcha/auction/SidebarManager.java +++ b/src/main/java/com/github/aburaagearou/yatchayatcha/auction/SidebarManager.java @@ -2,10 +2,8 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Color; import org.bukkit.entity.Player; import org.bukkit.scoreboard.DisplaySlot; import org.bukkit.scoreboard.Objective; diff --git a/src/main/java/com/github/aburaagearou/yatchayatcha/commands/AdminAuctionCommand.java b/src/main/java/com/github/aburaagearou/yatchayatcha/commands/AdminAuctionCommand.java index 99baa3d..1694476 100644 --- a/src/main/java/com/github/aburaagearou/yatchayatcha/commands/AdminAuctionCommand.java +++ b/src/main/java/com/github/aburaagearou/yatchayatcha/commands/AdminAuctionCommand.java @@ -6,7 +6,6 @@ import com.github.aburaagearou.yatchayatcha.YatchaYatcha; import com.github.aburaagearou.yatchayatcha.auction.AdminAuction; import com.github.aburaagearou.yatchayatcha.utils.Utilities; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -67,15 +66,14 @@ public void onCancel(CommandSender ignore) { @Description("オークションルールを表示します。") public void onRule(Player sender) { for(String rule : YYConfigUtil.getRule()) { - Bukkit.getOnlinePlayers().forEach(player -> Utilities.sendColoredMessage(player, rule)); + Utilities.broadcastColoredMessage(rule); } } @Subcommand("reloadconfig") @Description("コンフィグをリロードします。") public void onReloadConfig(CommandSender sender) { - plugin.saveDefaultConfig(); - plugin.reloadConfig(); + YYConfigUtil.reload(); sender.sendMessage("[YatchaYatcha] 設定を再読み込みしました。"); } diff --git a/src/main/java/com/github/aburaagearou/yatchayatcha/utils/EnhancedTask.java b/src/main/java/com/github/aburaagearou/yatchayatcha/utils/EnhancedTask.java new file mode 100644 index 0000000..81c0628 --- /dev/null +++ b/src/main/java/com/github/aburaagearou/yatchayatcha/utils/EnhancedTask.java @@ -0,0 +1,117 @@ +package com.github.aburaagearou.yatchayatcha.utils; + +import com.github.aburaagearou.yatchayatcha.YatchaYatcha; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; + +import java.util.function.Consumer; + +/** + * 拡張タスククラス + * 従来のTimer要素に加え、回数指定や容易な中断が可能 + * @author AburaAgeTarou + */ +public abstract class EnhancedTask implements Runnable { + + // スケジュールの実行に必要なプラグインインスタンス + protected JavaPlugin plugin = YatchaYatcha.getInstance(); + + // スケジュールに割り振られたタスクID + protected BukkitTask bukkitTask; + + // 回数 + protected long times = 0; + + // 遅延 + protected long delay = 0L; + + // 残り時間 + protected int count = -1; + + // キャンセルフラグ + protected boolean cancel = false; + + // 停止フラグ + protected boolean stop = false; + + // 処理 + protected Consumer loopTask; + protected Runnable beforeTask; + protected Runnable loopEndTask; + protected EnhancedTask afterTask; + protected EnhancedTask root; + + @Override + public abstract void run(); + + public abstract void start(); + + public void cancel(){ + this.cancel = true; + } + + public void stop(){ + this.cancel = true; + this.stop = true; + } + + public EnhancedTask before(Runnable beforeTask){ + this.beforeTask = beforeTask; + return this; + } + + public EnhancedTask loop(long times, long delay, Consumer loopTask){ + this.times = times; + this.delay = delay; + this.loopTask = loopTask; + return this; + } + + public EnhancedTask whileTask(long delay, Consumer loopTask){ + this.times = Long.MAX_VALUE; + this.delay = delay; + this.loopTask = loopTask; + return this; + } + + public EnhancedTask waitTick(long delay){ + this.times = 1L; + this.delay = delay; + this.loopTask = (task) -> {}; + return this; + } + + public EnhancedTask loopEnd(Runnable loopEndTask){ + this.loopEndTask = loopEndTask; + return this; + } + + public EnhancedTask single(long delay, Consumer loopTask){ + this.times = 1L; + this.delay = delay; + this.loopTask = loopTask; + return this; + } + + public EnhancedTask after(EnhancedTask afterTask){ + this.afterTask = afterTask; + if(this.root == null) this.root = this; + this.afterTask.root = this.root; + return this.afterTask; + } + + public EnhancedTask root(){ + if(root == null) return this; + return root; + } + + public void stopLoop(){ + if(bukkitTask != null) bukkitTask.cancel(); + } + + public int getCount(){ return count; } + + public void setCount(int count){ this.count = count; } + + public boolean isCancel() { return cancel; } +} diff --git a/src/main/java/com/github/aburaagearou/yatchayatcha/utils/SyncEnhancedTask.java b/src/main/java/com/github/aburaagearou/yatchayatcha/utils/SyncEnhancedTask.java new file mode 100644 index 0000000..0c7586e --- /dev/null +++ b/src/main/java/com/github/aburaagearou/yatchayatcha/utils/SyncEnhancedTask.java @@ -0,0 +1,60 @@ +package com.github.aburaagearou.yatchayatcha.utils; + +import org.bukkit.Bukkit; + +/** + * BukkitのSchedulerで処理を同期実行する拡張タスククラス + * @author AburaAgeTarou + */ +public class SyncEnhancedTask extends EnhancedTask { + + @Override + public void run() { + + // 停止 + if(stop) { + stopLoop(); + return; + } + + // 開始 + if(count++ < 0) { + count = 0; + if(loopTask != null){ + if(times == 1) bukkitTask = Bukkit.getScheduler().runTaskTimer(plugin, this, delay, 0L); + else bukkitTask = Bukkit.getScheduler().runTaskTimer(plugin, this, 0L, delay); + } + return; + } + + // ループ + loopTask.accept(this); + + // 終了 + if(count > times || cancel) { + if(loopEndTask != null) Bukkit.getScheduler().runTask(plugin, loopEndTask); + if(afterTask != null) { + afterTask.start(); + } + stopLoop(); + } + } + + @Override + public void start() { + + if(beforeTask != null) beforeTask.run(); + + // 遅延がない場合 + if(delay <= 0L){ + for(int i = 0; i < times; i++){ + Bukkit.getScheduler().runTask(plugin, () -> loopTask.accept(this)); + } + if(loopEndTask != null) Bukkit.getScheduler().runTask(plugin, loopEndTask); + if(afterTask != null) afterTask.start(); + } + else { + Bukkit.getScheduler().runTask(plugin, this); + } + } +} diff --git a/src/main/java/com/github/aburaagearou/yatchayatcha/utils/Utilities.java b/src/main/java/com/github/aburaagearou/yatchayatcha/utils/Utilities.java index d9ed4e5..3a07a20 100644 --- a/src/main/java/com/github/aburaagearou/yatchayatcha/utils/Utilities.java +++ b/src/main/java/com/github/aburaagearou/yatchayatcha/utils/Utilities.java @@ -1,12 +1,17 @@ package com.github.aburaagearou.yatchayatcha.utils; +import com.github.aburaagearou.yatchayatcha.YYConfigUtil; import com.github.aburaagearou.yatchayatcha.YatchaYatcha; import com.github.aburaagearou.yatchayatcha.hook.LunaChatHook; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; +import org.bukkit.SoundCategory; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import javax.annotation.Nullable; +import java.util.*; /** * ユーティリティクラス @@ -38,4 +43,38 @@ public static void broadcastColoredMessage(Component message) { } Bukkit.broadcast(message); } + + /** + * 効果音を再生 + * @param sounds 効果音 + * @param players 対象プレイヤー(Nullの場合は全員) + */ + public static void playSound(Collection sounds, @Nullable Player ...players) { + if(sounds == null || sounds.isEmpty()) return; + + // 対象プレイヤー + List playerList; + if(players != null && players.length > 0) { + playerList = new ArrayList<>(Arrays.asList(players)); + } + else { + playerList = new ArrayList<>(Bukkit.getOnlinePlayers()); + } + + // 遅延時間の昇順でソート + List sorted = new ArrayList<>(sounds); + sorted.sort(Comparator.comparingInt(YYConfigUtil.SoundSetting::getDelay)); + + // 遅延時間を考慮して再生 + int maxDelay = sorted.stream().max(Comparator.comparingInt(YYConfigUtil.SoundSetting::getDelay)).get().getDelay(); + SyncEnhancedTask syncedTask = new SyncEnhancedTask(); + syncedTask.loop(maxDelay, 1L, (task) -> { + int count = (syncedTask.getCount() - 1); + for(YYConfigUtil.SoundSetting sound : sorted) { + if(count == sound.getDelay()) { + playerList.forEach(player -> player.playSound(player.getLocation(), sound.getSound(), SoundCategory.MASTER, sound.getVolume(), sound.getPitch())); + } + } + }).start(); + } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index d4cf2ca..1b216ea 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -14,3 +14,21 @@ rule: - "&aさ&bん&cぷ&dる&eぷ&1る&2ぷ&3る" - "同じように行を増やせば説明を増やせるよ" - "でもTwitter民は3行までの文章しか読めないから配慮してあげてね" + +# 効果音 +sound-effects: + + # オークション開始 + start: block_note_block_basedrum-1-0.7-0,block_bell_use-1-1.5-0,block_bell_use-1-1.65-10,block_bell_use-1-1.65-12,block_bell_use-1-1.5-25,block_bell_use-1-1.65-27,block_bell_use-1-1.5-40,block_bell_use-1-1.65-42 + + # 入札(自分) + bid-self: entity_villager_yes-1-1-0 + + # 入札(他人) + bid-rival: entity_pillager_celebrate-1-1.2-0 + + # カウントダウン + countdown: entity_ender_dragon_hurt-1-1.4-0 + + # 落札 + success: ui_toast_challenge_complete-1-1-0,block_bell_use-1-1.9-0,block_bell_use-1-1.8-4,block_bell_use-1-1.9-8,block_bell_use-1-1.8-12,block_bell_use-1-1.9-16,,block_bell_use-1-1.8-20,block_bell_use-1-1.9-24,block_bell_use-1-1.8-28,