diff --git a/buildSrc/src/main/kotlin/space/uranos/mdsp/generator/EntitiesGenerator.kt b/buildSrc/src/main/kotlin/space/uranos/mdsp/generator/EntitiesGenerator.kt index 7fc9a50..71cb8dc 100644 --- a/buildSrc/src/main/kotlin/space/uranos/mdsp/generator/EntitiesGenerator.kt +++ b/buildSrc/src/main/kotlin/space/uranos/mdsp/generator/EntitiesGenerator.kt @@ -84,6 +84,16 @@ class EntitiesGenerator( .initializer("Type") .build() ) + .addProperty( + PropertySpec.builder( + "dataStorage", + ClassName("$BASE_PACKAGE.data", "DataStorage").parameterizedBy(ClassName(ENTITY_PACKAGE, name)), + KModifier.OVERRIDE + ) + .addAnnotation(AnnotationSpec.builder(Suppress::class).addMember("\"LeakingThis\"").build()) + .initializer("%T(this)", ClassName("$BASE_PACKAGE.data", "DataStorage")) + .build() + ) .addType( TypeSpec.companionObjectBuilder("Type") .superclass(ClassName(ENTITY_PACKAGE, name + "Type")) diff --git a/uranos-api/src/main/kotlin/space/uranos/entity/PaintingMotive.kt b/uranos-api/src/main/kotlin/space/uranos/PaintingMotive.kt similarity index 96% rename from uranos-api/src/main/kotlin/space/uranos/entity/PaintingMotive.kt rename to uranos-api/src/main/kotlin/space/uranos/PaintingMotive.kt index 2a3a9e0..7cdf83c 100644 --- a/uranos-api/src/main/kotlin/space/uranos/entity/PaintingMotive.kt +++ b/uranos-api/src/main/kotlin/space/uranos/PaintingMotive.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file */ -package space.uranos.entity +package space.uranos enum class PaintingMotive(val width: Int, val height: Int) { // Order is important diff --git a/uranos-server/src/main/kotlin/space/uranos/data/DataStorage.kt b/uranos-api/src/main/kotlin/space/uranos/data/DataStorage.kt similarity index 89% rename from uranos-server/src/main/kotlin/space/uranos/data/DataStorage.kt rename to uranos-api/src/main/kotlin/space/uranos/data/DataStorage.kt index 6fe715b..577938e 100644 --- a/uranos-server/src/main/kotlin/space/uranos/data/DataStorage.kt +++ b/uranos-api/src/main/kotlin/space/uranos/data/DataStorage.kt @@ -38,15 +38,12 @@ class DataStorage(val context: ContextT) { @Suppress("UNCHECKED_CAST") val entry = map[key] as Entry? - println(key) - println(value) - if (entry == null) map[key] = Entry(key, value) else entry.value = value } @Suppress("UNCHECKED_CAST") - fun get(key: DataStorageKey) = map[key] as V + fun get(key: DataStorageKey) = (map[key] as Entry?)!!.value suspend fun tick() { val actions = map.values.mapNotNull { it.tick() } @@ -58,4 +55,7 @@ class DataStorage(val context: ContextT) { key.tick(context, values) } } + + @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") + inline fun cast() = this as DataStorage } diff --git a/uranos-server/src/main/kotlin/space/uranos/data/DataStorageCombinableAction.kt b/uranos-api/src/main/kotlin/space/uranos/data/DataStorageCombinableAction.kt similarity index 100% rename from uranos-server/src/main/kotlin/space/uranos/data/DataStorageCombinableAction.kt rename to uranos-api/src/main/kotlin/space/uranos/data/DataStorageCombinableAction.kt diff --git a/uranos-server/src/main/kotlin/space/uranos/data/DataStorageKey.kt b/uranos-api/src/main/kotlin/space/uranos/data/DataStorageKey.kt similarity index 100% rename from uranos-server/src/main/kotlin/space/uranos/data/DataStorageKey.kt rename to uranos-api/src/main/kotlin/space/uranos/data/DataStorageKey.kt diff --git a/uranos-api/src/main/kotlin/space/uranos/entity/Entity.kt b/uranos-api/src/main/kotlin/space/uranos/entity/Entity.kt index eb4eac7..533a28a 100644 --- a/uranos-api/src/main/kotlin/space/uranos/entity/Entity.kt +++ b/uranos-api/src/main/kotlin/space/uranos/entity/Entity.kt @@ -8,6 +8,7 @@ package space.uranos.entity import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import space.uranos.Uranos +import space.uranos.data.DataStorage import space.uranos.world.World import java.util.* @@ -23,6 +24,7 @@ abstract class Entity internal constructor() { open val uuid: UUID = UUID.randomUUID() abstract val type: EntityType + abstract val dataStorage: DataStorage private val worldMutex = Mutex() var world: World? = null; protected set diff --git a/uranos-api/src/main/kotlin/space/uranos/entity/ItemEntity.kt b/uranos-api/src/main/kotlin/space/uranos/entity/ItemEntity.kt index 8dc4436..3be0df8 100644 --- a/uranos-api/src/main/kotlin/space/uranos/entity/ItemEntity.kt +++ b/uranos-api/src/main/kotlin/space/uranos/entity/ItemEntity.kt @@ -6,9 +6,13 @@ package space.uranos.entity import space.uranos.Position +import space.uranos.data.DataStorage open class ItemEntity(override var position: Position) : ObjectEntity() { - final override val type: EntityType = Type + final override val type: EntityType = Type - companion object Type : ItemEntityType() + @Suppress("LeakingThis") + public override val dataStorage: DataStorage = DataStorage(this) + + companion object Type : ItemEntityType() } diff --git a/uranos-api/src/main/kotlin/space/uranos/entity/LivingEntity.kt b/uranos-api/src/main/kotlin/space/uranos/entity/LivingEntity.kt index 75375c4..e468a94 100644 --- a/uranos-api/src/main/kotlin/space/uranos/entity/LivingEntity.kt +++ b/uranos-api/src/main/kotlin/space/uranos/entity/LivingEntity.kt @@ -3,13 +3,29 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file */ +@file:Suppress("LeakingThis") + package space.uranos.entity import space.uranos.Position import space.uranos.Vector +import space.uranos.data.DataStorage +import space.uranos.data.createDataStorageKey abstract class LivingEntity : Entity(), Mobile { abstract var headPitch: Float - abstract override var position: Position abstract override var velocity: Vector + abstract override val dataStorage: DataStorage + + override var position: Position + get() = dataStorage.cast().get(DataStorageKeys.position) + set(value) = dataStorage.cast().set(DataStorageKeys.position, value) + + object DataStorageKeys { + val position = createDataStorageKey("position") { entity: LivingEntity, value: Position -> + // TODO: Send the position to players + println(value) + null + } + } } diff --git a/uranos-api/src/main/kotlin/space/uranos/entity/PaintingEntity.kt b/uranos-api/src/main/kotlin/space/uranos/entity/PaintingEntity.kt index cf07c65..289fb24 100644 --- a/uranos-api/src/main/kotlin/space/uranos/entity/PaintingEntity.kt +++ b/uranos-api/src/main/kotlin/space/uranos/entity/PaintingEntity.kt @@ -6,6 +6,8 @@ package space.uranos.entity import space.uranos.CardinalDirection +import space.uranos.PaintingMotive +import space.uranos.data.DataStorage import space.uranos.world.VoxelLocation class PaintingEntity( @@ -13,9 +15,10 @@ class PaintingEntity( val direction: CardinalDirection, val motive: PaintingMotive ) : Entity() { - override val type: EntityType = Type + override val type: EntityType = Type + @Suppress("LeakingThis") + override val dataStorage: DataStorage = DataStorage(this) - - companion object Type : PaintingEntityType() + companion object Type : PaintingEntityType() } diff --git a/uranos-api/src/main/kotlin/space/uranos/entity/PlayerEntity.kt b/uranos-api/src/main/kotlin/space/uranos/entity/PlayerEntity.kt index 3b453fa..f7d5c64 100644 --- a/uranos-api/src/main/kotlin/space/uranos/entity/PlayerEntity.kt +++ b/uranos-api/src/main/kotlin/space/uranos/entity/PlayerEntity.kt @@ -7,11 +7,12 @@ package space.uranos.entity import space.uranos.Position import space.uranos.Vector +import space.uranos.data.DataStorage import space.uranos.player.Player import space.uranos.world.World open class PlayerEntity( - override var position: Position, + position: Position, /** * The player to which this entity belongs. * @@ -23,6 +24,13 @@ open class PlayerEntity( final override val type: EntityType = Type override var velocity: Vector = Vector.ZERO + @Suppress("LeakingThis") + override val dataStorage: DataStorage = DataStorage(this) + + init { + this.position = position + } + /** * Because [world] is never `null` for player entities, you can use this property instead of writing `world!!`. */ diff --git a/uranos-packet-codecs/src/main/kotlin/space/uranos/net/packet/play/PlayerOrientationPacketCodec.kt b/uranos-packet-codecs/src/main/kotlin/space/uranos/net/packet/play/PlayerOrientationPacketCodec.kt index aa83126..e186200 100644 --- a/uranos-packet-codecs/src/main/kotlin/space/uranos/net/packet/play/PlayerOrientationPacketCodec.kt +++ b/uranos-packet-codecs/src/main/kotlin/space/uranos/net/packet/play/PlayerOrientationPacketCodec.kt @@ -11,7 +11,7 @@ import space.uranos.net.packet.IncomingPacketCodec object PlayerOrientationPacketCodec : IncomingPacketCodec(0x14, PlayerOrientationPacket::class) { override fun decode(msg: ByteBuf): PlayerOrientationPacket = PlayerOrientationPacket( - 360 - msg.readFloat() % 360, + (360 - msg.readFloat()) % 360, msg.readFloat(), msg.readBoolean() ) diff --git a/uranos-packet-codecs/src/main/kotlin/space/uranos/net/packet/play/SpawnPaintingPacketCodec.kt b/uranos-packet-codecs/src/main/kotlin/space/uranos/net/packet/play/SpawnPaintingPacketCodec.kt index 1f411b2..5a7f954 100644 --- a/uranos-packet-codecs/src/main/kotlin/space/uranos/net/packet/play/SpawnPaintingPacketCodec.kt +++ b/uranos-packet-codecs/src/main/kotlin/space/uranos/net/packet/play/SpawnPaintingPacketCodec.kt @@ -7,8 +7,8 @@ package space.uranos.net.packet.play import io.netty.buffer.ByteBuf import space.uranos.CardinalDirection +import space.uranos.PaintingMotive import space.uranos.entity.PaintingEntity -import space.uranos.entity.PaintingMotive import space.uranos.net.MinecraftProtocolDataTypes.writeUUID import space.uranos.net.MinecraftProtocolDataTypes.writeVarInt import space.uranos.net.MinecraftProtocolDataTypes.writeVoxelLocation diff --git a/uranos-packets/src/main/kotlin/space/uranos/net/packet/play/SpawnPaintingPacket.kt b/uranos-packets/src/main/kotlin/space/uranos/net/packet/play/SpawnPaintingPacket.kt index be7f9cc..b9debb8 100644 --- a/uranos-packets/src/main/kotlin/space/uranos/net/packet/play/SpawnPaintingPacket.kt +++ b/uranos-packets/src/main/kotlin/space/uranos/net/packet/play/SpawnPaintingPacket.kt @@ -6,8 +6,7 @@ package space.uranos.net.packet.play import space.uranos.CardinalDirection -import space.uranos.Location -import space.uranos.entity.PaintingMotive +import space.uranos.PaintingMotive import space.uranos.net.packet.OutgoingPacket import space.uranos.world.VoxelLocation import java.util.* diff --git a/uranos-server/src/main/kotlin/space/uranos/UranosServer.kt b/uranos-server/src/main/kotlin/space/uranos/UranosServer.kt index 49bddbd..88e1b62 100644 --- a/uranos-server/src/main/kotlin/space/uranos/UranosServer.kt +++ b/uranos-server/src/main/kotlin/space/uranos/UranosServer.kt @@ -125,6 +125,7 @@ class UranosServer internal constructor() : Server() { private fun startDataStorageTicking() { scheduler.executeRepeating(1, 0) { players.forEach { it.dataStorage.tick() } + entities.forEach { it.dataStorage.tick() } } } diff --git a/uranos-server/src/main/kotlin/space/uranos/net/packet/play/IncomingPlayerPositionPacketHandler.kt b/uranos-server/src/main/kotlin/space/uranos/net/packet/play/IncomingPlayerPositionPacketHandler.kt new file mode 100644 index 0000000..efd39b6 --- /dev/null +++ b/uranos-server/src/main/kotlin/space/uranos/net/packet/play/IncomingPlayerPositionPacketHandler.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2020-2021 Moritz Ruth and Uranos contributors + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file + */ + +package space.uranos.net.packet.play + +import space.uranos.net.PacketReceivedEventHandler +import space.uranos.net.UranosSession + +object IncomingPlayerPositionPacketHandler : PacketReceivedEventHandler() { + override suspend fun handle(session: UranosSession, packet: IncomingPlayerPositionPacket) { + session.player!!.entity.position = packet.position + } +} diff --git a/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayProtocolHandler.kt b/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayProtocolHandler.kt index 02ec62e..4ed3774 100644 --- a/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayProtocolHandler.kt +++ b/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayProtocolHandler.kt @@ -11,7 +11,10 @@ import space.uranos.net.ProtocolPacketReceivedEventHandler object PlayProtocolHandler : ProtocolPacketReceivedEventHandler( mapOf( ClientSettingsPacket::class to ClientSettingsPacketHandler, + IncomingKeepAlivePacket::class to IncomingKeepAlivePacketHandler, + IncomingPlayerPositionPacket::class to IncomingPlayerPositionPacketHandler, IncomingPluginMessagePacket::class to IncomingPluginMessagePacketHandler, - IncomingKeepAlivePacket::class to IncomingKeepAlivePacketHandler + PlayerOrientationPacket::class to PlayerOrientationPacketHandler, + PlayerLocationPacket::class to PlayerLocationPacketHandler ) ) diff --git a/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayerLocationPacketHandler.kt b/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayerLocationPacketHandler.kt new file mode 100644 index 0000000..7e97ad9 --- /dev/null +++ b/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayerLocationPacketHandler.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2020-2021 Moritz Ruth and Uranos contributors + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file + */ + +package space.uranos.net.packet.play + +import space.uranos.net.PacketReceivedEventHandler +import space.uranos.net.UranosSession + +object PlayerLocationPacketHandler : PacketReceivedEventHandler() { + override suspend fun handle(session: UranosSession, packet: PlayerLocationPacket) { + val player = session.player!! + player.entity.position = player.entity.position.copy( + x = packet.location.x, + y = packet.location.y, + z = packet.location.z + ) + } +} diff --git a/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayerOrientationPacketHandler.kt b/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayerOrientationPacketHandler.kt new file mode 100644 index 0000000..e03fd87 --- /dev/null +++ b/uranos-server/src/main/kotlin/space/uranos/net/packet/play/PlayerOrientationPacketHandler.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2020-2021 Moritz Ruth and Uranos contributors + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file + */ + +package space.uranos.net.packet.play + +import space.uranos.net.PacketReceivedEventHandler +import space.uranos.net.UranosSession + +object PlayerOrientationPacketHandler : PacketReceivedEventHandler() { + override suspend fun handle(session: UranosSession, packet: PlayerOrientationPacket) { + val player = session.player!! + player.entity.position = player.entity.position.copy(yaw = packet.yaw, pitch = packet.pitch) + } +} diff --git a/uranos-server/src/main/kotlin/space/uranos/player/UranosPlayer.kt b/uranos-server/src/main/kotlin/space/uranos/player/UranosPlayer.kt index b8e0c4d..70b8a0b 100644 --- a/uranos-server/src/main/kotlin/space/uranos/player/UranosPlayer.kt +++ b/uranos-server/src/main/kotlin/space/uranos/player/UranosPlayer.kt @@ -70,6 +70,7 @@ class UranosPlayer( init { this.selectedHotbarSlot = selectedHotbarSlot + this.playerListName = null } override var currentlyViewedChunks = emptyList()