Add "Charge androids" and "Charge exopacks" buttons

This commit is contained in:
DBotThePony 2025-03-07 21:00:01 +07:00
parent 4861513797
commit f866f2a401
Signed by: DBot
GPG Key ID: DCC23B5715498507
12 changed files with 114 additions and 19 deletions

View File

@ -985,6 +985,12 @@ private fun gui(provider: MatteryLanguageProvider) {
gui("exopack.accept_wireless_charge", "Accept wireless charging")
gui("exopack.dont_accept_wireless_charge", "Do not accept wireless charging")
gui("charge_androids", "Charge Androids")
gui("dont_charge_androids", "Do not charge Androids")
gui("charge_exopacks", "Charge Exopacks")
gui("dont_charge_exopacks", "Do not charge Exopacks")
gui("multiblock.formed", "Multiblock is formed: %s")
gui("flywheel.current_loss_t", "Current energy loss per tick:")

View File

@ -978,6 +978,12 @@ private fun gui(provider: MatteryLanguageProvider) {
gui("exopack.accept_wireless_charge", "Принимать заряд от беспроводных зарядников")
gui("exopack.dont_accept_wireless_charge", "Не принимать заряд от беспроводных зарядников")
gui("charge_androids", "Заряжать андроидов")
gui("dont_charge_androids", "Не заряжать андроидов")
gui("charge_exopacks", "Заряжать экзопаки")
gui("dont_charge_exopacks", "Не заряжать экзопаки")
gui("multiblock.formed", "Мультиблок сформирован: %s")
gui("flywheel.current_loss_t", "Текущая потеря энергии в тик:")

View File

@ -30,14 +30,28 @@ class AndroidChargerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.ANDROID_CHARGER))
val energyConfig = ConfigurableEnergy(energy, modesTop = FlowDirection.NONE)
var chargeAndroids = true
set(value) {
field = value
markDirtyFast()
}
var chargeExopacks = true
set(value) {
field = value
markDirtyFast()
}
init {
savetables.stateful(energyConfig::energy, ENERGY_KEY)
savetablesConfig.bool(::chargeAndroids)
savetablesConfig.bool(::chargeExopacks)
}
override fun tick() {
super.tick()
if (redstoneControl.isBlockedByRedstone) return
if (redstoneControl.isBlockedByRedstone || !chargeAndroids && !chargeExopacks) return
val level = level ?: return
var available = energyConfig.energy.extractEnergy(energyConfig.energy.batteryLevel, true)
if (!available.isPositive) return
@ -49,14 +63,14 @@ class AndroidChargerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
for ((ent) in ents) {
val ply = (ent as Player).matteryPlayer
if (ply.isAndroid) {
if (chargeAndroids && ply.isAndroid) {
val received = ply.androidEnergy.receiveEnergyChecked(available, false)
available -= received
energyConfig.energy.extractEnergy(received, false)
if (!available.isPositive) return
}
if (ply.hasExopack && ply.acceptExopackChargeFromWirelessCharger) {
if (chargeExopacks && ply.hasExopack && ply.acceptExopackChargeFromWirelessCharger) {
val received = ply.exopackEnergy.receiveEnergyChecked(available, false)
available -= received
energyConfig.energy.extractEnergy(received, false)

View File

@ -17,21 +17,26 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.capability.moveEnergy
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.shuffle
import ru.dbotthepony.mc.otm.core.util.countingLazy
import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.ANDROID_STATION, p_155229_, p_155230_), MenuProvider {
class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.ANDROID_STATION, p_155229_, p_155230_), MenuProvider {
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return AndroidStationMenu(containerID, inventory, this)
}
private val workerState by countingLazy(blockStateChangesCounter) {
blockState.getValue(WorkerState.SEMI_WORKER_STATE)
}
override val energy: ProfiledEnergyStorage<WorkerEnergyStorage> = ProfiledEnergyStorage(object : WorkerEnergyStorage(::markDirtyFast, MachinesConfig.AndroidStation.VALUES) {
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
return super.extractEnergy(howMuch, simulate).also {
if (!simulate && this.batteryLevel.isZero) {
if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.IDLE) {
if (workerState != WorkerState.IDLE) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
}
}
@ -41,7 +46,7 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
return super.receiveEnergy(howMuch, simulate).also {
if (!simulate && it.isPositive) {
if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) {
if (workerState != WorkerState.WORKING) {
level?.setBlock(blockPos, blockState.setValue(
WorkerState.SEMI_WORKER_STATE,
WorkerState.WORKING
@ -53,9 +58,15 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
})
val energyConfig = ConfigurableEnergy(energy)
var chargeAndroids = true
set(value) {
field = value
markDirtyFast()
}
init {
savetables.stateful(::energy, ENERGY_KEY)
savetablesConfig.bool(::chargeAndroids)
}
private var tickedOnce = false
@ -66,20 +77,20 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
if (!tickedOnce) {
tickedOnce = true
if (energy.batteryLevel.isPositive && blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) {
if (energy.batteryLevel.isPositive && workerState != WorkerState.WORKING) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS)
} else if (energy.batteryLevel.isZero && blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.IDLE) {
} else if (!energy.batteryLevel.isPositive && workerState != WorkerState.IDLE) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
}
}
if (redstoneControl.isBlockedByRedstone) return
if (redstoneControl.isBlockedByRedstone || !chargeAndroids) return
val level = level ?: return
val x = blockPos.x.toDouble()
val y = blockPos.y.toDouble()
val z = blockPos.z.toDouble()
for (ent in level.getEntitiesOfClass(ServerPlayer::class.java, AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0))) {
for (ent in level.getEntitiesOfClass(ServerPlayer::class.java, AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0)).shuffle(level.otmRandom)) {
if (ent.matteryPlayer.isAndroid)
moveEnergy(energy, ent.matteryPlayer.androidEnergy, amount = energy.batteryLevel, simulate = false, ignoreFlowRestrictions = true)
}

View File

@ -45,6 +45,8 @@ object Widgets18 {
val SETTINGS_TAB = miscGrid.next()
val WIRELESS_CHARGING_ENABLED = miscGrid.next()
val WIRELESS_CHARGING_DISABLED = miscGrid.next()
val WIRELESS_CHARGING_ANDROIDS_ENABLED = miscGrid.next()
val WIRELESS_CHARGING_ANDROIDS_DISABLED = miscGrid.next()
private val slotBgGrid = WidgetLocation.SLOT_BACKGROUNDS.grid(4, 4)

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.client.screen.tech
import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
@ -10,8 +11,10 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
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.SpritePanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.BooleanButtonPanel
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.TallHorizontalProfiledPowerGaugePanel
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.menu.tech.AndroidChargerMenu
class AndroidChargerScreen(menu: AndroidChargerMenu, inventory: Inventory, title: Component) : MatteryScreen<AndroidChargerMenu>(menu, inventory, title) {
@ -40,7 +43,33 @@ class AndroidChargerScreen(menu: AndroidChargerMenu, inventory: Inventory, title
it.dockRight = 2f
}
makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig)
val controls = makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig)
if (menu.chargeExopacks != null) {
controls.addButton(
BooleanButtonPanel.square18(
this, frame,
prop = menu.chargeExopacks!!,
iconActive = Widgets18.WIRELESS_CHARGING_ENABLED,
iconInactive = Widgets18.WIRELESS_CHARGING_DISABLED,
tooltipActive = TranslatableComponent("otm.gui.charge_exopacks"),
tooltipInactive = TranslatableComponent("otm.gui.dont_charge_exopacks"),
)
)
}
if (menu.chargeAndroids != null) {
controls.addButton(
BooleanButtonPanel.square18(
this, frame,
prop = menu.chargeAndroids!!,
iconActive = Widgets18.WIRELESS_CHARGING_ANDROIDS_ENABLED,
iconInactive = Widgets18.WIRELESS_CHARGING_ANDROIDS_DISABLED,
tooltipActive = TranslatableComponent("otm.gui.charge_androids"),
tooltipInactive = TranslatableComponent("otm.gui.dont_charge_androids"),
)
)
}
return frame
}

View File

@ -34,6 +34,7 @@ import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.screen.panels.button.BooleanButtonPanel
import ru.dbotthepony.mc.otm.core.RandomSource2Generator
import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu
import ru.dbotthepony.mc.otm.network.AndroidResearchRequestPacket
@ -717,7 +718,18 @@ class AndroidStationScreen(p_97741_: AndroidStationMenu, p_97742_: Inventory, p_
this.playerStrip = playerStrip
makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig)
val controls = makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig)
controls.addButton(
BooleanButtonPanel.square18(
this, frame,
prop = menu.chargeAndroids,
iconActive = Widgets18.WIRELESS_CHARGING_ANDROIDS_ENABLED,
iconInactive = Widgets18.WIRELESS_CHARGING_ANDROIDS_DISABLED,
tooltipActive = TranslatableComponent("otm.gui.charge_androids"),
tooltipInactive = TranslatableComponent("otm.gui.dont_charge_androids"),
)
)
return frame
}

View File

@ -188,17 +188,20 @@ fun <T : Enum<T>> T.prev(values: Array<out T>): T {
return values[next]
}
fun IntArray.shuffle(random: RandomSource) {
fun IntArray.shuffle(random: RandomSource): IntArray {
for (i in lastIndex downTo 1) {
val j = random.nextInt(i + 1)
val copy = this[i]
this[i] = this[j]
this[j] = copy
}
return this
}
fun <T> MutableList<T>.shuffle(random: RandomSource) {
return Util.shuffle(this, random)
fun <T, L : MutableList<T>> L.shuffle(random: RandomSource): L {
Util.shuffle(this, random)
return this
}
fun <T> List<T>.random(random: RandomGenerator): T {

View File

@ -5,6 +5,7 @@ import ru.dbotthepony.mc.otm.block.entity.tech.AndroidChargerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.AndroidChargerMiddleBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.AndroidChargerTopBlockEntity
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.registry.game.MMenus
@ -13,6 +14,9 @@ class AndroidChargerMenu : MatteryPoweredMenu {
val energyConfig: EnergyConfigPlayerInput
val profiledEnergy: ProfiledLevelGaugeWidget<*>
val chargeAndroids: BooleanInputWithFeedback?
val chargeExopacks: BooleanInputWithFeedback?
constructor(
p_38852_: Int,
inventory: Inventory,
@ -20,6 +24,8 @@ class AndroidChargerMenu : MatteryPoweredMenu {
) : super(MMenus.ANDROID_CHARGER, p_38852_, inventory, tile) {
energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energyConfig?.energy, energyWidget)
chargeAndroids = BooleanInputWithFeedback(this, tile?.let { it::chargeAndroids })
chargeExopacks = BooleanInputWithFeedback(this, tile?.let { it::chargeExopacks })
}
constructor(
@ -29,6 +35,8 @@ class AndroidChargerMenu : MatteryPoweredMenu {
) : super(MMenus.ANDROID_CHARGER, p_38852_, inventory, tile?.lastTileEntity) {
energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.lastTileEntity?.energyConfig?.energy, energyWidget)
chargeAndroids = null
chargeExopacks = null
}
constructor(
@ -38,6 +46,8 @@ class AndroidChargerMenu : MatteryPoweredMenu {
) : super(MMenus.ANDROID_CHARGER, p_38852_, inventory, tile?.lastTileEntity) {
energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.lastTileEntity?.energyConfig?.energy, energyWidget)
chargeAndroids = null
chargeExopacks = null
}
init {

View File

@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.registry.game.MMenus
@ -25,7 +26,7 @@ class AndroidStationMenu @JvmOverloads constructor(
) : MatteryPoweredMenu(MMenus.ANDROID_STATION, containerID, inventory, tile) {
private fun container(target: (MatteryPlayer) -> KMutableProperty0<ItemStack>): Container {
if (player is ServerPlayer)
return PartContainer(target.invoke(player.matteryPlayer ?: throw NullPointerException("OTM player capability is missing")))
return PartContainer(target.invoke(player.matteryPlayer))
else
return SimpleContainer(1)
}
@ -115,6 +116,7 @@ class AndroidStationMenu @JvmOverloads constructor(
val equipment = makeEquipmentSlots()
val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget)
val chargeAndroids = BooleanInputWithFeedback(this, tile?.let { it::chargeAndroids })
init {
addInventorySlots()
@ -122,6 +124,6 @@ class AndroidStationMenu @JvmOverloads constructor(
}
override fun stillValid(player: Player): Boolean {
return super.stillValid(player) && player.matteryPlayer?.isAndroid == true
return super.stillValid(player) && player.matteryPlayer.isAndroid
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB