Extract observed map from saved counting map

This commit is contained in:
DBotThePony 2022-09-02 12:54:02 +07:00
parent 4e2928dbc7
commit cbea8873e9
Signed by: DBot
GPG Key ID: DCC23B5715498507
2 changed files with 347 additions and 302 deletions

View File

@ -0,0 +1,315 @@
package ru.dbotthepony.mc.otm.core
abstract class ObservedMap<K, V>(protected val backingMap: MutableMap<K, V> = HashMap()) : MutableMap<K, V> {
protected abstract fun onClear()
protected abstract fun onValueAdded(key: K, value: V)
protected abstract fun onValueRemoved(key: K, value: V)
final override val size: Int
get() = backingMap.size
final override fun containsKey(key: K): Boolean {
return backingMap.containsKey(key)
}
final override fun containsValue(value: V): Boolean {
return backingMap.containsValue(value)
}
final override fun get(key: K): V? {
return backingMap[key]
}
final override fun isEmpty(): Boolean {
return backingMap.isEmpty()
}
final override val entries: MutableSet<MutableMap.MutableEntry<K, V>> by lazy {
object : MutableSet<MutableMap.MutableEntry<K, V>> {
override fun add(element: MutableMap.MutableEntry<K, V>): Boolean {
this@ObservedMap[element.key] = element.value
return true
}
override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
for (value in elements) {
add(value)
}
return true
}
override fun clear() {
this@ObservedMap.clear()
}
private val setParent = this@ObservedMap.backingMap.entries
override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> {
return object : MutableIterator<MutableMap.MutableEntry<K, V>> {
private val parent = setParent.iterator()
private var last: MutableMap.MutableEntry<K, V>? = null
override fun hasNext(): Boolean {
return parent.hasNext()
}
override fun next(): MutableMap.MutableEntry<K, V> {
return parent.next().also { last = it }
}
override fun remove() {
val last = last ?: throw IllegalStateException("Never called next()")
parent.remove()
onValueRemoved(last.key, last.value)
}
}
}
override fun remove(element: MutableMap.MutableEntry<K, V>): Boolean {
if (setParent.remove(element)) {
onValueRemoved(element.key, element.value)
return true
}
return false
}
override fun removeAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
var any = false
for (element in elements) {
any = remove(element) || any
}
return any
}
override fun retainAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
val iterator = this.iterator()
var any = false
for (value in iterator) {
if (value !in elements) {
iterator.remove()
any = true
}
}
return any
}
override val size: Int
get() = setParent.size
override fun contains(element: MutableMap.MutableEntry<K, V>): Boolean {
return setParent.contains(element)
}
override fun containsAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
return setParent.containsAll(elements)
}
override fun isEmpty(): Boolean {
return setParent.isEmpty()
}
}
}
final override val keys: MutableSet<K> by lazy {
object : MutableSet<K> {
val parent = this@ObservedMap.backingMap.keys
override fun add(element: K): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(elements: Collection<K>): Boolean {
throw UnsupportedOperationException()
}
override fun clear() {
this@ObservedMap.clear()
}
override fun iterator(): MutableIterator<K> {
return object : MutableIterator<K> {
private val parentIterator = parent.iterator()
private var last: K? = null
override fun hasNext(): Boolean {
return parentIterator.hasNext()
}
override fun next(): K {
return parentIterator.next().also { last = it }
}
override fun remove() {
val last = last ?: throw IllegalStateException("Never called next()")
val value = this@ObservedMap[last] ?: throw ConcurrentModificationException()
parentIterator.remove()
onValueRemoved(last, value)
}
}
}
override fun remove(element: K): Boolean {
return this@ObservedMap.remove(element) != null
}
override fun removeAll(elements: Collection<K>): Boolean {
var changes = false
for (element in elements) {
changes = remove(element) || changes
}
return changes
}
override fun retainAll(elements: Collection<K>): Boolean {
val iterator = this.iterator()
var any = false
for (element in iterator) {
if (element !in elements) {
iterator.remove()
any = true
}
}
return any
}
override val size: Int
get() = parent.size
override fun contains(element: K): Boolean {
return parent.contains(element)
}
override fun containsAll(elements: Collection<K>): Boolean {
return parent.containsAll(elements)
}
override fun isEmpty(): Boolean {
return parent.isEmpty()
}
}
}
final override val values: MutableCollection<V> by lazy {
object : MutableCollection<V> {
private val parent = this@ObservedMap.backingMap.values
override val size: Int
get() = parent.size
override fun contains(element: V): Boolean {
return parent.contains(element)
}
override fun containsAll(elements: Collection<V>): Boolean {
return parent.containsAll(elements)
}
override fun isEmpty(): Boolean {
return parent.isEmpty()
}
override fun add(element: V): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(elements: Collection<V>): Boolean {
throw UnsupportedOperationException()
}
override fun clear() {
this@ObservedMap.clear()
}
override fun iterator(): MutableIterator<V> {
return object : MutableIterator<V> {
private val parentIterator = parent.iterator()
override fun hasNext(): Boolean {
return parentIterator.hasNext()
}
override fun next(): V {
return parentIterator.next()
}
override fun remove() {
parentIterator.remove()
}
}
}
override fun remove(element: V): Boolean {
val indexOf = this@ObservedMap.backingMap.firstNotNullOfOrNull { if (it.value == element) it.key else null } ?: return false
this@ObservedMap.remove(indexOf)
return true
}
override fun removeAll(elements: Collection<V>): Boolean {
var changes = false
for (element in elements) {
changes = remove(element) || changes
}
return changes
}
override fun retainAll(elements: Collection<V>): Boolean {
val iterator = this.iterator()
var changes = false
for (element in iterator) {
if (element !in elements) {
iterator.remove()
changes = true
}
}
return changes
}
}
}
override fun clear() {
onClear()
return backingMap.clear()
}
override fun put(key: K, value: V): V? {
val existing = backingMap.put(key, value)
if (existing == value) {
return existing
}
onValueAdded(key, value)
return existing
}
final override fun putAll(from: Map<out K, V>) {
for ((k, v) in from) {
this[k] = v
}
}
override fun remove(key: K): V? {
val removed = backingMap.remove(key)
if (removed != null) {
onValueRemoved(key, removed)
}
return removed
}
}

View File

@ -8,8 +8,9 @@ import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag import net.minecraft.nbt.Tag
import net.minecraft.world.level.saveddata.SavedData import net.minecraft.world.level.saveddata.SavedData
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.container.set import ru.dbotthepony.mc.otm.core.ObservedMap
import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.registry.WriteOnce
class SavedMapDelegate<V>(val parent: SavedCountingMap<SavedMapDelegate<V>>?, val index: Int, value: V) { class SavedMapDelegate<V>(val parent: SavedCountingMap<SavedMapDelegate<V>>?, val index: Int, value: V) {
constructor(value: V) : this(null, -1, value) constructor(value: V) : this(null, -1, value)
@ -37,11 +38,38 @@ class SavedMapDelegate<V>(val parent: SavedCountingMap<SavedMapDelegate<V>>?, va
} }
} }
class SavedCountingMap<T>( private class ObservedCountingMap<T> : ObservedMap<Int, T>(Int2ObjectAVLTreeMap()) {
var parent: SavedCountingMap<T> by WriteOnce()
override fun onClear() {
parent.isDirty = true
}
override fun onValueAdded(key: Int, value: T) {
parent.isDirty = true
}
override fun onValueRemoved(key: Int, value: T) {
parent.isDirty = true
}
}
class SavedCountingMap<T> private constructor(
val serializer: (map: SavedCountingMap<T>, value: T, index: Int) -> Tag, val serializer: (map: SavedCountingMap<T>, value: T, index: Int) -> Tag,
val deserializer: (map: SavedCountingMap<T>, nbt: Tag, index: Int) -> T, val deserializer: (map: SavedCountingMap<T>, nbt: Tag, index: Int) -> T,
val factory: (map: SavedCountingMap<T>, index: Int) -> T val factory: (map: SavedCountingMap<T>, index: Int) -> T,
) : SavedData(), MutableMap<Int, T> { private val map: ObservedCountingMap<T>
) : SavedData(), MutableMap<Int, T> by map {
constructor(
serializer: (map: SavedCountingMap<T>, value: T, index: Int) -> Tag,
deserializer: (map: SavedCountingMap<T>, nbt: Tag, index: Int) -> T,
factory: (map: SavedCountingMap<T>, index: Int) -> T,
) : this(serializer, deserializer, factory, ObservedCountingMap())
init {
map.parent = this
}
var nextIndex = 0 var nextIndex = 0
private set private set
@ -56,304 +84,6 @@ class SavedCountingMap<T>(
return computeIfAbsent(nextIndex++) return computeIfAbsent(nextIndex++)
} }
private val map = Int2ObjectAVLTreeMap<T>()
override val size: Int
get() = map.size
override fun containsKey(key: Int): Boolean {
return map.containsKey(key)
}
override fun containsValue(value: T): Boolean {
return map.containsValue(value)
}
override fun get(key: Int): T? {
return map[key]
}
override fun isEmpty(): Boolean {
return map.isEmpty()
}
override val entries: MutableSet<MutableMap.MutableEntry<Int, T>> by lazy {
object : MutableSet<MutableMap.MutableEntry<Int, T>> {
override fun add(element: MutableMap.MutableEntry<Int, T>): Boolean {
this@SavedCountingMap[element.key] = element.value
return true
}
override fun addAll(elements: Collection<MutableMap.MutableEntry<Int, T>>): Boolean {
for (value in elements) {
add(value)
}
return true
}
override fun clear() {
this@SavedCountingMap.clear()
}
private val setParent = this@SavedCountingMap.map.int2ObjectEntrySet()
override fun iterator(): MutableIterator<MutableMap.MutableEntry<Int, T>> {
return object : MutableIterator<MutableMap.MutableEntry<Int, T>> {
private val parent = setParent.iterator()
override fun hasNext(): Boolean {
return parent.hasNext()
}
override fun next(): MutableMap.MutableEntry<Int, T> {
return parent.next()
}
override fun remove() {
parent.remove()
isDirty = true
}
}
}
override fun remove(element: MutableMap.MutableEntry<Int, T>): Boolean {
if (setParent.remove(element)) {
isDirty = true
return true
}
return false
}
override fun removeAll(elements: Collection<MutableMap.MutableEntry<Int, T>>): Boolean {
if (setParent.removeAll(elements)) {
isDirty = true
return true
}
return false
}
override fun retainAll(elements: Collection<MutableMap.MutableEntry<Int, T>>): Boolean {
if (setParent.retainAll(elements)) {
isDirty = true
return true
}
return false
}
override val size: Int
get() = setParent.size
override fun contains(element: MutableMap.MutableEntry<Int, T>): Boolean {
return setParent.contains(element)
}
override fun containsAll(elements: Collection<MutableMap.MutableEntry<Int, T>>): Boolean {
return setParent.containsAll(elements)
}
override fun isEmpty(): Boolean {
return setParent.isEmpty()
}
}
}
override val keys: MutableSet<Int> by lazy {
object : MutableSet<Int> {
val parent = this@SavedCountingMap.map.keys
override fun add(element: Int): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(elements: Collection<Int>): Boolean {
throw UnsupportedOperationException()
}
override fun clear() {
this@SavedCountingMap.clear()
}
override fun iterator(): MutableIterator<Int> {
return object : MutableIterator<Int> {
private val parentIterator = parent.iterator()
override fun hasNext(): Boolean {
return parentIterator.hasNext()
}
override fun next(): Int {
return parentIterator.nextInt()
}
override fun remove() {
parentIterator.remove()
isDirty = true
}
}
}
override fun remove(element: Int): Boolean {
return this@SavedCountingMap.remove(element) != null
}
override fun removeAll(elements: Collection<Int>): Boolean {
var changes = false
for (element in elements) {
changes = remove(element) || changes
}
return changes
}
override fun retainAll(elements: Collection<Int>): Boolean {
val iterator = this.iterator()
var changes = false
for (element in iterator) {
if (element !in elements) {
iterator.remove()
changes = true
}
}
return changes
}
override val size: Int
get() = parent.size
override fun contains(element: Int): Boolean {
return parent.contains(element)
}
override fun containsAll(elements: Collection<Int>): Boolean {
return parent.containsAll(elements)
}
override fun isEmpty(): Boolean {
return parent.isEmpty()
}
}
}
override val values: MutableCollection<T> by lazy {
object : MutableCollection<T> {
private val parent = this@SavedCountingMap.map.values
override val size: Int
get() = parent.size
override fun contains(element: T): Boolean {
return parent.contains(element)
}
override fun containsAll(elements: Collection<T>): Boolean {
return parent.containsAll(elements)
}
override fun isEmpty(): Boolean {
return parent.isEmpty()
}
override fun add(element: T): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(elements: Collection<T>): Boolean {
throw UnsupportedOperationException()
}
override fun clear() {
this@SavedCountingMap.clear()
}
override fun iterator(): MutableIterator<T> {
return object : MutableIterator<T> {
private val parentIterator = parent.iterator()
override fun hasNext(): Boolean {
return parentIterator.hasNext()
}
override fun next(): T {
return parentIterator.next()
}
override fun remove() {
parentIterator.remove()
isDirty = true
}
}
}
override fun remove(element: T): Boolean {
val indexOf = this@SavedCountingMap.map.firstNotNullOfOrNull { if (it.value == element) it.key else null } ?: return false
this@SavedCountingMap.remove(indexOf)
return true
}
override fun removeAll(elements: Collection<T>): Boolean {
var changes = false
for (element in elements) {
changes = remove(element) || changes
}
return changes
}
override fun retainAll(elements: Collection<T>): Boolean {
val iterator = this.iterator()
var changes = false
for (element in iterator) {
if (element !in elements) {
iterator.remove()
changes = true
}
}
return changes
}
}
}
override fun clear() {
isDirty = true
return map.clear()
}
override fun put(key: Int, value: T): T? {
val existing = map.put(key, value)
if (existing == value) {
return existing
}
isDirty = true
return existing
}
override fun putAll(from: Map<out Int, T>) {
isDirty = true
return map.putAll(from)
}
override fun remove(key: Int): T? {
val removed = map.remove(key)
if (removed != null) {
isDirty = true
}
return removed
}
override fun save(output: CompoundTag): CompoundTag { override fun save(output: CompoundTag): CompoundTag {
output["map"] = ListTag().also { output["map"] = ListTag().also {
for ((key, value) in this.map) { for ((key, value) in this.map) {