New item viewer screen, that just does absolutely nothing

This commit is contained in:
DBotThePony 2022-06-28 19:41:40 +07:00
parent a401e7cf99
commit 4bb8f999d1
Signed by: DBot
GPG Key ID: DCC23B5715498507
8 changed files with 264 additions and 21 deletions

View File

@ -8,6 +8,7 @@ import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.block.entity.EnergyCounterPacket;
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings;
import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket;
import ru.dbotthepony.mc.otm.item.weapon.WeaponScopePacket;
import ru.dbotthepony.mc.otm.item.weapon.WeaponFireInputPacket;
@ -304,5 +305,14 @@ public class MatteryNetworking {
ItemFilterSlotPacket::play
// Optional.of(NetworkDirection.)
);
CHANNEL.registerMessage(
next_network_id++,
ItemMonitorPlayerSettings.class,
ItemMonitorPlayerSettings::write,
ItemMonitorPlayerSettings.Companion::read,
ItemMonitorPlayerSettings::play
// Optional.of(NetworkDirection.)
);
}
}

View File

@ -169,3 +169,20 @@ val ItemStack.tagNotNull: CompoundTag get() = orCreateTag
inline var Entity.position: Vec3
get() = position()
set(value) { setPos(value) }
inline val <reified T : Enum<T>> T.next: T get() {
val values = enumValues<T>()
val next = (ordinal + 1) % values.size
return values[next]
}
inline val <reified T : Enum<T>> T.prev: T get() {
val values = enumValues<T>()
var next = ordinal - 1
if (next < 0) {
next = values.size - 1
}
return values[next]
}

View File

@ -2,23 +2,127 @@ package ru.dbotthepony.mc.otm.block.entity.storage
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.StringTag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.network.NetworkEvent
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set
import java.util.UUID
import java.util.function.Supplier
class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag> {
enum class MatchMode {
FUZZY,
EXACT
}
enum class Target {
SYSTEM,
INVENTORY
}
enum class Amount {
ONE,
STACK,
FULL
}
var ingredientMatchingMode: MatchMode = MatchMode.FUZZY
var ingredientPriority = Target.SYSTEM
var resultTarget = Target.INVENTORY
var craftingAmount = Amount.STACK
override fun serializeNBT(): CompoundTag {
return CompoundTag().also {
it["ingredientMatchingMode"] = ingredientMatchingMode.name
it["ingredientPriority"] = ingredientPriority.name
it["resultTarget"] = resultTarget.name
it["craftingAmount"] = craftingAmount.name
}
}
override fun deserializeNBT(nbt: CompoundTag) {
nbt.ifHas("ingredientMatchingMode", StringTag::class.java) { ingredientMatchingMode = MatchMode.valueOf(it.asString) }
nbt.ifHas("ingredientPriority", StringTag::class.java) { ingredientPriority = Target.valueOf(it.asString) }
nbt.ifHas("resultTarget", StringTag::class.java) { resultTarget = Target.valueOf(it.asString) }
nbt.ifHas("craftingAmount", StringTag::class.java) { craftingAmount = Amount.valueOf(it.asString) }
}
fun read(buff: FriendlyByteBuf) {
ingredientMatchingMode = buff.readEnum(MatchMode::class.java)
ingredientPriority = buff.readEnum(Target::class.java)
resultTarget = buff.readEnum(Target::class.java)
craftingAmount = buff.readEnum(Amount::class.java)
}
fun read(other: ItemMonitorPlayerSettings) {
ingredientMatchingMode = other.ingredientMatchingMode
ingredientPriority = other.ingredientPriority
resultTarget = other.resultTarget
craftingAmount = other.craftingAmount
}
fun write(buff: FriendlyByteBuf) {
buff.writeEnum(ingredientMatchingMode)
buff.writeEnum(ingredientPriority)
buff.writeEnum(resultTarget)
buff.writeEnum(craftingAmount)
}
private fun playClient() {
val ply = minecraft.player ?: throw IllegalStateException("Player is missing")
val container = ply.containerMenu as? ItemMonitorMenu ?: return LOGGER.error("Received ItemMonitorPlayerSettings but container is missing or not of right type ({})!", ply.containerMenu)
container.settings.read(this)
}
private fun playServer(ply: ServerPlayer) {
val container = ply.containerMenu as? ItemMonitorMenu ?: return LOGGER.error("Received ItemMonitorPlayerSettings from {} but container is missing or not of right type ({})!", ply, ply.containerMenu)
container.settings.read(this)
(container.tile as ItemMonitorBlockEntity).setChangedLight()
}
fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
val ply = context.get().sender
if (ply != null) {
playServer(ply)
} else {
playClient()
}
}
companion object {
fun read(buff: FriendlyByteBuf): ItemMonitorPlayerSettings {
return ItemMonitorPlayerSettings().also { it.read(buff) }
}
private val LOGGER = LogManager.getLogger()
}
}
class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.ITEM_MONITOR, p_155229_, p_155230_) {
@ -26,6 +130,37 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override val energy = WorkerEnergyStorage(this)
val cell = BasicStorageGraphNode(energy)
val settings = HashMap<UUID, ItemMonitorPlayerSettings>()
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt.put("player_settings", CompoundTag().also {
for ((key, value) in this.settings) {
it[key.toString()] = value.serializeNBT()
}
})
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
this.settings.clear()
val settings = nbt.getCompound("player_settings")
for (key in settings.allKeys) {
val uuid = UUID.fromString(key)
val deserialized = ItemMonitorPlayerSettings()
deserialized.deserializeNBT(settings.getCompound(key))
check(this.settings.put(uuid, deserialized) == null) { "Duplicate UUID??? $uuid" }
}
}
fun getSettings(ply: ServerPlayer): ItemMonitorPlayerSettings {
return settings.computeIfAbsent(ply.uuid) { ItemMonitorPlayerSettings() }
}
fun tick() {
batteryChargeLoop()
cell.tickEnergyDemanding()

View File

@ -5,20 +5,21 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings
import ru.dbotthepony.mc.otm.client.render.RenderHelper
import ru.dbotthepony.mc.otm.client.render.SkinGrid
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu
import ru.dbotthepony.mc.otm.next
import ru.dbotthepony.mc.otm.prev
class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Component) :
MatteryScreen<ItemMonitorMenu>(menu, inventory, title) {
override fun makeMainFrame(): FramePanel {
val frame = object : FramePanel(this@ItemMonitorScreen, null, 0f, 0f, FRAME_WIDTH, FRAME_HEIGHT, getTitle()) {
override fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) {
super.innerRender(stack, mouse_x, mouse_y, flag)
// ProgressGaugePanel.GAUGE_BACKGROUND.render(stack, 28f + 3 * 18f + 6f, (ITEM_GRID_HEIGHT + 1) * 18f + 16f + 6f)
}
}
val frame = FramePanel(this@ItemMonitorScreen, null, 0f, 0f, FRAME_WIDTH, FRAME_HEIGHT, getTitle())
val topPanel = EditablePanel(this, frame)
topPanel.height = ITEM_GRID_HEIGHT * 18f
@ -82,8 +83,32 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
val arrowLine = EditablePanel(this, arrowAndButtons, y = 8f, height = 8f, width = arrowAndButtons.width)
val autoRefillMatchMode = SmallSquareButtonPanel(this, arrowLine)
val refillPriority = SmallSquareButtonPanel(this, arrowLine)
val autoRefillMatchMode = SmallSquareButtonPanel(this, arrowLine, skinElement = { REFILL_MATCH_MODE[menu.settings.ingredientMatchingMode.ordinal] }) {
when (it) {
0 -> menu.settings.ingredientMatchingMode = menu.settings.ingredientMatchingMode.next
1 -> menu.settings.ingredientMatchingMode = menu.settings.ingredientMatchingMode.prev
}
menu.sendSettingsToServer()
}
val refillPriority = object : SmallSquareButtonPanel(this@ItemMonitorScreen, arrowLine, lambdaOnPress = {
when (it) {
0 -> menu.settings.ingredientPriority = menu.settings.ingredientPriority.next
1 -> menu.settings.ingredientPriority = menu.settings.ingredientPriority.prev
}
menu.sendSettingsToServer()
}) {
override fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) {
super.innerRender(stack, mouse_x, mouse_y, flag)
when (menu.settings.ingredientPriority) {
ItemMonitorPlayerSettings.Target.SYSTEM -> ARROW.render(stack, 0f, 0f, width, height, UVWindingOrder.FLIP)
ItemMonitorPlayerSettings.Target.INVENTORY -> ARROW.render(stack)
}
}
}
refillPriority.setDockMargin(2f)
@ -101,8 +126,32 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
}
}
val whereToPutResult = SmallSquareButtonPanel(this, resultAndButtons, y = 8f)
val howMuchToCraft = SmallSquareButtonPanel(this, resultAndButtons, x = 10f, y = 8f)
object : SmallSquareButtonPanel(this@ItemMonitorScreen, resultAndButtons, y = 8f, lambdaOnPress = {
when (it) {
0 -> menu.settings.resultTarget = menu.settings.resultTarget.next
1 -> menu.settings.resultTarget = menu.settings.resultTarget.prev
}
menu.sendSettingsToServer()
}) {
override fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) {
super.innerRender(stack, mouse_x, mouse_y, flag)
when (menu.settings.resultTarget) {
ItemMonitorPlayerSettings.Target.SYSTEM -> ARROW.render(stack, 0f, 0f, width, height, UVWindingOrder.FLIP)
ItemMonitorPlayerSettings.Target.INVENTORY -> ARROW.render(stack)
}
}
}
SmallSquareButtonPanel(this, resultAndButtons, x = 10f, y = 8f, skinElement = { HOW_MUCH_TO_CRAFT[menu.settings.craftingAmount.ordinal] }) {
when (it) {
0 -> menu.settings.craftingAmount = menu.settings.craftingAmount.next
1 -> menu.settings.craftingAmount = menu.settings.craftingAmount.prev
}
menu.sendSettingsToServer()
}
val craftingHistory = GridPanel(this, bottomPanel, width = 3 * 18f, height = 3 * 18f, columns = 3, rows = 3)
craftingHistory.dock = Dock.LEFT
@ -133,5 +182,14 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
const val ITEM_GRID_WIDTH = 9
const val ITEM_GRID_HEIGHT = 5
val ARROW = SkinGrid.WIDGETS_8[1, 0]
val S = SkinGrid.WIDGETS_8[2, 0]
val F = SkinGrid.WIDGETS_8[3, 0]
val E = SkinGrid.WIDGETS_8[4, 0]
val ONE = SkinGrid.WIDGETS_8[5, 0]
val HOW_MUCH_TO_CRAFT = listOf(ONE, S, F)
val REFILL_MATCH_MODE = listOf(F, E)
}
}

View File

@ -61,8 +61,8 @@ abstract class SquareButtonPanel(
y: Float = 0f,
width: Float,
height: Float,
var skinElement: SkinElement? = null,
val lambdaOnPress: (() -> Unit)? = null,
val skinElement: (() -> SkinElement)? = null,
val lambdaOnPress: ((clickButton: Int) -> Unit)? = null,
) : EditablePanel(screen, parent, x, y, width, height) {
protected var pressed = false
@ -91,7 +91,7 @@ abstract class SquareButtonPanel(
IDLE.render(stack, 0f, 0f, width, height)
}
skinElement?.render(stack, 0f, 0f, width, height)
skinElement?.invoke()?.render(stack, 0f, 0f, width, height)
}
override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean {
@ -112,7 +112,7 @@ abstract class SquareButtonPanel(
pressed = false
if (isHovered) {
lambdaOnPress?.invoke()
lambdaOnPress?.invoke(flag)
}
}
@ -129,8 +129,8 @@ open class LargeSquareButtonPanel(
y: Float = 0f,
width: Float = SIZE,
height: Float = SIZE,
skinElement: SkinElement? = null,
lambdaOnPress: (() -> Unit)? = null,
skinElement: (() -> SkinElement)? = null,
lambdaOnPress: ((clickButton: Int) -> Unit)? = null,
) : SquareButtonPanel(screen, parent, x, y, width, height, skinElement, lambdaOnPress) {
final override val IDLE = SkinGrid.WIDGETS_18[0, 0]
final override val HOVERED = SkinGrid.WIDGETS_18[1, 0]
@ -148,8 +148,8 @@ open class SmallSquareButtonPanel(
y: Float = 0f,
width: Float = SIZE,
height: Float = SIZE,
skinElement: SkinElement? = null,
lambdaOnPress: (() -> Unit)? = null,
skinElement: (() -> SkinElement)? = null,
lambdaOnPress: ((clickButton: Int) -> Unit)? = null,
) : SquareButtonPanel(screen, parent, x, y, width, height, skinElement, lambdaOnPress) {
final override val IDLE = SkinGrid.WIDGETS_8[0, 0]
final override val HOVERED = SkinGrid.WIDGETS_8[0, 0]

View File

@ -1,12 +1,17 @@
package ru.dbotthepony.mc.otm.menu
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraftforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.orThrow
import ru.dbotthepony.mc.otm.registry.MMenus
import ru.dbotthepony.mc.otm.storage.*
@ -20,6 +25,9 @@ class ItemMonitorMenu @JvmOverloads constructor(
private val subscribed: VirtualComponent<ItemStackWrapper>?
private val local: PoweredVirtualComponent<ItemStackWrapper>?
val settings: ItemMonitorPlayerSettings = tile?.getSettings(inventory.player as ServerPlayer) ?: ItemMonitorPlayerSettings()
private var settingsNetworked = false
override fun getNetworkedItemView(): NetworkedItemView {
return view
}
@ -27,7 +35,7 @@ class ItemMonitorMenu @JvmOverloads constructor(
init {
if (tile != null) {
subscribed = tile.cell.storageGraph!!.getVirtualComponent(ITEM_STORAGE)
local = PoweredVirtualComponent(subscribed, tile.getCapability(MatteryCapability.ENERGY).resolve().get())
local = PoweredVirtualComponent(subscribed, tile.getCapability(MatteryCapability.ENERGY).orThrow())
view.setComponent(local)
} else {
subscribed = null
@ -37,6 +45,16 @@ class ItemMonitorMenu @JvmOverloads constructor(
addInventorySlots()
}
override fun broadcastFullState() {
super.broadcastFullState()
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with { ply as ServerPlayer }, settings)
settingsNetworked = true
}
fun sendSettingsToServer() {
MatteryNetworking.CHANNEL.sendToServer(settings)
}
override fun removed(p_38940_: Player) {
super.removed(p_38940_)
view.removed()
@ -46,6 +64,11 @@ class ItemMonitorMenu @JvmOverloads constructor(
override fun broadcastChanges() {
super.broadcastChanges()
view.network()
if (!settingsNetworked) {
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with { ply as ServerPlayer }, settings)
settingsNetworked = true
}
}
override fun getWorkingSlotStart(): Int {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 727 B

After

Width:  |  Height:  |  Size: 731 B