Button for manual stored experience drain from machine

This commit is contained in:
DBotThePony 2025-01-06 16:45:03 +07:00
parent c5edd9ff59
commit 65cbaf95b1
Signed by: DBot
GPG Key ID: DCC23B5715498507
12 changed files with 134 additions and 6 deletions

View File

@ -1025,7 +1025,9 @@ private fun gui(provider: MatteryLanguageProvider) {
gui("matter_panel.complexity", "Total complexity: %s") gui("matter_panel.complexity", "Total complexity: %s")
gui("experience", "%s experience points") gui("experience", "%s experience points")
gui("experience_with_limit", "%s / %s experience points")
gui("experience_levels", "%s experience levels") gui("experience_levels", "%s experience levels")
gui("experience_levels_with_limit", "%s / %s experience levels")
gui("experience.store", "Store %s experience levels") gui("experience.store", "Store %s experience levels")
gui("experience.store_all", "Store all experience levels") gui("experience.store_all", "Store all experience levels")

View File

@ -1022,7 +1022,9 @@ private fun gui(provider: MatteryLanguageProvider) {
gui("matter_panel.complexity", "Общая сложность: %s") gui("matter_panel.complexity", "Общая сложность: %s")
gui("experience", "%s очков опыта") gui("experience", "%s очков опыта")
gui("experience_with_limit", "%s / %s очков опыта")
gui("experience_levels", "%s уровней опыта") gui("experience_levels", "%s уровней опыта")
gui("experience_levels_with_limit", "%s / %s уровней опыта")
gui("experience.store", "Передать %s уровней опыта") gui("experience.store", "Передать %s уровней опыта")
gui("experience.store_all", "Передать все уровни опыта") gui("experience.store_all", "Передать все уровни опыта")

View File

@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.DockProperty
import ru.dbotthepony.mc.otm.client.screen.panels.DockResizeMode 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.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
@ -55,6 +56,8 @@ class GrillScreen(menu: GrillMenu, inventory: Inventory, title: Component) : Mat
frame.sizeToContents() frame.sizeToContents()
DeviceControls(this, frame, experience = menu.experience)
return frame return frame
} }
} }

View File

@ -71,7 +71,7 @@ class MatterEntanglerScreen(menu: MatterEntanglerMenu, inventory: Inventory, tit
it.dockRight = 20f it.dockRight = 20f
} }
DeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, upgrades = menu.upgrades, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig) DeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, upgrades = menu.upgrades, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig, experience = menu.experience)
return frame return frame
} }

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button
import com.mojang.blaze3d.platform.InputConstants import com.mojang.blaze3d.platform.InputConstants
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
@ -29,12 +30,14 @@ import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel
import ru.dbotthepony.mc.otm.client.screen.tech.EssenceStorageScreen
import ru.dbotthepony.mc.otm.config.ClientConfig import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.util.ItemStackSorter import ru.dbotthepony.mc.otm.core.util.ItemStackSorter
import ru.dbotthepony.mc.otm.core.util.getLevelFromXp
import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.UpgradeSlots import ru.dbotthepony.mc.otm.menu.UpgradeSlots
@ -43,9 +46,15 @@ import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.FluidConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.FluidConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget
import java.util.*
import java.util.function.IntConsumer import java.util.function.IntConsumer
import java.util.function.Predicate import java.util.function.Predicate
import kotlin.NoSuchElementException
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.pow import kotlin.math.pow
private val gunpowder = ItemStackIcon(ItemStack(Items.GUNPOWDER)).fixed() private val gunpowder = ItemStackIcon(ItemStack(Items.GUNPOWDER)).fixed()
@ -314,6 +323,7 @@ class DeviceControls<out S : MatteryScreen<*>>(
val fluidConfig: FluidConfigPlayerInput? = null, val fluidConfig: FluidConfigPlayerInput? = null,
val balanceInputs: BooleanInputWithFeedback? = null, val balanceInputs: BooleanInputWithFeedback? = null,
val upgrades: UpgradeSlots? = null, val upgrades: UpgradeSlots? = null,
val experience: TakeExperienceWidget? = null
) : EditablePanel<S>(screen, parent, x = parent.width + 3f, height = 0f, width = 0f) { ) : EditablePanel<S>(screen, parent, x = parent.width + 3f, height = 0f, width = 0f) {
val itemConfigButton: ButtonPanel<S>? val itemConfigButton: ButtonPanel<S>?
val energyConfigButton: ButtonPanel<S>? val energyConfigButton: ButtonPanel<S>?
@ -321,6 +331,7 @@ class DeviceControls<out S : MatteryScreen<*>>(
val redstoneControlsButton: EnumButtonPanel<S, RedstoneSetting>? val redstoneControlsButton: EnumButtonPanel<S, RedstoneSetting>?
val balanceInputsButton: BooleanButtonPanel<S>? val balanceInputsButton: BooleanButtonPanel<S>?
val upgradesButton: ButtonPanel<S>? val upgradesButton: ButtonPanel<S>?
val experienceButton: ButtonPanel<S>?
init { init {
childrenOrder = -1000 childrenOrder = -1000
@ -334,14 +345,35 @@ class DeviceControls<out S : MatteryScreen<*>>(
buttons.removeIf { it.isRemoved || it.parent != this } buttons.removeIf { it.isRemoved || it.parent != this }
var y = 0f var y = 0f
var x = 0f
var currentWidth = 0f
var totalWidth = 0f
var totalHeight = 0f
for (button in buttons) { for (button in buttons) {
button.setPos(button.dockLeft, y + button.dockTop) if (y != 0f && button.height + y > parent!!.height) {
totalHeight = totalHeight.coerceAtLeast(y - 2f)
y = 0f
x += currentWidth + 2f
totalWidth += currentWidth
currentWidth = 0f
}
button.setPos(x + button.dockLeft, y + button.dockTop)
y += button.height + button.dockMargin.vertical + 2f y += button.height + button.dockMargin.vertical + 2f
width = width.coerceAtLeast(button.width + button.dockMargin.horizontal) currentWidth = currentWidth.coerceAtLeast(button.width + button.dockMargin.horizontal)
} }
height = height.coerceAtLeast(y - 2f) if (currentWidth != 0f) {
totalWidth += currentWidth
}
if (y != 0f) {
totalHeight = totalHeight.coerceAtLeast(y - 2f)
}
width = max(totalWidth, width)
height = max(totalHeight, height)
} }
fun removeButton(button: EditablePanel<*>) { fun removeButton(button: EditablePanel<*>) {
@ -633,6 +665,68 @@ class DeviceControls<out S : MatteryScreen<*>>(
} else { } else {
fluidConfigButton = null fluidConfigButton = null
} }
if (experience != null) {
experienceButton = addButton(ExperienceButton(experience))
} else {
experienceButton = null
}
}
private inner class ExperienceButton(val widget: TakeExperienceWidget) : ButtonPanel<S>(this@DeviceControls.screen, this@DeviceControls, 0f, 0f, 18f, 18f) {
override fun onClick(mouseButton: Int) {
widget.input.accept(null)
}
override val icon: IGUIRenderable
get() = EssenceStorageScreen.DISPENSE_ALL
override var isDisabled: Boolean
get() = !widget.input.test(minecraft.player!!)
set(value) {}
override fun innerRenderTooltips(
graphics: MGUIGraphics,
mouseX: Float,
mouseY: Float,
partialTick: Float
): Boolean {
if (widget.maxAmount.get().isInfinite()) {
if (minecraft.window.isShiftDown) {
graphics.renderComponentTooltip(
font,
listOf(TranslatableComponent("otm.gui.experience_levels", getLevelFromXp(widget.amount.get().toLong()).toString())),
mouseX.toInt(),
mouseY.toInt()
)
} else {
graphics.renderComponentTooltip(
font,
listOf(TranslatableComponent("otm.gui.experience", "%.1f".format(Locale.ROOT, widget.amount.get()))),
mouseX.toInt(),
mouseY.toInt()
)
}
} else {
if (minecraft.window.isShiftDown) {
graphics.renderComponentTooltip(
font,
listOf(TranslatableComponent("otm.gui.experience_levels_with_limit", getLevelFromXp(widget.amount.get().toLong()).toString(), "~" + getLevelFromXp(widget.maxAmount.get().toLong()).toString())),
mouseX.toInt(),
mouseY.toInt()
)
} else {
graphics.renderComponentTooltip(
font,
listOf(TranslatableComponent("otm.gui.experience_with_limit", "%.1f".format(Locale.ROOT, widget.amount.get()), widget.maxAmount.get().toString())),
mouseX.toInt(),
mouseY.toInt()
)
}
}
return true
}
} }
override fun preRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { override fun preRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {

View File

@ -8,7 +8,7 @@ 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.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
import ru.dbotthepony.mc.otm.client.screen.panels.ScrollbarBackgroundPanel import ru.dbotthepony.mc.otm.client.screen.panels.ScrollbarBackgroundPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel 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.slot.BatterySlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
@ -66,7 +66,7 @@ open class AbstractProcessingMachineScreen<M : AbstractProcessingMachineMenu>(me
} }
} }
makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig, balanceInputs = menu.balanceInputs, upgrades = menu.upgrades) DeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig, balanceInputs = menu.balanceInputs, upgrades = menu.upgrades, experience = menu.experience)
if (isJeiLoaded) { if (isJeiLoaded) {
val recipeTypes = menu.recipeTypes val recipeTypes = menu.recipeTypes

View File

@ -19,6 +19,7 @@ import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.OutputSlot import ru.dbotthepony.mc.otm.menu.OutputSlot
import ru.dbotthepony.mc.otm.menu.makeSlots import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.menu.widget.IProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.IProgressGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus
import java.util.function.Supplier import java.util.function.Supplier
@ -69,6 +70,8 @@ class GrillMenu(
override val totalTicks: Int by mSynchronizer.computedInt(Supplier { tile?.fuelTotalTicks ?: 0 }) override val totalTicks: Int by mSynchronizer.computedInt(Supplier { tile?.fuelTotalTicks ?: 0 })
} }
val experience = TakeExperienceWidget(this, tile?.experience)
init { init {
addInventorySlots() addInventorySlots()
addStorageSlot(fuelSlot) addStorageSlot(fuelSlot)

View File

@ -26,6 +26,7 @@ import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus
import ru.dbotthepony.mc.otm.registry.MRecipes import ru.dbotthepony.mc.otm.registry.MRecipes
import java.util.* import java.util.*
@ -62,6 +63,7 @@ class MatterEntanglerMenu(
val outputs = makeSlots(tile?.output ?: SimpleContainer(1)) { a, b -> OutputSlot(a, b) { tile?.experience?.popExperience(player as ServerPlayer) } } val outputs = makeSlots(tile?.output ?: SimpleContainer(1)) { a, b -> OutputSlot(a, b) { tile?.experience?.popExperience(player as ServerPlayer) } }
val upgrades = makeUpgradeSlots(3, tile?.upgrades) val upgrades = makeUpgradeSlots(3, tile?.upgrades)
val experience = TakeExperienceWidget(this, tile?.experience)
private val entangling: Container = if (tile == null) object : SimpleContainer(2) { private val entangling: Container = if (tile == null) object : SimpleContainer(2) {
override fun getMaxStackSize(): Int { override fun getMaxStackSize(): Int {

View File

@ -12,6 +12,7 @@ import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget
import java.util.function.Supplier import java.util.function.Supplier
abstract class AbstractProcessingMachineMenu( abstract class AbstractProcessingMachineMenu(
@ -33,6 +34,7 @@ abstract class AbstractProcessingMachineMenu(
abstract val profiledEnergy: ProfiledLevelGaugeWidget<*> abstract val profiledEnergy: ProfiledLevelGaugeWidget<*>
abstract val balanceInputs: BooleanInputWithFeedback? abstract val balanceInputs: BooleanInputWithFeedback?
abstract val upgrades: UpgradeSlots? abstract val upgrades: UpgradeSlots?
abstract val experience: TakeExperienceWidget?
open val recipeTypes: Supplier<List<RecipeType<*>>>? open val recipeTypes: Supplier<List<RecipeType<*>>>?
get() = null get() = null

View File

@ -19,6 +19,7 @@ import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus
import java.util.function.Supplier import java.util.function.Supplier
@ -39,6 +40,7 @@ class PlatePressMenu(
override val balanceInputs = if (isTwin) BooleanInputWithFeedback(this) else null override val balanceInputs = if (isTwin) BooleanInputWithFeedback(this) else null
override val upgrades = makeUpgradeSlots(if (isTwin) 4 else 3, tile?.upgrades) override val upgrades = makeUpgradeSlots(if (isTwin) 4 else 3, tile?.upgrades)
override val experience = TakeExperienceWidget(this, tile?.experience)
override val processingTuples: List<ProcessingTuple> = immutableList(if (isTwin) 2 else 1) { override val processingTuples: List<ProcessingTuple> = immutableList(if (isTwin) 2 else 1) {
ProcessingTuple(inputSlots[it], outputSlots[it], gauges[it]) ProcessingTuple(inputSlots[it], outputSlots[it], gauges[it])

View File

@ -23,6 +23,7 @@ import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus
import java.util.function.Supplier import java.util.function.Supplier
@ -41,6 +42,7 @@ class PoweredFurnaceMenu(
override val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) override val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget)
override val balanceInputs = BooleanInputWithFeedback(this) override val balanceInputs = BooleanInputWithFeedback(this)
override val upgrades = makeUpgradeSlots(2, tile?.upgrades) override val upgrades = makeUpgradeSlots(2, tile?.upgrades)
override val experience = TakeExperienceWidget(this, tile?.experience)
override val processingTuples: List<ProcessingTuple> = immutableList(2) { override val processingTuples: List<ProcessingTuple> = immutableList(2) {
ProcessingTuple(inputSlots[it], outputSlots[it], progressGauge[it]) ProcessingTuple(inputSlots[it], outputSlots[it], progressGauge[it])

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.menu.widget
import net.minecraft.server.level.ServerPlayer
import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import java.util.function.DoubleSupplier
class TakeExperienceWidget(menu: MatteryMenu, storage: ExperienceStorage?) {
val input = menu.oneWayInput { storage!!.popExperience(menu.player as ServerPlayer) }
val amount = menu.mSynchronizer.computedDouble(DoubleSupplier { storage?.experience ?: 0.0 })
val maxAmount = menu.mSynchronizer.computedDouble(DoubleSupplier { storage?.maxExperience?.asDouble ?: Double.MAX_VALUE })
init {
input.filter { amount.get() >= 1.0 }
}
}