Update: 最新功能更新 - Main/RadioManager/GUIManager/LoginManager等模块优化
This commit is contained in:
+7
-1
@@ -36,4 +36,10 @@ build/
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
|
||||
# 开发辅助文件(本地保留,不推送到仓库)
|
||||
txt/
|
||||
*.xlsx
|
||||
*.patch
|
||||
新建*.txt
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,10 @@ public class ConfigManager {
|
||||
public long smtpVerifyExpire = 0;
|
||||
public long smtpLastSendTime = 0;
|
||||
public String smtpConfiguringPlayer = "";
|
||||
public String updatePlatform = "gh";
|
||||
public String broadcastServerUrl = "";
|
||||
public int httpPort = 8080;
|
||||
public String garbageTag= "admin";
|
||||
|
||||
|
||||
|
||||
public ConfigManager(File dataFolder) {
|
||||
@@ -321,11 +324,8 @@ public class ConfigManager {
|
||||
garbageMaxRounds = parseInt(
|
||||
m.getOrDefault("垃圾站_保留轮数",
|
||||
"1"), 1);
|
||||
|
||||
|
||||
// loadSettings() 末尾添加:
|
||||
}
|
||||
|
||||
|
||||
public void saveSettings() {
|
||||
File file = new File(dataFolder, "插件设置.txt");
|
||||
List<String> L = new ArrayList<>();
|
||||
@@ -344,8 +344,7 @@ public class ConfigManager {
|
||||
L.add("垃圾站_清理间隔秒=" + garbageInterval);
|
||||
L.add("垃圾站_保留轮数=" + garbageMaxRounds);
|
||||
|
||||
|
||||
writeLines(file, L);
|
||||
writeLines(file, L);
|
||||
}
|
||||
public double providerPointsPerScore = 2.0;
|
||||
public int baseEconomyReward = 100;
|
||||
@@ -375,6 +374,9 @@ public class ConfigManager {
|
||||
L.add("垃圾站_启用=true");
|
||||
L.add("垃圾站_清理间隔秒=300");
|
||||
L.add("垃圾站_保留轮数=1");
|
||||
L.add("# ---- 资源包(HTTP) ----");
|
||||
L.add("resource-pack-url=");
|
||||
L.add("http-port=8080");
|
||||
|
||||
|
||||
writeLines(f, L);
|
||||
|
||||
@@ -213,18 +213,6 @@ public class DatabaseManager {
|
||||
+ ")");
|
||||
safeAdd(st, "menu_snowball",
|
||||
"INTEGER DEFAULT 1");
|
||||
// ===== 独立任务进度表 =====
|
||||
st.executeUpdate(
|
||||
"CREATE TABLE IF NOT EXISTS "
|
||||
+ "quest_progress ("
|
||||
+ "player_name TEXT NOT NULL, "
|
||||
+ "condition_key TEXT NOT NULL, "
|
||||
+ "progress_value INTEGER DEFAULT 0, "
|
||||
+ "completed INTEGER DEFAULT 0, "
|
||||
+ "PRIMARY KEY (player_name, "
|
||||
+ "condition_key)"
|
||||
+ ")");
|
||||
|
||||
st.close();
|
||||
logger.info("[Sdf1_login] 数据库初始化完成");
|
||||
} catch (Exception e) {
|
||||
@@ -873,8 +861,9 @@ public class DatabaseManager {
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
获取指定ID的备份数据
|
||||
|
||||
/**
|
||||
* 获取指定ID的备份数据
|
||||
*/
|
||||
public String[] getInventoryBackupById(
|
||||
int backupId) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.*;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import java.io.File;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -41,7 +42,7 @@ public class GUIManager {
|
||||
g.setItem(14, mkItem(Material.EMERALD,
|
||||
"§d§l积分商城"));
|
||||
g.setItem(16, mkItem(Material.CHEST,
|
||||
"§e§l任务中心"));
|
||||
"§e§l新人礼包"));
|
||||
g.setItem(18, mkItem(Material.BOOK,
|
||||
"§6工单系统",
|
||||
"§7提交bug、求助、举报"));
|
||||
@@ -105,6 +106,32 @@ public class GUIManager {
|
||||
p.openInventory(g);
|
||||
}
|
||||
|
||||
// 在 openGiftStages 方法之前添加:
|
||||
|
||||
/**
|
||||
* 获取任务列表(带真实完成状态)
|
||||
* 使用 QuestTracker 解析 .md 文件
|
||||
*/
|
||||
public List<Map<String, Object>> getQuestList(
|
||||
String category) {
|
||||
QuestTracker qt = plugin.getQuestTracker();
|
||||
if (qt == null) return new ArrayList<>();
|
||||
List<QuestTracker.QuestFile> quests =
|
||||
qt.getQuests(category);
|
||||
List<Map<String, Object>> list =
|
||||
new ArrayList<>();
|
||||
for (QuestTracker.QuestFile qf : quests) {
|
||||
Map<String, Object> map =
|
||||
new LinkedHashMap<>();
|
||||
map.put("name", qf.displayName);
|
||||
map.put("conditions", qf.conditions);
|
||||
map.put("rewards", qf.rewards);
|
||||
map.put("questFile", qf);
|
||||
list.add(map);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开账号删除选择面板
|
||||
* 展示该玩家IP下所有账号,供选择删除
|
||||
@@ -370,7 +397,6 @@ public class GUIManager {
|
||||
"§7双击管理"));
|
||||
slot++;
|
||||
}
|
||||
|
||||
g.setItem(53, mkItem(Material.ARROW, "§7返回"));
|
||||
p.openInventory(g);
|
||||
}
|
||||
@@ -379,279 +405,154 @@ public class GUIManager {
|
||||
Inventory g = Bukkit.createInventory(
|
||||
null, 27, T_TASK_CENTER);
|
||||
fillBg(g);
|
||||
|
||||
QuestTracker qt =
|
||||
plugin.getQuestTracker();
|
||||
String player = p.getName();
|
||||
|
||||
// 新人任务进度
|
||||
List<QuestTracker.QuestFile> newQuests =
|
||||
qt.getQuests("新人任务");
|
||||
int newTotal = newQuests.size();
|
||||
int newDone =
|
||||
qt.getCompletedStageCount(
|
||||
player, newQuests);
|
||||
QuestTracker.QuestFile newCurrent =
|
||||
qt.getCurrentStage(
|
||||
player, newQuests);
|
||||
|
||||
String newInfo = newDone + "/" + newTotal;
|
||||
List<String> newLore = new ArrayList<>();
|
||||
newLore.add("§7进度: §e" + newInfo);
|
||||
if (newCurrent != null) {
|
||||
newLore.add("§7当前: §f"
|
||||
+ newCurrent.displayName);
|
||||
if (newCurrent.hasConditions()) {
|
||||
List<String> unmet =
|
||||
qt.getUnmetConditions(
|
||||
player,
|
||||
newCurrent.conditions);
|
||||
if (!unmet.isEmpty()) {
|
||||
for (String c : unmet) {
|
||||
newLore.add("§7 "
|
||||
+ qt.getProgress(
|
||||
player, c));
|
||||
}
|
||||
} else {
|
||||
newLore.add("§a✓ 条件已满足");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newLore.add("§a§l全部完成!");
|
||||
}
|
||||
|
||||
g.setItem(10, mkItem(Material.BOOK,
|
||||
"§e§l新人任务 §7["
|
||||
+ newInfo + "]",
|
||||
newLore.toArray(new String[0])));
|
||||
|
||||
// 主线任务
|
||||
List<QuestTracker.QuestFile> mainQuests =
|
||||
qt.getQuests("主线任务");
|
||||
"§e§l新人任务",
|
||||
"§7完成新手阶段获取奖励"));
|
||||
g.setItem(12, mkItem(Material.COMPASS,
|
||||
"§b§l主线任务 §7["
|
||||
+ qt.getCompletedStageCount(
|
||||
player, mainQuests)
|
||||
+ "/" + mainQuests.size()
|
||||
+ "]",
|
||||
"§b§l主线任务",
|
||||
"§7查看主线任务列表"));
|
||||
|
||||
// 支线任务
|
||||
List<QuestTracker.QuestFile> sideQuests =
|
||||
qt.getQuests("支线任务");
|
||||
g.setItem(14, mkItem(Material.PAPER,
|
||||
"§a§l支线任务 §7["
|
||||
+ qt.getCompletedStageCount(
|
||||
player, sideQuests)
|
||||
+ "/" + sideQuests.size()
|
||||
+ "]",
|
||||
"§a§l支线任务",
|
||||
"§7查看支线任务列表"));
|
||||
|
||||
g.setItem(16, mkItem(Material.EMERALD,
|
||||
"§d§l每日签到",
|
||||
"§7签到获取积分"));
|
||||
|
||||
// 打卡上报按钮(slot 21)
|
||||
g.setItem(21, mkItem(
|
||||
Material.EMERALD,
|
||||
"§a§l打卡上报",
|
||||
"§7验证当前阶段任务完成情况",
|
||||
"§7满足条件将自动标记完成"));
|
||||
|
||||
// 返回按钮(slot 26)
|
||||
g.setItem(26, mkItem(
|
||||
Material.ARROW, "§7返回"));
|
||||
g.setItem(22, mkItem(Material.ARROW, "§7返回"));
|
||||
p.openInventory(g);
|
||||
}
|
||||
|
||||
|
||||
public void openGiftStages(Player p) {
|
||||
Inventory g = Bukkit.createInventory(
|
||||
null, 54, T_GIFT_STAGES);
|
||||
null, 27, T_GIFT_STAGES);
|
||||
fillBg(g);
|
||||
|
||||
QuestTracker qt =
|
||||
plugin.getQuestTracker();
|
||||
QuestTracker qt = plugin.getQuestTracker();
|
||||
if (qt == null) {
|
||||
g.setItem(22, mkItem(Material.BARRIER,
|
||||
"§7任务系统未加载"));
|
||||
p.openInventory(g);
|
||||
return;
|
||||
}
|
||||
|
||||
List<QuestTracker.QuestFile> quests =
|
||||
qt.getQuests("新人任务");
|
||||
int total = quests.size();
|
||||
int completed =
|
||||
qt.getCompletedStageCount(
|
||||
p.getName(), quests);
|
||||
QuestTracker.QuestFile current =
|
||||
qt.getCurrentStage(
|
||||
p.getName(), quests);
|
||||
String playerName = p.getName();
|
||||
|
||||
g.setItem(4, mkItem(Material.BOOK,
|
||||
"§e§l新人任务进度",
|
||||
"§7已完成: §e" + completed
|
||||
+ "/" + total,
|
||||
current != null
|
||||
? "§7当前: §f"
|
||||
+ current.displayName
|
||||
: "§a§l全部完成!"));
|
||||
|
||||
for (int i = 0;
|
||||
i < quests.size() && i < 44; i++) {
|
||||
QuestTracker.QuestFile qf =
|
||||
quests.get(i);
|
||||
boolean done =
|
||||
qt.isStageCompleted(
|
||||
p.getName(), qf);
|
||||
boolean isCurrent =
|
||||
(current != null
|
||||
&& current == qf);
|
||||
int max = quests.size();
|
||||
for (int i = 0; i < max && i < 9; i++) {
|
||||
QuestTracker.QuestFile qf = quests.get(i);
|
||||
boolean completed =
|
||||
qt.isStageCompleted(playerName, qf);
|
||||
boolean claimed =
|
||||
qt.hasClaimed(playerName, qf);
|
||||
|
||||
Material mat;
|
||||
List<String> lore = new ArrayList<>();
|
||||
|
||||
if (done) {
|
||||
String status;
|
||||
if (completed && claimed) {
|
||||
mat = Material.LIME_WOOL;
|
||||
} else if (isCurrent) {
|
||||
status = "§a已领取";
|
||||
} else if (completed) {
|
||||
mat = Material.YELLOW_WOOL;
|
||||
status = "§e可领取";
|
||||
} else {
|
||||
mat = Material.RED_WOOL;
|
||||
status = "§c未达标";
|
||||
}
|
||||
|
||||
if (!qf.details.isEmpty()) {
|
||||
lore.add("§7---- 任务详情 ----");
|
||||
for (String d : qf.details) {
|
||||
lore.add("§f" + d);
|
||||
}
|
||||
}
|
||||
|
||||
if (qf.hasConditions()
|
||||
&& (done || isCurrent)) {
|
||||
lore.add("");
|
||||
for (String c : qf.conditions) {
|
||||
if (qt.isOptional(c))
|
||||
continue;
|
||||
if (qt.isConditionMet(
|
||||
p.getName(), c)) {
|
||||
lore.add("§7 §a✓ "
|
||||
+ qt.getProgress(
|
||||
p.getName(), c));
|
||||
} else {
|
||||
lore.add("§7 §c✗ "
|
||||
+ qt.getProgress(
|
||||
p.getName(), c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!qf.rewards.isEmpty()) {
|
||||
lore.add("");
|
||||
lore.add("§7---- 奖励 ----");
|
||||
for (String r : qf.rewards) {
|
||||
lore.add("§a" + r);
|
||||
}
|
||||
}
|
||||
|
||||
if (done
|
||||
&& !qf.rewards.isEmpty()
|
||||
&& !qt.hasClaimed(
|
||||
p.getName(), qf)) {
|
||||
lore.add("");
|
||||
lore.add("§e§l点击领取奖励");
|
||||
}
|
||||
if (done && qt.hasClaimed(
|
||||
p.getName(), qf)) {
|
||||
lore.add("");
|
||||
lore.add("§7已领取奖励");
|
||||
// 显示进度
|
||||
List<String> lore = new ArrayList<>();
|
||||
lore.add("§7" + status);
|
||||
for (String cond : qf.conditions) {
|
||||
String progress =
|
||||
qt.getProgress(playerName, cond);
|
||||
lore.add("§7" + progress);
|
||||
}
|
||||
|
||||
g.setItem(10 + i, mkItem(mat,
|
||||
"§e" + qf.displayName,
|
||||
lore.toArray(new String[0])));
|
||||
}
|
||||
// 返回按钮
|
||||
g.setItem(53, mkItem(
|
||||
Material.ARROW, "§7返回"));
|
||||
g.setItem(26, mkItem(Material.ARROW, "§7返回"));
|
||||
p.openInventory(g);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void openTaskList(Player p,
|
||||
String folderName) {
|
||||
QuestTracker qt =
|
||||
plugin.getQuestTracker();
|
||||
List<QuestTracker.QuestFile> tasks =
|
||||
qt.getQuests(folderName);
|
||||
|
||||
int size = Math.min(54,
|
||||
Math.max(54,
|
||||
((tasks.size() / 9) + 1) * 9));
|
||||
Inventory g = Bukkit.createInventory(
|
||||
null, size,
|
||||
public void openTaskList(Player p, String folderName) {
|
||||
Inventory g = Bukkit.createInventory(null, 54,
|
||||
"§d§l" + folderName);
|
||||
fillBg(g);
|
||||
|
||||
for (int i = 0;
|
||||
i < tasks.size()
|
||||
&& i < 45; i++) {
|
||||
QuestTracker.QuestFile qf =
|
||||
tasks.get(i);
|
||||
boolean done =
|
||||
qt.isStageCompleted(
|
||||
p.getName(), qf);
|
||||
Material mat = done
|
||||
? Material.LIME_WOOL
|
||||
: Material.BOOK;
|
||||
// [FIX] 使用 QuestTracker 获取真实任务数据
|
||||
QuestTracker qt = plugin.getQuestTracker();
|
||||
if (qt == null) {
|
||||
g.setItem(22, mkItem(Material.BARRIER,
|
||||
"§7任务系统未加载"));
|
||||
p.openInventory(g);
|
||||
return;
|
||||
}
|
||||
|
||||
List<QuestTracker.QuestFile> quests =
|
||||
qt.getQuests(folderName);
|
||||
String playerName = p.getName();
|
||||
|
||||
if (quests.isEmpty()) {
|
||||
g.setItem(22, mkItem(Material.BARRIER,
|
||||
"§7暂无任务"));
|
||||
p.openInventory(g);
|
||||
return;
|
||||
}
|
||||
|
||||
int slot = 0;
|
||||
for (QuestTracker.QuestFile qf : quests) {
|
||||
if (slot >= 45) break;
|
||||
|
||||
boolean completed =
|
||||
qt.isStageCompleted(playerName, qf);
|
||||
boolean claimed =
|
||||
qt.hasClaimed(playerName, qf);
|
||||
|
||||
Material mat;
|
||||
String status;
|
||||
if (completed && claimed) {
|
||||
mat = Material.LIME_WOOL;
|
||||
status = "§a✓ 已完成并领取";
|
||||
} else if (completed) {
|
||||
mat = Material.YELLOW_WOOL;
|
||||
status = "§e✓ 已完成 - 可领取奖励";
|
||||
} else {
|
||||
mat = Material.RED_WOOL;
|
||||
status = "§c未完成";
|
||||
}
|
||||
|
||||
List<String> lore = new ArrayList<>();
|
||||
lore.add(status);
|
||||
lore.add("§7───── 条件 ─────");
|
||||
|
||||
// 解锁条件
|
||||
if (qf.hasConditions()) {
|
||||
lore.add("§7──── 解锁条件 ────");
|
||||
for (String c : qf.conditions) {
|
||||
if (qt.isOptional(c))
|
||||
continue;
|
||||
if (qt.isConditionMet(
|
||||
p.getName(), c)) {
|
||||
lore.add("§a ✓ "
|
||||
+ qt.getProgress(
|
||||
p.getName(), c));
|
||||
} else {
|
||||
lore.add("§c ✗ "
|
||||
+ qt.getProgress(
|
||||
p.getName(), c));
|
||||
}
|
||||
// 显示每个条件及完成状态
|
||||
for (String cond : qf.conditions) {
|
||||
String progress =
|
||||
qt.getProgress(playerName, cond);
|
||||
if (qt.isOptional(cond)) {
|
||||
lore.add("§7[可选] " + progress);
|
||||
} else {
|
||||
lore.add("§e" + progress);
|
||||
}
|
||||
}
|
||||
|
||||
// 任务详情
|
||||
if (!qf.details.isEmpty()) {
|
||||
lore.add("");
|
||||
lore.add("§7──── 任务详情 ────");
|
||||
for (String d : qf.details) {
|
||||
lore.add("§f" + d);
|
||||
}
|
||||
}
|
||||
|
||||
// 任务奖励
|
||||
if (!qf.rewards.isEmpty()) {
|
||||
lore.add("");
|
||||
lore.add("§7──── 任务奖励 ────");
|
||||
lore.add("§7───── 奖励 ─────");
|
||||
for (String r : qf.rewards) {
|
||||
lore.add("§a" + r);
|
||||
}
|
||||
}
|
||||
|
||||
g.setItem(i, mkItem(mat,
|
||||
(done ? "§a✓ " : "§e")
|
||||
+ qf.displayName,
|
||||
g.setItem(slot, mkItem(mat,
|
||||
"§e" + qf.displayName,
|
||||
lore.toArray(new String[0])));
|
||||
slot++;
|
||||
}
|
||||
|
||||
if (tasks.isEmpty()) {
|
||||
g.setItem(22, mkItem(
|
||||
Material.BARRIER,
|
||||
"§7暂无任务"));
|
||||
}
|
||||
g.setItem(size - 1, mkItem(
|
||||
Material.ARROW, "§7返回"));
|
||||
g.setItem(53, mkItem(Material.ARROW, "§7返回"));
|
||||
p.openInventory(g);
|
||||
}
|
||||
|
||||
@@ -683,81 +584,11 @@ public class GUIManager {
|
||||
Material.SNOWBALL,
|
||||
"§e§l雪球菜单",
|
||||
"§7点击为该玩家发放菜单雪球"));
|
||||
g.setItem(16, mkItem(
|
||||
Material.ENDER_EYE,
|
||||
"§b§l打卡记录",
|
||||
"§7查看该玩家的群系打卡记录"));
|
||||
|
||||
g.setItem(22, mkItem(Material.ARROW, "§7返回"));
|
||||
p.openInventory(g);
|
||||
}
|
||||
|
||||
public void openCheckInRecords(
|
||||
Player p, String target) {
|
||||
Inventory g = Bukkit.createInventory(
|
||||
null, 54,
|
||||
"§b§l打卡记录: " + target);
|
||||
fillBg(g);
|
||||
|
||||
QuestTracker qt =
|
||||
plugin.getQuestTracker();
|
||||
List<String> records =
|
||||
qt.getPlayerRecords(target);
|
||||
|
||||
java.text.SimpleDateFormat sdf =
|
||||
new java.text.SimpleDateFormat(
|
||||
"yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
int slot = 0;
|
||||
for (int i = records.size() - 1;
|
||||
i >= 0 && slot < 45; i--) {
|
||||
String r = records.get(i);
|
||||
String[] parts = r.split("\\|");
|
||||
if (parts.length < 7) continue;
|
||||
|
||||
String world = parts[1];
|
||||
String biome = parts[2];
|
||||
String category = parts[3];
|
||||
String x = parts[4];
|
||||
String y = parts[5];
|
||||
String z = parts[6];
|
||||
String timeStr = "";
|
||||
if (parts.length >= 8) {
|
||||
try {
|
||||
long ts = Long.parseLong(
|
||||
parts[7]);
|
||||
timeStr = sdf.format(
|
||||
new java.util.Date(
|
||||
ts));
|
||||
} catch (Exception e) {
|
||||
timeStr = parts[7];
|
||||
}
|
||||
}
|
||||
|
||||
g.setItem(slot, mkItem(
|
||||
Material.PAPER,
|
||||
"§e" + category + " - "
|
||||
+ biome,
|
||||
"§7时间: " + timeStr,
|
||||
"§7世界: " + world,
|
||||
"§7坐标: " + x
|
||||
+ ", " + y
|
||||
+ ", " + z));
|
||||
slot++;
|
||||
}
|
||||
|
||||
if (slot == 0) {
|
||||
g.setItem(22, mkItem(
|
||||
Material.BARRIER,
|
||||
"§7暂无打卡记录"));
|
||||
}
|
||||
|
||||
g.setItem(53, mkItem(
|
||||
Material.ARROW, "§7返回"));
|
||||
p.openInventory(g);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打开账号请求面板
|
||||
* 玩家通过 /oa 命令触发
|
||||
|
||||
@@ -1,89 +1,96 @@
|
||||
package Sdf1_login;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
public class InviteManager {
|
||||
|
||||
private final Main plugin;
|
||||
|
||||
public InviteManager(Main plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public String generateCode(Player p) {
|
||||
String code = PasswordUtils.generateInviteCode();
|
||||
plugin.getDb().setField(
|
||||
p.getName(), "invite_code", code);
|
||||
return code;
|
||||
}
|
||||
|
||||
public void onInviteeCheckIn(String inviteeName) {
|
||||
String invitedBy = (String) plugin.getDb()
|
||||
.getField(inviteeName, "invited_by");
|
||||
if (invitedBy == null || invitedBy.isEmpty())
|
||||
return;
|
||||
|
||||
String month = new SimpleDateFormat("yyyy-MM")
|
||||
.format(new Date());
|
||||
String lastMonth = (String) plugin.getDb()
|
||||
.getField(invitedBy, "invite_month");
|
||||
|
||||
if (!month.equals(lastMonth)) {
|
||||
plugin.getDb().setField(
|
||||
invitedBy, "invite_month", month);
|
||||
plugin.getDb().setField(
|
||||
invitedBy, "monthly_invite_count", 0);
|
||||
}
|
||||
|
||||
int count = ((Number) plugin.getDb()
|
||||
.getField(invitedBy,
|
||||
"monthly_invite_count"))
|
||||
.intValue();
|
||||
plugin.getDb().setField(
|
||||
invitedBy, "monthly_invite_count",
|
||||
count + 1);
|
||||
|
||||
double rate = plugin.getCommission()
|
||||
.getCommissionRate(invitedBy);
|
||||
int bonus = (int) (1 * rate);
|
||||
if (bonus > 0) {
|
||||
plugin.getDb().addPoints(invitedBy, bonus);
|
||||
Player inviterPlayer = Bukkit
|
||||
.getPlayerExact(invitedBy);
|
||||
if (inviterPlayer != null
|
||||
&& inviterPlayer.isOnline()) {
|
||||
inviterPlayer.sendMessage(
|
||||
plugin.getConfig2()
|
||||
.msg("invite_referral_bonus")
|
||||
.replace("{points}",
|
||||
String.valueOf(bonus)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getAllInviteData() {
|
||||
List<Map<String, Object>> result =
|
||||
new ArrayList<>();
|
||||
for (Map<String, Object> user
|
||||
: plugin.getDb().getAllUsers()) {
|
||||
String code = (String) user.getOrDefault(
|
||||
"invite_code", "");
|
||||
if (!code.isEmpty()) {
|
||||
Map<String, Object> row =
|
||||
new LinkedHashMap<>();
|
||||
row.put("player",
|
||||
user.get("player_name"));
|
||||
row.put("code", code);
|
||||
row.put("monthly",
|
||||
user.getOrDefault(
|
||||
"monthly_invite_count", 0));
|
||||
result.add(row);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
package Sdf1_login;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
public class InviteManager {
|
||||
|
||||
private final Main plugin;
|
||||
|
||||
public InviteManager(Main plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public String generateCode(Player p) {
|
||||
String code = PasswordUtils.generateInviteCode();
|
||||
plugin.getDb().setField(
|
||||
p.getName(), "invite_code", code);
|
||||
return code;
|
||||
}
|
||||
|
||||
public void onInviteeCheckIn(String inviteeName) {
|
||||
String invitedBy = (String) plugin.getDb()
|
||||
.getField(inviteeName, "invited_by");
|
||||
if (invitedBy == null || invitedBy.isEmpty())
|
||||
return;
|
||||
|
||||
String month = new SimpleDateFormat("yyyy-MM")
|
||||
.format(new Date());
|
||||
String lastMonth = (String) plugin.getDb()
|
||||
.getField(invitedBy, "invite_month");
|
||||
|
||||
if (!month.equals(lastMonth)) {
|
||||
plugin.getDb().setField(
|
||||
invitedBy, "invite_month", month);
|
||||
plugin.getDb().setField(
|
||||
invitedBy, "monthly_invite_count", 0);
|
||||
}
|
||||
|
||||
int count = ((Number) plugin.getDb()
|
||||
.getField(invitedBy,
|
||||
"monthly_invite_count"))
|
||||
.intValue();
|
||||
plugin.getDb().setField(
|
||||
invitedBy, "monthly_invite_count",
|
||||
count + 1);
|
||||
|
||||
double rate = 0.10;
|
||||
if (count + 1 > 15) {
|
||||
rate = 0.60;
|
||||
} else if (count + 1 > 10) {
|
||||
rate = 0.35;
|
||||
} else if (count + 1 > 5) {
|
||||
rate = 0.15;
|
||||
}
|
||||
|
||||
int bonus = (int) (1 * rate);
|
||||
if (bonus > 0) {
|
||||
plugin.getDb().addPoints(invitedBy, bonus);
|
||||
Player inviterPlayer = Bukkit
|
||||
.getPlayerExact(invitedBy);
|
||||
if (inviterPlayer != null
|
||||
&& inviterPlayer.isOnline()) {
|
||||
inviterPlayer.sendMessage(
|
||||
plugin.getConfig2()
|
||||
.msg("invite_referral_bonus")
|
||||
.replace("{points}",
|
||||
String.valueOf(bonus)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getAllInviteData() {
|
||||
List<Map<String, Object>> result =
|
||||
new ArrayList<>();
|
||||
for (Map<String, Object> user
|
||||
: plugin.getDb().getAllUsers()) {
|
||||
String code = (String) user.getOrDefault(
|
||||
"invite_code", "");
|
||||
if (!code.isEmpty()) {
|
||||
Map<String, Object> row =
|
||||
new LinkedHashMap<>();
|
||||
row.put("player",
|
||||
user.get("player_name"));
|
||||
row.put("code", code);
|
||||
row.put("monthly",
|
||||
user.getOrDefault(
|
||||
"monthly_invite_count", 0));
|
||||
result.add(row);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,302 +1,308 @@
|
||||
package Sdf1_login;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LoginManager {
|
||||
|
||||
private final Main plugin;
|
||||
|
||||
public LoginManager(Main plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public boolean handleRegister(Player p,
|
||||
String[] args) {
|
||||
String name = p.getName();
|
||||
|
||||
// 已注册玩家不能再注册
|
||||
if (plugin.getDb().userExists(name)) {
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("already_registered"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// IP注册限制检查
|
||||
String ip = plugin.getPlayerIP(p);
|
||||
if (ip != null && plugin.getConfig2()
|
||||
.maxAccountsPerIP > 0) {
|
||||
if (!plugin.getIPGroup()
|
||||
.canRegister(ip)) {
|
||||
int count = plugin.getIPGroup()
|
||||
.getAccountCount(ip);
|
||||
int max = plugin.getConfig2()
|
||||
.maxAccountsPerIP;
|
||||
p.sendMessage("§c该IP注册已达上限("
|
||||
+ count + "/" + max + ")");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
p.sendMessage("§c用法: /reg <密码>");
|
||||
p.sendMessage("§7密码要求: 6位以上,"
|
||||
+ "包含大小写字母和数字");
|
||||
return true;
|
||||
}
|
||||
|
||||
String pwd = args[0];
|
||||
if (pwd.length() < 6) {
|
||||
p.sendMessage("§c密码长度不足6位");
|
||||
return true;
|
||||
}
|
||||
if (!pwd.matches(".*[a-z].*")
|
||||
|| !pwd.matches(".*[A-Z].*")
|
||||
|| !pwd.matches(".*[0-9].*")) {
|
||||
p.sendMessage("§c密码必须包含大写字母、"
|
||||
+ "小写字母和数字");
|
||||
return true;
|
||||
}
|
||||
|
||||
String salt =
|
||||
PasswordUtils.generateSalt();
|
||||
String hash =
|
||||
PasswordUtils.hash(pwd, salt);
|
||||
plugin.getDb().createUser(
|
||||
name, hash, salt);
|
||||
plugin.getLoggedIn().add(name);
|
||||
plugin.getDb().setLoggedIn(name, true);
|
||||
plugin.getDb().setField(name,
|
||||
"last_login_time",
|
||||
System.currentTimeMillis());
|
||||
plugin.getDb().setField(name,
|
||||
"last_online_check",
|
||||
System.currentTimeMillis());
|
||||
plugin.getDb().recordIP(name, ip);
|
||||
plugin.getDb().setField(name,
|
||||
"register_time",
|
||||
System.currentTimeMillis());
|
||||
plugin.restoreInventory(p);
|
||||
plugin.recordIPLogin(p);
|
||||
plugin.giveMenuSnowball(p);
|
||||
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("reg_success"));
|
||||
playRegisterSound(p);
|
||||
|
||||
try {
|
||||
org.bukkit.plugin.Plugin cy =
|
||||
Bukkit.getPluginManager()
|
||||
.getPlugin("CY_beibao");
|
||||
if (cy != null && cy.isEnabled()) {
|
||||
cy.getClass().getMethod(
|
||||
"onSdf1Activation",
|
||||
String.class,
|
||||
int.class, int.class)
|
||||
.invoke(cy, name, 9, 0);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void playRegisterSound(Player p) {
|
||||
p.playSound(p.getLocation(),
|
||||
Sound.BLOCK_NOTE_BLOCK_CHIME,
|
||||
1.0f, 0.79f);
|
||||
p.playSound(p.getLocation(),
|
||||
Sound.BLOCK_NOTE_BLOCK_BASS,
|
||||
1.0f, 0.79f);
|
||||
p.playSound(p.getLocation(),
|
||||
Sound.BLOCK_NOTE_BLOCK_PLING,
|
||||
1.0f, 0.79f);
|
||||
}
|
||||
|
||||
|
||||
public boolean handleLogin(Player p,
|
||||
String[] args) {
|
||||
String name = p.getName();
|
||||
try {
|
||||
if (plugin.getLoggedIn().contains(name)) {
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("already_logged_in"));
|
||||
return true;
|
||||
}
|
||||
if (!plugin.getDb().userExists(name)) {
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("not_registered"));
|
||||
return true;
|
||||
}
|
||||
if (args.length < 1) {
|
||||
p.sendMessage("§c用法: /login <密码>");
|
||||
return true;
|
||||
}
|
||||
String pwd = args[0];
|
||||
String salt = (String) plugin.getDb()
|
||||
.getField(name, "password_salt");
|
||||
if (salt == null) {
|
||||
p.sendMessage(
|
||||
"§c数据异常,请联系管理员");
|
||||
plugin.getLogger().severe(
|
||||
"[Sdf1_login] 玩家 " + name
|
||||
+ " 盐值为null");
|
||||
return true;
|
||||
}
|
||||
String hash =
|
||||
PasswordUtils.hash(pwd, salt);
|
||||
|
||||
boolean matchMain =
|
||||
plugin.getDb().checkPassword(
|
||||
name, hash);
|
||||
if (matchMain) {
|
||||
plugin.getLoggedIn().add(name);
|
||||
plugin.getDb().setLoggedIn(
|
||||
name, true);
|
||||
plugin.getDb().setField(name,
|
||||
"last_login_time",
|
||||
System.currentTimeMillis());
|
||||
plugin.getDb().setField(name,
|
||||
"last_online_check",
|
||||
System.currentTimeMillis());
|
||||
// 只在有有效备份时恢复
|
||||
plugin.restoreInventory(p);
|
||||
plugin.recordIPLogin(p);
|
||||
plugin.giveMenuSnowball(p);
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("login_success"));
|
||||
activateCY(p, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean matchTemp =
|
||||
plugin.getDb()
|
||||
.checkPasswordOrTemp(
|
||||
name, hash);
|
||||
if (matchTemp) {
|
||||
plugin.getLoggedIn().add(name);
|
||||
plugin.getDb().setLoggedIn(
|
||||
name, true);
|
||||
plugin.getDb().setField(name,
|
||||
"last_login_time",
|
||||
System.currentTimeMillis());
|
||||
plugin.getDb().setField(name,
|
||||
"last_online_check",
|
||||
System.currentTimeMillis());
|
||||
plugin.restoreInventory(p);
|
||||
plugin.recordIPLogin(p);
|
||||
plugin.giveMenuSnowball(p);
|
||||
plugin.getNeedsPasswordChange()
|
||||
.add(name);
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("login_success"));
|
||||
p.sendMessage(
|
||||
"§c§l[警告] §f您使用的是临时密码,请尽快修改密码!");
|
||||
p.sendMessage(
|
||||
"§7用法: /sdf1_login pw");
|
||||
activateCY(p, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("login_failed"));
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().severe(
|
||||
"[Sdf1_login] handleLogin异常: "
|
||||
+ e.getMessage());
|
||||
e.printStackTrace();
|
||||
p.sendMessage(
|
||||
"§c登录过程出错,请联系管理员");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void handleReset(Player p) {
|
||||
String name = p.getName();
|
||||
String emailAddr = (String)
|
||||
plugin.getDb().getField(
|
||||
name, "email");
|
||||
if (emailAddr == null
|
||||
|| emailAddr.isEmpty()) {
|
||||
p.sendMessage(
|
||||
"§c未设置邮箱,无法重置密码");
|
||||
return;
|
||||
}
|
||||
String tempPwd = PasswordUtils
|
||||
.generateTempPassword();
|
||||
String salt = (String)
|
||||
plugin.getDb().getField(
|
||||
name, "password_salt");
|
||||
String hash = PasswordUtils.hash(
|
||||
tempPwd, salt);
|
||||
plugin.getDb().setField(name,
|
||||
"temp_password", hash);
|
||||
plugin.getDb().setField(name,
|
||||
"temp_pw_expire",
|
||||
System.currentTimeMillis()
|
||||
+ 300000L);
|
||||
|
||||
plugin.getDb().setField(name,
|
||||
"temp_pw_used", 0);
|
||||
p.sendMessage("§e正在发送临时密码...");
|
||||
final String to = emailAddr;
|
||||
final String fName = name;
|
||||
final String pwd = tempPwd;
|
||||
final Main self = plugin;
|
||||
Bukkit.getScheduler()
|
||||
.runTaskAsynchronously(self,
|
||||
() -> {
|
||||
final boolean[] sent = {false};
|
||||
Thread t = new Thread(() -> {
|
||||
sent[0] = self.getEmail()
|
||||
.sendTempPassword(
|
||||
to, fName, pwd);
|
||||
}, "Sdf1_login-reset");
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
try {
|
||||
t.join(15000);
|
||||
} catch (
|
||||
InterruptedException ignored) {
|
||||
}
|
||||
if (t.isAlive()) {
|
||||
t.interrupt();
|
||||
Bukkit.getScheduler().runTask(
|
||||
self, () ->
|
||||
p.sendMessage(
|
||||
"§c邮件发送超时"));
|
||||
return;
|
||||
}
|
||||
Bukkit.getScheduler().runTask(
|
||||
self, () -> {
|
||||
if (sent[0]) {
|
||||
p.sendMessage(
|
||||
"§a临时密码已发送到 "
|
||||
+ to);
|
||||
} else {
|
||||
p.sendMessage(
|
||||
"§c邮件发送失败");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void activateCY(Player p,
|
||||
String name) {
|
||||
try {
|
||||
org.bukkit.plugin.Plugin cy =
|
||||
Bukkit.getPluginManager()
|
||||
.getPlugin("CY_beibao");
|
||||
if (cy != null && cy.isEnabled()) {
|
||||
cy.getClass().getMethod(
|
||||
"onSdf1Activation",
|
||||
String.class,
|
||||
int.class, int.class)
|
||||
.invoke(cy, name, 0, 0);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
package Sdf1_login;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LoginManager {
|
||||
|
||||
private final Main plugin;
|
||||
|
||||
public LoginManager(Main plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public boolean handleRegister(Player p,
|
||||
String[] args) {
|
||||
String name = p.getName();
|
||||
|
||||
// 已注册玩家不能再注册
|
||||
if (plugin.getDb().userExists(name)) {
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("already_registered"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// IP注册限制检查
|
||||
String ip = plugin.getPlayerIP(p);
|
||||
if (ip != null && plugin.getConfig2()
|
||||
.maxAccountsPerIP > 0) {
|
||||
if (!plugin.getIPGroup()
|
||||
.canRegister(ip)) {
|
||||
int count = plugin.getIPGroup()
|
||||
.getAccountCount(ip);
|
||||
int max = plugin.getConfig2()
|
||||
.maxAccountsPerIP;
|
||||
p.sendMessage("§c该IP注册已达上限("
|
||||
+ count + "/" + max + ")");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
p.sendMessage("§c用法: /reg <密码>");
|
||||
p.sendMessage("§7密码要求: 6位以上,"
|
||||
+ "包含大小写字母和数字");
|
||||
return true;
|
||||
}
|
||||
|
||||
String pwd = args[0];
|
||||
if (pwd.length() < 6) {
|
||||
p.sendMessage("§c密码长度不足6位");
|
||||
return true;
|
||||
}
|
||||
if (!pwd.matches(".*[a-z].*")
|
||||
|| !pwd.matches(".*[A-Z].*")
|
||||
|| !pwd.matches(".*[0-9].*")) {
|
||||
p.sendMessage("§c密码必须包含大写字母、"
|
||||
+ "小写字母和数字");
|
||||
return true;
|
||||
}
|
||||
|
||||
String salt =
|
||||
PasswordUtils.generateSalt();
|
||||
String hash =
|
||||
PasswordUtils.hash(pwd, salt);
|
||||
plugin.getDb().createUser(
|
||||
name, hash, salt);
|
||||
plugin.getLoggedIn().add(name);
|
||||
p.setAllowFlight(false);
|
||||
p.setFlying(false);
|
||||
plugin.getDb().setLoggedIn(name, true);
|
||||
plugin.getDb().setField(name,
|
||||
"last_login_time",
|
||||
System.currentTimeMillis());
|
||||
plugin.getDb().setField(name,
|
||||
"last_online_check",
|
||||
System.currentTimeMillis());
|
||||
plugin.getDb().recordIP(name, ip);
|
||||
plugin.getDb().setField(name,
|
||||
"register_time",
|
||||
System.currentTimeMillis());
|
||||
plugin.restoreInventory(p);
|
||||
plugin.recordIPLogin(p);
|
||||
plugin.giveMenuSnowball(p);
|
||||
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("reg_success"));
|
||||
playRegisterSound(p);
|
||||
|
||||
try {
|
||||
org.bukkit.plugin.Plugin cy =
|
||||
Bukkit.getPluginManager()
|
||||
.getPlugin("CY_beibao");
|
||||
if (cy != null && cy.isEnabled()) {
|
||||
cy.getClass().getMethod(
|
||||
"onSdf1Activation",
|
||||
String.class,
|
||||
int.class, int.class)
|
||||
.invoke(cy, name, 9, 0);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void playRegisterSound(Player p) {
|
||||
p.playSound(p.getLocation(),
|
||||
Sound.BLOCK_NOTE_BLOCK_CHIME,
|
||||
1.0f, 0.79f);
|
||||
p.playSound(p.getLocation(),
|
||||
Sound.BLOCK_NOTE_BLOCK_BASS,
|
||||
1.0f, 0.79f);
|
||||
p.playSound(p.getLocation(),
|
||||
Sound.BLOCK_NOTE_BLOCK_PLING,
|
||||
1.0f, 0.79f);
|
||||
}
|
||||
|
||||
|
||||
public boolean handleLogin(Player p,
|
||||
String[] args) {
|
||||
String name = p.getName();
|
||||
try {
|
||||
if (plugin.getLoggedIn().contains(name)) {
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("already_logged_in"));
|
||||
return true;
|
||||
}
|
||||
if (!plugin.getDb().userExists(name)) {
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("not_registered"));
|
||||
return true;
|
||||
}
|
||||
if (args.length < 1) {
|
||||
p.sendMessage("§c用法: /login <密码>");
|
||||
return true;
|
||||
}
|
||||
String pwd = args[0];
|
||||
String salt = (String) plugin.getDb()
|
||||
.getField(name, "password_salt");
|
||||
if (salt == null) {
|
||||
p.sendMessage(
|
||||
"§c数据异常,请联系管理员");
|
||||
plugin.getLogger().severe(
|
||||
"[Sdf1_login] 玩家 " + name
|
||||
+ " 盐值为null");
|
||||
return true;
|
||||
}
|
||||
String hash =
|
||||
PasswordUtils.hash(pwd, salt);
|
||||
|
||||
boolean matchMain =
|
||||
plugin.getDb().checkPassword(
|
||||
name, hash);
|
||||
if (matchMain) {
|
||||
plugin.getLoggedIn().add(name);
|
||||
plugin.getDb().setLoggedIn(
|
||||
name, true);
|
||||
plugin.getDb().setLoggedIn(
|
||||
name, true);
|
||||
plugin.getDb().setField(name,
|
||||
"last_login_time",
|
||||
System.currentTimeMillis());
|
||||
plugin.getDb().setField(name,
|
||||
"last_online_check",
|
||||
System.currentTimeMillis());
|
||||
// 只在有有效备份时恢复
|
||||
plugin.restoreInventory(p);
|
||||
plugin.recordIPLogin(p);
|
||||
plugin.giveMenuSnowball(p);
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("login_success"));
|
||||
activateCY(p, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean matchTemp =
|
||||
plugin.getDb()
|
||||
.checkPasswordOrTemp(
|
||||
name, hash);
|
||||
if (matchTemp) {
|
||||
plugin.getLoggedIn().add(name);
|
||||
plugin.getDb().setLoggedIn(
|
||||
name, true);
|
||||
p.setAllowFlight(false);
|
||||
p.setFlying(false);
|
||||
plugin.getDb().setField(name,
|
||||
"last_login_time",
|
||||
System.currentTimeMillis());
|
||||
plugin.getDb().setField(name,
|
||||
"last_online_check",
|
||||
System.currentTimeMillis());
|
||||
plugin.restoreInventory(p);
|
||||
plugin.recordIPLogin(p);
|
||||
plugin.giveMenuSnowball(p);
|
||||
plugin.getNeedsPasswordChange()
|
||||
.add(name);
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("login_success"));
|
||||
p.sendMessage(
|
||||
"§c§l[警告] §f您使用的是临时密码,请尽快修改密码!");
|
||||
p.sendMessage(
|
||||
"§7用法: /sdf1_login pw");
|
||||
activateCY(p, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
p.sendMessage(plugin.getConfig2()
|
||||
.msg("login_failed"));
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().severe(
|
||||
"[Sdf1_login] handleLogin异常: "
|
||||
+ e.getMessage());
|
||||
e.printStackTrace();
|
||||
p.sendMessage(
|
||||
"§c登录过程出错,请联系管理员");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void handleReset(Player p) {
|
||||
String name = p.getName();
|
||||
String emailAddr = (String)
|
||||
plugin.getDb().getField(
|
||||
name, "email");
|
||||
if (emailAddr == null
|
||||
|| emailAddr.isEmpty()) {
|
||||
p.sendMessage(
|
||||
"§c未设置邮箱,无法重置密码");
|
||||
return;
|
||||
}
|
||||
String tempPwd = PasswordUtils
|
||||
.generateTempPassword();
|
||||
String salt = (String)
|
||||
plugin.getDb().getField(
|
||||
name, "password_salt");
|
||||
String hash = PasswordUtils.hash(
|
||||
tempPwd, salt);
|
||||
plugin.getDb().setField(name,
|
||||
"temp_password", hash);
|
||||
plugin.getDb().setField(name,
|
||||
"temp_pw_expire",
|
||||
System.currentTimeMillis()
|
||||
+ 300000L);
|
||||
|
||||
plugin.getDb().setField(name,
|
||||
"temp_pw_used", 0);
|
||||
p.sendMessage("§e正在发送临时密码...");
|
||||
final String to = emailAddr;
|
||||
final String fName = name;
|
||||
final String pwd = tempPwd;
|
||||
final Main self = plugin;
|
||||
Bukkit.getScheduler()
|
||||
.runTaskAsynchronously(self,
|
||||
() -> {
|
||||
final boolean[] sent = {false};
|
||||
Thread t = new Thread(() -> {
|
||||
sent[0] = self.getEmail()
|
||||
.sendTempPassword(
|
||||
to, fName, pwd);
|
||||
}, "Sdf1_login-reset");
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
try {
|
||||
t.join(15000);
|
||||
} catch (
|
||||
InterruptedException ignored) {
|
||||
}
|
||||
if (t.isAlive()) {
|
||||
t.interrupt();
|
||||
Bukkit.getScheduler().runTask(
|
||||
self, () ->
|
||||
p.sendMessage(
|
||||
"§c邮件发送超时"));
|
||||
return;
|
||||
}
|
||||
Bukkit.getScheduler().runTask(
|
||||
self, () -> {
|
||||
if (sent[0]) {
|
||||
p.sendMessage(
|
||||
"§a临时密码已发送到 "
|
||||
+ to);
|
||||
} else {
|
||||
p.sendMessage(
|
||||
"§c邮件发送失败");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void activateCY(Player p,
|
||||
String name) {
|
||||
try {
|
||||
org.bukkit.plugin.Plugin cy =
|
||||
Bukkit.getPluginManager()
|
||||
.getPlugin("CY_beibao");
|
||||
if (cy != null && cy.isEnabled()) {
|
||||
cy.getClass().getMethod(
|
||||
"onSdf1Activation",
|
||||
String.class,
|
||||
int.class, int.class)
|
||||
.invoke(cy, name, 0, 0);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1096
-1275
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@ import java.util.regex.Pattern;
|
||||
public class QuestTracker {
|
||||
|
||||
private final Plugin plugin;
|
||||
private final PlayerStorage storage;
|
||||
private final QuestStorage storage;
|
||||
private final Map<String, String>
|
||||
playerBiome = new HashMap<>();
|
||||
private final Map<String, List<QuestFile>>
|
||||
@@ -76,9 +76,9 @@ public class QuestTracker {
|
||||
|
||||
public QuestTracker(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.storage = new PlayerStorage(
|
||||
plugin.getDataFolder(),
|
||||
plugin.getLogger());
|
||||
this.storage = new QuestStorage(
|
||||
plugin.getDataFolder());
|
||||
|
||||
loadAllQuests();
|
||||
}
|
||||
|
||||
@@ -1490,30 +1490,22 @@ public class QuestTracker {
|
||||
}
|
||||
return unmet;
|
||||
}
|
||||
|
||||
public String getProgress(
|
||||
String player,
|
||||
String rawCond) {
|
||||
if (player == null
|
||||
|| rawCond == null)
|
||||
String player, String rawCond) {
|
||||
if (player == null || rawCond == null)
|
||||
return "§7未知";
|
||||
|
||||
String key = stripOptional(rawCond);
|
||||
// 打卡群系进度
|
||||
if (key.contains("打卡")
|
||||
&& (key.contains("群系")
|
||||
|| key.contains("风景点"))) {
|
||||
|
||||
if (key.contains("打卡")
|
||||
&& key.contains("群系")) {
|
||||
String biome =
|
||||
extractBiome(key);
|
||||
|
||||
if ("ALL".equals(biome)) {
|
||||
int total = getCounter(
|
||||
player, "biome_ALL");
|
||||
return "§7群系打卡: §e"
|
||||
+ total + "/1";
|
||||
}
|
||||
|
||||
if (!biome.isEmpty()) {
|
||||
int catCount = getCounter(
|
||||
player,
|
||||
@@ -1522,16 +1514,12 @@ public class QuestTracker {
|
||||
+ "群系: §e"
|
||||
+ catCount + "/1";
|
||||
}
|
||||
|
||||
int total = getCounter(
|
||||
player, "biome_ALL");
|
||||
return "§7群系打卡: §e"
|
||||
+ total + "/1";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 阶段依赖
|
||||
if (key.contains("完成")
|
||||
&& key.contains("阶段")) {
|
||||
boolean done = checkStageDependency(
|
||||
@@ -1541,9 +1529,6 @@ public class QuestTracker {
|
||||
: "§c✗ " + key;
|
||||
}
|
||||
|
||||
|
||||
// 注册登录(检查主数据库是否已注册)
|
||||
// 注册登录(检查主数据库是否已注册)
|
||||
if ("完成注册登录".equals(key)) {
|
||||
boolean done = getDb() != null
|
||||
&& getDb().userExists(
|
||||
@@ -1553,7 +1538,6 @@ public class QuestTracker {
|
||||
: "§c✗ 完成注册登录";
|
||||
}
|
||||
|
||||
// 绑定邮箱
|
||||
if (key.contains("绑定Email")
|
||||
|| key.contains("绑定邮箱")) {
|
||||
Object val =
|
||||
@@ -1566,7 +1550,6 @@ public class QuestTracker {
|
||||
: "§c✗ 绑定Email";
|
||||
}
|
||||
|
||||
// 在线时间
|
||||
if (key.contains("在线")
|
||||
&& key.contains("小时")) {
|
||||
int needed = parseNumberFromText(key);
|
||||
@@ -1578,17 +1561,16 @@ public class QuestTracker {
|
||||
+ needed + "小时";
|
||||
}
|
||||
|
||||
// 打招呼/发消息/聊天
|
||||
if (key.contains("打招呼")
|
||||
|| key.contains("打个招呼")
|
||||
|| key.contains("发消息")
|
||||
|| key.contains("聊天")) {
|
||||
int cur = getCounter(
|
||||
player, "CHAT");
|
||||
return "§7聊天: §e" + cur + "/1";
|
||||
return "§7聊天: §e"
|
||||
+ cur + "/1";
|
||||
}
|
||||
|
||||
// 破坏/放置方块
|
||||
if ((key.contains("破坏")
|
||||
|| key.contains("放置"))
|
||||
&& key.contains("方块")) {
|
||||
@@ -1606,20 +1588,17 @@ public class QuestTracker {
|
||||
&& key.contains("登录")) {
|
||||
int needed = parseNumberFromText(key);
|
||||
if (needed <= 0) needed = 1;
|
||||
int totalDays = getIntField(
|
||||
player,
|
||||
"total_checkin_days");
|
||||
if (totalDays == 0) {
|
||||
totalDays = getIntField(
|
||||
player,
|
||||
"checkin_streak");
|
||||
}
|
||||
Object val =
|
||||
getDb().getField(
|
||||
player,
|
||||
"checkin_streak");
|
||||
int streak = val instanceof Number
|
||||
? ((Number) val).intValue()
|
||||
: 0;
|
||||
return "§7连续登录: §e"
|
||||
+ totalDays + "/" + needed + "天";
|
||||
+ streak + "/" + needed + "天";
|
||||
}
|
||||
|
||||
|
||||
// 挖矿
|
||||
if (key.startsWith("MINE:")) {
|
||||
String[] parts = key.split(":");
|
||||
if (parts.length >= 3) {
|
||||
@@ -1634,7 +1613,6 @@ public class QuestTracker {
|
||||
}
|
||||
}
|
||||
|
||||
// 击杀生物
|
||||
if (key.startsWith("KILL:")) {
|
||||
String[] parts = key.split(":");
|
||||
if (parts.length >= 3) {
|
||||
@@ -1649,7 +1627,6 @@ public class QuestTracker {
|
||||
}
|
||||
}
|
||||
|
||||
// 击杀玩家
|
||||
if (key.startsWith("KILL_PLAYER")) {
|
||||
String[] parts = key.split(":");
|
||||
int needed = parts.length >= 2
|
||||
@@ -1660,7 +1637,6 @@ public class QuestTracker {
|
||||
+ cur + "/" + needed;
|
||||
}
|
||||
|
||||
// 合成
|
||||
if (key.startsWith("CRAFT")) {
|
||||
String[] parts = key.split(":");
|
||||
int needed = parts.length >= 2
|
||||
@@ -1671,7 +1647,6 @@ public class QuestTracker {
|
||||
+ cur + "/" + needed;
|
||||
}
|
||||
|
||||
// 钓鱼
|
||||
if (key.startsWith("FISH")) {
|
||||
String[] parts = key.split(":");
|
||||
int needed = parts.length >= 2
|
||||
@@ -1682,7 +1657,6 @@ public class QuestTracker {
|
||||
+ cur + "/" + needed;
|
||||
}
|
||||
|
||||
// 在线时长(毫秒)
|
||||
if (key.startsWith("PLAYTIME")) {
|
||||
String[] parts = key.split(":");
|
||||
long needed = parts.length >= 2
|
||||
@@ -1694,7 +1668,7 @@ public class QuestTracker {
|
||||
+ formatMs(cur) + "/"
|
||||
+ formatMs(needed);
|
||||
}
|
||||
// 上报村庄
|
||||
|
||||
if (key.contains("上报")
|
||||
&& key.contains("村庄")) {
|
||||
int needed = parseNumberFromText(key);
|
||||
@@ -1705,7 +1679,6 @@ public class QuestTracker {
|
||||
+ cur + "/" + needed;
|
||||
}
|
||||
|
||||
// 探索村庄
|
||||
if (key.contains("探索")
|
||||
&& key.contains("村庄")) {
|
||||
int cur = getCounter(
|
||||
@@ -1713,40 +1686,28 @@ public class QuestTracker {
|
||||
return "§7探索村庄: §e"
|
||||
+ cur + "/1";
|
||||
}
|
||||
// ===== 修改后 =====
|
||||
|
||||
if (key.contains("7天")
|
||||
|| key.contains("七天")) {
|
||||
int needed = parseNumberFromText(key);
|
||||
if (needed <= 0) needed = 1;
|
||||
|
||||
// 优先使用 total_checkin_days(累计天数)
|
||||
int totalDays = getIntField(
|
||||
int streak = getIntField(
|
||||
player,
|
||||
"total_checkin_days");
|
||||
if (totalDays == 0) {
|
||||
totalDays = getIntField(
|
||||
player,
|
||||
"checkin_streak");
|
||||
}
|
||||
if (totalDays == 0) {
|
||||
totalDays = getIntField(
|
||||
"checkin_streak");
|
||||
if (streak == 0) {
|
||||
streak = getIntField(
|
||||
player, "streak");
|
||||
}
|
||||
|
||||
plugin.getLogger().info(
|
||||
"[QuestTracker] 登录检测: "
|
||||
+ player
|
||||
+ " 需要=" + needed
|
||||
+ " 实际(累计天数)=" + totalDays);
|
||||
if (streak == 0) {
|
||||
streak = getIntField(
|
||||
player,
|
||||
"total_checkin_days");
|
||||
}
|
||||
return "§7近7天登录: §e"
|
||||
+ totalDays + "/"
|
||||
+ streak + "/"
|
||||
+ needed + "天";
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 完成新手任务全部
|
||||
if (key.contains("新手任务")
|
||||
&& key.contains("全部")) {
|
||||
List<QuestFile> quests =
|
||||
@@ -1763,7 +1724,6 @@ public class QuestTracker {
|
||||
+ quests.size();
|
||||
}
|
||||
|
||||
// 完成主线任务全部
|
||||
if (key.contains("主线任务")
|
||||
&& key.contains("全部")) {
|
||||
List<QuestFile> quests =
|
||||
@@ -1782,23 +1742,7 @@ public class QuestTracker {
|
||||
|
||||
return "§7" + key;
|
||||
}
|
||||
private int getIntField(
|
||||
String player, String field) {
|
||||
try {
|
||||
Object val = getDb().getField(
|
||||
player, field);
|
||||
if (val instanceof Number) {
|
||||
return ((Number) val).intValue();
|
||||
}
|
||||
if (val != null) {
|
||||
return Integer.parseInt(
|
||||
val.toString().trim());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public List<String> checkInBiome(
|
||||
String player,
|
||||
@@ -2051,32 +1995,42 @@ public class QuestTracker {
|
||||
return false;
|
||||
|
||||
String key = stripOptional(rawCond);
|
||||
// 打卡群系
|
||||
|
||||
// 无条件类文本直接通过
|
||||
if (key.equals("无前级条件")
|
||||
|| key.equals("无条件")
|
||||
|| key.equals("无")
|
||||
|| key.equals("none")
|
||||
|| key.equals("无需条件")
|
||||
|| key.equals("无解锁条件")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.contains("打卡")
|
||||
&& (key.contains("群系")
|
||||
|| key.contains("风景点"))) {
|
||||
|
||||
String biome =
|
||||
extractBiome(key);
|
||||
|
||||
if ("ALL".equals(biome)) {
|
||||
int total = getCounter(
|
||||
player, "biome_ALL");
|
||||
return total >= 1;
|
||||
}
|
||||
|
||||
if (!biome.isEmpty()) {
|
||||
int catCount = getCounter(
|
||||
player,
|
||||
"biomecat_" + biome);
|
||||
return catCount >= 1; // ← 加这一行
|
||||
return catCount >= 1;
|
||||
}
|
||||
|
||||
return getCounter(
|
||||
player, "biome_ALL") >= 1;
|
||||
}
|
||||
|
||||
// 注册登录
|
||||
if (key.contains("完成")
|
||||
&& key.contains("阶段")) {
|
||||
return checkStageDependency(
|
||||
player, key);
|
||||
}
|
||||
|
||||
if ("完成注册登录".equals(key)) {
|
||||
return getDb() != null
|
||||
@@ -2084,8 +2038,6 @@ public class QuestTracker {
|
||||
player);
|
||||
}
|
||||
|
||||
|
||||
// 绑定邮箱
|
||||
if (key.contains("绑定Email")
|
||||
|| key.contains("绑定邮箱")) {
|
||||
Object val =
|
||||
@@ -2095,7 +2047,6 @@ public class QuestTracker {
|
||||
&& !val.toString().isEmpty();
|
||||
}
|
||||
|
||||
// 在线时间
|
||||
if (key.contains("在线")
|
||||
&& key.contains("小时")) {
|
||||
int needed = parseNumberFromText(key);
|
||||
@@ -2105,7 +2056,6 @@ public class QuestTracker {
|
||||
return cur >= needed * 3600000L;
|
||||
}
|
||||
|
||||
// 打招呼/发消息/聊天
|
||||
if (key.contains("打招呼")
|
||||
|| key.contains("打个招呼")
|
||||
|| key.contains("发消息")
|
||||
@@ -2114,7 +2064,6 @@ public class QuestTracker {
|
||||
player, "CHAT") >= 1;
|
||||
}
|
||||
|
||||
// 破坏/放置方块
|
||||
if ((key.contains("破坏")
|
||||
|| key.contains("放置"))
|
||||
&& key.contains("方块")) {
|
||||
@@ -2127,25 +2076,20 @@ public class QuestTracker {
|
||||
return total >= needed;
|
||||
}
|
||||
|
||||
// 连续登录
|
||||
if (key.contains("连续")
|
||||
&& key.contains("登录")) {
|
||||
int needed = parseNumberFromText(key);
|
||||
if (needed <= 0) needed = 1;
|
||||
// 优先用累计天数,因为
|
||||
// streak 可能大于 total(数据不一致时)
|
||||
int totalDays = getIntField(
|
||||
player,
|
||||
"total_checkin_days");
|
||||
if (totalDays == 0) {
|
||||
totalDays = getIntField(
|
||||
player,
|
||||
"checkin_streak");
|
||||
}
|
||||
return totalDays >= needed;
|
||||
Object val =
|
||||
getDb().getField(
|
||||
player,
|
||||
"checkin_streak");
|
||||
int streak = val instanceof Number
|
||||
? ((Number) val).intValue()
|
||||
: 0;
|
||||
return streak >= needed;
|
||||
}
|
||||
|
||||
// 挖矿
|
||||
if (key.startsWith("MINE:")) {
|
||||
String[] p = key.split(":");
|
||||
if (p.length >= 3) {
|
||||
@@ -2155,7 +2099,6 @@ public class QuestTracker {
|
||||
}
|
||||
}
|
||||
|
||||
// 击杀生物
|
||||
if (key.startsWith("KILL:")) {
|
||||
String[] p = key.split(":");
|
||||
if (p.length >= 3) {
|
||||
@@ -2165,7 +2108,6 @@ public class QuestTracker {
|
||||
}
|
||||
}
|
||||
|
||||
// 击杀玩家
|
||||
if (key.startsWith("KILL_PLAYER")) {
|
||||
String[] p = key.split(":");
|
||||
int n = p.length >= 2
|
||||
@@ -2174,7 +2116,6 @@ public class QuestTracker {
|
||||
"KILL_PLAYER") >= n;
|
||||
}
|
||||
|
||||
// 合成
|
||||
if (key.startsWith("CRAFT")) {
|
||||
String[] p = key.split(":");
|
||||
int n = p.length >= 2
|
||||
@@ -2183,7 +2124,6 @@ public class QuestTracker {
|
||||
player, "CRAFT") >= n;
|
||||
}
|
||||
|
||||
// 钓鱼
|
||||
if (key.startsWith("FISH")) {
|
||||
String[] p = key.split(":");
|
||||
int n = p.length >= 2
|
||||
@@ -2192,7 +2132,6 @@ public class QuestTracker {
|
||||
player, "FISH") >= n;
|
||||
}
|
||||
|
||||
// 在线时长
|
||||
if (key.startsWith("PLAYTIME")) {
|
||||
String[] p = key.split(":");
|
||||
long n = p.length >= 2
|
||||
@@ -2200,69 +2139,27 @@ public class QuestTracker {
|
||||
return getCounterLong(player,
|
||||
"PLAYTIME") >= n;
|
||||
}
|
||||
// 上报村庄
|
||||
|
||||
if (key.contains("上报")
|
||||
&& key.contains("村庄")) {
|
||||
int needed = parseNumberFromText(key);
|
||||
if (needed <= 0) needed = 1;
|
||||
int cur = getCounter(
|
||||
player, "REPORT_VILLAGE");
|
||||
return cur >= needed;
|
||||
return getCounter(
|
||||
player, "REPORT_VILLAGE")
|
||||
>= needed;
|
||||
}
|
||||
|
||||
// 探索村庄
|
||||
if (key.contains("探索")
|
||||
&& key.contains("村庄")) {
|
||||
return getCounter(
|
||||
player, "REPORT_VILLAGE")
|
||||
>= 1;
|
||||
}
|
||||
// 近7天登录记录
|
||||
|
||||
if (key.contains("7天")
|
||||
|| key.contains("七天")) {
|
||||
int needed = parseNumberFromText(key);
|
||||
if (needed <= 0) needed = 1;
|
||||
// 优先使用 total_checkin_days
|
||||
int totalDays = getIntField(
|
||||
player,
|
||||
"total_checkin_days");
|
||||
if (totalDays == 0) {
|
||||
totalDays = getIntField(
|
||||
player,
|
||||
"checkin_streak");
|
||||
}
|
||||
if (totalDays == 0) {
|
||||
totalDays = getIntField(
|
||||
player, "streak");
|
||||
return totalDays >= needed;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 诊断:读取数据库所有字段
|
||||
try {
|
||||
var user = getDb().getUser(
|
||||
player);
|
||||
if (user != null) {
|
||||
plugin.getLogger().info(
|
||||
"[QuestTracker] "
|
||||
+ "登录诊断 "
|
||||
+ player + ": "
|
||||
+ user.toString());
|
||||
} else {
|
||||
plugin.getLogger().info(
|
||||
"[QuestTracker] "
|
||||
+ "登录诊断: "
|
||||
+ player
|
||||
+ " getUser返回null");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().info(
|
||||
"[QuestTracker] "
|
||||
+ "登录诊断异常: "
|
||||
+ e.getMessage());
|
||||
}
|
||||
|
||||
int streak = getIntField(
|
||||
player,
|
||||
"checkin_streak");
|
||||
@@ -2275,17 +2172,9 @@ public class QuestTracker {
|
||||
player,
|
||||
"total_checkin_days");
|
||||
}
|
||||
|
||||
plugin.getLogger().info(
|
||||
"[QuestTracker] 登录检测: "
|
||||
+ player
|
||||
+ " 需要=" + needed
|
||||
+ " 实际=" + streak);
|
||||
|
||||
return streak >= needed;
|
||||
}
|
||||
|
||||
// 完成新手任务全部内容
|
||||
if (key.contains("新手任务")
|
||||
&& key.contains("全部")) {
|
||||
List<QuestFile> quests =
|
||||
@@ -2299,7 +2188,6 @@ public class QuestTracker {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 完成主线任务全部内容
|
||||
if (key.contains("主线任务")
|
||||
&& key.contains("全部")) {
|
||||
List<QuestFile> quests =
|
||||
@@ -2365,6 +2253,23 @@ public class QuestTracker {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
private int getIntField(
|
||||
String player, String field) {
|
||||
try {
|
||||
Object val = getDb().getField(
|
||||
player, field);
|
||||
if (val instanceof Number) {
|
||||
return ((Number) val).intValue();
|
||||
}
|
||||
if (val != null) {
|
||||
return Integer.parseInt(
|
||||
val.toString().trim());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private long getCounterLong(
|
||||
String player, String key) {
|
||||
|
||||
@@ -14,15 +14,20 @@ import java.util.logging.Logger;
|
||||
public class RadioDownloadListener
|
||||
implements Listener {
|
||||
|
||||
private final Logger log;
|
||||
private final Main plugin;
|
||||
private final Logger log;
|
||||
private final Map<UUID, Integer> retryCount =
|
||||
new ConcurrentHashMap<>();
|
||||
private static final int MAX_RETRY = 2;
|
||||
private final Map<UUID, Integer> totalAttempts =
|
||||
new ConcurrentHashMap<>();
|
||||
private static final int MAX_RETRY = 3;
|
||||
// 每位玩家最多总共尝试5次,防死循环
|
||||
private static final int MAX_TOTAL = 5;
|
||||
|
||||
public RadioDownloadListener(Main plugin) {
|
||||
this.plugin = plugin;
|
||||
this.log = plugin.getLogger();
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -33,86 +38,81 @@ public class RadioDownloadListener
|
||||
String status = e.getStatus().name();
|
||||
|
||||
log.info("[Radio] " + p.getName()
|
||||
+ " status: " + status);
|
||||
+ " 资源包: " + status);
|
||||
|
||||
switch (status) {
|
||||
case "ACCEPTED":
|
||||
break;
|
||||
|
||||
case "DOWNLOADED":
|
||||
break;
|
||||
|
||||
case "SUCCESS":
|
||||
log.info("[Radio] " + p.getName()
|
||||
+ " 资源包加载成功");
|
||||
retryCount.remove(uuid);
|
||||
totalAttempts.remove(uuid);
|
||||
break;
|
||||
|
||||
case "FAILED_DOWNLOAD":
|
||||
handleRetry(p, uuid);
|
||||
int retry = retryCount
|
||||
.getOrDefault(uuid, 0) + 1;
|
||||
int total = totalAttempts
|
||||
.getOrDefault(uuid, 0) + 1;
|
||||
retryCount.put(uuid, retry);
|
||||
totalAttempts.put(uuid, total);
|
||||
|
||||
log.warning("[Radio] " + p.getName()
|
||||
+ " 下载失败 (重试"
|
||||
+ retry + "/" + MAX_RETRY
|
||||
+ ", 总计" + total
|
||||
+ "/" + MAX_TOTAL + ")");
|
||||
|
||||
if (total >= MAX_TOTAL) {
|
||||
p.sendMessage(
|
||||
"§7[Radio] §f资源包加载失败,跳过");
|
||||
retryCount.remove(uuid);
|
||||
totalAttempts.remove(uuid);
|
||||
break;
|
||||
}
|
||||
|
||||
if (retry > MAX_RETRY) {
|
||||
retryCount.put(uuid, 0);
|
||||
Bukkit.getScheduler()
|
||||
.runTaskLater(plugin,
|
||||
() -> {
|
||||
if (p.isOnline()
|
||||
&& plugin
|
||||
.radio
|
||||
!= null) {
|
||||
plugin.radio
|
||||
.sendResourcePack(
|
||||
p);
|
||||
}
|
||||
}, 100L);
|
||||
break;
|
||||
}
|
||||
|
||||
p.sendMessage(
|
||||
"§e[Radio] §f下载失败,重试中...");
|
||||
Bukkit.getScheduler()
|
||||
.runTaskLater(plugin,
|
||||
() -> {
|
||||
if (p.isOnline()
|
||||
&& plugin.radio
|
||||
!= null) {
|
||||
plugin.radio
|
||||
.sendResourcePack(
|
||||
p);
|
||||
}
|
||||
}, 60L);
|
||||
break;
|
||||
|
||||
case "DECLINED":
|
||||
log.info("[Radio] " + p.getName()
|
||||
+ " 拒绝下载");
|
||||
p.sendMessage(
|
||||
"§e[Radio] §f你拒绝了资源包");
|
||||
retryCount.remove(uuid);
|
||||
break;
|
||||
|
||||
case "DISCARDED":
|
||||
log.warning("[Radio] " + p.getName()
|
||||
+ " DISCARDED");
|
||||
p.sendMessage(
|
||||
"§c[Radio] §f资源包下载失败"
|
||||
+ ",可能原因:");
|
||||
p.sendMessage(
|
||||
"§71. CDN/防火墙拦截");
|
||||
p.sendMessage(
|
||||
"§72. SSL证书问题");
|
||||
retryCount.remove(uuid);
|
||||
break;
|
||||
|
||||
case "INVALID_URL":
|
||||
log.warning("[Radio] " + p.getName()
|
||||
+ " URL无效");
|
||||
retryCount.remove(uuid);
|
||||
totalAttempts.remove(uuid);
|
||||
break;
|
||||
|
||||
default:
|
||||
log.info("[Radio] " + p.getName()
|
||||
+ " 未知: " + status);
|
||||
retryCount.remove(uuid);
|
||||
totalAttempts.remove(uuid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRetry(Player p, UUID uuid) {
|
||||
int count = retryCount
|
||||
.getOrDefault(uuid, 0) + 1;
|
||||
retryCount.put(uuid, count);
|
||||
|
||||
log.warning("[Radio] " + p.getName()
|
||||
+ " 下载失败 (" + count
|
||||
+ "/" + MAX_RETRY + ")");
|
||||
|
||||
if (count <= MAX_RETRY) {
|
||||
p.sendMessage(
|
||||
"§e[Radio] §f下载失败,重试中... ("
|
||||
+ count + "/" + MAX_RETRY + ")");
|
||||
Bukkit.getScheduler().runTaskLater(
|
||||
plugin,
|
||||
() -> {
|
||||
if (p.isOnline()
|
||||
&& plugin.radio != null) {
|
||||
plugin.radio
|
||||
.sendResourcePack(p);
|
||||
}
|
||||
}, 60L);
|
||||
} else {
|
||||
p.sendMessage(
|
||||
"§c[Radio] §f资源包加载失败,"
|
||||
+ "部分音乐无法播放");
|
||||
retryCount.remove(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1641,4 +1641,4 @@ public class TicketManager {
|
||||
}
|
||||
return it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,5 +86,4 @@ commands:
|
||||
usage: /垃圾清理
|
||||
menu:
|
||||
description: 雪球菜单开关控制
|
||||
usage: /menu <开/关>
|
||||
commands:
|
||||
usage: /menu <开/关>
|
||||
Reference in New Issue
Block a user