network: store items in future containers before opening it

This commit is contained in:
Bixilon 2022-02-23 22:14:48 +01:00
parent e6b3f81a76
commit 0d4acf15f4
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
8 changed files with 47 additions and 115 deletions

View File

@ -16,6 +16,7 @@ import de.bixilon.kutil.cast.CastUtil.nullCast
import de.bixilon.kutil.collections.CollectionUtil.synchronizedBiMapOf
import de.bixilon.kutil.collections.CollectionUtil.synchronizedMapOf
import de.bixilon.kutil.collections.map.LockMap
import de.bixilon.kutil.collections.map.SynchronizedMap
import de.bixilon.kutil.collections.map.bi.SynchronizedBiMap
import de.bixilon.kutil.math.MMath.clamp
import de.bixilon.kutil.math.MMath.floor
@ -85,6 +86,7 @@ class LocalPlayerEntity(
val baseAbilities = Abilities()
val inventory = PlayerInventory(connection)
val incompleteContainers: SynchronizedMap<Int, SynchronizedMap<Int, ItemStack>> = synchronizedMapOf()
val containers: SynchronizedBiMap<Int, Container> = synchronizedBiMapOf(
ProtocolDefinition.PLAYER_CONTAINER_ID to inventory,
)

View File

@ -1,35 +0,0 @@
/*
* 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.modding.event.events.container
import de.bixilon.minosoft.modding.event.EventInitiators
import de.bixilon.minosoft.modding.event.events.CancelableEvent
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.c2s.play.container.CloseContainerC2SP
import de.bixilon.minosoft.protocol.packets.s2c.play.container.CloseContainerS2CP
/**
* Fired when an container (inventory, window, whatever) closes
*/
class ContainerCloseEvent(
connection: PlayConnection,
initiator: EventInitiators,
val containerId: Int,
) : PlayConnectionEvent(connection, initiator), CancelableEvent {
constructor(connection: PlayConnection, packet: CloseContainerS2CP) : this(connection, EventInitiators.SERVER, packet.containerId)
constructor(connection: PlayConnection, packet: CloseContainerC2SP) : this(connection, EventInitiators.CLIENT, packet.containerId)
}

View File

@ -1,25 +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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.modding.event.events.container
import de.bixilon.minosoft.data.registries.other.containers.Container
import de.bixilon.minosoft.modding.event.EventInitiators
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
class ContainerRevisionChangeEvent(
connection: PlayConnection,
initiator: EventInitiators,
val container: Container,
val revision: Long,
) : PlayConnectionEvent(connection, initiator)

View File

@ -1,31 +0,0 @@
/*
* 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.modding.event.events.container
import de.bixilon.minosoft.data.inventory.stack.ItemStack
import de.bixilon.minosoft.data.registries.other.containers.Container
import de.bixilon.minosoft.modding.event.EventInitiators
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.s2c.play.container.ContainerItemS2CP
class ContainerSlotChangeEvent(
connection: PlayConnection,
initiator: EventInitiators,
val container: Container,
val slot: Int,
val itemStack: ItemStack?,
) : PlayConnectionEvent(connection, initiator) {
constructor(connection: PlayConnection, packet: ContainerItemS2CP) : this(connection, EventInitiators.SERVER, connection.player.containers[packet.containerId]!!, packet.slot, packet.itemStack)
}

View File

@ -12,12 +12,10 @@
*/
package de.bixilon.minosoft.protocol.packets.s2c.play.container
import de.bixilon.minosoft.modding.event.events.container.ContainerCloseEvent
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
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType
@ -27,16 +25,8 @@ class CloseContainerS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
val containerId: Int = buffer.readUnsignedByte()
override fun handle(connection: PlayConnection) {
val event = ContainerCloseEvent(connection, this)
if (connection.fireEvent(event)) {
return
}
if (containerId == ProtocolDefinition.PLAYER_CONTAINER_ID) {
return
}
connection.player.containers.remove(containerId)
connection.player.containers[containerId]?.onClose()
// ToDo: Send event to gui
}
override fun log(reducedLog: Boolean) {

View File

@ -12,7 +12,7 @@
*/
package de.bixilon.minosoft.protocol.packets.s2c.play.container
import de.bixilon.minosoft.modding.event.events.container.ContainerSlotChangeEvent
import de.bixilon.kutil.collections.CollectionUtil.synchronizedMapOf
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
@ -34,10 +34,19 @@ class ContainerItemS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
val itemStack = buffer.readItemStack()
override fun handle(connection: PlayConnection) {
connection.player.containers[containerId]?.set(slot, itemStack)
val container = connection.player.containers[containerId]
// ToDo: Check for changes
connection.fireEvent(ContainerSlotChangeEvent(connection, this))
if (container == null) {
val slots = connection.player.incompleteContainers.synchronizedGetOrPut(containerId) { synchronizedMapOf() }
if (itemStack == null) {
slots -= slot
} else {
slots[slot] = itemStack
}
return
}
container[slot] = itemStack
container.serverRevision = revision
}
override fun log(reducedLog: Boolean) {

View File

@ -12,9 +12,9 @@
*/
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.minosoft.data.inventory.stack.ItemStack
import de.bixilon.minosoft.modding.event.EventInitiators
import de.bixilon.minosoft.modding.event.events.container.ContainerSlotChangeEvent
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
@ -44,12 +44,26 @@ class ContainerItemsS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
}
override fun handle(connection: PlayConnection) {
connection.player.containers[containerId]?.let { container ->
container.clear()
for ((slot, itemStack) in items.withIndex()) {
itemStack?.let { container[slot] = itemStack }
connection.fireEvent(ContainerSlotChangeEvent(connection, EventInitiators.SERVER, container, slot, itemStack))
val container = connection.player.containers[containerId]
val slots = if (container == null) {
synchronizedMapOf()
} else {
container.lock.lock()
container.slots.clear()
container.slots
}
for ((slotId, stack) in this.items.withIndex()) {
if (stack == null) {
continue
}
slots[slotId] = stack
}
if (container == null) {
connection.player.incompleteContainers[containerId] = slots.unsafeCast()
} else {
container.lock.unlock()
}
}

View File

@ -69,12 +69,20 @@ class OpenContainerS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
if (containerId == ProtocolDefinition.PLAYER_CONTAINER_ID) {
return
}
connection.player.containers[containerId] = Container(
// ToDo: Container factories instead of generic container
val container = Container(
connection,
containerType,
title,
hasTitle,
)
connection.player.incompleteContainers.remove(containerId)?.let {
for ((slot, stack) in it) {
container[slot] = stack
}
}
connection.player.containers[containerId] = container
// ToDo: Open GUI
}
override fun log(reducedLog: Boolean) {