mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 03:15:35 -04:00
container: simple action
This commit is contained in:
parent
a5f8e2cddc
commit
21a3769c3c
@ -14,6 +14,8 @@
|
||||
package de.bixilon.minosoft.data.inventory.click
|
||||
|
||||
@Deprecated("ToDo")
|
||||
class FastMoveContainerAction : ContainerAction {
|
||||
class FastMoveContainerAction(
|
||||
val slot: Int,
|
||||
) : ContainerAction {
|
||||
private val mode: Int get() = 1
|
||||
}
|
||||
|
@ -13,19 +13,77 @@
|
||||
|
||||
package de.bixilon.minosoft.data.inventory.click
|
||||
|
||||
@Deprecated("ToDo")
|
||||
import de.bixilon.minosoft.data.inventory.stack.ItemStack
|
||||
import de.bixilon.minosoft.data.registries.other.containers.Container
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.container.ContainerClickC2SP
|
||||
|
||||
class SimpleContainerAction(
|
||||
val slot: Int,
|
||||
val action: SimpleContainerActions,
|
||||
val slot: Int?,
|
||||
val count: ContainerCounts,
|
||||
) : ContainerAction {
|
||||
private val mode: Int get() = 0
|
||||
private val button: Int
|
||||
get() = action.ordinal
|
||||
get() = count.ordinal
|
||||
|
||||
private fun pickItem(connection: PlayConnection, containerId: Int, container: Container) {
|
||||
val item = container[slot ?: return] ?: return
|
||||
// ToDo: Check course of binding
|
||||
val previous = item.copy()
|
||||
val floatingItem: ItemStack
|
||||
if (count == ContainerCounts.ALL) {
|
||||
container.remove(slot)
|
||||
floatingItem = item
|
||||
} else {
|
||||
// half
|
||||
val stayCount = maxOf(item.item.count / 2, 1)
|
||||
item.item.count = stayCount
|
||||
floatingItem = previous.copy(count = previous.item.count - stayCount)
|
||||
}
|
||||
container.floatingItem = floatingItem
|
||||
connection.sendPacket(ContainerClickC2SP(containerId, container.serverRevision, slot, 0, count.ordinal, container.createAction(this), mapOf(slot to item), previous))
|
||||
}
|
||||
|
||||
enum class SimpleContainerActions {
|
||||
LEFT_MOUSE_CLICK,
|
||||
RIGHT_MOUSE_CLICK,
|
||||
private fun putItem(connection: PlayConnection, containerId: Int, container: Container, floatingItem: ItemStack) {
|
||||
floatingItem.lock()
|
||||
val target = container.slots[slot]
|
||||
try {
|
||||
if (count == ContainerCounts.ALL) {
|
||||
floatingItem.item._count = 0
|
||||
} else {
|
||||
floatingItem.item._count-- // don't use decrease, item + container is already locked
|
||||
}
|
||||
if (slot == null || target == null) {
|
||||
return connection.sendPacket(ContainerClickC2SP(containerId, container.serverRevision, null, 0, count.ordinal, container.createAction(this), mapOf(), null))
|
||||
}
|
||||
if (target.typeEquals(floatingItem)) {
|
||||
// merge
|
||||
val subtract = minOf(target.item.item.maxStackSize - target.item._count, floatingItem.item._count)
|
||||
target.item._count += subtract
|
||||
floatingItem.item._count -= subtract
|
||||
if (!floatingItem._valid) {
|
||||
container.floatingItem = null
|
||||
}
|
||||
return
|
||||
}
|
||||
// swap
|
||||
container.floatingItem = target
|
||||
container.slots[slot] = floatingItem
|
||||
} finally {
|
||||
floatingItem.commit()
|
||||
target?.lock() // lock to prevent exception
|
||||
target?.commit()
|
||||
}
|
||||
}
|
||||
|
||||
override fun invoke(connection: PlayConnection, containerId: Int, container: Container) {
|
||||
val floatingItem = container.floatingItem ?: return pickItem(connection, containerId, container)
|
||||
return putItem(connection, containerId, container, floatingItem)
|
||||
}
|
||||
|
||||
enum class ContainerCounts {
|
||||
ALL,
|
||||
PART,
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -186,6 +186,10 @@ class ItemStack {
|
||||
return Objects.hash(item, _display, _durability, _enchanting, _hide, _nbt)
|
||||
}
|
||||
|
||||
private fun _equals(other: ItemStack): Boolean {
|
||||
return _display == other._display && _durability == other._durability && _enchanting == other._enchanting && _hide == other._hide && _nbt == other._nbt
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is ItemStack) {
|
||||
return false
|
||||
@ -193,7 +197,14 @@ class ItemStack {
|
||||
if (other.hashCode() != this.hashCode()) {
|
||||
return false
|
||||
}
|
||||
return item == other.item && _display == other._display && _durability == other._durability && _enchanting == other._enchanting && _hide == other._hide && _nbt == other._nbt
|
||||
return item == other.item && _equals(other)
|
||||
}
|
||||
|
||||
fun typeEquals(other: ItemStack?): Boolean {
|
||||
if (other == null) {
|
||||
return false
|
||||
}
|
||||
return item.item == other.item.item && _equals(other)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
@ -17,13 +17,15 @@ import de.bixilon.kutil.collections.CollectionUtil.synchronizedBiMapOf
|
||||
import de.bixilon.kutil.collections.CollectionUtil.toSynchronizedMap
|
||||
import de.bixilon.kutil.collections.map.bi.SynchronizedBiMap
|
||||
import de.bixilon.kutil.concurrent.lock.SimpleLock
|
||||
import de.bixilon.kutil.watcher.DataWatcher.Companion.observe
|
||||
import de.bixilon.kutil.watcher.DataWatcher.Companion.watched
|
||||
import de.bixilon.kutil.watcher.map.MapDataWatcher
|
||||
import de.bixilon.kutil.watcher.map.MapDataWatcher.Companion.watchedMap
|
||||
import de.bixilon.minosoft.data.inventory.click.ContainerAction
|
||||
import de.bixilon.minosoft.data.inventory.stack.ItemStack
|
||||
import de.bixilon.minosoft.data.inventory.stack.property.HolderProperty
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.container.CloseContainerC2SP
|
||||
|
||||
open class Container(
|
||||
protected val connection: PlayConnection,
|
||||
@ -32,7 +34,7 @@ open class Container(
|
||||
val hasTitle: Boolean = false,
|
||||
) : Iterable<Map.Entry<Int, ItemStack>> {
|
||||
@Deprecated("Should not be accessed dirctly")
|
||||
val slots: MutableMap<Int, ItemStack> by MapDataWatcher.watchedMap(mutableMapOf())
|
||||
val slots: MutableMap<Int, ItemStack> by watchedMap(mutableMapOf())
|
||||
val lock = SimpleLock()
|
||||
var revision by watched(0L)
|
||||
var serverRevision = 0
|
||||
@ -40,6 +42,10 @@ open class Container(
|
||||
var actions: SynchronizedBiMap<Int, ContainerAction> = synchronizedBiMapOf()
|
||||
var floatingItem: ItemStack? by watched(null)
|
||||
|
||||
init {
|
||||
this::floatingItem.observe(this) { it?.holder?.container = this }
|
||||
}
|
||||
|
||||
fun _validate() {
|
||||
var itemsRemoved = 0
|
||||
for ((slot, itemStack) in slots.toSynchronizedMap()) {
|
||||
@ -175,6 +181,13 @@ open class Container(
|
||||
actions.remove(actionId)?.revert(connection, connection.player.containers.getKey(this) ?: return, this)
|
||||
}
|
||||
|
||||
fun onClose() {
|
||||
floatingItem = null // ToDo: Does not seem correct
|
||||
|
||||
// minecraft behavior, when opening the inventory an open packet is never sent, but a close is
|
||||
connection.sendPacket(CloseContainerC2SP(connection.player.containers.getKey(this) ?: return))
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<Map.Entry<Int, ItemStack>> {
|
||||
return slots.toSynchronizedMap().iterator()
|
||||
}
|
||||
|
@ -14,6 +14,10 @@
|
||||
package de.bixilon.minosoft.gui.rendering.gui.elements.items
|
||||
|
||||
import de.bixilon.kutil.watcher.map.MapDataWatcher.Companion.observeMap
|
||||
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||
import de.bixilon.minosoft.data.inventory.click.CloneContainerAction
|
||||
import de.bixilon.minosoft.data.inventory.click.FastMoveContainerAction
|
||||
import de.bixilon.minosoft.data.inventory.click.SimpleContainerAction
|
||||
import de.bixilon.minosoft.data.registries.other.containers.Container
|
||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.atlas.Vec2iBinding
|
||||
@ -21,6 +25,7 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||
import de.bixilon.minosoft.gui.rendering.gui.gui.AbstractLayout
|
||||
import de.bixilon.minosoft.gui.rendering.gui.gui.dragged.Dragged
|
||||
import de.bixilon.minosoft.gui.rendering.gui.gui.dragged.elements.item.FloatingItem
|
||||
import de.bixilon.minosoft.gui.rendering.gui.input.ModifierKeys
|
||||
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseActions
|
||||
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseButtons
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||
@ -28,6 +33,7 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.isGreater
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.isSmaller
|
||||
import de.bixilon.minosoft.util.delegate.RenderingDelegate.observeRendering
|
||||
import glm_.vec2.Vec2i
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||
|
||||
@ -73,6 +79,11 @@ class ContainerItemsElement(
|
||||
this._size = size
|
||||
|
||||
container::slots.observeMap(this) { update = true; }
|
||||
container::floatingItem.observeRendering(this) {
|
||||
this.floatingItem?.close()
|
||||
this.floatingItem = null
|
||||
this.floatingItem = FloatingItem(guiRenderer, it ?: return@observeRendering).apply { show() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||
@ -119,32 +130,29 @@ class ContainerItemsElement(
|
||||
}
|
||||
|
||||
override fun onMouseAction(position: Vec2i, button: MouseButtons, action: MouseActions): Boolean {
|
||||
// this is not in items element, because you can also click into "nothing"
|
||||
val consumed = super<AbstractLayout>.onMouseAction(position, button, action)
|
||||
if (action != MouseActions.PRESS || (button != MouseButtons.LEFT && button != MouseButtons.RIGHT)) {
|
||||
if (action != MouseActions.PRESS) {
|
||||
return consumed
|
||||
}
|
||||
|
||||
val shiftDown = guiRenderer.isKeyDown(ModifierKeys.SHIFT)
|
||||
val activeElement = activeElement
|
||||
val stack = activeElement?.stack
|
||||
val containerId = renderWindow.connection.player.containers.getKey(container) ?: return consumed
|
||||
var floatingItem = this.floatingItem
|
||||
if ((floatingItem != null && floatingItem.visible) || stack?._valid != true) {
|
||||
return consumed
|
||||
if (button == MouseButtons.MIDDLE) {
|
||||
if (guiRenderer.connection.player.gamemode != Gamemodes.CREATIVE) {
|
||||
return true
|
||||
}
|
||||
container.invokeAction(CloneContainerAction(activeElement?.slotId ?: return true))
|
||||
return true
|
||||
}
|
||||
if (button == MouseButtons.LEFT || button == MouseButtons.RIGHT) {
|
||||
container.invokeAction(if (shiftDown) {
|
||||
FastMoveContainerAction(activeElement?.slotId ?: return true)
|
||||
} else {
|
||||
SimpleContainerAction(activeElement?.slotId, if (button == MouseButtons.LEFT) SimpleContainerAction.ContainerCounts.ALL else SimpleContainerAction.ContainerCounts.PART)
|
||||
})
|
||||
return true
|
||||
}
|
||||
// val clickAction: ContainerClickActions
|
||||
// val stackToFloat: ItemStack
|
||||
// if (button == MouseButtons.LEFT) {
|
||||
// stackToFloat = stack
|
||||
// clickAction = ContainerClickActions.LEFT_MOUSE_CLICK
|
||||
// } else {
|
||||
// stackToFloat = stack.copy(count = maxOf(stack.item.count / 2, 1))
|
||||
// clickAction = ContainerClickActions.RIGHT_MOUSE_CLICK
|
||||
// stack.item.count = stack.item.count - stackToFloat.item.count
|
||||
// }
|
||||
// renderWindow.connection.sendPacket(ContainerClickC2SP(containerId, container.serverRevision, activeElement.slotId, clickAction, container.createAction(), mapOf(activeElement.slotId to stack), stack))
|
||||
// floatingItem = FloatingItem(guiRenderer, activeElement.slotId, stackToFloat)
|
||||
// this.floatingItem = floatingItem
|
||||
// floatingItem.show()
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import glm_.vec2.Vec2i
|
||||
|
||||
class FloatingItem(
|
||||
guiRenderer: GUIRenderer,
|
||||
val sourceId: Int,
|
||||
val stack: ItemStack,
|
||||
size: Vec2i = RawItemElement.DEFAULT_SIZE,
|
||||
) : Dragged(guiRenderer) {
|
||||
|
@ -26,7 +26,6 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.isGreater
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.isSmaller
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.container.CloseContainerC2SP
|
||||
import glm_.vec2.Vec2i
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||
|
||||
@ -70,7 +69,6 @@ abstract class ContainerScreen(
|
||||
|
||||
override fun onClose() {
|
||||
super.onClose()
|
||||
// minecraft behavior, when opening the inventory an open packet is never sent, but a close is
|
||||
renderWindow.connection.sendPacket(CloseContainerC2SP(renderWindow.connection.player.containers.getKey(container) ?: return))
|
||||
container.onClose()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user