diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt index 59189fe10..6872ace4d 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt @@ -47,8 +47,7 @@ abstract class Entity( var entityMetaData: EntityMetaData = EntityMetaData(connection) - @JvmField - protected var hasCollisions = true + protected open val hasCollisions = true fun forceMove(relativePosition: Vec3) { position = position + relativePosition diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt index 8ee433ad2..ca65d6f22 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt @@ -13,7 +13,6 @@ package de.bixilon.minosoft.data.entities.entities.player import de.bixilon.minosoft.data.Gamemodes -import de.bixilon.minosoft.data.PlayerPropertyData import de.bixilon.minosoft.data.entities.EntityMetaDataFields import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.data.entities.entities.EntityMetaDataFunction @@ -22,32 +21,33 @@ import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.entities.EntityFactory import de.bixilon.minosoft.data.mappings.entities.EntityType import de.bixilon.minosoft.data.player.Hands +import de.bixilon.minosoft.data.player.PlayerProperties +import de.bixilon.minosoft.data.player.PlayerProperty +import de.bixilon.minosoft.data.player.tab.TabListItem import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.util.nbt.tag.CompoundTag import glm_.vec3.Vec3 -import java.util.* class PlayerEntity( connection: PlayConnection, entityType: EntityType, - position: Vec3, - rotation: EntityRotation, - @get:EntityMetaDataFunction(name = "Name") var name: String, - @get:EntityMetaDataFunction(name = "uuid") var uuid: UUID, - @get:EntityMetaDataFunction(name = "Properties") val properties: HashSet?, - gamemode: Gamemodes, + position: Vec3 = Vec3(0, 0, 0), + rotation: EntityRotation = EntityRotation(0.0, 0.0), + name: String = "TBA", + properties: Map = mapOf(), + var tabListItem: TabListItem = TabListItem(name = name, gamemode = Gamemodes.SURVIVAL, properties = properties), ) : LivingEntity(connection, entityType, position, rotation) { - private var _gamemode: Gamemodes = gamemode - var gamemode: Gamemodes - get() = _gamemode - set(value) { - hasCollisions = value != Gamemodes.SPECTATOR - _gamemode = value - } - init { - hasCollisions = gamemode != Gamemodes.SPECTATOR - } + @get:EntityMetaDataFunction(name = "Gamemode") + val gamemode: Gamemodes + get() = tabListItem.gamemode + + @get:EntityMetaDataFunction(name = "name") + val name: String + get() = tabListItem.name + + override val hasCollisions: Boolean + get() = gamemode != Gamemodes.SPECTATOR @get:EntityMetaDataFunction(name = "Absorption hearts") val playerAbsorptionHearts: Float diff --git a/src/main/java/de/bixilon/minosoft/data/player/Player.kt b/src/main/java/de/bixilon/minosoft/data/player/Player.kt index 4514cc9cb..9b78a2db6 100644 --- a/src/main/java/de/bixilon/minosoft/data/player/Player.kt +++ b/src/main/java/de/bixilon/minosoft/data/player/Player.kt @@ -12,7 +12,6 @@ */ package de.bixilon.minosoft.data.player -import de.bixilon.minosoft.data.Gamemodes import de.bixilon.minosoft.data.accounts.Account import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity @@ -28,7 +27,7 @@ class Player( val experienceCondition = PlayerExperienceCondition() val inventoryManager = PlayerInventoryManager() var spawnPosition: Vec3i = VecUtil.EMPTY_VEC3I - val entity: PlayerEntity = PlayerEntity(connection, connection.mapping.entityRegistry.get(PlayerEntity.RESOURCE_LOCATION)!!, VecUtil.EMPTY_VEC3, EntityRotation(0.0, 0.0), account.username, account.uuid, null, Gamemodes.SPECTATOR) + val entity: PlayerEntity = PlayerEntity(connection, connection.mapping.entityRegistry.get(PlayerEntity.RESOURCE_LOCATION)!!, VecUtil.EMPTY_VEC3, EntityRotation(0.0, 0.0), account.username) @Deprecated(message = "Will be replaced with some kind of teleport manager, ...") var isSpawnConfirmed = false diff --git a/src/main/java/de/bixilon/minosoft/data/player/tab/TabListItem.kt b/src/main/java/de/bixilon/minosoft/data/player/tab/TabListItem.kt index ddcd9eb42..3a3f67b5a 100644 --- a/src/main/java/de/bixilon/minosoft/data/player/tab/TabListItem.kt +++ b/src/main/java/de/bixilon/minosoft/data/player/tab/TabListItem.kt @@ -27,9 +27,14 @@ data class TabListItem( ) { fun merge(data: TabListItemData) { + specialMerge(data) + data.gamemode?.let { gamemode = it } + } + + fun specialMerge(data: TabListItemData) { data.name?.let { name = it } data.ping?.let { ping = it } - data.gamemode?.let { gamemode = it } + data.hasDisplayName?.let { displayName = if (it) { data.displayName!! diff --git a/src/main/java/de/bixilon/minosoft/data/world/World.kt b/src/main/java/de/bixilon/minosoft/data/world/World.kt index 4f5f77bfb..481f7cb82 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/World.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/World.kt @@ -80,8 +80,8 @@ class World : BiomeAccessor { } } - fun addEntity(entityId: Int, entityUUID: UUID?, entity: Entity) { - entityIdMap[entityId] = entity + fun addEntity(entityId: Int?, entityUUID: UUID?, entity: Entity) { + entityId?.let { entityIdMap[it] = entity } entityUUID?.let { entityUUIDMap[it] = entity } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/login/PacketLoginSuccess.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/login/PacketLoginSuccess.java index b1adc7e87..30fe085c4 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/login/PacketLoginSuccess.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/login/PacketLoginSuccess.java @@ -13,6 +13,7 @@ package de.bixilon.minosoft.protocol.packets.clientbound.login; +import de.bixilon.minosoft.data.text.ChatComponent; import de.bixilon.minosoft.protocol.network.connection.PlayConnection; import de.bixilon.minosoft.protocol.packets.clientbound.PlayClientboundPacket; import de.bixilon.minosoft.protocol.protocol.ConnectionStates; @@ -41,8 +42,11 @@ public class PacketLoginSuccess extends PlayClientboundPacket { public void handle(PlayConnection connection) { connection.setConnectionState(ConnectionStates.PLAY); - connection.getPlayer().getEntity().setUuid(getUUID()); - connection.getPlayer().getEntity().setName(getPlayerName()); + var playerEntity = connection.getPlayer().getEntity(); + playerEntity.getTabListItem().setName(this.playerName); + playerEntity.getTabListItem().setDisplayName(ChatComponent.valueOf(this.playerName)); + + connection.getWorld().addEntity(null, this.uuid, playerEntity); } @Override diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChangeGameState.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChangeGameState.java index c8c840131..ad562b616 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChangeGameState.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChangeGameState.java @@ -51,7 +51,7 @@ public class PacketChangeGameState extends PlayClientboundPacket { switch (getReason()) { case STOP_RAINING -> connection.getWorld().setRaining(false); case START_RAINING -> connection.getWorld().setRaining(true); - case CHANGE_GAMEMODE -> connection.getPlayer().getEntity().setGamemode(Gamemodes.byId(getIntValue())); + case CHANGE_GAMEMODE -> connection.getPlayer().getEntity().getTabListItem().setGamemode(Gamemodes.byId(getIntValue())); } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketJoinGame.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketJoinGame.kt index 4f5dab1ad..f5d8b2025 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketJoinGame.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketJoinGame.kt @@ -138,13 +138,13 @@ class PacketJoinGame(buffer: PlayInByteBuffer) : PlayClientboundPacket() { return } val playerEntity = connection.player.entity - playerEntity.gamemode = gamemode + playerEntity.tabListItem.gamemode = gamemode connection.world.isHardcore = isHardcore connection.mapping.dimensionRegistry.setData(dimensions) connection.world.dimension = dimension - connection.world.addEntity(entityId, connection.player.entity.uuid, playerEntity) + connection.world.addEntity(entityId, null, playerEntity) connection.world.hashedSeed = hashedSeed connection.world.biomeAccessor = if (connection.version.versionId < ProtocolVersions.V_19W36A) { BlockBiomeAccessor(connection.world) @@ -183,7 +183,7 @@ class PacketJoinGame(buffer: PlayInByteBuffer) : PlayClientboundPacket() { } override fun log() { - Log.protocol("[IN] Receiving join game packet (entityId=$entityId, gamemode=$gamemode, dimension=$dimensions, difficulty=$difficulty, hardcore=$isHardcore, viewDistance=$viewDistance)") + Log.protocol("[IN] Receiving join game packet (entityId=$entityId, gamemode=$gamemode, dimension=$dimension, difficulty=$difficulty, hardcore=$isHardcore, viewDistance=$viewDistance)") } companion object : ErrorHandler { diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketPlayerPositionAndRotation.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketPlayerPositionAndRotation.java index ee6862564..4939b129f 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketPlayerPositionAndRotation.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketPlayerPositionAndRotation.java @@ -63,7 +63,7 @@ public class PacketPlayerPositionAndRotation extends PlayClientboundPacket { @Override public void log() { - Log.protocol(String.format("[IN] Received player location: (position=%s, rotation=%s, onGround=%b)", this.position, this.rotation, this.onGround)); + Log.protocol(String.format("[IN] Received player position (position=%s, rotation=%s, onGround=%b)", this.position, this.rotation, this.onGround)); } public Vec3 getPosition() { diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketRespawn.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketRespawn.kt index c10791f5f..7aa46f84d 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketRespawn.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketRespawn.kt @@ -91,7 +91,7 @@ class PacketRespawn(buffer: PlayInByteBuffer) : PlayClientboundPacket() { connection.world.chunks.clear() connection.world.dimension = dimension connection.player.isSpawnConfirmed = false - connection.player.entity.gamemode = gamemode + connection.player.entity.tabListItem.gamemode = gamemode connection.renderer?.renderWindow?.worldRenderer?.clearChunkCache() } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnPlayer.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnPlayer.java deleted file mode 100644 index ca0e8f4c4..000000000 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnPlayer.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program.If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.protocol.packets.clientbound.play; - -import de.bixilon.minosoft.config.StaticConfiguration; -import de.bixilon.minosoft.data.Gamemodes; -import de.bixilon.minosoft.data.PlayerPropertyData; -import de.bixilon.minosoft.data.entities.EntityRotation; -import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity; -import de.bixilon.minosoft.data.entities.meta.EntityMetaData; -import de.bixilon.minosoft.modding.event.events.EntitySpawnEvent; -import de.bixilon.minosoft.protocol.network.connection.PlayConnection; -import de.bixilon.minosoft.protocol.packets.clientbound.PlayClientboundPacket; -import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer; -import de.bixilon.minosoft.util.logging.Log; -import glm_.vec3.Vec3; - -import java.util.HashSet; -import java.util.UUID; - -import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*; - -public class PacketSpawnPlayer extends PlayClientboundPacket { - private final int entityId; - private final UUID entityUUID; - private final PlayerEntity entity; - - public PacketSpawnPlayer(PlayInByteBuffer buffer) { - this.entityId = buffer.readVarInt(); - String name = "TBA"; - HashSet properties = null; - if (buffer.getVersionId() < V_14W21A) { - name = buffer.readString(); - this.entityUUID = UUID.fromString(buffer.readString()); - properties = new HashSet<>(); - int length = buffer.readVarInt(); - for (int i = 0; i < length; i++) { - properties.add(new PlayerPropertyData(buffer.readString(), buffer.readString(), buffer.readString())); - } - } else { - this.entityUUID = buffer.readUUID(); - } - Vec3 position; - if (buffer.getVersionId() < V_16W06A) { - position = new Vec3(buffer.readFixedPointNumberInt(), buffer.readFixedPointNumberInt(), buffer.readFixedPointNumberInt()); - } else { - position = buffer.readEntityPosition(); - } - short yaw = buffer.readAngle(); - short pitch = buffer.readAngle(); - - if (buffer.getVersionId() < V_15W31A) { - buffer.getConnection().getMapping().getItemRegistry().get(buffer.readUnsignedShort()); // current item - } - EntityMetaData metaData = null; - if (buffer.getVersionId() < V_19W34A) { - metaData = buffer.readMetaData(); - } - this.entity = new PlayerEntity(buffer.getConnection(), buffer.getConnection().getMapping().getEntityRegistry().get(PlayerEntity.Companion.getRESOURCE_LOCATION()), position, new EntityRotation(yaw, pitch, 0), name, this.entityUUID, properties, Gamemodes.CREATIVE); // ToDo - if (metaData != null) { - this.entity.setEntityMetaData(metaData); - if (StaticConfiguration.VERBOSE_ENTITY_META_DATA_LOGGING) { - Log.verbose(String.format("Metadata of entity %s (entityId=%d): %s", this.entity.toString(), this.entityId, this.entity.getEntityMetaDataAsString())); - } - } - } - - @Override - public void handle(PlayConnection connection) { - connection.fireEvent(new EntitySpawnEvent(connection, this)); - - connection.getWorld().addEntity(this.entityId, this.entityUUID, this.entity); - } - - @Override - public void log() { - Log.protocol(String.format("[IN] Player spawned at %s (entityId=%d, name=%s, uuid=%s)", this.entity.getPosition(), this.entityId, this.entity.getName(), this.entity.getUuid())); - } - - public PlayerEntity getEntity() { - return this.entity; - } - -} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnPlayer.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnPlayer.kt new file mode 100644 index 000000000..e21fde4fd --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnPlayer.kt @@ -0,0 +1,94 @@ +/* + * Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program.If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ +package de.bixilon.minosoft.protocol.packets.clientbound.play + +import de.bixilon.minosoft.config.StaticConfiguration +import de.bixilon.minosoft.data.PlayerPropertyData +import de.bixilon.minosoft.data.entities.EntityRotation +import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity +import de.bixilon.minosoft.data.entities.meta.EntityMetaData +import de.bixilon.minosoft.modding.event.events.EntitySpawnEvent +import de.bixilon.minosoft.protocol.network.connection.PlayConnection +import de.bixilon.minosoft.protocol.packets.clientbound.PlayClientboundPacket +import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer +import de.bixilon.minosoft.protocol.protocol.ProtocolVersions +import de.bixilon.minosoft.util.Util +import de.bixilon.minosoft.util.logging.Log +import glm_.vec3.Vec3 +import java.util.* + +class PacketSpawnPlayer(buffer: PlayInByteBuffer) : PlayClientboundPacket() { + private val entityId: Int + private var entityUUID: UUID? = null + val entity: PlayerEntity + + init { + entityId = buffer.readVarInt() + var name = "TBA" + + val properties: MutableSet = mutableSetOf() + if (buffer.versionId < ProtocolVersions.V_14W21A) { + name = buffer.readString() + entityUUID = Util.getUUIDFromString(buffer.readString()) + val length = buffer.readVarInt() + for (i in 0 until length) { + properties.add(PlayerPropertyData(buffer.readString(), buffer.readString(), buffer.readString())) + } + } else { + entityUUID = buffer.readUUID() + } + + val position: Vec3 = if (buffer.versionId < ProtocolVersions.V_16W06A) { + Vec3(buffer.readFixedPointNumberInt(), buffer.readFixedPointNumberInt(), buffer.readFixedPointNumberInt()) + } else { + buffer.readEntityPosition() + } + + val yaw = buffer.readAngle() + val pitch = buffer.readAngle() + if (buffer.versionId < ProtocolVersions.V_15W31A) { + buffer.connection.mapping.itemRegistry.get(buffer.readUnsignedShort()) // current item + } + + var metaData: EntityMetaData? = null + if (buffer.versionId < ProtocolVersions.V_19W34A) { + metaData = buffer.readMetaData() + } + entity = PlayerEntity( + connection = buffer.connection, + entityType = buffer.connection.mapping.entityRegistry.get(PlayerEntity.RESOURCE_LOCATION)!!, + position = position, + rotation = EntityRotation(yaw.toFloat(), pitch.toFloat(), 0.0f), + name = name, + // ToDo: properties = properties, + ) + + if (metaData != null) { + entity.entityMetaData = metaData + if (StaticConfiguration.VERBOSE_ENTITY_META_DATA_LOGGING) { + Log.verbose(String.format("Metadata of entity %s (entityId=%d): %s", entity.toString(), entityId, entity.entityMetaDataAsString)) + } + } + } + + override fun handle(connection: PlayConnection) { + connection.tabList.tabListItems[entityUUID]?.let { entity.tabListItem = it } + + connection.fireEvent(EntitySpawnEvent(connection, this)) + connection.world.addEntity(entityId, entityUUID, entity) + } + + override fun log() { + Log.protocol("[IN] Player spawned at (position=${entity.position}, entityId=$entityId, name=${entity.name}, uuid=$entityUUID)") + } +} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketTabListItem.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketTabListItem.kt index b7ae5ca47..df37c6d34 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketTabListItem.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketTabListItem.kt @@ -13,6 +13,7 @@ package de.bixilon.minosoft.protocol.packets.clientbound.play import de.bixilon.minosoft.data.Gamemodes +import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity import de.bixilon.minosoft.data.player.PlayerProperties import de.bixilon.minosoft.data.player.PlayerProperty import de.bixilon.minosoft.data.player.tab.TabListItem @@ -118,6 +119,7 @@ class PacketTabListItem(buffer: PlayInByteBuffer) : PlayClientboundPacket() { } for ((uuid, data) in items) { // legacy + if (connection.version.versionId < ProtocolVersions.V_14W19A) { // ToDo: 19? val item: TabListItem = if (data.remove) { // add or remove @@ -141,6 +143,10 @@ class PacketTabListItem(buffer: PlayInByteBuffer) : PlayClientboundPacket() { connection.tabList.tabListItems.remove(uuid) continue } + + val entity = connection.world.getEntity(uuid) + + val tabListItem = connection.tabList.tabListItems[uuid] ?: run { if (data.name == null) { // item not yet created @@ -151,7 +157,18 @@ class PacketTabListItem(buffer: PlayInByteBuffer) : PlayClientboundPacket() { item } ?: continue + + if (entity === connection.player.entity) { + entity.tabListItem.specialMerge(data) + continue + } + tabListItem.merge(data) + if (entity == null || entity !is PlayerEntity) { + continue + } + + entity.tabListItem = tabListItem } }