Did massive refactoring to sort everything

Started implementing reliable UDP system
TODO: Implement UDP hole-punching system
This commit is contained in:
Gabriel Tofvesson 2018-07-28 02:14:09 +02:00
parent 2af938169c
commit f45c59e796
22 changed files with 138 additions and 37 deletions

View File

@ -1,6 +1,9 @@
import net.tofvesson.math.MathSerializer; import net.tofvesson.annotation.SyncedVar;
import net.tofvesson.data.DiffTracked;
import net.tofvesson.data.DiffTrackedArray;
import net.tofvesson.data.SyncHandler;
import net.tofvesson.serializers.MathSerializer;
import net.tofvesson.math.Vector3; import net.tofvesson.math.Vector3;
import net.tofvesson.networking.*;
public class Main { public class Main {
@SyncedVar("NonNegative") @SyncedVar("NonNegative")
@ -33,7 +36,6 @@ public class Main {
public static void main(String[] args){ public static void main(String[] args){
Main testObject = new Main(); Main testObject = new Main();
SyncHandler.Companion.registerSerializer(MathSerializer.Companion.getSingleton());
SyncHandler sync = new SyncHandler(); SyncHandler sync = new SyncHandler();
sync.registerSyncObject(testObject); sync.registerSyncObject(testObject);
sync.registerSyncObject(Main.class); sync.registerSyncObject(Main.class);

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.annotation
/** /**
* Prevents SyncedVar system from syncing superclasses * Prevents SyncedVar system from syncing superclasses

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.annotation
import net.tofvesson.reflect.* import net.tofvesson.reflect.*
@ -31,7 +31,7 @@ enum class SyncFlag {
fun createFlag(name: String): SyncFlag { fun createFlag(name: String): SyncFlag {
// Do duplication check // Do duplication check
if(getByName(name)!=null) throw IllegalArgumentException("Flag \"$name\" is already registered!") if(getByName(name) !=null) throw IllegalArgumentException("Flag \"$name\" is already registered!")
// Get unsafe // Get unsafe
val unsafe = getUnsafe() val unsafe = getUnsafe()

View File

@ -0,0 +1,10 @@
package net.tofvesson.data
fun ByteArray.readBits(index: Int, bitCount: Int, bitOffset: Int = 0): Int {
var result = 0
for(i in 0 until bitCount)
result = result or readBit(index, bitOffset+i)
return result
}
fun ByteArray.readBit(index: Int, bitOffset: Int = 0) = (this[index + (bitOffset ushr 3)].toInt() ushr (bitOffset and 7)) and 1

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.data
import java.util.* import java.util.*

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.data
class DiffTrackedArray<T>(val elementType: Class<T>, val size: Int, gen: (Int) -> T) { class DiffTrackedArray<T>(val elementType: Class<T>, val size: Int, gen: (Int) -> T) {

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.data
data class Holder(var value: Any?){ data class Holder(var value: Any?){
companion object { companion object {

View File

@ -1,6 +1,7 @@
package net.tofvesson.networking package net.tofvesson.data
import net.tofvesson.math.collapseLowerByte import net.tofvesson.exception.InsufficientCapacityException
import net.tofvesson.math.*
import java.nio.ByteBuffer import java.nio.ByteBuffer
@Suppress("MemberVisibilityCanBePrivate", "unused") @Suppress("MemberVisibilityCanBePrivate", "unused")

View File

@ -1,5 +1,7 @@
package net.tofvesson.networking package net.tofvesson.data
import net.tofvesson.annotation.SyncFlag
import net.tofvesson.exception.UnsupportedTypeException
import java.lang.reflect.Field import java.lang.reflect.Field
import java.util.* import java.util.*

View File

@ -1,6 +1,14 @@
package net.tofvesson.networking package net.tofvesson.data
import net.tofvesson.annotation.NoUpwardCascade
import net.tofvesson.annotation.SyncFlag
import net.tofvesson.annotation.SyncedVar
import net.tofvesson.exception.UnsupportedTypeException
import net.tofvesson.reflect.access import net.tofvesson.reflect.access
import net.tofvesson.serializers.DiffTrackedSerializer
import net.tofvesson.serializers.MathSerializer
import net.tofvesson.serializers.PrimitiveArraySerializer
import net.tofvesson.serializers.PrimitiveSerializer
import java.lang.reflect.Field import java.lang.reflect.Field
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.security.NoSuchAlgorithmException import java.security.NoSuchAlgorithmException
@ -20,6 +28,7 @@ class SyncHandler(private val permissiveMismatchCheck: Boolean = false) {
serializers.add(PrimitiveSerializer.singleton) serializers.add(PrimitiveSerializer.singleton)
serializers.add(PrimitiveArraySerializer.singleton) serializers.add(PrimitiveArraySerializer.singleton)
serializers.add(DiffTrackedSerializer.singleton) serializers.add(DiffTrackedSerializer.singleton)
serializers.add(MathSerializer.singleton)
} }
fun registerSerializer(serializer: Serializer) { fun registerSerializer(serializer: Serializer) {
@ -121,7 +130,7 @@ class SyncHandler(private val permissiveMismatchCheck: Boolean = false) {
private fun computeObjectSize(value: Any, writeState: WriteState) = computeTypeSize(value.javaClass, value, writeState) private fun computeObjectSize(value: Any, writeState: WriteState) = computeTypeSize(value.javaClass, value, writeState)
private fun computeClassSize(value: Class<*>, writeState: WriteState) = computeTypeSize(value, null, writeState) private fun computeClassSize(value: Class<*>, writeState: WriteState) = computeTypeSize(value, null, writeState)
private fun computeTypeSize(type: Class<*>, value: Any?, writeState: WriteState) { private fun computeTypeSize(type: Class<*>, value: Any?, writeState: WriteState) {
for(field in collectSyncable(type, value==null)) for(field in collectSyncable(type, value == null))
getCompatibleSerializer(field.access().type) getCompatibleSerializer(field.access().type)
.computeSize(field, SyncFlag.parse(field.getAnnotation(SyncedVar::class.java).value), value, writeState) .computeSize(field, SyncFlag.parse(field.getAnnotation(SyncedVar::class.java).value), value, writeState)
} }
@ -129,7 +138,7 @@ class SyncHandler(private val permissiveMismatchCheck: Boolean = false) {
private fun readObject(value: Any, writeBuffer: WriteBuffer) = readType(value.javaClass, value, writeBuffer) private fun readObject(value: Any, writeBuffer: WriteBuffer) = readType(value.javaClass, value, writeBuffer)
private fun readClass(value: Class<*>, writeBuffer: WriteBuffer) = readType(value, null, writeBuffer) private fun readClass(value: Class<*>, writeBuffer: WriteBuffer) = readType(value, null, writeBuffer)
private fun readType(type: Class<*>, value: Any?, writeBuffer: WriteBuffer) { private fun readType(type: Class<*>, value: Any?, writeBuffer: WriteBuffer) {
for(field in collectSyncable(type, value==null)) for(field in collectSyncable(type, value == null))
getCompatibleSerializer(field.type) getCompatibleSerializer(field.type)
.serialize(field, SyncFlag.parse(field.getAnnotation(SyncedVar::class.java).value), value, writeBuffer) .serialize(field, SyncFlag.parse(field.getAnnotation(SyncedVar::class.java).value), value, writeBuffer)
} }
@ -137,7 +146,7 @@ class SyncHandler(private val permissiveMismatchCheck: Boolean = false) {
private fun writeObject(value: Any, readBuffer: ReadBuffer) = writeType(value.javaClass, value, readBuffer) private fun writeObject(value: Any, readBuffer: ReadBuffer) = writeType(value.javaClass, value, readBuffer)
private fun writeClass(value: Class<*>, readBuffer: ReadBuffer) = writeType(value, null, readBuffer) private fun writeClass(value: Class<*>, readBuffer: ReadBuffer) = writeType(value, null, readBuffer)
private fun writeType(type: Class<*>, value: Any?, readBuffer: ReadBuffer) { private fun writeType(type: Class<*>, value: Any?, readBuffer: ReadBuffer) {
for(field in collectSyncable(type, value==null)) for(field in collectSyncable(type, value == null))
getCompatibleSerializer(field.type) getCompatibleSerializer(field.type)
.deserialize(field, SyncFlag.parse(field.getAnnotation(SyncedVar::class.java).value), value, readBuffer) .deserialize(field, SyncFlag.parse(field.getAnnotation(SyncedVar::class.java).value), value, readBuffer)
} }

View File

@ -1,7 +1,7 @@
package net.tofvesson.networking package net.tofvesson.data
import net.tofvesson.math.collapseLowerByte import net.tofvesson.exception.InsufficientCapacityException
import net.tofvesson.math.toNumber import net.tofvesson.math.*
import java.nio.ByteBuffer import java.nio.ByteBuffer
import kotlin.experimental.and import kotlin.experimental.and
import kotlin.experimental.or import kotlin.experimental.or

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.data
import net.tofvesson.math.collapseLowerByte import net.tofvesson.math.collapseLowerByte
@ -10,9 +10,9 @@ data class WriteState(private var _bytes: Int, private var _bits: Int, private v
var header: Int = _header var header: Int = _header
private set private set
fun registerBytes(bytes: Int): WriteState { this.bytes += bytes; return this } fun registerBytes(bytes: Int): WriteState { this.bytes += bytes; return this }
fun registerBits(bits: Int) : WriteState { this.bits += bits; return this } fun registerBits(bits: Int) : WriteState { this.bits += bits; return this }
fun registerHeader(header: Int): WriteState{ this.header += header; return this } fun registerHeader(header: Int): WriteState { this.header += header; return this }
fun computeRequiredBytes(additionalBytes: Int = 0, additionalBits: Int = 0) = fun computeRequiredBytes(additionalBytes: Int = 0, additionalBits: Int = 0) =
bytes + additionalBytes + computeBitFieldOffset(additionalBits) bytes + additionalBytes + computeBitFieldOffset(additionalBits)

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.exception
class InsufficientCapacityException: RuntimeException { class InsufficientCapacityException: RuntimeException {
constructor() : super() constructor() : super()

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.exception
class MismatchedFlagException: RuntimeException { class MismatchedFlagException: RuntimeException {
constructor() : super() constructor() : super()

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.exception
class UnsupportedTypeException: RuntimeException { class UnsupportedTypeException: RuntimeException {
constructor() : super() constructor() : super()

View File

@ -1,4 +1,4 @@
package net.tofvesson.networking package net.tofvesson.math
import java.nio.ByteBuffer import java.nio.ByteBuffer
import kotlin.experimental.or import kotlin.experimental.or

View File

@ -1,6 +1,6 @@
package net.tofvesson.math package net.tofvesson.math
import net.tofvesson.networking.DiffTracked import net.tofvesson.data.DiffTracked
class Vector3(xPos: Float, yPos: Float, zPos: Float) { class Vector3(xPos: Float, yPos: Float, zPos: Float) {

View File

@ -0,0 +1,64 @@
package net.tofvesson.networking
import net.tofvesson.reflect.access
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
import java.util.concurrent.atomic.AtomicBoolean
class ReliableUDP(address: InetAddress, port: Short, private val onAccept: (ByteArray, Int, Int) -> Unit, private val automaticAccept: Boolean, acceptTimeout: Long = 10L) {
private enum class PacketType(val bits: Int = (javaClass.getDeclaredField("\$VALUES").access().get(null) as Array<*>).indexOf(this)) {
DATA, ACK, FIN;
companion object {
val fieldSize = (Math.log((javaClass.getDeclaredField("\$VALUES").access().get(null) as Array<*>).size.toDouble()) / Math.log(2.0)).toInt() + 1
}
}
private var socket = DatagramSocket()
private val sync: Thread? = if(automaticAccept) Thread { acceptLoop() } else null
private val stop = AtomicBoolean(false)
private var finInitiated = false
private val packet = DatagramPacket(ByteArray(socket.receiveBufferSize), socket.receiveBufferSize)
init {
socket.connect(address, port.toInt())
socket.soTimeout = 0
sync?.start()
}
private fun acceptLoop(){
while(synchronized(stop){!stop.get()}){
accept()
if(packet.length==0) continue // Drop empty packets
val packetType = PacketType.values()[packet.data[0].toInt()]
when(packetType){
PacketType.DATA -> {
}
PacketType.ACK -> {
}
PacketType.FIN -> {
}
}
}
}
fun accept(){
if(automaticAccept && Thread.currentThread() != sync)
throw IllegalThreadStateException("Current thread isn't setup to accept datagram packets")
socket.receive(packet)
}
fun send(){
if(finInitiated) throw IllegalStateException("Cannot send message after connection is closed!")
}
fun _send(){
}
}

View File

@ -1,5 +1,7 @@
package net.tofvesson.networking package net.tofvesson.serializers
import net.tofvesson.annotation.SyncFlag
import net.tofvesson.data.*
import java.lang.reflect.Field import java.lang.reflect.Field
class DiffTrackedSerializer private constructor(): Serializer(arrayOf( class DiffTrackedSerializer private constructor(): Serializer(arrayOf(

View File

@ -1,6 +1,9 @@
package net.tofvesson.math package net.tofvesson.serializers
import net.tofvesson.networking.* import net.tofvesson.annotation.SyncFlag
import net.tofvesson.data.*
import net.tofvesson.exception.MismatchedFlagException
import net.tofvesson.math.*
import net.tofvesson.reflect.access import net.tofvesson.reflect.access
import java.lang.reflect.Field import java.lang.reflect.Field
@ -102,13 +105,13 @@ class MathSerializer: Serializer(arrayOf(
if(nn || pc){ if(nn || pc){
var track = 0 var track = 0
flags = Array(flags.size - resize){ flags = Array(flags.size - resize){
if(flags[track]==SyncFlag.NonNegative && nn){ if(flags[track]== SyncFlag.NonNegative && nn){
if(flags[++track]==SyncFlag.NoCompress && pc) if(flags[++track]== SyncFlag.NoCompress && pc)
flags[++track] flags[++track]
else flags[track] else flags[track]
} }
else if(flags[track]==SyncFlag.NoCompress && nn){ else if(flags[track]== SyncFlag.NoCompress && nn){
if(flags[++track]==SyncFlag.NonNegative && pc) if(flags[++track]== SyncFlag.NonNegative && pc)
flags[++track] flags[++track]
else flags[track] else flags[track]
}else flags[track] }else flags[track]

View File

@ -1,5 +1,7 @@
package net.tofvesson.networking package net.tofvesson.serializers
import net.tofvesson.annotation.SyncFlag
import net.tofvesson.data.*
import java.lang.reflect.Field import java.lang.reflect.Field
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")

View File

@ -1,5 +1,11 @@
package net.tofvesson.networking package net.tofvesson.serializers
import net.tofvesson.annotation.SyncFlag
import net.tofvesson.data.ReadBuffer
import net.tofvesson.data.Serializer
import net.tofvesson.data.WriteBuffer
import net.tofvesson.data.WriteState
import net.tofvesson.math.*
import net.tofvesson.reflect.* import net.tofvesson.reflect.*
import java.lang.reflect.Field import java.lang.reflect.Field