container gui factories, gui: generic container (wip)

This commit is contained in:
Bixilon 2022-02-26 13:11:21 +01:00
parent e9a9061101
commit f7aef99cf3
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
28 changed files with 548 additions and 73 deletions

View File

@ -0,0 +1,20 @@
/*
* 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.data.registries.factory.clazz.mapping
import kotlin.reflect.KClass
interface ClassMappingFactory<T : Any> {
val clazz: KClass<T>
}

View File

@ -0,0 +1,50 @@
/*
* Minosoft
* Copyright (C) 2021 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.data.registries.factory.clazz.mapping
import kotlin.reflect.KClass
import kotlin.reflect.full.superclasses
open class DefaultClassMappingFactory<T : ClassMappingFactory<*>>(vararg factories: T) {
private val factoryMap: Map<KClass<*>, T>
init {
val ret: MutableMap<KClass<*>, T> = mutableMapOf()
for (factory in factories) {
ret[factory.clazz] = factory
if (factory is MultiClassMappingFactory) {
for (clazz in factory.aliases) {
ret[clazz] = factory
}
}
}
factoryMap = ret.toMap()
}
operator fun get(`class`: KClass<*>?): T? {
return factoryMap[`class`]
}
fun forObject(`object`: Any): T? {
var clazz: KClass<*> = `object`::class
while (clazz != Any::class) {
this[clazz]?.let { return it }
clazz = clazz.superclasses.firstOrNull() ?: break
}
return null
}
}

View File

@ -0,0 +1,20 @@
/*
* 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.data.registries.factory.clazz.mapping
import kotlin.reflect.KClass
interface MultiClassMappingFactory {
val aliases: Set<KClass<*>>
}

View File

@ -26,5 +26,4 @@ object DefaultContainerFactories : DefaultFactory<ContainerFactory<*>>(
Generic9x4Container,
Generic9x5Container,
Generic9x6Container,
)
)

View File

@ -13,6 +13,7 @@
package de.bixilon.minosoft.gui.rendering.gui.elements.items
import de.bixilon.kutil.watcher.DataWatcher.Companion.observe
import de.bixilon.kutil.watcher.map.MapDataWatcher.Companion.observeMap
import de.bixilon.minosoft.data.container.Container
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
@ -25,7 +26,6 @@ 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
@ -71,10 +71,10 @@ class ContainerItemsElement(
this._size = size
container::slots.observeMap(this) { update = true; }
container::floatingItem.observeRendering(this) {
container::floatingItem.observe(this) {
this.floatingItem?.close()
this.floatingItem = null
this.floatingItem = FloatingItem(guiRenderer, stack = it ?: return@observeRendering, container = container).apply { show() }
this.floatingItem = FloatingItem(guiRenderer, stack = it ?: return@observe, container = container).apply { show() }
}
}

View File

@ -13,6 +13,7 @@
package de.bixilon.minosoft.gui.rendering.gui.elements.items
import de.bixilon.kutil.watcher.DataWatcher.Companion.observe
import de.bixilon.minosoft.data.container.stack.ItemStack
import de.bixilon.minosoft.data.registries.items.block.BlockItem
import de.bixilon.minosoft.data.text.ChatColors
@ -32,7 +33,6 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.KUtil
import de.bixilon.minosoft.util.delegate.RenderingDelegate.observeRendering
import glm_.vec2.Vec2i
import glm_.vec3.Vec3i
@ -50,7 +50,7 @@ class RawItemElement(
return
}
if (value != null) {
value::revision.observeRendering(this) { forceSilentApply() }
value::revision.observe(this) { forceSilentApply() }
}
if (field == value) {
return

View File

@ -22,16 +22,17 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
open class AtlasImageElement(
guiRenderer: GUIRenderer,
textureLike: TextureLike,
size: Vec2i = textureLike.size,
textureLike: TextureLike?,
size: Vec2i = textureLike?.size ?: Vec2i.EMPTY,
tint: RGBColor = ChatColors.WHITE,
) : Element(guiRenderer, GUIMesh.GUIMeshStruct.FLOATS_PER_VERTEX * 6) {
var texture: AbstractTexture = textureLike.texture
var texture: AbstractTexture? = textureLike?.texture
set(value) {
field = value
cacheUpToDate = false
@ -66,12 +67,12 @@ open class AtlasImageElement(
cacheUpToDate = false
}
var textureLike: TextureLike = textureLike
var textureLike: TextureLike? = textureLike
set(value) {
if (field === value) {
return
}
texture = value.texture
texture = value?.texture
field = value
uvStart = null
uvEnd = null
@ -85,6 +86,8 @@ open class AtlasImageElement(
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
val texture = texture ?: return
val textureLike = textureLike ?: return
consumer.addQuad(offset, offset + size, texture, uvStart ?: textureLike.uvStart, uvEnd ?: textureLike.uvEnd, tint, options)
}

View File

@ -21,13 +21,14 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ImageElement
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.VecUtil
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
open class ProgressElement(
guiRenderer: GUIRenderer,
val emptyAtlasElement: AtlasElement,
val fullAtlasElement: AtlasElement,
val emptyAtlasElement: AtlasElement?,
val fullAtlasElement: AtlasElement?,
progress: Float = 0.0f,
) : Element(guiRenderer) {
var progress = progress
@ -43,10 +44,10 @@ open class ProgressElement(
protected lateinit var progressImage: ImageElement
constructor(guiRenderer: GUIRenderer, atlasElements: Array<AtlasElement>, progress: Float = 0.0f) : this(guiRenderer, atlasElements[0], atlasElements[1], progress)
constructor(guiRenderer: GUIRenderer, atlasElements: Array<AtlasElement?>, progress: Float = 0.0f) : this(guiRenderer, atlasElements.getOrNull(0), atlasElements.getOrNull(1), progress)
init {
_size = emptyAtlasElement.size
_size = emptyAtlasElement?.size ?: Vec2i.EMPTY
forceSilentApply()
}
@ -56,6 +57,8 @@ open class ProgressElement(
}
override fun forceSilentApply() {
val emptyAtlasElement = emptyAtlasElement ?: return
val fullAtlasElement = fullAtlasElement ?: return
progressImage = ImageElement(guiRenderer, fullAtlasElement.texture, uvStart = fullAtlasElement.uvStart, uvEnd = Vec2(VecUtil.lerp(progress, fullAtlasElement.uvStart.x, fullAtlasElement.uvEnd.x), fullAtlasElement.uvEnd.y), size = Vec2i((fullAtlasElement.size.x * progress).toInt(), emptyAtlasElement.size.y))
cacheUpToDate = false

View File

@ -19,6 +19,4 @@ import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
interface GUIBuilder<T : GUIElement> {
fun build(guiRenderer: GUIRenderer): T
fun register(guiRenderer: GUIRenderer) {}
}

View File

@ -25,7 +25,7 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.gui.rendering.gui.elements.LayoutedElement
import de.bixilon.minosoft.gui.rendering.gui.elements.Pollable
import de.bixilon.minosoft.gui.rendering.gui.gui.dragged.Dragged
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.inventory.LocalInventoryScreen
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.ContainerGUIManager
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.menu.pause.PauseMenu
import de.bixilon.minosoft.gui.rendering.gui.hud.Initializable
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
@ -55,7 +55,7 @@ class GUIManager(
}
private fun registerDefaultElements() {
LocalInventoryScreen.register(guiRenderer)
ContainerGUIManager.register(guiRenderer)
}
override fun postInit() {
@ -236,6 +236,10 @@ class GUIManager(
_push(layouted)
}
fun pop(element: GUIElement) {
TODO("Not yet implemented")
}
fun pop() {
if (guiRenderer.dragged.element != null) {
guiRenderer.dragged.element = null

View File

@ -20,6 +20,7 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.LayoutedElement
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.AtlasImageElement
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.EMPTY
import glm_.vec2.Vec2i
abstract class Screen(
@ -38,6 +39,6 @@ abstract class Screen(
}
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
background.render(offset, consumer, options)
background.render(Vec2i.EMPTY, consumer, options)
}
}

View File

@ -0,0 +1,51 @@
/*
* Minosoft
* Copyright (C) 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.gui.rendering.gui.gui.screen.container
import de.bixilon.minosoft.data.container.Container
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.AtlasSlot
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.AtlasImageElement
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.isSmaller
import glm_.vec2.Vec2i
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
abstract class BackgroundedContainerScreen<C : Container>(
guiRenderer: GUIRenderer,
container: C,
background: AtlasElement?,
items: Int2ObjectOpenHashMap<AtlasSlot> = background?.slots ?: Int2ObjectOpenHashMap(),
) : ContainerScreen<C>(guiRenderer, container, items) {
private val containerBackground = AtlasImageElement(guiRenderer, background)
override val customRenderer: Boolean get() = true
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
val centerOffset = offset + (size - containerBackground.size) / 2
super.forceRender(centerOffset, consumer, options)
containerBackground.render(centerOffset, consumer, options)
forceRenderContainerScreen(centerOffset, consumer, options)
}
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
val centerOffset = (size - containerBackground.size) / 2
if (position isSmaller centerOffset) {
return null
}
return super.getAt(position - centerOffset)
}
}

View File

@ -0,0 +1,30 @@
/*
* 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.gui.rendering.gui.gui.screen.container
import de.bixilon.kutil.cast.CastUtil.unsafeCast
import de.bixilon.minosoft.data.container.Container
import de.bixilon.minosoft.data.registries.factory.clazz.mapping.DefaultClassMappingFactory
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.generic.GenericContainerScreen
object ContainerGUIFactories : DefaultClassMappingFactory<ContainerGUIFactory<*, *>>(
GenericContainerScreen,
) {
fun build(guiRenderer: GUIRenderer, container: Container): ContainerScreen<*>? {
val factory = this.forObject(container)?.unsafeCast<ContainerGUIFactory<ContainerScreen<Container>, Container>>() ?: return null
return factory.build(guiRenderer, container)
}
}

View File

@ -0,0 +1,23 @@
/*
* 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.gui.rendering.gui.gui.screen.container
import de.bixilon.minosoft.data.container.Container
import de.bixilon.minosoft.data.registries.factory.clazz.mapping.ClassMappingFactory
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
interface ContainerGUIFactory<T : ContainerScreen<C>, C : Container> : ClassMappingFactory<C> {
fun build(guiRenderer: GUIRenderer, container: C): T
}

View File

@ -0,0 +1,73 @@
/*
* 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.gui.rendering.gui.gui.screen.container
import de.bixilon.minosoft.config.key.KeyAction
import de.bixilon.minosoft.config.key.KeyBinding
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.container.Container
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
import de.bixilon.minosoft.gui.rendering.gui.gui.LayoutedGUIElement
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.inventory.LocalInventoryScreen
import de.bixilon.minosoft.modding.event.events.container.ContainerCloseEvent
import de.bixilon.minosoft.modding.event.events.container.ContainerOpenEvent
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
import de.bixilon.minosoft.util.KUtil.toResourceLocation
object ContainerGUIManager {
private fun registerLocalContainerEvent(guiRenderer: GUIRenderer) {
guiRenderer.renderWindow.inputHandler.registerKeyCallback("minosoft:local_inventory".toResourceLocation(), KeyBinding(
mapOf(
KeyAction.PRESS to setOf(KeyCodes.KEY_E),
),
)) { guiRenderer.gui.open(LocalInventoryScreen) }
}
fun open(guiRenderer: GUIRenderer, container: Container) {
val screen = ContainerGUIFactories.build(guiRenderer, container) ?: throw Exception("Can not open $container: No factory! (Probably not yet implemented)")
for (element in guiRenderer.gui.elementOrder.toList()) {
if (element !is LayoutedGUIElement<*>) {
continue
}
if (element.element !is ContainerScreen<*>) {
continue
}
guiRenderer.gui.pop(element)
}
guiRenderer.gui.push(screen)
}
fun close(guiRenderer: GUIRenderer, container: Container) {
for (element in guiRenderer.gui.elementOrder) {
if (element !is LayoutedGUIElement<*>) {
continue
}
if (element.element !is ContainerScreen<*>) {
continue
}
if (element.element.container == container) {
guiRenderer.gui.pop(element)
break
}
}
}
fun register(guiRenderer: GUIRenderer) {
registerLocalContainerEvent(guiRenderer)
guiRenderer.connection.registerEvent(CallbackEventInvoker.of<ContainerOpenEvent> { open(guiRenderer, it.container) })
guiRenderer.connection.registerEvent(CallbackEventInvoker.of<ContainerCloseEvent> { close(guiRenderer, it.container) })
}
}

View File

@ -15,39 +15,37 @@ package de.bixilon.minosoft.gui.rendering.gui.gui.screen.container
import de.bixilon.minosoft.data.container.Container
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.AtlasSlot
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.gui.rendering.gui.elements.items.ContainerItemsElement
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.AtlasImageElement
import de.bixilon.minosoft.gui.rendering.gui.gui.AbstractLayout
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.Screen
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 glm_.vec2.Vec2i
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
abstract class ContainerScreen(
abstract class ContainerScreen<C : Container>(
guiRenderer: GUIRenderer,
val container: Container,
background: AtlasElement,
items: Int2ObjectOpenHashMap<AtlasSlot> = background.slots,
val container: C,
items: Int2ObjectOpenHashMap<AtlasSlot>,
) : Screen(guiRenderer), AbstractLayout<Element> {
private val containerBackground = AtlasImageElement(guiRenderer, background)
protected val containerElement = ContainerItemsElement(guiRenderer, container, items).apply { parent = this@ContainerScreen }
protected open val containerElement = ContainerItemsElement(guiRenderer, container, items).apply { parent = this@ContainerScreen }
override var activeElement: Element? = null
override var activeDragElement: Element? = null
protected open val customRenderer: Boolean = false
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
super.forceRender(offset, consumer, options)
if (customRenderer) {
return
}
forceRenderContainerScreen(offset, consumer, options)
}
val centerOffset = offset + (size - containerBackground.size) / 2
containerBackground.render(centerOffset, consumer, options)
containerElement.render(centerOffset, consumer, options)
protected fun forceRenderContainerScreen(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
containerElement.render(offset, consumer, options)
}
override fun forceSilentApply() {
@ -56,15 +54,10 @@ abstract class ContainerScreen(
}
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
val centerOffset = (size - containerBackground.size) / 2
if (position isSmaller centerOffset) {
if (position isGreater containerElement.size) {
return null
}
val offset = position - centerOffset
if (offset isGreater containerElement.size) {
return null
}
return Pair(containerElement, offset)
return Pair(containerElement, position)
}
override fun onClose() {

View File

@ -0,0 +1,107 @@
/*
* Minosoft
* Copyright (C) 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.gui.rendering.gui.gui.screen.container.generic
import de.bixilon.minosoft.data.container.types.generic.GenericContainer
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.AtlasSlot
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.gui.rendering.gui.elements.items.ContainerItemsElement
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.AtlasImageElement
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.ContainerGUIFactory
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.ContainerScreen
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.EMPTY
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.isSmaller
import glm_.vec2.Vec2i
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import kotlin.reflect.KClass
open class GenericContainerScreen(
guiRenderer: GUIRenderer,
container: GenericContainer,
) : ContainerScreen<GenericContainer>(
guiRenderer,
container,
Int2ObjectOpenHashMap(),
) {
private val headerAtlas = guiRenderer.atlasManager["minecraft:generic_container_header"]
private val slotRowAtlas = guiRenderer.atlasManager["minecraft:generic_container_slot_row"]
private val footerAtlas = guiRenderer.atlasManager["minecraft:generic_container_footer"]
private val header = AtlasImageElement(guiRenderer, headerAtlas)
private val slotRow = AtlasImageElement(guiRenderer, slotRowAtlas)
private val footer = AtlasImageElement(guiRenderer, footerAtlas)
override val containerElement = ContainerItemsElement(guiRenderer, container, calculateSlots()).apply { parent = this@GenericContainerScreen }
override val customRenderer: Boolean get() = true
private val containerSize = Vec2i(maxOf(header.size.x, slotRow.size.x, footer.size.x), header.size.y + slotRow.size.y * container.rows + footer.size.y)
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
val centerOffset = (size - containerSize) / 2
val initialOffset = Vec2i(centerOffset)
super.forceRender(centerOffset, consumer, options)
header.render(centerOffset, consumer, options)
centerOffset.y += header.size.y
for (i in 0 until container.rows) {
slotRow.render(centerOffset, consumer, options)
centerOffset.y += slotRow.size.y
}
footer.render(centerOffset, consumer, options)
forceRenderContainerScreen(initialOffset, consumer, options)
}
override fun getAt(position: Vec2i): Pair<Element, Vec2i>? {
val centerOffset = (size - Vec2i.EMPTY) / 2
if (position isSmaller centerOffset) {
return null
}
return super.getAt(position - centerOffset)
}
private fun calculateSlots(): Int2ObjectOpenHashMap<AtlasSlot> {
val slots: Int2ObjectOpenHashMap<AtlasSlot> = Int2ObjectOpenHashMap()
var slotOffset = 0
val offset = Vec2i(0, 0)
fun pushElement(atlasElement: AtlasElement) {
for ((slotId, slot) in atlasElement.slots) {
slots[slotId + slotOffset] = AtlasSlot(slot.start + offset, slot.end + offset)
}
slotOffset += atlasElement.slots.size
offset.y += atlasElement.size.y
}
headerAtlas?.let { pushElement(it) }
slotRowAtlas?.let {
for (row in 0 until container.rows) {
pushElement(it)
}
}
footerAtlas?.let { pushElement(it) }
return slots
}
companion object : ContainerGUIFactory<GenericContainerScreen, GenericContainer> {
override val clazz: KClass<GenericContainer> = GenericContainer::class
override fun build(guiRenderer: GUIRenderer, container: GenericContainer): GenericContainerScreen {
return GenericContainerScreen(guiRenderer, container)
}
}
}

View File

@ -15,14 +15,14 @@ package de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.inventory
import de.bixilon.minosoft.data.container.types.PlayerInventory
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.ContainerScreen
import de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.BackgroundedContainerScreen
import de.bixilon.minosoft.util.KUtil.toResourceLocation
open class InventoryScreen(
guiRenderer: GUIRenderer,
val inventory: PlayerInventory,
) : ContainerScreen(
container: PlayerInventory,
) : BackgroundedContainerScreen<PlayerInventory>(
guiRenderer,
inventory,
guiRenderer.atlasManager["minecraft:inventory_base".toResourceLocation()]!!,
container,
guiRenderer.atlasManager["minecraft:inventory_base".toResourceLocation()],
)

View File

@ -13,13 +13,9 @@
package de.bixilon.minosoft.gui.rendering.gui.gui.screen.container.inventory
import de.bixilon.minosoft.config.key.KeyAction
import de.bixilon.minosoft.config.key.KeyBinding
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
import de.bixilon.minosoft.gui.rendering.gui.gui.GUIBuilder
import de.bixilon.minosoft.gui.rendering.gui.gui.LayoutedGUIElement
import de.bixilon.minosoft.util.KUtil.toResourceLocation
class LocalInventoryScreen(guiRenderer: GUIRenderer) : InventoryScreen(guiRenderer, guiRenderer.connection.player.inventory) {
@ -29,13 +25,5 @@ class LocalInventoryScreen(guiRenderer: GUIRenderer) : InventoryScreen(guiRender
override fun build(guiRenderer: GUIRenderer): LayoutedGUIElement<LocalInventoryScreen> {
return LayoutedGUIElement(LocalInventoryScreen(guiRenderer))
}
override fun register(guiRenderer: GUIRenderer) {
guiRenderer.renderWindow.inputHandler.registerKeyCallback("minosoft:local_inventory".toResourceLocation(), KeyBinding(
mapOf(
KeyAction.PRESS to setOf(KeyCodes.KEY_E),
),
)) { guiRenderer.gui.open(LocalInventoryScreen) }
}
}
}

View File

@ -26,8 +26,8 @@ import glm_.vec2.Vec2i
class HotbarAirElement(guiRenderer: GUIRenderer) : Element(guiRenderer), Pollable {
private val water = guiRenderer.renderWindow.connection.registries.fluidRegistry[DefaultFluids.WATER]!!
private val airBubble = guiRenderer.atlasManager["minecraft:air_bubble"]!!
private val poppingAirBubble = guiRenderer.atlasManager["minecraft:popping_air_bubble"]!!
private val airBubble = guiRenderer.atlasManager["minecraft:air_bubble"]
private val poppingAirBubble = guiRenderer.atlasManager["minecraft:popping_air_bubble"]
init {
forceSilentApply()

View File

@ -34,12 +34,12 @@ class HotbarExperienceBarElement(guiRenderer: GUIRenderer) : Element(guiRenderer
*/
private val atlasElements = arrayOf(
arrayOf(
guiRenderer.atlasManager["minecraft:empty_experience_bar"]!!,
guiRenderer.atlasManager["minecraft:full_experience_bar"]!!,
guiRenderer.atlasManager["minecraft:empty_experience_bar"],
guiRenderer.atlasManager["minecraft:full_experience_bar"],
),
arrayOf(
guiRenderer.atlasManager["minecraft:empty_horse_jump_bar"]!!,
guiRenderer.atlasManager["minecraft:full_horse_jump_bar"]!!,
guiRenderer.atlasManager["minecraft:empty_horse_jump_bar"],
guiRenderer.atlasManager["minecraft:full_horse_jump_bar"],
),
)

View File

@ -23,9 +23,9 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
import glm_.vec2.Vec2i
class HotbarProtectionElement(guiRenderer: GUIRenderer) : Element(guiRenderer), Pollable {
private val emptyProtection = guiRenderer.atlasManager["minecraft:empty_protection"]!!
private val halfProtection = guiRenderer.atlasManager["minecraft:half_protection"]!!
private val fullProtection = guiRenderer.atlasManager["minecraft:full_protection"]!!
private val emptyProtection = guiRenderer.atlasManager["minecraft:empty_protection"]
private val halfProtection = guiRenderer.atlasManager["minecraft:half_protection"]
private val fullProtection = guiRenderer.atlasManager["minecraft:full_protection"]
init {
forceSilentApply()

View File

@ -31,13 +31,13 @@ import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
class CrosshairHUDElement(guiRenderer: GUIRenderer) : CustomHUDElement(guiRenderer) {
private val profile = guiRenderer.connection.profiles.gui
private val crosshairProfile = profile.hud.crosshair
private lateinit var crosshairAtlasElement: AtlasElement
private var crosshairAtlasElement: AtlasElement? = null
private var mesh: GUIMesh? = null
private var previousDebugEnabled: Boolean? = true
private var reapply = true
override fun init() {
crosshairAtlasElement = guiRenderer.atlasManager[ATLAS_NAME]!!
crosshairAtlasElement = guiRenderer.atlasManager[ATLAS_NAME]
crosshairProfile::color.profileWatch(this, profile = profile) { reapply = true }
}
@ -64,6 +64,7 @@ class CrosshairHUDElement(guiRenderer: GUIRenderer) : CustomHUDElement(guiRender
override fun apply() {
mesh?.unload()
this.mesh = null
val crosshairAtlasElement = crosshairAtlasElement ?: return
val mesh = GUIMesh(renderWindow, guiRenderer.matrix, DirectArrayFloatList(42))

View File

@ -0,0 +1,24 @@
/*
* 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.container.Container
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
class ContainerCloseEvent(
connection: PlayConnection,
val containerId: Int,
val container: Container,
) : PlayConnectionEvent(connection)

View File

@ -0,0 +1,24 @@
/*
* 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.container.Container
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
class ContainerOpenEvent(
connection: PlayConnection,
val containerId: Int,
val container: Container,
) : PlayConnectionEvent(connection)

View File

@ -12,6 +12,7 @@
*/
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
@ -25,8 +26,9 @@ class CloseContainerS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
val containerId: Int = buffer.readUnsignedByte()
override fun handle(connection: PlayConnection) {
connection.player.containers[containerId]?.onClose()
// ToDo: Send event to gui
val container = connection.player.containers[containerId] ?: return
container.onClose()
connection.fireEvent(ContainerCloseEvent(connection, containerId, container))
}
override fun log(reducedLog: Boolean) {

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play.container
import de.bixilon.minosoft.data.container.DefaultInventoryTypes
import de.bixilon.minosoft.data.registries.other.containers.ContainerType
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.modding.event.events.container.ContainerOpenEvent
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
@ -77,7 +78,8 @@ class OpenContainerS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
}
}
connection.player.containers[containerId] = container
// ToDo: Open GUI
connection.fireEvent(ContainerOpenEvent(connection, containerId, container))
}
override fun log(reducedLog: Boolean) {

View File

@ -905,5 +905,64 @@
}
}
}
},
"minecraft:generic_container_header": {
"0": {
"start": [0, 0],
"end": [176, 17],
"texture": "minecraft:textures/gui/container/generic_54.png"
}
},
"minecraft:generic_container_slot_row": {
"0": {
"start": [0, 17],
"end": [176, 35],
"texture": "minecraft:textures/gui/container/generic_54.png",
"slots": {
"0": {
"start": [8, 1],
"end": [25, 18]
},
"1": {
"start": [26, 1],
"end": [43, 18]
},
"2": {
"start": [44, 1],
"end": [61, 18]
},
"3": {
"start": [62, 1],
"end": [79, 18]
},
"4": {
"start": [80, 1],
"end": [97, 18]
},
"5": {
"start": [98, 1],
"end": [115, 18]
},
"6": {
"start": [116, 1],
"end": [133, 18]
},
"7": {
"start": [134, 1],
"end": [151, 18]
},
"8": {
"start": [152, 1],
"end": [169, 18]
}
}
}
},
"minecraft:generic_container_footer": {
"0": {
"start": [0, 125],
"end": [176, 222],
"texture": "minecraft:textures/gui/container/generic_54.png"
}
}
}