From 245103cf4400620d0dbbdce91fe38ed86f8f7bca Mon Sep 17 00:00:00 2001 From: BRanulf Date: Thu, 17 Jul 2025 09:19:51 +0800 Subject: [PATCH] RRRRRRRRRRRRRRRR --- README.md | 103 ++++++-- README_API.md | 230 ++++++++++++++++++ README_EN.md | 103 ++++++-- build.gradle | 118 +++------ common.gradle | 144 +++++++++++ gradle.properties | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 26 ++ settings.json | 8 + .../playertime/LocalizationManager.java | 5 +- .../branulf}/playertime/ModConfig.java | 2 +- .../branulf}/playertime/PlayerTimeMod.java | 18 +- .../playertime/PlayerTimeTracker.java | 3 +- .../branulf}/playertime/WebServer.java | 16 +- .../playertime/api/OnlinePlayersResponse.java | 2 +- .../playertime/api/PlayerCountResponse.java | 2 +- .../playertime/api/PlayerStatsResponse.java | 2 +- .../playertime/api/ServerStatusResponse.java | 2 +- .../playertime/api/WhitelistResponse.java | 2 +- .../config/playertime-default-config.json | 5 +- src/main/resources/fabric.mod.json | 5 +- src/main/resources/playertime.mixins.json | 2 +- versions/1.21.4/gradle.properties | 8 + versions/1.21.5/gradle.properties | 8 + versions/1.21.6/gradle.properties | 8 + versions/1.21.7/gradle.properties | 8 + versions/mainProject | 1 + versions/mapping_12105_12104.txt | 0 versions/mapping_12106_12105.txt | 0 versions/mapping_12107_12106.txt | 0 30 files changed, 680 insertions(+), 157 deletions(-) create mode 100644 README_API.md create mode 100644 common.gradle create mode 100644 settings.json rename src/main/java/{com/example => org/branulf}/playertime/LocalizationManager.java (97%) rename src/main/java/{com/example => org/branulf}/playertime/ModConfig.java (99%) rename src/main/java/{com/example => org/branulf}/playertime/PlayerTimeMod.java (95%) rename src/main/java/{com/example => org/branulf}/playertime/PlayerTimeTracker.java (99%) rename src/main/java/{com/example => org/branulf}/playertime/WebServer.java (97%) rename src/main/java/{com/example => org/branulf}/playertime/api/OnlinePlayersResponse.java (94%) rename src/main/java/{com/example => org/branulf}/playertime/api/PlayerCountResponse.java (93%) rename src/main/java/{com/example => org/branulf}/playertime/api/PlayerStatsResponse.java (97%) rename src/main/java/{com/example => org/branulf}/playertime/api/ServerStatusResponse.java (96%) rename src/main/java/{com/example => org/branulf}/playertime/api/WhitelistResponse.java (92%) create mode 100644 versions/1.21.4/gradle.properties create mode 100644 versions/1.21.5/gradle.properties create mode 100644 versions/1.21.6/gradle.properties create mode 100644 versions/1.21.7/gradle.properties create mode 100644 versions/mainProject create mode 100644 versions/mapping_12105_12104.txt create mode 100644 versions/mapping_12106_12105.txt create mode 100644 versions/mapping_12107_12106.txt diff --git a/README.md b/README.md index 20ecc98..db090f3 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,87 @@ -# 一个服务器在线玩家时间以及服务器状态的简单的mod +## 简体中文 + [English](https://git.branulf.top/Branulf/ServerPlayerOnlineTracker/src/branch/master/README_EN.md) -注意:本mod并不完善,可能会存在些许的bug -### 包含功能: -* 显示/记录服务器在线玩家时间 -* 显示服务器状态 -* 显示服务器在线玩家列表 -* ~~移除游戏中的Herobrine~~ +# ServerPlayerOnlineTracker - 服务器玩家在线及状态追踪 -### 使用方法: -1. 安装Fabric Loader和Fabric API -2. 将最新版本的mod放入mods文件夹 -3. 首次启动服务器自动生成配置文件 -4. 修改Web服务器端口(默认60048),语言(目前仅支持zh_cn和en_us),自动保存时间(默认300秒) -5. 如需在外部访问请确保端口已开放 +一个简单的 Fabric 服务器端 Mod,用于追踪玩家在线时长、显示服务器实时状态,并提供一个美观的网页界面。 -### API获取数据: -*(也许可以用于机器人?)* -* 获取服务器在线玩家列表:【服务器IP+配置的端口】+`/api/online-players` -* 获取服务器状态:【服务器IP+配置的端口】+`/api/server-status` -* 获取服务器在线玩家时间:【服务器IP+配置的端口】+`/api/stats` -* 获取服务器在线玩家数量:【服务器IP+配置的端口】+`/api/player-count` -* ~~原始数据文件:【服务器IP+配置的端口】+`/api/playerdata`~~ \ No newline at end of file +## 主要功能 + +* **玩家在线时长追踪** + * 记录玩家总在线时长、最近30天和最近7天的在线时长。 + * 支持仅追踪白名单玩家(可在配置文件中设置)。 + * 数据自动保存,防止服务器崩溃导致数据丢失。 +* **服务器状态监控** + * 实时显示服务器内存使用情况(已用/可用/使用率)。 + * 实时显示服务器磁盘使用情况(总量/已用/可用/使用率)。 + * 实时显示服务器性能指标(TPS/MSPT)。 + * 显示服务器运行时间、版本、在线玩家数、最大玩家数、MOTD、处理器核心数。 +* **网页界面** + * 提供一个直观、响应式的网页界面,方便查看所有统计数据。 + * 支持深色/浅色主题切换。 + * 数据自动刷新。 +* **游戏内命令** + * `/onlineTime [页码]`:在游戏内查看玩家在线时长排行榜。 +* **多语言支持** + * 支持简体中文 (`zh_cn`) 和英文 (`en_us`)。 + * 可在配置文件中切换语言。 +* **更新检查** + * Mod 启动时自动检查新版本。 + +## 安装 + +1. 确保您的 Minecraft 服务器已安装 Fabric Loader (推荐 0.15.0+)。 +2. 下载最新版本的 `ServerPlayerOnlineTracker-*.jar` 文件。 +3. 将下载的 `.jar` 文件放入服务器的 `mods` 文件夹。 +4. 启动服务器。 + +## 使用方法 + +### 网页界面 + +Mod 启动后,会自动在您配置的端口(默认 `60048`)启动一个 Web 服务器。 + +1. 在浏览器中访问 `http://您的服务器IP:60048` 即可查看所有统计数据。 +2. 如果端口被占用或您想更改端口,请修改 `config/playertime-config.json` 文件中的 `webPort` 字段。 + +### 游戏内命令 + +* `/onlineTime`:查看第一页玩家在线时长排行榜。 +* `/onlineTime <页码>`:查看指定页码的玩家在线时长排行榜。 + +## 配置文件 + +首次运行 Mod 后,会在服务器根目录的 `config` 文件夹下生成一个 `playertime-config.json` 文件。您可以编辑此文件来调整 Mod 的行为。 + +```json +{ + "webPort": 60048, // 网页服务器监听的端口,默认 60048 + "language": "zh_cn", // 网页和游戏内消息的语言,可选 "zh_cn" 或 "en_us" + "whitelistOnly": true, // 是否只追踪和显示白名单玩家的在线时间,默认 true + "saveIntervalMinutes": 5 // 自动保存玩家数据的时间间隔(分钟),默认 5 分钟,设置为 0 禁用 +} +``` + +## API + +[API文档](https://git.branulf.top/Branulf/ServerPlayerOnlineTracker/src/branch/master/README_API.md) + +## 兼容性 + +* **Minecraft 版本:** 1.21.4+ +* **Fabric Loader:** 0.16.10+ +* **依赖:** Fabric API + +## 许可证 + +本项目基于 [GPL3 许可证](https://www.gnu.org/licenses/gpl-3.0.en.html) 开源。 + +## 链接 + +* **源代码:** [https://git.branulf.top/Branulf/ServerPlayerOnlineTracker](https://git.branulf.top/Branulf/ServerPlayerOnlineTracker) +* **主页:** [https://git.branulf.top/Branulf](https://git.branulf.top/Branulf) + +## 鸣谢 + +* **作者:** BRanulf \ No newline at end of file diff --git a/README_API.md b/README_API.md new file mode 100644 index 0000000..15bd561 --- /dev/null +++ b/README_API.md @@ -0,0 +1,230 @@ +### 可用 API 接口 + +本 Mod 提供了一系列 RESTful API 接口,允许外部应用获取服务器的玩家在线数据和实时状态。所有 API 接口均通过 HTTP GET 请求访问。 + +**基础 URL:** `http://您的服务器IP:配置的端口` (默认端口为 `60048`) + +--- + +#### `GET /api/stats` + +* **描述:** 获取所有玩家的在线时长统计数据。 +* **响应:** JSON 数组,每个元素代表一个玩家的统计信息。 +* **响应示例结构:** + + ```json + [ + { + "playerName": "玩家名称", + "uuid": "114514-1919810", + "totalTimeSeconds": 123456, + "totalTimeFormatted": "34h 17m", + "last30DaysSeconds": 54321, + "last30DaysFormatted": "15h 05m", + "last7DaysSeconds": 9876, + "last7DaysFormatted": "02h 44m" + } + // ... 更多玩家 + ] + ``` + +* **字段说明:** + * `playerName` (String): 玩家名称。 + * `uuid` (String): 玩家的 UUID。 + * `totalTimeSeconds` (long): 总在线时长(秒)。 + * `totalTimeFormatted` (String): 总在线时长(格式化字符串,例如 "34h 17m")。 + * `last30DaysSeconds` (long): 最近 30 天在线时长(秒)。 + * `last30DaysFormatted` (String): 最近 30 天在线时长(格式化字符串)。 + * `last7DaysSeconds` (long): 最近 7 天在线时长(秒)。 + * `last7DaysFormatted` (String): 最近 7 天在线时长(格式化字符串)。 + +--- + +#### `GET /api/lang` + +* **描述:** 获取 Mod 当前加载的本地化语言字符串。 + * **注意:** 此接口主要用于内部调试和网页前端加载语言,不建议公开暴露。 +* **响应:** JSON 对象,键为语言字符串的 key,值为对应的翻译文本。 +* **响应示例结构:** + + ```json + { + "playertime.command.title": "§6===== 玩家在线时长 (第 {0}/{1} 页) =====", + "playertime.web.title": "玩家在线及状态统计", + // ... 更多语言键值对 + } + ``` + +--- + +#### `GET /api/online-players` + +* **描述:** 获取当前在线玩家的列表,按白名单状态分类。 +* **响应:** JSON 对象,包含两个列表:`whitelisted` 和 `non_whitelisted`。 +* **响应示例结构:** + + ```json + { + "whitelisted": [ + { + "name": "WhitelistedPlayer1", + "uuid": "114514-1919810" + } + ], + "non_whitelisted": [ + { + "name": "NonWhitelistedPlayer1", + "uuid": "51121-55555121" + } + ] + } + ``` + +* **字段说明:** + * `whitelisted` (List>): 白名单在线玩家列表。每个 Map 包含 `name` (玩家名称) 和 `uuid` (玩家 UUID)。 + * `non_whitelisted` (List>): 非白名单在线玩家列表。每个 Map 包含 `name` (玩家名称) 和 `uuid` (玩家 UUID)。 + +--- + +#### `GET /api/player-count` + +* **描述:** 获取当前在线玩家的数量统计。 +* **响应:** JSON 对象,包含总数、白名单玩家数和非白名单玩家数。 +* **响应示例结构:** + + ```json + { + "total": 10, + "whitelisted": 8, + "non_whitelisted": 2 + } + ``` + +* **字段说明:** + * `total` (int): 在线玩家总数。 + * `whitelisted` (int): 在线白名单玩家数。 + * `non_whitelisted` (int): 在线非白名单玩家数(通常指假人或未在白名单的玩家)。 + +--- + +#### `GET /api/whitelist` + +* **描述:** 获取服务器的白名单列表。 +* **响应:** JSON 数组,每个元素代表一个白名单玩家的信息。 +* **响应示例结构:** + + ```json + [ + { + "name": "BRanulf", + "uuid": "114514-1919810", + "online": true + }, + { + "name": "DarkSharkBee", + "uuid": "51121-55555121", + "online": false + } + // ... 更多白名单玩家 + ] + ``` + +* **字段说明:** + * `name` (String): 白名单玩家名称。 + * `uuid` (String): 白名单玩家的 UUID。 + * `online` (boolean): 该玩家当前是否在线。 + +--- + +#### `GET /api/server-status` + +* **描述:** 获取服务器的详细运行状态信息。 +* **响应:** JSON 对象,包含内存、磁盘、处理器、运行时间及服务器自身信息。 +* **响应示例结构:** + + ```json + { + "memory": { + "max": 8589934592, + "total": 8589934592, + "used": 2147483648, + "free": 6442450944, + "usage_percentage": 25.0 + }, + "disk": { + "total": 1073741824000, + "free": 536870912000, + "usable": 536870912000, + "usage_percentage": 50.0 + }, + "available_processors": 8, + "uptime": 3600, + "uptime_formatted": "01小时 00分钟 00秒", + "server": { + "version": "1.21.4", + "motd": "§aWelcome to My Server!", + "player_count": 5, + "max_players": 20, + "average_tick_time_ms": 15.23, + "recent_tick_samples_ms": [14.5, 16.1, 15.0, 15.8, ...] + } + } + ``` + +* **字段说明:** + * `memory` (Object): 内存统计信息。 + * `max` (long): JVM 可用的最大内存(字节)。 + * `total` (long): JVM 当前分配的总内存(字节)。 + * `used` (long): JVM 已使用的内存(字节)。 + * `free` (long): JVM 可用的空闲内存(字节)。 + * `usage_percentage` (double): 内存使用率(已用 / 最大 * 100)。 + * `disk` (Object): 磁盘统计信息。 + * `total` (long): 磁盘总空间(字节)。 + * `free` (long): 磁盘空闲空间(字节)。 + * `usable` (long): 磁盘可用空间(字节)。 + * `usage_percentage` (double): 磁盘使用率((总 - 空闲) / 总 * 100)。 + * `available_processors` (int): 服务器可用的处理器核心数。 + * `uptime` (long): 服务器运行时间(秒)。 + * `uptime_formatted` (String): 服务器运行时间(格式化字符串,例如 "01小时 00分钟 00秒")。 + * `server` (Object): Minecraft 服务器自身信息。 + * `version` (String): Minecraft 服务器版本。 + * `motd` (String): 服务器 MOTD。 + * `player_count` (int): 当前在线玩家数。 + * `max_players` (int): 服务器最大玩家容量。 + * `average_tick_time_ms` (double): 服务器平均 Tick 时间(毫秒,即 MSPT)。 + * `recent_tick_samples_ms` (List): 最近的 Tick 时间样本(毫秒)。 + +--- + +#### `GET /api/playerdata` + +* **描述:** 获取原始的玩家在线时间数据文件内容。 + * **警告:** 此接口直接暴露服务器的玩家数据文件内容,包含 UUID 和在线时间等敏感信息。**强烈建议不要将此接口公开暴露给外部网络。** +* **响应:** JSON 对象,内容与 `player_time_data.json` 文件完全一致。 +* **响应示例结构:** + + ```json + { + "114514-1919810": { + "totalTime": 123456, + "lastLogin": 0, // 0 表示离线,非 0 表示上次登录时间戳 + "rolling30Days": { + "days": 30, + "entries": [ + { "timestamp": 1678886400, "seconds": 3600 }, + // ... + ] + }, + "rolling7Days": { + "days": 7, + "entries": [ + { "timestamp": 1678886400, "seconds": 1800 }, + // ... + ] + } + }, + "51121-55555121": { + // ... + } + } + ``` \ No newline at end of file diff --git a/README_EN.md b/README_EN.md index a34c84e..a319807 100644 --- a/README_EN.md +++ b/README_EN.md @@ -1,24 +1,87 @@ -# A simple mod for tracking online player time and server status +## English + [中文简体](https://git.branulf.top/Branulf/ServerPlayerOnlineTracker/src/branch/master/README.md) -Note: This mod is not perfect and may have some bugs. -### Features include: -* Display/record server online player time -* Show server status -* Display a list of online players on the server -* ~~Remove Herobrine from the game~~ +# ServerPlayerOnlineTracker - Server Player Online & Status Tracker -### How to use: -1. Install Fabric Loader and Fabric API. -2. Place the latest version of the mod into the mods folder. -3. The configuration file will be generated automatically when starting the server for the first time. -4. Modify the web server port (default 60048), language (currently only supports zh_cn and en_us), and automatic save interval (default 300 seconds). -5. If external access is needed, ensure that the port is open. +A simple Fabric server-side mod designed to track player online time, display real-time server status, and provide a beautiful web interface. -### API data retrieval: -*(Maybe can be used for bots?)* -* Get a list of online players on the server: [Server IP + configured port] + `/api/online-players` -* Get server status: [Server IP + configured port] + `/api/server-status` -* Get online player time on the server: [Server IP + configured port] + `/api/stats` -* Get number of online players on the server: [Server IP + configured port] + `/api/player-count` -* ~~Raw data file: [Server IP + configured port] + `/api/playerdata`~~ \ No newline at end of file +## Key Features + +* **Player Online Time Tracking** + * Records total online time, last 30 days, and last 7 days online time for players. + * Supports tracking whitelisted players only (configurable in the config file). + * Automatic data saving to prevent data loss from server crashes. +* **Server Status Monitoring** + * Real-time display of server memory usage (used/available/percentage). + * Real-time display of server disk usage (total/used/available/percentage). + * Real-time display of server performance metrics (TPS/MSPT). + * Shows server uptime, version, current player count, max players, MOTD, and processor cores. +* **Web Interface** + * Provides an intuitive and responsive web interface for easy viewing of all statistics. + * Supports dark/light theme toggling. + * Automatic data refresh. +* **In-Game Command** + * `/onlineTime [page]` to view the player online time leaderboard in-game. +* **Multi-language Support** + * Supports Simplified Chinese (`zh_cn`) and English (`en_us`). + * Language can be switched in the configuration file. +* **Update Checker** + * Automatically checks for new mod versions on startup. + +## Installation + +1. Ensure you have Fabric Loader installed on your Minecraft server (recommended 0.15.0+). +2. Download the latest `ServerPlayerOnlineTracker-*.jar` file. +3. Place the downloaded `.jar` file into your server's `mods` folder. +4. Start your server. + +## Usage + +### Web Interface + +After the mod starts, a web server will automatically launch on your configured port (default `60048`). + +1. Access it in your browser by navigating to `http://YOUR_SERVER_IP:60048` to view all statistics. +2. If the port is occupied or you wish to change it, modify the `webPort` field in the `config/playertime-config.json` file. + +### In-Game Command + +* `/onlineTime`: View the first page of the player online time leaderboard. +* `/onlineTime `: View a specific page of the player online time leaderboard. + +## Configuration + +Upon the first run of the mod, a `playertime-config.json` file will be generated in your server's `config` folder. You can edit this file to adjust the mod's behavior. + +```json +{ + "webPort": 60048, // Port for the web server to listen on, default 60048 + "language": "zh_cn", // Language for web and in-game messages, options: "zh_cn" or "en_us" + "whitelistOnly": true, // Whether to track and display online time only for whitelisted players, default true + "saveIntervalMinutes": 5 // Interval for automatic player data saving in minutes, default 5 minutes, set to 0 to disable +} +``` + +## API + +[API Documentation](https://git.branulf.top/Branulf/ServerPlayerOnlineTracker/src/branch/master/README_API.md) + +## Compatibility + +* **Minecraft Version:** 1.21.4+ +* **Fabric Loader:** 0.16.10+ +* **Dependencies:** Fabric API + +## License + +This project is open-source under the [GPL3 License](https://www.gnu.org/licenses/gpl-3.0.en.html). + +## Links + +* **Source Code:** [https://git.branulf.top/Branulf/ServerPlayerOnlineTracker](https://git.branulf.top/Branulf/ServerPlayerOnlineTracker) +* **Homepage:** [https://git.branulf.top/Branulf](https://git.branulf.top/Branulf) + +## Credits + +* **Author:** BRanulf \ No newline at end of file diff --git a/build.gradle b/build.gradle index 45341dd..505cdb6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,96 +1,46 @@ plugins { - id 'fabric-loom' version '1.9.2' - id 'maven-publish' + id 'fabric-loom' version '1.10.5' apply false + id 'com.replaymod.preprocess' version '9d21b334a7' + + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false } version = project.mod_version group = project.maven_group -base { - archivesName = project.archives_base_name +preprocess { + strictExtraMappings.set(false) + def mc12104 = createNode("1.21.4", 1_21_04, "") + def mc12105 = createNode("1.21.5", 1_21_05, "") + def mc12106 = createNode("1.21.6", 1_21_06, "") + def mc12107 = createNode("1.21.7", 1_21_07, "") + + mc12107.link(mc12106, file("versions/mapping_12107_12106.txt")) + mc12106.link(mc12105, file("versions/mapping_12106_12105.txt")) + mc12105.link(mc12104, file("versions/mapping_12105_12104.txt")) } - -repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. -} - -dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - implementation 'com.google.code.gson:gson:2.8.9' -} - -processResources { - inputs.property "version", project.version - inputs.property "minecraft_version", project.minecraft_version - inputs.property "loader_version", project.loader_version - filteringCharset "UTF-8" - - filesMatching("fabric.mod.json") { - expand "version": project.version, - "minecraft_version": project.minecraft_version, - "loader_version": project.loader_version +tasks.register('buildAndGather') { + subprojects { + dependsOn project.tasks.named('build').get() } - -// from(sourceSets.main.resources.srcDirs) { -// include "assets/**" -// } -} - -def targetJavaVersion = 21 -tasks.withType(JavaCompile).configureEach { - // ensure that the encoding is set to UTF-8, no matter what the system default is - // this fixes some edge cases with special characters not displaying correctly - // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html - // If Javadoc is generated, this must be specified in that task too. - it.options.encoding = "UTF-8" - if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { - it.options.release.set(targetJavaVersion) - } -} - -java { - def javaVersion = JavaVersion.toVersion(targetJavaVersion) - if (JavaVersion.current() < javaVersion) { - toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) - } - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() -} - -jar { - from("LICENSE") { - rename { "${it}_${project.archivesBaseName}" } - } -} - -// configure the maven publication -publishing { - publications { - create("mavenJava", MavenPublication) { - artifactId = project.archives_base_name - from components.java + doFirst { + println 'Gathering builds' + def buildLibs = { + p -> p.buildDir.toPath().resolve('libs') + } + delete fileTree(buildLibs(rootProject)) { + include '*' + } + subprojects { + copy { + from(buildLibs(project)) { + include '*.jar' + exclude '*-dev.jar', '*-sources.jar', '*-shadow.jar' + } + into buildLibs(rootProject) + duplicatesStrategy DuplicatesStrategy.INCLUDE + } } } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } } - - diff --git a/common.gradle b/common.gradle new file mode 100644 index 0000000..55b4d0d --- /dev/null +++ b/common.gradle @@ -0,0 +1,144 @@ +apply plugin: 'maven-publish' +apply plugin: 'com.github.johnrengelman.shadow' +apply plugin: 'fabric-loom' +apply plugin: 'com.replaymod.preprocess' + +int mcVersion = project.mcVersion + +repositories { + maven { + url 'https://maven.fabricmc.net/' + } + maven { + url 'https://masa.dy.fi/maven' + } + maven { + url 'https://maven.fallenbreath.me/releases' + } + maven { + url 'https://jitpack.io' + } + maven { + url 'https://www.cursemaven.com' + } + maven { url "https://maven.shedaniel.me/" } + maven {url "https://maven.terraformersmc.com/"} +} + +dependencies { + minecraft "com.mojang:minecraft:${project.minecraft_version}" // 从子项目 + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" // 从子项目 + modImplementation "net.fabricmc:fabric-loader:${rootProject.loader_version}" // 从根项目 + + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" + + implementation 'com.google.code.gson:gson:2.8.9' +} + + +JavaVersion JAVA_COMPATIBILITY +if (mcVersion >= 12100) { + JAVA_COMPATIBILITY = JavaVersion.VERSION_21 +} else if (mcVersion >= 11800) { + JAVA_COMPATIBILITY = JavaVersion.VERSION_17 +} else if (mcVersion >= 11700) { + JAVA_COMPATIBILITY = JavaVersion.VERSION_16 +} else { + JAVA_COMPATIBILITY = JavaVersion.VERSION_1_8 +} +JavaVersion MIXIN_COMPATIBILITY_LEVEL = JAVA_COMPATIBILITY + +loom { + def commonVmArgs = ['-Dmixin.debug.export=true'] + runConfigs.configureEach { + runDir '../../run' + vmArgs commonVmArgs + ideConfigGenerated true + } +} + +shadowJar { + configurations = [project.configurations.shadow] + exclude("META-INF") + archiveClassifier.set('shadow') +} + +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +tasks.withType(ShadowJar).configureEach { + enableRelocation true + relocationPrefix 'branulf.playertime.libs' +} + +remapJar { + dependsOn(shadowJar) + mustRunAfter(shadowJar) + inputFile = shadowJar.archiveFile +} + +String modVersionSuffix = '' +if (System.getenv("BUILD_RELEASE") != "true") { + String buildNumber = System.getenv("BUILD_ID") + modVersionSuffix += buildNumber != null ? ('+build.' + buildNumber) : '' +} +String fullModVersion = rootProject.mod_version + modVersionSuffix + +String fullProjectVersion + +group = rootProject.maven_group +if (System.getenv("JITPACK") == "true") { + base.archivesName = rootProject.archives_base_name + '-mc' + project.minecraft_version + fullProjectVersion = 'v' + rootProject.mod_version + modVersionSuffix +} else { + base.archivesName = rootProject.archives_base_name + fullProjectVersion = 'v' + rootProject.mod_version + '-mc' + project.minecraft_version + modVersionSuffix +} +version = fullProjectVersion + +processResources { + inputs.property "id", rootProject.mod_id + inputs.property "name", rootProject.mod_name + inputs.property "version", fullModVersion + + filesMatching("fabric.mod.json") { + def valueMap = [ + "id" : rootProject.mod_id, + "name" : rootProject.mod_name, + "version" : fullModVersion, + "minecraft_version": project.minecraft_dependency, + "loader_version" : rootProject.loader_version + ] + expand valueMap + } + +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" + options.compilerArgs << "-Xlint:deprecation" << "-Xlint:unchecked" + if (JAVA_COMPATIBILITY <= JavaVersion.VERSION_1_8) { + options.compilerArgs << '-Xlint:-options' + } +} + +java { + sourceCompatibility = JAVA_COMPATIBILITY + targetCompatibility = JAVA_COMPATIBILITY + withSourcesJar() +} + +jar { + from(rootProject.file('LICENSE')) { + rename { "${it}_${rootProject.archives_base_name}" } + } +} + +//publishing { +// publications { +// mavenJava(MavenPublication) { +// from components.java +// } +// } +// repositories { +// } +//} diff --git a/gradle.properties b/gradle.properties index ea2e8a8..5378078 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,9 @@ minecraft_version=1.21.4 yarn_mappings=1.21.4+build.8 loader_version=0.16.10 # Mod Properties -mod_version=1.14.514.141 +mod_name=Disc Jockey Revive +mod_id=disc_jockey_revive +mod_version=1.14.514.144 maven_group=org.example1 archives_base_name=ServerPlayerOnlineTracker # Dependencies diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5482f4d..39b0042 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.11.1-bin.zip +distributionUrl=https://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.12.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index f91a4fe..cbdfe54 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,9 +1,35 @@ +import groovy.json.JsonSlurper + pluginManagement { repositories { maven { name = 'Fabric' url = 'https://maven.fabricmc.net/' } + maven { + name = 'Jitpack' + url = 'https://jitpack.io' + } + mavenCentral() gradlePluginPortal() } + resolutionStrategy { + eachPlugin { + switch (requested.id.id) { + case "com.replaymod.preprocess": { + useModule("com.github.Fallen-Breath:preprocessor:${requested.version}") + break + } + } + } + } +} + +def settings = new JsonSlurper().parseText(file('settings.json').text) +for (String version : settings.versions) { + include(":$version") + + def proj = project(":$version") + proj.projectDir = file("versions/$version") + proj.buildFileName = "../../common.gradle" } diff --git a/settings.json b/settings.json new file mode 100644 index 0000000..2c8244b --- /dev/null +++ b/settings.json @@ -0,0 +1,8 @@ +{ + "versions": [ + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7" + ] +} diff --git a/src/main/java/com/example/playertime/LocalizationManager.java b/src/main/java/org/branulf/playertime/LocalizationManager.java similarity index 97% rename from src/main/java/com/example/playertime/LocalizationManager.java rename to src/main/java/org/branulf/playertime/LocalizationManager.java index 4f08fda..4339249 100644 --- a/src/main/java/com/example/playertime/LocalizationManager.java +++ b/src/main/java/org/branulf/playertime/LocalizationManager.java @@ -1,6 +1,5 @@ -package com.example.playertime; +package org.branulf.playertime; -import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import net.fabricmc.loader.api.FabricLoader; @@ -12,7 +11,7 @@ import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; -// 这个是gemini写的 (保留原注释,但代码已根据需求调整) +// 这个是AI写的 (保留原注释,但代码已根据需求调整) public class LocalizationManager { private final Map translations = new HashMap<>(); private final String defaultLanguage = "zh_cn"; // 默认语言代码 diff --git a/src/main/java/com/example/playertime/ModConfig.java b/src/main/java/org/branulf/playertime/ModConfig.java similarity index 99% rename from src/main/java/com/example/playertime/ModConfig.java rename to src/main/java/org/branulf/playertime/ModConfig.java index 4a9a5bf..907dfa7 100644 --- a/src/main/java/com/example/playertime/ModConfig.java +++ b/src/main/java/org/branulf/playertime/ModConfig.java @@ -1,4 +1,4 @@ -package com.example.playertime; +package org.branulf.playertime; import com.google.gson.*; import java.io.*; diff --git a/src/main/java/com/example/playertime/PlayerTimeMod.java b/src/main/java/org/branulf/playertime/PlayerTimeMod.java similarity index 95% rename from src/main/java/com/example/playertime/PlayerTimeMod.java rename to src/main/java/org/branulf/playertime/PlayerTimeMod.java index 2e53ded..c023316 100644 --- a/src/main/java/com/example/playertime/PlayerTimeMod.java +++ b/src/main/java/org/branulf/playertime/PlayerTimeMod.java @@ -1,4 +1,4 @@ -package com.example.playertime; +package org.branulf.playertime; import com.mojang.brigadier.arguments.IntegerArgumentType; import net.fabricmc.api.ModInitializer; @@ -26,12 +26,10 @@ import org.w3c.dom.NodeList; import org.w3c.dom.Element; import java.net.URL; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; public class PlayerTimeMod implements ModInitializer { public static final Logger LOGGER = LoggerFactory.getLogger("PlayerTimeTracker"); @@ -223,11 +221,18 @@ public class PlayerTimeMod implements ModInitializer { MutableText footer = Text.literal(""); if (currentPage > 1) { + //#if MC >= 12105 + //$ footer.append(Text.literal(localizationManager.getString("playertime.command.prev_page")) + //$ .styled(style -> style.withClickEvent(new ClickEvent.RunCommand( + //$ "/onlineTime " + (currentPage - 1) + //$ )).withColor(Formatting.GREEN))); + //#else footer.append(Text.literal(localizationManager.getString("playertime.command.prev_page")) .styled(style -> style.withClickEvent(new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/onlineTime " + (currentPage - 1) )).withColor(Formatting.GREEN))); + //#endif } if (currentPage > 1 && currentPage < totalPages) { @@ -240,11 +245,18 @@ public class PlayerTimeMod implements ModInitializer { if (currentPage > 1 || totalEntries > 0) { footer.append(" "); } + //#if MC >= 12105 + //$ footer.append(Text.literal(localizationManager.getString("playertime.command.next_page")) + //$ .styled(style -> style.withClickEvent(new ClickEvent.RunCommand( + //$ "/onlineTime " + (currentPage + 1) + //$ )).withColor(Formatting.GREEN))); + //#else footer.append(Text.literal(localizationManager.getString("playertime.command.next_page")) .styled(style -> style.withClickEvent(new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/onlineTime " + (currentPage + 1) )).withColor(Formatting.GREEN))); + //#endif } player.sendMessage(footer, false); diff --git a/src/main/java/com/example/playertime/PlayerTimeTracker.java b/src/main/java/org/branulf/playertime/PlayerTimeTracker.java similarity index 99% rename from src/main/java/com/example/playertime/PlayerTimeTracker.java rename to src/main/java/org/branulf/playertime/PlayerTimeTracker.java index 1b76e97..8838f90 100644 --- a/src/main/java/com/example/playertime/PlayerTimeTracker.java +++ b/src/main/java/org/branulf/playertime/PlayerTimeTracker.java @@ -1,4 +1,4 @@ -package com.example.playertime; +package org.branulf.playertime; import com.google.gson.*; import com.mojang.authlib.GameProfile; @@ -14,7 +14,6 @@ import java.nio.file.Path; import java.time.Instant; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; public class PlayerTimeTracker { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); diff --git a/src/main/java/com/example/playertime/WebServer.java b/src/main/java/org/branulf/playertime/WebServer.java similarity index 97% rename from src/main/java/com/example/playertime/WebServer.java rename to src/main/java/org/branulf/playertime/WebServer.java index 4fffdba..0c35f4e 100644 --- a/src/main/java/com/example/playertime/WebServer.java +++ b/src/main/java/org/branulf/playertime/WebServer.java @@ -1,18 +1,14 @@ -package com.example.playertime; +package org.branulf.playertime; import com.google.gson.*; import com.sun.net.httpserver.HttpServer; -import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpExchange; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.PlayerManager; -import net.minecraft.server.network.ServerPlayerEntity; import java.io.*; import java.lang.management.ManagementFactory; import java.net.InetSocketAddress; -import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.*; import java.util.*; @@ -20,11 +16,11 @@ import java.util.concurrent.*; import java.util.stream.Collectors; // 导入API类,别忘了 -import com.example.playertime.api.PlayerStatsResponse; -import com.example.playertime.api.ServerStatusResponse; -import com.example.playertime.api.OnlinePlayersResponse; -import com.example.playertime.api.PlayerCountResponse; -import com.example.playertime.api.WhitelistResponse; +import org.branulf.playertime.api.PlayerStatsResponse; +import org.branulf.playertime.api.ServerStatusResponse; +import org.branulf.playertime.api.OnlinePlayersResponse; +import org.branulf.playertime.api.PlayerCountResponse; +import org.branulf.playertime.api.WhitelistResponse; public class WebServer { diff --git a/src/main/java/com/example/playertime/api/OnlinePlayersResponse.java b/src/main/java/org/branulf/playertime/api/OnlinePlayersResponse.java similarity index 94% rename from src/main/java/com/example/playertime/api/OnlinePlayersResponse.java rename to src/main/java/org/branulf/playertime/api/OnlinePlayersResponse.java index 3e135c8..96899cf 100644 --- a/src/main/java/com/example/playertime/api/OnlinePlayersResponse.java +++ b/src/main/java/org/branulf/playertime/api/OnlinePlayersResponse.java @@ -1,4 +1,4 @@ -package com.example.playertime.api; +package org.branulf.playertime.api; import java.util.List; import java.util.Map; diff --git a/src/main/java/com/example/playertime/api/PlayerCountResponse.java b/src/main/java/org/branulf/playertime/api/PlayerCountResponse.java similarity index 93% rename from src/main/java/com/example/playertime/api/PlayerCountResponse.java rename to src/main/java/org/branulf/playertime/api/PlayerCountResponse.java index 5eef9eb..1dec3bc 100644 --- a/src/main/java/com/example/playertime/api/PlayerCountResponse.java +++ b/src/main/java/org/branulf/playertime/api/PlayerCountResponse.java @@ -1,4 +1,4 @@ -package com.example.playertime.api; +package org.branulf.playertime.api; // 用于 /api/player-count 接口返回的玩家数量数据结构 public class PlayerCountResponse { diff --git a/src/main/java/com/example/playertime/api/PlayerStatsResponse.java b/src/main/java/org/branulf/playertime/api/PlayerStatsResponse.java similarity index 97% rename from src/main/java/com/example/playertime/api/PlayerStatsResponse.java rename to src/main/java/org/branulf/playertime/api/PlayerStatsResponse.java index afb950b..d7e6f84 100644 --- a/src/main/java/com/example/playertime/api/PlayerStatsResponse.java +++ b/src/main/java/org/branulf/playertime/api/PlayerStatsResponse.java @@ -1,4 +1,4 @@ -package com.example.playertime.api; +package org.branulf.playertime.api; // 用于 /api/stats 接口返回的玩家统计数据结构 public class PlayerStatsResponse { diff --git a/src/main/java/com/example/playertime/api/ServerStatusResponse.java b/src/main/java/org/branulf/playertime/api/ServerStatusResponse.java similarity index 96% rename from src/main/java/com/example/playertime/api/ServerStatusResponse.java rename to src/main/java/org/branulf/playertime/api/ServerStatusResponse.java index acaa47b..d8777f9 100644 --- a/src/main/java/com/example/playertime/api/ServerStatusResponse.java +++ b/src/main/java/org/branulf/playertime/api/ServerStatusResponse.java @@ -1,4 +1,4 @@ -package com.example.playertime.api; +package org.branulf.playertime.api; import java.util.List; diff --git a/src/main/java/com/example/playertime/api/WhitelistResponse.java b/src/main/java/org/branulf/playertime/api/WhitelistResponse.java similarity index 92% rename from src/main/java/com/example/playertime/api/WhitelistResponse.java rename to src/main/java/org/branulf/playertime/api/WhitelistResponse.java index 53fc6a8..265f497 100644 --- a/src/main/java/com/example/playertime/api/WhitelistResponse.java +++ b/src/main/java/org/branulf/playertime/api/WhitelistResponse.java @@ -1,4 +1,4 @@ -package com.example.playertime.api; +package org.branulf.playertime.api; // 用于 /api/whitelist 接口返回的白名单列表数据结构 public class WhitelistResponse { diff --git a/src/main/resources/config/playertime-default-config.json b/src/main/resources/config/playertime-default-config.json index fe0250d..f4e4686 100644 --- a/src/main/resources/config/playertime-default-config.json +++ b/src/main/resources/config/playertime-default-config.json @@ -1,5 +1,6 @@ { "webPort": 60048, "language": "zh_cn", - "autoSaveSeconds": 60 -} + "whitelistOnly": true, + "saveIntervalMinutes": 5 +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 441061a..ecf2145 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -16,12 +16,9 @@ "environment": "server", "entrypoints": { "main": [ - "com.example.playertime.PlayerTimeMod" + "org.branulf.playertime.PlayerTimeMod" ] }, - "mixins": [ - "playertime.mixins.json" - ], "depends": { "fabricloader": ">=${loader_version}", "fabric": "*", diff --git a/src/main/resources/playertime.mixins.json b/src/main/resources/playertime.mixins.json index 5f09377..eb0a118 100644 --- a/src/main/resources/playertime.mixins.json +++ b/src/main/resources/playertime.mixins.json @@ -1,6 +1,6 @@ { "required": true, - "package": "com.example.playertime.mixins", + "package": "org.branulf.playertime.mixins", "compatibilityLevel": "JAVA_21", "injectors": { "defaultRequire": 1 diff --git a/versions/1.21.4/gradle.properties b/versions/1.21.4/gradle.properties new file mode 100644 index 0000000..a0ee0d6 --- /dev/null +++ b/versions/1.21.4/gradle.properties @@ -0,0 +1,8 @@ +minecraft_version=1.21.4 +yarn_mappings=1.21.4+build.8 + +minecraft_dependency=1.21.4 + +game_versions=1.21.4 + +fabric_api_version=0.119.2+1.21.4 diff --git a/versions/1.21.5/gradle.properties b/versions/1.21.5/gradle.properties new file mode 100644 index 0000000..d086409 --- /dev/null +++ b/versions/1.21.5/gradle.properties @@ -0,0 +1,8 @@ +minecraft_version=1.21.5 +yarn_mappings=1.21.5+build.1 + +minecraft_dependency=1.21.5 + +game_versions=1.21.5 + +fabric_api_version=0.119.5+1.21.5 diff --git a/versions/1.21.6/gradle.properties b/versions/1.21.6/gradle.properties new file mode 100644 index 0000000..35db5bb --- /dev/null +++ b/versions/1.21.6/gradle.properties @@ -0,0 +1,8 @@ +minecraft_version=1.21.6 +yarn_mappings=1.21.6+build.1 + +minecraft_dependency=1.21.6 + +game_versions=1.21.6 + +fabric_api_version=0.127.0+1.21.6 diff --git a/versions/1.21.7/gradle.properties b/versions/1.21.7/gradle.properties new file mode 100644 index 0000000..cbb511d --- /dev/null +++ b/versions/1.21.7/gradle.properties @@ -0,0 +1,8 @@ +minecraft_version=1.21.7 +yarn_mappings=1.21.7+build.7 + +minecraft_dependency=1.21.7 + +game_versions=1.21.7 + +fabric_api_version=0.128.1+1.21.7 \ No newline at end of file diff --git a/versions/mainProject b/versions/mainProject new file mode 100644 index 0000000..3d8ac63 --- /dev/null +++ b/versions/mainProject @@ -0,0 +1 @@ +1.21.4 \ No newline at end of file diff --git a/versions/mapping_12105_12104.txt b/versions/mapping_12105_12104.txt new file mode 100644 index 0000000..e69de29 diff --git a/versions/mapping_12106_12105.txt b/versions/mapping_12106_12105.txt new file mode 100644 index 0000000..e69de29 diff --git a/versions/mapping_12107_12106.txt b/versions/mapping_12107_12106.txt new file mode 100644 index 0000000..e69de29