This commit is contained in:
DBotThePony 2022-10-26 22:27:10 +07:00
parent 1e34b7dfce
commit ebabcdf731
Signed by: DBot
GPG Key ID: DCC23B5715498507
2 changed files with 36 additions and 1 deletions

View File

@ -10,11 +10,28 @@ import java.util.function.Predicate
import kotlin.NoSuchElementException
import kotlin.math.absoluteValue
/**
* Represents value which can be encoded onto or decoded from stream.
*
* Also provides [copy] and [compare] methods
*/
interface IStreamCodec<V> {
fun read(stream: DataInputStream): V
fun write(stream: DataOutputStream, value: V)
/**
* if value is immutable, return it right away
*/
fun copy(value: V): V
fun compare(a: V, b: V): Boolean
/**
* Optional equality check override. Utilized to determine whenever e.g. network value is different from new value
*
* By default uses [Any.equals]
*/
fun compare(a: V, b: V): Boolean {
return a == b
}
}
class StreamCodec<V>(

View File

@ -94,6 +94,24 @@ enum class MapAction {
CLEAR, ADD, REMOVE
}
/**
* Universal one-to-many value synchronizer
*
* This class represent collection of synchronizable values (similar to entitydata or menu's dataslots)
*
* Advantages of this class are:
* * It can be freely pooled. You can call [collectNetworkPayload] and [FieldSynchronizer.Endpoint.collectNetworkPayload] as much as you like,
* because they use dirty lists to track which fields need networking. **Warning**: If you attach one or more "observed" values (more on them below),
* each call to above methods will cause scan on observed fields.
* * It is universal. No, seriously, you can use it anywhere, all it needs is you encode [FastByteArrayOutputStream], send it over your
* networking channel, and create [InputStream] to feed to [FieldSynchronizer.Endpoint]
* * Its capabilities at networking are only limited by codecs you provide, see [FieldSynchronizer.Field], [IStreamCodec]
* * Provides not only single values, but also smart [FieldSynchronizer.Map] map synchronization
* * Has network version "conflict" resolver. If source FieldSynchronizer and target FieldSynchronizer have different set of fields, they can figure out how to synchronize
* only known fields. **Keep in mind this only works if you manually specify names on ALL created fields**
* * Directly bytestream embeddable. [FieldSynchronizer.Endpoint] always knows how much bytes to read from incoming stream, you can directly embed it into your data flow
* on network channel.
*/
@Suppress("unused")
class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCallback: Boolean) {
constructor() : this(Runnable {}, false)