This commit is contained in:
yaohunya 2025-07-19 05:09:22 +08:00
commit 32631e6c59
11 changed files with 647 additions and 0 deletions

37
pom.xml Normal file
View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yaohun.main</groupId>
<artifactId>DemonPlayerMail</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>public-rpg</id>
<url>https://repo.aurora-pixels.com/repository/public-rpg/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>me.Demon.DemonPlugin</groupId>
<artifactId>DemonAPI</artifactId>
<version>2.2.9</version>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12.2</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,93 @@
package com.yaohun.playermail;
import com.yaohun.playermail.gui.MailGui;
import com.yaohun.playermail.gui.ToMailGui;
import com.yaohun.playermail.listener.ClickInventory;
import com.yaohun.playermail.listener.PlayerListener;
import com.yaohun.playermail.manage.PlayerManager;
import com.yaohun.playermail.util.LangUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public class MailMain extends JavaPlugin {
private static MailMain instance;
private static PlayerManager playerManager;
@Override
public void onEnable() {
instance = this;
LangUtil.initLangUtil();
playerManager = new PlayerManager();
new PlayerListener(this);
new ToMailGui(this);
getServer().getPluginManager().registerEvents(new ClickInventory(), this);
}
@Override
public void onDisable() {
getPlayerManager().saveAllPlayerData();
saveConfig();
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if("dpmail".equalsIgnoreCase(label)){
if(args.length >= 1 && "open".equalsIgnoreCase(args[0])){
if(args.length == 2 && sender.isOp()){
String name = args[1];
Player player = Bukkit.getPlayer(name);
if(player == null){
return true;
}
MailGui.openGui(player);
return true;
}
MailGui.openGui((Player) sender);
}
if(!sender.isOp()){
return true;
}
if (args.length == 0) {
sender.sendMessage("");
sender.sendMessage("§e------- ======= §6玩家邮箱 §e======= -------");
sender.sendMessage("§2/"+label+" open §e[玩家] §f- §2打开收件箱");
sender.sendMessage("§2/"+label+" to §e[玩家] §f- §2打开发件箱");
sender.sendMessage("§2/"+label+" save §f- §2保存玩家邮箱");
sender.sendMessage("§e------- ======= §6玩家邮箱 §e======= -------");
sender.sendMessage("");
return true;
}
if("to".equalsIgnoreCase(args[0])){
if(!(sender instanceof Player)){
sender.sendMessage("§c控制台无法执行此操作.");
return true;
}
if(args.length == 1){
sender.sendMessage("[邮箱] 缺少玩家参数.");
return true;
}
String name = args[1];
ToMailGui.openGui((Player) sender,name);
return true;
}
if("save".equalsIgnoreCase(args[0])){
getPlayerManager().saveAllPlayerData();
sender.sendMessage("[邮箱] 已保存所有玩家数据.");
return true;
}
}
return false;
}
public static MailMain inst() {
return instance;
}
public static PlayerManager getPlayerManager() {
return playerManager;
}
}

View File

@ -0,0 +1,90 @@
package com.yaohun.playermail.data;
import com.yaohun.playermail.MailMain;
import me.Demon.DemonPlayerMail.Api.DMailAPI;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
public class PlayerData {
private File file;
private FileConfiguration config;
private String playerName;
private HashMap<Long, ItemStack> stackHashMap = new HashMap<>();
public PlayerData(String playerName) {
this.playerName = playerName;
this.file = new File("plugins/AuData/MailData",playerName+".yml");
if(!file.exists()) {
this.file.getParentFile().mkdirs();
this.config = YamlConfiguration.loadConfiguration(this.file);
} else {
this.config = YamlConfiguration.loadConfiguration(this.file);
}
loadMailStack();
}
private void loadMailStack(){
ConfigurationSection section = config.getConfigurationSection("MailData");
if(section == null){
return;
}
for(String key : section.getKeys(false)){
long expiryTime = Long.parseLong(key);
ItemStack itemStack = section.getItemStack(key);
stackHashMap.put(expiryTime,itemStack);
}
}
public void saveMailStack(){
config.set("MailData",null);
if(!stackHashMap.isEmpty()) {
long nowTime = System.currentTimeMillis();
for (Long key : stackHashMap.keySet()) {
if (nowTime >= key) {
continue;
}
ItemStack itemStack = stackHashMap.get(key);
config.set("MailData." + key, itemStack);
}
}
try {
config.save(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public HashMap<Long, ItemStack> getStackHashMap() {
return stackHashMap;
}
public int getMailAmount(){
return stackHashMap.size();
}
public void resetMailData(){
stackHashMap.clear();
}
public ItemStack getMailStack(long expiryTime){
return stackHashMap.get(expiryTime);
}
public void removeMailStack(long expiryTime){
stackHashMap.remove(expiryTime);
}
public void addMailStack(long expiryTime,ItemStack stack){
stackHashMap.put(expiryTime,stack);
}
}

View File

@ -0,0 +1,61 @@
package com.yaohun.playermail.gui;
import com.yaohun.playermail.MailMain;
import com.yaohun.playermail.data.PlayerData;
import com.yaohun.playermail.manage.PlayerManager;
import com.yaohun.playermail.util.LangUtil;
import me.Demon.DemonPlugin.DemonAPI;
import me.Demon.DemonPlugin.data.NbtItem;
import org.bukkit.Bukkit;
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.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MailGui {
private static String invTitle = LangUtil.player_mail_title;
public static void openGui(Player player){
String playerName = player.getName();
PlayerManager playerManager = MailMain.getPlayerManager();
PlayerData playerData = playerManager.getPlayerData(playerName);
Inventory inv = Bukkit.createInventory(null,45,invTitle);
HashMap<Long, ItemStack> stackHashMap = playerData.getStackHashMap();
if(!stackHashMap.isEmpty()){
for (Long key : stackHashMap.keySet()){
ItemStack itemStack = stackHashMap.get(key);
NbtItem nbtItem = new NbtItem(itemStack);
nbtItem.setLong("itemKey",key);
inv.addItem(nbtItem.getItem());
}
}
ItemStack glass = DemonAPI.glass(15,"§7[§a■□■§7]");
for (int i = 36; i < 45; i++){
inv.setItem(i, glass);
}
inv.setItem(40,infoStack());
player.openInventory(inv);
}
public static ItemStack infoStack() {
ItemStack item = new ItemStack(Material.SNOW_BALL);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§a点击一键签收");
List<String> lore = new ArrayList<>();
lore.add("§e★§7点击将邮件物品全部收取");
lore.add("§c★§7请检查背包空位是否充足");
meta.setLore(lore);
item.setItemMeta(meta);
return item;
}
}

View File

@ -0,0 +1,102 @@
package com.yaohun.playermail.gui;
import com.yaohun.playermail.MailMain;
import com.yaohun.playermail.data.PlayerData;
import com.yaohun.playermail.manage.PlayerManager;
import com.yaohun.playermail.util.LangUtil;
import me.Demon.DemonPlayerMail.Api.DMailAPI;
import me.Demon.DemonPlugin.DemonAPI;
import me.Demon.DemonPlugin.Util.RandomUtil;
import me.Demon.DemonPlugin.data.NbtItem;
import org.bukkit.Bukkit;
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.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.HashMap;
public class ToMailGui implements Listener {
public ToMailGui(MailMain plugin){
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
private static String invTitle = "管理员发件箱 - ";
public static void openGui(Player player,String addressee){
Inventory inv = Bukkit.createInventory(null,45,invTitle+addressee);
PlayerManager playerManager = MailMain.getPlayerManager();
PlayerData playerData = playerManager.getPlayerData(addressee);
HashMap<Long, ItemStack> stackHashMap = playerData.getStackHashMap();
if(!stackHashMap.isEmpty()){
for (Long key : stackHashMap.keySet()){
ItemStack itemStack = stackHashMap.get(key);
NbtItem nbtItem = new NbtItem(itemStack);
nbtItem.setLong("itemKey",key);
inv.addItem(nbtItem.getItem());
}
}
for (int i=36;i<45;i++){
inv.setItem(i, DemonAPI.glass(15,"§7[§a■□■§7]"));
}
ItemStack stack = new ItemStack(Material.SNOW_BALL);
ItemMeta meta = stack.getItemMeta();
meta.setDisplayName("§6§l确认发货");
stack.setItemMeta(meta);
NbtItem nbtItem = new NbtItem(stack);
nbtItem.setString("addressee",addressee);
inv.setItem(40,nbtItem.getItem());
player.openInventory(inv);
}
@EventHandler
public void onClick(InventoryClickEvent e){
int rawSlot = e.getRawSlot();
Player player = (Player) e.getWhoClicked();
String playerName = player.getName();
Inventory inv = e.getInventory();
if(e.getView().getTitle().contains(invTitle)){
if(rawSlot >= 36 && rawSlot <= 44) {
e.setCancelled(true);
if(rawSlot == 40){
NbtItem nbtItem = new NbtItem(e.getCurrentItem());
String addressee = nbtItem.getString("addressee");
PlayerManager playerManager = MailMain.getPlayerManager();
PlayerData playerData = playerManager.getPlayerData(addressee);
playerData.resetMailData();
Inventory cacheInv = Bukkit.createInventory(null, 27, "这是一个缓存虚拟器");
for (int i = 0; i < 36; i++) {
ItemStack item = inv.getItem(i);
if (!DemonAPI.itemIsNull(item)) {
cacheInv.addItem(item);
}
}
int amount = 0;
for (int slot = 0; slot < 27; slot++){
ItemStack stack = cacheInv.getItem(slot);
if (!DemonAPI.itemIsNull(stack)) {
DMailAPI.GiveItem(playerName, stack);
amount += stack.getAmount();
}
}
if(amount >= 1) {
playerData.saveMailStack();
player.closeInventory();
player.sendMessage(LangUtil.admin_sent_successfully.replace("{player}",addressee));
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP,0.8f,1.2f);
} else {
player.closeInventory();
player.sendMessage(LangUtil.admin_no_items_sent);
}
}
}
}
}
}

View File

@ -0,0 +1,105 @@
package com.yaohun.playermail.listener;
import com.sun.org.apache.bcel.internal.generic.LOR;
import com.yaohun.playermail.MailMain;
import com.yaohun.playermail.data.PlayerData;
import com.yaohun.playermail.gui.MailGui;
import com.yaohun.playermail.manage.PlayerManager;
import com.yaohun.playermail.util.LangUtil;
import me.Demon.DemonPlugin.DemonAPI;
import me.Demon.DemonPlugin.data.NbtItem;
import org.bukkit.Location;
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.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
public class ClickInventory implements Listener {
@EventHandler
public void onClick(InventoryClickEvent e){
int rawSlot = e.getRawSlot();
Player player = (Player) e.getWhoClicked();
String playerName = player.getName();
// 检查视图标题是否与玩家邮件标题匹配
if(e.getView().getTitle().equalsIgnoreCase(LangUtil.player_mail_title)){
e.setCancelled(true);
// 获取玩家位置
Location playerLocation = player.getLocation();
// 获取玩家管理器实例
PlayerManager playerManager = MailMain.getPlayerManager();
// 根据玩家名称获取玩家数据
PlayerData playerData = playerManager.getPlayerData(playerName);
// 检查槽位索引是否在玩家库存范围内
if(rawSlot >= 0 && rawSlot < 36){
// 获取当前点击的物品堆
ItemStack stack = e.getCurrentItem();
// 如果物品堆为空则返回
if(DemonAPI.itemIsNull(stack)){
return;
}
// 创建NBT物品对象
NbtItem nbtItem = new NbtItem(stack);
// 如果物品没有'itemKey'则返回
if (!nbtItem.hasKey("itemKey")) {
return;
}
// 获取物品键值
long itemKey = nbtItem.getLong("itemKey");
// 根据物品键值获取邮件中的物品堆
ItemStack clickStack = playerData.getMailStack(itemKey);
// 如果物品堆为空则返回
if (clickStack == null) {
return;
}
// 将物品堆添加到玩家库存中
player.getInventory().addItem(clickStack);
// 从玩家数据中移除邮件中的物品堆
playerData.removeMailStack(itemKey);
// 播放比较器点击声音
player.playSound(playerLocation, Sound.BLOCK_COMPARATOR_CLICK,1,2);
// 打开邮件界面
MailGui.openGui(player);
return;
}
// 检查是否点击了特定槽位
if(rawSlot == 40){
// 获取玩家数据中的物品堆哈希映射
HashMap<Long,ItemStack> stackHashMap = playerData.getStackHashMap();
// 如果哈希映射为空提示玩家邮件中无物品
if(stackHashMap.isEmpty()){
player.sendMessage(LangUtil.mail_no_items);
player.playSound(playerLocation, Sound.ENTITY_VILLAGER_NO,0.8F,1.4F);
return;
}
// 如果玩家库存没有足够的空槽位提示玩家背包空间不足
if(!DemonAPI.hasEmptyInventorySlots(player,stackHashMap.size())){
player.sendMessage(LangUtil.insufficient_backpack_space);
player.playSound(playerLocation, Sound.ENTITY_VILLAGER_NO,0.8F,1.4F);
return;
}
// 遍历哈希映射中的物品堆并添加到玩家库存中
for (ItemStack stack : stackHashMap.values()){
if (stack != null && !DemonAPI.itemIsNull(stack)) {
player.getInventory().addItem(stack);
}
}
// 提示玩家邮件签收成功并播放声音
player.sendMessage(LangUtil.signed_successfully.replace("{amount}",String.valueOf(stackHashMap.size())));
player.playSound(playerLocation, Sound.ENTITY_EXPERIENCE_ORB_PICKUP,0.8F,1.4F);
// 重置玩家数据中的邮件数据
playerData.resetMailData();
// 保存邮件物品堆数据
playerData.saveMailStack();
// 关闭玩家的界面
player.closeInventory();
}
}
}
}

View File

@ -0,0 +1,42 @@
package com.yaohun.playermail.listener;
import com.yaohun.playermail.MailMain;
import com.yaohun.playermail.data.PlayerData;
import com.yaohun.playermail.manage.PlayerManager;
import com.yaohun.playermail.util.LangUtil;
import me.Demon.DemonPlayerMail.Api.DMailAPI;
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.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
public class PlayerListener implements Listener {
public PlayerListener(MailMain plugin){
plugin.getServer().getPluginManager().registerEvents(this,plugin);
}
@EventHandler
public void onjoin(PlayerChangedWorldEvent e){
Player p = e.getPlayer();
String playerName = p.getName();
PlayerManager playerManager = MailMain.getPlayerManager();
PlayerData playerData = playerManager.getPlayerData(playerName);
int amountMail = playerData.getMailAmount();
if(amountMail >= 1){
OpenMail(p, LangUtil.notice_player.replace("{amount}",String.valueOf(amountMail)));
}
}
public static void OpenMail (Player player,String message) {
TextComponent Click = new TextComponent(message);
Click.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("§e点击打开邮箱").create()));
Click.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/dpmail open"));
player.spigot().sendMessage(Click);
}
}

View File

@ -0,0 +1,37 @@
package com.yaohun.playermail.manage;
import com.yaohun.playermail.data.PlayerData;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
public class PlayerManager {
private Map<String, PlayerData> playerDataMap = new HashMap<>();
public PlayerManager(){
for (Player player : Bukkit.getOnlinePlayers()){
if(player.getLevel() >= 50){
String playerName = player.getName();
PlayerData playerData = new PlayerData(playerName);
playerDataMap.put(playerName, playerData);
}
}
}
public PlayerData getPlayerData(String playerName){
if(!playerDataMap.containsKey(playerName)) {
PlayerData playerData = new PlayerData(playerName);
playerDataMap.put(playerName, playerData);
}
return playerDataMap.get(playerName);
}
public void saveAllPlayerData(){
for (PlayerData playerData : playerDataMap.values()){
playerData.saveMailStack();
}
}
}

View File

@ -0,0 +1,27 @@
package com.yaohun.playermail.util;
import me.Demon.DemonPlugin.DemonAPI;
import me.Demon.DemonPlugin.Util.AreaType;
public class LangUtil {
public static String player_mail_title = "§m§a§i§l§r学院邮箱 - 玩家收件箱";
public static String notice_player = "§7[§a§l邮箱§7] §f您的私人邮件箱有§a[{amount}件]§f物品尚未签收 §e[点击签收]";
public static String mail_no_items = "§7[§a§l邮箱§7] §f你没有可签收的物品";
public static String insufficient_backpack_space = "§7[§a§l邮箱§7] §f背包没有足够的空间放置邮箱物品";
public static String signed_successfully = "§7[§a§l邮箱§7] §f成功签收 §a{amount}件 §f物品";
public static String admin_no_items_sent = "§7[§a§l邮箱§7] §f你没有可发送的物品";
public static String admin_sent_successfully = "§7[§a§l邮箱§7] §f成功发送物品到 §6{player} §f的游戏邮箱中.";
public static void initLangUtil() {
if(DemonAPI.getAreaType() == AreaType.TaiWan){
player_mail_title = "§m§a§i§l§r學院郵箱 - 玩家收件箱";
notice_player = "§7[§a§l郵箱§7] §f您的私人郵件箱有§a[{amount}件]§f物品尚未簽收 §e[點擊簽收]";
mail_no_items = "§7[§a§l郵箱§7] §f你沒有可簽收的物品";
insufficient_backpack_space = "§7[§a§l郵箱§7] §f背包沒有足夠的空間放置郵箱物品";
signed_successfully = "§7[§a§l郵箱§7] §f成功簽收 §a{amount}件 §f物品";
admin_no_items_sent = "§7[§a§l郵箱§7] §f你沒有可發送的物品";
admin_sent_successfully = "§7[§a§l郵箱§7] §f成功發送物品到 §6{player} §f的遊戲郵箱中.";
}
}
}

View File

@ -0,0 +1,46 @@
package me.Demon.DemonPlayerMail.Api;
import com.yaohun.playermail.MailMain;
import com.yaohun.playermail.data.PlayerData;
import com.yaohun.playermail.manage.PlayerManager;
import me.Demon.DemonPlugin.DemonAPI;
import me.Demon.DemonPlugin.Util.RandomUtil;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
/**
* @author Administrator
*/
public class DMailAPI {
public static void GiveItem(String playerName, ItemStack stack) {
PlayerManager playerManager = MailMain.getPlayerManager();
PlayerData playerData = playerManager.getPlayerData(playerName);
int totalAmount = stack.getAmount();
while (totalAmount > 0) {
if (totalAmount >= 64) {
// 创建一个新的 ItemStack数量为64
ItemStack fullStack = stack.clone();
fullStack.setAmount(64);
// 给予玩家满的 64 个物品
long expiryTime = System.currentTimeMillis() + (1000 * 60 * 60 * 24 * 3) + RandomUtil.getRandomInt(1, 10000);
playerData.addMailStack(expiryTime, fullStack);
// 减去已处理的数量
totalAmount -= 64;
} else {
// 创建一个新的 ItemStack数量为剩余的物品数量
ItemStack remainingStack = stack.clone();
remainingStack.setAmount(totalAmount);
// 给予玩家剩余的物品
long expiryTime = System.currentTimeMillis() + (1000 * 60 * 60 * 24 * 3) + RandomUtil.getRandomInt(1, 10000);
playerData.addMailStack(expiryTime, remainingStack);
// 剩余数量为0结束循环
totalAmount = 0;
}
}
}
}

View File

@ -0,0 +1,7 @@
name: DemonPlayerMail
main: com.yaohun.playermail.MailMain
version: 2.0.0
depend:
- DemonAPI
commands:
dpmail: