API v2
警告
API v2 已不再受支持且不与 HuskSync v3.0 兼容。见数据快照 API 获取 v3 API 的相关信息。 🚨
HuskSync 提供了一个 API 用于获取和返回 UserData
对象;这是一个用户同步数据的快照。 该页面默认你已阅读 API 介绍章节,并将 HuskSync(v2.x)的 API 导入了你的仓库。
🚨 HuskSync API v2 仅针对 v2.0 - v2.2.8 的 HuskSync。它不与 v3.0+ 的 HuskSync 兼容。HuskSync v3 的等价 API 可以在数据快照 API找到。
目录
1. 通过 UUID 获取玩家
- HuskSync 有一个
User
对象,代表着特定玩家在数据库中保存的数据。你可以通过方法HuskSyncAPI#getUser(uuid)
请求玩家数据。 - 若你有一个在线的
org.bukkit.Player
对象,你可以使用方法BukkitPlayer#adapt(player)
来获取一个OnlineUser
对象(继承User
),以此代表一个已登入的玩家。
Java
public class HuskSyncAPIHook {
private final HuskSyncAPI huskSyncAPI;
public HuskSyncAPIHook() {
this.huskSyncAPI = HuskSyncAPI.getInstance();
}
public void logUserName(UUID uuid) {
// getUser() returns a CompletableFuture supplying an Optional<User>
huskSyncAPI.getUser(uuid).thenAccept(optionalUser -> {
// Check if we found a user by that UUID either online or on the database
if (optionalUser.isEmpty()) {
// If we didn't, we'll log that they don't exist
System.out.println("User does not exist!");
return;
}
// The User object has two fields; uuid and username.
System.out.println("User name is: " + optionalUser.get().username);
});
}
}
2. 获取玩家数据
- 通过一个
User
对象,我们现在可以调用方法HuskSyncAPI#getUserData()
来获取他们最新的数据。 UserData
对象包含八个数据“模块”,每个模块都包含特定的信息。- UserData 对象不会包含全部的数据“模块”;在被插件保存的 UserData 中所包含的模块内容由配置文本决定。
- 你可以单独或获取每一个模块的内容,返回值会包装为一个 Optional(若未指定则返回为空),见下:
UserData#getStatus();
- 玩家的基本属性(生命值、饱食度、饱和度、经验值和游戏模式等)UserData#getInventory();
- 玩家的背包内容。包含一个 base64 序列化的ItemStack
数组。UserData#getEnderChest();
- 玩家的末影箱内容。包含一个 base64 序列化的ItemStack
数组。UserData#getPotionEffects();
- 玩家当前的药水效果。包含一个 base64 序列化的PotionEffect
数组。UserData#getAdvancements();
- 返回玩家当前获取的进度和成就UserData#getStatistics();
- 玩家的四大类统计数据(未分类、物品、方块和实体)UserData#getLocation();
- 玩家的位置数据,用于启用了同步位置数据的服务器UserData#getPersistentDataContainer();
- 玩家的持久化数据容器,包含了一个有键值的映射表
Java
public class HuskSyncAPIHook {
// ... //
public void logUserData(UUID uuid) {
huskSyncAPI.getUser(uuid).thenAccept(optionalUser -> {
// Optional#isPresent() is the opposite of #isEmpty()
if (optionalUser.isPresent()) {
logHealth(optionalUser.get());
}
});
}
private void logHealth(User user) {
// A user might not have data, if it's deleted by an admin or they're brand new
huskSyncAPI.getUserData(user).thenAccept(optionalUserData -> {
if (optionalUserData.isPresent()) {
// Get the StatusData from the UserData object
Optional<StatusData> statusData = optionalUserData.get().getStatus();
// Print the health from the fields, if the user has a status object
statusData.ifPresent(status -> {
System.out.println("%s's health: %d/%d", user.username, status.health, status.maxHealth);
});
}
});
}
}
3. 获取玩家的背包内容
- API 提供了反序列化
ItemData
的方法来处理 base64 序列化的背包和末影箱ItemStack
数组,将它们转化为实际的ItemStack
数组数据。 - 若要反序列化背包物品,使用方法
HuskSyncAPI#deserializeInventory(serializedItems)
。 - 若要翻序列化末影箱物品,使用方法
HuskSyncAPI#deserializeItemStackArray(serializedItems)
。 - 相似地,
HuskSyncAPI#getPlayerInventory(user)
和HuskSyncAPI#getPlayerEnderChest(user)
方法可以更优雅地达到目的。请注意如果最后的 UserData 不包含 ItemData(译者注:原文似乎笔误,写成了 UserData),那么这里返回的 ItemData 将会是对应的空 ItemStack 数组。 - 序列化和反序列化对药水效果同样可用。
Java
public class HuskSyncAPIHook {
// ... //
private void printInventoryItems(User user) {
huskSyncAPI.getUserData(user).thenAccept(optionalUserData -> {
if (optionalUserData.isPresent()) {
// Get the ItemData and make sure it's present
Optional<ItemData> inventoryDataOptional = optionalUserData.get().getInventory();
if (inventoryDataOptional.isEmpty) {
return;
}
ItemData inventoryData = inventoryDataOptional.get();
// Get the ItemStack[] array as a BukkitInventoryMap.
// This returns a future, but we're using #join() to block the thread until it's done
BukkitInventoryMap inventory = huskSyncAPI.deserializeInventory(inventoryData.serializedItems).join();
// A BukkitInventoryMap is simply a wrapper for an ItemStack array.
// It provides a few handy methods for getting the player's armor, their offhand item, etc.
// To get the ItemStack array from it, just call BukkitInventoryMap#getContents();
for (ItemStack item : inventory.getContents()) {
// Print out the item material types of every item in the player's inventory
System.out.println(item.getType().name());
}
}
});
}
}
HuskSyncAPI#getPlayerInventory()
Java
private void printInventoryItems(User user) {
huskSyncAPI.getPlayerInventory(user).thenAccept(inventory -> {
if (inventory.isPresent()) {
for (ItemStack item : inventory.get().getContents()) {
System.out.println(item.getType().name());
}
}
});
}
HuskSyncAPI#getPlayerInventory()
Java
private void printEnderChestItems(User user) {
huskSyncAPI.getPlayerEnderChest(user).thenAccept(enderChest -> {
if (enderChest.isPresent()) {
for (ItemStack item : enderChest.get()) {
System.out.println(item.getType().name());
}
}
});
}
4. 更新玩家数据
- 你可以使用
HuskSyncAPI#setUserData(user, userData)
来将一个玩家的数据修改并提交至数据库。 - 若你需要在每次更新后修改玩家数据,你可能需要监听 HuskSync 所提供的事件。
- 你可以使用
HuskSyncAPI#serializeItemStackArray(itemStack[])
来将任何 ItemStack 序列化为 base64 值。 - 相似地,你可以使用
HuskSyncAPI#setInventoryData(user, bukkitInventoryMap)
来设置玩家背包内容,或使用HuskSyncAPI#setEnderChestData(user, itemStack[])
来设置玩家的末影箱内容。 - 更新 UserData 将会完全覆盖玩家当前的“活跃”数据。HuskSync 设计之初就不会追踪玩家的“活跃”数据,仅会在保存时产生数据的“快照”。换句话说,获取并更新用户数据有可能造成回档。
Java
public class HuskSyncAPIHook {
// Set a user's health to 20
private void updateUserHealth(User user) {
huskSyncAPI.getUserData(user).thenAccept(optionalUserData -> {
if (optionalUserData.isPresent()) {
UserData data = optionalUserData.get();
Optional<StatusData> statusDataOptional = data.getStatus();
StatusData statusData = statusDataOptional.get();
statusData.health = 20;
// This returns a CompletableFuture<Void> that will invoke #thenRun() when it has completed
huskSyncAPI.setUserData(user, data).thenRun(() -> {
System.out.println("Healed " + user.username + "!");
});
}
});
}
}