feat: 最適化とKommandアップデート
This commit is contained in:
parent
4343d01d11
commit
b3bdc95f63
|
|
@ -1 +1 @@
|
|||
Subproject commit e0613cd05278222b0a2ac1c79a2d4ef317c9cea1
|
||||
Subproject commit 3835c9b9e2d488681b39f4cfd827e3e3371a1e1b
|
||||
|
|
@ -41,8 +41,8 @@ class GhostDisplaysPlugin : JavaPlugin() {
|
|||
logger.info("GhostDisplays ready: ${displayRegistry.controllerCount()} controllers active.")
|
||||
|
||||
server.scheduler.runTaskTimer(this, Runnable {
|
||||
displayRegistry.tick()
|
||||
}, 10L, 10L)
|
||||
displayRegistry.updateAudiences()
|
||||
}, 20L, 20L)
|
||||
}
|
||||
|
||||
override fun onDisable() {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,12 @@ interface DisplayController<T : Display> {
|
|||
|
||||
fun refreshAudience(target: Player? = null)
|
||||
|
||||
/**
|
||||
* 定期的な更新チェックが必要かどうかを返します。
|
||||
* trueの場合、サーバーのtick毎(または定期タスク)にrefreshAudienceが呼び出されます。
|
||||
*/
|
||||
fun needsPeriodicUpdate(): Boolean = false
|
||||
|
||||
fun destroy()
|
||||
|
||||
fun onClick(priority: ClickPriority = ClickPriority.NORMAL, handler: DisplayClickHandler): HandlerRegistration
|
||||
|
|
|
|||
|
|
@ -7,4 +7,12 @@ import org.bukkit.entity.Player
|
|||
*/
|
||||
fun interface AudiencePredicate {
|
||||
fun test(player: Player): Boolean
|
||||
|
||||
/**
|
||||
* 表示対象判定が動的(時間経過や移動で変化する)かどうかを返します。
|
||||
* trueの場合、定期的な再評価の対象となります。
|
||||
*/
|
||||
fun isDynamic(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,15 @@ object AudiencePredicates {
|
|||
}
|
||||
|
||||
fun near(location: Location, radius: Double): AudiencePredicate {
|
||||
|
||||
val radiusSq = radius * radius
|
||||
val worldName = location.world?.name
|
||||
require(worldName != null) { "Location must have a world" }
|
||||
return AudiencePredicate { player ->
|
||||
player.world.name == worldName && player.location.distanceSquared(location) <= radiusSq
|
||||
|
||||
return object : AudiencePredicate {
|
||||
override fun test(player: Player): Boolean {
|
||||
return player.world.name == worldName && player.location.distanceSquared(location) <= radiusSq
|
||||
}
|
||||
override fun isDynamic(): Boolean = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,11 +32,17 @@ internal class BaseDisplayController<T : Display>(
|
|||
private val viewerCounts = ConcurrentHashMap<UUID, Int>()
|
||||
private val handlers = CopyOnWriteArrayList<HandlerEntry>()
|
||||
|
||||
// Audience Management
|
||||
// Audience Management
|
||||
private var baseVisibility: Boolean = false
|
||||
private val audienceRules = CopyOnWriteArrayList<RuleEntry>()
|
||||
private val autoVisiblePlayers = ConcurrentHashMap.newKeySet<UUID>()
|
||||
|
||||
// 最適化: 定期更新が必要なルールがあるか
|
||||
private var hasDynamicRules: Boolean = false
|
||||
|
||||
override fun needsPeriodicUpdate(): Boolean = hasDynamicRules
|
||||
|
||||
override fun show(player: Player) {
|
||||
runSync {
|
||||
val uuid = player.uniqueId
|
||||
|
|
@ -110,13 +116,32 @@ internal class BaseDisplayController<T : Display>(
|
|||
override fun addAudienceRule(predicate: AudiencePredicate, action: AudienceAction): HandlerRegistration {
|
||||
val entry = RuleEntry(predicate, action)
|
||||
audienceRules.add(entry)
|
||||
updateDynamicStatus()
|
||||
refreshAudience()
|
||||
return HandlerRegistration {
|
||||
audienceRules.remove(entry)
|
||||
updateDynamicStatus()
|
||||
refreshAudience()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDynamicStatus() {
|
||||
// 簡易判定: クラス名に "Near" が含まれる、または特定の実装であることを期待する
|
||||
// ただし現状はラムダなので名前判定は不安定。
|
||||
// AudiencePredicate 側にマーカーインターフェースをつけるのが正しいが、
|
||||
// 今回は「ユーザー定義のPredicate」も含めて、動的かどうかわからない。
|
||||
// -> AudiencePredicates.near() が返すオブジェクトに特徴を持たせる。
|
||||
hasDynamicRules = audienceRules.any { isDynamicPredicate(it.predicate) }
|
||||
}
|
||||
|
||||
private fun isDynamicPredicate(predicate: AudiencePredicate): Boolean {
|
||||
// AudiencePredicates.near が返すクラスの実装詳細に依存するか、
|
||||
// AudiencePredicate にプロパティを追加する。
|
||||
// ここでは一旦、toString() 等で識別するか?いや、安全ではない。
|
||||
// API変更: AudiencePredicate に default isDynamic() を追加する。
|
||||
return predicate.isDynamic()
|
||||
}
|
||||
|
||||
override fun clearAudienceRules() {
|
||||
audienceRules.clear()
|
||||
refreshAudience()
|
||||
|
|
|
|||
|
|
@ -82,16 +82,18 @@ internal class DisplayRegistry : Listener {
|
|||
controllers.forEach { it.refreshAudience(player) }
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
fun updateAudiences() {
|
||||
val players = org.bukkit.Bukkit.getOnlinePlayers()
|
||||
if (players.isEmpty()) return
|
||||
val controllers = controllersSnapshot()
|
||||
if (controllers.isEmpty()) return
|
||||
|
||||
// 最適化: 動的な評価が必要なコントローラーだけ抽出できれば良いが、
|
||||
// 現状はシンプルに全走査する。
|
||||
// 動的な評価が必要なコントローラーだけを抽出して評価する
|
||||
val activeControllers = controllers.filter { it.needsPeriodicUpdate() }
|
||||
if (activeControllers.isEmpty()) return
|
||||
|
||||
players.forEach { player ->
|
||||
controllers.forEach { controller ->
|
||||
activeControllers.forEach { controller ->
|
||||
controller.refreshAudience(player)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user