diff --git a/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/handler/ModuleHandler.kt b/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/handler/ModuleHandler.kt index a6bbeda..2d568f9 100644 --- a/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/handler/ModuleHandler.kt +++ b/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/handler/ModuleHandler.kt @@ -6,6 +6,7 @@ import com.aiyostudio.esync.internal.api.event.ModuleRegistryEvent import com.aiyostudio.esync.internal.module.impl.EnderChestModuleImpl import com.aiyostudio.esync.internal.module.impl.InventoryModuleImpl import com.aiyostudio.esync.internal.module.impl.PlayerStatusModuleImpl +import com.aiyostudio.esync.internal.module.impl.StatisticsModuleImpl import org.bukkit.Bukkit import org.bukkit.configuration.ConfigurationSection @@ -18,6 +19,7 @@ object ModuleHandler { "inventory" -> return InventoryModuleImpl(option) "player-status" -> return PlayerStatusModuleImpl(option) "ender-chest" -> return EnderChestModuleImpl(option) + "statistics" -> return StatisticsModuleImpl(option) } return null } diff --git a/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/module/entity/StatisticsEntity.kt b/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/module/entity/StatisticsEntity.kt new file mode 100644 index 0000000..cb68695 --- /dev/null +++ b/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/module/entity/StatisticsEntity.kt @@ -0,0 +1,23 @@ +package com.aiyostudio.esync.internal.module.entity + +import com.aiyostudio.esync.common.module.IEntity +import com.aiyostudio.esync.internal.plugin.EfficientSyncBukkit +import org.bukkit.Statistic +import org.bukkit.entity.Player +import java.util.logging.Level + +class StatisticsEntity : IEntity { + val statistics = mutableMapOf() + + override fun apply(player: Any): Boolean { + try { + if (player !is Player) return false + statistics.forEach { (k, v) -> player.setStatistic(k, v) } + } catch (e: Exception) { + EfficientSyncBukkit.instance.logger.log(Level.WARNING, e) { + "Failed to apply 'statistics' data for ${(player as Player).uniqueId}" + } + } + return false + } +} \ No newline at end of file diff --git a/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/module/impl/StatisticsModuleImpl.kt b/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/module/impl/StatisticsModuleImpl.kt new file mode 100644 index 0000000..b3dbd3e --- /dev/null +++ b/bukkit/src/main/kotlin/com/aiyostudio/esync/internal/module/impl/StatisticsModuleImpl.kt @@ -0,0 +1,74 @@ +package com.aiyostudio.esync.internal.module.impl + +import com.aiyostudio.esync.common.module.AbstractModule +import com.aiyostudio.esync.internal.module.entity.StatisticsEntity +import io.netty.buffer.Unpooled +import org.bukkit.Bukkit +import org.bukkit.Statistic +import org.bukkit.configuration.ConfigurationSection +import java.util.* + +class StatisticsModuleImpl( + private val option: ConfigurationSection +) : AbstractModule() { + override val uniqueKey: String = "statistics" + + override fun firstLoad(uuid: UUID, bytea: ByteArray?): Boolean { + if (bytea == null || bytea.isEmpty()) { + this.caches[uuid] = StatisticsEntity() + } else { + this.caches[uuid] = wrapper(bytea) + } + return true + } + + override fun attemptLoad(uuid: UUID, bytea: ByteArray?): Boolean { + return firstLoad(uuid, bytea) + } + + override fun preLoad(uuid: UUID) { + if (option.getBoolean("always-clear")) { + val player = Bukkit.getPlayer(uuid) + player?.takeIf { it.isOnline }?.run { + Statistic.entries.forEach { entry -> setStatistic(entry, 0) } + } + } + } + + override fun apply(uuid: UUID): Boolean { + val player = Bukkit.getPlayer(uuid) + return this.find(uuid)?.apply(player) ?: false + } + + override fun toByteArray(uuid: UUID): ByteArray? { + val player = Bukkit.getPlayer(uuid) + return player?.let { + val buf = Unpooled.buffer() + val entries = Statistic.entries + buf.writeInt(entries.size) + entries.forEach { k -> + val bytes = k.name.toByteArray(Charsets.UTF_8) + buf.writeInt(bytes.size) + buf.writeBytes(bytes) + buf.writeInt(player.getStatistic(k)) + } + buf.array() + } + } + + override fun wrapper(bytea: ByteArray): StatisticsEntity { + val result = StatisticsEntity() + val buf = Unpooled.wrappedBuffer(bytea) + val size = buf.readInt() + for (i in 0 until size) { + val length = buf.readInt() + val bytes = ByteArray(length) + buf.readBytes(bytes) + val str = String(bytes, Charsets.UTF_8) + val statistic = Statistic.valueOf(str) + val value = buf.readInt() + result.statistics[statistic] = value + } + return result + } +} \ No newline at end of file diff --git a/bukkit/src/main/resources/config.yml b/bukkit/src/main/resources/config.yml index 82da7e2..1ac2288 100644 --- a/bukkit/src/main/resources/config.yml +++ b/bukkit/src/main/resources/config.yml @@ -63,15 +63,16 @@ modules: # Player status, including: health, buffs player-status: enable: true - # 每次登录都清空玩家药水效果 - # Clear potion every time always-clear: true # 末影箱 # Ender chest ender-chest: enable: true - # 每次登录都清空玩家末影箱 - # Clear ender-chest every time + always-clear: true + # 统计数据 + # Statistics + statistics: + enable: true always-clear: true # 至少加载了哪些模块才允许行动(移动, 执行命令) @@ -79,4 +80,5 @@ modules: depends: - "inventory" - "player-status" - - "ender-chest" \ No newline at end of file + - "ender-chest" + - "statistics" \ No newline at end of file