InvSync开发者文档

March 16, 2025 / Administrator / 113阅读 / 0评论 / 分类:

接入API方法

方式1 不需要读取离线玩家的同步

同步需要实现一个接口 com.xbaimiao.invsync.api.addon.InvSyncAddon

然后调用 com.xbaimiao.invsync.api.addon.InvSyncAddonManager#register方法注册即可

以下代码为这个接口的源代码

public interface InvSyncAddon {

    /**
     * 服务器给玩家同步数据的时候调用
     *
     * @param event 同步的事件 里面包含玩家和数据 这时可以往里面获取自己的数据
     */
    void onSync(InvSyncPluginDataSyncEvent event);

    @Deprecated()
    default void onSave(InvSyncPluginDataSaveEvent event) {

    }

    /**
     * 服务器保存数据的时候调用
     *
     * @param event  保存的事件 里面包含玩家和数据 这时可以往里面存入自己的数据
     * @param reason 保存原因
     */
    default void onSave(InvSyncPluginDataSaveEvent event, SaveReason reason) {

    }

}

方式2 需要读取离线玩家数据的

需要继承一个抽象类 com.xbaimiao.invsync.bukkit.api.addon.OfflineInvSyncAddon

然后调用 com.xbaimiao.invsync.api.addon.InvSyncAddonManager#register方法注册即可

下面是这个抽象类的源代码

public abstract class OfflineInvSyncAddon implements InvSyncAddon {

    @Nullable
    public PluginDataSync readOfflineData(@NotNull UUID uuid) {
        if (Bukkit.getPlayer(uuid) != null) throw new RuntimeException("玩家在线");

        PlayerData playerData = InvSyncAPI.getAPI().readFromRedisOrMysql(uuid);
        if (playerData == null) return null;
        return new PluginDataSync(playerData.getPluginData());
    }

    /**
     * 读取离线玩家的数据
     *
     * @param uuid 玩家uuid
     * @param key  数据key
     */
    public byte @Nullable [] readOfflineData(@NotNull UUID uuid, @NotNull String key) {
        if (Bukkit.getPlayer(uuid) != null) throw new RuntimeException("玩家在线");

        PlayerData playerData = InvSyncAPI.getAPI().readFromRedisOrMysql(uuid);
        if (playerData == null) return null;
        PluginDataSync pluginDataSync = new PluginDataSync(playerData.getPluginData());
        return pluginDataSync.read(key);
    }

    /**
     * 写入离线玩家的数据
     *
     * @param uuid  玩家uuid
     * @param key   数据key
     * @param bytes 数据
     */
    public void writeOfflineData(@NotNull UUID uuid, @NotNull String key, byte @NotNull [] bytes) {
        if (Bukkit.getPlayer(uuid) != null) throw new RuntimeException("玩家在线");

        PlayerData playerData = InvSyncAPI.getAPI().readFromRedisOrMysql(uuid);
        if (playerData == null) return;

        PluginDataSync pluginDataSync = new PluginDataSync(playerData.getPluginData());
        pluginDataSync.put(key, bytes);
        playerData.pluginData = pluginDataSync.serializer();

        InvSync.getPlugin().getRedisManager().setPlayerData(playerData);
        InvSync.getPlugin().getMysqlManager().savePlayerData(playerData);
    }

    /**
     * 获取玩家uuid
     *
     * @param name 玩家名字
     * @return 玩家的UUID
     */
    public UUID getUUID(String name) {
        return UtilKt.toPlayerUUID(name);
    }

}

示范例子:同步玩家飞行状态

public class SyncFlyAddon implements InvSyncAddon {

    private String flag = "fly";

    @Override
    public void onSync(InvSyncPluginDataSyncEvent event) {
        Player player = event.getPlayer();
        byte[] data = event.readData(flag);
        if (data == null) return;
        try {
            DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
            player.setAllowFlight(dis.readBoolean());
            player.setFlying(dis.readBoolean());
            dis.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void onSave(InvSyncPluginDataSaveEvent event, SaveReason reason) {
        Player player = event.getPlayer();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        try {
            dos.writeBoolean(player.getAllowFlight());
            dos.writeBoolean(player.isFlying());
            event.putData(flag, baos.toByteArray());
            dos.close();
            baos.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

kotlin进阶玩法

委托基本属性

第一步 需要放置一个源文件在你的项目里,因为InvSync的kotlin为relocate过的,直接调用不可取 所以必须要把我发的源文件放置在你的项目

import com.xbaimiao.invsync.api.delegate.DelegatePropertyAddon
import org.bukkit.entity.Player
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

interface DelegateProperty<K, V> : ReadWriteProperty<K, V?> {

    fun defaultsTo(defaultValue: (k: K) -> V): ReadWriteProperty<K, V> {
        val parent = this
        return object : ReadWriteProperty<K, V> {
            override fun getValue(thisRef: K, property: KProperty<*>): V {
                return parent.getValue(thisRef, property) ?: defaultValue(thisRef).also {
                    setValue(thisRef, property, it)
                }
            }

            override fun setValue(thisRef: K, property: KProperty<*>, value: V) {
                parent.setValue(thisRef, property, value)
            }
        }
    }

}

fun <V> delegateProperty(
    id: String,
    serializableProperty: SerializableProperty<V>
): DelegateProperty<Player, V> {
    return object : DelegateProperty<Player, V> {

        override fun getValue(thisRef: Player, property: KProperty<*>): V? {
            val dataMap = DelegatePropertyAddon.playerDataMap(thisRef)
            val value = dataMap.get(id)
            return if (value == null) {
                null
            } else {
                serializableProperty.deserialize(value)
            }
        }

        override fun setValue(thisRef: Player, property: KProperty<*>, value: V?) {
            val dataMap = DelegatePropertyAddon.playerDataMap(thisRef)
            dataMap.put(id, value?.let { serializableProperty.serialize(it) })
        }

    }
}

interface SerializableProperty<V> {
    fun serialize(value: V): String
    fun deserialize(value: String): V

    companion object {

        val LONG = object : SerializableProperty<Long> {
            override fun serialize(value: Long): String {
                return value.toString()
            }

            override fun deserialize(value: String): Long {
                return value.toLong()
            }
        }

        val STRING = object : SerializableProperty<String> {
            override fun serialize(value: String): String {
                return value
            }

            override fun deserialize(value: String): String {
                return value
            }
        }

        val BOOLEAN = object : SerializableProperty<Boolean> {
            override fun serialize(value: Boolean): String {
                return value.toString()
            }

            override fun deserialize(value: String): Boolean {
                return value.toBoolean()
            }
        }

        val DOUBLE = object : SerializableProperty<Double> {
            override fun serialize(value: Double): String {
                return value.toString()
            }

            override fun deserialize(value: String): Double {
                return value.toDouble()
            }
        }

    }
}

第二步 定义一个自定义的属性 示例中采用 Boolean作为测试

var Player.isSb by delegateProperty<Boolean>("sb", SerializableProperty.BOOLEAN)
    .defaultsTo { false }

第三步 就可以直接操作这个自定义的属性了

  • 此属性会安全的全服同步,前提是玩家在线时进行操作的


fun main(player: Player) {
    player.isSb = true
}

委托自定义类

自己看看源码吧

var Player.isSb by delegateProperty<Boolean>("sb", SerializableProperty.BOOLEAN)
    .defaultsTo { false }

var Player.data by delegateProperty<DIYClass>("data", DIYClassSerializer)

object DIYClassSerializer : SerializableProperty<DIYClass> {
    private val gson = Gson()
    override fun serialize(value: DIYClass): String {
        return gson.toJson(value)
    }

    override fun deserialize(value: String): DIYClass {
        return gson.fromJson(value, DIYClass::class.java)
    }

}

class DIYClass(
    val name: String,
    val age: Int
)

fun main(player: Player) {
    player.isSb = true

    val data = player.data
    if (data == null) {
        player.data = DIYClass("测试", 0)
    } else {
        println(data.name)
    }
}

#minecraft(3)

文章作者:Administrator

文章链接:https://halo.xbaimiao.com/archives/invsynckai-fa-zhe-wen-dang

版权声明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0 许可协议,转载请注明出处!


评论