修bug修bug

This commit is contained in:
BRanulf 2025-06-07 14:48:03 +08:00
parent a5b4efc36e
commit eef2bbebad
6 changed files with 8 additions and 99 deletions

View File

@ -6,7 +6,7 @@ minecraft_version=1.21.4
yarn_mappings=1.21.4+build.8
loader_version=0.16.10
# Mod Properties
mod_version=1.14.514.131
mod_version=1.14.514.132
maven_group=org.example1
archives_base_name=ServerPlayerOnlineTracker
# Dependencies

View File

@ -9,7 +9,6 @@ public class ModConfig {
private final Path configPath;
private int webPort = 60048;
private String language = "zh_cn";
private long autoSaveSeconds = 300;
public ModConfig(Path configDir) {
this.configPath = configDir.resolve("playertime-config.json");
@ -37,19 +36,13 @@ public class ModConfig {
if (json.has("webPort")) {
webPort = json.get("webPort").getAsInt();
} else {
PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少webPort字段,添加默认值'%s'并保存", webPort);
PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少webPort字段添加默认值'%s'并保存", webPort);
saveConfig();
}
if (json.has("language")) {
language = json.get("language").getAsString();
} else {
PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少“language”字段添加默认值'%s'并保存", language);
saveConfig();
}
if (json.has("autoSaveSeconds")) {
autoSaveSeconds = json.get("autoSaveSeconds").getAsLong();
} else {
PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少“autoSaveSeconds”字段添加默认值'%s'并保存", autoSaveSeconds);
PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少language字段添加默认值'%s'并保存", language);
saveConfig();
}
@ -64,7 +57,6 @@ public class ModConfig {
JsonObject json = new JsonObject();
json.addProperty("webPort", webPort);
json.addProperty("language", language);
json.addProperty("autoSaveSeconds", autoSaveSeconds);
try {
Files.createDirectories(configPath.getParent());
@ -86,9 +78,4 @@ public class ModConfig {
public String getLanguage() {
return language;
}
// 获取保存间隔
public long getSeconds() {
return autoSaveSeconds;
}
}

View File

@ -19,10 +19,6 @@ import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class PlayerTimeMod implements ModInitializer {
@ -30,29 +26,16 @@ public class PlayerTimeMod implements ModInitializer {
private static PlayerTimeTracker timeTracker;
private static WebServer webServer;
private static ModConfig config;
public static LocalizationManager localizationManager; // 新增本地化管理器
// TODO 定时保存配置文件没整暂时硬编码
private ScheduledExecutorService scheduler;
private ScheduledFuture<?> saveTask;
private static long AUTO_SAVE_INTERVAL_SECONDS;
// 后续还是想把logger改成英文
public static LocalizationManager localizationManager;
@Override
public void onInitialize() {
config = new ModConfig(FabricLoader.getInstance().getConfigDir());
localizationManager = new LocalizationManager(config.getLanguage());
scheduler = Executors.newSingleThreadScheduledExecutor();
try {
LOGGER.info("[在线时间] 初始化 玩家在线时长视奸Mod");
AUTO_SAVE_INTERVAL_SECONDS = config.getSeconds();
ServerLifecycleEvents.SERVER_STARTING.register(server -> {
timeTracker = new PlayerTimeTracker(server);
try {
@ -62,21 +45,6 @@ public class PlayerTimeMod implements ModInitializer {
} catch (Exception e) {
LOGGER.error("[在线时间] 无法启动Web服务器", e);
}
LOGGER.info("[在线时间] 每{}秒({}分钟)安排自动保存任务。",
AUTO_SAVE_INTERVAL_SECONDS, AUTO_SAVE_INTERVAL_SECONDS / 60);
saveTask = scheduler.scheduleAtFixedRate(
() -> {
if (timeTracker != null) {
LOGGER.info("[在线时间] 自动保存玩家数据中...");
timeTracker.saveAll();
LOGGER.info("[在线时间] 自动保存完成。");
}
},
AUTO_SAVE_INTERVAL_SECONDS,
AUTO_SAVE_INTERVAL_SECONDS,
TimeUnit.SECONDS
);
});
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
@ -94,24 +62,6 @@ public class PlayerTimeMod implements ModInitializer {
ServerLifecycleEvents.SERVER_STOPPING.register(server -> {
LOGGER.info("[在线时间] 服务器停止 - 正在保存数据");
if (saveTask != null) {
saveTask.cancel(false);
LOGGER.info("[在线时间] 自动保存任务已取消。");
}
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
LOGGER.warn("[在线时间] 调度程序未在5秒内终止。");
}
} catch (InterruptedException e) {
LOGGER.error("[在线时间] 调度程序终止被中断", e);
Thread.currentThread().interrupt();
}
LOGGER.info("[在线时间] 调度程序关闭");
}
if (webServer != null) {
webServer.stop();
}
@ -123,12 +73,8 @@ public class PlayerTimeMod implements ModInitializer {
}
});
} catch (Exception e) {
LOGGER.error("[在线时间] Mod出屎化失败", e);
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdownNow();
}
LOGGER.error("[在线时间] Mod初始化失败", e);
throw new RuntimeException("[在线时间] Mod初始化失败 ", e);
}
registerCommands();
@ -146,12 +92,11 @@ public class PlayerTimeMod implements ModInitializer {
return localizationManager;
}
public static void registerCommands() {
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("onlineTime")
.requires(source -> source.hasPermissionLevel(0))
.executes(context -> showOnlineTime(context.getSource(), 1)) // 默认第一页
.executes(context -> showOnlineTime(context.getSource(), 1))
.then(CommandManager.argument("page", IntegerArgumentType.integer(1))
.executes(context -> showOnlineTime(
context.getSource(),
@ -172,7 +117,7 @@ public class PlayerTimeMod implements ModInitializer {
Map<String, String> stats = tracker.getWhitelistedPlayerStats();
List<String> sorted = stats.entrySet().stream()
.sorted((a, b) -> comparePlayTime(b.getValue(), a.getValue()))
.sorted((a, b) -> comparePlayTime(a.getValue(), b.getValue()))
.map(entry -> formatPlayerTime(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
@ -249,5 +194,4 @@ public class PlayerTimeMod implements ModInitializer {
player.sendMessage(footer, false);
}
}

View File

@ -27,16 +27,6 @@ public class PlayerTimeTracker {
loadData();
}
// 没用了但是先保留吧
// private boolean isWhitelisted(String playerName) {
// MinecraftServer server = this.server;
// if (server == null) return false;
//
// return server.getPlayerManager().getWhitelist()
// .isAllowed(server.getUserCache().findByName(playerName).orElse(null));
// }
public void onPlayerJoin(ServerPlayerEntity player) {
PlayerTimeData data = playerData.computeIfAbsent(player.getUuid(), uuid -> new PlayerTimeData());
data.lastLogin = Instant.now().getEpochSecond();
@ -202,17 +192,6 @@ public class PlayerTimeTracker {
PlayerTimeMod.LOGGER.info("[在线时间] 开始保存所有玩家数据...");
JsonObject root = new JsonObject();
playerData.forEach((uuid, data) -> {
if (data.lastLogin > 0) {
long now = Instant.now().getEpochSecond();
long sessionTime = now - data.lastLogin;
if (sessionTime > 0) {
data.totalTime += sessionTime;
data.rolling30Days.addPlayTime(now, sessionTime);
data.rolling7Days.addPlayTime(now, sessionTime);
PlayerTimeMod.LOGGER.debug("[在线时间] 累积当前会话时间 {} 秒,保存期间玩家 {}", sessionTime, getPlayerName(uuid));
}
data.lastLogin = 0;
}
root.add(uuid.toString(), GSON.toJsonTree(data));
});
@ -254,7 +233,6 @@ public class PlayerTimeTracker {
try (Writer writer = Files.newBufferedWriter(dataFile)) {
GSON.toJson(root, writer);
// PlayerTimeMod.LOGGER.debug("[在线时间] Async save successful for player {}", getPlayerName(uuid));
} catch (Exception e) {
PlayerTimeMod.LOGGER.error("[在线时间] 无法异步保存玩家的在线时间数据 " + getPlayerName(uuid) + " (UUID: " + uuid + ")", e);
}
@ -325,5 +303,4 @@ public class PlayerTimeTracker {
public Path getDataFile() {
return this.dataFile;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -6,6 +6,7 @@
<title data-lang-key="playertime.web.title">玩家在线及状态统计</title>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="icon" href="favicon.ico" type="image/x-icon">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>