From d4b0aa1e4bab5fa8b7c947a7547cecdc853c0a16 Mon Sep 17 00:00:00 2001
From: yaohunya <1763917516@qq.com>
Date: Tue, 12 Aug 2025 01:14:12 +0800
Subject: [PATCH] 1.0.0
---
pom.xml | 37 +++
src/main/java/com/yaohun/trade/TradeMain.java | 96 ++++++++
.../java/com/yaohun/trade/config/Config.java | 48 ++++
.../com/yaohun/trade/data/InviteData.java | 36 +++
.../java/com/yaohun/trade/data/TradeData.java | 221 ++++++++++++++++++
.../com/yaohun/trade/data/TradeLogData.java | 73 ++++++
.../java/com/yaohun/trade/gui/GuiMain.java | 70 ++++++
.../java/com/yaohun/trade/gui/TradeGui.java | 85 +++++++
.../com/yaohun/trade/listener/BreakBlcok.java | 52 +++++
.../yaohun/trade/listener/ClickInventory.java | 205 ++++++++++++++++
.../yaohun/trade/listener/PlayerListener.java | 30 +++
.../yaohun/trade/manage/InviteManager.java | 187 +++++++++++++++
.../com/yaohun/trade/manage/LogsManager.java | 61 +++++
.../com/yaohun/trade/util/MessageUtil.java | 31 +++
.../java/com/yaohun/trade/util/StackUtil.java | 23 ++
.../com/yaohun/trade/util/TradeState.java | 7 +
src/main/resources/DemonTrade.yml | 28 +++
src/main/resources/config.yml | 4 +
src/main/resources/plugin.yml | 8 +
19 files changed, 1302 insertions(+)
create mode 100644 pom.xml
create mode 100644 src/main/java/com/yaohun/trade/TradeMain.java
create mode 100644 src/main/java/com/yaohun/trade/config/Config.java
create mode 100644 src/main/java/com/yaohun/trade/data/InviteData.java
create mode 100644 src/main/java/com/yaohun/trade/data/TradeData.java
create mode 100644 src/main/java/com/yaohun/trade/data/TradeLogData.java
create mode 100644 src/main/java/com/yaohun/trade/gui/GuiMain.java
create mode 100644 src/main/java/com/yaohun/trade/gui/TradeGui.java
create mode 100644 src/main/java/com/yaohun/trade/listener/BreakBlcok.java
create mode 100644 src/main/java/com/yaohun/trade/listener/ClickInventory.java
create mode 100644 src/main/java/com/yaohun/trade/listener/PlayerListener.java
create mode 100644 src/main/java/com/yaohun/trade/manage/InviteManager.java
create mode 100644 src/main/java/com/yaohun/trade/manage/LogsManager.java
create mode 100644 src/main/java/com/yaohun/trade/util/MessageUtil.java
create mode 100644 src/main/java/com/yaohun/trade/util/StackUtil.java
create mode 100644 src/main/java/com/yaohun/trade/util/TradeState.java
create mode 100644 src/main/resources/DemonTrade.yml
create mode 100644 src/main/resources/config.yml
create mode 100644 src/main/resources/plugin.yml
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..55a04b0
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,37 @@
+
+
+ 4.0.0
+
+ org.example
+ DemonTrade
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+
+ public-rpg
+ https://repo.aurora-pixels.com/repository/public-rpg/
+
+
+
+
+
+ org.spigotmc
+ spigot-api
+ 1.12.2
+
+
+ me.Demon.DemonPlugin
+ DemonAPI
+ 2.2.9
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/yaohun/trade/TradeMain.java b/src/main/java/com/yaohun/trade/TradeMain.java
new file mode 100644
index 0000000..960fbe5
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/TradeMain.java
@@ -0,0 +1,96 @@
+package com.yaohun.trade;
+
+import com.yaohun.trade.config.Config;
+import com.yaohun.trade.data.TradeData;
+import com.yaohun.trade.gui.GuiMain;
+import com.yaohun.trade.listener.BreakBlcok;
+import com.yaohun.trade.listener.ClickInventory;
+import com.yaohun.trade.listener.PlayerListener;
+import com.yaohun.trade.manage.InviteManager;
+import com.yaohun.trade.manage.LogsManager;
+import com.yaohun.trade.util.MessageUtil;
+import org.bukkit.Bukkit;
+import org.bukkit.Sound;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+
+public class TradeMain extends JavaPlugin {
+
+ private static TradeMain instance;
+ private static LogsManager logsManager;
+
+ @Override
+ public void onEnable() {
+ instance = this;
+ Config.reloadConfig(this);
+ logsManager = new LogsManager();
+ getServer().getPluginManager().registerEvents(new GuiMain(), this);
+ getServer().getPluginManager().registerEvents(new BreakBlcok(), this);
+ getServer().getPluginManager().registerEvents(new ClickInventory(), this);
+ getServer().getPluginManager().registerEvents(new PlayerListener(), this);
+ }
+
+ @Override
+ public void onDisable() {
+ getLogsManager().saveAllLog();
+ for (TradeData tradeData : InviteManager.tradeData){
+ tradeData.closeTradeGui(true);
+ }
+ }
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if(args.length == 0){
+ String message = Config.getString("commandUsageInvite");
+ MessageUtil.sendMessage(sender, message, Sound.ENTITY_VILLAGER_NO);
+ return true;
+ }
+ if(args.length == 1) {
+ if ("reload".equalsIgnoreCase(args[0]) && sender.isOp()) {
+ Config.reloadConfig(this);
+ sender.sendMessage("[交易] 配置文件已重载.");
+ return true;
+ }
+ if ("save".equalsIgnoreCase(args[0]) && sender.isOp()) {
+ getLogsManager().saveAllLog();
+ sender.sendMessage("[交易] 正在保存日志数据.");
+ return true;
+ }
+ if ("list".equalsIgnoreCase(args[0]) && sender.isOp()) {
+ sender.sendMessage("[交易] 正在进行的交易:");
+ for (TradeData tradeData : InviteManager.tradeData){
+ sender.sendMessage(" - "+tradeData.getTradeID()+" "+tradeData.getPlayerName()+" <-> "+tradeData.getTargetName());
+ }
+ return true;
+ }
+ if ("accept".equalsIgnoreCase(args[0])) {
+ InviteManager.acceptInvite((Player) sender);
+ return true;
+ }
+ if ("deny".equalsIgnoreCase(args[0])) {
+ InviteManager.denyInvite((Player) sender);
+ return true;
+ }
+ Player player = (Player) sender;
+ String tragetName = args[0];
+ Player target = Bukkit.getPlayer(tragetName);
+ if(target == null || !target.isOnline()){
+ String message = Config.getString("invitePlayerOffline");
+ MessageUtil.sendMessage(player, message, Sound.ENTITY_VILLAGER_NO);
+ return true;
+ }
+ InviteManager.sendInvite(player, target);
+ }
+ return false;
+ }
+
+ public static TradeMain inst() {
+ return instance;
+ }
+
+ public static LogsManager getLogsManager() {
+ return logsManager;
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/config/Config.java b/src/main/java/com/yaohun/trade/config/Config.java
new file mode 100644
index 0000000..4883d96
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/config/Config.java
@@ -0,0 +1,48 @@
+package com.yaohun.trade.config;
+
+import com.yaohun.trade.TradeMain;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.LangData;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.entity.Player;
+
+import java.io.File;
+import java.util.List;
+
+public class Config {
+
+ public static String invTitle = "玩家交易系统";
+ private static LangData langData;
+ private static boolean breakChestEnabled;
+ private static List breakChestWorlds;
+ private static int limitDistance;
+ public static int[] playerButts = new int[]{36,37,38,39};
+ public static int[] targetButts = new int[]{41,42,43,44};
+ public static int[] playerSlots = new int[]{0,1,2,3,9,10,11,12,18,19,20,21,27,28,29,30};
+ public static int[] targetSlots = new int[]{5,6,7,8,14,15,16,17,23,24,25,26,32,33,34,35};
+
+ public static void reloadConfig(TradeMain plugin){
+ langData = DemonAPI.getLangData("DemonTrade");
+ plugin.reloadConfig();
+ plugin.saveConfig();
+ FileConfiguration config = plugin.getConfig();
+ breakChestEnabled = config.getBoolean("BreakChest.enabled");
+ breakChestWorlds = config.getStringList("BreakChest.worlds");
+ limitDistance = config.getInt("LimitDistance",32);
+ }
+
+ public static String getString(String key){
+ return langData.getMessage(key);
+ }
+
+ public static int getLimitDistance() {
+ return limitDistance;
+ }
+
+ public static boolean isBreakChestEnabled(){
+ return breakChestEnabled;
+ }
+ public static boolean isBreakChestWorld(String world){
+ return breakChestWorlds.contains(world);
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/data/InviteData.java b/src/main/java/com/yaohun/trade/data/InviteData.java
new file mode 100644
index 0000000..c6d2137
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/data/InviteData.java
@@ -0,0 +1,36 @@
+package com.yaohun.trade.data;
+
+import org.bukkit.entity.Player;
+
+public class InviteData {
+
+ private Player player;
+ private Player target;
+ private long initiationTime;
+
+ public InviteData(Player player, Player target) {
+ this.player = player;
+ this.target = target;
+ this.initiationTime = System.currentTimeMillis();
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
+
+ public String playerName(){
+ return player.getName();
+ }
+
+ public Player getTarget() {
+ return target;
+ }
+
+ public String targetName(){
+ return target.getName();
+ }
+
+ public boolean isExpired() {
+ return System.currentTimeMillis() - initiationTime > 1000 * 30;
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/data/TradeData.java b/src/main/java/com/yaohun/trade/data/TradeData.java
new file mode 100644
index 0000000..69d6290
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/data/TradeData.java
@@ -0,0 +1,221 @@
+package com.yaohun.trade.data;
+
+import com.yaohun.trade.TradeMain;
+import com.yaohun.trade.util.StackUtil;
+import com.yaohun.trade.config.Config;
+import com.yaohun.trade.util.MessageUtil;
+import com.yaohun.trade.util.TradeState;
+import me.Demon.DemonPlugin.DemonAPI;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class TradeData {
+
+ private final String tradeID = "DATA-"+System.currentTimeMillis();
+ private Player player;
+ private String playerName;
+ private Player target;
+ private String targetName;
+ private boolean isTradeStop;
+ private boolean isTradeBreakTheLaw;
+ private HashMap stateMap = new HashMap<>();
+ private Inventory inventory;
+
+ public TradeData(Player player, Player target,Inventory inventory) {
+ this.player = player;
+ this.playerName = player.getName();
+ stateMap.put(player, TradeState.OPEN);
+ this.target = target;
+ this.targetName = target.getName();
+ stateMap.put(target, TradeState.OPEN);
+ this.inventory = inventory;
+ this.isTradeStop = false;
+ this.isTradeBreakTheLaw = false;
+ }
+
+ public String getTradeID() {
+ return tradeID;
+ }
+
+ public void setTradeBreakTheLaw(boolean tradeBreakTheLaw) {
+ isTradeBreakTheLaw = tradeBreakTheLaw;
+ }
+
+ public boolean isTradeStop() {
+ return isTradeStop;
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
+
+ public String getPlayerName() {
+ return playerName;
+ }
+
+ public Player getTarget() {
+ return target;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public TradeState getState(Player player){
+ return stateMap.get(player);
+ }
+
+ public void setStateData(Player player, TradeState state){
+ stateMap.put(player, state);
+ }
+
+ public boolean isMutualComfirm(){
+ return stateMap.get(player) == TradeState.CONFIRM && stateMap.get(target) == TradeState.CONFIRM;
+ }
+
+ private boolean isInventoryFull(boolean targetD){
+ if(targetD){
+ int slotAmount = 0;
+ for (int slot : Config.playerButts.clone()) {
+ ItemStack stack = inventory.getItem(slot);
+ if (!DemonAPI.itemIsNull(stack)) {
+ slotAmount++;
+ }
+ }
+ if (!DemonAPI.hasEmptyInventorySlots(target, slotAmount)) {
+ return false;
+ }
+ } else {
+ int slotAmount = 0;
+ for (int slot : Config.targetSlots.clone()) {
+ ItemStack stack = inventory.getItem(slot);
+ if (!DemonAPI.itemIsNull(stack)) {
+ slotAmount++;
+ }
+ }
+ if (!DemonAPI.hasEmptyInventorySlots(player, slotAmount)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void successTrade(){
+ if(!isInventoryFull(false)){
+ isTradeBreakTheLaw = true;
+ player.closeInventory();
+ MessageUtil.sendMessage(player,Config.getString("insufficientSpace"), Sound.ENTITY_BLAZE_DEATH);
+ MessageUtil.sendMessage(target,Config.getString("insufficientSpace"), Sound.ENTITY_BLAZE_DEATH);
+ return;
+ }
+ if(!isInventoryFull(true)){
+ isTradeBreakTheLaw = true;
+ target.closeInventory();
+ MessageUtil.sendMessage(player,Config.getString("insufficientSpace2"), Sound.ENTITY_BLAZE_DEATH);
+ MessageUtil.sendMessage(target,Config.getString("insufficientSpace2"), Sound.ENTITY_BLAZE_DEATH);
+ return;
+ }
+ this.isTradeStop = true;
+ int playerCount = 0;
+ List playerList = new ArrayList<>();
+ for (int slot : Config.targetSlots.clone()){
+ ItemStack stack = inventory.getItem(slot);
+ if(!DemonAPI.itemIsNull(stack)){
+ if(stack.getType().equals(Material.STAINED_GLASS_PANE)){
+ continue;
+ }
+ ItemStack item = StackUtil.removeTagStack(stack);
+ int amount = stack.getAmount();
+ String itemName = DemonAPI.getItemName(item);
+ playerList.add(ChatColor.stripColor(itemName)+"x"+amount);
+ DemonAPI.giveItem(player, item);
+ playerCount += amount;
+ }
+ }
+ player.closeInventory();
+
+ int tragetCount = 0;
+ List targetList = new ArrayList<>();
+ for (int slot : Config.playerSlots.clone()){
+ ItemStack stack = inventory.getItem(slot);
+ if(!DemonAPI.itemIsNull(stack)){
+ if(stack.getType().equals(Material.STAINED_GLASS_PANE)){
+ continue;
+ }
+ ItemStack item = StackUtil.removeTagStack(stack);
+ int amount = stack.getAmount();
+ String itemName = DemonAPI.getItemName(item);
+ targetList.add(ChatColor.stripColor(itemName)+"x"+amount);
+ DemonAPI.giveItem(target, item);
+ tragetCount += stack.getAmount();
+ }
+ }
+ target.closeInventory();
+
+ String CompleteTrade = Config.getString("CompleteTrade");
+ String CompleteTrade2 = Config.getString("CompleteTrade2");
+ if(playerCount >= 1) {
+ MessageUtil.sendMessage(player, CompleteTrade.replace("{count}", String.valueOf(playerCount)), Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+ } else {
+ MessageUtil.sendMessage(player, CompleteTrade2, Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+ }
+ if(tragetCount >= 1) {
+ MessageUtil.sendMessage(target, CompleteTrade.replace("{count}", String.valueOf(tragetCount)), Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+ } else {
+ MessageUtil.sendMessage(target, CompleteTrade2, Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+ }
+ TradeLogData logData = new TradeLogData();
+ logData.setTradeID(getTradeID());
+ logData.setPlayerName(player.getName());
+ logData.setTargetName(target.getName());
+ logData.setTradeTime(System.currentTimeMillis());
+ logData.setPlayerList(playerList);
+ logData.setTargetList(targetList);
+ TradeMain.getLogsManager().addLogData(logData);
+ }
+
+ public void closeTradeGui(boolean closePlayer){
+ this.isTradeStop = true;
+ for (int slot : Config.playerSlots.clone()){
+ ItemStack stack = inventory.getItem(slot);
+ if(!DemonAPI.itemIsNull(stack)){
+ if(stack.getType().equals(Material.STAINED_GLASS_PANE)){
+ continue;
+ }
+ ItemStack item = StackUtil.removeTagStack(stack);
+ DemonAPI.giveItem(player, item);
+ }
+ }
+ player.closeInventory();
+ for (int slot : Config.targetSlots.clone()){
+ ItemStack stack = inventory.getItem(slot);
+ if(!DemonAPI.itemIsNull(stack)){
+ if(stack.getType().equals(Material.STAINED_GLASS_PANE)){
+ continue;
+ }
+ ItemStack item = StackUtil.removeTagStack(stack);
+ DemonAPI.giveItem(target, item);
+ }
+ }
+ target.closeInventory();
+ if(!isTradeBreakTheLaw) {
+ String message = Config.getString("closeTheInterface");
+ String message2 = Config.getString("closeTheInterface2");
+ if (closePlayer) {
+ MessageUtil.sendMessage(player, message.replace("{name}",targetName), Sound.ENTITY_VILLAGER_NO);
+ MessageUtil.sendMessage(target, message2.replace("{name}",playerName), Sound.ENTITY_VILLAGER_NO);
+ } else {
+ MessageUtil.sendMessage(target, message.replace("{name}",playerName), Sound.ENTITY_VILLAGER_NO);
+ MessageUtil.sendMessage(player, message2.replace("{name}",targetName), Sound.ENTITY_VILLAGER_NO);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/data/TradeLogData.java b/src/main/java/com/yaohun/trade/data/TradeLogData.java
new file mode 100644
index 0000000..fda5194
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/data/TradeLogData.java
@@ -0,0 +1,73 @@
+package com.yaohun.trade.data;
+
+import java.util.List;
+
+public class TradeLogData {
+
+ private String tradeID;
+ private String playerName;
+ private String targetName;
+ private long tradeTime;
+ private List playerList;
+ private List targetList;
+
+ public TradeLogData(String tradeID, String playerName, String targetName, long tradeTime, List playerList, List targetList) {
+ this.tradeID = tradeID;
+ this.playerName = playerName;
+ this.targetName = targetName;
+ this.tradeTime = tradeTime;
+ this.playerList = playerList;
+ this.targetList = targetList;
+ }
+
+ public TradeLogData() {
+ }
+
+ public void setTradeID(String tradeID) {
+ this.tradeID = tradeID;
+ }
+
+ public void setPlayerName(String playerName) {
+ this.playerName = playerName;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public void setTradeTime(long tradeTime) {
+ this.tradeTime = tradeTime;
+ }
+
+ public void setPlayerList(List playerList) {
+ this.playerList = playerList;
+ }
+
+ public void setTargetList(List targetList) {
+ this.targetList = targetList;
+ }
+
+ public String getTradeID() {
+ return tradeID;
+ }
+
+ public String getPlayerName() {
+ return playerName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public long getTradeTime() {
+ return tradeTime;
+ }
+
+ public List getPlayerList() {
+ return playerList;
+ }
+
+ public List getTargetList() {
+ return targetList;
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/gui/GuiMain.java b/src/main/java/com/yaohun/trade/gui/GuiMain.java
new file mode 100644
index 0000000..be6fe8e
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/gui/GuiMain.java
@@ -0,0 +1,70 @@
+package com.yaohun.trade.gui;
+
+import com.yaohun.trade.manage.InviteManager;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.Bukkit;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+public class GuiMain implements Listener {
+
+ @EventHandler
+ public void onclick(InventoryClickEvent e){
+ Player p = (Player) e.getWhoClicked();
+ Inventory inv = e.getInventory();
+ int rawSlot = e.getRawSlot();
+ if(inv != null && inv.getTitle().contains("向你发起的交易请求?")){
+ e.setCancelled(true);
+ if(rawSlot >= 0 && rawSlot < 27) {
+ ItemStack item = e.getCurrentItem();
+ if (!DemonAPI.itemIsNull(item)) {
+ NbtItem nbti = new NbtItem(item);
+ if(nbti.hasKey("trade_yes")){
+ p.closeInventory();
+ InviteManager.acceptInvite(p);
+ p.playSound(p.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,1);
+ }
+ if(nbti.hasKey("trade_no")){
+ p.closeInventory();
+ InviteManager.denyInvite(p);
+ p.playSound(p.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,1);
+ }
+ }
+ }
+ }
+ }
+
+ public static void OpenGui(Player p,String playName){
+ Inventory inv = Bukkit.createInventory(null,27,"是否接受"+playName+"向你发起的交易请求?");
+ for (int i : new int[]{0,1,2,3,9,10,11,12,18,19,20,21}){
+ inv.setItem(i, YesTrade(playName));
+ }
+ for (int i : new int[]{5,6,7,8,14,15,16,17,23,24,25,26}){
+ inv.setItem(i, NoTrade(playName));
+ }
+ p.openInventory(inv);
+ }
+
+ public static ItemStack YesTrade(String playName){
+ ItemStack item = DemonAPI.glass(5,"§a§l同意请求");
+ NbtItem nbti = new NbtItem(item);
+ nbti.setString("trade_yes",playName);
+ item = nbti.getItem();
+ return item;
+ }
+
+ public static ItemStack NoTrade(String playName){
+ ItemStack item = DemonAPI.glass(14,"§c§l拒绝请求");
+ NbtItem nbti = new NbtItem(item);
+ nbti.setString("trade_no",playName);
+ item = nbti.getItem();
+ return item;
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/gui/TradeGui.java b/src/main/java/com/yaohun/trade/gui/TradeGui.java
new file mode 100644
index 0000000..eca394b
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/gui/TradeGui.java
@@ -0,0 +1,85 @@
+package com.yaohun.trade.gui;
+
+import com.yaohun.trade.config.Config;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.*;
+
+public class TradeGui implements InventoryHolder {
+
+ private Inventory inventory;
+ private Player player;
+ private Player target;
+ private int[] progressSlot = new int[]{4,13,22,31,40};
+
+ public TradeGui(Player player, Player target) {
+ this.player = player;
+ this.target = target;
+ this.inventory = Bukkit.createInventory(null,45,Config.invTitle);
+ initPlayerGlass();
+ initTargetGlass();
+
+ ItemStack stack = DemonAPI.glass(3,"§a§l▷▷▷§7[§c"+target.getName()+"§7]§a§l▷▷▷");
+ ItemMeta meta = stack.getItemMeta();
+ List lore = new ArrayList<>();
+ lore.add("§b§l◀◀◀§7[§a"+player.getName()+"§7]§b§l◀◀◀");
+ meta.setLore(lore);
+ stack.setItemMeta(meta);
+ for (int slot : progressSlot){
+ this.inventory.setItem(slot,stack);
+ }
+ }
+
+ private void initPlayerGlass(){
+ ItemStack stack = DemonAPI.glass(6,"§a确认按钮");
+ ItemMeta meta = stack.getItemMeta();
+ List lore = new ArrayList<>();
+ lore.add("§l"+player.getName());
+ meta.setLore(lore);
+ stack.setItemMeta(meta);
+ NbtItem nbtItem = new NbtItem(stack);
+ nbtItem.setString("buttOwner",player.getName());
+ for(int i = 0; i < Config.playerButts.length; i++){
+ inventory.setItem(Config.playerButts[i],nbtItem.getItem());
+ }
+
+ ItemStack equipSlot = DemonAPI.glass(8,"§7[§c空§7]");
+ for (int i : Config.playerSlots){
+ inventory.setItem(i,equipSlot);
+ }
+ }
+ private void initTargetGlass(){
+ ItemStack stack = DemonAPI.glass(4,"§a确认按钮");
+ ItemMeta meta = stack.getItemMeta();
+ List lore = new ArrayList<>();
+ lore.add("§l"+target.getName());
+ meta.setLore(lore);
+ stack.setItemMeta(meta);
+ NbtItem nbtItem = new NbtItem(stack);
+ nbtItem.setString("buttOwner",target.getName());
+ for(int i = 0; i < Config.targetButts.length; i++){
+ inventory.setItem(Config.targetButts[i],nbtItem.getItem());
+ }
+
+ ItemStack equipSlot = DemonAPI.glass(8,"§7[§c空§7]");
+ for (int i : Config.targetSlots){
+ inventory.setItem(i,equipSlot);
+ }
+ }
+
+ @Override
+ public Inventory getInventory() {
+ return inventory;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/yaohun/trade/listener/BreakBlcok.java b/src/main/java/com/yaohun/trade/listener/BreakBlcok.java
new file mode 100644
index 0000000..2af743e
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/listener/BreakBlcok.java
@@ -0,0 +1,52 @@
+package com.yaohun.trade.listener;
+
+import com.yaohun.trade.config.Config;
+import com.yaohun.trade.util.MessageUtil;
+import me.Demon.DemonPlugin.DemonAPI;
+import org.bukkit.Sound;
+import org.bukkit.World;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockState;
+import org.bukkit.block.Chest;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Wolf;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+public class BreakBlcok implements Listener {
+
+ @EventHandler
+ public void onBreak(BlockBreakEvent e) {
+ Player player = e.getPlayer();
+ World world = player.getWorld();
+ if (Config.isBreakChestEnabled()) {
+ if (Config.isBreakChestWorld(world.getName())) {
+ if (!player.isOp()) {
+ return;
+ }
+ Block block = e.getBlock();
+ BlockState blockState = block.getState();
+ if (blockState instanceof Chest) {
+ Chest chest = (Chest) blockState;
+ Inventory inv = chest.getBlockInventory();
+ boolean stats = false;
+ for (int slot = 0; slot < inv.getSize(); slot++) {
+ ItemStack stack = inv.getItem(slot);
+ if (DemonAPI.itemIsNull(stack) || DemonAPI.itemIsLore(stack)) {
+ continue;
+ }
+ stats = true;
+ break;
+ }
+ if (stats) {
+ e.setCancelled(true);
+ MessageUtil.sendMessage(player, Config.getString("breakchest"), Sound.ENTITY_VILLAGER_NO);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/listener/ClickInventory.java b/src/main/java/com/yaohun/trade/listener/ClickInventory.java
new file mode 100644
index 0000000..6201720
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/listener/ClickInventory.java
@@ -0,0 +1,205 @@
+package com.yaohun.trade.listener;
+
+import com.yaohun.trade.util.StackUtil;
+import com.yaohun.trade.config.Config;
+import com.yaohun.trade.data.TradeData;
+import com.yaohun.trade.manage.InviteManager;
+import com.yaohun.trade.util.MessageUtil;
+import com.yaohun.trade.util.TradeState;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.Util.CDTimeAPI;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class ClickInventory implements Listener {
+ @EventHandler
+ public void onClick(InventoryClickEvent e){
+ int rawSlot = e.getRawSlot();
+ Player player = (Player) e.getWhoClicked();
+ UUID uuid = player.getUniqueId();
+ Inventory inv = e.getInventory();
+ if(e.getView().getTitle().equalsIgnoreCase(Config.invTitle)){
+ if(e.getClick() == ClickType.DOUBLE_CLICK){
+ e.setCancelled(true);
+ player.closeInventory();
+ MessageUtil.sendMessage(player,Config.getString("doubleClickAnit"),Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ if(e.getClick() == ClickType.SHIFT_LEFT || e.getClick() == ClickType.SHIFT_RIGHT){
+ e.setCancelled(true);
+ player.closeInventory();
+ MessageUtil.sendMessage(player,Config.getString("shfitClickAnit"),Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ if(rawSlot >0 && rawSlot < 45) {
+ e.setCancelled(true);
+ TradeData tradeData = InviteManager.getTradeData(player);
+ if(tradeData == null){
+ player.closeInventory();
+ return;
+ }
+ ItemStack stack = e.getCurrentItem();
+ if(tradeData.getPlayer().equals(player)){
+ if(!isClickValidPlace(false,rawSlot)){
+ if(rawSlot == 36 || rawSlot == 37 || rawSlot == 38 || rawSlot == 39){
+ if(tradeData.getState(player).equals(TradeState.CONFIRM)){
+ return;
+ }
+ tradeData.setStateData(player,TradeState.CONFIRM);
+ if(tradeData.isMutualComfirm()){
+ // 执行交易操作
+ tradeData.successTrade();
+ InviteManager.tradeData.remove(tradeData);
+ } else {
+ confirmGlassState(inv, false);
+ MessageUtil.sendMessage(player,Config.getString("ConfirmTheTrade"), Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+ MessageUtil.sendMessage(tradeData.getTarget(), Config.getString("ConfirmTheTrade2"), Sound.ENTITY_CAT_AMBIENT);
+ }
+ return;
+ }
+ if(CDTimeAPI.isCD(uuid,"crossingClick")) {
+ tradeData.setTradeBreakTheLaw(true);
+ MessageUtil.sendMessage(player, Config.getString("crossingTheLine"), Sound.ENTITY_BLAZE_DEATH);
+ MessageUtil.sendMessage(tradeData.getTarget(), Config.getString("crossingTheLine2").replace("{name}", player.getName()), Sound.ENTITY_BLAZE_DEATH);
+ player.closeInventory();
+ } else {
+ MessageUtil.sendMessage(player, Config.getString("crossingTheLine3"), Sound.ENTITY_BLAZE_DEATH);
+ CDTimeAPI.setPlayerCD(uuid,"crossingClick",3000);
+ }
+ } else {
+ player.playSound(player.getLocation(),Sound.BLOCK_COMPARATOR_CLICK,1,1);
+ if(DemonAPI.itemIsNull(stack)){
+ return;
+ }
+ if(!DemonAPI.itemIsLore(stack)){
+ player.getInventory().addItem(StackUtil.removeTagStack(stack));
+ inv.setItem(rawSlot, DemonAPI.glass(8,"§7[§c空§7]"));
+ return;
+ }
+ ItemStack cursor = e.getCursor();
+ if(DemonAPI.itemIsNull(cursor) || DemonAPI.itemIsLore(cursor)){
+ return;
+ }
+ inv.setItem(rawSlot, StackUtil.addTagStack(cursor, player.getName()));
+ e.setCursor(new ItemStack(Material.AIR));
+ }
+ }
+ if(tradeData.getTarget().equals(player)){
+ if(!isClickValidPlace(true,rawSlot)){
+ if(rawSlot == 41 || rawSlot == 42 || rawSlot == 43 || rawSlot == 44){
+ if(tradeData.getState(player).equals(TradeState.CONFIRM)){
+ return;
+ }
+ tradeData.setStateData(player,TradeState.CONFIRM);
+ if(tradeData.isMutualComfirm()){
+ // 执行交易操作
+ tradeData.successTrade();
+ InviteManager.tradeData.remove(tradeData);
+ } else {
+ confirmGlassState(inv, true);
+ MessageUtil.sendMessage(player,Config.getString("ConfirmTheTrade"), Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+ MessageUtil.sendMessage(tradeData.getPlayer(), Config.getString("ConfirmTheTrade2"), Sound.ENTITY_CAT_AMBIENT);
+ }
+ return;
+ }
+ if(CDTimeAPI.isCD(uuid,"crossingClick")) {
+ tradeData.setTradeBreakTheLaw(true);
+ MessageUtil.sendMessage(player, Config.getString("crossingTheLine"), Sound.ENTITY_BLAZE_DEATH);
+ MessageUtil.sendMessage(tradeData.getPlayer(), Config.getString("crossingTheLine2").replace("{name}", player.getName()), Sound.ENTITY_BLAZE_DEATH);
+ player.closeInventory();
+ } else {
+ MessageUtil.sendMessage(player, Config.getString("crossingTheLine3"), Sound.ENTITY_BLAZE_DEATH);
+ CDTimeAPI.setPlayerCD(uuid,"crossingClick",3000);
+ }
+ } else {
+ player.playSound(player.getLocation(),Sound.BLOCK_COMPARATOR_CLICK,1,1);
+ if(DemonAPI.itemIsNull(stack)){
+ return;
+ }
+ if(!DemonAPI.itemIsLore(stack)){
+ player.getInventory().addItem(StackUtil.removeTagStack(stack));
+ inv.setItem(rawSlot, DemonAPI.glass(8,"§7[§c空§7]"));
+ return;
+ }
+ ItemStack cursor = e.getCursor();
+ if(DemonAPI.itemIsNull(cursor) || DemonAPI.itemIsLore(cursor)){
+ return;
+ }
+ inv.setItem(rawSlot, StackUtil.addTagStack(cursor, player.getName()));
+ e.setCursor(new ItemStack(Material.AIR));
+ }
+ }
+ }
+ }
+ }
+
+ public boolean isClickValidPlace(boolean targetD, int rawSlot){
+ if(targetD){
+ for (int slot : Config.targetSlots){
+ if(rawSlot == slot){
+ return true;
+ }
+ }
+ } else {
+ for (int slot : Config.playerSlots) {
+ if (rawSlot == slot) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void confirmGlassState(Inventory inv,boolean targetD){
+ ItemStack stack = DemonAPI.glass(5,"§c§l 已锁定交易品");
+ ItemMeta meta = stack.getItemMeta();
+ List lore = new ArrayList<>();
+ lore.add("§7按下 §c§lESC §7取消交易");
+ meta.setLore(lore);
+ stack.setItemMeta(meta);
+ if(targetD){
+ for (int slot : Config.targetButts){
+ inv.setItem(slot,stack);
+ }
+ } else {
+ for (int slot : Config.playerButts){
+ inv.setItem(slot,stack);
+ }
+ }
+ }
+
+ @EventHandler
+ public void onClose(InventoryCloseEvent e){
+ Player player = (Player) e.getPlayer();
+ Inventory inv = e.getInventory();
+ if(e.getView().getTitle().equalsIgnoreCase(Config.invTitle)){
+ TradeData tradeData = InviteManager.getTradeData(player);
+ if(tradeData == null){
+ return;
+ }
+ if(tradeData.isTradeStop()){
+ return;
+ }
+ if(tradeData.getPlayer().equals(player)){
+ tradeData.closeTradeGui(true);
+ }else if(tradeData.getTarget().equals(player)){
+ tradeData.closeTradeGui(false);
+ }
+ InviteManager.tradeData.remove(tradeData);
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/listener/PlayerListener.java b/src/main/java/com/yaohun/trade/listener/PlayerListener.java
new file mode 100644
index 0000000..6f8c65e
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/listener/PlayerListener.java
@@ -0,0 +1,30 @@
+package com.yaohun.trade.listener;
+
+import com.yaohun.trade.data.TradeData;
+import com.yaohun.trade.manage.InviteManager;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+public class PlayerListener implements Listener {
+
+ @EventHandler
+ public void onQuit(PlayerQuitEvent e){
+ Player player = e.getPlayer();
+ TradeData tradeData = InviteManager.getTradeData(player);
+ if(tradeData == null){
+ return;
+ }
+ if(tradeData.isTradeStop()){
+ return;
+ }
+ if(tradeData.getPlayer().equals(player)){
+ tradeData.closeTradeGui(true);
+ }else if(tradeData.getTarget().equals(player)){
+ tradeData.closeTradeGui(false);
+ }
+ InviteManager.tradeData.remove(tradeData);
+ System.out.printf("[日志 - 交易] 玩家 "+player.getName()+" 因退出游戏导致交易终止.");
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/manage/InviteManager.java b/src/main/java/com/yaohun/trade/manage/InviteManager.java
new file mode 100644
index 0000000..97794cd
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/manage/InviteManager.java
@@ -0,0 +1,187 @@
+package com.yaohun.trade.manage;
+
+import com.yaohun.trade.config.Config;
+import com.yaohun.trade.data.InviteData;
+import com.yaohun.trade.data.TradeData;
+import com.yaohun.trade.gui.GuiMain;
+import com.yaohun.trade.gui.TradeGui;
+import com.yaohun.trade.util.MessageUtil;
+import com.yaohun.trade.util.TradeState;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.Util.AreaType;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+
+import java.util.*;
+
+public class InviteManager {
+
+ public static final List tradeData = new ArrayList<>();
+ private static final Map inviteData = new HashMap<>();
+
+ public static TradeData getTradeData(Player player) {
+ for (TradeData tradeData : tradeData) {
+ if (tradeData.getPlayer().equals(player)) {
+ return tradeData;
+ }else if (tradeData.getTarget().equals(player)) {
+ return tradeData;
+ }
+ }
+ return null;
+ }
+
+ private static boolean isInviteExit(Player player){
+ return inviteData.containsKey(player.getName());
+ }
+ private static boolean isInviteTargetExit(Player target){
+ for (InviteData inviteData : inviteData.values()){
+ if (inviteData.getTarget().equals(target)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static InviteData getInviteData(Player player) {
+ for (InviteData inviteData : inviteData.values()){
+ if (inviteData.getTarget().equals(player)) {
+ return inviteData;
+ }else if (inviteData.getPlayer().equals(player)) {
+ return inviteData;
+ }
+ }
+ return null;
+ }
+
+
+ public static void sendInvite(Player player,Player target) {
+ String playerName = player.getName();
+ // 判断目标是否存在交易请求尚未处理
+ if(isInviteTargetExit(target)){
+ String message = Config.getString("targetNotProcessedYet").replace("{target}", target.getName());
+ MessageUtil.sendMessage(player, message, Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ // 玩家若已创建交易请求,则无法再次创建
+ if(isInviteExit(player)){
+ InviteData data = inviteData.get(playerName);
+ // 判断上一个创建的交易请求是否已超时
+ if(!data.isExpired()) {
+ String message = Config.getString("inviteAlreadyExist").replace("{target}", target.getName());
+ MessageUtil.sendMessage(player, message, Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ }
+ InviteData data = new InviteData(player, target);
+ String targetName = target.getName();
+ inviteData.put(playerName, data);
+ String sendAnInvitation = Config.getString("sendAnInvitation").replace("{target}", targetName);
+ MessageUtil.sendMessage(player, sendAnInvitation, Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+
+ String receivedAnInvitation = Config.getString("receivedAnInvitation").replace("{player}", playerName);
+ MessageUtil.sendMessage(target, receivedAnInvitation, Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+ if (DemonAPI.getAreaType() == AreaType.DEFAULT) {
+ MessageUtil.sendClickMessage(target, "§r §a§l【点击同意】 §r", "trade accept");
+ MessageUtil.sendClickMessage(target, "§r §c§l【点击拒绝】 §r", "trade deny");
+ } else {
+ MessageUtil.sendClickMessage(target, "§r §a§l【點擊同意】 §r", "trade accept");
+ MessageUtil.sendClickMessage(target, "§r §c§l【點擊拒絕】 §r", "trade deny");
+ }
+
+ GuiMain.OpenGui(target,playerName);
+ }
+
+ public static void acceptInvite(Player target) {
+ String targetName = target.getName();
+ InviteData data = getInviteData(target);
+ // 判断玩家是否有交易需要处理
+ if (data == null) {
+ MessageUtil.sendMessage(target, Config.getString("inviteNotExist"), Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ String playerName = data.playerName();
+ // 判断这个交易请求是否已过期
+ if(data.isExpired()){
+ MessageUtil.sendMessage(target, Config.getString("inviteExpire"), Sound.ENTITY_VILLAGER_NO);
+ inviteData.remove(playerName);
+ return;
+ }
+ inviteData.remove(playerName);
+ // 判断发起玩家是否已离线
+ Player player = Bukkit.getPlayer(playerName);
+ if(player == null || !player.isOnline()){
+ MessageUtil.sendMessage(target, Config.getString("invitePlayerOffline"), Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ // 判断发起玩家和接收玩家是否是同一人
+ if(player.equals(target)){
+ MessageUtil.sendMessage(target, Config.getString("inviteNotSelf"), Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ // 判断两人距离是否已超出距离
+ if(hasDistance(player, target)){
+ String message = Config.getString("inviteDistanceLimit").replace("{distance}", String.valueOf(Config.getLimitDistance()));
+ MessageUtil.sendMessage(target, message, Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ // 打开交易界面进行交易
+ String message = Config.getString("inviteSuccess");
+ MessageUtil.sendMessage(target, message.replace("{name}",playerName),Sound.BLOCK_CHEST_OPEN);
+ MessageUtil.sendMessage(player, message.replace("{name}",targetName),Sound.BLOCK_CHEST_OPEN);
+
+ /*打开界面*/
+ Inventory gui = new TradeGui(player,target).getInventory();
+ player.openInventory(gui);
+ target.openInventory(gui);
+ tradeData.add(new TradeData(player,target,gui));
+ // player.openInventory(player.getEnderChest());
+ }
+
+ public static void denyInvite(Player target) {
+ InviteData data = getInviteData(target);
+ // 判断玩家是否有交易需要处理
+ if (data == null) {
+ MessageUtil.sendMessage(target, Config.getString("inviteNotExist"), Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ String playerName = data.playerName();
+ // 判断这个交易请求是否已过期
+ if(data.isExpired()){
+ MessageUtil.sendMessage(target, Config.getString("inviteExpire"), Sound.ENTITY_VILLAGER_NO);
+ inviteData.remove(playerName);
+ return;
+ }
+ inviteData.remove(playerName);
+ // 判断发起玩家是否已离线
+ Player player = Bukkit.getPlayer(playerName);
+ if(player == null || !player.isOnline()){
+ MessageUtil.sendMessage(target, Config.getString("invitePlayerOffline"), Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ // 判断发起玩家和接收玩家是否是同一人
+ if(player.equals(target)){
+ MessageUtil.sendMessage(target, Config.getString("inviteNotSelf"), Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ String sendMessage = Config.getString("inviteDenySend").replace("{target}", target.getName());
+ MessageUtil.sendMessage(player, sendMessage);
+ String targetMessage = Config.getString("inviteDenyTarget").replace("{player}", playerName);
+ MessageUtil.sendMessage(target, targetMessage);
+ }
+
+ private static boolean hasDistance(Player player, Player target){
+ Location locA = player.getLocation();
+ Location locB = target.getLocation();
+ if(!locA.getWorld().equals(locB.getWorld())){
+ return true;
+ }
+ double distance = locA.distance(locB);
+ if(distance >= Config.getLimitDistance()){
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/manage/LogsManager.java b/src/main/java/com/yaohun/trade/manage/LogsManager.java
new file mode 100644
index 0000000..aaf3554
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/manage/LogsManager.java
@@ -0,0 +1,61 @@
+package com.yaohun.trade.manage;
+
+import com.yaohun.trade.data.TradeLogData;
+import me.Demon.DemonPlugin.DemonAPI;
+import org.bukkit.Bukkit;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class LogsManager {
+
+ private File file;
+ private FileConfiguration config;
+
+ private List logDataList = new ArrayList<>();
+
+ public LogsManager() {
+ String pathData = "plugins/AuLogs/TradeLog";
+ File path = new File(pathData);
+ if(!path.exists()){
+ path.mkdirs();
+ }
+ this.file = new File(pathData, DemonAPI.getTime("yyyy-MM")+".yml");
+ if(!file.exists()){
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ this.config = YamlConfiguration.loadConfiguration(this.file);
+ }
+
+ public void addLogData(TradeLogData logData){
+ this.logDataList.add(logData);
+ }
+
+ public void saveAllLog(){
+ if(logDataList.isEmpty()){
+ return;
+ }
+ for (TradeLogData logData : logDataList){
+ String tradeId = logData.getTradeID();
+ this.config.set(tradeId+".时间",DemonAPI.LongToStringData(logData.getTradeTime(),"yyyy-MM-dd HH:mm:ss"));
+ this.config.set(tradeId+".发起者",logData.getPlayerName());
+ this.config.set(tradeId+".发起者物品",logData.getPlayerList());
+ this.config.set(tradeId+".接收者",logData.getTargetName());
+ this.config.set(tradeId+".接收者物品",logData.getTargetList());
+ }
+ try {
+ this.config.save(this.file);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ Bukkit.getConsoleSender().sendMessage("§6[交易系统] §7成功保存交易日志: §a"+logDataList.size()+"条");
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/util/MessageUtil.java b/src/main/java/com/yaohun/trade/util/MessageUtil.java
new file mode 100644
index 0000000..d9a7f5e
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/util/MessageUtil.java
@@ -0,0 +1,31 @@
+package com.yaohun.trade.util;
+
+import net.md_5.bungee.api.chat.ClickEvent;
+import net.md_5.bungee.api.chat.ComponentBuilder;
+import net.md_5.bungee.api.chat.HoverEvent;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.Sound;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class MessageUtil {
+
+ public static void sendClickMessage(Player player, String message,String command){
+ TextComponent tomessage = new TextComponent(message);
+ tomessage.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/"+command));
+ tomessage.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("§a极§b光§c像§d素").create()));
+ player.spigot().sendMessage(tomessage);
+ }
+
+ public static void sendMessage(CommandSender sender, String message) {
+ sender.sendMessage(message);
+ }
+
+ public static void sendMessage(CommandSender sender, String message, Sound sound) {
+ sender.sendMessage(message);
+ if(sender instanceof Player){
+ Player player = (Player) sender;
+ player.playSound(player.getLocation(), sound, 0.8f,1.2f);
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/util/StackUtil.java b/src/main/java/com/yaohun/trade/util/StackUtil.java
new file mode 100644
index 0000000..e15370c
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/util/StackUtil.java
@@ -0,0 +1,23 @@
+package com.yaohun.trade.util;
+
+import me.Demon.DemonPlugin.Util.RandomUtil;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.inventory.ItemStack;
+
+public class StackUtil {
+
+ public static ItemStack addTagStack(ItemStack stack, String ownerName){
+ NbtItem nbtItem = new NbtItem(stack);
+ nbtItem.setString("tradeTag",ownerName+"#"+ RandomUtil.getRandomInt(1000,8000));
+ return nbtItem.getItem();
+ }
+
+ public static ItemStack removeTagStack(ItemStack stack){
+ NbtItem nbtItem = new NbtItem(stack);
+ if(nbtItem.hasKey("tradeTag")) {
+ nbtItem.removeKey("tradeTag");
+ return nbtItem.getItem();
+ }
+ return stack;
+ }
+}
diff --git a/src/main/java/com/yaohun/trade/util/TradeState.java b/src/main/java/com/yaohun/trade/util/TradeState.java
new file mode 100644
index 0000000..0700ce1
--- /dev/null
+++ b/src/main/java/com/yaohun/trade/util/TradeState.java
@@ -0,0 +1,7 @@
+package com.yaohun.trade.util;
+
+public enum TradeState {
+ OPEN,
+ CONFIRM,
+ SUCCEED
+}
diff --git a/src/main/resources/DemonTrade.yml b/src/main/resources/DemonTrade.yml
new file mode 100644
index 0000000..6acfe24
--- /dev/null
+++ b/src/main/resources/DemonTrade.yml
@@ -0,0 +1,28 @@
+Message:
+ commandUsageInvite: "§f[§c系统§f] §a正确用法: §e/trade [玩家名]"
+ breakchest: "§f[§c系统§f] §a请将箱子中的物品取出后再尝试破坏."
+ invitePlayerOffline: "§f[§c系统§f] §a目标玩家貌似不存在或已离线."
+ targetNotProcessedYet: "§f[§c系统§f] §a玩家 §e{target} §a存在尚未处理的交易请求."
+ inviteAlreadyExist: "§f[§c系统§f] §a你已经想玩家 §e{target} §a发送过交易请求."
+ sendAnInvitation: "§f[§c系统§f] §a发送成功,已向 §e{target} §a发出交易请求."
+ receivedAnInvitation: "§f[§c系统§f] §a你收到了来自 §e{player} §a的交易请求."
+ inviteNotExist: "§f[§c系统§f] §a没有需要处理的交易请求."
+ inviteExpire: "§f[§c系统§f] §a这个交易请求貌似已过期."
+ inviteNotSelf: "§f[§c系统§f] §a处理失败,无法同意自己的交易请求."
+ inviteDistanceLimit: "§f[§c系统§f] §a处理失败,交易双方都需要在§e<{distance}格>§a方块内."
+ inviteSuccess: "§f[§c系统§f] §a您正在与 §e{name} §a进行交易."
+ inviteDenySend: "§f[§c系统§f] §a玩家 §e{target} §a拒绝了你发起的交易请求."
+ inviteDenyTarget: "§f[§c系统§f] §a你婉拒了来自 §e{player} §a的交易请求."
+ crossingTheLine: "§f[§c系统§f] §b交易取消,因为你误触到了不属于你的操作区."
+ crossingTheLine2: "§f[§c系统§f] §b交易取消,因玩家 §e{name} §b进行了越界违规操作."
+ crossingTheLine3: "§f[§c系统§f] §b亲,你点击的位置并不是你的操作区."
+ ConfirmTheTrade: "§f[§c系统§f] §a成功确认交易,请耐心等待交易方确认."
+ ConfirmTheTrade2: "§f[§c系统§f] §a交易方已确认交易,请尽快确认完成交易."
+ insufficientSpace: "§f[§c系统§f] §b交易取消,发起交易方没有足够的空间放入交易品."
+ insufficientSpace2: "§f[§c系统§f] §b交易取消,接受交易方没有足够的空间放入交易品."
+ closeTheInterface: "§f[§c系统§f] §b成功取消与 §e{name} §b的交易事件."
+ closeTheInterface2: "§f[§c系统§f] §b玩家 §e{name} §b取消了与你的交易."
+ doubleClickAnit: "§f[§c系统§f] §b交易取消,交易系统不支持双击点击."
+ shfitClickAnit: "§f[§c系统§f] §b交易取消,交易系统不支持SHIFT点击."
+ CompleteTrade: "§f[§c系统§f] §6交易成功,您获得了 §a{count}件 §6交易物品."
+ CompleteTrade2: "§f[§c系统§f] §6交易成功,物品已发送至对方背包."
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
new file mode 100644
index 0000000..7693c86
--- /dev/null
+++ b/src/main/resources/config.yml
@@ -0,0 +1,4 @@
+BreakChest:
+ enabled: true
+ worlds:
+ - PlotSquared
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
new file mode 100644
index 0000000..907cdf1
--- /dev/null
+++ b/src/main/resources/plugin.yml
@@ -0,0 +1,8 @@
+name: DemonTrade
+main: com.yaohun.trade.TradeMain
+version: 1.0.0
+author: yaohun
+depend:
+ - DemonAPI
+commands:
+ trade:
\ No newline at end of file