update 8
This commit is contained in:
@@ -17,14 +17,10 @@ import java.util.UUID;
|
||||
public class PlayerTags {
|
||||
private final Survival plugin;
|
||||
private final File tagsFile;
|
||||
// 原有:玩家-称号列表映射
|
||||
private final Map<UUID, List<String>> playerTags = new HashMap<>();
|
||||
// 新增:玩家-(称号-到期时间戳)映射(毫秒级,永久用Long.MAX_VALUE)
|
||||
private final Map<UUID, Map<String, Long>> expireTimeMap = new HashMap<>();
|
||||
// 原有:玩家-选中称号索引映射
|
||||
public Map<UUID, Integer> playerselectTag = new HashMap<>();
|
||||
|
||||
// 常量:7天的毫秒数(7*24*60*60*1000)
|
||||
private static final long SEVEN_DAYS_MS = 604800000L;
|
||||
|
||||
public PlayerTags(Survival plugin) {
|
||||
@@ -32,36 +28,28 @@ public class PlayerTags {
|
||||
this.tagsFile = new File(plugin.getDataFolder(), "playertags.data");
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心辅助:清理玩家的所有过期称号(所有方法调用前先执行)
|
||||
*/
|
||||
public void cleanExpiredTags(Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
List<String> validTags = new ArrayList<>();
|
||||
List<String> allTags = playerTags.getOrDefault(uuid, new ArrayList<>());
|
||||
Map<String, Long> tagExpires = expireTimeMap.getOrDefault(uuid, new HashMap<>());
|
||||
|
||||
// 遍历所有称号,保留未过期的
|
||||
for (String tag : allTags) {
|
||||
long expireTime = tagExpires.getOrDefault(tag, Long.MAX_VALUE);
|
||||
// 未过期判断:永久(MAX)或当前时间 < 到期时间
|
||||
if (expireTime == Long.MAX_VALUE || System.currentTimeMillis() < expireTime) {
|
||||
validTags.add(tag);
|
||||
} else {
|
||||
// 过期:移除过期时间记录
|
||||
tagExpires.remove(tag);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新有效称号列表和过期时间映射
|
||||
if (validTags.isEmpty()) {
|
||||
playerTags.remove(uuid);
|
||||
expireTimeMap.remove(uuid);
|
||||
playerselectTag.put(uuid, -1); // 无有效称号,重置选中索引
|
||||
playerselectTag.put(uuid, -1);
|
||||
} else {
|
||||
playerTags.put(uuid, validTags);
|
||||
expireTimeMap.put(uuid, tagExpires);
|
||||
// 检查选中的称号是否已过期:若过期/索引无效,重置索引
|
||||
int currentIndex = playerselectTag.getOrDefault(uuid, -1);
|
||||
if (currentIndex == -1 || currentIndex >= validTags.size()) {
|
||||
playerselectTag.put(uuid, -1);
|
||||
@@ -69,11 +57,8 @@ public class PlayerTags {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前选中的称号索引(自动过滤过期)
|
||||
*/
|
||||
public int getCurrentTag(Player player) {
|
||||
cleanExpiredTags(player); // 先清理过期
|
||||
cleanExpiredTags(player);
|
||||
UUID uuid = player.getUniqueId();
|
||||
Integer index = playerselectTag.get(uuid);
|
||||
if (index == null) {
|
||||
@@ -82,34 +67,29 @@ public class PlayerTags {
|
||||
|
||||
List<String> validTags = playerTags.getOrDefault(uuid, new ArrayList<>());
|
||||
if (validTags.isEmpty() || index < 0 || index >= validTags.size()) {
|
||||
playerselectTag.put(uuid, -1); // 索引无效,重置
|
||||
playerselectTag.put(uuid, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置玩家选择的标签索引(自动过滤过期)
|
||||
*/
|
||||
public boolean setSelectedTag(Player player, int index) {
|
||||
cleanExpiredTags(player); // 先清理过期
|
||||
cleanExpiredTags(player);
|
||||
UUID uuid = player.getUniqueId();
|
||||
List<String> validTags = playerTags.getOrDefault(uuid, new ArrayList<>());
|
||||
|
||||
// 无有效称号或索引无效,返回失败
|
||||
if (validTags.isEmpty() || index < 0 || index >= validTags.size()) {
|
||||
playerselectTag.put(uuid, -1);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置选中索引,返回成功
|
||||
playerselectTag.put(uuid, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载称号数据:核心逻辑——识别旧数据并转为7天过期
|
||||
* 修复核心:正确读取新版本数据中的expireTimeMap,避免误判为旧数据
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void loadTags() {
|
||||
@@ -118,17 +98,27 @@ public class PlayerTags {
|
||||
}
|
||||
|
||||
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(tagsFile))) {
|
||||
// 读取第一个对象:判断是旧版本(List<String>)还是新版本(含过期时间)
|
||||
// 读取三个核心对象(新版本数据结构)
|
||||
Object firstObj = ois.readObject();
|
||||
Object secondObj = ois.readObject();
|
||||
Object thirdObj = null; // 新版本的第三个对象:expireTimeMap
|
||||
Object thirdObj = ois.readObject(); // 关键修复:读取第三个对象(expireTimeMap)
|
||||
|
||||
// 1. 识别旧版本数据(仅2个对象:playerTags + playerselectTag)
|
||||
if (firstObj instanceof Map<?, ?> && secondObj instanceof Map<?, ?> && ois.available() == 0) {
|
||||
// 1. 优先判断新版本数据(3个对象完整)
|
||||
if (firstObj instanceof Map<?, ?> && secondObj instanceof Map<?, ?> && thirdObj instanceof Map<?, ?>) {
|
||||
// 强制转换并加载数据
|
||||
playerTags.putAll((Map<UUID, List<String>>) firstObj);
|
||||
playerselectTag.putAll((Map<UUID, Integer>) secondObj);
|
||||
expireTimeMap.putAll((Map<UUID, Map<String, Long>>) thirdObj);
|
||||
plugin.getLogger().info("新版本称号数据加载完成!共加载 " + playerTags.size() + " 个玩家的称号");
|
||||
return; // 加载成功直接返回,避免进入旧数据处理
|
||||
}
|
||||
|
||||
// 2. 处理旧版本数据(仅2个对象:无expireTimeMap)
|
||||
if (firstObj instanceof Map<?, ?> && secondObj instanceof Map<?, ?>) {
|
||||
Map<UUID, List<String>> oldPlayerTags = (Map<UUID, List<String>>) firstObj;
|
||||
Map<UUID, Integer> oldSelectTag = (Map<UUID, Integer>) secondObj;
|
||||
|
||||
// 旧数据转换:为每个称号设置“当前时间+7天”的到期时间
|
||||
// 旧数据转换为7天过期
|
||||
for (Map.Entry<UUID, List<String>> entry : oldPlayerTags.entrySet()) {
|
||||
UUID uuid = entry.getKey();
|
||||
List<String> oldTags = entry.getValue();
|
||||
@@ -136,34 +126,27 @@ public class PlayerTags {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 为当前玩家创建“称号-到期时间”映射
|
||||
Map<String, Long> tagExpires = new HashMap<>();
|
||||
long sevenDaysLater = System.currentTimeMillis() + SEVEN_DAYS_MS; // 7天后到期
|
||||
long sevenDaysLater = System.currentTimeMillis() + SEVEN_DAYS_MS;
|
||||
for (String tag : oldTags) {
|
||||
tagExpires.put(tag, sevenDaysLater); // 每个旧称号都设为7天过期
|
||||
tagExpires.put(tag, sevenDaysLater);
|
||||
}
|
||||
|
||||
// 存入新结构
|
||||
playerTags.put(uuid, new ArrayList<>(oldTags)); // 复制旧称号列表
|
||||
expireTimeMap.put(uuid, tagExpires); // 存入7天过期时间
|
||||
playerTags.put(uuid, new ArrayList<>(oldTags));
|
||||
expireTimeMap.put(uuid, tagExpires);
|
||||
}
|
||||
|
||||
// 恢复选中索引
|
||||
playerselectTag.putAll(oldSelectTag);
|
||||
plugin.getLogger().info("旧版本称号数据加载完成,已自动转为7日后到期!");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
// 2. 识别新版本数据(3个对象:playerTags + playerselectTag + expireTimeMap)
|
||||
else if (firstObj instanceof Map<?, ?> && secondObj instanceof Map<?, ?> && thirdObj instanceof Map<?, ?>) {
|
||||
playerTags.putAll((Map<UUID, List<String>>) firstObj);
|
||||
playerselectTag.putAll((Map<UUID, Integer>) secondObj);
|
||||
expireTimeMap.putAll((Map<UUID, Map<String, Long>>) thirdObj);
|
||||
plugin.getLogger().info("新版本称号数据加载完成!");
|
||||
}
|
||||
// 3. 数据格式错误
|
||||
plugin.getLogger().warning("称号数据格式错误,无法识别!");
|
||||
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
// 回退逻辑:仅加载称号列表,所有称号设为7天过期
|
||||
// 回退逻辑:仅加载称号列表,设为7天过期
|
||||
try (ObjectInputStream fallback = new ObjectInputStream(new FileInputStream(tagsFile))) {
|
||||
Object obj = fallback.readObject();
|
||||
if (obj instanceof Map<?, ?> oldPlayerTags) {
|
||||
@@ -176,7 +159,7 @@ public class PlayerTags {
|
||||
for (Object tagObj : (List<?>) entry.getValue()) {
|
||||
if (tagObj instanceof String tag) {
|
||||
tags.add(tag);
|
||||
tagExpires.put(tag, sevenDaysLater); // 回退时也设为7天过期
|
||||
tagExpires.put(tag, sevenDaysLater);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,16 +176,13 @@ public class PlayerTags {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存称号数据:同步保存playerTags、playerselectTag、expireTimeMap
|
||||
*/
|
||||
public void saveTags() {
|
||||
if (!tagsFile.getParentFile().exists()) {
|
||||
tagsFile.getParentFile().mkdirs();
|
||||
}
|
||||
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(tagsFile))) {
|
||||
// 按顺序写入3个核心结构(新版本)
|
||||
// 按顺序写入三个核心结构(与加载时对应)
|
||||
oos.writeObject(playerTags);
|
||||
oos.writeObject(playerselectTag);
|
||||
oos.writeObject(expireTimeMap);
|
||||
@@ -211,71 +191,50 @@ public class PlayerTags {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取玩家的有效称号列表(自动过滤过期)
|
||||
*/
|
||||
public List<String> getTags(Player player) {
|
||||
cleanExpiredTags(player);
|
||||
return playerTags.getOrDefault(player.getUniqueId(), new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增称号:默认永久(可手动指定过期时间)
|
||||
*
|
||||
* @param player 目标玩家
|
||||
* @param tag 称号名称
|
||||
* @param isPermanent 是否永久(true=永久,false=7天过期)
|
||||
*/
|
||||
public void addTag(Player player, String tag, boolean isPermanent) {
|
||||
cleanExpiredTags(player); // 先清理过期
|
||||
cleanExpiredTags(player);
|
||||
UUID uuid = player.getUniqueId();
|
||||
List<String> tags = playerTags.computeIfAbsent(uuid, k -> new ArrayList<>());
|
||||
Map<String, Long> tagExpires = expireTimeMap.computeIfAbsent(uuid, k -> new HashMap<>());
|
||||
|
||||
// 避免重复添加相同称号
|
||||
if (!tags.contains(tag)) {
|
||||
tags.add(tag);
|
||||
// 设置过期时间:永久=Long.MAX_VALUE,临时=当前时间+7天
|
||||
long expireTime = isPermanent ? Long.MAX_VALUE : System.currentTimeMillis() + SEVEN_DAYS_MS;
|
||||
tagExpires.put(tag, expireTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载原有addTag方法:默认添加永久称号(保持向下兼容)
|
||||
*/
|
||||
public void addTag(Player player, String tag, int days) {
|
||||
cleanExpiredTags(player); // 先清理过期
|
||||
cleanExpiredTags(player);
|
||||
UUID uuid = player.getUniqueId();
|
||||
List<String> tags = playerTags.computeIfAbsent(uuid, k -> new ArrayList<>());
|
||||
Map<String, Long> tagExpires = expireTimeMap.computeIfAbsent(uuid, k -> new HashMap<>());
|
||||
|
||||
// 避免重复添加相同称号
|
||||
if (!tags.contains(tag)) {
|
||||
tags.add(tag);
|
||||
long expireTime;
|
||||
if (days == 999) {
|
||||
expireTime = Long.MAX_VALUE; // 999天视为永久
|
||||
expireTime = Long.MAX_VALUE;
|
||||
} else if (days <= 0) {
|
||||
expireTime = System.currentTimeMillis() - 1; // 天数≤0:立即过期(触发清理)
|
||||
expireTime = System.currentTimeMillis() - 1;
|
||||
} else {
|
||||
// 计算有效期:当前时间 + 天数×24×60×60×1000(转换为毫秒)
|
||||
expireTime = System.currentTimeMillis() + (long) days * 24 * 60 * 60 * 1000;
|
||||
}
|
||||
tagExpires.put(tag, expireTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除称号:同时删除过期时间记录
|
||||
*/
|
||||
public void removeTag(Player player, String tag) {
|
||||
cleanExpiredTags(player);
|
||||
UUID uuid = player.getUniqueId();
|
||||
List<String> tags = playerTags.get(uuid);
|
||||
Map<String, Long> tagExpires = expireTimeMap.get(uuid);
|
||||
|
||||
// 移除称号列表和过期时间映射中的对应条目
|
||||
if (tags != null) {
|
||||
tags.remove(tag);
|
||||
if (tags.isEmpty()) {
|
||||
@@ -293,7 +252,6 @@ public class PlayerTags {
|
||||
}
|
||||
}
|
||||
|
||||
// 若移除的是当前选中称号,重置索引
|
||||
int currentIndex = playerselectTag.getOrDefault(uuid, -1);
|
||||
List<String> validTags = playerTags.getOrDefault(uuid, new ArrayList<>());
|
||||
if (currentIndex != -1 && (currentIndex >= validTags.size() || !validTags.contains(tag))) {
|
||||
@@ -301,30 +259,20 @@ public class PlayerTags {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增:获取称号的到期时间(返回时间戳,单位毫秒)
|
||||
*
|
||||
* @return 永久返回-1,过期/不存在返回-2,有效返回到期时间戳
|
||||
*/
|
||||
public long getTagExpireTime(Player player, String tag) {
|
||||
cleanExpiredTags(player);
|
||||
UUID uuid = player.getUniqueId();
|
||||
Map<String, Long> tagExpires = expireTimeMap.getOrDefault(uuid, new HashMap<>());
|
||||
List<String> validTags = playerTags.getOrDefault(uuid, new ArrayList<>());
|
||||
|
||||
// 称号不存在或已过期,返回-2
|
||||
if (!validTags.contains(tag)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
long expireTime = tagExpires.getOrDefault(tag, Long.MAX_VALUE);
|
||||
// 永久称号返回-1,否则返回时间戳
|
||||
return expireTime == Long.MAX_VALUE ? -1 : expireTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增:获取称号的剩余时间(返回字符串,如“2天3小时”)
|
||||
*/
|
||||
public String getTagRemainingTime(Player player, String tag) {
|
||||
long expireTime = getTagExpireTime(player, tag);
|
||||
if (expireTime == -1) {
|
||||
@@ -334,18 +282,15 @@ public class PlayerTags {
|
||||
return "已过期/不存在";
|
||||
}
|
||||
|
||||
// 计算剩余毫秒数(可能为负,需处理)
|
||||
long remainingMs = expireTime - System.currentTimeMillis();
|
||||
if (remainingMs <= 0) {
|
||||
return "已过期";
|
||||
}
|
||||
|
||||
// 转换为天、时、分
|
||||
long days = remainingMs / (24 * 60 * 60 * 1000);
|
||||
long hours = (remainingMs % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000);
|
||||
long minutes = (remainingMs % (60 * 60 * 1000)) / (60 * 1000);
|
||||
|
||||
// 拼接剩余时间字符串
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (days > 0) sb.append(days).append("天");
|
||||
if (hours > 0) sb.append(hours).append("小时");
|
||||
|
||||
@@ -3,15 +3,23 @@ package org.xgqy.survival;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.xgqy.survival.command.DqshopCommandExecutor;
|
||||
import org.xgqy.survival.command.FriendCommandExecutor;
|
||||
import org.xgqy.survival.command.HandleCommandExecutor;
|
||||
import org.xgqy.survival.command.HelpCommandExecutor;
|
||||
import org.xgqy.survival.command.HubCommandExecutor;
|
||||
import org.xgqy.survival.command.InventoryCommandExecutor;
|
||||
import org.xgqy.survival.command.KillCommandExecutor;
|
||||
import org.xgqy.survival.command.LandCommandExecutor;
|
||||
import org.xgqy.survival.command.LoginCommandExecutor;
|
||||
import org.xgqy.survival.command.PartyCommandExecutor;
|
||||
import org.xgqy.survival.command.PcCommandExecutor;
|
||||
import org.xgqy.survival.command.PointCommandExecutor;
|
||||
import org.xgqy.survival.command.PvpCommandExecutor;
|
||||
import org.xgqy.survival.command.RegCommandExecutor;
|
||||
import org.xgqy.survival.command.ReportCommandExecutor;
|
||||
@@ -20,25 +28,34 @@ import org.xgqy.survival.command.TagCommandExecutor;
|
||||
import org.xgqy.survival.command.TeleportCommandExecutor;
|
||||
import org.xgqy.survival.command.TpAccCommandExecutor;
|
||||
import org.xgqy.survival.command.TpFinCommandExecutor;
|
||||
import org.xgqy.survival.command.msgCommandExecutor;
|
||||
import org.xgqy.survival.event.ChatEvent;
|
||||
import org.xgqy.survival.event.ChooseTagEvent;
|
||||
import org.xgqy.survival.event.JoinEvent;
|
||||
import org.xgqy.survival.event.LandEvent;
|
||||
import org.xgqy.survival.event.LoginEvent;
|
||||
import org.xgqy.survival.event.QuitEvent;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public final class Survival extends JavaPlugin {
|
||||
private PlayerTags playerTags;
|
||||
private AccountManager accountManager; // 新增账号管理器
|
||||
private AccountManager accountManager;
|
||||
public Map<Player, Boolean> krt = new HashMap<>();
|
||||
public Map<Player, Player> banlist = new HashMap<>();
|
||||
public Map<Player, String> banreason = new HashMap<>();
|
||||
public Map<Player, HashSet<Player>> reportlist = new HashMap<>();
|
||||
// Teleport
|
||||
public Map<Player, Player> teleport = new HashMap<>();
|
||||
public Map<Player, Player> Ateleport = new HashMap<>();
|
||||
public Map<Player, Location> teleportp = new HashMap<>();
|
||||
@@ -50,94 +67,347 @@ public final class Survival extends JavaPlugin {
|
||||
party
|
||||
----------------------------------------
|
||||
*/
|
||||
public Map<Player,Integer> party = new HashMap<>();
|
||||
public Map<Integer,List<Player>> partyp = new HashMap<>();
|
||||
public Map<Integer,Player> owner = new HashMap<>();
|
||||
public Map<Integer,List<Player>> ban = new HashMap<>();
|
||||
public Map<Player, Integer> party = new HashMap<>();
|
||||
public Map<Integer, List<Player>> partyp = new HashMap<>();
|
||||
public Map<Integer, Player> owner = new HashMap<>();
|
||||
public Map<Integer, List<Player>> ban = new HashMap<>();
|
||||
/*
|
||||
----------------------------------------
|
||||
friend
|
||||
----------------------------------------
|
||||
*/
|
||||
public Map<Player,List<Player>> friends = new HashMap<>();
|
||||
public Map<Player, List<Player>> friends = new ConcurrentHashMap<>();
|
||||
public Map<Player, List<Player>> waiting = new ConcurrentHashMap<>();
|
||||
/*
|
||||
----------------------------------------
|
||||
信用分
|
||||
----------------------------------------
|
||||
*/
|
||||
public Map<Player, Integer> ppoint = new HashMap<>();
|
||||
private List<String> msg = new ArrayList<>();
|
||||
public Map<Player, String> breason = new HashMap<>();
|
||||
/*
|
||||
----------------------------------------
|
||||
领地
|
||||
----------------------------------------
|
||||
*/
|
||||
public static class Land{
|
||||
public Location start,end;
|
||||
public List<Boolean> defaultperm;
|
||||
public String owner;
|
||||
public Map<String,List<Boolean>> perm;
|
||||
public boolean boomb;
|
||||
public Land(Location start,Location end,List<Boolean> defaultperm,String owner,Map<String,List<Boolean>> perm){
|
||||
this.start=start;
|
||||
this.end=end;
|
||||
this.defaultperm = defaultperm;
|
||||
this.owner=owner;
|
||||
this.perm=perm;
|
||||
}
|
||||
public Boolean getBoomb(){
|
||||
return boomb;
|
||||
}
|
||||
public void setBoomb(Boolean boomb){
|
||||
this.boomb=boomb;
|
||||
}
|
||||
public Location getStart(){
|
||||
return start;
|
||||
}
|
||||
public Location getEnd(){
|
||||
return end;
|
||||
}
|
||||
public List<Boolean> getDefaultperm(){
|
||||
return defaultperm;
|
||||
}
|
||||
public String getOwner(){
|
||||
return owner;
|
||||
}
|
||||
public List<Boolean> getPerm(Player player){
|
||||
return perm.getOrDefault(player,null);
|
||||
}
|
||||
public void setStart(Location start){
|
||||
this.start=start;
|
||||
}
|
||||
public void setEnd(Location end) {
|
||||
this.end = end;
|
||||
}
|
||||
public void setDefaultperm(List<Boolean> defaultperm){
|
||||
this.defaultperm=defaultperm;
|
||||
}
|
||||
public void setOwner(String owner){
|
||||
this.owner=owner;
|
||||
}
|
||||
public void setPerm(Player player,List<Boolean> perm){
|
||||
this.perm.put(player.getName(),perm);
|
||||
}
|
||||
}
|
||||
public List<Land> land =new ArrayList<>();
|
||||
|
||||
public Map<Player,String> inland=new HashMap<>();
|
||||
// 信用分数据文件相关
|
||||
private File ppointFile;
|
||||
private FileConfiguration ppointConfig;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// 初始化账号管理器
|
||||
accountManager = new AccountManager(this);
|
||||
|
||||
msg.add(ChatColor.GREEN+"可以用 /help 命令来查看命令列表");
|
||||
msg.add(ChatColor.GREEN+"如果遇到作弊玩家可以用 /report <玩家名> <原因> 来举报!管理员会很快处理的");
|
||||
msg.add(ChatColor.GREEN+"想传送到玩家怎么办? 用 /teleport <玩家名> 命令!");
|
||||
msg.add(ChatColor.GREEN+"更换IP但没有更换账号导致的封禁不能找管理员解决");
|
||||
msg.add(ChatColor.GREEN+"星阁钱语的名称其实叫星阁浅语");
|
||||
msg.add(ChatColor.RED+"作弊会导致账号封禁!请不要作弊");
|
||||
msg.add(ChatColor.RED+"在服务器内说不文明用语会导致账号被封禁,请不要这样做");
|
||||
msg.add(ChatColor.GREEN+"今天签到了吗?快输入 /qd 签到吧!");
|
||||
msg.add(ChatColor.GREEN+"其实可以输入 /pvp 来开启/关闭自己的pvp模式");
|
||||
msg.add(ChatColor.RED+"你不可以把别人的家毁掉!这样你将会受到处罚");
|
||||
msg.add(ChatColor.GOLD+"能给我捐点钱吗");
|
||||
// 初始化信用分数据文件
|
||||
initPpointFile();
|
||||
// 加载已在线玩家的信用分数据
|
||||
loadPpoint();
|
||||
|
||||
new BukkitRunnable(){
|
||||
msg.add(ChatColor.GREEN + "可以用 /help 命令来查看命令列表");
|
||||
msg.add(ChatColor.GREEN + "如果遇到作弊玩家可以用 /report <玩家名> <原因> 来举报!管理员会很快处理的");
|
||||
msg.add(ChatColor.GREEN + "想传送到玩家怎么办? 用 /teleport <玩家名> 命令!");
|
||||
msg.add(ChatColor.GREEN + "更换IP但没有更换账号导致的封禁不能找管理员解决");
|
||||
msg.add(ChatColor.GREEN + "星阁钱语的名称其实叫星阁浅语");
|
||||
msg.add(ChatColor.RED + "作弊会导致账号封禁!请不要作弊");
|
||||
msg.add(ChatColor.RED + "在服务器内说不文明用语会导致账号被封禁,请不要这样做");
|
||||
msg.add(ChatColor.GREEN + "今天签到了吗?快输入 /qd 签到吧!");
|
||||
msg.add(ChatColor.GREEN + "其实可以输入 /pvp 来开启/关闭自己的pvp模式");
|
||||
msg.add(ChatColor.RED + "你不可以把别人的家毁掉!这样你将会受到处罚");
|
||||
msg.add(ChatColor.GREEN + "每日坚持签到可以获得信用分");
|
||||
msg.add(ChatColor.GREEN + "服务器官网: https://starpavilion.xyz");
|
||||
msg.add(ChatColor.GREEN + "赞助我们? https://starpavilion.xyz/sponsor.html");
|
||||
msg.add(ChatColor.RED+"封禁者会在此处公示: https://starpavilion.xyz/bans.html");
|
||||
msg.add(ChatColor.RED + "信用分过低将会导致你的账号受限甚至永久封禁!");
|
||||
msg.add(ChatColor.GREEN + "信用分被扣除会提醒,如果您的信用分被莫名扣除,请及时到QQ群 717903781 申诉。");
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for(Player plr : Bukkit.getOnlinePlayers()){
|
||||
for (Player plr : Bukkit.getOnlinePlayers()) {
|
||||
// 只向已登录玩家发送提示
|
||||
if (accountManager.isLoggedIn(plr)) {
|
||||
plr.sendMessage(ChatColor.LIGHT_PURPLE+"小提示 "+ChatColor.WHITE+" | "+msg.get((int)(Math.random()*10000)%msg.size()));
|
||||
plr.sendMessage(ChatColor.LIGHT_PURPLE + "小提示 " + ChatColor.WHITE + " | " + msg.get((int) (Math.random() * 10000) % msg.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}.runTaskLater(this,20*60);
|
||||
}.runTaskLater(this, 20 * 60);
|
||||
|
||||
// Plugin startup logic
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Player plr : Bukkit.getOnlinePlayers()) {
|
||||
// 检查玩家是否有违规扣分记录
|
||||
if (plr.getScoreboard().getObjective("handled") != null &&
|
||||
plr.getScoreboard().getObjective("handled").getScore(plr).getScore() != 0) {
|
||||
|
||||
ZonedDateTime beijingTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
String formattedTime = beijingTime.format(formatter);
|
||||
|
||||
// 确保玩家信用分已初始化
|
||||
int currentPoint = ppoint.getOrDefault(plr, 100);
|
||||
int deductPoint = plr.getScoreboard().getObjective("handled").getScore(plr).getScore();
|
||||
int newPoint = currentPoint - deductPoint;
|
||||
//ppoint.put(plr, newPoint);
|
||||
|
||||
// 发送扣分提示
|
||||
plr.sendMessage(ChatColor.RED + "警告" + ChatColor.WHITE + " | " + ChatColor.RED + "您的账号 " + ChatColor.YELLOW + plr.getName() + ChatColor.RED + " 在 " + ChatColor.WHITE + formattedTime + ChatColor.RED + " 有疑似违规行为,扣取信用分 " + ChatColor.YELLOW + deductPoint + ChatColor.RED + " 分。\n");
|
||||
plr.sendMessage(ChatColor.RED + "-----------警告单-----------");
|
||||
plr.sendMessage(ChatColor.RED + "|账号名: " + ChatColor.YELLOW + plr.getName());
|
||||
plr.sendMessage(ChatColor.RED + "|违规时间: " + ChatColor.YELLOW + formattedTime);
|
||||
plr.sendMessage(ChatColor.RED + "|违规行为: " + ChatColor.YELLOW + breason.getOrDefault(plr, "管理员扣分"));
|
||||
plr.sendMessage(ChatColor.RED + "|违规扣分: " + ChatColor.YELLOW + deductPoint + " 分");
|
||||
plr.sendMessage(ChatColor.RED + "|剩余信用分: " + ChatColor.YELLOW + newPoint);
|
||||
|
||||
// 根据剩余信用分执行处罚
|
||||
if (newPoint > 80) {
|
||||
plr.sendMessage(ChatColor.RED + "|采取处罚: " + ChatColor.YELLOW + "无");
|
||||
} else if (newPoint <= 0) {
|
||||
plr.kickPlayer(ChatColor.RED + "您好! 您由于在 " + formattedTime + " 信用分小于 0 ,我们决定对你的账号 " + plr.getName() + " 采取\n" + ChatColor.RED + ChatColor.BOLD + "永久封禁\n" + ChatColor.RED + "措施,如果您想解封您的账号,请到QQ群 717903781 申诉\n\n" + ChatColor.RED + "如果您对本次处罚不满,请采取以下措施:\n" + ChatColor.YELLOW + "1.如果您对自己的行为" + ChatColor.BOLD + " 问心无愧 " + ChatColor.YELLOW + "请立即向QQ 2213866559 发送解封申请\n" + ChatColor.YELLOW + "2.如果您属实有违规行为,请" + ChatColor.BOLD + "手写" + ChatColor.YELLOW + "一篇 " + ChatColor.BOLD + "100字以上且AIGC合格" + ChatColor.YELLOW + " 的检讨发送到申诉QQ群,态度诚恳我们将会对你进行解封");
|
||||
} else if (newPoint <= 20) {
|
||||
plr.sendMessage(ChatColor.RED + "|采取处罚: " + ChatColor.YELLOW + "限制行为及发言,列入监管名单,限制功能使用");
|
||||
} else if (newPoint <= 50) {
|
||||
plr.sendMessage(ChatColor.RED + "|采取处罚: " + ChatColor.YELLOW + "限制行为及发言,限制功能使用");
|
||||
} else if (newPoint <= 80) {
|
||||
plr.sendMessage(ChatColor.RED + "|采取处罚: " + ChatColor.YELLOW + "监管行为及发言,签到将奖励转换为信用分");
|
||||
}
|
||||
plr.sendMessage(ChatColor.RED + "|为了维护游戏环境,请不要违规!");
|
||||
plr.sendMessage(ChatColor.RED + "----------------------------");
|
||||
|
||||
// 清理临时数据
|
||||
breason.remove(plr);
|
||||
plr.getScoreboard().getObjective("handled").getScore(plr).setScore(0);
|
||||
|
||||
// 实时保存扣分后的信用分数据
|
||||
savePpoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(this, 20 * 5, 20 * 5);
|
||||
|
||||
// 初始化玩家标签
|
||||
playerTags = new PlayerTags(this);
|
||||
playerTags.loadTags();
|
||||
|
||||
// 注册事件监听器,包括新的登录事件
|
||||
// 注册事件监听器
|
||||
Bukkit.getPluginManager().registerEvents(new JoinEvent(this), this);
|
||||
Bukkit.getPluginManager().registerEvents(new ChatEvent(this), this);
|
||||
Bukkit.getPluginManager().registerEvents(new ChooseTagEvent(this), this);
|
||||
Bukkit.getPluginManager().registerEvents(new LoginEvent(this), this); // 新增登录事件监听器
|
||||
Bukkit.getPluginManager().registerEvents(new QuitEvent(this),this);
|
||||
//Bukkit.getPluginManager().registerEvents(new AntiExploit(),this);
|
||||
//Bukkit.getPluginManager().registerEvents(new AntiXray(this),this);
|
||||
Bukkit.getPluginManager().registerEvents(new LoginEvent(this), this);
|
||||
Bukkit.getPluginManager().registerEvents(new LandEvent(this),this);
|
||||
|
||||
// 注册命令执行器,包括新的注册和登录命令
|
||||
// 注册命令执行器
|
||||
getCommand("report").setExecutor(new ReportCommandExecutor(this));
|
||||
getCommand("handle").setExecutor(new HandleCommandExecutor(this));
|
||||
getCommand("pvp").setExecutor(new PvpCommandExecutor(this));
|
||||
getCommand("settag").setExecutor(new SetTagCommandExecutor(this));
|
||||
getCommand("help").setExecutor(new HelpCommandExecutor(this));
|
||||
//getCommand("fly").setExecutor(new FlyCommandExecutor(this));
|
||||
getCommand("tag").setExecutor(new TagCommandExecutor(this));
|
||||
getCommand("hub").setExecutor(new HubCommandExecutor(this));
|
||||
getCommand("teleport").setExecutor(new TeleportCommandExecutor(this));
|
||||
getCommand("tpacc").setExecutor(new TpAccCommandExecutor(this));
|
||||
getCommand("tpfin").setExecutor(new TpFinCommandExecutor(this));
|
||||
getCommand("shop").setExecutor(new DqshopCommandExecutor(this));
|
||||
getCommand("reg").setExecutor(new RegCommandExecutor(this)); // 新增注册命令
|
||||
getCommand("login").setExecutor(new LoginCommandExecutor(this)); // 新增登录命令
|
||||
getCommand("reg").setExecutor(new RegCommandExecutor(this));
|
||||
getCommand("login").setExecutor(new LoginCommandExecutor(this));
|
||||
getCommand("party").setExecutor(new PartyCommandExecutor(this));
|
||||
getCommand("inventory").setExecutor(new InventoryCommandExecutor(this));
|
||||
getCommand("pc").setExecutor(new PcCommandExecutor(this));
|
||||
getCommand("msg").setExecutor(new msgCommandExecutor(this));
|
||||
getCommand("friend").setExecutor(new FriendCommandExecutor(this));
|
||||
getCommand("point").setExecutor(new PointCommandExecutor(this));
|
||||
getCommand("selfkill").setExecutor(new KillCommandExecutor(this));
|
||||
getCommand("land").setExecutor(new LandCommandExecutor(this));
|
||||
getLogger().info("Survival插件已启用,信用分持久化功能加载完成!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// 保存玩家标签数据
|
||||
playerTags.saveTags();
|
||||
accountManager.saveAccounts(); // 保存账号信息
|
||||
// Plugin shutdown logic
|
||||
|
||||
// 保存信用分数据
|
||||
savePpoint();
|
||||
|
||||
// 保存好友数据
|
||||
try {
|
||||
FriendCommandExecutor executor = (FriendCommandExecutor) this.getCommand("friend").getExecutor();
|
||||
if (executor != null) {
|
||||
executor.saveFriendData();
|
||||
getLogger().info("好友数据已保存!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
getLogger().severe("插件卸载时保存好友数据失败:" + e.getMessage());
|
||||
}
|
||||
|
||||
// 保存账号信息
|
||||
accountManager.saveAccounts();
|
||||
|
||||
getLogger().info("Survival插件已禁用,所有数据已保存!");
|
||||
}
|
||||
|
||||
// 初始化信用分数据文件
|
||||
private void initPpointFile() {
|
||||
// 创建插件数据文件夹(若不存在)
|
||||
File dataFolder = getDataFolder();
|
||||
if (!dataFolder.exists()) {
|
||||
if (dataFolder.mkdirs()) {
|
||||
getLogger().info("插件数据文件夹创建成功!");
|
||||
} else {
|
||||
getLogger().severe("插件数据文件夹创建失败!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建信用分文件(路径:plugins/Survival/ppoint.yml)
|
||||
ppointFile = new File(dataFolder, "ppoint.yml");
|
||||
if (!ppointFile.exists()) {
|
||||
try {
|
||||
if (ppointFile.createNewFile()) {
|
||||
getLogger().info("信用分数据文件创建成功!");
|
||||
} else {
|
||||
getLogger().severe("信用分数据文件创建失败!");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("创建信用分文件时发生异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 加载配置文件
|
||||
ppointConfig = YamlConfiguration.loadConfiguration(ppointFile);
|
||||
}
|
||||
|
||||
// 保存信用分数据到文件(关键修正处)
|
||||
public void savePpoint() {
|
||||
if (ppointConfig == null || ppointFile == null) {
|
||||
getLogger().severe("信用分配置未初始化,保存失败!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 修正:清空原有配置的正确方式(将所有键设为null或移除)
|
||||
for (String key : ppointConfig.getKeys(false)) {
|
||||
ppointConfig.set(key, null); // 用null覆盖原有值,或用 ppointConfig.remove(key) 直接移除键
|
||||
}
|
||||
|
||||
// 将在线玩家的信用分存入配置(用UUID作为键,参数完整)
|
||||
for (Map.Entry<Player, Integer> entry : ppoint.entrySet()) {
|
||||
Player player = entry.getKey();
|
||||
if (player.isOnline()) {
|
||||
UUID playerUuid = player.getUniqueId();
|
||||
ppointConfig.set(playerUuid.toString(), entry.getValue()); // 完整参数:路径(UUID字符串)+ 值(信用分)
|
||||
}
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
try {
|
||||
ppointConfig.save(ppointFile);
|
||||
getLogger().info("信用分数据保存成功!");
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("保存信用分数据失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 加载信用分数据(仅加载在线玩家)
|
||||
private void loadPpoint() {
|
||||
if (ppointConfig == null || ppointFile == null) {
|
||||
getLogger().severe("信用分配置未初始化,加载失败!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历配置中的所有UUID,为在线玩家分配信用分
|
||||
for (String uuidStr : ppointConfig.getKeys(false)) {
|
||||
try {
|
||||
UUID playerUuid = UUID.fromString(uuidStr);
|
||||
Player player = Bukkit.getPlayer(playerUuid);
|
||||
if (player != null && player.isOnline()) {
|
||||
// 读取信用分(默认100分)
|
||||
int point = ppointConfig.getInt(uuidStr, 100);
|
||||
ppoint.put(player, point);
|
||||
getLogger().info("加载玩家 " + player.getName() + " 的信用分:" + point);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
getLogger().warning("无效的UUID格式:" + uuidStr + ",跳过该数据");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 玩家上线时加载其信用分(供JoinEvent/LoginEvent调用)
|
||||
public void loadPlayerPpoint(Player player) {
|
||||
if (ppointConfig == null) {
|
||||
getLogger().severe("信用分配置未初始化,无法加载玩家 " + player.getName() + " 的信用分!");
|
||||
return;
|
||||
}
|
||||
|
||||
UUID playerUuid = player.getUniqueId();
|
||||
String uuidStr = playerUuid.toString();
|
||||
|
||||
// 读取已有信用分,无数据则设为默认100分
|
||||
int point = ppointConfig.getInt(uuidStr, 100);
|
||||
ppoint.put(player, point);
|
||||
getLogger().info("玩家 " + player.getName() + " 上线,加载信用分:" + point);
|
||||
}
|
||||
|
||||
// 获取玩家标签管理器
|
||||
public PlayerTags getPlayerTags() {
|
||||
return playerTags;
|
||||
}
|
||||
|
||||
// 新增获取账号管理器的方法
|
||||
// 获取账号管理器
|
||||
public AccountManager getAccountManager() {
|
||||
return accountManager;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ public class HelpCommandExecutor implements CommandExecutor {
|
||||
sender.sendMessage(ChatColor.GREEN+"/party <参数> <参数> - 队伍");
|
||||
sender.sendMessage(ChatColor.GREEN+"/friend <参数> <参数> - 好友");
|
||||
sender.sendMessage(ChatColor.GREEN+"/msg <内容> - 私聊");
|
||||
sender.sendMessage(ChatColor.GREEN+"/selfkill - 自杀");
|
||||
sender.sendMessage(ChatColor.YELLOW + "-----------------------------");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -45,12 +45,14 @@ public class ChooseTagEvent implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event.getView().getTitle().contains("称号") && !event.getView().getTitle().contains("商城")&& !event.getView().getTitle().contains("背包")) {
|
||||
if (!event.getView().getTitle().contains("称号") && !event.getView().getTitle().contains("商城")&& !event.getView().getTitle().contains("背包")&& !event.getView().getTitle().contains("签到")) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
if (event.getView().getTitle().contains("称号")) {
|
||||
if(event.getView().getTitle().contains("签到")){
|
||||
|
||||
} else if (event.getView().getTitle().contains("称号")) {
|
||||
ItemStack clickedItem = event.getCurrentItem();
|
||||
if (clickedItem == null || clickedItem.getType() != Material.NAME_TAG) {
|
||||
return;
|
||||
|
||||
@@ -21,6 +21,12 @@ public class JoinEvent implements Listener {
|
||||
|
||||
@EventHandler
|
||||
private void join(PlayerJoinEvent e) {
|
||||
if(plugin.ppoint.getOrDefault(e.getPlayer(),100) <= 0){
|
||||
e.getPlayer().kickPlayer(ChatColor.RED+"您好! 您由于 信用分小于 0 ,我们决定对你的账号 "+ e.getPlayer().getName() +" 采取\n"+ChatColor.RED+ChatColor.BOLD+"永久封禁\n"+ChatColor.RED+"措施,如果您想解封您的账号,请到QQ群 717903781 申诉\n\n"+ChatColor.RED+"如果您对本次处罚不满,请采取以下措施:\n"+ChatColor.YELLOW+"1.如果您对自己的行为"+ChatColor.BOLD+" 问心无愧 "+ChatColor.YELLOW+"请立即向QQ 2213866559 发送解封申请\n"+ChatColor.YELLOW+"2.如果您属实有违规行为,请"+ChatColor.BOLD+"手写"+ChatColor.YELLOW+"一篇 "+ChatColor.BOLD+"100字以上且AIGC合格"+ChatColor.YELLOW+" 的检讨发送到申诉QQ群,态度诚恳我们将会对你进行解封");
|
||||
}
|
||||
if(plugin.ppoint.getOrDefault(e.getPlayer(),100) == 100){
|
||||
plugin.ppoint.put(e.getPlayer(),100);
|
||||
}
|
||||
PlayerTags playertags = plugin.getPlayerTags();
|
||||
List<String> tags = playertags.getTags(e.getPlayer());
|
||||
if (!tags.isEmpty() && playertags.getCurrentTag(e.getPlayer()) != -1) {
|
||||
|
||||
@@ -45,6 +45,9 @@ commands:
|
||||
reg:
|
||||
description: to register an account
|
||||
usage: /<command> <password> <password>
|
||||
pc:
|
||||
description: chat in a party
|
||||
usage: /<command> <message>
|
||||
login:
|
||||
description: to login
|
||||
usage: /<command> <password>
|
||||
@@ -59,9 +62,27 @@ commands:
|
||||
msg:
|
||||
description: private chat with friend
|
||||
usage: /<command> <player> <message>
|
||||
qd:
|
||||
description: qian dao
|
||||
usage: /<command>
|
||||
friend:
|
||||
description: add friend
|
||||
usage: /<command> <add|allow|deny|remove> <player>
|
||||
gift:
|
||||
description: gift
|
||||
usage: /<command>
|
||||
aboutme:
|
||||
description: about you
|
||||
usage: /<command>
|
||||
point:
|
||||
description: change point
|
||||
usage: /<command> <player> <set|add|remove> <number>
|
||||
land:
|
||||
description: change point
|
||||
usage: /<command> <player> <set|add|remove> <number>
|
||||
selfkill:
|
||||
description: self kill
|
||||
usage: /<command>
|
||||
permissions:
|
||||
permission.settag:
|
||||
description: Allows setting player tags
|
||||
|
||||
Reference in New Issue
Block a user