Upgrade system, conditional quickmove slots, frame panel close button
This commit is contained in:
parent
6690ca03c4
commit
9dcf24cae7
@ -603,6 +603,18 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
|
||||
add(MItems.ZPM_BATTERY, "Zero Point Module")
|
||||
add(MItems.ZPM_BATTERY, "description", "Can be found in hands of those who travel between dimensions, if they ever reached different reality of origin of these constructs...")
|
||||
|
||||
add(MItems.CreativeUpgrades.SPEED, "Creative Speed Upgrade")
|
||||
add(MItems.CreativeUpgrades.ENERGY_CONSUMPTION, "Creative Energy Consumption Upgrade")
|
||||
add(MItems.CreativeUpgrades.ENERGY_STORAGE, "Creative Energy Storage Upgrade")
|
||||
add(MItems.CreativeUpgrades.ENERGY_STORAGE_FLAT, "Creative Energy Storage Upgrade (Flat)")
|
||||
add(MItems.CreativeUpgrades.ENERGY_STORAGE_FLAT_SMALL, "Creative Energy Storage Upgrade (Flat Small)")
|
||||
add(MItems.CreativeUpgrades.ENERGY_THROUGHPUT, "Creative Energy Throughput Upgrade")
|
||||
add(MItems.CreativeUpgrades.ENERGY_THROUGHPUT_FLAT, "Creative Energy Throughput Upgrade (Flat)")
|
||||
add(MItems.CreativeUpgrades.ENERGY_THROUGHPUT_FLAT_SMALL, "Creative Energy Throughput Upgrade (Flat Small)")
|
||||
add(MItems.CreativeUpgrades.FAILSAFE, "Creative Failsafe Upgrade")
|
||||
add(MItems.CreativeUpgrades.FAILURE, "Creative Failure Upgrade")
|
||||
add(MItems.CreativeUpgrades.PROCESSING_ITEMS, "Creative Item Processing Upgrade")
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,6 +700,27 @@ private fun gui(provider: MatteryLanguageProvider) {
|
||||
gui("side_mode.pull", "Pull")
|
||||
gui("side_mode.push", "Push")
|
||||
|
||||
gui("upgrades", "Upgrades")
|
||||
gui("upgrades.current", "Active upgrades:")
|
||||
gui("upgrade.speed", "Operation speed: %s%%")
|
||||
gui("upgrade.processing_items", "Items processed per cycle: +%s")
|
||||
gui("upgrade.energy_storage_flat", "Energy capacity: +%s")
|
||||
gui("upgrade.energy_storage", "Energy capacity: +%s%%")
|
||||
gui("upgrade.energy_consumed", "Energy consumption: %s%%")
|
||||
gui("upgrade.energy_throughput_flat", "Energy throughput: +%s")
|
||||
gui("upgrade.energy_throughput", "Energy throughput: +%s%%")
|
||||
gui("upgrade.failsafe", "Failure chance: %s%%")
|
||||
|
||||
gui("upgrade_type.list", "Upgrade classification:")
|
||||
gui("upgrade_type.allowed", "Allowed upgrades:")
|
||||
gui("upgrade_type.allowed_none", "No possible upgrades at the moment.")
|
||||
gui("upgrade_type.speed", "Speed")
|
||||
gui("upgrade_type.processing", "Processing")
|
||||
gui("upgrade_type.energy_storage", "Energy Storage")
|
||||
gui("upgrade_type.energy_consumption", "Energy Consumption")
|
||||
gui("upgrade_type.energy_throughput", "Energy Throughput")
|
||||
gui("upgrade_type.failsafe", "Failsafe")
|
||||
|
||||
gui("balance_inputs", "Balance input slots")
|
||||
|
||||
gui("sorting.default", "Default sorting")
|
||||
|
@ -607,6 +607,18 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
|
||||
add(MItems.ZPM_BATTERY, "Модуль нулевой точки")
|
||||
add(MItems.ZPM_BATTERY, "description", "Может быть найден у тех, кто путешествует между измерениями, если, конечно, они смогли достигнуть вселенной, где данные устройства были созиданы...")
|
||||
|
||||
add(MItems.CreativeUpgrades.SPEED, "Творческое улучшение скорости")
|
||||
add(MItems.CreativeUpgrades.ENERGY_CONSUMPTION, "Творческое улучшение энергоэффективности")
|
||||
add(MItems.CreativeUpgrades.ENERGY_STORAGE, "Творческое улучшение энергохраналища")
|
||||
add(MItems.CreativeUpgrades.ENERGY_STORAGE_FLAT, "Творческое улучшение энергохраналища (простое)")
|
||||
add(MItems.CreativeUpgrades.ENERGY_STORAGE_FLAT_SMALL, "Творческое улучшение энергохраналища (малое простое)")
|
||||
add(MItems.CreativeUpgrades.ENERGY_THROUGHPUT, "Творческое улучшение энергоканала")
|
||||
add(MItems.CreativeUpgrades.ENERGY_THROUGHPUT_FLAT, "Творческое улучшение энергоканала (простое)")
|
||||
add(MItems.CreativeUpgrades.ENERGY_THROUGHPUT_FLAT_SMALL, "Творческое улучшение энергоканала (малое простое)")
|
||||
add(MItems.CreativeUpgrades.FAILSAFE, "Творческое улучшение отказоустойчивости")
|
||||
add(MItems.CreativeUpgrades.FAILURE, "Творческое улучшение краха")
|
||||
add(MItems.CreativeUpgrades.PROCESSING_ITEMS, "Творческое улучшение обработки")
|
||||
}
|
||||
}
|
||||
|
||||
@ -692,6 +704,27 @@ private fun gui(provider: MatteryLanguageProvider) {
|
||||
gui("side_mode.pull", "Автоматическое вытягивание")
|
||||
gui("side_mode.push", "Автоматическое выталкивание")
|
||||
|
||||
gui("upgrades", "Улучшения")
|
||||
gui("upgrades.current", "Активные улучшения:")
|
||||
gui("upgrade.speed", "Скорость работы: %s%%")
|
||||
gui("upgrade.processing_items", "Работы за цикл: +%s")
|
||||
gui("upgrade.energy_storage_flat", "Хранилище энергии: +%s")
|
||||
gui("upgrade.energy_storage", "Хранилище энергии: +%s%%")
|
||||
gui("upgrade.energy_consumed", "Потребление энергии: %s%%")
|
||||
gui("upgrade.energy_throughput_flat", "Пропускная способность энергии: +%s")
|
||||
gui("upgrade.energy_throughput", "Пропускная способность энергии: +%s%%")
|
||||
gui("upgrade.failsafe", "Шанс неудачи: %s%%")
|
||||
|
||||
gui("upgrade_type.list", "Классификация улучшения:")
|
||||
gui("upgrade_type.allowed", "Допустимые улучшения:")
|
||||
gui("upgrade_type.allowed_none", "На данный момент нет допустимых улучшений.")
|
||||
gui("upgrade_type.speed", "Скорость")
|
||||
gui("upgrade_type.processing", "Обработка")
|
||||
gui("upgrade_type.energy_storage", "Энергохранилище")
|
||||
gui("upgrade_type.energy_consumption", "Энергоэффективность")
|
||||
gui("upgrade_type.energy_throughput", "Энергоканал")
|
||||
gui("upgrade_type.failsafe", "Отказоустойчивость")
|
||||
|
||||
gui("balance_inputs", "Балансировать входные слоты")
|
||||
|
||||
gui("sorting.default", "Сортировка по умолчанию")
|
||||
|
@ -112,6 +112,8 @@ fun addTags(tagsProvider: TagsProvider) {
|
||||
tagsProvider.items.forge("shears").add(MItems.TRITANIUM_SHEARS)
|
||||
tagsProvider.items.forge("shields").add(MItems.TRITANIUM_SHIELD)
|
||||
|
||||
tagsProvider.items.Appender(MItemTags.UPGRADES).add(MItems.CreativeUpgrades.LIST)
|
||||
|
||||
tagsProvider.blocks.Appender(BlockTags.STAIRS)
|
||||
.add(MRegistry.FLOOR_TILES_STAIRS.blocks.values)
|
||||
.add(MRegistry.TRITANIUM_STAIRS.allBlocks.values)
|
||||
|
@ -63,6 +63,10 @@ public class MatteryCapability {
|
||||
@NotNull
|
||||
public static final Capability<ICurio> CURIOS_ITEM = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
|
||||
@Nonnull
|
||||
@NotNull
|
||||
public static final Capability<IMatteryUpgrade> UPGRADE = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
|
||||
public static void register(RegisterCapabilitiesEvent event) {
|
||||
event.register(IMatteryEnergyStorage.class);
|
||||
event.register(MatteryPlayerCapability.class);
|
||||
@ -72,5 +76,6 @@ public class MatteryCapability {
|
||||
event.register(IReplicationTaskProvider.class);
|
||||
event.register(IMatteryDrive.class);
|
||||
event.register(StorageNode.class);
|
||||
event.register(IMatteryUpgrade.class);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,9 @@ package ru.dbotthepony.mc.otm.block.entity
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
||||
import ru.dbotthepony.mc.otm.core.math.set
|
||||
@ -153,6 +155,7 @@ abstract class MachineJobEventLoop<JobType : IMachineJob> : INBTSerializable<Com
|
||||
protected abstract val energy: IMatteryEnergyStorage?
|
||||
protected abstract val isBlockedByRedstone: Boolean
|
||||
protected abstract fun deserializeJob(nbt: CompoundTag): JobType?
|
||||
protected abstract val upgrades: IMatteryUpgrade?
|
||||
|
||||
var currentJob: JobType? = null
|
||||
set(value) {
|
||||
@ -263,7 +266,8 @@ abstract class MachineJobEventLoop<JobType : IMachineJob> : INBTSerializable<Com
|
||||
return
|
||||
}
|
||||
|
||||
var availableTicks = ticks
|
||||
val upgrades = upgrades ?: IMatteryUpgrade.Companion
|
||||
var availableTicks = ticks * (1.0 + upgrades.speedBonus.coerceIn(MachinesConfig.Upgrades.MIN_SPEED, MachinesConfig.Upgrades.MAX_SPEED))
|
||||
val energy = energy
|
||||
|
||||
while (!isIdling && weakGreaterThan(availableTicks, 0.0) && throttleTicks <= 0) {
|
||||
@ -299,18 +303,23 @@ abstract class MachineJobEventLoop<JobType : IMachineJob> : INBTSerializable<Com
|
||||
idleTicksAnim = 0
|
||||
|
||||
if (weakLessThan(workTicks, currentJob.ticks)) {
|
||||
val ticksLeft = currentJob.ticks - workTicks
|
||||
val ticksLeft = (currentJob.ticks - workTicks).coerceAtMost(availableTicks)
|
||||
val ticksAdvanced: Double
|
||||
|
||||
var requiredPower: Decimal? = null
|
||||
var extractedPower: Decimal? = null
|
||||
|
||||
if (currentJob.powerUsage.isZero) {
|
||||
ticksAdvanced = availableTicks.coerceAtMost(ticksLeft)
|
||||
ticksAdvanced = ticksLeft
|
||||
} else {
|
||||
requiredPower = currentJob.powerUsage * ticksLeft.coerceAtMost(availableTicks)
|
||||
extractedPower = energy!!.extractEnergy(requiredPower, true)
|
||||
ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceAtMost(ticksLeft).coerceAtMost(availableTicks)
|
||||
requiredPower = currentJob.powerUsage * (Decimal.ONE + upgrades.energyConsumed.coerceIn(MachinesConfig.Upgrades.MIN_ENERGY, MachinesConfig.Upgrades.MAX_ENERGY)) * ticksLeft.coerceAtMost(availableTicks)
|
||||
|
||||
if (requiredPower.isPositive) {
|
||||
extractedPower = energy!!.extractEnergy(requiredPower, true)
|
||||
ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceIn(0.0, ticksLeft)
|
||||
} else {
|
||||
ticksAdvanced = ticksLeft
|
||||
}
|
||||
}
|
||||
|
||||
if (weakEqualDoubles(ticksAdvanced, 0.0)) {
|
||||
|
@ -11,9 +11,11 @@ import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
||||
import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
|
||||
@ -30,7 +32,7 @@ abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
|
||||
blockPos: BlockPos,
|
||||
blockState: BlockState,
|
||||
val jobDeserializer: (tag: CompoundTag) -> JobType?,
|
||||
maxJobs: Int = 1
|
||||
maxJobs: Int = 1,
|
||||
) : MatteryPoweredBlockEntity(type, blockPos, blockState) {
|
||||
val jobEventLoops: ImmutableList<MachineJobEventLoop<JobType>> = immutableList(maxJobs) { id ->
|
||||
object : MachineJobEventLoop<JobType>() {
|
||||
@ -38,6 +40,8 @@ abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
|
||||
get() = matteryEnergy
|
||||
override val isBlockedByRedstone: Boolean
|
||||
get() = redstoneControl.isBlockedByRedstone
|
||||
override val upgrades: IMatteryUpgrade?
|
||||
get() = this@MatteryWorkerBlockEntity.upgrades
|
||||
|
||||
override fun deserializeJob(nbt: CompoundTag): JobType? {
|
||||
return jobDeserializer.invoke(nbt)
|
||||
@ -61,6 +65,8 @@ abstract class MatteryWorkerBlockEntity<JobType : IMachineJob>(
|
||||
}
|
||||
}
|
||||
|
||||
open val upgrades: IMatteryUpgrade? get() = null
|
||||
|
||||
var balanceInputs = false
|
||||
|
||||
init {
|
||||
|
@ -12,11 +12,14 @@ import ru.dbotthepony.mc.otm.block.entity.JobContainer
|
||||
import ru.dbotthepony.mc.otm.block.entity.JobStatus
|
||||
import ru.dbotthepony.mc.otm.block.entity.MachineItemJob
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
||||
import ru.dbotthepony.mc.otm.capability.UpgradeType
|
||||
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||
import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.container.balance
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
|
||||
@ -29,7 +32,8 @@ class PlatePressBlockEntity(
|
||||
p_155230_: BlockState,
|
||||
val isTwin: Boolean = false,
|
||||
) : MatteryWorkerBlockEntity<MachineItemJob>(if (isTwin) MBlockEntities.TWIN_PLATE_PRESS else MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ::MachineItemJob, if (isTwin) 2 else 1) {
|
||||
val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::setChangedLight, MachinesConfig.PLATE_PRESS))
|
||||
override val upgrades = UpgradeContainer(this::setChangedLight, if (isTwin) 4 else 3, UpgradeType.BASIC)
|
||||
val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::setChangedLight, upgrades.transform(MachinesConfig.PLATE_PRESS)))
|
||||
val inputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer)
|
||||
val outputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer)
|
||||
|
||||
@ -55,6 +59,7 @@ class PlatePressBlockEntity(
|
||||
savetable(::inputContainer)
|
||||
savetable(::outputContainer)
|
||||
savetables.double(::experience)
|
||||
savetables.stateful(::upgrades)
|
||||
}
|
||||
|
||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||
|
200
src/main/kotlin/ru/dbotthepony/mc/otm/capability/Upgrades.kt
Normal file
200
src/main/kotlin/ru/dbotthepony/mc/otm/capability/Upgrades.kt
Normal file
@ -0,0 +1,200 @@
|
||||
package ru.dbotthepony.mc.otm.capability
|
||||
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
|
||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.immutableSet
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.util.formatPower
|
||||
|
||||
/**
|
||||
* Upgrades merge by sum of their effects
|
||||
*
|
||||
* Values which are otherwise not stated to allow negatives or not, Do allow negative values.
|
||||
*/
|
||||
interface IMatteryUpgrade {
|
||||
/**
|
||||
* Type(s) this upgrade represent
|
||||
*/
|
||||
val upgradeTypes: Set<UpgradeType> get() = setOf()
|
||||
|
||||
/**
|
||||
* [speedBonus] of `1.0` means that machine doubles the speed (performs twice the amount of
|
||||
* work ticks per work cycle).
|
||||
*/
|
||||
val speedBonus: Double get() = 0.0
|
||||
|
||||
/**
|
||||
* **CAN NOT be negative.**
|
||||
*
|
||||
* [processingItems] of `4` means machine will accept at most 5 (1 + 4) of items per job.
|
||||
*/
|
||||
val processingItems: Int get() = 0
|
||||
|
||||
/**
|
||||
* **CAM NOT be negative.**
|
||||
*
|
||||
* Added directly over regular energy storage capacity.
|
||||
*/
|
||||
val energyStorageFlat: Decimal get() = Decimal.ZERO
|
||||
|
||||
/**
|
||||
* **CAM NOT be negative.**
|
||||
*/
|
||||
val energyStorage: Decimal get() = Decimal.ZERO
|
||||
|
||||
/**
|
||||
* Value of `1` means power consumption is doubled, `2` is tripled, `-0.5` is halved.
|
||||
*/
|
||||
val energyConsumed: Decimal get() = Decimal.ZERO
|
||||
|
||||
/**
|
||||
* **CAN NOT be negative.**
|
||||
*
|
||||
* Added directly over regular throughput
|
||||
*/
|
||||
val energyThroughputFlat: Decimal get() = Decimal.ZERO
|
||||
|
||||
/**
|
||||
* **CAN NOT be negative.**
|
||||
*
|
||||
* Value of `1` means power throughput is doubled, `2` is tripled, and so on.
|
||||
*/
|
||||
val energyThroughput: Decimal get() = Decimal.ZERO
|
||||
|
||||
/**
|
||||
* **CAN NOT be negative.**
|
||||
*
|
||||
* **Merged by multiplication**
|
||||
*/
|
||||
val failureMultiplier: Double get() = 1.0
|
||||
|
||||
companion object : IMatteryUpgrade
|
||||
}
|
||||
|
||||
fun IMatteryUpgrade.addUpgradeTooltipLines(tooltips: MutableCollection<Component>) {
|
||||
if (upgradeTypes.isNotEmpty() && ShiftPressedCond.asBoolean) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade_type.list").withStyle(ChatFormatting.GRAY))
|
||||
|
||||
for (upgrade in upgradeTypes) {
|
||||
tooltips.add(upgrade.component.copy().withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
|
||||
tooltips.add(TextComponent(""))
|
||||
}
|
||||
|
||||
if (speedBonus >= 0.01) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.speed", TextComponent("+" + (speedBonus.coerceIn(MachinesConfig.Upgrades.MIN_SPEED, MachinesConfig.Upgrades.MAX_SPEED) * 100.0).toInt().toString()).withStyle(ChatFormatting.DARK_GREEN)).withStyle(ChatFormatting.GRAY))
|
||||
} else if (speedBonus <= -0.01) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.speed", TextComponent((speedBonus.coerceIn(MachinesConfig.Upgrades.MIN_SPEED, MachinesConfig.Upgrades.MAX_SPEED) * 100.0).toInt().toString()).withStyle(ChatFormatting.DARK_RED)).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
|
||||
if (processingItems != 0) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.processing_items", TextComponent("+$processingItems").withStyle(ChatFormatting.DARK_GREEN)).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
|
||||
if (energyStorageFlat != Decimal.ZERO) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.energy_storage_flat", energyStorageFlat.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN)).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
|
||||
if (energyStorage != Decimal.ZERO) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.energy_storage", TextComponent((energyStorage * 100).toString(0)).withStyle(ChatFormatting.DARK_GREEN)).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
|
||||
if (energyConsumed > Decimal.ONE) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.energy_consumed", TextComponent("+" + (energyConsumed.coerceIn(MachinesConfig.Upgrades.MIN_ENERGY, MachinesConfig.Upgrades.MAX_ENERGY) * 100).toString(0)).withStyle(ChatFormatting.DARK_RED)).withStyle(ChatFormatting.GRAY))
|
||||
} else if (energyConsumed < Decimal.MINUS_ONE) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.energy_consumed", TextComponent((energyConsumed.coerceIn(MachinesConfig.Upgrades.MIN_ENERGY, MachinesConfig.Upgrades.MAX_ENERGY) * 100).toString(0)).withStyle(ChatFormatting.DARK_GREEN)).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
|
||||
if (energyThroughputFlat != Decimal.ZERO) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.energy_throughput_flat", energyThroughputFlat.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN)).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
|
||||
if (energyThroughput != Decimal.ZERO) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.energy_throughput", TextComponent((energyThroughput * 100).toString(0)).withStyle(ChatFormatting.DARK_GREEN)).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
|
||||
if (failureMultiplier >= 1.01) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.failsafe", TextComponent("+" + ((failureMultiplier - 1) * 100).toInt().toString()).withStyle(ChatFormatting.DARK_RED)).withStyle(ChatFormatting.GRAY))
|
||||
} else if (failureMultiplier <= 0.99) {
|
||||
tooltips.add(TranslatableComponent("otm.gui.upgrade.failsafe", TextComponent(((failureMultiplier.coerceAtLeast(0.0) - 1) * 100).toInt().toString()).withStyle(ChatFormatting.DARK_GREEN)).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
}
|
||||
|
||||
fun IMatteryUpgrade.getUpgradeTooltipLines(): MutableList<Component> {
|
||||
return ArrayList<Component>().also { addUpgradeTooltipLines(it) }
|
||||
}
|
||||
|
||||
enum class UpgradeType {
|
||||
SPEED,
|
||||
PROCESSING,
|
||||
ENERGY_STORAGE,
|
||||
ENERGY_CONSUMPTION,
|
||||
ENERGY_THROUGHPUT,
|
||||
FAILSAFE;
|
||||
|
||||
val localeId = "otm.gui.upgrade_type.${name.lowercase()}"
|
||||
val component: Component get() = TranslatableComponent(localeId)
|
||||
|
||||
val flag = 1 shl (ordinal + 1)
|
||||
fun set() = sets[flag]
|
||||
|
||||
companion object {
|
||||
private val cached = values()
|
||||
|
||||
private val sets = Array(2 shl cached.size) {
|
||||
immutableSet {
|
||||
for (u in values()) if (it.and(u.flag) != 0) accept(u)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val ALL = set(*values())
|
||||
@JvmField
|
||||
val BASIC = set(SPEED, ENERGY_STORAGE, ENERGY_CONSUMPTION, ENERGY_THROUGHPUT)
|
||||
|
||||
fun set(vararg types: UpgradeType): Set<UpgradeType> {
|
||||
var flags = 0
|
||||
for (v in types) flags = flags or v.flag
|
||||
return sets[flags]
|
||||
}
|
||||
|
||||
fun set(): Set<UpgradeType> {
|
||||
return sets[0]
|
||||
}
|
||||
|
||||
fun set(
|
||||
type0: UpgradeType,
|
||||
): Set<UpgradeType> = sets[type0.flag]
|
||||
|
||||
fun set(
|
||||
type0: UpgradeType,
|
||||
type1: UpgradeType,
|
||||
): Set<UpgradeType> = sets[type0.flag or type1.flag]
|
||||
|
||||
fun set(
|
||||
type0: UpgradeType,
|
||||
type1: UpgradeType,
|
||||
type2: UpgradeType,
|
||||
): Set<UpgradeType> = sets[type0.flag or type1.flag or type2.flag]
|
||||
|
||||
fun set(
|
||||
type0: UpgradeType,
|
||||
type1: UpgradeType,
|
||||
type2: UpgradeType,
|
||||
type3: UpgradeType,
|
||||
): Set<UpgradeType> = sets[type0.flag or type1.flag or type2.flag or type3.flag]
|
||||
|
||||
fun set(
|
||||
type0: UpgradeType,
|
||||
type1: UpgradeType,
|
||||
type2: UpgradeType,
|
||||
type3: UpgradeType,
|
||||
type4: UpgradeType,
|
||||
): Set<UpgradeType> = sets[type0.flag or type1.flag or type2.flag or type3.flag or type4.flag]
|
||||
}
|
||||
}
|
@ -59,7 +59,7 @@ object Widgets18 {
|
||||
val PATTERN_SLOT_BACKGROUND = slotBgGrid.next()
|
||||
val MATTER_CAPACITOR_SLOT_BACKGROUND = slotBgGrid.next()
|
||||
|
||||
private val controlsGrid = WidgetLocation.SIDE_CONTROLS.grid(rows = 7, columns = 9)
|
||||
private val controlsGrid = WidgetLocation.SIDE_CONTROLS.grid(rows = 8, columns = 9)
|
||||
|
||||
val BATTERY_ONLY = controlsGrid.next()
|
||||
val ITEMS_CONFIGURATION = controlsGrid.next()
|
||||
@ -160,4 +160,6 @@ object Widgets18 {
|
||||
put(RelativeSide.FRONT, FRONT_CONTROLS)
|
||||
put(RelativeSide.BACK, BACK_CONTROLS)
|
||||
}
|
||||
|
||||
val UPGRADES = controlsGrid.next()
|
||||
}
|
||||
|
@ -319,7 +319,10 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
|
||||
* @return FramePanel created, or null
|
||||
*/
|
||||
protected open fun makeMainFrame(): FramePanel<MatteryScreen<*>>? {
|
||||
return FramePanel(this, null, 0f, 0f, DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT, getTitle())
|
||||
return FramePanel(this, null, 0f, 0f, DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT, getTitle()).also {
|
||||
it.onClose { onClose() }
|
||||
it.makeCloseButton()
|
||||
}
|
||||
}
|
||||
|
||||
public override fun recalculateQuickCraftRemaining() {
|
||||
|
@ -1,8 +1,10 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen.panels
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceArraySet
|
||||
import net.minecraft.client.gui.ComponentPath
|
||||
import net.minecraft.client.gui.Font
|
||||
@ -23,6 +25,7 @@ import ru.dbotthepony.mc.otm.client.render.currentScissorRect
|
||||
import ru.dbotthepony.mc.otm.client.render.popScissorRect
|
||||
import ru.dbotthepony.mc.otm.client.render.pushScissorRect
|
||||
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.button.AbstractButtonPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.input.QueryUserPanel
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
@ -417,6 +420,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
||||
return field
|
||||
}
|
||||
|
||||
field = null
|
||||
return null
|
||||
}
|
||||
|
||||
@ -965,7 +969,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
if (isHovered) {
|
||||
if (isHovered || this is AbstractButtonPanel<*> && isPressed) {
|
||||
val tooltip = tooltip
|
||||
val tooltipList = tooltipList
|
||||
|
||||
@ -1186,10 +1190,6 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
||||
this.height = height
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOGGER = LogManager.getLogger()!!
|
||||
}
|
||||
|
||||
protected open fun visibilityChanges(new: Boolean, old: Boolean) {
|
||||
|
||||
}
|
||||
@ -1589,7 +1589,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
||||
fun keyPressed(key: Int, scancode: Int, mods: Int): Boolean {
|
||||
if (!isVisible() || !acceptKeyboardInput) return false
|
||||
if (!isEverFocused()) return false
|
||||
if (flashAnyBlocker(true)) return true
|
||||
if (flashAnyBlocker(key !in ignoreFlashKeys)) return true
|
||||
if (isFocusedThis) return keyPressedInternal(key, scancode, mods)
|
||||
|
||||
for (child in visibleChildrenInternal) {
|
||||
@ -1737,4 +1737,21 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
||||
fun queryUser(title: Component, text: Collection<Component>, onConfirm: Runnable, onCancel: Runnable? = null): QueryUserPanel<S> {
|
||||
return QueryUserPanel(screen, title, text, onConfirm, onCancel).also { blockingWindow = it }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOGGER = LogManager.getLogger()!!
|
||||
|
||||
private val ignoreFlashKeys = IntAVLTreeSet()
|
||||
|
||||
init {
|
||||
ignoreFlashKeys.add(InputConstants.KEY_LEFT)
|
||||
ignoreFlashKeys.add(InputConstants.KEY_RIGHT)
|
||||
ignoreFlashKeys.add(InputConstants.KEY_UP)
|
||||
ignoreFlashKeys.add(InputConstants.KEY_DOWN)
|
||||
ignoreFlashKeys.add(InputConstants.KEY_RCONTROL)
|
||||
ignoreFlashKeys.add(InputConstants.KEY_LCONTROL)
|
||||
ignoreFlashKeys.add(InputConstants.KEY_RSHIFT)
|
||||
ignoreFlashKeys.add(InputConstants.KEY_LSHIFT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ import net.minecraft.network.chat.Component
|
||||
import org.lwjgl.opengl.GL30
|
||||
import ru.dbotthepony.mc.otm.client.playGuiClickSound
|
||||
import ru.dbotthepony.mc.otm.client.render.*
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.button.AbstractButtonPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel
|
||||
|
||||
open class FramePanel<out S : Screen>(
|
||||
screen: S,
|
||||
@ -123,6 +125,30 @@ open class FramePanel<out S : Screen>(
|
||||
}
|
||||
}
|
||||
|
||||
inner class CloseButton : AbstractButtonPanel<S>(screen, this@FramePanel, this@FramePanel.width - CLOSE_BUTTON.width, 0f, CLOSE_BUTTON.width, CLOSE_BUTTON.height) {
|
||||
override fun onClick(mouseButton: Int) {
|
||||
close()
|
||||
}
|
||||
|
||||
override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
if (isPressed) {
|
||||
CLOSE_BUTTON_PRESSED.render(graphics, 0f, 0f, width, height)
|
||||
} else if (isHovered) {
|
||||
CLOSE_BUTTON_HOVERED.render(graphics, 0f, 0f, width, height)
|
||||
} else {
|
||||
CLOSE_BUTTON.render(graphics, 0f, 0f, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRemoved() {
|
||||
super.onRemoved()
|
||||
|
||||
if (closeButton == this) {
|
||||
closeButton = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected val tabs: java.util.ArrayList<Tab> = ArrayList()
|
||||
|
||||
override fun performLayout() {
|
||||
@ -131,13 +157,29 @@ open class FramePanel<out S : Screen>(
|
||||
tab.initial = i == 0
|
||||
}
|
||||
|
||||
closeButton?.setPos(width - CLOSE_BUTTON.width, 0f)
|
||||
|
||||
super.performLayout()
|
||||
}
|
||||
|
||||
protected var dragging = false
|
||||
protected var closeButton: CloseButton? = null
|
||||
|
||||
var closeOnEscape = false
|
||||
|
||||
fun makeCloseButton() {
|
||||
if (closeButton == null)
|
||||
closeButton = CloseButton()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds close button and makes panel [close] when user presses ESC with this panel focused
|
||||
*/
|
||||
fun behaveAsWindow() {
|
||||
closeOnEscape = true
|
||||
makeCloseButton()
|
||||
}
|
||||
|
||||
init {
|
||||
setDockPadding(PADDING, if (title != null) PADDING_TOP else PADDING, PADDING, PADDING)
|
||||
}
|
||||
@ -187,9 +229,24 @@ open class FramePanel<out S : Screen>(
|
||||
|
||||
}
|
||||
|
||||
protected val closeCallbacks = ArrayList<Runnable>()
|
||||
|
||||
fun onClose(callback: Runnable) {
|
||||
closeCallbacks.add(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Usually just calls [remove]
|
||||
*/
|
||||
open fun close() {
|
||||
if (isRemoved) return
|
||||
remove()
|
||||
closeCallbacks.forEach { it.run() }
|
||||
}
|
||||
|
||||
override fun keyPressedInternal(key: Int, scancode: Int, mods: Int): Boolean {
|
||||
if (key == InputConstants.KEY_ESCAPE && closeOnEscape) {
|
||||
remove()
|
||||
close()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -258,9 +315,13 @@ open class FramePanel<out S : Screen>(
|
||||
padding = DockProperty(-3f, -3f, -3f, -3f)
|
||||
)
|
||||
|
||||
val TAB_RIGHT_CONNECTION = WidgetLocation.MISC.sprite(x = 30f, y = 0f, width = 3f, height = 5f)
|
||||
val TAB_LEFT_CONNECTION = WidgetLocation.MISC.sprite(x = 33f, y = 0f, width = 3f, height = 5f)
|
||||
val TAB_BACKGROUND = WidgetLocation.MISC.sprite(x = 30f, y = 6f, width = 6f, height = 6f)
|
||||
val TAB_RIGHT_CONNECTION = WidgetLocation.MISC.sprite(x = 30f, y = 0f, width = 3f, height = 5f)
|
||||
val TAB_LEFT_CONNECTION = WidgetLocation.MISC.sprite(x = 33f, y = 0f, width = 3f, height = 5f)
|
||||
val TAB_BACKGROUND = WidgetLocation.MISC.sprite(x = 30f, y = 6f, width = 6f, height = 6f)
|
||||
|
||||
val CLOSE_BUTTON = WidgetLocation.MISC.sprite(x = 51f, y = 0f, width = 13f, height = 11f)
|
||||
val CLOSE_BUTTON_HOVERED = WidgetLocation.MISC.sprite(x = 51f, y = 11f, width = 13f, height = 11f)
|
||||
val CLOSE_BUTTON_PRESSED = WidgetLocation.MISC.sprite(x = 51f, y = 22f, width = 13f, height = 11f)
|
||||
|
||||
const val TAB_HEIGHT = 28f
|
||||
const val TAB_WIDTH = 28f
|
||||
|
@ -3,26 +3,38 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.network.chat.Component
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.capability.addUpgradeTooltipLines
|
||||
import ru.dbotthepony.mc.otm.client.isCtrlDown
|
||||
import ru.dbotthepony.mc.otm.client.isShiftDown
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.client.render.AbstractMatterySprite
|
||||
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.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.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.core.GetterSetter
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import ru.dbotthepony.mc.otm.menu.UpgradeSlots
|
||||
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
||||
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 java.util.function.Predicate
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.pow
|
||||
|
||||
private fun <S : MatteryScreen<*>> makeRedstoneSettingButton(
|
||||
screen: S,
|
||||
@ -212,6 +224,7 @@ private fun <S : MatteryScreen<*>> makeItemHandlerControlPanel(
|
||||
moveButtons(front, back, left, right, top, bottom)
|
||||
screen.addPanel(frame)
|
||||
frame.requestFocus()
|
||||
frame.closeOnEscape = true
|
||||
|
||||
return frame
|
||||
}
|
||||
@ -240,6 +253,7 @@ private fun <S : MatteryScreen<*>> makeEnergyConfigPanel(
|
||||
moveButtons(front, back, left, right, top, bottom)
|
||||
screen.addPanel(frame)
|
||||
frame.requestFocus()
|
||||
frame.closeOnEscape = true
|
||||
|
||||
return frame
|
||||
}
|
||||
@ -268,6 +282,7 @@ private fun <S : MatteryScreen<*>> makeFluidConfigPanel(
|
||||
moveButtons(front, back, left, right, top, bottom)
|
||||
screen.addPanel(frame)
|
||||
frame.requestFocus()
|
||||
frame.closeOnEscape = true
|
||||
|
||||
return frame
|
||||
}
|
||||
@ -281,12 +296,17 @@ class DeviceControls<out S : MatteryScreen<*>>(
|
||||
val energyConfig: EnergyConfigPlayerInput? = null,
|
||||
val fluidConfig: FluidConfigPlayerInput? = null,
|
||||
val balanceInputs: BooleanInputWithFeedback? = null,
|
||||
val upgrades: UpgradeSlots? = null,
|
||||
) : EditablePanel<S>(screen, parent, x = parent.width + 3f, height = 0f, width = 0f) {
|
||||
val itemConfigButton: LargeRectangleButtonPanel<S>?
|
||||
val energyConfigButton: LargeRectangleButtonPanel<S>?
|
||||
val fluidConfigButton: LargeRectangleButtonPanel<S>?
|
||||
val redstoneControlsButton: LargeEnumRectangleButtonPanel<S, RedstoneSetting>?
|
||||
val balanceInputsButton: LargeBooleanRectangleButtonPanel<S>?
|
||||
val upgradesButton: LargeRectangleButtonPanel<S>?
|
||||
|
||||
private var upgradeWindow: FramePanel<S>? = null
|
||||
|
||||
private var nextY = 0f
|
||||
|
||||
fun <P : EditablePanel<@UnsafeVariance S>> addButton(button: P): P {
|
||||
@ -310,6 +330,82 @@ class DeviceControls<out S : MatteryScreen<*>>(
|
||||
redstoneControlsButton = null
|
||||
}
|
||||
|
||||
if (upgrades != null) {
|
||||
upgradesButton = addButton(object : LargeRectangleButtonPanel<S>(
|
||||
screen, this@DeviceControls,
|
||||
skinElement = Widgets18.UPGRADES
|
||||
) {
|
||||
init {
|
||||
tooltip = TranslatableComponent("otm.gui.upgrades")
|
||||
}
|
||||
|
||||
override fun tickInner() {
|
||||
super.tickInner()
|
||||
|
||||
tooltipList = ArrayList<Component>().also {
|
||||
it.add(TranslatableComponent("otm.gui.upgrades"))
|
||||
it.add(TextComponent(""))
|
||||
|
||||
if (upgrades.allowedTypes.isEmpty()) {
|
||||
it.add(TranslatableComponent("otm.gui.upgrade_type.allowed_none").withStyle(ChatFormatting.DARK_GRAY))
|
||||
} else {
|
||||
it.add(TranslatableComponent("otm.gui.upgrade_type.allowed").withStyle(ChatFormatting.GRAY))
|
||||
|
||||
for (upgrade in upgrades.allowedTypes) {
|
||||
it.add(upgrade.component.copy().withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
}
|
||||
|
||||
val i = it.size
|
||||
upgrades.currentStats.addUpgradeTooltipLines(it)
|
||||
|
||||
if (it.size != i) {
|
||||
it.add(i, TranslatableComponent("otm.gui.upgrades.current").withStyle(ChatFormatting.GRAY))
|
||||
it.add(i, TextComponent(""))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(mouseButton: Int) {
|
||||
if (mouseButton == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||
if (upgradeWindow != null && !upgradeWindow!!.isRemoved) {
|
||||
upgradeWindow!!.toScreenCenter()
|
||||
upgradeWindow!!.popup()
|
||||
} else {
|
||||
val square = ceil(upgrades.slots.size.toDouble().pow(0.5)).toInt()
|
||||
val size = square * AbstractSlotPanel.SIZE
|
||||
|
||||
upgradeWindow = FramePanel(screen, (size + 40f).coerceAtLeast(120f), 30f + size, TranslatableComponent("otm.gui.upgrades")).also { frame ->
|
||||
val grid = GridPanel(screen, frame, width = AbstractSlotPanel.SIZE * square, height = AbstractSlotPanel.SIZE * square, columns = square, rows = square)
|
||||
|
||||
for (slot in upgrades.slots) {
|
||||
SlotPanel(screen, grid, slot)
|
||||
}
|
||||
|
||||
grid.dock = Dock.FILL
|
||||
grid.dockResize = DockResizeMode.NONE
|
||||
|
||||
screen.addPanel(frame)
|
||||
|
||||
val parentFrame = this@DeviceControls.parent!!
|
||||
|
||||
frame.behaveAsWindow()
|
||||
frame.setPos(parentFrame.absoluteX + parentFrame.width / 2f - frame.width / 2f, parentFrame.absoluteY + parentFrame.height / 2f - frame.height / 2f)
|
||||
frame.popup()
|
||||
|
||||
upgrades.openState.value = true
|
||||
frame.onClose { upgrades.openState.value = false }
|
||||
|
||||
parentFrame.blockingWindow = frame
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
upgradesButton = null
|
||||
}
|
||||
|
||||
if (balanceInputs != null) {
|
||||
balanceInputsButton = addButton(LargeBooleanRectangleButtonPanel(
|
||||
screen, this,
|
||||
@ -396,8 +492,9 @@ fun <S : MatteryScreen<*>> makeDeviceControls(
|
||||
energyConfig: EnergyConfigPlayerInput? = null,
|
||||
fluidConfig: FluidConfigPlayerInput? = null,
|
||||
balanceInputs: BooleanInputWithFeedback? = null,
|
||||
upgrades: UpgradeSlots? = null,
|
||||
): DeviceControls<S> {
|
||||
return DeviceControls(screen, parent, extra = extra, redstoneConfig = redstoneConfig,
|
||||
itemConfig = itemConfig, energyConfig = energyConfig, fluidConfig = fluidConfig,
|
||||
balanceInputs = balanceInputs)
|
||||
balanceInputs = balanceInputs, upgrades = upgrades)
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ open class QueryUserPanel<out S: Screen>(
|
||||
this.width = maxWidth.coerceAtLeast(bottom.children.stream().mapToDouble { it.width.toDouble() }.sum().toFloat() + 2f) + PADDING * 2f
|
||||
|
||||
toScreenCenter()
|
||||
behaveAsWindow()
|
||||
}
|
||||
|
||||
override fun keyPressedInternal(key: Int, scancode: Int, mods: Int): Boolean {
|
||||
|
@ -636,7 +636,7 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I
|
||||
researchCanvas.setDockMargin(4f, 4f, 4f, 4f)
|
||||
|
||||
research!!.toScreenCenter()
|
||||
research!!.closeOnEscape = true
|
||||
research!!.behaveAsWindow()
|
||||
addPanel(research!!)
|
||||
research!!.requestFocus()
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
|
||||
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.WidePowerGaugePanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel
|
||||
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
|
||||
|
||||
@ -24,7 +23,7 @@ class PlatePressScreen(menu: PlatePressMenu, inventory: Inventory, title: Compon
|
||||
ProgressGaugePanel(this, frame, menu.progressGauge, 78f, PROGRESS_ARROW_TOP)
|
||||
SlotPanel(this, frame, menu.outputSlot, 104f, PROGRESS_SLOT_TOP)
|
||||
|
||||
makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig)
|
||||
makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig, upgrades = menu.upgrades)
|
||||
|
||||
return frame
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class TwinPlatePressScreen(menu: TwinPlatePressMenu, inventory: Inventory, title
|
||||
ProgressGaugePanel(this, frame, menu.progressGauge1, 78f, PROGRESS_ARROW_TOP + 10f)
|
||||
SlotPanel(this, frame, menu.outputSlots[1], 104f, PROGRESS_SLOT_TOP + 10f)
|
||||
|
||||
makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig, balanceInputs = menu.balanceInputs)
|
||||
makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig, balanceInputs = menu.balanceInputs, upgrades = menu.upgrades)
|
||||
|
||||
return frame
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import ru.dbotthepony.mc.otm.block.entity.tech.AndroidStationBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.tech.ChemicalGeneratorBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
|
||||
object MachinesConfig : AbstractConfig("machines") {
|
||||
@ -42,4 +43,34 @@ object MachinesConfig : AbstractConfig("machines") {
|
||||
}
|
||||
|
||||
val ANDROID_CHARGER = BlockEnergyStorageImpl.makeConfigEntry(builder, MNames.ANDROID_CHARGER, capacity = Decimal(400_000), throughput = Decimal(8192)) { AndroidCharger }
|
||||
|
||||
object Upgrades {
|
||||
init {
|
||||
builder.push("UPGRADES")
|
||||
}
|
||||
|
||||
val MIN_SPEED: Double by builder
|
||||
.comment("Minimal combined upgrade speed percentage (upgrades can't decrease machine speed below this)")
|
||||
.defineInRange("MIN_SPEED", -0.8, -1.0, Double.MAX_VALUE)
|
||||
|
||||
val MAX_SPEED: Double by builder
|
||||
.comment("Maximal combined upgrade speed percentage")
|
||||
.defineInRange("MAX_SPEED", Double.MAX_VALUE, 0.0, Double.MAX_VALUE)
|
||||
|
||||
val MIN_ENERGY by builder
|
||||
.comment("Minimal combined energy consumption percentage (upgrades can't decrease machine energy consumption below this)")
|
||||
.defineDecimal("MIN_ENERGY", Decimal(-0.8), Decimal(-1.0))
|
||||
|
||||
val MAX_ENERGY by builder
|
||||
.comment("Maximal combined energy consumption percentage")
|
||||
.defineDecimal("MAX_ENERGY", Decimal.LONG_MAX_VALUE, Decimal.ZERO)
|
||||
|
||||
init {
|
||||
builder.pop()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
Upgrades
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
package ru.dbotthepony.mc.otm.container
|
||||
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.UpgradeType
|
||||
import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
|
||||
import ru.dbotthepony.mc.otm.config.VerboseBalanceValues
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import kotlin.math.pow
|
||||
|
||||
open class UpgradeContainer(slotCount: Int, open val allowedUpgrades: Set<UpgradeType> = UpgradeType.ALL, watcher: Runnable = Runnable {}) : MatteryContainer(watcher, slotCount), IMatteryUpgrade {
|
||||
constructor(watcher: Runnable, slotCount: Int, allowedUpgrades: Set<UpgradeType>) : this(slotCount, allowedUpgrades, watcher)
|
||||
|
||||
final override val upgradeTypes: Set<UpgradeType>
|
||||
get() = setOf()
|
||||
|
||||
override val speedBonus: Double
|
||||
get() = stream().filter { it.isNotEmpty }.mapToDouble { it.getCapability(MatteryCapability.UPGRADE).map { it.speedBonus }.orElse(0.0) * it.count }.sum()
|
||||
override val processingItems: Int
|
||||
get() = stream().filter { it.isNotEmpty }.mapToInt { it.getCapability(MatteryCapability.UPGRADE).map { it.processingItems }.orElse(0).coerceAtLeast(0) * it.count }.sum()
|
||||
override val energyStorageFlat: Decimal
|
||||
get() = stream().filter { it.isNotEmpty }.map { it.getCapability(MatteryCapability.UPGRADE).map { it.energyStorageFlat }.orElse(Decimal.ZERO).moreThanZero() * it.count }.reduce(Decimal.ZERO, Decimal::plus)
|
||||
override val energyStorage: Decimal
|
||||
get() = stream().filter { it.isNotEmpty }.map { it.getCapability(MatteryCapability.UPGRADE).map { it.energyStorage }.orElse(Decimal.ZERO).moreThanZero() * it.count }.reduce(Decimal.ZERO, Decimal::plus)
|
||||
override val energyConsumed: Decimal
|
||||
get() = stream().filter { it.isNotEmpty }.map { it.getCapability(MatteryCapability.UPGRADE).map { it.energyConsumed }.orElse(Decimal.ZERO) * it.count }.reduce(Decimal.ZERO, Decimal::plus)
|
||||
override val failureMultiplier: Double
|
||||
get() = stream().filter { it.isNotEmpty }.mapToDouble { it.getCapability(MatteryCapability.UPGRADE).map { it.failureMultiplier }.orElse(1.0).coerceAtLeast(0.0).pow(it.count.toDouble()) }.reduce(1.0) { a, b -> a * b }
|
||||
override val energyThroughputFlat: Decimal
|
||||
get() = stream().filter { it.isNotEmpty }.map { it.getCapability(MatteryCapability.UPGRADE).map { it.energyThroughputFlat }.orElse(Decimal.ZERO).moreThanZero() * it.count }.reduce(Decimal.ZERO, Decimal::plus)
|
||||
override val energyThroughput: Decimal
|
||||
get() = stream().filter { it.isNotEmpty }.map { it.getCapability(MatteryCapability.UPGRADE).map { it.energyThroughput }.orElse(Decimal.ZERO).moreThanZero() * it.count }.reduce(Decimal.ZERO, Decimal::plus)
|
||||
|
||||
fun transform(values: ConciseBalanceValues): ConciseBalanceValues {
|
||||
return object : ConciseBalanceValues {
|
||||
override val capacity: Decimal
|
||||
get() = values.capacity * (energyStorage + Decimal.ONE) + energyStorageFlat
|
||||
override val throughput: Decimal
|
||||
get() = values.throughput * (energyThroughput + Decimal.ONE) + energyThroughputFlat
|
||||
}
|
||||
}
|
||||
|
||||
fun transform(values: VerboseBalanceValues): VerboseBalanceValues {
|
||||
return object : VerboseBalanceValues {
|
||||
override val capacity: Decimal
|
||||
get() = values.capacity * (energyStorage + Decimal.ONE) + energyStorageFlat
|
||||
override val receive: Decimal
|
||||
get() = values.receive * (energyThroughput + Decimal.ONE) + energyThroughputFlat
|
||||
override val extract: Decimal
|
||||
get() = values.extract * (energyThroughput + Decimal.ONE) + energyThroughputFlat
|
||||
}
|
||||
}
|
||||
}
|
@ -91,8 +91,8 @@ inline fun <T> LazyOptional<T>.ifPresentK(lambda: (T) -> Unit) {
|
||||
|
||||
val ItemStack.tagNotNull: CompoundTag get() = orCreateTag
|
||||
|
||||
val FluidStack.isNotEmpty get() = !isEmpty
|
||||
val ItemStack.isNotEmpty get() = !isEmpty
|
||||
inline val FluidStack.isNotEmpty get() = !isEmpty
|
||||
inline val ItemStack.isNotEmpty get() = !isEmpty
|
||||
|
||||
inline var Entity.position: Vec3
|
||||
get() = position()
|
||||
|
@ -0,0 +1,41 @@
|
||||
package ru.dbotthepony.mc.otm.core.collect
|
||||
|
||||
import java.util.EnumMap
|
||||
import java.util.function.BooleanSupplier
|
||||
import java.util.stream.Stream
|
||||
|
||||
class ConditionalEnumSet<T : Enum<T>>private constructor(private val backing: EnumMap<T, BooleanSupplier>, marker: Unit) : Set<T> {
|
||||
constructor(clazz: Class<T>) : this(EnumMap(clazz), Unit)
|
||||
constructor(map: Map<T, BooleanSupplier>) : this(EnumMap(map), Unit)
|
||||
|
||||
override val size: Int
|
||||
get() = backing.values.stream().filter { it.asBoolean }.count().toInt()
|
||||
|
||||
override fun contains(element: T): Boolean {
|
||||
return backing[element]?.asBoolean ?: false
|
||||
}
|
||||
|
||||
override fun containsAll(elements: Collection<T>): Boolean {
|
||||
return elements.all { contains(it) }
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
return backing.isEmpty() || backing.values.none { it.asBoolean }
|
||||
}
|
||||
|
||||
override fun stream(): Stream<T> {
|
||||
return backing.entries.stream().filter { it.value.asBoolean }.map { it.key }
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<T> {
|
||||
return backing.entries.iterator().filter { it.value.asBoolean }.map { it.key }
|
||||
}
|
||||
|
||||
fun add(value: T, condition: BooleanSupplier) {
|
||||
backing[value] = condition
|
||||
}
|
||||
|
||||
fun remove(value: T): Boolean {
|
||||
return backing.remove(value) != null
|
||||
}
|
||||
}
|
@ -1,68 +1,57 @@
|
||||
package ru.dbotthepony.mc.otm.core.collect
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap
|
||||
import java.util.function.BooleanSupplier
|
||||
import java.util.stream.Stream
|
||||
|
||||
class ConditionalSet<T> : AbstractSet<T> {
|
||||
// method without boxing
|
||||
fun interface Condition {
|
||||
fun check(): Boolean
|
||||
class ConditionalSet<E : Any> : Set<E> {
|
||||
private val backing = Object2ObjectLinkedOpenHashMap<E, BooleanSupplier>()
|
||||
|
||||
override val size: Int
|
||||
get() = backing.values.stream().filter { it.asBoolean }.count().toInt()
|
||||
|
||||
override fun contains(element: E): Boolean {
|
||||
return backing[element]?.asBoolean ?: false
|
||||
}
|
||||
|
||||
private val getters: Array<Pair<Condition, T>>
|
||||
|
||||
constructor(vararg getters: Pair<Condition, T>) : super() {
|
||||
this.getters = Array(getters.size) { getters[it] }
|
||||
override fun containsAll(elements: Collection<E>): Boolean {
|
||||
return elements.all { contains(it) }
|
||||
}
|
||||
|
||||
constructor(getters: List<Pair<Condition, T>>) : super() {
|
||||
this.getters = Array(getters.size) { getters[it] }
|
||||
override fun isEmpty(): Boolean {
|
||||
return backing.isEmpty() || backing.values.stream().noneMatch { it.asBoolean }
|
||||
}
|
||||
|
||||
constructor(getters: Stream<Pair<Condition, T>>) : super() {
|
||||
this.getters = getters.toArray { arrayOfNulls<Pair<Condition, T>>(it) }
|
||||
override fun stream(): Stream<E> {
|
||||
return backing.entries.stream().filter { it.value.asBoolean }.map { it.key }
|
||||
}
|
||||
|
||||
override val size: Int get() {
|
||||
var i = 0
|
||||
|
||||
for (pair in getters) {
|
||||
if (pair.first.check()) {
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
return i
|
||||
override fun iterator(): Iterator<E> {
|
||||
return backing.entries.iterator().filter { it.value.asBoolean }.map { it.key }
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<T> {
|
||||
return object : Iterator<T> {
|
||||
val parent = getters.iterator()
|
||||
private var pair: Pair<Condition, T>? = null
|
||||
fun add(element: E, condition: BooleanSupplier): Boolean {
|
||||
if (element in backing) return false
|
||||
backing[element] = condition
|
||||
return true
|
||||
}
|
||||
|
||||
private fun search() {
|
||||
for (pair in parent) {
|
||||
if (pair.first.check()) {
|
||||
this.pair = pair
|
||||
return
|
||||
}
|
||||
}
|
||||
fun addFirst(element: E, condition: BooleanSupplier): Boolean {
|
||||
if (element in backing) return false
|
||||
backing.putAndMoveToFirst(element, condition)
|
||||
return true
|
||||
}
|
||||
|
||||
this.pair = null
|
||||
}
|
||||
fun replace(element: E, condition: BooleanSupplier) {
|
||||
backing[element] = condition
|
||||
}
|
||||
|
||||
init {
|
||||
search()
|
||||
}
|
||||
fun replaceFirst(element: E, condition: BooleanSupplier) {
|
||||
backing.remove(element)
|
||||
backing.putAndMoveToFirst(element, condition)
|
||||
}
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return pair != null
|
||||
}
|
||||
|
||||
override fun next(): T {
|
||||
val pair = pair ?: throw NoSuchElementException()
|
||||
search()
|
||||
return pair.second
|
||||
}
|
||||
}
|
||||
fun remove(element: E): Boolean {
|
||||
return backing.remove(element) != null
|
||||
}
|
||||
}
|
||||
|
51
src/main/kotlin/ru/dbotthepony/mc/otm/item/SimpleUpgrade.kt
Normal file
51
src/main/kotlin/ru/dbotthepony/mc/otm/item/SimpleUpgrade.kt
Normal file
@ -0,0 +1,51 @@
|
||||
package ru.dbotthepony.mc.otm.item
|
||||
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.TooltipFlag
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraftforge.common.capabilities.Capability
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider
|
||||
import net.minecraftforge.common.util.LazyOptional
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.UpgradeType
|
||||
import ru.dbotthepony.mc.otm.capability.addUpgradeTooltipLines
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
|
||||
class SimpleUpgrade(
|
||||
properties: Properties,
|
||||
override val upgradeTypes: Set<UpgradeType>,
|
||||
override val speedBonus: Double = 0.0,
|
||||
override val processingItems: Int = 0,
|
||||
override val energyStorageFlat: Decimal = Decimal.ZERO,
|
||||
override val energyStorage: Decimal = Decimal.ZERO,
|
||||
override val energyConsumed: Decimal = Decimal.ZERO,
|
||||
override val energyThroughputFlat: Decimal = Decimal.ZERO,
|
||||
override val energyThroughput: Decimal = Decimal.ZERO,
|
||||
override val failureMultiplier: Double = 1.0,
|
||||
) : Item(properties), IMatteryUpgrade, ICapabilityProvider {
|
||||
private val resolver = LazyOptional.of { this }
|
||||
|
||||
override fun <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||
if (cap === MatteryCapability.UPGRADE) {
|
||||
return resolver.cast()
|
||||
}
|
||||
|
||||
return LazyOptional.empty()
|
||||
}
|
||||
|
||||
override fun appendHoverText(p_41421_: ItemStack, p_41422_: Level?, p_41423_: MutableList<Component>, p_41424_: TooltipFlag) {
|
||||
super.appendHoverText(p_41421_, p_41422_, p_41423_, p_41424_)
|
||||
addUpgradeTooltipLines(p_41423_)
|
||||
}
|
||||
|
||||
override fun initCapabilities(stack: ItemStack, nbt: CompoundTag?): ICapabilityProvider {
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
@ -23,6 +24,9 @@ import net.minecraft.world.item.enchantment.EnchantmentHelper.hasBindingCurse
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraftforge.network.NetworkEvent
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.UpgradeType
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorSlots
|
||||
@ -31,7 +35,12 @@ import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot
|
||||
import ru.dbotthepony.mc.otm.container.ItemFilter
|
||||
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
import ru.dbotthepony.mc.otm.core.collect.ConditionalEnumSet
|
||||
import ru.dbotthepony.mc.otm.core.collect.ConditionalSet
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.util.BigDecimalValueCodec
|
||||
import ru.dbotthepony.mc.otm.core.util.BinaryStringCodec
|
||||
import ru.dbotthepony.mc.otm.core.util.BooleanValueCodec
|
||||
@ -49,10 +58,14 @@ import ru.dbotthepony.mc.otm.network.packetHandled
|
||||
import ru.dbotthepony.mc.otm.network.sender
|
||||
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
|
||||
import ru.dbotthepony.mc.otm.network.synchronizer.IField
|
||||
import ru.dbotthepony.mc.otm.network.synchronizer.IMutableBooleanField
|
||||
import java.io.DataInputStream
|
||||
import java.io.DataOutputStream
|
||||
import java.math.BigDecimal
|
||||
import java.util.*
|
||||
import java.util.function.BooleanSupplier
|
||||
import java.util.function.DoubleSupplier
|
||||
import java.util.function.IntSupplier
|
||||
import java.util.function.Predicate
|
||||
import java.util.function.Supplier
|
||||
|
||||
@ -63,6 +76,17 @@ data class EquipmentSlots(
|
||||
val curiosSlots: List<PlayerSlot<Slot, Slot>>
|
||||
)
|
||||
|
||||
/**
|
||||
* [openState] **is clientside only**, attempting to use it on server will result
|
||||
* in classloading exceptions.
|
||||
*/
|
||||
data class UpgradeSlots(
|
||||
val slots: List<MatterySlot>,
|
||||
val allowedTypes: Set<UpgradeType>,
|
||||
val openState: GetterSetter<Boolean>,
|
||||
val currentStats: IMatteryUpgrade
|
||||
)
|
||||
|
||||
abstract class MatteryMenu @JvmOverloads protected constructor(
|
||||
menuType: MenuType<*>?,
|
||||
containerId: Int,
|
||||
@ -382,7 +406,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
|
||||
return player.distanceToSqr(pos.x.toDouble() + 0.5, pos.y.toDouble() + 0.5, pos.z.toDouble() + 0.5) <= 64.0
|
||||
}
|
||||
|
||||
private val externalSlots = ArrayList<Slot>()
|
||||
private val externalSlots = ConditionalSet<Slot>()
|
||||
private val quickMoveMapping = Reference2ObjectOpenHashMap<Slot, ReferenceArrayList<Collection<Slot>>>()
|
||||
|
||||
override fun addSlot(pSlot: Slot): Slot {
|
||||
@ -412,11 +436,17 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
|
||||
|
||||
/**
|
||||
* Adds slot to "storage slots" list (utilized by quick move) and calls [addSlot]
|
||||
*
|
||||
* [condition] allows to specify when slot is invisible on GUI (hence being ignored by quick move)
|
||||
*/
|
||||
protected fun <T : Slot> addStorageSlot(slot: T, addMapping: Boolean = true): T {
|
||||
protected fun <T : Slot> addStorageSlot(slot: T, addMapping: Boolean = true, prepend: Boolean = false, condition: BooleanSupplier = BooleanSupplier { true }): T {
|
||||
if (slot !in externalSlots) {
|
||||
addSlot(slot)
|
||||
externalSlots.add(slot)
|
||||
|
||||
if (prepend)
|
||||
externalSlots.replaceFirst(slot, condition)
|
||||
else
|
||||
externalSlots.replace(slot, condition)
|
||||
|
||||
if (addMapping) {
|
||||
mapQuickMove(slot, equipmentSlots)
|
||||
@ -446,8 +476,8 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
|
||||
mapQuickMove(slot, externalSlots, prepend = prepend)
|
||||
}
|
||||
|
||||
protected fun mapQuickMove(slot: Slot, target: Collection<Slot>, prepend: Boolean = false) {
|
||||
val listing = quickMoveMapping.computeIfAbsent(slot, Reference2ObjectFunction { ReferenceArrayList(1) })
|
||||
protected fun mapQuickMove(slot: Slot, target: Collection<Slot>, prepend: Boolean = false, condition: BooleanSupplier = BooleanSupplier { true }) {
|
||||
val listing = quickMoveMapping.computeIfAbsent(slot, Reference2ObjectFunction { ReferenceArrayList(1) /* ReferenceArrayList ибо мы используем его в некотором смысле как множество */ })
|
||||
listing.remove(target)
|
||||
|
||||
if (prepend)
|
||||
@ -715,6 +745,56 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
|
||||
)
|
||||
}
|
||||
|
||||
fun makeUpgradeSlots(count: Int, container: UpgradeContainer?): UpgradeSlots {
|
||||
if (container != null) {
|
||||
require(count == container.containerSize) { "Upgrade container size ${container.containerSize} does not match with provided size $count" }
|
||||
}
|
||||
|
||||
val allowedTypes = EnumMap<UpgradeType, IMutableBooleanField>(UpgradeType::class.java)
|
||||
|
||||
for (value in UpgradeType.ALL) {
|
||||
allowedTypes[value] = mSynchronizer.bool()
|
||||
|
||||
if (container != null) {
|
||||
allowedTypes[value]!!.boolean = value in container.allowedUpgrades
|
||||
}
|
||||
}
|
||||
|
||||
val syncContainer = container ?: SimpleContainer(count)
|
||||
|
||||
var isOpen = false
|
||||
val input = PlayerInput(BooleanValueCodec, allowSpectators = true, handler = { isOpen = it })
|
||||
|
||||
return UpgradeSlots(
|
||||
slots = immutableList(count) {
|
||||
object : MatterySlot(syncContainer, it) {
|
||||
init {
|
||||
mapQuickMoveToInventory(this)
|
||||
addStorageSlot(this, prepend = true, condition = { isOpen })
|
||||
}
|
||||
|
||||
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||
return super.mayPlace(itemStack) && itemStack.getCapability(MatteryCapability.UPGRADE).map { it.upgradeTypes.any { allowedTypes[it]!!.boolean } }.orElse(false)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
allowedTypes = ConditionalEnumSet(allowedTypes),
|
||||
openState = GetterSetter.of({ isOpen }, { input.input(it); isOpen = it }),
|
||||
currentStats = object : IMatteryUpgrade {
|
||||
override val upgradeTypes: Set<UpgradeType> = setOf()
|
||||
override val speedBonus: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.speedBonus ?: 0.0 }).property
|
||||
override val processingItems: Int by mSynchronizer.computedInt(IntSupplier { container?.processingItems ?: 0 }).property
|
||||
override val energyStorageFlat: Decimal by mSynchronizer.computedDecimal { container?.energyStorageFlat ?: Decimal.ZERO }
|
||||
override val energyStorage: Decimal by mSynchronizer.computedDecimal { container?.energyStorage ?: Decimal.ZERO }
|
||||
override val energyConsumed: Decimal by mSynchronizer.computedDecimal { container?.energyConsumed ?: Decimal.ZERO }
|
||||
override val energyThroughputFlat: Decimal by mSynchronizer.computedDecimal { container?.energyThroughputFlat ?: Decimal.ZERO }
|
||||
override val energyThroughput: Decimal by mSynchronizer.computedDecimal { container?.energyThroughput ?: Decimal.ZERO }
|
||||
override val failureMultiplier: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.failureMultiplier ?: 1.0 }).property
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TEXTURE_EMPTY_SLOTS: List<ResourceLocation> = ImmutableList.of(
|
||||
InventoryMenu.EMPTY_ARMOR_SLOT_BOOTS,
|
||||
|
@ -10,6 +10,7 @@ import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.energy
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.runOnClient
|
||||
|
@ -26,6 +26,8 @@ class PlatePressMenu @JvmOverloads constructor(
|
||||
val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig, allowPull = true)
|
||||
val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget)
|
||||
|
||||
val upgrades = makeUpgradeSlots(3, tile?.upgrades)
|
||||
|
||||
init {
|
||||
addStorageSlot(inputSlot)
|
||||
addStorageSlot(outputSlot)
|
||||
|
@ -31,6 +31,8 @@ class TwinPlatePressMenu @JvmOverloads constructor(
|
||||
|
||||
val balanceInputs = BooleanInputWithFeedback(this)
|
||||
|
||||
val upgrades = makeUpgradeSlots(4, tile?.upgrades)
|
||||
|
||||
init {
|
||||
if (tile != null) {
|
||||
balanceInputs.with(tile::balanceInputs)
|
||||
|
@ -130,6 +130,7 @@ private fun CreativeModeTab.Output.fluids(value: Item) {
|
||||
private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
|
||||
with(consumer) {
|
||||
accept(MItems.MACHINES)
|
||||
accept(MItems.CreativeUpgrades.LIST)
|
||||
|
||||
accept(MRegistry.CARGO_CRATES.item)
|
||||
accept(MItems.HOLO_SIGN)
|
||||
|
@ -4,7 +4,6 @@ package ru.dbotthepony.mc.otm.registry
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.EquipmentSlot
|
||||
import net.minecraft.world.food.FoodProperties
|
||||
import net.minecraft.world.item.*
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
@ -15,9 +14,11 @@ import net.minecraftforge.eventbus.api.IEventBus
|
||||
import net.minecraftforge.registries.DeferredRegister
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.capability.UpgradeType
|
||||
import ru.dbotthepony.mc.otm.config.ItemsConfig
|
||||
import ru.dbotthepony.mc.otm.core.collect.SupplierList
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.item.*
|
||||
import ru.dbotthepony.mc.otm.item.exopack.ExoPackCraftingUpgradeItem
|
||||
import ru.dbotthepony.mc.otm.item.exopack.ExoPackProbeItem
|
||||
@ -160,6 +161,38 @@ object MItems {
|
||||
TRITANIUM_ANVIL = SupplierList(props)
|
||||
}
|
||||
|
||||
object CreativeUpgrades {
|
||||
val SPEED: SimpleUpgrade by registry.register("creative_speed_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.SPEED.set(), speedBonus = 1.0) }
|
||||
val ENERGY_CONSUMPTION: SimpleUpgrade by registry.register("creative_energy_consumption_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.ENERGY_CONSUMPTION.set(), energyConsumed = Decimal.MINUS_ONE) }
|
||||
val ENERGY_STORAGE: SimpleUpgrade by registry.register("creative_energy_storage_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.ENERGY_STORAGE.set(), energyStorage = Decimal.ONE) }
|
||||
val ENERGY_STORAGE_FLAT: SimpleUpgrade by registry.register("creative_energy_storage_flat_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.ENERGY_STORAGE.set(), energyStorageFlat = Decimal.LONG_MAX_VALUE) }
|
||||
val ENERGY_STORAGE_FLAT_SMALL: SimpleUpgrade by registry.register("creative_energy_storage_flat2_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.ENERGY_STORAGE.set(), energyStorageFlat = Decimal.INT_MAX_VALUE) }
|
||||
val ENERGY_THROUGHPUT: SimpleUpgrade by registry.register("creative_energy_throughput_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.ENERGY_THROUGHPUT.set(), energyThroughput = Decimal.ONE) }
|
||||
val ENERGY_THROUGHPUT_FLAT: SimpleUpgrade by registry.register("creative_energy_throughput_flat_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.ENERGY_THROUGHPUT.set(), energyThroughputFlat = Decimal.LONG_MAX_VALUE) }
|
||||
val ENERGY_THROUGHPUT_FLAT_SMALL: SimpleUpgrade by registry.register("creative_energy_throughput_flat2_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.ENERGY_THROUGHPUT.set(), energyThroughputFlat = Decimal.INT_MAX_VALUE) }
|
||||
val FAILSAFE: SimpleUpgrade by registry.register("creative_failsafe_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.FAILSAFE.set(), failureMultiplier = 0.0) }
|
||||
val FAILURE: SimpleUpgrade by registry.register("creative_failure_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.FAILSAFE.set(), failureMultiplier = 2.0) }
|
||||
val PROCESSING_ITEMS: SimpleUpgrade by registry.register("creative_processing_upgrade") { SimpleUpgrade(Item.Properties().rarity(Rarity.EPIC), UpgradeType.PROCESSING.set(), processingItems = 1) }
|
||||
|
||||
val LIST = SupplierList(
|
||||
::SPEED,
|
||||
::ENERGY_CONSUMPTION,
|
||||
::ENERGY_STORAGE,
|
||||
::ENERGY_STORAGE_FLAT,
|
||||
::ENERGY_STORAGE_FLAT_SMALL,
|
||||
::ENERGY_THROUGHPUT,
|
||||
::ENERGY_THROUGHPUT_FLAT,
|
||||
::ENERGY_THROUGHPUT_FLAT_SMALL,
|
||||
::FAILSAFE,
|
||||
::FAILURE,
|
||||
::PROCESSING_ITEMS,
|
||||
)
|
||||
}
|
||||
|
||||
init {
|
||||
CreativeUpgrades
|
||||
}
|
||||
|
||||
val MATTER_DUST: Item by registry.register(MNames.MATTER_DUST) { MatterDustItem() }
|
||||
|
||||
val TRITANIUM_ORE_CLUMP: Item by registry.register(MNames.TRITANIUM_ORE_CLUMP) { Item(DEFAULT_PROPERTIES) }
|
||||
|
@ -25,6 +25,7 @@ object MItemTags {
|
||||
val CARGO_CRATES: TagKey<Item> = ItemTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "cargo_crates"))
|
||||
val MINECART_CARGO_CRATES: TagKey<Item> = ItemTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "minecart_cargo_crates"))
|
||||
val INDUSTRIAL_GLASS: TagKey<Item> = ItemTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "industrial_glass"))
|
||||
val UPGRADES: TagKey<Item> = ItemTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "upgrades"))
|
||||
|
||||
val CRAFTING_TABLES: TagKey<Item> = ItemTags.create(ResourceLocation("forge", "crafting_tables"))
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
Loading…
Reference in New Issue
Block a user