
自定义玩家数据
一个适用于Minecraft服务器或模组开发者的实用模组框架。
自定义玩家数据
Fabric Framework 1.20.6,用于管理持久化且已同步的玩家数据。
此模组允许您定义附加到每个玩家的自定义变量,这些变量会保存在 Minecraft 原生的 player.dat 文件中,并在服务器和客户端之间自动同步。
功能特性
- JSON 架构:在
player_data_schema.json文件中定义您的变量,该文件会在地图文件夹中自动生成。 - 原生持久化:数据通过 Mixin 直接存储在
player.dat中 — 即使崩溃也不会丢失数据。 - 自动同步:所有变量在连接时以及每次更改时都会发送到客户端(非常适合 HUD 显示)。
- 开发者 API:其他模组可将其作为依赖项,以编程方式注入和操作变量。
- 自定义类型:创建您自己的复杂数据类型(例如
Power、Skill、Quest…)。 - 管理员命令:
/playerdata get和/playerdata set供管理员使用。 - 验证:支持
int类型的最小/最大值、空值检查、运行时类型验证。
对于服务器管理员
安装
- 将
.jar文件放入 Fabric 1.20.6 服务器的mods/文件夹中。 - 首次启动服务器 —
player_data_schema.json文件将在您的世界文件夹中生成(位于level.dat旁边)。 - 根据需要修改 JSON,然后重新启动。
JSON 架构格式
{
"note": {
"type": "int",
"defaultValue": 0,
"maxValue": 5,
"minValue": 0,
"null": false
},
"hudColor": {
"type": "string",
"defaultValue": "light_blue",
"null": false
},
"powers": {
"type": "Power",
"array": true,
"defaultValue": null,
"null": true
}
}
| 参数 | 描述 | 是否必填 |
|---|---|---|
type |
int、string、boolean 或已注册的自定义类型 |
是 |
defaultValue |
新玩家的默认值 | 否 |
maxValue |
最大值(仅限 int 类型) |
否 |
minValue |
最小值(仅限 int 类型) |
否 |
null |
是否允许 null(默认为 false) |
否 |
array |
该变量是否为数组(默认为 false) |
否 |
重要:如果某个变量设置了
"null": false且没有defaultValue,启动时将会记录错误。
命令
| 命令 | 描述 | 权限 |
|---|---|---|
/playerdata get <变量> <玩家> |
显示当前值 | 管理员等级 2+ |
/playerdata set <变量> <玩家> <值> |
修改值(仅限基本类型) | 管理员等级 2+ |
示例:
/playerdata get note Steve
/playerdata set hudColor Steve red
/playerdata set note Steve 3
开发者指南 — 将自定义玩家数据用作 API
1. 添加依赖项
在您的 build.gradle 文件中,将 JAR 添加为本地依赖项(如果已发布,也可通过 Maven 仓库添加):
dependencies {
// 添加这一行
modImplementation files("libs/custom-player-data-1.0.0.jar")
}
在您的 fabric.mod.json 文件中,添加以下依赖项:
{
"depends": {
"custom-player-data": ">=1.0.0"
}
}
2. 创建自定义类型(可选)
如果您需要存储复杂数据,请实现 ICustomDataType:
package com.myMod.data;
import fr.hdi.api.ICustomDataType;
import net.minecraft.nbt.NbtCompound;
public class Skill implements ICustomDataType {
private String name = "";
private int xp = 0;
private boolean unlocked = false;
public Skill() {}
public Skill(String name, int xp, boolean unlocked) {
this.name = name;
this.xp = xp;
this.unlocked = unlocked;
}
@Override
public void writeNbt(NbtCompound nbt) {
nbt.putString("name", name);
nbt.putInt("xp", xp);
nbt.putBoolean("unlocked", unlocked);
}
@Override
public void readNbt(NbtCompound nbt) {
this.name = nbt.getString("name");
this.xp = nbt.getInt("xp");
this.unlocked = nbt.getBoolean("unlocked");
}
public String getName() { return name; }
public int getXp() { return xp; }
public boolean isUnlocked() { return unlocked; }
public void setXp(int xp) { this.xp = xp; }
public void setUnlocked(boolean unlocked) { this.unlocked = unlocked; }
@Override
public String toString() {
return "Skill{" + name + ", xp=" + xp + ", unlocked=" + unlocked + "}";
}
}
3. 注册您的类型和变量
在您的模组的 onInitialize() 方法中:
package com.myMod;
import com.myMod.data.Skill;
import fr.hdi.api.TypeRegistry;
import fr.hdi.schema.SchemaManager;
import fr.hdi.schema.VariableDefinition;
import net.fabricmc.api.ModInitializer;
public class myMod implements ModInitializer {
@Override
public void onInitialize() {
// 1. 注册自定义类型
TypeRegistry.register("Skill", Skill::new);
// 2. 注册所有可能的变量架构
SchemaManager.registerVariable(
VariableDefinition.builder("level", "int")
.defaultValue(1)
.minValue(1)
.maxValue(100)
.build()
);
SchemaManager.registerVariable(
VariableDefinition.builder("clan", "string")
.defaultValue("none")
.build()
);
SchemaManager.registerVariable(
VariableDefinition.builder("hasCompletedTutorial", "boolean")
.defaultValue(false)
.build()
);
SchemaManager.registerVariable(
VariableDefinition.builder("skills", "Skill")
.array(true)
.nullable(true)
.defaultNull()
.build()
);
}
}
4. 读取和写入玩家数据
使用 PlayerDataStore 从服务器代码的任何位置访问数据:
import fr.hdi.api.PlayerDataStore;
import net.minecraft.server.network.ServerPlayerEntity;
// 读取基本类型
int level = PlayerDataStore.getInt(player, "level");
String clan = PlayerDataStore.getString(player, "clan");
boolean done = PlayerDataStore.getBoolean(player, "hasCompletedTutorial");
// 使用默认值读取
String color = PlayerDataStore.getString(player, "color", "red");
// 读取自定义类型
Skill skill = PlayerDataStore.getCustom(player, "mainSkill", Skill.class);
// 读取列表
List<Skill> skills = PlayerDataStore.getList(player, "skills", Skill.class);
// 通用读取
Object raw = PlayerDataStore.getData(player, "level");
// 设置基本变量
PlayerDataStore.setData(player, "level", 42);
PlayerDataStore.setData(player, "clan", "Dragons");
PlayerDataStore.setData(player, "hasCompletedTutorial", true);
// 写入自定义类型数组
Skill newSkill = new Skill("Archery", 150, true);
List<Skill> skillList = new ArrayList<>();
skillList.add(newSkill);
PlayerDataStore.setData(player, "skills", skillList);
5. 在客户端读取数据
数据会自动同步到客户端。使用 CustomPlayerDataClient:
import fr.hdi.CustomPlayerDataClient;
int level = CustomPlayerDataClient.getClientInt("level");
String color = CustomPlayerDataClient.getClientString("hudColor");
boolean done = CustomPlayerDataClient.getClientBoolean("hasCompletedTutorial");
正在加载版本记录…
正在加载评论…
评论在新手盒子客户端中发表,这里同步展示。