even more optimize synchronizeToPlayers

This commit is contained in:
DBotThePony 2022-09-30 00:04:16 +07:00
parent 177a380bf3
commit 8892487394
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -30,7 +30,13 @@ import java.lang.ref.WeakReference
import java.util.LinkedList
import java.util.WeakHashMap
private data class Subscribers(val blockEntities: LinkedList<WeakReference<BlockEntity>> = LinkedList(), val players: LinkedList<ServerPlayer> = LinkedList(), val level: WeakReference<Level>, val chunkPos: Long) {
private data class Subscribers(
val blockEntities: LinkedList<WeakReference<BlockEntity>> = LinkedList(),
val players: LinkedList<ServerPlayer> = LinkedList(),
val level: WeakReference<Level>,
val chunkPos: Long,
var changeset: Int = 0
) {
fun cleanUpBlocks() {
val listIterator = blockEntities.listIterator()
@ -49,6 +55,7 @@ private data class Subscribers(val blockEntities: LinkedList<WeakReference<Block
}
blockEntities.add(WeakReference(blockEntity))
changeset++
}
fun unsubscribe(blockEntity: BlockEntity): Boolean {
@ -57,6 +64,7 @@ private data class Subscribers(val blockEntities: LinkedList<WeakReference<Block
for (value in listIterator) {
if (value.get() === blockEntity) {
listIterator.remove()
changeset++
break
}
}
@ -106,17 +114,20 @@ abstract class SynchronizedBlockEntity(p_155228_: BlockEntityType<*>, p_155229_:
playerMap.get(level)?.remove(subCache.chunkPos)
}
}
lastSubscriptionChangeset = -1
}
private fun subscribe(): LinkedList<ServerPlayer> {
private fun subscribe(): Subscribers {
unsubscribe()
val subs = playerMap.computeIfAbsent(level) { Long2ObjectAVLTreeMap() }.computeIfAbsent(ChunkPos(blockPos).toLong(), Long2ObjectFunction { Subscribers(level = WeakReference(level), chunkPos = ChunkPos(blockPos).toLong()) })
subs.subscribe(this)
_subCache = subs
return subs.players
return subs
}
private val playerSubscribers get() = _subCache?.players ?: subscribe()
private val subscription get() = _subCache ?: subscribe()
private var lastSubscriptionChangeset = -1
fun synchronizeToPlayers() {
if (synchronizationRadius <= 0.0 || synchronizer.isEmpty) {
@ -127,10 +138,14 @@ abstract class SynchronizedBlockEntity(p_155228_: BlockEntityType<*>, p_155229_:
synchronizer.observe()
if (playerSubscribers.isEmpty()) {
val subscription = subscription
if (subscription.players.isEmpty() || lastSubscriptionChangeset == subscription.changeset && !synchronizer.hasChanges) {
return
}
lastSubscriptionChangeset = subscription.changeset
val (xi, yi, zi) = blockPos
val bx = xi + 0.5
val by = yi + 0.5
@ -138,7 +153,7 @@ abstract class SynchronizedBlockEntity(p_155228_: BlockEntityType<*>, p_155229_:
val double = synchronizationRadius * synchronizationRadius
playerSubscribers.stream().filter {
subscription.players.stream().filter {
if (!it.isAlive) {
return@filter false
}
@ -191,6 +206,7 @@ abstract class SynchronizedBlockEntity(p_155228_: BlockEntityType<*>, p_155229_:
LOGGER.error("Player ${event.player} started 'watching' chunk ${event.chunk} more than once.")
} else {
players.add(event.player)
it.changeset++
}
}
}
@ -201,6 +217,8 @@ abstract class SynchronizedBlockEntity(p_155228_: BlockEntityType<*>, p_155229_:
if (subs.players.remove(event.player)) {
if (subs.isEmpty) {
playerMap.get(event.level)?.remove(event.pos.toLong())
} else {
subs.changeset++
}
} else {
LOGGER.error("Player ${event.player} stopped 'watching' chunk at ${event.pos} before starting to watch it/stopped 'watching' more than once.")
@ -217,6 +235,7 @@ abstract class SynchronizedBlockEntity(p_155228_: BlockEntityType<*>, p_155229_:
for (value in listIterator) {
if (value === event.entity) {
listIterator.remove()
entry.value.changeset++
}
}