Display equipment in energy servo, display curios in android station

This commit is contained in:
DBotThePony 2023-03-02 20:55:41 +07:00
parent 193489021b
commit d151fd6727
Signed by: DBot
GPG Key ID: DCC23B5715498507
10 changed files with 171 additions and 116 deletions

View File

@ -97,18 +97,13 @@ class ExoPackInventoryScreen(menu: ExoPackInventoryMenu) : MatteryScreen<ExoPack
}
}
val topLine = EditablePanel(this, frame, height = 18f * 4f)
val topLine = EditablePanel(this, frame, height = PlayerEquipmentPanel.HEIGHT)
topLine.dock = Dock.TOP
topLine.setDockMargin(top = 3f)
makeArmorStrip(menu.armorSlots, topLine).also {
it.dock = Dock.LEFT
}
val playerRectangle = EntityRendererPanel(this, topLine, minecraft!!.player!!)
playerRectangle.dock = Dock.LEFT
playerRectangle.setDockMargin(right = 3f)
val equipment = PlayerEquipmentPanel(this, topLine, armorSlots = menu.armorSlots)
equipment.dock = Dock.LEFT
equipment.setDockMargin(right = 3f)
val craftingCanvas = EditablePanel(this, topLine, width = 90f)
craftingCanvas.dock = Dock.LEFT
@ -171,32 +166,10 @@ class ExoPackInventoryScreen(menu: ExoPackInventoryMenu) : MatteryScreen<ExoPack
var x = -4f
if (menu.curiosSlots.isNotEmpty()) {
val curiosWidth = if (menu.curiosSlots.stream().anyMatch { it.second != null }) AbstractSlotPanel.SIZE * 2f else AbstractSlotPanel.SIZE
val curiosHeight = menu.curiosSlots.size.coerceAtMost(4) * AbstractSlotPanel.SIZE
val curios = makeCuriosPanel(this, frame, menu.curiosSlots)!!
val curiosRect =
if (menu.curiosSlots.size > 4)
ScrollbarBackgroundPanel.padded(this, frame, x,
width = curiosWidth,
height = curiosHeight, alwaysShowScrollbar = true)
else
BackgroundPanel.padded(this, frame, x,
width = curiosWidth,
height = curiosHeight)
x -= curiosRect.width
curiosRect.x = x
for ((slot, cosmetic) in menu.curiosSlots) {
val row = EditablePanel(this, if (curiosRect is ScrollbarBackgroundPanel) curiosRect.canvas else curiosRect, height = AbstractSlotPanel.SIZE)
row.dock = Dock.TOP
SlotPanel(this, row, slot).dock = Dock.RIGHT
if (cosmetic != null) {
SlotPanel(this, row, cosmetic).dock = Dock.LEFT
}
}
x -= curios.width
curios.x = x
}
EffectListPanel(this, frame, menu.ply, x - 56f, gridHeight = 6).tick()

View File

@ -29,6 +29,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollBarConstants
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton
import ru.dbotthepony.mc.otm.core.math.integerDivisionDown
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.PlayerSlot
import java.util.Collections
/**
@ -583,30 +584,6 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
}
}
fun makeArmorStrip(slots: Collection<Pair<MatteryMenu.EquipmentSlot, Slot?>>, parent: EditablePanel<*>? = null): EditablePanel<*> {
val armorSlotsStrip = EditablePanel(this, parent, width = 18f)
armorSlotsStrip.dock = Dock.LEFT
for ((slot, cosmeticSlot) in slots) {
if (cosmeticSlot == null) {
SlotPanel(this, armorSlotsStrip, slot).also {
it.dock = Dock.TOP
}
} else {
FoldableSlotPanel(this, armorSlotsStrip,
SlotPanel(this, null, slot).also {
CosmeticToggleButton(this, it, slot.type)
},
listOf(SlotPanel(this, null, cosmeticSlot))
).also {
it.dock = Dock.TOP
}
}
}
return armorSlotsStrip
}
companion object {
const val DEFAULT_FRAME_WIDTH = AbstractSlotPanel.SIZE * 9f + 16f
const val DEFAULT_FRAME_HEIGHT = 100f

View File

@ -0,0 +1,81 @@
package ru.dbotthepony.mc.otm.client.screen.panels
import net.minecraft.world.inventory.Slot
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.FoldableSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.BackgroundPanel
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.PlayerSlot
fun <S : MatteryScreen<*>> makeCuriosPanel(screen: S, parent: FramePanel<S>, slots: List<PlayerSlot<Slot, Slot>>, autoAlign: Boolean = false): EditablePanel<S>? {
if (slots.isEmpty()) {
return null
}
val curiosWidth = if (slots.any { it.cosmetic != null }) AbstractSlotPanel.SIZE * 2f else AbstractSlotPanel.SIZE
val curiosHeight = slots.size.coerceAtMost(4) * AbstractSlotPanel.SIZE
val curiosRect =
if (slots.size > 4)
ScrollbarBackgroundPanel.padded(screen, parent, 0f,
width = curiosWidth,
height = curiosHeight, alwaysShowScrollbar = true)
else
BackgroundPanel.padded(screen, parent, 0f,
width = curiosWidth,
height = curiosHeight)
if (autoAlign) {
curiosRect.x = -4f - curiosRect.width
}
for ((slot, cosmetic) in slots) {
val row = EditablePanel(screen, if (curiosRect is ScrollbarBackgroundPanel) curiosRect.canvas else curiosRect, height = AbstractSlotPanel.SIZE)
row.dock = Dock.TOP
SlotPanel(screen, row, slot).dock = Dock.RIGHT
if (cosmetic != null) {
SlotPanel(screen, row, cosmetic).dock = Dock.LEFT
}
}
return curiosRect
}
@Suppress("LeakingThis")
open class PlayerEquipmentPanel<S : MatteryScreen<*>>(
screen: S,
parent: EditablePanel<*>?,
x: Float = 0f,
y: Float = 0f,
val armorSlots: List<PlayerSlot<MatteryMenu.EquipmentSlot, Slot>>
) : EditablePanel<S>(screen, parent, x, y, height = HEIGHT, width = WIDTH) {
val armorSlotsStrip = EditablePanel(screen, this, width = AbstractSlotPanel.SIZE)
val entityPanel = EntityRendererPanel(screen, this, minecraft.player!!)
init {
entityPanel.dock = Dock.LEFT
armorSlotsStrip.dock = Dock.LEFT
for ((slot, cosmeticSlot) in armorSlots) {
if (cosmeticSlot == null) {
SlotPanel(screen, armorSlotsStrip, slot).dock = Dock.TOP
} else {
FoldableSlotPanel(screen, armorSlotsStrip,
SlotPanel(screen, null, slot).also { CosmeticToggleButton(screen, it, slot.type) },
listOf(SlotPanel(screen, null, cosmeticSlot))).dock = Dock.TOP
}
}
}
companion object {
val HEIGHT = EntityRendererPanel.ENTITY_RECTANGLE.height
val WIDTH = AbstractSlotPanel.SIZE + EntityRendererPanel.ENTITY_RECTANGLE.width
}
}

View File

@ -707,17 +707,11 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I
it.dockTop = 6f
}
val playerStrip = EditablePanel(this, frame, height = 72f)
makeCuriosPanel(this, frame, menu.equipment.curiosSlots, autoAlign = true)
val playerStrip = PlayerEquipmentPanel(this, frame, armorSlots = menu.equipment.armorSlots)
playerStrip.dock = Dock.TOP
makeArmorStrip(menu.armorSlots, playerStrip).also {
it.dock = Dock.LEFT
}
EntityRendererPanel(this, playerStrip, minecraft!!.player!!).also {
it.dock = Dock.LEFT
}
val androidStrip = EditablePanel(this, playerStrip, width = AbstractSlotPanel.SIZE)
androidStrip.dock = Dock.LEFT

View File

@ -7,9 +7,12 @@ import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.BatterySlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.DockResizeMode
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
import ru.dbotthepony.mc.otm.client.screen.panels.PlayerEquipmentPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.makeCuriosPanel
import ru.dbotthepony.mc.otm.client.screen.widget.HorizontalPowerGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.TallHorizontalPowerGaugePanel
@ -19,14 +22,23 @@ class EnergyServoScreen(menu: EnergyServoMenu, inventory: Inventory, title: Comp
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
val frame = FramePanel.padded(this,
width = AbstractSlotPanel.SIZE * 2f + HorizontalPowerGaugePanel.GAUGE_BACKGROUND_TALL.width + 8f + ProgressGaugePanel.GAUGE_BACKGROUND.width * 2f,
AbstractSlotPanel.SIZE, title)
AbstractSlotPanel.SIZE + PlayerEquipmentPanel.HEIGHT + 4f, title)
BatterySlotPanel(this, frame, menu.dischargeSlot).also {
val equipment = PlayerEquipmentPanel(this, frame, armorSlots = menu.equipment.armorSlots)
equipment.dock = Dock.FILL
equipment.dockResize = DockResizeMode.NONE
makeCuriosPanel(this, frame, menu.equipment.curiosSlots, autoAlign = true)
val strip = EditablePanel(this, frame, height = AbstractSlotPanel.SIZE)
strip.dock = Dock.BOTTOM
BatterySlotPanel(this, strip, menu.dischargeSlot).also {
it.dock = Dock.LEFT
it.dockRight = 2f
}
object : EditablePanel<EnergyServoScreen>(this@EnergyServoScreen, frame) {
object : EditablePanel<EnergyServoScreen>(this@EnergyServoScreen, strip) {
init {
dock = Dock.LEFT
dockRight = 2f
@ -39,12 +51,12 @@ class EnergyServoScreen(menu: EnergyServoMenu, inventory: Inventory, title: Comp
}
}
TallHorizontalPowerGaugePanel(this, frame, menu.powerGauge).also {
TallHorizontalPowerGaugePanel(this, strip, menu.powerGauge).also {
it.dock = Dock.LEFT
it.dockRight = 2f
}
object : EditablePanel<EnergyServoScreen>(this@EnergyServoScreen, frame) {
object : EditablePanel<EnergyServoScreen>(this@EnergyServoScreen, strip) {
init {
dock = Dock.LEFT
dockRight = 2f
@ -57,7 +69,7 @@ class EnergyServoScreen(menu: EnergyServoMenu, inventory: Inventory, title: Comp
}
}
BatterySlotPanel(this, frame, menu.chargeSlot).also {
BatterySlotPanel(this, strip, menu.chargeSlot).also {
it.dock = Dock.LEFT
it.dockRight
}

View File

@ -10,6 +10,7 @@ import ru.dbotthepony.mc.otm.container.awareStream
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
import ru.dbotthepony.mc.otm.core.orNull
import ru.dbotthepony.mc.otm.menu.PlayerSlot
import top.theillusivec4.curios.api.CuriosApi
import top.theillusivec4.curios.common.inventory.CosmeticCurioSlot
import top.theillusivec4.curios.common.inventory.CurioSlot
@ -20,10 +21,10 @@ val isCuriosLoaded by lazy {
ModList.get().isLoaded(CuriosApi.MODID)
}
private fun Player.getCuriosSlotsImpl(): Collection<Pair<Slot, Slot?>> {
private fun Player.getCuriosSlotsImpl(): List<PlayerSlot<Slot, Slot>> {
val handler = getCapability(MatteryCapability.CURIOS_INVENTORY).orNull() ?: return listOf()
val result = ArrayList<Pair<Slot, Slot?>>()
val result = ArrayList<PlayerSlot<Slot, Slot>>()
val sortedIdentifiers = ArrayList<String>(handler.curios.keys.size)
sortedIdentifiers.addAll(handler.curios.keys)
@ -44,9 +45,9 @@ private fun Player.getCuriosSlotsImpl(): Collection<Pair<Slot, Slot?>> {
if (curio.hasCosmetic()) {
val cosmetic = CosmeticCurioSlot(this, curio.cosmeticStacks, slot, identifier, 0, 0)
result.add(regular to cosmetic)
result.add(PlayerSlot(regular, cosmetic))
} else {
result.add(regular to null)
result.add(PlayerSlot(regular))
}
}
}
@ -58,7 +59,7 @@ private fun Player.getCuriosSlotsImpl(): Collection<Pair<Slot, Slot?>> {
/**
* [Pair]<Regular, Cosmetic>
*/
val Player.curiosSlots: Collection<Pair<Slot, Slot?>> get() {
val Player.curiosSlots: List<PlayerSlot<Slot, Slot>> get() {
if (!isCuriosLoaded) {
return listOf()
}

View File

@ -50,7 +50,10 @@ class ExoPackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
}
}
val armorSlots: List<kotlin.Pair<EquipmentSlot, Slot?>> = makeArmorSlots()
init {
addInventorySlots(autoFrame = false)
craftingSlots.forEach(this::addSlot)
}
val offhandSlot = object : InventorySlot(capability.ply.inventory, 40) {
override fun getNoItemIcon(): Pair<ResourceLocation, ResourceLocation> {
@ -58,19 +61,12 @@ class ExoPackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
}
}
val armorSlots = makeArmorSlots()
val allAccessibleSlots: List<Slot>
init {
addInventorySlots(autoFrame = false)
craftingSlots.forEach(this::addSlot)
addSlot(offhandSlot)
for ((a, b) in armorSlots) {
addSlot(a)
if (b != null) addSlot(b)
}
val builder = ImmutableList.builder<Slot>()
builder.addAll(playerInventorySlots)
@ -80,7 +76,7 @@ class ExoPackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
allAccessibleSlots = builder.build()
}
val curiosSlots: List<kotlin.Pair<Slot, Slot?>> = ImmutableList.copyOf(ply.curiosSlots)
val curiosSlots: ImmutableList<PlayerSlot<Slot, Slot>> = ImmutableList.copyOf(ply.curiosSlots)
init {
for ((a, b) in curiosSlots) {
@ -163,10 +159,10 @@ class ExoPackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
}
for (slot in armorSlots) {
quickMoveMapping[slot.first] = ::playerInventorySlots
quickMoveMapping[slot.functional] = ::playerInventorySlots
if (slot.second != null) {
quickMoveMapping[slot.first] = ::playerInventorySlots
if (slot.cosmetic != null) {
quickMoveMapping[slot.cosmetic] = ::playerInventorySlots
}
}

View File

@ -20,6 +20,7 @@ import net.minecraftforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorSlots
import ru.dbotthepony.mc.otm.compat.curios.curiosSlots
import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot
import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
@ -44,6 +45,13 @@ import java.util.function.Predicate
import java.util.function.Supplier
import kotlin.collections.ArrayList
data class PlayerSlot<A : Slot, B : Slot>(val functional: A, val cosmetic: B? = null)
data class EquipmentSlots(
val armorSlots: List<PlayerSlot<MatteryMenu.EquipmentSlot, Slot>>,
val curiosSlots: List<PlayerSlot<Slot, Slot>>
)
abstract class MatteryMenu @JvmOverloads protected constructor(
menuType: MenuType<*>?,
containerId: Int,
@ -367,10 +375,16 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
abstract val storageSlots: Collection<Slot>
protected val quickMoveMapping = Reference2ObjectOpenHashMap<Slot, () -> Collection<Slot>?>()
/**
* Marks slot as "storage" - shift clicking it will move its contents to Player's inventory
*/
protected fun storage2Inventory(slot: Slot) {
quickMoveMapping[slot] = ::playerInventorySlots
}
/**
* Marks slot as "inventory" - shift clicking it will move its contents to menu's storage slots
*/
protected fun inventory2Storage(slot: Slot) {
quickMoveMapping[slot] = ::storageSlots
}
@ -536,14 +550,31 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
super.addDataSlots(p_38885_)
}
fun makeArmorSlots(): List<kotlin.Pair<EquipmentSlot, Slot?>> {
fun makeArmorSlots(): List<PlayerSlot<EquipmentSlot, Slot>> {
val cosmetic = ply.cosmeticArmorSlots
return ImmutableList.of(
EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.HEAD) to cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.HEAD),
EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.CHEST) to cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.CHEST),
EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.LEGS) to cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.LEGS),
EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.FEET) to cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.FEET),
PlayerSlot(EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.HEAD), cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.HEAD)),
PlayerSlot(EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.CHEST), cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.CHEST)),
PlayerSlot(EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.LEGS), cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.LEGS)),
PlayerSlot(EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.FEET), cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.FEET)),
).also {
for ((a, b) in it) {
addSlot(a)
if (b != null) addSlot(b)
}
}
}
fun makeEquipmentSlots(): EquipmentSlots {
return EquipmentSlots(
armorSlots = makeArmorSlots(),
curiosSlots = ImmutableList.copyOf(ply.curiosSlots).also {
for ((a, b) in it) {
addSlot(a)
if (b != null) addSlot(b)
}
}
)
}

View File

@ -12,6 +12,7 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.mc.otm.block.entity.tech.AndroidStationBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.registry.MMenus
@ -98,12 +99,12 @@ class AndroidStationMenu @JvmOverloads constructor(
return super.mayPickup(player) && powerWidget.level >= AndroidStationBlockEntity.ENERGY_PER_OPERATION
}
override fun mayPlace(p_40231_: ItemStack): Boolean {
override fun mayPlace(itemStack: ItemStack): Boolean {
if (tile is AndroidStationBlockEntity) {
return tile.energy.batteryLevel >= AndroidStationBlockEntity.ENERGY_PER_OPERATION && condition.invoke(p_40231_)
return tile.energy.batteryLevel >= AndroidStationBlockEntity.ENERGY_PER_OPERATION && condition.invoke(itemStack)
}
return powerWidget.level >= AndroidStationBlockEntity.ENERGY_PER_OPERATION && condition.invoke(p_40231_)
return powerWidget.level >= AndroidStationBlockEntity.ENERGY_PER_OPERATION && condition.invoke(itemStack)
}
}
@ -111,28 +112,15 @@ class AndroidStationMenu @JvmOverloads constructor(
it.getCapability(ForgeCapabilities.ENERGY).isPresent
}
override val storageSlots: ImmutableList<Slot>
val armorSlots = makeArmorSlots()
val equipment = makeEquipmentSlots()
init {
for ((a, b) in armorSlots) {
addSlot(a)
if (b != null) addSlot(b)
}
addInventorySlots()
addSlot(androidBattery)
}
val builder = ImmutableList.builder<Slot>()
for ((a, _) in armorSlots) {
builder.add(a)
}
builder.add(androidBattery)
storageSlots = builder.build()
override val storageSlots = immutableList {
accept(androidBattery)
}
override fun stillValid(player: Player): Boolean {

View File

@ -33,6 +33,8 @@ class EnergyServoMenu @JvmOverloads constructor(
}
}
val equipment = makeEquipmentSlots()
val powerGauge = LevelGaugeWidget(this, tile?.energy)
val itemConfig = ItemHandlerPlayerInput(this)
val energyConfig = EnergyPlayerInput(this, true, true)