mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 18:34:56 -04:00
proper enchanting screen
This commit is contained in:
parent
899b838b2c
commit
56a6a3c821
@ -43,6 +43,7 @@ open class Container(
|
|||||||
@Deprecated("Should not be accessed directly")
|
@Deprecated("Should not be accessed directly")
|
||||||
val slots: MutableMap<Int, ItemStack> by watchedMap(mutableMapOf())
|
val slots: MutableMap<Int, ItemStack> by watchedMap(mutableMapOf())
|
||||||
val lock = SimpleLock()
|
val lock = SimpleLock()
|
||||||
|
var propertiesRevision by watched(0L)
|
||||||
var revision by watched(0L)
|
var revision by watched(0L)
|
||||||
var serverRevision = 0
|
var serverRevision = 0
|
||||||
private var lastActionId = 0
|
private var lastActionId = 0
|
||||||
|
@ -22,6 +22,7 @@ import de.bixilon.minosoft.data.container.slots.SlotType
|
|||||||
import de.bixilon.minosoft.data.container.stack.ItemStack
|
import de.bixilon.minosoft.data.container.stack.ItemStack
|
||||||
import de.bixilon.minosoft.data.registries.MultiResourceLocationAble
|
import de.bixilon.minosoft.data.registries.MultiResourceLocationAble
|
||||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||||
|
import de.bixilon.minosoft.data.registries.enchantment.Enchantment
|
||||||
import de.bixilon.minosoft.data.registries.items.DefaultItems
|
import de.bixilon.minosoft.data.registries.items.DefaultItems
|
||||||
import de.bixilon.minosoft.data.registries.other.containers.ContainerFactory
|
import de.bixilon.minosoft.data.registries.other.containers.ContainerFactory
|
||||||
import de.bixilon.minosoft.data.registries.other.containers.ContainerType
|
import de.bixilon.minosoft.data.registries.other.containers.ContainerType
|
||||||
@ -29,8 +30,13 @@ 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.util.KUtil.toResourceLocation
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
|
|
||||||
class EnchantingContainer(connection: PlayConnection, type: ContainerType, title: ChatComponent?) : InventorySynchronizedContainer(connection, type, title, (ENCHANTING_SLOTS + 1)..(ENCHANTING_SLOTS + PlayerInventory.MAIN_SLOTS)) {
|
class EnchantingContainer(connection: PlayConnection, type: ContainerType, title: ChatComponent?) : InventorySynchronizedContainer(connection, type, title, ENCHANTING_SLOTS until (ENCHANTING_SLOTS + PlayerInventory.MAIN_SLOTS)) {
|
||||||
override val sections: Array<IntRange> = arrayOf(0 until ENCHANTING_SLOTS, ENCHANTING_SLOTS until ENCHANTING_SLOTS + PlayerInventory.MAIN_SLOTS)
|
override val sections: Array<IntRange> = arrayOf(0 until ENCHANTING_SLOTS, ENCHANTING_SLOTS until ENCHANTING_SLOTS + PlayerInventory.MAIN_SLOTS)
|
||||||
|
val costs = IntArray(ENCHANTING_OPTIONS) { -1 }
|
||||||
|
val enchantments: Array<Enchantment?> = arrayOfNulls(ENCHANTING_OPTIONS)
|
||||||
|
var enchantmentLevels = IntArray(ENCHANTING_OPTIONS) { -1 }
|
||||||
|
var seed = -1
|
||||||
|
private set
|
||||||
|
|
||||||
override fun getSlotType(slotId: Int): SlotType? {
|
override fun getSlotType(slotId: Int): SlotType? {
|
||||||
return when (slotId) {
|
return when (slotId) {
|
||||||
@ -58,6 +64,15 @@ class EnchantingContainer(connection: PlayConnection, type: ContainerType, title
|
|||||||
return 1 + ENCHANTING_SLOTS + PlayerInventory.MAIN_SLOTS_PER_ROW * 3 + slot.ordinal
|
return 1 + ENCHANTING_SLOTS + PlayerInventory.MAIN_SLOTS_PER_ROW * 3 + slot.ordinal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun readProperty(property: Int, value: Int) {
|
||||||
|
when (property) {
|
||||||
|
0, 1, 2 -> costs[property] = value
|
||||||
|
3 -> seed = value
|
||||||
|
4, 5, 6 -> enchantments[property - 4] = connection.registries.enchantmentRegistry.getOrNull(value)
|
||||||
|
7, 8, 9 -> enchantmentLevels[property - 7] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private object LapislazuliSlot : SlotType {
|
private object LapislazuliSlot : SlotType {
|
||||||
override fun canPut(container: Container, slot: Int, stack: ItemStack): Boolean {
|
override fun canPut(container: Container, slot: Int, stack: ItemStack): Boolean {
|
||||||
return stack.item.item.resourceLocation == DefaultItems.LAPISLAZULI
|
return stack.item.item.resourceLocation == DefaultItems.LAPISLAZULI
|
||||||
@ -68,7 +83,9 @@ class EnchantingContainer(connection: PlayConnection, type: ContainerType, title
|
|||||||
companion object : ContainerFactory<EnchantingContainer>, MultiResourceLocationAble {
|
companion object : ContainerFactory<EnchantingContainer>, MultiResourceLocationAble {
|
||||||
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:enchantment".toResourceLocation()
|
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:enchantment".toResourceLocation()
|
||||||
override val ALIASES: Set<ResourceLocation> = setOf("minecraft:enchanting_table".toResourceLocation(), "EnchantTable".toResourceLocation())
|
override val ALIASES: Set<ResourceLocation> = setOf("minecraft:enchanting_table".toResourceLocation(), "EnchantTable".toResourceLocation())
|
||||||
|
const val LAPISLAZULI_SLOT = 1
|
||||||
const val ENCHANTING_SLOTS = 2
|
const val ENCHANTING_SLOTS = 2
|
||||||
|
const val ENCHANTING_OPTIONS = 3
|
||||||
|
|
||||||
override fun build(connection: PlayConnection, type: ContainerType, title: ChatComponent?): EnchantingContainer {
|
override fun build(connection: PlayConnection, type: ContainerType, title: ChatComponent?): EnchantingContainer {
|
||||||
return EnchantingContainer(connection, type, title)
|
return EnchantingContainer(connection, type, title)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2020 Moritz Zwerger
|
* 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 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.
|
||||||
*
|
*
|
||||||
@ -54,6 +54,13 @@ open class ResourceLocation(
|
|||||||
return full
|
return full
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun toMinifiedString(): String {
|
||||||
|
if (namespace == ProtocolDefinition.DEFAULT_NAMESPACE) {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
return toString()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val String.namespace: String
|
val String.namespace: String
|
||||||
get() {
|
get() {
|
||||||
|
@ -37,7 +37,7 @@ abstract class AbstractButtonElement(
|
|||||||
text: Any,
|
text: Any,
|
||||||
disabled: Boolean = false,
|
disabled: Boolean = false,
|
||||||
) : Element(guiRenderer) {
|
) : Element(guiRenderer) {
|
||||||
protected val textElement = TextElement(guiRenderer, text, background = false).apply { parent = this@AbstractButtonElement }
|
protected val textElement = TextElement(guiRenderer, text, background = false, parent = this)
|
||||||
protected abstract val disabledAtlas: AtlasElement?
|
protected abstract val disabledAtlas: AtlasElement?
|
||||||
protected abstract val normalAtlas: AtlasElement?
|
protected abstract val normalAtlas: AtlasElement?
|
||||||
protected abstract val hoveredAtlas: AtlasElement?
|
protected abstract val hoveredAtlas: AtlasElement?
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.enchanting
|
package de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.enchanting
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
|
import de.bixilon.kutil.watcher.DataWatcher.Companion.observe
|
||||||
|
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||||
import de.bixilon.minosoft.data.container.types.EnchantingContainer
|
import de.bixilon.minosoft.data.container.types.EnchantingContainer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||||
@ -27,8 +29,14 @@ import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
class EnchantingContainerScreen(guiRenderer: GUIRenderer, container: EnchantingContainer) : LabeledContainerScreen<EnchantingContainer>(guiRenderer, container, guiRenderer.atlasManager["minecraft:enchanting_container".toResourceLocation()]) {
|
class EnchantingContainerScreen(guiRenderer: GUIRenderer, container: EnchantingContainer) : LabeledContainerScreen<EnchantingContainer>(guiRenderer, container, guiRenderer.atlasManager["minecraft:enchanting_container".toResourceLocation()]) {
|
||||||
private val cards: Array<EnchantmentButtonElement> = Array(CARDS) { EnchantmentButtonElement(guiRenderer, this, guiRenderer.atlasManager["minecraft:level_requirement_${it}"], guiRenderer.atlasManager["minecraft:level_requirement_${it}_disabled"]) }
|
private val cards: Array<EnchantmentButtonElement> = Array(EnchantingContainer.ENCHANTING_OPTIONS) { EnchantmentButtonElement(guiRenderer, this, guiRenderer.atlasManager["minecraft:level_requirement_${it}"], guiRenderer.atlasManager["minecraft:level_requirement_${it}_disabled"], it) }
|
||||||
private val cardAreas = arrayOf(atlasElement?.areas?.get("card_0"), atlasElement?.areas?.get("card_1"), atlasElement?.areas?.get("card_2"))
|
private val cardAreas = Array(EnchantingContainer.ENCHANTING_OPTIONS) { atlasElement?.areas?.get("card_$it") }
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
container::propertiesRevision.observe(this) { forceApply() }
|
||||||
|
container::revision.observe(this) { forceApply() }
|
||||||
|
}
|
||||||
|
|
||||||
override fun forceRenderContainerScreen(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
override fun forceRenderContainerScreen(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||||
super.forceRenderContainerScreen(offset, consumer, options)
|
super.forceRenderContainerScreen(offset, consumer, options)
|
||||||
@ -56,9 +64,21 @@ class EnchantingContainerScreen(guiRenderer: GUIRenderer, container: EnchantingC
|
|||||||
return super.getContainerAt(position)
|
return super.getContainerAt(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun forceSilentApply() {
|
||||||
|
super.forceSilentApply()
|
||||||
|
var lapisCount = container[EnchantingContainer.LAPISLAZULI_SLOT]?.item?._count ?: 0
|
||||||
|
if (guiRenderer.connection.player.gamemode == Gamemodes.CREATIVE) {
|
||||||
|
lapisCount = 64
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index in 0 until EnchantingContainer.ENCHANTING_OPTIONS) {
|
||||||
|
val card = cards[index]
|
||||||
|
card.update(lapisCount < index + 1, container.costs[index], container.enchantments[index], container.enchantmentLevels[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object : ContainerGUIFactory<EnchantingContainerScreen, EnchantingContainer> {
|
companion object : ContainerGUIFactory<EnchantingContainerScreen, EnchantingContainer> {
|
||||||
override val clazz: KClass<EnchantingContainer> = EnchantingContainer::class
|
override val clazz: KClass<EnchantingContainer> = EnchantingContainer::class
|
||||||
const val CARDS = 3
|
|
||||||
|
|
||||||
override fun build(guiRenderer: GUIRenderer, container: EnchantingContainer): EnchantingContainerScreen {
|
override fun build(guiRenderer: GUIRenderer, container: EnchantingContainer): EnchantingContainerScreen {
|
||||||
return EnchantingContainerScreen(guiRenderer, container)
|
return EnchantingContainerScreen(guiRenderer, container)
|
||||||
|
@ -14,31 +14,46 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.enchanting
|
package de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.enchanting
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
|
import de.bixilon.minosoft.data.registries.enchantment.Enchantment
|
||||||
|
import de.bixilon.minosoft.data.text.ChatColors
|
||||||
|
import de.bixilon.minosoft.data.text.ChatComponent
|
||||||
|
import de.bixilon.minosoft.data.text.TextComponent
|
||||||
|
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.atlas.AtlasElement
|
import de.bixilon.minosoft.gui.rendering.gui.atlas.AtlasElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments
|
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments.Companion.getOffset
|
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments.Companion.getOffset
|
||||||
|
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.input.button.AbstractButtonElement
|
import de.bixilon.minosoft.gui.rendering.gui.elements.input.button.AbstractButtonElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.AtlasImageElement
|
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.AtlasImageElement
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
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.protocol.packets.c2s.play.container.ContainerButtonC2SP
|
||||||
|
|
||||||
class EnchantmentButtonElement(
|
class EnchantmentButtonElement(
|
||||||
guiRenderer: GUIRenderer,
|
guiRenderer: GUIRenderer,
|
||||||
val container: EnchantingContainerScreen,
|
val container: EnchantingContainerScreen,
|
||||||
val levelAtlas: AtlasElement?,
|
val levelAtlas: AtlasElement?,
|
||||||
val disabledLevelAtlas: AtlasElement?,
|
val disabledLevelAtlas: AtlasElement?,
|
||||||
) : AbstractButtonElement(guiRenderer, "< text >", true) {
|
val index: Int,
|
||||||
|
) : AbstractButtonElement(guiRenderer, "", true) {
|
||||||
override val disabledAtlas = guiRenderer.atlasManager["enchanting_table_card_disabled"]
|
override val disabledAtlas = guiRenderer.atlasManager["enchanting_table_card_disabled"]
|
||||||
override val normalAtlas = guiRenderer.atlasManager["enchanting_table_card_normal"]
|
override val normalAtlas = guiRenderer.atlasManager["enchanting_table_card_normal"]
|
||||||
override val hoveredAtlas = guiRenderer.atlasManager["enchanting_table_card_hovered"]
|
override val hoveredAtlas = guiRenderer.atlasManager["enchanting_table_card_hovered"]
|
||||||
|
private val levelText = TextElement(guiRenderer, ChatComponent.EMPTY, background = false)
|
||||||
|
|
||||||
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||||
super.forceRender(offset, consumer, options)
|
super.forceRender(offset, consumer, options)
|
||||||
|
|
||||||
val level = AtlasImageElement(guiRenderer, if (disabled) disabledLevelAtlas else levelAtlas)
|
val level = AtlasImageElement(guiRenderer, if (disabled) disabledLevelAtlas else levelAtlas)
|
||||||
val size = size
|
val size = size
|
||||||
level.render(offset + Vec2i(5, HorizontalAlignments.CENTER.getOffset(size.y, level.size.y)), consumer, options)
|
level.render(offset + Vec2i(5, VerticalAlignments.CENTER.getOffset(size.y, level.size.y)), consumer, options)
|
||||||
|
|
||||||
|
if (!_disabled) {
|
||||||
|
levelText.render(offset + Vec2i(HorizontalAlignments.RIGHT.getOffset(size.x, levelText.size.x) - 3, VerticalAlignments.BOTTOM.getOffset(size.y, levelText.size.y) - 2), consumer, options)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -48,6 +63,15 @@ class EnchantmentButtonElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun submit() {
|
override fun submit() {
|
||||||
TODO("Not yet implemented")
|
container.container.id?.let { guiRenderer.connection.network.send(ContainerButtonC2SP(it, index)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(disabled: Boolean, cost: Int, enchantment: Enchantment?, level: Int) {
|
||||||
|
_disabled = disabled || cost <= 0
|
||||||
|
levelText.text = TextComponent(cost).color(RenderConstants.EXPERIENCE_BAR_LEVEL_COLOR)
|
||||||
|
textElement._chatComponent = if (enchantment == null) ChatComponent.EMPTY else TextComponent(enchantment.resourceLocation.toMinifiedString() + " $level").color(ChatColors.BLUE)
|
||||||
|
textElement.forceSilentApply()
|
||||||
|
|
||||||
|
forceSilentApply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ import de.bixilon.minosoft.util.logging.LogMessageType
|
|||||||
|
|
||||||
@LoadPacket
|
@LoadPacket
|
||||||
class ContainerButtonC2SP(
|
class ContainerButtonC2SP(
|
||||||
private val containerId: Byte,
|
private val containerId: Int,
|
||||||
private val buttonId: Byte, // up, middle, bottom (0, 1, 2); in later versions: lectern page, etc
|
private val buttonId: Int,
|
||||||
) : PlayC2SPacket {
|
) : PlayC2SPacket {
|
||||||
|
|
||||||
override fun write(buffer: PlayOutByteBuffer) {
|
override fun write(buffer: PlayOutByteBuffer) {
|
||||||
|
@ -20,14 +20,16 @@ import de.bixilon.minosoft.util.logging.Log
|
|||||||
import de.bixilon.minosoft.util.logging.LogLevels
|
import de.bixilon.minosoft.util.logging.LogLevels
|
||||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||||
|
|
||||||
@LoadPacket
|
@LoadPacket(threadSafe = false)
|
||||||
class ContainerPropertiesS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
|
class ContainerPropertiesS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
|
||||||
val containerId = buffer.readUnsignedByte()
|
val containerId = buffer.readUnsignedByte()
|
||||||
val property = buffer.readUnsignedShort()
|
val property = buffer.readUnsignedShort()
|
||||||
val value = buffer.readUnsignedShort()
|
val value = buffer.readUnsignedShort()
|
||||||
|
|
||||||
override fun handle(connection: PlayConnection) {
|
override fun handle(connection: PlayConnection) {
|
||||||
connection.player.containers[containerId]?.readProperty(property, value)
|
val container = connection.player.containers[containerId] ?: return
|
||||||
|
container.readProperty(property, value)
|
||||||
|
container.propertiesRevision++
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun log(reducedLog: Boolean) {
|
override fun log(reducedLog: Boolean) {
|
||||||
|
@ -29,7 +29,7 @@ import de.bixilon.minosoft.util.logging.Log
|
|||||||
import de.bixilon.minosoft.util.logging.LogLevels
|
import de.bixilon.minosoft.util.logging.LogLevels
|
||||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||||
|
|
||||||
@LoadPacket
|
@LoadPacket(threadSafe = false)
|
||||||
class OpenContainerS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
|
class OpenContainerS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
|
||||||
val containerId = if (buffer.versionId <= V_1_14) { // ToDo: This is completely guessed, it has changed between 1.13 and 1.14, same as #L38
|
val containerId = if (buffer.versionId <= V_1_14) { // ToDo: This is completely guessed, it has changed between 1.13 and 1.14, same as #L38
|
||||||
buffer.readUnsignedByte()
|
buffer.readUnsignedByte()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user