container revision fixes, item rendering: render material color quad

This commit is contained in:
Bixilon 2021-10-23 15:48:36 +02:00
parent 191c2e665e
commit 7e6fc7c933
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
7 changed files with 101 additions and 22 deletions

View File

@ -42,6 +42,7 @@ import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.getAndRemove
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.listCast
import java.util.*
class ItemStack(
val item: Item,
@ -54,7 +55,7 @@ class ItemStack(
unbreakable: Boolean = false,
durability: Int = 0,
val nbt: MutableMap<String, Any> = synchronizedMapOf(),
val container: Container? = null,
container: Container? = null,
hideFlags: Int = 0,
) : TextFormattable {
var count = count
@ -105,6 +106,17 @@ class ItemStack(
field = value
apply()
}
var container = container
set(value) {
if (field != null && value != null) {
throw IllegalStateException("Item already in a different container!")
}
if (field === value) {
return
}
field = value
apply()
}
// ToDo: Apply if enchantments, lore or nbt changes
@ -319,6 +331,33 @@ class ItemStack(
val damageable: Boolean
get() = item.maxDamage > 0 || !unbreakable
override fun hashCode(): Int {
return Objects.hash(item, count, durability, nbt)
}
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
if (other !is ItemStack) {
return false
}
if (hashCode() != other.hashCode()) {
return false
}
return item == other.item
&& count == other.count
&& durability == other.durability
&& enchantments == other.enchantments
&& nbt == other.nbt
&& lore == other.lore
&& customDisplayName == other.customDisplayName
&& repairCost == other.repairCost
&& unbreakable == other.unbreakable
&& hideFlags == other.hideFlags
}
companion object {
private const val HIDE_ENCHANTMENT_BIT = 0
private const val HIDE_MODIFIERS_BIT = 1

View File

@ -41,6 +41,7 @@ open class Container(
for ((slot, itemStack) in slots.toSynchronizedMap()) {
if (itemStack.count <= 0 || itemStack.durability < 0) {
slots.remove(slot)
itemStack.container = null
changes = true
}
}
@ -53,13 +54,29 @@ open class Container(
return slots[slotId]
}
operator fun set(slotId: Int, itemStack: ItemStack?) {
if (itemStack == null) {
slots.remove(slotId) ?: return
} else {
slots[slotId] = itemStack // ToDo: Check for changes
}
fun remove(slotId: Int): ItemStack? {
val itemStack = slots.remove(slotId) ?: return null
itemStack.container = null
revision++
return itemStack
}
/**
* @return The previous item
*/
operator fun set(slotId: Int, itemStack: ItemStack?): ItemStack? {
if (itemStack == null) {
return remove(slotId)
}
val previous = slots[slotId]
if (previous == itemStack) {
return previous
}
slots[slotId] = itemStack // ToDo: Check for changes
itemStack.container = this
revision++
return previous
}
fun clear() {

View File

@ -9,6 +9,7 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
import glm_.vec2.Vec2i
import java.lang.Integer.max
class ContainerItemsElement(
hudRenderer: HUDRenderer,
@ -24,17 +25,20 @@ class ContainerItemsElement(
}
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
var maxZ = 0
for ((_, data) in itemElements.toSynchronizedMap()) {
data.element.render(offset + data.offset, z, consumer, options)
maxZ = max(maxZ, data.element.render(offset + data.offset, z, consumer, options))
}
return 2
return maxZ
}
override fun silentApply(): Boolean {
if (this.revision == container.revision) {
val revision = container.revision
if (this.revision == revision) {
return false
}
this.revision = revision
var changes = false
for ((slot, binding) in slots) {
@ -56,7 +60,7 @@ class ContainerItemsElement(
changes = true
} else {
if (data.element.item == item) {
if (data.element.poll()) {
if (data.element.silentApply()) {
changes = true
}
} else {

View File

@ -1,6 +1,7 @@
package de.bixilon.minosoft.gui.rendering.gui.elements.items
import de.bixilon.minosoft.data.inventory.ItemStack
import de.bixilon.minosoft.data.registries.items.block.BlockItem
import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.data.text.TextComponent
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
@ -9,6 +10,7 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments.Compa
import de.bixilon.minosoft.gui.rendering.gui.elements.Pollable
import de.bixilon.minosoft.gui.rendering.gui.elements.VerticalAlignments
import de.bixilon.minosoft.gui.rendering.gui.elements.VerticalAlignments.Companion.getOffset
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ColorElement
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
@ -41,15 +43,22 @@ class ItemElement(
}
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
if (item == null) {
return 0
}
val item = item ?: return 0
val size = size
val countSize = countText.size
countText.render(offset + Vec2i(HorizontalAlignments.RIGHT.getOffset(size.x, countSize.x), VerticalAlignments.BOTTOM.getOffset(size.y, countSize.y)), z + 1, consumer, options)
var color = ChatColors.WHITE
if (item.item is BlockItem) {
item.item.block?.defaultState?.material?.color?.let { color = it }
}
val image = ColorElement(hudRenderer, _size, color)
image.render(offset, z + 1, consumer, options)
// ToDo: Render model
return 2
return TextElement.LAYERS + 1
}
override fun poll(): Boolean {

View File

@ -46,14 +46,14 @@ class HotbarBaseElement(hudRenderer: HUDRenderer) : Element(hudRenderer), Pollab
base.render(offset + HORIZONTAL_MARGIN, z, consumer, options)
baseAtlasElement.slots[selectedSlot + PlayerInventory.HOTBAR_OFFSET]?.let {
frame.render(offset + it.start - HORIZONTAL_MARGIN + FRAME_OFFSET, z + 2, consumer, options)
frame.render(offset + it.start - HORIZONTAL_MARGIN + FRAME_OFFSET, z + 1, consumer, options)
}
inventoryElement.render(offset, z, consumer, options)
val inventoryZ = inventoryElement.render(offset, z + 2, consumer, options)
// ToDo: Item rendering
return 2 // bar + frame
return 2 + inventoryZ// bar + frame
}
override fun poll(): Boolean {

View File

@ -216,11 +216,20 @@ class Camera(
connection.registerEvent(CallbackEventInvoker.of<ResizeWindowEvent> { recalculateViewProjectionMatrix() })
fun dropItem(type: BlockBreakC2SP.BreakType) {
fun dropItem(stack: Boolean) {
val time = System.currentTimeMillis()
if (time - lastDropPacketSent < ProtocolDefinition.TICK_TIME) {
return
}
val type = if (stack) {
connection.player.inventory.getHotbarSlot()?.count = 0
BlockBreakC2SP.BreakType.DROP_ITEM_STACK
} else {
connection.player.inventory.getHotbarSlot()?.let {
it.count--
}
BlockBreakC2SP.BreakType.DROP_ITEM
}
connection.sendPacket(BlockBreakC2SP(type, connection.player.positionInfo.blockPosition))
lastDropPacketSent = time
}
@ -230,13 +239,13 @@ class Camera(
mutableMapOf(
KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_Q),
),
)) { dropItem(BlockBreakC2SP.BreakType.DROP_ITEM) }
)) { dropItem(false) }
renderWindow.inputHandler.registerKeyCallback(DROP_ITEM_STACK_KEYBINDING, KeyBinding(
mutableMapOf(
KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_Q),
KeyAction.MODIFIER to mutableSetOf(KeyCodes.KEY_LEFT_CONTROL)
),
)) { dropItem(BlockBreakC2SP.BreakType.DROP_ITEM_STACK) }
)) { dropItem(true) }
frustum.recalculate()
connection.fireEvent(FrustumChangeEvent(renderWindow, frustum))
}

View File

@ -34,10 +34,11 @@ class ContainerItemSetS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
override fun handle(connection: PlayConnection) {
connection.player.containers[containerId]?.set(slot, itemStack)
// ToDo: Check for changes
connection.fireEvent(ContainerSlotChangeEvent(connection, this))
}
override fun log() {
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Container item set (containerId=$containerId, slot=$slot, itemStack=$itemStack)" }
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Container item set (containerId=$containerId, revision=$revision, slot=$slot, itemStack=$itemStack)" }
}
}