network: allow setting floating item

This commit is contained in:
Bixilon 2022-11-20 21:36:29 +01:00
parent bbd623ea5f
commit 9d1a5bf104
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
5 changed files with 51 additions and 18 deletions

View File

@ -0,0 +1,23 @@
/*
* Minosoft
* Copyright (C) 2020-2022 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.data.container
import de.bixilon.kutil.collections.CollectionUtil.synchronizedMapOf
import de.bixilon.kutil.collections.map.SynchronizedMap
import de.bixilon.minosoft.data.container.stack.ItemStack
class IncompleteContainer() {
val slots: SynchronizedMap<Int, ItemStack> = synchronizedMapOf()
var floating: ItemStack? = null
}

View File

@ -37,6 +37,7 @@ import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.abilities.ItemCooldown
import de.bixilon.minosoft.data.accounts.Account
import de.bixilon.minosoft.data.container.Container
import de.bixilon.minosoft.data.container.IncompleteContainer
import de.bixilon.minosoft.data.container.InventorySlots
import de.bixilon.minosoft.data.container.stack.ItemStack
import de.bixilon.minosoft.data.container.types.PlayerInventory
@ -92,7 +93,7 @@ class LocalPlayerEntity(
val baseAbilities = Abilities()
val inventory = PlayerInventory(connection)
val incompleteContainers: SynchronizedMap<Int, SynchronizedMap<Int, ItemStack>> = synchronizedMapOf()
val incompleteContainers: SynchronizedMap<Int, IncompleteContainer> = synchronizedMapOf()
val containers: SynchronizedBiMap<Int, Container> = synchronizedBiMapOf(
ProtocolDefinition.PLAYER_CONTAINER_ID to inventory,
)

View File

@ -12,7 +12,7 @@
*/
package de.bixilon.minosoft.protocol.packets.s2c.play.container
import de.bixilon.kutil.collections.CollectionUtil.synchronizedMapOf
import de.bixilon.minosoft.data.container.IncompleteContainer
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.factory.LoadPacket
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
@ -30,22 +30,29 @@ class ContainerItemS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
} else {
-1
}
val slot = buffer.readUnsignedShort()
val slot = buffer.readShort().toInt()
val itemStack = buffer.readItemStack()
override fun handle(connection: PlayConnection) {
val container = connection.player.containers[containerId]
if (container == null) {
val slots = connection.player.incompleteContainers.synchronizedGetOrPut(containerId) { synchronizedMapOf() }
if (itemStack == null) {
slots -= slot
val incomplete = connection.player.incompleteContainers.synchronizedGetOrPut(containerId) { IncompleteContainer() }
if (slot < 0) {
incomplete.floating = itemStack
} else if (itemStack == null) {
incomplete.slots -= slot
} else {
slots[slot] = itemStack
incomplete.slots[slot] = itemStack
}
return
}
container[slot] = itemStack
if (slot < 0) {
container.floatingItem = itemStack
} else {
container[slot] = itemStack
}
container.serverRevision = revision
}

View File

@ -12,10 +12,8 @@
*/
package de.bixilon.minosoft.protocol.packets.s2c.play.container
import de.bixilon.kutil.cast.CastUtil.unsafeCast
import de.bixilon.kutil.collections.CollectionUtil.synchronizedMapOf
import de.bixilon.kutil.collections.map.SynchronizedMap
import de.bixilon.minosoft.data.container.Container
import de.bixilon.minosoft.data.container.IncompleteContainer
import de.bixilon.minosoft.data.container.stack.ItemStack
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.factory.LoadPacket
@ -25,6 +23,7 @@ import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_1_17_1_PRE1
import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType
import java.util.*
@LoadPacket
class ContainerItemsS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
@ -41,24 +40,25 @@ class ContainerItemsS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
buffer.readUnsignedShort()
}
) { buffer.readItemStack() }
val cursor = if (buffer.versionId >= V_1_17_1_PRE1) {
buffer.readItemStack()
val floatingItem = if (buffer.versionId >= V_1_17_1_PRE1) {
buffer.readItemStack()?.let { Optional.of(it) } ?: Optional.empty()
} else {
null
}
private fun pushIncompleteContainer(connection: PlayConnection) {
val slots: SynchronizedMap<Int, ItemStack> = synchronizedMapOf()
val container = IncompleteContainer()
for ((slotId, stack) in this.items.withIndex()) {
if (stack == null) {
continue
}
slots[slotId] = stack
container.slots[slotId] = stack
}
container.floating = floatingItem?.let { if (it.isEmpty) null else it.get() }
connection.player.incompleteContainers[containerId] = slots.unsafeCast()
connection.player.incompleteContainers[containerId] = container
}
private fun updateContainer(container: Container) {
@ -72,6 +72,7 @@ class ContainerItemsS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
container._set(slotId, stack)
}
container.serverRevision = revision
this.floatingItem?.let { container.floatingItem = if (it.isEmpty) null else it.get() }
container.lock.unlock()
container.revision++
}
@ -86,6 +87,6 @@ class ContainerItemsS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
}
override fun log(reducedLog: Boolean) {
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Container items (containerId=$containerId, items=${items.contentToString()}" }
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Container items (containerId=$containerId, items=${items.contentToString()}, floating=$floatingItem)" }
}
}

View File

@ -73,9 +73,10 @@ class OpenContainerS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
val container = containerType.factory.build(connection, containerType, title)
connection.player.incompleteContainers.remove(containerId)?.let {
for ((slot, stack) in it) {
for ((slot, stack) in it.slots) {
container[slot] = stack
}
container.floatingItem = it.floating
}
connection.player.containers[containerId] = container
connection.player.openedContainer = container