From 52d1e19501d427b2cee781ef4f9eb9fc9e103070 Mon Sep 17 00:00:00 2001 From: zhangyuheng Date: Fri, 5 Jan 2024 17:29:38 +0800 Subject: [PATCH] finish basic shop --- .../java/cn/lunadeer/newbtitle/Events.java | 4 +- .../java/cn/lunadeer/newbtitle/NewbTitle.java | 8 ++ .../java/cn/lunadeer/newbtitle/SaleTitle.java | 45 +++---- src/main/java/cn/lunadeer/newbtitle/Shop.java | 105 ++++++++++++++++ .../java/cn/lunadeer/newbtitle/XPlayer.java | 56 ++++++++- .../lunadeer/newbtitle/utils/STUI/Line.java | 67 ++++++++++ .../lunadeer/newbtitle/utils/STUI/View.java | 115 ++++++++++++++++++ 7 files changed, 375 insertions(+), 25 deletions(-) create mode 100644 src/main/java/cn/lunadeer/newbtitle/utils/STUI/Line.java create mode 100644 src/main/java/cn/lunadeer/newbtitle/utils/STUI/View.java diff --git a/src/main/java/cn/lunadeer/newbtitle/Events.java b/src/main/java/cn/lunadeer/newbtitle/Events.java index 4de2d62..3832aa6 100644 --- a/src/main/java/cn/lunadeer/newbtitle/Events.java +++ b/src/main/java/cn/lunadeer/newbtitle/Events.java @@ -1,4 +1,6 @@ package cn.lunadeer.newbtitle; -public class Events { +import org.bukkit.event.Listener; + +public class Events implements Listener { } diff --git a/src/main/java/cn/lunadeer/newbtitle/NewbTitle.java b/src/main/java/cn/lunadeer/newbtitle/NewbTitle.java index d64acce..ec9fb7d 100644 --- a/src/main/java/cn/lunadeer/newbtitle/NewbTitle.java +++ b/src/main/java/cn/lunadeer/newbtitle/NewbTitle.java @@ -1,9 +1,13 @@ package cn.lunadeer.newbtitle; import cn.lunadeer.newbtitle.utils.ConfigManager; +import cn.lunadeer.newbtitle.utils.XLogger; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; +import java.util.Objects; + public final class NewbTitle extends JavaPlugin { @Override @@ -12,7 +16,11 @@ public final class NewbTitle extends JavaPlugin { instance = this; config = new ConfigManager(instance); + Bukkit.getPluginManager().registerEvents(new Events(), this); + Objects.requireNonNull(Bukkit.getPluginCommand("NewbTitle")).setExecutor(new Commands()); + Objects.requireNonNull(Bukkit.getPluginCommand("NewbTitle")).setTabCompleter(new Commands()); + XLogger.info("NewbTitle 称号插件已加载"); } @Override diff --git a/src/main/java/cn/lunadeer/newbtitle/SaleTitle.java b/src/main/java/cn/lunadeer/newbtitle/SaleTitle.java index fc9ed76..c371801 100644 --- a/src/main/java/cn/lunadeer/newbtitle/SaleTitle.java +++ b/src/main/java/cn/lunadeer/newbtitle/SaleTitle.java @@ -23,50 +23,48 @@ public class SaleTitle extends Title { this._sale_end_at = sale_end_at; } - public static SaleTitle create(Integer title_id) { - String sql = ""; - sql += "INSERT INTO nt_title_shop (title_id, price, days, amount, sale_end_at) "; - sql += "VALUES (" + title_id + ", 0, 0, -1, CURRENT_TIMESTAMP) "; - sql += "RETURNING id;"; - ResultSet rs = Database.query(sql); - try { - if (rs != null && rs.next()) { - Integer id = rs.getInt("id"); - return new SaleTitle(id, title_id, 0, 0, -1, System.currentTimeMillis()); - } - } catch (Exception e) { - XLogger.err("SaleTitle create failed: " + e.getMessage()); - } - return null; - } - public Integer getPrice() { return this._price; } - public void setPrice(Integer price) { + private void setPrice(Integer price) { this._price = price; this.save(); } + public static void setPrice(Integer id, Integer price) { + SaleTitle title = Shop.getSaleTitles().get(id); + title.setPrice(price); + } + public Integer getDays() { return this._days; } - public void setDays(Integer days) { + private void setDays(Integer days) { this._days = days; this.save(); } + public static void setDays(Integer id, Integer days) { + SaleTitle title = Shop.getSaleTitles().get(id); + title.setDays(days); + } + public Integer getAmount() { return this._amount; } - public void setAmount(Integer amount) { + private void setAmount(Integer amount) { this._amount = amount; this.save(); } + public static void setAmount(Integer id, Integer amount) { + SaleTitle title = Shop.getSaleTitles().get(id); + title.setAmount(amount); + } + public String getSaleEndAt() { if (this._sale_end_at == -1L) { return "常驻"; @@ -77,11 +75,16 @@ public class SaleTitle extends Title { } } - public void setSaleEndAt(Long sale_end_at) { + private void setSaleEndAt(Long sale_end_at) { this._sale_end_at = sale_end_at; this.save(); } + public static void setSaleEndAt(Integer id, Long sale_end_at) { + SaleTitle title = Shop.getSaleTitles().get(id); + title.setSaleEndAt(sale_end_at); + } + public Boolean isSaleExpired() { if (this._sale_end_at == -1L) { return false; diff --git a/src/main/java/cn/lunadeer/newbtitle/Shop.java b/src/main/java/cn/lunadeer/newbtitle/Shop.java index 1b35de8..10c6984 100644 --- a/src/main/java/cn/lunadeer/newbtitle/Shop.java +++ b/src/main/java/cn/lunadeer/newbtitle/Shop.java @@ -1,4 +1,109 @@ package cn.lunadeer.newbtitle; +import cn.lunadeer.newbtitle.utils.Database; +import cn.lunadeer.newbtitle.utils.Notification; +import cn.lunadeer.newbtitle.utils.STUI.Line; +import cn.lunadeer.newbtitle.utils.STUI.View; +import cn.lunadeer.newbtitle.utils.XLogger; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; +import org.bukkit.entity.Player; + +import java.sql.ResultSet; +import java.util.HashMap; +import java.util.Map; + public class Shop { + public static void open(Player player, Integer page) { + Line header = Line.create(); + header.set(Line.Slot.LEFT, "称号") + .set(Line.Slot.MIDDLE, "价格|天|剩余") + .set(Line.Slot.RIGHT, "操作"); + + Map titles = getSaleTitles(); + int offset = (page - 1) * 4; + if (offset >= titles.size() || offset < 0) { + Notification.error(player, "页数超出范围"); + return; + } + View view = View.create(); + view.title("|| 称号商店 ||") + .set(View.Slot.SUBTITLE, header); + for (int i = offset; i < offset + 4; i++) { + if (i >= titles.size()) { + break; + } + SaleTitle title = titles.get(i); + Line line = Line.create(); + TextComponent buy_button = Component.text("购买") + .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/nt shop buy " + title.getId())); + line.set(Line.Slot.LEFT, (TextComponent) title.getTitle()) + .set(Line.Slot.MIDDLE, title.getPrice() + "|" + + (title.getDays() < 0 ?"∞" : title.getDays()) + "|" + + (title.getAmount() < 0 ? "∞" : title.getAmount())) + .set(Line.Slot.RIGHT, buy_button); + view.set(View.Slot.LINE_1, line); + } + Line action_bar = Line.create(); + TextComponent previous_button = Component.text("上一页") + .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/nt shop " + (page - 1))); + TextComponent next_button = Component.text("下一页") + .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/nt shop " + (page + 1))); + action_bar.set(Line.Slot.MIDDLE, previous_button) + .set(Line.Slot.RIGHT, next_button); + view.set(View.Slot.ACTIONBAR, action_bar); + view.showOn(player); + } + + public static void addTitle(Integer title_id) { + String sql = ""; + sql += "INSERT INTO nt_title_shop (title_id, price, days, amount, sale_end_at) "; + sql += "VALUES (" + title_id + ", 0, 0, -1, CURRENT_TIMESTAMP) "; + sql += "RETURNING id;"; + ResultSet rs = Database.query(sql); + try { + if (rs != null && rs.next()) { + Integer id = rs.getInt("id"); + SaleTitle title = new SaleTitle(id, title_id, 0, 0, -1, System.currentTimeMillis()); + } + } catch (Exception e) { + XLogger.err("SaleTitle create failed: " + e.getMessage()); + } + } + + public static void deleteTitle(Integer id) { + String sql = ""; + sql += "DELETE FROM nt_title_shop WHERE id = " + id + ";"; + Database.query(sql); + } + + public static Map getSaleTitles() { + String sql = ""; + sql += "SELECT "; + sql += "id, "; + sql += "title_id, "; + sql += "price, "; + sql += "days, "; + sql += "amount, "; + sql += "sale_end_at"; + sql += "FROM nt_title_shop;"; + ResultSet rs = Database.query(sql); + Map titles = new HashMap<>(); + try { + while (rs != null && rs.next()) { + Integer id = rs.getInt("id"); + Integer title_id = rs.getInt("title_id"); + Integer price = rs.getInt("price"); + Integer days = rs.getInt("days"); + Integer amount = rs.getInt("amount"); + Long sale_end_at = rs.getLong("sale_end_at"); + SaleTitle title = new SaleTitle(id, title_id, price, days, amount, sale_end_at); + titles.put(id, title); + } + } catch (Exception e) { + XLogger.err("XPlayer getTitles failed: " + e.getMessage()); + } + return titles; + } } diff --git a/src/main/java/cn/lunadeer/newbtitle/XPlayer.java b/src/main/java/cn/lunadeer/newbtitle/XPlayer.java index b935d94..8f7f67a 100644 --- a/src/main/java/cn/lunadeer/newbtitle/XPlayer.java +++ b/src/main/java/cn/lunadeer/newbtitle/XPlayer.java @@ -2,12 +2,18 @@ package cn.lunadeer.newbtitle; import cn.lunadeer.newbtitle.utils.Database; import cn.lunadeer.newbtitle.utils.Notification; +import cn.lunadeer.newbtitle.utils.STUI.Line; +import cn.lunadeer.newbtitle.utils.STUI.View; import cn.lunadeer.newbtitle.utils.XLogger; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; import org.bukkit.entity.Player; import java.sql.ResultSet; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.UUID; public class XPlayer { @@ -21,7 +27,47 @@ public class XPlayer { _titles = getTitles(player.getUniqueId()); _current_title_id = getCurrentTitleId(player.getUniqueId()); _coin = getCoin(player.getUniqueId()); - applyCurrentTitle(); + updateUsingTitle(_current_title_id); + } + + public void openBackpack(Integer page) { + Line header = Line.create(); + header.set(Line.Slot.LEFT, "称号") + .set(Line.Slot.MIDDLE, "到期时间") + .set(Line.Slot.RIGHT, "操作"); + + Map titles = getTitles(_player.getUniqueId()); + int offset = (page - 1) * 4; + if (offset >= titles.size() || offset < 0) { + Notification.error(_player, "页数超出范围"); + return; + } + View view = View.create(); + view.title("|| 我的称号 ||") + .set(View.Slot.SUBTITLE, header); + for (int i = offset; i < offset + 4; i++) { + if (i >= titles.size()) { + break; + } + PlayerTitle title = titles.get(i); + Line line = Line.create(); + boolean is_using = Objects.equals(title.getId(), _current_title_id); + TextComponent buy_button = Component.text(is_using ? "卸下" : "使用") + .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/nt use " + (is_using ? -1 : title.getId()))); + line.set(Line.Slot.LEFT, (TextComponent) title.getTitle()) + .set(Line.Slot.MIDDLE, title.getExpireAt()) + .set(Line.Slot.RIGHT, buy_button); + view.set(View.Slot.LINE_1, line); + } + Line action_bar = Line.create(); + TextComponent previous_button = Component.text("上一页") + .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/nt list " + (page - 1))); + TextComponent next_button = Component.text("下一页") + .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/nt list " + (page + 1))); + action_bar.set(Line.Slot.MIDDLE, previous_button) + .set(Line.Slot.RIGHT, next_button); + view.set(View.Slot.ACTIONBAR, action_bar); + view.showOn(_player); } public void updateUsingTitle(Integer title_id) { @@ -42,13 +88,13 @@ public class XPlayer { return; } if (!_titles.containsKey(_current_title_id)) { - Notification.error(_player, "你没有这个称号"); + Notification.error(_player, "称号 " + _current_title_id + " 显示错误"); _current_title_id = -1; return; } PlayerTitle title = _titles.get(_current_title_id); if (title.isExpired()) { - Notification.error(_player, "此称号已经过期"); + Notification.error(_player, "称号 " + title.getTitle() + " 已过期"); _current_title_id = -1; return; } @@ -160,14 +206,17 @@ public class XPlayer { return; } set_coin(_coin - title.getPrice()); + Notification.info(_player, "成功购买称号: " + title.getTitle()); if (title.getDays() == -1) { title_bought.setExpireAtTimestamp(-1L); return; } if (title_bought.isExpired()) { title_bought.setExpireAtTimestamp(System.currentTimeMillis() + title.getDays() * 24 * 60 * 60 * 1000L); + Notification.info(_player, "称号 " + title.getTitle() + " 已重新激活,有效期至 " + title_bought.getExpireAt()); } else { title_bought.setExpireAtTimestamp(title_bought.getExpireAtTimestamp() + title.getDays() * 24 * 60 * 60 * 1000L); + Notification.info(_player, "称号 " + title.getTitle() + " 已续期至 " + title_bought.getExpireAt()); } } @@ -177,5 +226,6 @@ public class XPlayer { } PlayerTitle title = _titles.get(title_id); title.setExpireAtTimestamp(expire_at); + Notification.info(_player, "获得称号: " + title.getTitle() + ",有效期至 " + title.getExpireAt()); } } diff --git a/src/main/java/cn/lunadeer/newbtitle/utils/STUI/Line.java b/src/main/java/cn/lunadeer/newbtitle/utils/STUI/Line.java new file mode 100644 index 0000000..3f50aec --- /dev/null +++ b/src/main/java/cn/lunadeer/newbtitle/utils/STUI/Line.java @@ -0,0 +1,67 @@ +package cn.lunadeer.newbtitle.utils.STUI; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; + + +public class Line { + public enum Slot { + LEFT, + MIDDLE, + RIGHT + } + private TextComponent left_elements; + private TextComponent middle_elements; + private TextComponent right_elements; + + + public Line() { + this.left_elements = Component.text().build(); + this.middle_elements = Component.text().build(); + this.right_elements = Component.text().build(); + } + + public TextComponent build() { + TextComponent gap = Component.text(" "); + return Component.text().append(left_elements) + .append(gap) + .append(middle_elements) + .append(gap) + .append(right_elements).build(); + } + + public static Line create() { + return new Line(); + } + + public Line set(Slot slot, TextComponent component) { + switch (slot) { + case LEFT: + this.left_elements = component; + break; + case MIDDLE: + this.middle_elements = component; + break; + case RIGHT: + this.right_elements = component; + break; + } + return this; + } + + public Line set(Slot slot, String component) { + switch (slot) { + case LEFT: + this.left_elements = Component.text(component); + break; + case MIDDLE: + this.middle_elements = Component.text(component); + break; + case RIGHT: + this.right_elements = Component.text(component); + break; + } + return this; + } + +} diff --git a/src/main/java/cn/lunadeer/newbtitle/utils/STUI/View.java b/src/main/java/cn/lunadeer/newbtitle/utils/STUI/View.java new file mode 100644 index 0000000..3085c99 --- /dev/null +++ b/src/main/java/cn/lunadeer/newbtitle/utils/STUI/View.java @@ -0,0 +1,115 @@ +package cn.lunadeer.newbtitle.utils.STUI; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.entity.Player; + +public class View { + public enum Slot { + SUBTITLE, + LINE_1, + LINE_2, + LINE_3, + LINE_4, + ACTIONBAR + } + + protected TextComponent title; + protected TextComponent subtitle; + protected TextComponent content_line1; + protected TextComponent content_line2; + protected TextComponent content_line3; + protected TextComponent content_line4; + protected TextComponent actionbar; + + public void showOn(Player player){ + player.sendMessage(title); + player.sendMessage(subtitle); + player.sendMessage(content_line1); + player.sendMessage(content_line2); + player.sendMessage(content_line3); + player.sendMessage(content_line4); + player.sendActionBar(actionbar); + } + + public static View create(){ + return new View(); + } + + public View title(String title){ + this.title = Component.text(title); + return this; + } + + public View set(Slot line, TextComponent component){ + switch (line){ + case SUBTITLE: + this.subtitle = component; + break; + case LINE_1: + this.content_line1 = component; + break; + case LINE_2: + this.content_line2 = component; + break; + case LINE_3: + this.content_line3 = component; + break; + case LINE_4: + this.content_line4 = component; + break; + case ACTIONBAR: + this.actionbar = component; + break; + } + return this; + } + + public View set(Slot line, String component){ + switch (line){ + case SUBTITLE: + this.subtitle = Component.text(component); + break; + case LINE_1: + this.content_line1 = Component.text(component); + break; + case LINE_2: + this.content_line2 = Component.text(component); + break; + case LINE_3: + this.content_line3 = Component.text(component); + break; + case LINE_4: + this.content_line4 = Component.text(component); + break; + case ACTIONBAR: + this.actionbar = Component.text(component); + break; + } + return this; + } + + public View set(Slot line, Line component){ + switch (line){ + case SUBTITLE: + this.subtitle = component.build(); + break; + case LINE_1: + this.content_line1 = component.build(); + break; + case LINE_2: + this.content_line2 = component.build(); + break; + case LINE_3: + this.content_line3 = component.build(); + break; + case LINE_4: + this.content_line4 = component.build(); + break; + case ACTIONBAR: + this.actionbar = component.build(); + break; + } + return this; + } +}