diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt index 2a286fb55..ffcb3b9b3 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt @@ -1025,7 +1025,9 @@ private fun gui(provider: MatteryLanguageProvider) { gui("matter_panel.complexity", "Total complexity: %s") gui("experience", "%s experience points") + gui("experience_with_limit", "%s / %s experience points") 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_all", "Store all experience levels") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt index 318c1db8a..2b23f5139 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt @@ -1022,7 +1022,9 @@ private fun gui(provider: MatteryLanguageProvider) { gui("matter_panel.complexity", "Общая сложность: %s") gui("experience", "%s очков опыта") + gui("experience_with_limit", "%s / %s очков опыта") gui("experience_levels", "%s уровней опыта") + gui("experience_levels_with_limit", "%s / %s уровней опыта") gui("experience.store", "Передать %s уровней опыта") gui("experience.store_all", "Передать все уровни опыта") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/GrillScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/GrillScreen.kt index 881d6fbfa..c96391cf7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/GrillScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/GrillScreen.kt @@ -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.EditablePanel 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.SlotPanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel @@ -55,6 +56,8 @@ class GrillScreen(menu: GrillMenu, inventory: Inventory, title: Component) : Mat frame.sizeToContents() + DeviceControls(this, frame, experience = menu.experience) + return frame } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterEntanglerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterEntanglerScreen.kt index b706d73ed..e29d26246 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterEntanglerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterEntanglerScreen.kt @@ -71,7 +71,7 @@ class MatterEntanglerScreen(menu: MatterEntanglerMenu, inventory: Inventory, tit 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 } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt index 2a5b9bec4..a907108ea 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt @@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import com.mojang.blaze3d.platform.InputConstants import net.minecraft.ChatFormatting +import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component import net.minecraft.world.item.ItemStack 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.SlotPanel 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.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.math.RelativeSide 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.MatterySlot 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.IPlayerInputWithFeedback 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.Predicate +import kotlin.NoSuchElementException +import kotlin.collections.ArrayList +import kotlin.collections.HashMap import kotlin.math.ceil +import kotlin.math.max import kotlin.math.pow private val gunpowder = ItemStackIcon(ItemStack(Items.GUNPOWDER)).fixed() @@ -314,6 +323,7 @@ class DeviceControls>( val fluidConfig: FluidConfigPlayerInput? = null, val balanceInputs: BooleanInputWithFeedback? = null, val upgrades: UpgradeSlots? = null, + val experience: TakeExperienceWidget? = null ) : EditablePanel(screen, parent, x = parent.width + 3f, height = 0f, width = 0f) { val itemConfigButton: ButtonPanel? val energyConfigButton: ButtonPanel? @@ -321,6 +331,7 @@ class DeviceControls>( val redstoneControlsButton: EnumButtonPanel? val balanceInputsButton: BooleanButtonPanel? val upgradesButton: ButtonPanel? + val experienceButton: ButtonPanel? init { childrenOrder = -1000 @@ -334,14 +345,35 @@ class DeviceControls>( buttons.removeIf { it.isRemoved || it.parent != this } var y = 0f + var x = 0f + var currentWidth = 0f + var totalWidth = 0f + var totalHeight = 0f 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 - 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<*>) { @@ -633,6 +665,68 @@ class DeviceControls>( } else { fluidConfigButton = null } + + if (experience != null) { + experienceButton = addButton(ExperienceButton(experience)) + } else { + experienceButton = null + } + } + + private inner class ExperienceButton(val widget: TakeExperienceWidget) : ButtonPanel(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) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AbstractProcessingMachineScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AbstractProcessingMachineScreen.kt index 87cbf79c8..9409e8873 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AbstractProcessingMachineScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AbstractProcessingMachineScreen.kt @@ -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.FramePanel 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.BatterySlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel @@ -66,7 +66,7 @@ open class AbstractProcessingMachineScreen(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) { val recipeTypes = menu.recipeTypes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/GrillMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/GrillMenu.kt index 69b8bf52b..323cf7f61 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/GrillMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/GrillMenu.kt @@ -19,6 +19,7 @@ import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.OutputSlot import ru.dbotthepony.mc.otm.menu.makeSlots import ru.dbotthepony.mc.otm.menu.widget.IProgressGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget import ru.dbotthepony.mc.otm.registry.MMenus import java.util.function.Supplier @@ -69,6 +70,8 @@ class GrillMenu( override val totalTicks: Int by mSynchronizer.computedInt(Supplier { tile?.fuelTotalTicks ?: 0 }) } + val experience = TakeExperienceWidget(this, tile?.experience) + init { addInventorySlots() addStorageSlot(fuelSlot) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterEntanglerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterEntanglerMenu.kt index 81291e26e..e4ed662d8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterEntanglerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterEntanglerMenu.kt @@ -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.ProfiledLevelGaugeWidget 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.MRecipes 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 upgrades = makeUpgradeSlots(3, tile?.upgrades) + val experience = TakeExperienceWidget(this, tile?.experience) private val entangling: Container = if (tile == null) object : SimpleContainer(2) { override fun getMaxStackSize(): Int { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/AbstractProcessingMachineMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/AbstractProcessingMachineMenu.kt index f3ba2b63b..5d5e12026 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/AbstractProcessingMachineMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/AbstractProcessingMachineMenu.kt @@ -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.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget import java.util.function.Supplier abstract class AbstractProcessingMachineMenu( @@ -33,6 +34,7 @@ abstract class AbstractProcessingMachineMenu( abstract val profiledEnergy: ProfiledLevelGaugeWidget<*> abstract val balanceInputs: BooleanInputWithFeedback? abstract val upgrades: UpgradeSlots? + abstract val experience: TakeExperienceWidget? open val recipeTypes: Supplier>>? get() = null diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt index 42cc23a25..217f436c2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt @@ -19,6 +19,7 @@ import ru.dbotthepony.mc.otm.menu.makeSlots import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget import ru.dbotthepony.mc.otm.registry.MMenus import java.util.function.Supplier @@ -39,6 +40,7 @@ class PlatePressMenu( override val balanceInputs = if (isTwin) BooleanInputWithFeedback(this) else null override val upgrades = makeUpgradeSlots(if (isTwin) 4 else 3, tile?.upgrades) + override val experience = TakeExperienceWidget(this, tile?.experience) override val processingTuples: List = immutableList(if (isTwin) 2 else 1) { ProcessingTuple(inputSlots[it], outputSlots[it], gauges[it]) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PoweredFurnaceMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PoweredFurnaceMenu.kt index 36ca763d9..edd447d35 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PoweredFurnaceMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PoweredFurnaceMenu.kt @@ -23,6 +23,7 @@ import ru.dbotthepony.mc.otm.menu.makeSlots import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.TakeExperienceWidget import ru.dbotthepony.mc.otm.registry.MMenus import java.util.function.Supplier @@ -41,6 +42,7 @@ class PoweredFurnaceMenu( override val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) override val balanceInputs = BooleanInputWithFeedback(this) override val upgrades = makeUpgradeSlots(2, tile?.upgrades) + override val experience = TakeExperienceWidget(this, tile?.experience) override val processingTuples: List = immutableList(2) { ProcessingTuple(inputSlots[it], outputSlots[it], progressGauge[it]) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/TakeExperienceWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/TakeExperienceWidget.kt new file mode 100644 index 000000000..a33c721f1 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/TakeExperienceWidget.kt @@ -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 } + } +}