diff --git a/pom.xml b/pom.xml index f94f957..f51c597 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.lunadeer MiniPlayerTitle - 3.0.2 + 3.0.3 jar MiniPlayerTitle diff --git a/src/main/java/cn/lunadeer/miniplayertitle/Commands.java b/src/main/java/cn/lunadeer/miniplayertitle/Commands.java index a5cb81f..dfc1087 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/Commands.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/Commands.java @@ -1,7 +1,9 @@ package cn.lunadeer.miniplayertitle; +import cn.lunadeer.miniplayertitle.commands.PlayerManage; import cn.lunadeer.miniplayertitle.commands.TitleManage; import cn.lunadeer.miniplayertitle.commands.TitleShopSale; +import cn.lunadeer.miniplayertitle.dtos.PlayerInfoDTO; import cn.lunadeer.miniplayertitle.tuis.*; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -55,7 +57,7 @@ public class Commands implements TabExecutor { case "use_title": // mplt use_title <背包ID> [页码] TitleManage.useTitle(sender, args); break; - case "create_title": // mplt create_title <称号名称> <称号描述> + case "create_title": // mplt create_title <称号名称> [称号描述] TitleManage.createTitle(sender, args); break; case "delete_title": // mplt delete_title <称号ID> [页码] @@ -70,6 +72,12 @@ public class Commands implements TabExecutor { case "custom_title": // mplt custom_title <称号> TitleManage.customTitle(sender, args); break; + case "add_coin": // mplt add_coin <玩家名称> <称号币数量> + PlayerManage.addCoin(sender, args); + break; + case "set_coin": // mplt set_coin <玩家名称> <称号币数量> + PlayerManage.setCoin(sender, args); + break; default: return false; } @@ -81,7 +89,7 @@ public class Commands implements TabExecutor { if (args.length == 1) { return Arrays.asList("menu", "all_titles", "my_titles", "shop", "custom_info", "sale_info", "create_sale", "set_sale", "delete_sale", "buy_sale", "use_title", "create_title", - "delete_title", "edit_title_name", "edit_title_desc", "custom_title"); + "delete_title", "edit_title_name", "edit_title_desc", "custom_title", "add_coin", "set_coin"); } if (args.length == 2) { switch (args[0]) { @@ -99,7 +107,11 @@ public class Commands implements TabExecutor { case "set_sale": return Arrays.asList("price", "days", "amount", "end_at", "more_end_at", "less_end_at"); case "custom_title": + case "create_title": return Collections.singletonList("<称号内容>"); + case "add_coin": + case "set_coin": + return PlayerInfoDTO.playerNameList(); default: return null; } @@ -112,6 +124,11 @@ public class Commands implements TabExecutor { return Collections.singletonList("<新的称号描述>"); case "edit_title_name": return Collections.singletonList("<新的称号名称>"); + case "create_title": + return Collections.singletonList("<称号描述>"); + case "add_coin": + case "set_coin": + return Collections.singletonList("<数量>"); default: return null; } diff --git a/src/main/java/cn/lunadeer/miniplayertitle/Events.java b/src/main/java/cn/lunadeer/miniplayertitle/Events.java index 5f93526..7e7f331 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/Events.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/Events.java @@ -1,6 +1,7 @@ package cn.lunadeer.miniplayertitle; import cn.lunadeer.miniplayertitle.dtos.PlayerInfoDTO; +import cn.lunadeer.miniplayertitle.dtos.PlayerTitleDTO; import io.papermc.paper.event.player.AsyncChatEvent; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @@ -15,12 +16,19 @@ public class Events implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { Player bukkitPlayer = event.getPlayer(); - PlayerInfoDTO player = PlayerInfoDTO.get(bukkitPlayer.getUniqueId()); + PlayerInfoDTO player = PlayerInfoDTO.get(bukkitPlayer); if (player == null) { MiniPlayerTitle.notification.error(bukkitPlayer, "获取玩家信息时出现错误,请联系管理员"); return; } - updateName(bukkitPlayer, player.getUsingTitle()); + PlayerTitleDTO title = PlayerTitleDTO.get(bukkitPlayer.getUniqueId(), player.getUsingTitle().getId()); + if (title == null || title.isExpired()) { + MiniPlayerTitle.notification.warn(bukkitPlayer, "你当前使用的称号 %s 已过期", player.getUsingTitle().getTitlePlainText()); + player.setUsingTitle(null); + updateName(bukkitPlayer, null); + } else { + updateName(bukkitPlayer, title.getTitle()); + } } @EventHandler diff --git a/src/main/java/cn/lunadeer/miniplayertitle/commands/PlayerManage.java b/src/main/java/cn/lunadeer/miniplayertitle/commands/PlayerManage.java new file mode 100644 index 0000000..3af2b29 --- /dev/null +++ b/src/main/java/cn/lunadeer/miniplayertitle/commands/PlayerManage.java @@ -0,0 +1,62 @@ +package cn.lunadeer.miniplayertitle.commands; + +import cn.lunadeer.miniplayertitle.MiniPlayerTitle; +import cn.lunadeer.miniplayertitle.dtos.PlayerInfoDTO; +import org.bukkit.command.CommandSender; + +import static cn.lunadeer.miniplayertitle.commands.Apis.notOpOrConsole; + +public class PlayerManage { + + /** + * 给玩家添加称号币 + * mplt add_coin <玩家名称> <称号币数量> + * + * @param sender CommandSender + * @param args String[] + */ + public static void addCoin(CommandSender sender, String[] args) { + if (notOpOrConsole(sender)) return; + try { + PlayerInfoDTO playerInfo = PlayerInfoDTO.get(args[1]); + if (playerInfo == null) { + MiniPlayerTitle.notification.error(sender, "玩家不存在"); + return; + } + if (playerInfo.addCoin(Integer.parseInt(args[2]))) { + MiniPlayerTitle.notification.info(sender, "成功给玩家 %s 添加 %s 称号币", playerInfo.getLastUseName(), args[2]); + MiniPlayerTitle.notification.info(sender, "玩家 %s 当前余额 %d 称号币", playerInfo.getLastUseName(), playerInfo.getCoin()); + } else { + MiniPlayerTitle.notification.error(sender, "给玩家添加称号币失败,详细错误请查看控制台日志"); + } + } catch (Exception e) { + MiniPlayerTitle.notification.error(sender, "给玩家添加称号币时出错:%s", e.getMessage()); + } + } + + /** + * 给玩家设置称号币余额 + * mplt set_coin <玩家名称> <称号币数量> + * + * @param sender CommandSender + * @param args String[] + */ + public static void setCoin(CommandSender sender, String[] args) { + if (notOpOrConsole(sender)) return; + try { + PlayerInfoDTO playerInfo = PlayerInfoDTO.get(args[1]); + if (playerInfo == null) { + MiniPlayerTitle.notification.error(sender, "玩家不存在"); + return; + } + if (playerInfo.setCoin(Integer.parseInt(args[2]))) { + MiniPlayerTitle.notification.info(sender, "成功给玩家 %s 设置 %s 称号币", playerInfo.getLastUseName(), args[2]); + MiniPlayerTitle.notification.info(sender, "玩家 %s 当前余额 %d 称号币", playerInfo.getLastUseName(), playerInfo.getCoin()); + } else { + MiniPlayerTitle.notification.error(sender, "给玩家设置称号币失败,详细错误请查看控制台日志"); + } + } catch (Exception e) { + MiniPlayerTitle.notification.error(sender, "给玩家设置称号币时出错:%s", e.getMessage()); + } + } +} diff --git a/src/main/java/cn/lunadeer/miniplayertitle/commands/TitleManage.java b/src/main/java/cn/lunadeer/miniplayertitle/commands/TitleManage.java index 86a6dd1..911d189 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/commands/TitleManage.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/commands/TitleManage.java @@ -10,24 +10,26 @@ import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.time.LocalDateTime; + import static cn.lunadeer.miniplayertitle.commands.Apis.notOpOrConsole; import static cn.lunadeer.miniplayertitle.commands.Apis.updateName; public class TitleManage { /** * 创建称号 - * mplt create_title <称号名称> <称号描述> + * mplt create_title <称号名称> [称号描述] * * @param sender CommandSender * @param args String[] */ public static void createTitle(CommandSender sender, String[] args) { if (notOpOrConsole(sender)) return; - if (args.length != 3) { - MiniPlayerTitle.notification.warn(sender, "用法: /mplt create_title <称号名称> <称号描述>"); + if (args.length < 2) { + MiniPlayerTitle.notification.warn(sender, "用法: /mplt create_title <称号名称> [称号描述]"); return; } - TitleDTO title = TitleDTO.create(args[1], args[2]); + TitleDTO title = TitleDTO.create(args[1], args.length == 3 ? args[2] : "这是一个管理员创建的称号"); if (title != null) { MiniPlayerTitle.notification.info(sender, Component.text("成功创建称号: [" + title.getId() + "]").append(title.getTitleColored())); AllTitles.show(sender, new String[]{"all_titles"}); @@ -158,6 +160,12 @@ public class TitleManage { MiniPlayerTitle.notification.error(sender, "获取玩家信息时出现错误"); return; } + if (title.getExpireAt().isBefore(LocalDateTime.now())) { + MiniPlayerTitle.notification.error(sender, "称号 %s 已过期", title.getTitle().getTitlePlainText()); + playerInfo.setUsingTitle(null); + updateName(player, null); + return; + } boolean success = playerInfo.setUsingTitle(title.getTitle()); if (success) { updateName((Player) sender, title.getTitle()); diff --git a/src/main/java/cn/lunadeer/miniplayertitle/dtos/PlayerInfoDTO.java b/src/main/java/cn/lunadeer/miniplayertitle/dtos/PlayerInfoDTO.java index 63bb94c..9d1400b 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/dtos/PlayerInfoDTO.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/dtos/PlayerInfoDTO.java @@ -1,46 +1,93 @@ package cn.lunadeer.miniplayertitle.dtos; import cn.lunadeer.miniplayertitle.MiniPlayerTitle; +import org.bukkit.entity.Player; +import javax.annotation.Nullable; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; public class PlayerInfoDTO { private UUID uuid; private Integer coin; private TitleDTO using_title; + private String last_use_name; public static PlayerInfoDTO get(UUID uuid) { String sql = ""; - sql = "SELECT uuid, coin, using_title_id FROM mplt_player_info WHERE uuid = ?;"; + sql = "SELECT uuid, coin, using_title_id, last_use_name FROM mplt_player_info WHERE uuid = ?;"; try (ResultSet rs = MiniPlayerTitle.database.query(sql, uuid)) { if (rs.next()) return getPlayerInfoDTO(rs); - else return create(uuid); + else return null; } catch (Exception e) { MiniPlayerTitle.database.handleDatabaseError("获取玩家信息失败", e, sql); } return null; } - private static PlayerInfoDTO create(UUID uuid) { + public static PlayerInfoDTO get(Player player) { + PlayerInfoDTO info = get(player.getUniqueId()); + if (info == null) { + info = create(player); + if (info == null) { + MiniPlayerTitle.logger.err("创建玩家信息时失败"); + return null; + } + } else { + info = updateName(player); + if (info == null) { + MiniPlayerTitle.logger.err("更新玩家名称时失败"); + return null; + } + } + return info; + } + + public static PlayerInfoDTO get(String name) { String sql = ""; - sql = "INSERT INTO mplt_player_info (uuid, coin) " + - "VALUES (?, ?) " + + sql = "SELECT uuid, coin, using_title_id, last_use_name FROM mplt_player_info WHERE last_use_name = ?;"; + try (ResultSet rs = MiniPlayerTitle.database.query(sql, name)) { + if (rs.next()) return getPlayerInfoDTO(rs); + else return null; + } catch (Exception e) { + MiniPlayerTitle.database.handleDatabaseError("获取玩家信息失败", e, sql); + } + return null; + } + + private static PlayerInfoDTO create(Player player) { + String sql = ""; + sql = "INSERT INTO mplt_player_info (uuid, coin, last_use_name) " + + "VALUES (?, ?, ?) " + "ON CONFLICT DO NOTHING;"; - try (ResultSet rs = MiniPlayerTitle.database.query(sql, uuid, MiniPlayerTitle.config.getDefaultCoin())) { - return get(uuid); + try (ResultSet rs = MiniPlayerTitle.database.query(sql, player.getUniqueId(), MiniPlayerTitle.config.getDefaultCoin(), player.getName())) { + return get(player.getUniqueId()); } catch (Exception e) { MiniPlayerTitle.database.handleDatabaseError("创建玩家信息失败", e, sql); } return null; } + private static PlayerInfoDTO updateName(Player player) { + String sql = ""; + sql = "UPDATE mplt_player_info SET last_use_name = ? WHERE uuid = ?;"; + try (ResultSet rs = MiniPlayerTitle.database.query(sql, player.getName(), player.getUniqueId())) { + return get(player.getUniqueId()); + } catch (Exception e) { + MiniPlayerTitle.database.handleDatabaseError("更新玩家名称失败", e, sql); + } + return null; + } + private static PlayerInfoDTO getPlayerInfoDTO(ResultSet rs) throws SQLException { PlayerInfoDTO playerInfoDTO = new PlayerInfoDTO(); playerInfoDTO.uuid = UUID.fromString(rs.getString("uuid")); playerInfoDTO.coin = rs.getInt("coin"); playerInfoDTO.using_title = TitleDTO.get(rs.getInt("using_title_id")); + playerInfoDTO.last_use_name = rs.getString("last_use_name"); return playerInfoDTO; } @@ -52,10 +99,15 @@ public class PlayerInfoDTO { return using_title; } - public boolean setUsingTitle(TitleDTO title) { + public String getLastUseName() { + return last_use_name; + } + + public boolean setUsingTitle(@Nullable TitleDTO title) { String sql = ""; sql = "UPDATE mplt_player_info SET using_title_id = ? WHERE uuid = ?;"; - try (ResultSet rs = MiniPlayerTitle.database.query(sql, title.getId(), uuid)) { + try (ResultSet rs = MiniPlayerTitle.database.query(sql, title == null ? -1 : title.getId(), uuid)) { + this.using_title = title == null ? TitleDTO.get(-1) : title; return true; } catch (Exception e) { MiniPlayerTitle.database.handleDatabaseError("设置玩家使用称号失败", e, sql); @@ -79,4 +131,18 @@ public class PlayerInfoDTO { return false; } + public static List playerNameList() { + String sql = ""; + sql = "SELECT last_use_name FROM mplt_player_info;"; + List names = new ArrayList<>(); + try (ResultSet rs = MiniPlayerTitle.database.query(sql)) { + while (rs.next()) { + names.add(rs.getString("last_use_name")); + } + } catch (Exception e) { + MiniPlayerTitle.database.handleDatabaseError("获取玩家名称列表失败", e, sql); + } + return names; + } + } diff --git a/src/main/java/cn/lunadeer/miniplayertitle/dtos/PlayerTitleDTO.java b/src/main/java/cn/lunadeer/miniplayertitle/dtos/PlayerTitleDTO.java index 9310bad..8e153e8 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/dtos/PlayerTitleDTO.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/dtos/PlayerTitleDTO.java @@ -82,6 +82,20 @@ public class PlayerTitleDTO { return null; } + public static PlayerTitleDTO get(UUID player, Integer title) { + String sql = ""; + sql += "SELECT id, player_uuid, title_id, expire_at_y, expire_at_m, expire_at_d FROM mplt_player_title " + + "WHERE player_uuid = ? AND title_id = ?;"; + try (ResultSet rs = MiniPlayerTitle.database.query(sql, player, title)) { + if (rs.next()) { + return getRs(rs); + } + } catch (Exception e) { + MiniPlayerTitle.database.handleDatabaseError("获取玩家称号失败", e, sql); + } + return null; + } + private static PlayerTitleDTO getRs(ResultSet rs) throws SQLException { PlayerTitleDTO playerTitle = new PlayerTitleDTO(); playerTitle.id = rs.getInt("id"); diff --git a/src/main/java/cn/lunadeer/miniplayertitle/tuis/Menu.java b/src/main/java/cn/lunadeer/miniplayertitle/tuis/Menu.java index 759f32a..d415009 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/tuis/Menu.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/tuis/Menu.java @@ -4,6 +4,7 @@ import cn.lunadeer.minecraftpluginutils.stui.ListView; import cn.lunadeer.minecraftpluginutils.stui.components.Button; import cn.lunadeer.minecraftpluginutils.stui.components.Line; import cn.lunadeer.miniplayertitle.MiniPlayerTitle; +import cn.lunadeer.miniplayertitle.dtos.PlayerInfoDTO; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -16,6 +17,14 @@ public class Menu { Player player = playerOnly(sender); if (player == null) return; + + PlayerInfoDTO playerInfo = PlayerInfoDTO.get(player.getUniqueId()); + if (playerInfo == null) { + MiniPlayerTitle.notification.error(player, "获取玩家信息时出现错误"); + return; + } + Line balance = Line.create() + .append("称号币余额: ").append(playerInfo.getCoin().toString()); Line backpack = Line.create() .append(Button.create("称号背包").setExecuteCommand("/mplt my_titles").build()).append("查看你拥有的称号"); Line shop = Line.create() @@ -28,6 +37,8 @@ public class Menu { ListView view = ListView.create(10, "/mplt"); view.title("称号系统") .navigator(Line.create().append("主菜单")) + .add(balance) + .add(Line.create()) .add(backpack) .add(shop) .add(manual); diff --git a/src/main/java/cn/lunadeer/miniplayertitle/tuis/MyTitles.java b/src/main/java/cn/lunadeer/miniplayertitle/tuis/MyTitles.java index 11cc344..4edec16 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/tuis/MyTitles.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/tuis/MyTitles.java @@ -9,6 +9,7 @@ import cn.lunadeer.miniplayertitle.dtos.PlayerTitleDTO; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.time.LocalDateTime; import java.util.List; import java.util.Objects; @@ -41,6 +42,8 @@ public class MyTitles { .append(title.getTitle().getTitleColored()); if (title.getExpireAt() == null) { line.append("永久"); + } else if (title.getExpireAt().isBefore(LocalDateTime.now())) { + line.append("已过期"); } else { line.append("有效期至: " + title.getExpireAt().getYear() + "年" + title.getExpireAt().getMonthValue() + "月" + title.getExpireAt().getDayOfMonth() + "日"); } diff --git a/src/main/java/cn/lunadeer/miniplayertitle/tuis/SaleInfo.java b/src/main/java/cn/lunadeer/miniplayertitle/tuis/SaleInfo.java index 468296d..8b167d7 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/tuis/SaleInfo.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/tuis/SaleInfo.java @@ -7,6 +7,7 @@ import cn.lunadeer.minecraftpluginutils.stui.components.NumChanger; import cn.lunadeer.miniplayertitle.MiniPlayerTitle; import cn.lunadeer.miniplayertitle.dtos.TitleDTO; import cn.lunadeer.miniplayertitle.dtos.TitleShopDTO; +import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -100,9 +101,9 @@ public class SaleInfo { } else { if (player.isOp()) { end_at.append(Button.create("<<").setPreSufIx("", "").setHoverText("提前10天").setExecuteCommand("/mplt set_sale less_end_at " + titleShop.getId() + " 10 " + page).build() - .append(Button.create("-").setPreSufIx("", "").setHoverText("提前1天").setExecuteCommand("/mplt set_sale less_end_at " + titleShop.getId() + " 1 " + page).build())); - end_at.append(titleShop.getSaleEndAt().getYear() + "年" + titleShop.getSaleEndAt().getMonthValue() + "月" + titleShop.getSaleEndAt().getDayOfMonth() + "日"); - end_at.append(Button.create("+").setPreSufIx("", "").setHoverText("延后1天").setExecuteCommand("/mplt set_sale more_end_at " + titleShop.getId() + " 1 " + page).build() + .append(Button.create("-").setPreSufIx("", "").setHoverText("提前1天").setExecuteCommand("/mplt set_sale less_end_at " + titleShop.getId() + " 1 " + page).build()) + .append(Component.text(titleShop.getSaleEndAt().getYear() + "年" + titleShop.getSaleEndAt().getMonthValue() + "月" + titleShop.getSaleEndAt().getDayOfMonth() + "日")) + .append(Button.create("+").setPreSufIx("", "").setHoverText("延后1天").setExecuteCommand("/mplt set_sale more_end_at " + titleShop.getId() + " 1 " + page).build()) .append(Button.create(">>").setPreSufIx("", "").setHoverText("延后10天").setExecuteCommand("/mplt set_sale more_end_at " + titleShop.getId() + " 10 " + page).build())); end_at.append(Button.create("转为常驻").setExecuteCommand("/mplt set_sale end_at " + titleShop.getId() + " -1:-1:-1 " + page).build()); } else { diff --git a/src/main/java/cn/lunadeer/miniplayertitle/tuis/Shop.java b/src/main/java/cn/lunadeer/miniplayertitle/tuis/Shop.java index 09cb480..13af849 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/tuis/Shop.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/tuis/Shop.java @@ -33,6 +33,7 @@ public class Shop { continue; } Line line = Line.create() + .append(title.getId().toString()) .append(title.getTitle().getTitleColored()) .append(Button.createGreen("详情").setExecuteCommand("/mplt sale_info " + title.getId()).build()); view.add(line); diff --git a/src/main/java/cn/lunadeer/miniplayertitle/utils/DatabaseTables.java b/src/main/java/cn/lunadeer/miniplayertitle/utils/DatabaseTables.java index 4a60ba6..bf7ba6c 100644 --- a/src/main/java/cn/lunadeer/miniplayertitle/utils/DatabaseTables.java +++ b/src/main/java/cn/lunadeer/miniplayertitle/utils/DatabaseTables.java @@ -106,5 +106,7 @@ public class DatabaseTables { "'default' " + ") ON CONFLICT (id) DO NOTHING;"; MiniPlayerTitle.database.query(sql); + + MiniPlayerTitle.database.addColumnIfNotExists("mplt_player_info", "last_use_name", "TEXT NOT NULL DEFAULT 'null'"); } }