mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 11:24:56 -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
|
package de.bixilon.minosoft.data.inventory.click
|
||||||
|
|
||||||
@Deprecated("ToDo")
|
@Deprecated("ToDo")
|
||||||
class FastMoveContainerAction : ContainerAction {
|
class FastMoveContainerAction(
|
||||||
|
val slot: Int,
|
||||||
|
) : ContainerAction {
|
||||||
private val mode: Int get() = 1
|
private val mode: Int get() = 1
|
||||||
}
|
}
|
||||||
|
@ -13,19 +13,77 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.inventory.click
|
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(
|
class SimpleContainerAction(
|
||||||
val slot: Int,
|
val slot: Int?,
|
||||||
val action: SimpleContainerActions,
|
val count: ContainerCounts,
|
||||||
) : ContainerAction {
|
) : ContainerAction {
|
||||||
private val mode: Int get() = 0
|
private val mode: Int get() = 0
|
||||||
private val button: Int
|
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 {
|
private fun putItem(connection: PlayConnection, containerId: Int, container: Container, floatingItem: ItemStack) {
|
||||||
LEFT_MOUSE_CLICK,
|
floatingItem.lock()
|
||||||
RIGHT_MOUSE_CLICK,
|
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)
|
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 {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other !is ItemStack) {
|
if (other !is ItemStack) {
|
||||||
return false
|
return false
|
||||||
@ -193,7 +197,14 @@ class ItemStack {
|
|||||||
if (other.hashCode() != this.hashCode()) {
|
if (other.hashCode() != this.hashCode()) {
|
||||||
return false
|
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 {
|
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.CollectionUtil.toSynchronizedMap
|
||||||
import de.bixilon.kutil.collections.map.bi.SynchronizedBiMap
|
import de.bixilon.kutil.collections.map.bi.SynchronizedBiMap
|
||||||
import de.bixilon.kutil.concurrent.lock.SimpleLock
|
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.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.click.ContainerAction
|
||||||
import de.bixilon.minosoft.data.inventory.stack.ItemStack
|
import de.bixilon.minosoft.data.inventory.stack.ItemStack
|
||||||
import de.bixilon.minosoft.data.inventory.stack.property.HolderProperty
|
import de.bixilon.minosoft.data.inventory.stack.property.HolderProperty
|
||||||
import de.bixilon.minosoft.data.text.ChatComponent
|
import de.bixilon.minosoft.data.text.ChatComponent
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
|
import de.bixilon.minosoft.protocol.packets.c2s.play.container.CloseContainerC2SP
|
||||||
|
|
||||||
open class Container(
|
open class Container(
|
||||||
protected val connection: PlayConnection,
|
protected val connection: PlayConnection,
|
||||||
@ -32,7 +34,7 @@ open class Container(
|
|||||||
val hasTitle: Boolean = false,
|
val hasTitle: Boolean = false,
|
||||||
) : Iterable<Map.Entry<Int, ItemStack>> {
|
) : Iterable<Map.Entry<Int, ItemStack>> {
|
||||||
@Deprecated("Should not be accessed dirctly")
|
@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()
|
val lock = SimpleLock()
|
||||||
var revision by watched(0L)
|
var revision by watched(0L)
|
||||||
var serverRevision = 0
|
var serverRevision = 0
|
||||||
@ -40,6 +42,10 @@ open class Container(
|
|||||||
var actions: SynchronizedBiMap<Int, ContainerAction> = synchronizedBiMapOf()
|
var actions: SynchronizedBiMap<Int, ContainerAction> = synchronizedBiMapOf()
|
||||||
var floatingItem: ItemStack? by watched(null)
|
var floatingItem: ItemStack? by watched(null)
|
||||||
|
|
||||||
|
init {
|
||||||
|
this::floatingItem.observe(this) { it?.holder?.container = this }
|
||||||
|
}
|
||||||
|
|
||||||
fun _validate() {
|
fun _validate() {
|
||||||
var itemsRemoved = 0
|
var itemsRemoved = 0
|
||||||
for ((slot, itemStack) in slots.toSynchronizedMap()) {
|
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)
|
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>> {
|
override fun iterator(): Iterator<Map.Entry<Int, ItemStack>> {
|
||||||
return slots.toSynchronizedMap().iterator()
|
return slots.toSynchronizedMap().iterator()
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,10 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.gui.elements.items
|
package de.bixilon.minosoft.gui.rendering.gui.elements.items
|
||||||
|
|
||||||
import de.bixilon.kutil.watcher.map.MapDataWatcher.Companion.observeMap
|
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.data.registries.other.containers.Container
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.atlas.Vec2iBinding
|
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.AbstractLayout
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.gui.dragged.Dragged
|
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.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.MouseActions
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseButtons
|
import de.bixilon.minosoft.gui.rendering.gui.input.mouse.MouseButtons
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
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.EMPTY
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.isGreater
|
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.gui.rendering.util.vec.vec2.Vec2iUtil.isSmaller
|
||||||
|
import de.bixilon.minosoft.util.delegate.RenderingDelegate.observeRendering
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||||
|
|
||||||
@ -73,6 +79,11 @@ class ContainerItemsElement(
|
|||||||
this._size = size
|
this._size = size
|
||||||
|
|
||||||
container::slots.observeMap(this) { update = true; }
|
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?) {
|
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 {
|
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)
|
val consumed = super<AbstractLayout>.onMouseAction(position, button, action)
|
||||||
if (action != MouseActions.PRESS || (button != MouseButtons.LEFT && button != MouseButtons.RIGHT)) {
|
if (action != MouseActions.PRESS) {
|
||||||
return consumed
|
return consumed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val shiftDown = guiRenderer.isKeyDown(ModifierKeys.SHIFT)
|
||||||
val activeElement = activeElement
|
val activeElement = activeElement
|
||||||
val stack = activeElement?.stack
|
if (button == MouseButtons.MIDDLE) {
|
||||||
val containerId = renderWindow.connection.player.containers.getKey(container) ?: return consumed
|
if (guiRenderer.connection.player.gamemode != Gamemodes.CREATIVE) {
|
||||||
var floatingItem = this.floatingItem
|
return true
|
||||||
if ((floatingItem != null && floatingItem.visible) || stack?._valid != true) {
|
}
|
||||||
return consumed
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ import glm_.vec2.Vec2i
|
|||||||
|
|
||||||
class FloatingItem(
|
class FloatingItem(
|
||||||
guiRenderer: GUIRenderer,
|
guiRenderer: GUIRenderer,
|
||||||
val sourceId: Int,
|
|
||||||
val stack: ItemStack,
|
val stack: ItemStack,
|
||||||
size: Vec2i = RawItemElement.DEFAULT_SIZE,
|
size: Vec2i = RawItemElement.DEFAULT_SIZE,
|
||||||
) : Dragged(guiRenderer) {
|
) : 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.gui.mesh.GUIVertexOptions
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.isGreater
|
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.gui.rendering.util.vec.vec2.Vec2iUtil.isSmaller
|
||||||
import de.bixilon.minosoft.protocol.packets.c2s.play.container.CloseContainerC2SP
|
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||||
|
|
||||||
@ -70,7 +69,6 @@ abstract class ContainerScreen(
|
|||||||
|
|
||||||
override fun onClose() {
|
override fun onClose() {
|
||||||
super.onClose()
|
super.onClose()
|
||||||
// minecraft behavior, when opening the inventory an open packet is never sent, but a close is
|
container.onClose()
|
||||||
renderWindow.connection.sendPacket(CloseContainerC2SP(renderWindow.connection.player.containers.getKey(container) ?: return))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user