Matter entangler, ingredient matrix, shadow containers, quantum battery recipes, more JEI compat
This commit is contained in:
parent
04524db1a5
commit
e6758f1e27
@ -48,6 +48,7 @@ import ru.dbotthepony.mc.otm.datagen.models.addBlockModels
|
|||||||
import ru.dbotthepony.mc.otm.datagen.recipes.addBlastingRecipes
|
import ru.dbotthepony.mc.otm.datagen.recipes.addBlastingRecipes
|
||||||
import ru.dbotthepony.mc.otm.datagen.recipes.addCraftingTableRecipes
|
import ru.dbotthepony.mc.otm.datagen.recipes.addCraftingTableRecipes
|
||||||
import ru.dbotthepony.mc.otm.datagen.recipes.addDecorativesRecipes
|
import ru.dbotthepony.mc.otm.datagen.recipes.addDecorativesRecipes
|
||||||
|
import ru.dbotthepony.mc.otm.datagen.recipes.addMatterEntanglerRecipes
|
||||||
import ru.dbotthepony.mc.otm.datagen.recipes.addPlatePressRecipes
|
import ru.dbotthepony.mc.otm.datagen.recipes.addPlatePressRecipes
|
||||||
import ru.dbotthepony.mc.otm.datagen.recipes.addShapelessRecipes
|
import ru.dbotthepony.mc.otm.datagen.recipes.addShapelessRecipes
|
||||||
import ru.dbotthepony.mc.otm.datagen.recipes.addOreSmeltingRecipes
|
import ru.dbotthepony.mc.otm.datagen.recipes.addOreSmeltingRecipes
|
||||||
@ -564,6 +565,7 @@ object DataGen {
|
|||||||
addShapelessRecipes(consumer)
|
addShapelessRecipes(consumer)
|
||||||
addOreSmeltingRecipes(consumer)
|
addOreSmeltingRecipes(consumer)
|
||||||
addPainterRecipes(consumer)
|
addPainterRecipes(consumer)
|
||||||
|
addMatterEntanglerRecipes(consumer)
|
||||||
}
|
}
|
||||||
|
|
||||||
addPlatePressRecipes(recipeProvider)
|
addPlatePressRecipes(recipeProvider)
|
||||||
|
@ -432,6 +432,7 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
|||||||
add(MBlocks.DEV_CHEST, "Dev Chest")
|
add(MBlocks.DEV_CHEST, "Dev Chest")
|
||||||
add(MBlocks.DEV_CHEST, "desc", "Contains all items present in game")
|
add(MBlocks.DEV_CHEST, "desc", "Contains all items present in game")
|
||||||
add(MBlocks.PAINTER, "Painting Table")
|
add(MBlocks.PAINTER, "Painting Table")
|
||||||
|
add(MBlocks.MATTER_ENTANGLER, "Matter Entangler")
|
||||||
|
|
||||||
add(MBlocks.FLUID_TANK, "Fluid Tank")
|
add(MBlocks.FLUID_TANK, "Fluid Tank")
|
||||||
add(MBlocks.FLUID_TANK, "named", "Fluid Tank (%s)")
|
add(MBlocks.FLUID_TANK, "named", "Fluid Tank (%s)")
|
||||||
@ -713,6 +714,8 @@ private fun gui(provider: MatteryLanguageProvider) {
|
|||||||
with(provider.english) {
|
with(provider.english) {
|
||||||
gui("quicksearch", "Quick search...")
|
gui("quicksearch", "Quick search...")
|
||||||
|
|
||||||
|
gui("energy_required", "Energy required: %s")
|
||||||
|
|
||||||
gui("insert_priority", "Insert priority")
|
gui("insert_priority", "Insert priority")
|
||||||
gui("extract_priority", "Extract priority")
|
gui("extract_priority", "Extract priority")
|
||||||
gui("increase", "Increase")
|
gui("increase", "Increase")
|
||||||
|
@ -434,6 +434,7 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
|||||||
add(MBlocks.DEV_CHEST, "Сундук разработчика")
|
add(MBlocks.DEV_CHEST, "Сундук разработчика")
|
||||||
add(MBlocks.DEV_CHEST, "desc", "Хранит все предметы, которые есть в игре")
|
add(MBlocks.DEV_CHEST, "desc", "Хранит все предметы, которые есть в игре")
|
||||||
add(MBlocks.PAINTER, "Стол маляра")
|
add(MBlocks.PAINTER, "Стол маляра")
|
||||||
|
add(MBlocks.MATTER_ENTANGLER, "Квантовый запутыватель материи")
|
||||||
|
|
||||||
add(MBlocks.FLUID_TANK, "Жидкостный бак")
|
add(MBlocks.FLUID_TANK, "Жидкостный бак")
|
||||||
add(MBlocks.FLUID_TANK, "named", "Жидкостный бак (%s)")
|
add(MBlocks.FLUID_TANK, "named", "Жидкостный бак (%s)")
|
||||||
|
@ -134,6 +134,7 @@ fun addLootTables(lootTables: LootTables) {
|
|||||||
lootTables.tile(MBlocks.MATTER_RECONSTRUCTOR)
|
lootTables.tile(MBlocks.MATTER_RECONSTRUCTOR)
|
||||||
lootTables.tile(MBlocks.FLUID_TANK)
|
lootTables.tile(MBlocks.FLUID_TANK)
|
||||||
lootTables.tile(MBlocks.PAINTER)
|
lootTables.tile(MBlocks.PAINTER)
|
||||||
|
lootTables.tile(MBlocks.MATTER_ENTANGLER)
|
||||||
|
|
||||||
lootTables.tile(MBlocks.ENERGY_SERVO)
|
lootTables.tile(MBlocks.ENERGY_SERVO)
|
||||||
lootTables.tile(MBlocks.ENERGY_COUNTER)
|
lootTables.tile(MBlocks.ENERGY_COUNTER)
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||||
|
|
||||||
|
import net.minecraft.data.recipes.FinishedRecipe
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient
|
||||||
|
import net.minecraftforge.common.Tags
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||||
|
import ru.dbotthepony.mc.otm.recipe.IngredientMatrix
|
||||||
|
import ru.dbotthepony.mc.otm.recipe.MatterEntanglerRecipe
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MItems
|
||||||
|
import java.util.function.Consumer
|
||||||
|
|
||||||
|
fun addMatterEntanglerRecipes(consumer: Consumer<FinishedRecipe>) {
|
||||||
|
consumer.accept(
|
||||||
|
MatterEntanglerRecipe(
|
||||||
|
modLocation("quantum_capacitor"),
|
||||||
|
IngredientMatrix.of(
|
||||||
|
listOf(Ingredient.of(MItems.ELECTRIC_PARTS), Ingredient.of(MItemTags.GOLD_WIRES), Ingredient.of(MItems.ELECTRIC_PARTS)),
|
||||||
|
listOf(Ingredient.of(MItems.BATTERY_CAPACITOR), Ingredient.of(MItems.QUANTUM_TRANSCEIVER), Ingredient.of(MItems.BATTERY_CAPACITOR)),
|
||||||
|
listOf(Ingredient.of(MItemTags.TRITANIUM_PLATES), Ingredient.of(MItemTags.TRITANIUM_PLATES), Ingredient.of(MItemTags.TRITANIUM_PLATES)),
|
||||||
|
),
|
||||||
|
Decimal(40),
|
||||||
|
400.0,
|
||||||
|
ItemStack(MItems.QUANTUM_CAPACITOR, 2)
|
||||||
|
).energetic().toFinished()
|
||||||
|
)
|
||||||
|
|
||||||
|
consumer.accept(
|
||||||
|
MatterEntanglerRecipe(
|
||||||
|
modLocation("quantum_battery"),
|
||||||
|
IngredientMatrix.of(
|
||||||
|
listOf(Ingredient.of(Tags.Items.STORAGE_BLOCKS_REDSTONE), Ingredient.of(MItemTags.GOLD_WIRES), Ingredient.of(Tags.Items.STORAGE_BLOCKS_REDSTONE)),
|
||||||
|
listOf(Ingredient.of(MItems.BATTERY_DENSE), Ingredient.of(MItems.QUANTUM_TRANSCEIVER), Ingredient.of(MItems.BATTERY_DENSE)),
|
||||||
|
listOf(Ingredient.of(MItemTags.TRITANIUM_PLATES), Ingredient.of(MItemTags.TRITANIUM_PLATES), Ingredient.of(MItemTags.TRITANIUM_PLATES)),
|
||||||
|
),
|
||||||
|
Decimal(120),
|
||||||
|
600.0,
|
||||||
|
ItemStack(MItems.QUANTUM_BATTERY, 2)
|
||||||
|
).energetic().toFinished()
|
||||||
|
)
|
||||||
|
}
|
@ -162,6 +162,7 @@ fun addTags(tagsProvider: TagsProvider) {
|
|||||||
MBlocks.PLATE_PRESS,
|
MBlocks.PLATE_PRESS,
|
||||||
MBlocks.TWIN_PLATE_PRESS,
|
MBlocks.TWIN_PLATE_PRESS,
|
||||||
MBlocks.MATTER_RECYCLER,
|
MBlocks.MATTER_RECYCLER,
|
||||||
|
MBlocks.MATTER_ENTANGLER,
|
||||||
|
|
||||||
MBlocks.POWERED_FURNACE,
|
MBlocks.POWERED_FURNACE,
|
||||||
MBlocks.POWERED_SMOKER,
|
MBlocks.POWERED_SMOKER,
|
||||||
|
@ -306,8 +306,10 @@ abstract class MachineJobEventLoop<JobType : IJob>(val codec: Codec<JobType>) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var lastTickWasError = false
|
||||||
|
|
||||||
val isUnableToProcess: Boolean
|
val isUnableToProcess: Boolean
|
||||||
get() = throttleTicks > 0
|
get() = throttleTicks > 0 || lastTickWasError
|
||||||
|
|
||||||
val workProgress: Float
|
val workProgress: Float
|
||||||
get() {
|
get() {
|
||||||
@ -392,6 +394,8 @@ abstract class MachineJobEventLoop<JobType : IJob>(val codec: Codec<JobType>) :
|
|||||||
isIdling = false
|
isIdling = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastTickWasError = false
|
||||||
|
|
||||||
if (isIdling) {
|
if (isIdling) {
|
||||||
workingTicksAnim = 0
|
workingTicksAnim = 0
|
||||||
errorTicksAnim = 0
|
errorTicksAnim = 0
|
||||||
@ -430,6 +434,7 @@ abstract class MachineJobEventLoop<JobType : IJob>(val codec: Codec<JobType>) :
|
|||||||
idleReason = IdleReason.POWER
|
idleReason = IdleReason.POWER
|
||||||
isIdling = true
|
isIdling = true
|
||||||
idleTicksAnim++
|
idleTicksAnim++
|
||||||
|
lastTickWasError = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,6 +472,7 @@ abstract class MachineJobEventLoop<JobType : IJob>(val codec: Codec<JobType>) :
|
|||||||
|
|
||||||
if (!status.success) {
|
if (!status.success) {
|
||||||
throttleTicks += status.throttleTicks
|
throttleTicks += status.throttleTicks
|
||||||
|
lastTickWasError = true
|
||||||
|
|
||||||
if (status.idleReason != null) {
|
if (status.idleReason != null) {
|
||||||
idleReason = status.idleReason
|
idleReason = status.idleReason
|
||||||
@ -505,6 +511,7 @@ abstract class MachineJobEventLoop<JobType : IJob>(val codec: Codec<JobType>) :
|
|||||||
errorTicksAnim = 0
|
errorTicksAnim = 0
|
||||||
} else {
|
} else {
|
||||||
throttleTicks += status.throttleTicks
|
throttleTicks += status.throttleTicks
|
||||||
|
lastTickWasError = true
|
||||||
|
|
||||||
if (status.idleReason != null) {
|
if (status.idleReason != null) {
|
||||||
idleReason = status.idleReason
|
idleReason = status.idleReason
|
||||||
|
@ -17,7 +17,7 @@ import ru.dbotthepony.mc.otm.core.immutableList
|
|||||||
import ru.dbotthepony.mc.otm.core.immutableMap
|
import ru.dbotthepony.mc.otm.core.immutableMap
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.mapPresent
|
import ru.dbotthepony.mc.otm.core.nbt.mapPresent
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.PainterMenu
|
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu
|
||||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -0,0 +1,157 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.block.entity.matter
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
|
import net.minecraft.core.BlockPos
|
||||||
|
import net.minecraft.world.entity.player.Inventory
|
||||||
|
import net.minecraft.world.entity.player.Player
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraft.world.level.Level
|
||||||
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
|
import ru.dbotthepony.mc.otm.block.entity.ItemJob
|
||||||
|
import ru.dbotthepony.mc.otm.block.entity.JobContainer
|
||||||
|
import ru.dbotthepony.mc.otm.block.entity.JobStatus
|
||||||
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
|
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.capability.matter.MatterStorageImpl
|
||||||
|
import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage
|
||||||
|
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||||
|
import ru.dbotthepony.mc.otm.container.MatteryCraftingContainer
|
||||||
|
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||||
|
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||||
|
import ru.dbotthepony.mc.otm.container.ShadowCraftingContainer
|
||||||
|
import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||||
|
import ru.dbotthepony.mc.otm.data.minRange
|
||||||
|
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
|
||||||
|
import ru.dbotthepony.mc.otm.menu.matter.MatterEntanglerMenu
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||||
|
|
||||||
|
class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryWorkerBlockEntity<MatterEntanglerBlockEntity.Job>(MBlockEntities.MATTER_ENTANGLER, blockPos, blockState, Job.CODEC) {
|
||||||
|
class Job(itemStack: ItemStack, val matter: Decimal, ticks: Double) : ItemJob(itemStack, ticks, MachinesConfig.MATTER_ENTANGLER.energyConsumption) {
|
||||||
|
val matterPerTick = matter / ticks
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val CODEC: Codec<Job> = RecordCodecBuilder.create {
|
||||||
|
it.group(
|
||||||
|
ItemStack.CODEC.fieldOf("itemStack").forGetter(ItemJob::itemStack),
|
||||||
|
DecimalCodec.minRange(Decimal.ZERO).fieldOf("matter").forGetter(Job::matter),
|
||||||
|
Codec.DOUBLE.minRange(0.0).fieldOf("ticks").forGetter(ItemJob::ticks),
|
||||||
|
).apply(it, ::Job)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val upgrades = UpgradeContainer(::markDirtyFast, 3, UpgradeType.BASIC_MATTER)
|
||||||
|
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_ENTANGLER)))
|
||||||
|
val matter = ProfiledMatterStorage(MatterStorageImpl(::markDirtyFast, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MATTER_ENTANGLER::matterCapacity)))
|
||||||
|
val node = MatterNode()
|
||||||
|
|
||||||
|
val energyConfig = ConfigurableEnergy(energy)
|
||||||
|
|
||||||
|
val inputs = object : MatteryCraftingContainer(::itemContainerUpdated, 3, 3) {
|
||||||
|
override fun getMaxStackSize(): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val output = object : MatteryContainer(::itemContainerUpdated, 1) {
|
||||||
|
override fun getMaxStackSize(slot: Int, itemStack: ItemStack): Int {
|
||||||
|
return Int.MAX_VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val itemConfig = ConfigurableItemHandler(
|
||||||
|
input = inputs.handler(object : HandlerFilter {
|
||||||
|
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||||
|
val shadow = ShadowCraftingContainer.shadow(inputs, slot, stack)
|
||||||
|
|
||||||
|
return (level ?: return false)
|
||||||
|
.recipeManager
|
||||||
|
.byType(MRecipes.MATTER_ENTANGLER)
|
||||||
|
.values
|
||||||
|
.any { it.preemptivelyMatches(shadow, level!!) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
output = output.handler(HandlerFilter.OnlyOut)
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
savetables.stateful(::energy, ENERGY_KEY)
|
||||||
|
savetables.stateful(::matter, MATTER_STORAGE_KEY)
|
||||||
|
savetables.stateful(::upgrades)
|
||||||
|
savetables.stateful(::inputs)
|
||||||
|
savetables.stateful(::output)
|
||||||
|
|
||||||
|
exposeGlobally(MatteryCapability.MATTER_NODE, node)
|
||||||
|
exposeGlobally(MatteryCapability.MATTER, matter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setLevel(level: Level) {
|
||||||
|
super.setLevel(level)
|
||||||
|
node.discover(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
|
||||||
|
return MatterEntanglerMenu(containerID, inventory, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onJobTick(status: JobStatus<Job>, id: Int) {
|
||||||
|
val required = status.job.matterPerTick * status.ticksAdvanced
|
||||||
|
|
||||||
|
if (matter.storedMatter < required) {
|
||||||
|
matter.receiveMatter(node.graph.extractMatter(status.job.matterPerTick.coerceAtLeast(Decimal.TEN).coerceAtMost(matter.missingMatter), false), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
status.scale(matter.extractMatter(required, false) / required)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tick() {
|
||||||
|
super.tick()
|
||||||
|
|
||||||
|
if (jobEventLoops[0].currentJob == null) {
|
||||||
|
matter.extractMatter(node.graph.receiveMatter(matter.storedMatter, false), false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onJobFinish(status: JobStatus<Job>, id: Int) {
|
||||||
|
if (!output.fullyAddItem(status.job.itemStack)) {
|
||||||
|
status.noItem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun computeNextJob(id: Int): JobContainer<Job> {
|
||||||
|
if (!energy.batteryLevel.isPositive)
|
||||||
|
return JobContainer.noEnergy()
|
||||||
|
|
||||||
|
val recipe = (level ?: return JobContainer.failure())
|
||||||
|
.recipeManager
|
||||||
|
.byType(MRecipes.MATTER_ENTANGLER)
|
||||||
|
.values
|
||||||
|
.firstOrNull { it.matches(inputs, level!!) } ?: return JobContainer.noItem()
|
||||||
|
|
||||||
|
val result = recipe.assemble(inputs, level!!.registryAccess())
|
||||||
|
|
||||||
|
inputs.forEach { it.shrink(1) }
|
||||||
|
inputs.setChanged()
|
||||||
|
|
||||||
|
return JobContainer.success(
|
||||||
|
Job(
|
||||||
|
result,
|
||||||
|
recipe.matter,
|
||||||
|
recipe.ticks * MachinesConfig.MATTER_ENTANGLER.workTimeMultiplier
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.block.matter
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos
|
||||||
|
import net.minecraft.world.level.Level
|
||||||
|
import net.minecraft.world.level.block.EntityBlock
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityTicker
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||||
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
|
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
|
||||||
|
import ru.dbotthepony.mc.otm.block.entity.matter.MatterEntanglerBlockEntity
|
||||||
|
|
||||||
|
class MatterEntanglerBlock : RotatableMatteryBlock(), EntityBlock {
|
||||||
|
override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity {
|
||||||
|
return MatterEntanglerBlockEntity(blockPos, blockState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : BlockEntity?> getTicker(p_153212_: Level, p_153213_: BlockState, p_153214_: BlockEntityType<T>): BlockEntityTicker<T>? {
|
||||||
|
if (p_153212_.isClientSide) return null
|
||||||
|
return BlockEntityTicker { _, _, _, tile -> if (tile is MatterEntanglerBlockEntity) tile.tick() }
|
||||||
|
}
|
||||||
|
}
|
@ -230,6 +230,8 @@ fun Player.items(includeCosmetics: Boolean = true): Iterator<ItemStack> {
|
|||||||
matteryPlayer?.let {
|
matteryPlayer?.let {
|
||||||
if (it.hasExopack) {
|
if (it.hasExopack) {
|
||||||
iterators.add(it.exopackContainer.iterator())
|
iterators.add(it.exopackContainer.iterator())
|
||||||
|
iterators.add(it.exopackEnergy.parent.iterator())
|
||||||
|
iterators.add(it.exopackChargeSlots.iterator())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package ru.dbotthepony.mc.otm.client.screen
|
package ru.dbotthepony.mc.otm.client.screen
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.InputConstants
|
|
||||||
import net.minecraft.client.gui.screens.inventory.InventoryScreen
|
import net.minecraft.client.gui.screens.inventory.InventoryScreen
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.item.Items
|
import net.minecraft.world.item.Items
|
||||||
@ -276,7 +275,7 @@ class ExopackInventoryScreen(menu: ExopackInventoryMenu) : MatteryScreen<Exopack
|
|||||||
curios.x = x
|
curios.x = x
|
||||||
}
|
}
|
||||||
|
|
||||||
EffectListPanel(this, frame, menu.ply, x - 56f, gridHeight = 6).tick()
|
EffectListPanel(this, frame, menu.player, x - 56f, gridHeight = 6).tick()
|
||||||
|
|
||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
|||||||
import net.minecraft.ChatFormatting
|
import net.minecraft.ChatFormatting
|
||||||
import net.minecraft.client.gui.Font
|
import net.minecraft.client.gui.Font
|
||||||
import net.minecraft.client.gui.GuiGraphics
|
import net.minecraft.client.gui.GuiGraphics
|
||||||
import net.minecraft.client.gui.screens.Screen
|
|
||||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
@ -35,6 +34,7 @@ import ru.dbotthepony.mc.otm.client.screen.widget.HorizontalPowerGaugePanel
|
|||||||
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.PatternGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.PatternGaugePanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledMatterGaugePanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledPowerGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.ProfiledPowerGaugePanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.TallHorizontalProfiledPowerGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.TallHorizontalProfiledPowerGaugePanel
|
||||||
@ -209,7 +209,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
|
|||||||
if (menu.playerExoSuitSlots.isEmpty()) {
|
if (menu.playerExoSuitSlots.isEmpty()) {
|
||||||
inventoryFrame = FramePanel<MatteryScreen<*>>(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH, INVENTORY_FRAME_HEIGHT, inventory.displayName).also(this::addPanel)
|
inventoryFrame = FramePanel<MatteryScreen<*>>(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH, INVENTORY_FRAME_HEIGHT, inventory.displayName).also(this::addPanel)
|
||||||
inventoryFrame!!.makeHelpButton().addSlotFiltersHelp().also {
|
inventoryFrame!!.makeHelpButton().addSlotFiltersHelp().also {
|
||||||
if (menu.ply.matteryPlayer?.hasExopack == true)
|
if (menu.player.matteryPlayer?.hasExopack == true)
|
||||||
it.tooltips.add(TranslatableComponent("otm.gui.help.slot_charging"))
|
it.tooltips.add(TranslatableComponent("otm.gui.help.slot_charging"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
|
|||||||
} else {
|
} else {
|
||||||
inventoryFrame = FramePanel<MatteryScreen<*>>(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH_EXTENDED, BASE_INVENTORY_FRAME_HEIGHT + AbstractSlotPanel.SIZE * inventoryRows, inventory.displayName).also(this::addPanel)
|
inventoryFrame = FramePanel<MatteryScreen<*>>(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH_EXTENDED, BASE_INVENTORY_FRAME_HEIGHT + AbstractSlotPanel.SIZE * inventoryRows, inventory.displayName).also(this::addPanel)
|
||||||
inventoryFrame!!.makeHelpButton().addSlotFiltersHelp().also {
|
inventoryFrame!!.makeHelpButton().addSlotFiltersHelp().also {
|
||||||
if (menu.ply.matteryPlayer?.hasExopack == true)
|
if (menu.player.matteryPlayer?.hasExopack == true)
|
||||||
it.tooltips.add(TranslatableComponent("otm.gui.help.slot_charging"))
|
it.tooltips.add(TranslatableComponent("otm.gui.help.slot_charging"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,7 +421,9 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matter != null) {
|
if (profiledMatter != null) {
|
||||||
|
ProfiledMatterGaugePanel(this, gauges, profiledMatter).dock = Dock.LEFT
|
||||||
|
} else if (matter != null) {
|
||||||
MatterGaugePanel(this, gauges, matter).dock = Dock.LEFT
|
MatterGaugePanel(this, gauges, matter).dock = Dock.LEFT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package ru.dbotthepony.mc.otm.client.screen.tech
|
package ru.dbotthepony.mc.otm.client.screen.decorative
|
||||||
|
|
||||||
import net.minecraft.client.gui.GuiGraphics
|
import net.minecraft.client.gui.GuiGraphics
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
@ -27,7 +27,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollableCanvasPanel
|
|||||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.core.math.RGBAColor
|
import ru.dbotthepony.mc.otm.core.math.RGBAColor
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.PainterMenu
|
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu
|
||||||
|
|
||||||
class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : MatteryScreen<PainterMenu>(menu, inventory, title) {
|
class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : MatteryScreen<PainterMenu>(menu, inventory, title) {
|
||||||
inner class Bar(parent: EditablePanel<*>, val dye: DyeColor) : EditablePanel<PainterScreen>(this@PainterScreen, parent, width = 5f) {
|
inner class Bar(parent: EditablePanel<*>, val dye: DyeColor) : EditablePanel<PainterScreen>(this@PainterScreen, parent, width = 5f) {
|
@ -0,0 +1,75 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.client.screen.matter
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
import net.minecraft.world.entity.player.Inventory
|
||||||
|
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.SpritePanel
|
||||||
|
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.panels.util.GridPanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
|
||||||
|
import ru.dbotthepony.mc.otm.menu.matter.MatterEntanglerMenu
|
||||||
|
|
||||||
|
class MatterEntanglerScreen(menu: MatterEntanglerMenu, inventory: Inventory, title: Component) : MatteryScreen<MatterEntanglerMenu>(menu, inventory, title) {
|
||||||
|
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
|
||||||
|
val frame = FramePanel(this, DEFAULT_FRAME_WIDTH, 110f, title)
|
||||||
|
|
||||||
|
makeBars(frame, profiledEnergy = menu.profiledEnergy, profiledMatter = menu.profiledMatter, batterySlot = menu.batterySlot)
|
||||||
|
|
||||||
|
GridPanel.slots(this, frame, 3, 3).also {
|
||||||
|
it.dock = Dock.LEFT
|
||||||
|
it.dockLeft = 20f
|
||||||
|
it.dockRight = 4f
|
||||||
|
it.dockResize = DockResizeMode.NONE
|
||||||
|
|
||||||
|
for (slot in menu.inputs)
|
||||||
|
SlotPanel(this, it, slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressGaugePanel(this, frame, menu.progress).also {
|
||||||
|
it.dock = Dock.LEFT
|
||||||
|
it.dockHorizontal(4f)
|
||||||
|
it.dockResize = DockResizeMode.NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotPanel(this, frame, menu.outputs[0]).also {
|
||||||
|
it.dock = Dock.LEFT
|
||||||
|
it.dockHorizontal(4f)
|
||||||
|
it.dockResize = DockResizeMode.NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
val strip = EditablePanel(this, frame, height = AbstractSlotPanel.SIZE)
|
||||||
|
strip.dock = Dock.BOTTOM
|
||||||
|
strip.dockTop = 4f
|
||||||
|
strip.childrenOrder = -1
|
||||||
|
|
||||||
|
SlotPanel(this, strip, menu.entanglingA).also {
|
||||||
|
it.dock = Dock.LEFT
|
||||||
|
it.dockLeft = 20f
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotPanel(this, strip, menu.entanglingB).also {
|
||||||
|
it.dock = Dock.LEFT
|
||||||
|
it.dockLeft = 4f
|
||||||
|
}
|
||||||
|
|
||||||
|
SpritePanel(this, strip, ProgressGaugePanel.GAUGE_BACKGROUND).also {
|
||||||
|
it.dock = Dock.FILL
|
||||||
|
it.dockResize = DockResizeMode.NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotPanel(this, strip, menu.entanglingC).also {
|
||||||
|
it.dock = Dock.RIGHT
|
||||||
|
it.dockRight = 20f
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, upgrades = menu.upgrades, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig)
|
||||||
|
|
||||||
|
return frame
|
||||||
|
}
|
||||||
|
}
|
@ -346,6 +346,10 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun dockHorizontal(value: Float) {
|
||||||
|
dockMargin = dockMargin.copy(left = value, right = value)
|
||||||
|
}
|
||||||
|
|
||||||
var dockTop: Float
|
var dockTop: Float
|
||||||
get() = dockMargin.top
|
get() = dockMargin.top
|
||||||
set(value) {
|
set(value) {
|
||||||
|
@ -41,7 +41,7 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title:
|
|||||||
label.dock = Dock.TOP
|
label.dock = Dock.TOP
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!menu.ply.isSpectator) {
|
if (!menu.player.isSpectator) {
|
||||||
val button = ButtonPanel(this, frame, 0f, 0f, 0f, 20f, TranslatableComponent("block.overdrive_that_matters.energy_counter.switch"), onPress = Runnable { menu.switchDirection.accept(null) })
|
val button = ButtonPanel(this, frame, 0f, 0f, 0f, 20f, TranslatableComponent("block.overdrive_that_matters.energy_counter.switch"), onPress = Runnable { menu.switchDirection.accept(null) })
|
||||||
button.dock = Dock.TOP
|
button.dock = Dock.TOP
|
||||||
button.setDockMargin(4f, 5f, 4f, 0f)
|
button.setDockMargin(4f, 5f, 4f, 0f)
|
||||||
|
@ -79,9 +79,28 @@ open class MatterGaugePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
GAUGE_BACKGROUND.render(graphics)
|
GAUGE_BACKGROUND.render(graphics)
|
||||||
val height = this.height * (1f - widget.percentage)
|
|
||||||
|
|
||||||
if (widget.percentage > 0.01f) {
|
if (widget.percentage > 0.01f) {
|
||||||
|
renderLevel(graphics, 0f, 0f, width, height, widget.percentage, wavesStrength)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun innerRenderTooltips(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
|
||||||
|
if (isHovered) {
|
||||||
|
graphics.renderComponentTooltip(font, makeTooltip(), mouseX.toInt(), mouseY.toInt())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val GAUGE_BACKGROUND = WidgetLocation.VERTICAL_GAUGES.sprite(x = 18f, width = 9f)
|
||||||
|
val GAUGE_FOREGROUND = WidgetLocation.VERTICAL_GAUGES.sprite(x = 27f, width = 9f)
|
||||||
|
|
||||||
|
fun renderLevel(graphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float, percentage: Float, wavesStrength: Float = 0.5f) {
|
||||||
|
graphics.pose().pushPose()
|
||||||
|
graphics.pose().translate(x, y, 0f)
|
||||||
RenderSystem.setShader(GameRenderer::getPositionTexShader)
|
RenderSystem.setShader(GameRenderer::getPositionTexShader)
|
||||||
RenderSystem.enableBlend()
|
RenderSystem.enableBlend()
|
||||||
RenderSystem.defaultBlendFunc()
|
RenderSystem.defaultBlendFunc()
|
||||||
@ -98,15 +117,15 @@ open class MatterGaugePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
|
|
||||||
builder.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_TEX)
|
builder.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_TEX)
|
||||||
|
|
||||||
builder.vertex(matrix, 0f, this.height, 0f).uv(u0, v1).endVertex()
|
builder.vertex(matrix, 0f, height, 0f).uv(u0, v1).endVertex()
|
||||||
builder.vertex(matrix, width, this.height, 0f).uv(u1, v1).endVertex()
|
builder.vertex(matrix, width, height, 0f).uv(u1, v1).endVertex()
|
||||||
|
|
||||||
for (i in 4 downTo 0) {
|
for (i in 4 downTo 0) {
|
||||||
val sin = sin((System.currentTimeMillis() / 50L + i * 2L).toDouble() / 4.0).toFloat() * wavesStrength.coerceAtMost(4f)
|
val sin = sin((System.currentTimeMillis() / 50L + i * 2L).toDouble() / 4.0).toFloat() * wavesStrength.coerceAtMost(4f)
|
||||||
val cos = cos((System.currentTimeMillis() / 50L + i * 3L + 27L).toDouble() / 4.0).toFloat() * wavesStrength.coerceAtMost(4f)
|
val cos = cos((System.currentTimeMillis() / 50L + i * 3L + 27L).toDouble() / 4.0).toFloat() * wavesStrength.coerceAtMost(4f)
|
||||||
|
|
||||||
val thisX = (width * (i / 4f))
|
val thisX = (width * (i / 4f))
|
||||||
val thisY = (height + sin + cos).coerceAtLeast(0f)
|
val thisY = (height * (1f - percentage) + sin + cos).coerceAtLeast(0f)
|
||||||
|
|
||||||
builder.vertex(matrix, thisX, thisY, 0f).uv(
|
builder.vertex(matrix, thisX, thisY, 0f).uv(
|
||||||
GAUGE_FOREGROUND.partialU((i / 4f) * GAUGE_FOREGROUND.width),
|
GAUGE_FOREGROUND.partialU((i / 4f) * GAUGE_FOREGROUND.width),
|
||||||
@ -115,22 +134,9 @@ open class MatterGaugePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
BufferUploader.drawWithShader(builder.end())
|
BufferUploader.drawWithShader(builder.end())
|
||||||
|
graphics.pose().popPose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun innerRenderTooltips(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
|
|
||||||
if (isHovered) {
|
|
||||||
graphics.renderComponentTooltip(font, makeTooltip(), mouseX.toInt(), mouseY.toInt())
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val GAUGE_BACKGROUND = WidgetLocation.VERTICAL_GAUGES.sprite(x = 18f, width = 9f)
|
|
||||||
val GAUGE_FOREGROUND = WidgetLocation.VERTICAL_GAUGES.sprite(x = 27f, width = 9f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatLevel(a: Decimal, b: Decimal): Component {
|
private fun formatLevel(a: Decimal, b: Decimal): Component {
|
||||||
|
50
src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/Gauges.kt
Normal file
50
src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/Gauges.kt
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.compat.jei
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.GuiGraphics
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
|
||||||
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.formatMatter
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.formatPower
|
||||||
|
import ru.dbotthepony.mc.otm.systemTime
|
||||||
|
|
||||||
|
fun renderMatterGauge(
|
||||||
|
guiGraphics: GuiGraphics,
|
||||||
|
x: Float,
|
||||||
|
y: Float,
|
||||||
|
width: Float = MatterGaugePanel.GAUGE_BACKGROUND.width,
|
||||||
|
height: Float = MatterGaugePanel.GAUGE_BACKGROUND.height,
|
||||||
|
drainSpeed: Float = 1f,
|
||||||
|
wavesStrength: Float = drainSpeed * 2f,
|
||||||
|
) {
|
||||||
|
MatterGaugePanel.GAUGE_BACKGROUND.render(guiGraphics, x, y, width, height)
|
||||||
|
MatterGaugePanel.renderLevel(guiGraphics, x, y, width, height, 1f - ((systemTime.secondsF * drainSpeed) % 1f), wavesStrength)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun renderEnergyGauge(
|
||||||
|
guiGraphics: GuiGraphics,
|
||||||
|
x: Float,
|
||||||
|
y: Float,
|
||||||
|
width: Float = PowerGaugePanel.GAUGE_BACKGROUND.width,
|
||||||
|
height: Float = PowerGaugePanel.GAUGE_BACKGROUND.height,
|
||||||
|
drainSpeed: Float = 1f
|
||||||
|
) {
|
||||||
|
val perc = 1f - ((systemTime.secondsF * drainSpeed) % 1f)
|
||||||
|
PowerGaugePanel.GAUGE_BACKGROUND.render(guiGraphics, x, y, width, height)
|
||||||
|
PowerGaugePanel.GAUGE_FOREGROUND.renderPartial(guiGraphics, x, y + height * (1f - perc) - 1f, width, height * perc)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun matterGaugeTooltips(target: MutableList<Component>, matter: Decimal, mouseX: Double, mouseY: Double, x: Float, y: Float, width: Float = MatterGaugePanel.GAUGE_BACKGROUND.width, height: Float = MatterGaugePanel.GAUGE_BACKGROUND.height) {
|
||||||
|
if (mouseX in x .. (x + width - 1) && mouseY in y .. (y + height - 1)) {
|
||||||
|
target.add(TranslatableComponent("otm.gui.matter_panel.matter_required", matter.formatMatter(formatAsReadable = ShiftPressedCond)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun energyGaugeTooltips(target: MutableList<Component>, energy: Decimal, mouseX: Double, mouseY: Double, x: Float, y: Float, width: Float = PowerGaugePanel.GAUGE_BACKGROUND.width, height: Float = PowerGaugePanel.GAUGE_BACKGROUND.height) {
|
||||||
|
if (mouseX in x .. (x + width - 1) && mouseY in y .. (y + height - 1)) {
|
||||||
|
target.add(TranslatableComponent("otm.gui.energy_required", energy.formatPower(formatAsReadable = ShiftPressedCond)))
|
||||||
|
}
|
||||||
|
}
|
@ -69,14 +69,17 @@ class JEIPlugin : IModPlugin {
|
|||||||
registration.addRecipeCatalyst(ItemStack(MItems.POWERED_BLAST_FURNACE), RecipeTypes.BLASTING)
|
registration.addRecipeCatalyst(ItemStack(MItems.POWERED_BLAST_FURNACE), RecipeTypes.BLASTING)
|
||||||
registration.addRecipeCatalyst(ItemStack(MItems.POWERED_SMOKER), RecipeTypes.SMOKING)
|
registration.addRecipeCatalyst(ItemStack(MItems.POWERED_SMOKER), RecipeTypes.SMOKING)
|
||||||
registration.addRecipeCatalyst(ItemStack(MItems.ExopackUpgrades.CRAFTING_UPGRADE), RecipeTypes.CRAFTING)
|
registration.addRecipeCatalyst(ItemStack(MItems.ExopackUpgrades.CRAFTING_UPGRADE), RecipeTypes.CRAFTING)
|
||||||
|
registration.addRecipeCatalyst(ItemStack(MItems.ITEM_MONITOR), RecipeTypes.CRAFTING)
|
||||||
registration.addRecipeCatalyst(ItemStack(MItems.PLATE_PRESS), PlatePressRecipeCategory.recipeType)
|
registration.addRecipeCatalyst(ItemStack(MItems.PLATE_PRESS), PlatePressRecipeCategory.recipeType)
|
||||||
registration.addRecipeCatalyst(ItemStack(MItems.PAINTER), PainterRecipeCategory.recipeType)
|
registration.addRecipeCatalyst(ItemStack(MItems.PAINTER), PainterRecipeCategory.recipeType)
|
||||||
|
registration.addRecipeCatalyst(ItemStack(MItems.MATTER_ENTANGLER), MatterEntanglerRecipeCategory.recipeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerCategories(registration: IRecipeCategoryRegistration) {
|
override fun registerCategories(registration: IRecipeCategoryRegistration) {
|
||||||
helpers = registration.jeiHelpers
|
helpers = registration.jeiHelpers
|
||||||
registration.addRecipeCategories(PlatePressRecipeCategory)
|
registration.addRecipeCategories(PlatePressRecipeCategory)
|
||||||
registration.addRecipeCategories(PainterRecipeCategory)
|
registration.addRecipeCategories(PainterRecipeCategory)
|
||||||
|
registration.addRecipeCategories(MatterEntanglerRecipeCategory)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerRecipes(registration: IRecipeRegistration) {
|
override fun registerRecipes(registration: IRecipeRegistration) {
|
||||||
@ -84,6 +87,7 @@ class JEIPlugin : IModPlugin {
|
|||||||
|
|
||||||
registration.addRecipes(PlatePressRecipeCategory.recipeType, level.recipeManager.getAllRecipesFor(MRecipes.PLATE_PRESS).filter { !it.isIncomplete })
|
registration.addRecipes(PlatePressRecipeCategory.recipeType, level.recipeManager.getAllRecipesFor(MRecipes.PLATE_PRESS).filter { !it.isIncomplete })
|
||||||
registration.addRecipes(PainterRecipeCategory.recipeType, level.recipeManager.getAllRecipesFor(MRecipes.PAINTER).filter { !it.isIncomplete })
|
registration.addRecipes(PainterRecipeCategory.recipeType, level.recipeManager.getAllRecipesFor(MRecipes.PAINTER).filter { !it.isIncomplete })
|
||||||
|
registration.addRecipes(MatterEntanglerRecipeCategory.recipeType, level.recipeManager.getAllRecipesFor(MRecipes.MATTER_ENTANGLER).filter { !it.isIncomplete })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerRecipeTransferHandlers(registration: IRecipeTransferRegistration) {
|
override fun registerRecipeTransferHandlers(registration: IRecipeTransferRegistration) {
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.compat.jei
|
||||||
|
|
||||||
|
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder
|
||||||
|
import mezz.jei.api.gui.drawable.IDrawable
|
||||||
|
import mezz.jei.api.gui.ingredient.IRecipeSlotsView
|
||||||
|
import mezz.jei.api.recipe.IFocusGroup
|
||||||
|
import mezz.jei.api.recipe.RecipeIngredientRole
|
||||||
|
import mezz.jei.api.recipe.RecipeType
|
||||||
|
import mezz.jei.api.recipe.category.IRecipeCategory
|
||||||
|
import net.minecraft.client.gui.GuiGraphics
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
|
import ru.dbotthepony.mc.otm.client.render.ItemStackIcon
|
||||||
|
import ru.dbotthepony.mc.otm.client.render.draw
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
|
||||||
|
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||||
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import ru.dbotthepony.mc.otm.recipe.IMatterEntanglerRecipe
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MItems
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MNames
|
||||||
|
|
||||||
|
object MatterEntanglerRecipeCategory : IRecipeCategory<IMatterEntanglerRecipe>, IDrawable {
|
||||||
|
private val recipeType = RecipeType.create(OverdriveThatMatters.MOD_ID, MNames.MATTER_ENTANGLER, IMatterEntanglerRecipe::class.java)
|
||||||
|
|
||||||
|
override fun getRecipeType(): RecipeType<IMatterEntanglerRecipe> {
|
||||||
|
return recipeType
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTitle(): Component {
|
||||||
|
return MItems.MATTER_ENTANGLER.description
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBackground(): IDrawable {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getWidth(): Int {
|
||||||
|
return 140
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getHeight(): Int {
|
||||||
|
return 60
|
||||||
|
}
|
||||||
|
|
||||||
|
private val icon = IGUIRenderable2IDrawable(ItemStackIcon(ItemStack(MItems.MATTER_ENTANGLER)))
|
||||||
|
|
||||||
|
override fun getIcon(): IDrawable {
|
||||||
|
return icon
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setRecipe(builder: IRecipeLayoutBuilder, recipe: IMatterEntanglerRecipe, focuses: IFocusGroup) {
|
||||||
|
for (x in 0 until recipe.ingredients.width) {
|
||||||
|
for (y in 0 until recipe.ingredients.height) {
|
||||||
|
builder.addSlot(RecipeIngredientRole.INPUT, 30 + x * 18, 4 + y * 18).addIngredients(recipe.ingredients[x, y])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.addSlot(RecipeIngredientRole.OUTPUT, 116, 18 + 4).addItemStack(recipe.result)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun draw(guiGraphics: GuiGraphics, xOffset: Int, yOffset: Int) {
|
||||||
|
for (x in 0 until 3) {
|
||||||
|
for (y in 0 until 3) {
|
||||||
|
AbstractSlotPanel.SLOT_BACKGROUND.render(guiGraphics, xOffset + x * 18f + 29f, yOffset + y * 18f + 3f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractSlotPanel.SLOT_BACKGROUND.render(guiGraphics, xOffset + 115f, yOffset + 18f + 3f)
|
||||||
|
ProgressGaugePanel.GAUGE_BACKGROUND.render(guiGraphics, xOffset + 89f, yOffset + 18f + 4f)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun draw(recipe: IMatterEntanglerRecipe, recipeSlotsView: IRecipeSlotsView, guiGraphics: GuiGraphics, mouseX: Double, mouseY: Double) {
|
||||||
|
renderMatterGauge(guiGraphics, 13f, 6f, drainSpeed = (recipe.matter / Decimal(300)).toFloat())
|
||||||
|
renderEnergyGauge(guiGraphics, 4f, 6f, drainSpeed = (recipe.ticks / 2000.0).toFloat())
|
||||||
|
|
||||||
|
guiGraphics.draw(minecraft.font, x = 85f, y = 45f, text = TranslatableComponent("otm.gui.recipe.ticks", recipe.ticks), drawShadow = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTooltipStrings(recipe: IMatterEntanglerRecipe, recipeSlotsView: IRecipeSlotsView, mouseX: Double, mouseY: Double): MutableList<Component> {
|
||||||
|
val result = ArrayList<Component>()
|
||||||
|
|
||||||
|
matterGaugeTooltips(result, recipe.matter, mouseX, mouseY, 13f, 6f)
|
||||||
|
energyGaugeTooltips(result, MachinesConfig.MATTER_ENTANGLER.energyConsumption * recipe.ticks * MachinesConfig.MATTER_ENTANGLER.workTimeMultiplier, mouseX, mouseY, 4f, 6f)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
@ -43,8 +43,10 @@ object PainterRecipeCategory : IRecipeCategory<PainterRecipe>, IDrawable {
|
|||||||
return 56
|
return 56
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val icon = IGUIRenderable2IDrawable(ItemStackIcon(ItemStack(MItems.PAINTER)))
|
||||||
|
|
||||||
override fun getIcon(): IDrawable {
|
override fun getIcon(): IDrawable {
|
||||||
return IGUIRenderable2IDrawable(ItemStackIcon(ItemStack(MItems.PAINTER)))
|
return icon
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setRecipe(builder: IRecipeLayoutBuilder, recipe: PainterRecipe, focuses: IFocusGroup) {
|
override fun setRecipe(builder: IRecipeLayoutBuilder, recipe: PainterRecipe, focuses: IFocusGroup) {
|
||||||
|
@ -13,6 +13,14 @@ object MachinesConfig : AbstractConfig("machines") {
|
|||||||
energyConsumption = Decimal(15)
|
energyConsumption = Decimal(15)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val MATTER_ENTANGLER = workerValues(
|
||||||
|
MNames.MATTER_ENTANGLER,
|
||||||
|
energyStorage = Decimal(40_000),
|
||||||
|
energyThroughput = Decimal(400),
|
||||||
|
energyConsumption = Decimal(120),
|
||||||
|
matterCapacity = Decimal(60),
|
||||||
|
)
|
||||||
|
|
||||||
val MATTER_DECOMPOSER = workerValues(
|
val MATTER_DECOMPOSER = workerValues(
|
||||||
MNames.MATTER_DECOMPOSER,
|
MNames.MATTER_DECOMPOSER,
|
||||||
energyStorage = Decimal(100_000),
|
energyStorage = Decimal(100_000),
|
||||||
|
@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.ints.IntSet
|
|||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap
|
||||||
import net.minecraft.world.Container
|
import net.minecraft.world.Container
|
||||||
|
import net.minecraft.world.inventory.CraftingContainer
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.item.enchantment.EnchantmentHelper.hasVanishingCurse
|
import net.minecraft.world.item.enchantment.EnchantmentHelper.hasVanishingCurse
|
||||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||||
@ -245,3 +246,14 @@ fun Container.balance() {
|
|||||||
|
|
||||||
balance(IntArraySet(containerSize).also { for (i in 0 until containerSize) it.add(i) }, false)
|
balance(IntArraySet(containerSize).also { for (i in 0 until containerSize) it.add(i) }, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator fun CraftingContainer.get(column: Int, row: Int): ItemStack {
|
||||||
|
return getItem(column + row * width)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun CraftingContainer.get(column: Int, row: Int, flop: Boolean): ItemStack {
|
||||||
|
return if (flop)
|
||||||
|
get(width - column - 1, row)
|
||||||
|
else
|
||||||
|
get(column, row)
|
||||||
|
}
|
||||||
|
@ -4,7 +4,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
|||||||
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
|
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList
|
import it.unimi.dsi.fastutil.ints.IntArrayList
|
||||||
import it.unimi.dsi.fastutil.ints.IntComparators
|
import it.unimi.dsi.fastutil.ints.IntComparators
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectIterators
|
import it.unimi.dsi.fastutil.ints.IntSpliterator
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectSpliterators
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.ListTag
|
import net.minecraft.nbt.ListTag
|
||||||
@ -13,11 +14,16 @@ import net.minecraft.resources.ResourceLocation
|
|||||||
import net.minecraft.world.Container
|
import net.minecraft.world.Container
|
||||||
import kotlin.jvm.JvmOverloads
|
import kotlin.jvm.JvmOverloads
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
|
import net.minecraft.world.entity.player.StackedContents
|
||||||
|
import net.minecraft.world.inventory.StackedContentsCompatible
|
||||||
import net.minecraft.world.item.Item
|
import net.minecraft.world.item.Item
|
||||||
import net.minecraft.world.item.Items
|
import net.minecraft.world.item.Items
|
||||||
import net.minecraftforge.common.util.INBTSerializable
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
import net.minecraftforge.registries.ForgeRegistries
|
import net.minecraftforge.registries.ForgeRegistries
|
||||||
import ru.dbotthepony.mc.otm.core.addSorted
|
import ru.dbotthepony.mc.otm.core.addSorted
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.any
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.count
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
@ -26,17 +32,18 @@ import ru.dbotthepony.mc.otm.core.util.ItemValueCodec
|
|||||||
import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec
|
import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec
|
||||||
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
|
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
|
||||||
import ru.dbotthepony.mc.otm.network.synchronizer.IField
|
import ru.dbotthepony.mc.otm.network.synchronizer.IField
|
||||||
import java.lang.ref.PhantomReference
|
|
||||||
import java.lang.ref.ReferenceQueue
|
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.function.Consumer
|
||||||
|
import java.util.function.Predicate
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
import java.util.stream.Stream
|
||||||
|
import java.util.stream.StreamSupport
|
||||||
import kotlin.NoSuchElementException
|
import kotlin.NoSuchElementException
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
open class MatteryContainer(protected val watcher: Runnable, private val size: Int) : Container, Iterable<ItemStack>, INBTSerializable<Tag?> {
|
open class MatteryContainer(protected val watcher: Runnable, private val size: Int) : Container, Iterable<ItemStack>, INBTSerializable<Tag?>, StackedContentsCompatible {
|
||||||
constructor(size: Int) : this({}, size)
|
constructor(size: Int) : this({}, size)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -440,6 +447,12 @@ open class MatteryContainer(protected val watcher: Runnable, private val size: I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun fillStackedContents(contents: StackedContents) {
|
||||||
|
for (item in iterator()) {
|
||||||
|
contents.accountStack(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final override fun removeItem(slot: Int, amount: Int): ItemStack {
|
final override fun removeItem(slot: Int, amount: Int): ItemStack {
|
||||||
if (amount <= 0 || slot < 0 || slot >= size || slots[slot].isEmpty)
|
if (amount <= 0 || slot < 0 || slot >= size || slots[slot].isEmpty)
|
||||||
return ItemStack.EMPTY
|
return ItemStack.EMPTY
|
||||||
@ -576,6 +589,26 @@ open class MatteryContainer(protected val watcher: Runnable, private val size: I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inner class Spliterator(private val parent: IntSpliterator) : java.util.Spliterator<ItemStack> {
|
||||||
|
override fun tryAdvance(action: Consumer<in ItemStack>): Boolean {
|
||||||
|
return parent.tryAdvance {
|
||||||
|
action.accept(getItem(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun trySplit(): java.util.Spliterator<ItemStack>? {
|
||||||
|
return parent.trySplit()?.let(::Spliterator)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun estimateSize(): Long {
|
||||||
|
return parent.estimateSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun characteristics(): Int {
|
||||||
|
return parent.characteristics()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private object EmptyIterator : IContainerIterator {
|
private object EmptyIterator : IContainerIterator {
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
return false
|
return false
|
||||||
@ -601,4 +634,29 @@ open class MatteryContainer(protected val watcher: Runnable, private val size: I
|
|||||||
|
|
||||||
return Iterator()
|
return Iterator()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final override fun countItem(item: Item): Int {
|
||||||
|
return iterator().filter { it.item == item }.count().toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
final override fun hasAnyOf(set: Set<Item>): Boolean {
|
||||||
|
return iterator().any { it.item in set }
|
||||||
|
}
|
||||||
|
|
||||||
|
final override fun hasAnyMatching(predicate: Predicate<ItemStack>): Boolean {
|
||||||
|
return iterator().any(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
final override fun spliterator(): java.util.Spliterator<ItemStack> {
|
||||||
|
if (isEmpty) {
|
||||||
|
return ObjectSpliterators.emptySpliterator()
|
||||||
|
}
|
||||||
|
|
||||||
|
indicesReferenced = true
|
||||||
|
return Spliterator(nonEmptyIndices.intSpliterator())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stream(): Stream<ItemStack> {
|
||||||
|
return StreamSupport.stream(spliterator(), false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.container
|
||||||
|
|
||||||
|
import net.minecraft.world.inventory.CraftingContainer
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
|
||||||
|
open class MatteryCraftingContainer(watcher: Runnable, private val width: Int, private val height: Int) : MatteryContainer(watcher, width * height), CraftingContainer {
|
||||||
|
constructor(width: Int, height: Int) : this({}, width, height)
|
||||||
|
final override fun getWidth(): Int {
|
||||||
|
return width
|
||||||
|
}
|
||||||
|
|
||||||
|
final override fun getHeight(): Int {
|
||||||
|
return height
|
||||||
|
}
|
||||||
|
|
||||||
|
final override fun getItems(): MutableList<ItemStack> {
|
||||||
|
val i = spliterator()
|
||||||
|
val result = ArrayList<ItemStack>(i.estimateSize().toInt())
|
||||||
|
i.forEachRemaining { result.add(it) }
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.container
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap
|
||||||
|
import net.minecraft.world.Container
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import java.util.Arrays
|
||||||
|
|
||||||
|
class ShadowContainer(private val parent: Container) : Container by parent {
|
||||||
|
private val shadowed = Int2ObjectArrayMap<ItemStack>(0)
|
||||||
|
|
||||||
|
override fun clearContent() {
|
||||||
|
shadowed.clear()
|
||||||
|
parent.clearContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean {
|
||||||
|
return parent.isEmpty && shadowed.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItem(slot: Int): ItemStack {
|
||||||
|
return shadowed[slot] ?: parent.getItem(slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeItem(slot: Int, count: Int): ItemStack {
|
||||||
|
val shadow = shadowed[slot] ?: return parent.removeItem(slot, count)
|
||||||
|
val copy = shadow.copyWithCount(shadow.count.coerceAtLeast(count))
|
||||||
|
shadow.split(count)
|
||||||
|
if (shadow.isEmpty) shadowed[slot] = ItemStack.EMPTY
|
||||||
|
return copy
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeItemNoUpdate(slot: Int): ItemStack {
|
||||||
|
shadowed[slot] ?: return parent.removeItemNoUpdate(slot)
|
||||||
|
val old = shadowed[slot]
|
||||||
|
shadowed[slot] = ItemStack.EMPTY
|
||||||
|
return old!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setItem(slot: Int, item: ItemStack) {
|
||||||
|
shadowed[slot] = item
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun shadow(container: Container, slot: Int, itemStack: ItemStack): Container {
|
||||||
|
return ShadowContainer(container).also { it[slot] = itemStack }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.container
|
||||||
|
|
||||||
|
import net.minecraft.world.Container
|
||||||
|
import net.minecraft.world.entity.player.StackedContents
|
||||||
|
import net.minecraft.world.inventory.CraftingContainer
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.toList
|
||||||
|
|
||||||
|
class ShadowCraftingContainer(private val parent: CraftingContainer) : Container by ShadowContainer(parent), CraftingContainer {
|
||||||
|
override fun fillStackedContents(contents: StackedContents) {
|
||||||
|
for (item in iterator()) {
|
||||||
|
contents.accountStack(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getWidth(): Int {
|
||||||
|
return parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getHeight(): Int {
|
||||||
|
return parent.height
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItems(): MutableList<ItemStack> {
|
||||||
|
return iterator().toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun shadow(container: CraftingContainer, slot: Int, itemStack: ItemStack): CraftingContainer {
|
||||||
|
return ShadowCraftingContainer(container).also { it[slot] = itemStack }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,14 @@ package ru.dbotthepony.mc.otm.core.collect
|
|||||||
import it.unimi.dsi.fastutil.objects.ObjectIterators
|
import it.unimi.dsi.fastutil.objects.ObjectIterators
|
||||||
import ru.dbotthepony.mc.otm.core.addAll
|
import ru.dbotthepony.mc.otm.core.addAll
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
|
import java.util.Spliterator
|
||||||
|
import java.util.Spliterators
|
||||||
import java.util.function.BinaryOperator
|
import java.util.function.BinaryOperator
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
|
import java.util.function.Supplier
|
||||||
import java.util.stream.Collector
|
import java.util.stream.Collector
|
||||||
|
import java.util.stream.Stream
|
||||||
|
import java.util.stream.StreamSupport
|
||||||
|
|
||||||
// Purpose of Stream API over Iterators is that it is simple enough for JIT to inline most of it,
|
// Purpose of Stream API over Iterators is that it is simple enough for JIT to inline most of it,
|
||||||
// unlike actual Streams.
|
// unlike actual Streams.
|
||||||
@ -370,3 +375,29 @@ fun <T> Iterator<T>.maybe(): T? {
|
|||||||
fun <T> emptyIterator(): MutableIterator<T> {
|
fun <T> emptyIterator(): MutableIterator<T> {
|
||||||
return ObjectIterators.emptyIterator()
|
return ObjectIterators.emptyIterator()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> Iterator<T>.toStream(): Stream<T> {
|
||||||
|
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(this, 0), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Iterator<T>.allEqual(): Boolean {
|
||||||
|
if (hasNext()) {
|
||||||
|
val v = next()
|
||||||
|
|
||||||
|
while (hasNext()) {
|
||||||
|
if (v != next()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Iterator<T>.count(): Long {
|
||||||
|
var count = 0L
|
||||||
|
while (hasNext()) count++
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
@ -17,19 +17,64 @@ import org.apache.logging.log4j.LogManager
|
|||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
import ru.dbotthepony.mc.otm.core.util.readBinaryJsonWithCodecIndirect
|
import ru.dbotthepony.mc.otm.core.util.readBinaryJsonWithCodecIndirect
|
||||||
import ru.dbotthepony.mc.otm.core.util.writeBinaryJsonWithCodec
|
import ru.dbotthepony.mc.otm.core.util.writeBinaryJsonWithCodec
|
||||||
import java.util.*
|
import kotlin.collections.ArrayDeque
|
||||||
import kotlin.NoSuchElementException
|
|
||||||
import kotlin.concurrent.getOrSet
|
|
||||||
|
|
||||||
class Codec2RecipeSerializer<S : Recipe<*>>(val empty: S?, val codec: Codec<S>) : Codec<S> by codec, RecipeSerializer<S> {
|
class Codec2RecipeSerializer<S : Recipe<*>> private constructor(
|
||||||
constructor(supplier: (() -> ResourceLocation) -> Codec<S>) : this(null, supplier.invoke(::context))
|
val empty: S?,
|
||||||
constructor(empty: S, supplier: (() -> ResourceLocation) -> Codec<S>) : this(empty, supplier.invoke(::context))
|
private val id: ArrayDeque<ResourceLocation>,
|
||||||
|
codec: (Codec2RecipeSerializer<S>.Context) -> Codec<S>,
|
||||||
|
) : Codec<S>, RecipeSerializer<S> {
|
||||||
|
constructor(empty: S?, codec: (Codec2RecipeSerializer<S>.Context) -> Codec<S>) : this(empty, ArrayDeque(), codec)
|
||||||
|
constructor(supplier: (Codec2RecipeSerializer<S>.Context) -> Codec<S>) : this(null, supplier)
|
||||||
|
|
||||||
override fun fromJson(p_44103_: ResourceLocation, p_44104_: JsonObject): S {
|
private val codec = codec.invoke(Context())
|
||||||
|
|
||||||
|
inner class Context() {
|
||||||
|
val id: ResourceLocation
|
||||||
|
get() = checkNotNull(this@Codec2RecipeSerializer.id.lastOrNull()) { "Not currently deserializing recipe" }
|
||||||
|
|
||||||
|
fun <O : Recipe<*>> wrap(other: Codec2RecipeSerializer<O>): Codec<O> {
|
||||||
|
return object : Codec<O> {
|
||||||
|
override fun <T : Any> encode(input: O, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||||
|
try {
|
||||||
|
other.id.addLast(this@Context.id)
|
||||||
|
return other.encode(input, ops, prefix)
|
||||||
|
} finally {
|
||||||
|
other.id.removeLast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<O, T>> {
|
||||||
|
try {
|
||||||
|
other.id.addLast(this@Context.id)
|
||||||
|
return other.decode(ops, input)
|
||||||
|
} finally {
|
||||||
|
other.id.removeLast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> encode(input: S, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||||
|
return codec.encode(input, ops, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<S, T>> {
|
||||||
|
return codec.decode(ops, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <O : Recipe<*>> xmap(to: (S) -> O, from: (O) -> S): Codec2RecipeSerializer<O> {
|
||||||
|
return Codec2RecipeSerializer(empty?.let(to), id) { _ ->
|
||||||
|
codec.xmap(to, from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fromJson(id: ResourceLocation, data: JsonObject): S {
|
||||||
try {
|
try {
|
||||||
deck.getOrSet(::LinkedList).addLast(p_44103_)
|
this.id.addLast(id)
|
||||||
|
|
||||||
return codec.decode(JsonOps.INSTANCE, p_44104_).get().map(
|
return decode(JsonOps.INSTANCE, data).get().map(
|
||||||
{
|
{
|
||||||
it.first
|
it.first
|
||||||
},
|
},
|
||||||
@ -38,29 +83,29 @@ class Codec2RecipeSerializer<S : Recipe<*>>(val empty: S?, val codec: Codec<S>)
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
deck.get().removeLast()
|
this.id.removeLast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fromNetwork(p_44105_: ResourceLocation, p_44106_: FriendlyByteBuf): S? {
|
override fun fromNetwork(id: ResourceLocation, data: FriendlyByteBuf): S? {
|
||||||
try {
|
try {
|
||||||
deck.getOrSet(::LinkedList).addLast(p_44105_)
|
this.id.addLast(id)
|
||||||
|
|
||||||
return p_44106_.readBinaryJsonWithCodecIndirect(codec)
|
return data.readBinaryJsonWithCodecIndirect(this)
|
||||||
.resultOrPartial { LOGGER.error("Failed to read recipe $p_44105_ from network: $it") }.orElse(null)
|
.resultOrPartial { LOGGER.error("Failed to read recipe $id from network: $it") }.orElse(null)
|
||||||
} finally {
|
} finally {
|
||||||
deck.get().removeLast()
|
this.id.removeLast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toNetwork(p_44101_: FriendlyByteBuf, p_44102_: S) {
|
override fun toNetwork(data: FriendlyByteBuf, recipe: S) {
|
||||||
p_44101_.writeBinaryJsonWithCodec(codec, p_44102_)
|
data.writeBinaryJsonWithCodec(this, recipe)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toFinished(recipe: S): FinishedRecipe {
|
fun toFinished(recipe: S): FinishedRecipe {
|
||||||
return object : FinishedRecipe {
|
return object : FinishedRecipe {
|
||||||
override fun serializeRecipeData(p_125967_: JsonObject) {
|
override fun serializeRecipeData(p_125967_: JsonObject) {
|
||||||
codec.encode(recipe, JsonOps.INSTANCE, p_125967_).get().map(
|
encode(recipe, JsonOps.INSTANCE, p_125967_).get().map(
|
||||||
{
|
{
|
||||||
it as JsonObject
|
it as JsonObject
|
||||||
|
|
||||||
@ -92,33 +137,7 @@ class Codec2RecipeSerializer<S : Recipe<*>>(val empty: S?, val codec: Codec<S>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : Codec<ResourceLocation> {
|
companion object {
|
||||||
private val deck = ThreadLocal<LinkedList<ResourceLocation>>()
|
|
||||||
|
|
||||||
private fun context(): ResourceLocation {
|
|
||||||
val deck = deck.getOrSet(::LinkedList)
|
|
||||||
|
|
||||||
if (deck.isEmpty()) {
|
|
||||||
throw NoSuchElementException("Context stack is empty")
|
|
||||||
} else {
|
|
||||||
return deck.last
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T : Any> encode(input: ResourceLocation, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
|
||||||
return DataResult.success(ops.empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<ResourceLocation, T>> {
|
|
||||||
val deck = deck.getOrSet(::LinkedList)
|
|
||||||
|
|
||||||
if (deck.isEmpty()) {
|
|
||||||
return DataResult.error { "Attempt to use recipe serializer codec ResourceLocation' hack outside Codec2RecipeSerializer" }
|
|
||||||
} else {
|
|
||||||
return DataResult.success(Pair(deck.last, ops.empty()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val LOGGER = LogManager.getLogger()
|
private val LOGGER = LogManager.getLogger()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.data
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Pair
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.DataResult
|
||||||
|
import com.mojang.serialization.DynamicOps
|
||||||
|
import com.mojang.serialization.JsonOps
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.allEqual
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.toStream
|
||||||
|
import ru.dbotthepony.mc.otm.core.stream
|
||||||
|
import ru.dbotthepony.mc.otm.recipe.IIngredientMatrix
|
||||||
|
import ru.dbotthepony.mc.otm.recipe.IngredientMatrix
|
||||||
|
import java.util.function.Supplier
|
||||||
|
|
||||||
|
object IngredientMatrixCodec : Codec<IIngredientMatrix> {
|
||||||
|
private val ingredientList = Codec.list(IngredientCodec)
|
||||||
|
|
||||||
|
override fun <T : Any> encode(input: IIngredientMatrix, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||||
|
return DataResult.success(
|
||||||
|
ops.createList(
|
||||||
|
(0 until input.height).stream().map { row ->
|
||||||
|
ops.createList((0 until input.width).stream().map { column ->
|
||||||
|
JsonOps.INSTANCE.convertTo(ops, input[column, row].toJson())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class Handwritten(val pattern: List<String>, val key: Map<Char, Ingredient>)
|
||||||
|
|
||||||
|
private val handwrittenCodec = RecordCodecBuilder.create<Handwritten> {
|
||||||
|
it.group(
|
||||||
|
Codec.list(Codec.STRING)
|
||||||
|
.flatXmap(
|
||||||
|
{ DataResult.success(it) },
|
||||||
|
{ if (it.iterator().map { it.length }.allEqual()) DataResult.success(it) else DataResult.error { "One or more of patten strings differ in length" } }
|
||||||
|
)
|
||||||
|
.fieldOf("pattern").forGetter(Handwritten::pattern),
|
||||||
|
Codec.unboundedMap(
|
||||||
|
Codec.STRING
|
||||||
|
.flatXmap(
|
||||||
|
{ if (it.length == 1) DataResult.success(it[0]) else DataResult.error { "Ingredient key must be exactly 1 symbol in length, '$it' is invalid" } },
|
||||||
|
{ DataResult.success(it.toString()) }
|
||||||
|
), IngredientCodec).fieldOf("key").forGetter(Handwritten::key)
|
||||||
|
).apply(it, ::Handwritten)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<IIngredientMatrix, T>> {
|
||||||
|
return ops.getList(input).get().map(
|
||||||
|
{
|
||||||
|
val lines = ArrayList<DataResult<List<Ingredient>>>()
|
||||||
|
|
||||||
|
it.accept {
|
||||||
|
lines.add(ingredientList.decode(ops, it).map { it.first })
|
||||||
|
}
|
||||||
|
|
||||||
|
val errors = ArrayList<Supplier<String>>()
|
||||||
|
val ingredients = ArrayList<List<Ingredient>>()
|
||||||
|
|
||||||
|
lines.withIndex().forEach {
|
||||||
|
val (line, result) = it
|
||||||
|
result.get().map({ ingredients.add(it) }, { errors.add { "Line $line: ${it.message()}" } })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.isNotEmpty()) {
|
||||||
|
DataResult.error { "Failed to decode ingredient matrix: ${errors.joinToString { it.get() }}" }
|
||||||
|
} else if (ingredients.isEmpty()) {
|
||||||
|
DataResult.error { "Ingredient list is empty" }
|
||||||
|
} else if (!ingredients.iterator().map { it.size }.allEqual()) {
|
||||||
|
DataResult.error { "Ingredient list is not a matrix (one or multiple of rows are mismatched size)" }
|
||||||
|
} else {
|
||||||
|
val result = IngredientMatrix(ingredients.first().size, ingredients.size)
|
||||||
|
|
||||||
|
for ((row, columns) in ingredients.withIndex()) {
|
||||||
|
for ((column, ingredient) in columns.withIndex()) {
|
||||||
|
result[column, row] = ingredient
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataResult.success(Pair(result, ops.empty()))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ err1 ->
|
||||||
|
handwrittenCodec.decode(ops, input).get().map(
|
||||||
|
{
|
||||||
|
DataResult.success(it)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DataResult.error { "Failed to decode ingredients as list: ${err1.message()} and as pattern/dictionary: ${it.message()}" }
|
||||||
|
}
|
||||||
|
).flatMap {
|
||||||
|
val handwritten = it.first
|
||||||
|
val result = IngredientMatrix(handwritten.pattern.first().length, handwritten.pattern.size)
|
||||||
|
|
||||||
|
for ((row, pattern) in handwritten.pattern.withIndex()) {
|
||||||
|
for ((column, symbol) in pattern.withIndex()) {
|
||||||
|
val ingredient = if (symbol == ' ') handwritten.key[symbol] ?: Ingredient.EMPTY else handwritten.key[symbol] ?: return@flatMap DataResult.error { "Unknown ingredient with index '$symbol'" }
|
||||||
|
result[column, row] = ingredient
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataResult.success(Pair(result, ops.empty()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.item
|
||||||
|
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
|
||||||
|
interface IQuantumLinked {
|
||||||
|
fun merge(from: ItemStack, into: ItemStack): ItemStack
|
||||||
|
}
|
@ -63,7 +63,7 @@ import kotlin.collections.forEach
|
|||||||
import kotlin.collections.iterator
|
import kotlin.collections.iterator
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
|
||||||
class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanceValues?) : Item(Properties().stacksTo(1).rarity(if (balanceValues == null) Rarity.EPIC else Rarity.UNCOMMON)) {
|
class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanceValues?) : Item(Properties().stacksTo(1).rarity(if (balanceValues == null) Rarity.EPIC else Rarity.UNCOMMON)), IQuantumLinked {
|
||||||
val isCreative = balanceValues == null
|
val isCreative = balanceValues == null
|
||||||
|
|
||||||
interface IValues {
|
interface IValues {
|
||||||
@ -169,9 +169,9 @@ class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanc
|
|||||||
|
|
||||||
fun updateValues() {
|
fun updateValues() {
|
||||||
if (!values.isServer && isServerThread()) {
|
if (!values.isServer && isServerThread()) {
|
||||||
values = serverData.values(stack.tag?.getUUIDSafe("id") ?: UUID.randomUUID().also { stack.tagNotNull["id"] = it })
|
values = serverData.values(stack.tag?.getUUIDSafe("uuid") ?: UUID.randomUUID().also { stack.tagNotNull["uuid"] = it })
|
||||||
} else if (isClientThread()) {
|
} else if (isClientThread()) {
|
||||||
val id = stack.tag?.getUUIDSafe("id") ?: return
|
val id = stack.tag?.getUUIDSafe("uuid") ?: return
|
||||||
|
|
||||||
if (values.uuid != id)
|
if (values.uuid != id)
|
||||||
values = clientData.computeIfAbsent(id, Function { UnboundValues(it) })
|
values = clientData.computeIfAbsent(id, Function { UnboundValues(it) })
|
||||||
@ -278,6 +278,10 @@ class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanc
|
|||||||
get() = if (isCreative) Decimal.LONG_MAX_VALUE else super.missingPower
|
get() = if (isCreative) Decimal.LONG_MAX_VALUE else super.missingPower
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun merge(from: ItemStack, into: ItemStack): ItemStack {
|
||||||
|
return from.copyWithCount(from.count + into.count)
|
||||||
|
}
|
||||||
|
|
||||||
override fun isBarVisible(p_150899_: ItemStack): Boolean {
|
override fun isBarVisible(p_150899_: ItemStack): Boolean {
|
||||||
if (isCreative) return false
|
if (isCreative) return false
|
||||||
return p_150899_.matteryEnergy != null
|
return p_150899_.matteryEnergy != null
|
||||||
|
@ -69,7 +69,7 @@ class ExopackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
|
|||||||
}
|
}
|
||||||
|
|
||||||
val armorSlots = makeArmorSlots()
|
val armorSlots = makeArmorSlots()
|
||||||
val curiosSlots: ImmutableList<PlayerSlot<Slot, Slot>> = ImmutableList.copyOf(ply.curiosSlots)
|
val curiosSlots: ImmutableList<PlayerSlot<Slot, Slot>> = ImmutableList.copyOf(player.curiosSlots)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
for ((a, b) in curiosSlots) {
|
for ((a, b) in curiosSlots) {
|
||||||
@ -84,10 +84,10 @@ class ExopackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun popFurnaceExp() {
|
private fun popFurnaceExp() {
|
||||||
if (capability.isExopackSmeltingInstalled && capability.exopackSmelterExperience >= 1f && !ply.level().isClientSide) {
|
if (capability.isExopackSmeltingInstalled && capability.exopackSmelterExperience >= 1f && !player.level().isClientSide) {
|
||||||
val whole = capability.exopackSmelterExperience.toInt()
|
val whole = capability.exopackSmelterExperience.toInt()
|
||||||
capability.exopackSmelterExperience -= whole
|
capability.exopackSmelterExperience -= whole
|
||||||
ExperienceOrb.award(ply.level() as ServerLevel, ply.position(), whole)
|
ExperienceOrb.award(player.level() as ServerLevel, player.position(), whole)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,8 +99,8 @@ class ExopackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val furnaceOutputs: List<MachineOutputSlot> = capability.smelters.map {
|
val furnaceOutputs: List<OutputSlot> = capability.smelters.map {
|
||||||
object : MachineOutputSlot(it.output, 0, onTake = { popFurnaceExp() }) {
|
object : OutputSlot(it.output, 0, onTake = { popFurnaceExp() }) {
|
||||||
override fun mayPickup(player: Player): Boolean {
|
override fun mayPickup(player: Player): Boolean {
|
||||||
return super.mayPickup(player) && capability.isExopackSmeltingInstalled
|
return super.mayPickup(player) && capability.isExopackSmeltingInstalled
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ class ExopackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
if (capability.isExopackEnderAccessInstalled) {
|
if (capability.isExopackEnderAccessInstalled) {
|
||||||
enderChestSlots = makeSlots(ply.enderChestInventory) { a, b ->
|
enderChestSlots = makeSlots(player.enderChestInventory) { a, b ->
|
||||||
MatterySlot(a, b).also {
|
MatterySlot(a, b).also {
|
||||||
addStorageSlot(it, condition = enderChestOpenState)
|
addStorageSlot(it, condition = enderChestOpenState)
|
||||||
}
|
}
|
||||||
@ -238,16 +238,16 @@ class ExopackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendInitialData(container: ExopackInventoryMenu, itemStacks: NonNullList<ItemStack>, carried: ItemStack, remoteDataSlots: IntArray) {
|
fun sendInitialData(container: ExopackInventoryMenu, itemStacks: NonNullList<ItemStack>, carried: ItemStack, remoteDataSlots: IntArray) {
|
||||||
MatteryPlayerNetworkChannel.send(container.ply as ServerPlayer, ExopackMenuInitPacket(itemStacks, carried, container.incrementStateId()))
|
MatteryPlayerNetworkChannel.send(container.player as ServerPlayer, ExopackMenuInitPacket(itemStacks, carried, container.incrementStateId()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendSlotChange(container: ExopackInventoryMenu, slotId: Int, itemStack: ItemStack) {
|
fun sendSlotChange(container: ExopackInventoryMenu, slotId: Int, itemStack: ItemStack) {
|
||||||
if (container.slots[slotId].container != container.ply.inventory || container.ply.containerMenu is ExopackInventoryMenu)
|
if (container.slots[slotId].container != container.player.inventory || container.player.containerMenu is ExopackInventoryMenu)
|
||||||
MatteryPlayerNetworkChannel.send(container.ply as ServerPlayer, ExopackSlotPacket(slotId, itemStack, container.stateId))
|
MatteryPlayerNetworkChannel.send(container.player as ServerPlayer, ExopackSlotPacket(slotId, itemStack, container.stateId))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendCarriedChange(container: ExopackInventoryMenu, itemStack: ItemStack) {
|
fun sendCarriedChange(container: ExopackInventoryMenu, itemStack: ItemStack) {
|
||||||
MatteryPlayerNetworkChannel.send(container.ply as ServerPlayer, ExopackCarriedPacket(itemStack, container.stateId))
|
MatteryPlayerNetworkChannel.send(container.player as ServerPlayer, ExopackCarriedPacket(itemStack, container.stateId))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendDataChange(container: ExopackInventoryMenu, dataSlotId: Int, shortData: Int) {
|
fun sendDataChange(container: ExopackInventoryMenu, dataSlotId: Int, shortData: Int) {
|
||||||
|
@ -101,7 +101,7 @@ abstract class MatteryMenu(
|
|||||||
* Server->Client synchronizer
|
* Server->Client synchronizer
|
||||||
*/
|
*/
|
||||||
val mSynchronizer = FieldSynchronizer()
|
val mSynchronizer = FieldSynchronizer()
|
||||||
val ply: Player get() = inventory.player
|
val player: Player get() = inventory.player
|
||||||
|
|
||||||
private val _playerInventorySlots = ArrayList<InventorySlot>()
|
private val _playerInventorySlots = ArrayList<InventorySlot>()
|
||||||
private val _playerHotbarSlots = ArrayList<InventorySlot>()
|
private val _playerHotbarSlots = ArrayList<InventorySlot>()
|
||||||
@ -229,7 +229,7 @@ abstract class MatteryMenu(
|
|||||||
protected var inventorySlotIndexStart = 0
|
protected var inventorySlotIndexStart = 0
|
||||||
protected var inventorySlotIndexEnd = 0
|
protected var inventorySlotIndexEnd = 0
|
||||||
|
|
||||||
private val playerPacketDistributor = PacketDistributor.PLAYER.with { ply as ServerPlayer }
|
private val playerPacketDistributor = PacketDistributor.PLAYER.with { player as ServerPlayer }
|
||||||
|
|
||||||
fun addFilterSlots(slots: ItemFilter): List<GetterSetter<ItemStack>> {
|
fun addFilterSlots(slots: ItemFilter): List<GetterSetter<ItemStack>> {
|
||||||
val result = ArrayList<GetterSetter<ItemStack>>(slots.size)
|
val result = ArrayList<GetterSetter<ItemStack>>(slots.size)
|
||||||
@ -277,8 +277,8 @@ abstract class MatteryMenu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isSameInventory(other: Slot): Boolean {
|
override fun isSameInventory(other: Slot): Boolean {
|
||||||
if (container === inventory || container === ply.matteryPlayer?.exopackContainer)
|
if (container === inventory || container === player.matteryPlayer?.exopackContainer)
|
||||||
return (other.container === inventory || other.container === ply.matteryPlayer?.exopackContainer) && isSameFilter(other)
|
return (other.container === inventory || other.container === player.matteryPlayer?.exopackContainer) && isSameFilter(other)
|
||||||
|
|
||||||
return super.isSameInventory(other)
|
return super.isSameInventory(other)
|
||||||
}
|
}
|
||||||
@ -287,7 +287,7 @@ abstract class MatteryMenu(
|
|||||||
private set
|
private set
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val mattery = ply.matteryPlayer
|
val mattery = player.matteryPlayer
|
||||||
|
|
||||||
if (mattery != null) {
|
if (mattery != null) {
|
||||||
if (container === inventory) {
|
if (container === inventory) {
|
||||||
@ -349,7 +349,7 @@ abstract class MatteryMenu(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun addInventorySlots(autoFrame: Boolean = !ply.isSpectator) {
|
protected fun addInventorySlots(autoFrame: Boolean = !player.isSpectator) {
|
||||||
check(_playerInventorySlots.isEmpty()) { "Already created inventory slots" }
|
check(_playerInventorySlots.isEmpty()) { "Already created inventory slots" }
|
||||||
autoCreateInventoryFrame = autoFrame
|
autoCreateInventoryFrame = autoFrame
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ abstract class MatteryMenu(
|
|||||||
addSlot(slot)
|
addSlot(slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
val mattery = ply.matteryPlayer
|
val mattery = player.matteryPlayer
|
||||||
|
|
||||||
if (mattery != null && mattery.hasExopack) {
|
if (mattery != null && mattery.hasExopack) {
|
||||||
for (i in 0 until mattery.exopackContainer.containerSize) {
|
for (i in 0 until mattery.exopackContainer.containerSize) {
|
||||||
@ -415,9 +415,9 @@ abstract class MatteryMenu(
|
|||||||
|
|
||||||
if (payload != null) {
|
if (payload != null) {
|
||||||
if (broadcastOnce) {
|
if (broadcastOnce) {
|
||||||
MenuNetworkChannel.send(ply, MenuFieldPacket(containerId, payload))
|
MenuNetworkChannel.send(player, MenuFieldPacket(containerId, payload))
|
||||||
} else {
|
} else {
|
||||||
MenuNetworkChannel.sendNow(ply, MenuFieldPacket(containerId, payload))
|
MenuNetworkChannel.sendNow(player, MenuFieldPacket(containerId, payload))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,7 +449,7 @@ abstract class MatteryMenu(
|
|||||||
|
|
||||||
fun syncCarried() {
|
fun syncCarried() {
|
||||||
setRemoteCarried(carried.copy())
|
setRemoteCarried(carried.copy())
|
||||||
MenuNetworkChannel.send(ply as ServerPlayer, SetCarriedPacket(carried))
|
MenuNetworkChannel.send(player as ServerPlayer, SetCarriedPacket(carried))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun syncCarried(stack: ItemStack) {
|
fun syncCarried(stack: ItemStack) {
|
||||||
@ -635,11 +635,11 @@ abstract class MatteryMenu(
|
|||||||
|
|
||||||
if (remainder.isEmpty) {
|
if (remainder.isEmpty) {
|
||||||
source.set(ItemStack.EMPTY)
|
source.set(ItemStack.EMPTY)
|
||||||
source.onTake(ply, copy)
|
source.onTake(player, copy)
|
||||||
} else {
|
} else {
|
||||||
copy.count = source.item.count - remainder.count
|
copy.count = source.item.count - remainder.count
|
||||||
source.item.count = remainder.count
|
source.item.count = remainder.count
|
||||||
source.onTake(ply, copy)
|
source.onTake(player, copy)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@ -745,7 +745,7 @@ abstract class MatteryMenu(
|
|||||||
return armorSlots!!
|
return armorSlots!!
|
||||||
}
|
}
|
||||||
|
|
||||||
val cosmetic = ply.cosmeticArmorSlots
|
val cosmetic = player.cosmeticArmorSlots
|
||||||
|
|
||||||
return ImmutableList.of(
|
return ImmutableList.of(
|
||||||
PlayerSlot(EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.HEAD), cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.HEAD)),
|
PlayerSlot(EquipmentSlot(net.minecraft.world.entity.EquipmentSlot.HEAD), cosmetic?.get(net.minecraft.world.entity.EquipmentSlot.HEAD)),
|
||||||
@ -780,7 +780,7 @@ abstract class MatteryMenu(
|
|||||||
fun makeEquipmentSlots(mapMoveToExternal: Boolean = false): EquipmentSlots {
|
fun makeEquipmentSlots(mapMoveToExternal: Boolean = false): EquipmentSlots {
|
||||||
return EquipmentSlots(
|
return EquipmentSlots(
|
||||||
armorSlots = makeArmorSlots(mapMoveToExternal),
|
armorSlots = makeArmorSlots(mapMoveToExternal),
|
||||||
curiosSlots = curiosSlots ?: ImmutableList.copyOf(ply.curiosSlots).also {
|
curiosSlots = curiosSlots ?: ImmutableList.copyOf(player.curiosSlots).also {
|
||||||
for ((a, b) in it) {
|
for ((a, b) in it) {
|
||||||
equipmentSlots.add(a)
|
equipmentSlots.add(a)
|
||||||
addSlot(a)
|
addSlot(a)
|
||||||
|
@ -11,7 +11,6 @@ import ru.dbotthepony.mc.otm.capability.FlowDirection
|
|||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.energy
|
import ru.dbotthepony.mc.otm.capability.energy
|
||||||
import ru.dbotthepony.mc.otm.client.minecraft
|
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.GetterSetter
|
||||||
import ru.dbotthepony.mc.otm.core.immutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.runOnClient
|
import ru.dbotthepony.mc.otm.runOnClient
|
||||||
@ -80,7 +79,7 @@ open class UserFilteredSlot(container: Container, index: Int, x: Int = 0, y: Int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class MachineOutputSlot(container: Container, index: Int, x: Int = 0, y: Int = 0, val onTake: (ItemStack) -> Unit = {}) : MatterySlot(container, index, x, y) {
|
open class OutputSlot(container: Container, index: Int, x: Int = 0, y: Int = 0, val onTake: (ItemStack) -> Unit = {}) : MatterySlot(container, index, x, y) {
|
||||||
override fun mayPlace(itemStack: ItemStack): Boolean {
|
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler
|
|||||||
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
||||||
import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.isNotEmpty
|
import ru.dbotthepony.mc.otm.capability.isNotEmpty
|
||||||
import ru.dbotthepony.mc.otm.capability.isNotFull
|
import ru.dbotthepony.mc.otm.menu.OutputSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
||||||
@ -50,7 +49,7 @@ class FluidTankMenu(containerId: Int, inventory: Inventory, tile: FluidTankBlock
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val output = MachineOutputSlot(tile?.output ?: SimpleContainer(1), 0)
|
val output = OutputSlot(tile?.output ?: SimpleContainer(1), 0)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// сначала слот на заполнение из бака
|
// сначала слот на заполнение из бака
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package ru.dbotthepony.mc.otm.menu.tech
|
package ru.dbotthepony.mc.otm.menu.decorative
|
||||||
|
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
@ -7,10 +7,8 @@ import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
|
|||||||
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
|
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
|
||||||
import ru.dbotthepony.mc.otm.core.orNull
|
|
||||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||||
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
import ru.dbotthepony.mc.otm.menu.OutputSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
||||||
@ -27,8 +25,8 @@ class MatterDecomposerMenu @JvmOverloads constructor(
|
|||||||
override fun mayPlace(itemStack: ItemStack) = MatterManager.canDecompose(itemStack)
|
override fun mayPlace(itemStack: ItemStack) = MatterManager.canDecompose(itemStack)
|
||||||
}
|
}
|
||||||
|
|
||||||
val outputMain: MachineOutputSlot
|
val outputMain: OutputSlot
|
||||||
val outputStacking: MachineOutputSlot
|
val outputStacking: OutputSlot
|
||||||
val progressWidget = ProgressGaugeWidget(this, tile)
|
val progressWidget = ProgressGaugeWidget(this, tile)
|
||||||
val matterWidget = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter))
|
val matterWidget = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter))
|
||||||
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig)
|
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig)
|
||||||
@ -40,8 +38,8 @@ class MatterDecomposerMenu @JvmOverloads constructor(
|
|||||||
val container = tile?.outputContainer ?: SimpleContainer(2)
|
val container = tile?.outputContainer ?: SimpleContainer(2)
|
||||||
|
|
||||||
// Выход
|
// Выход
|
||||||
outputMain = MachineOutputSlot(container, 0)
|
outputMain = OutputSlot(container, 0)
|
||||||
outputStacking = MachineOutputSlot(container, 1)
|
outputStacking = OutputSlot(container, 1)
|
||||||
|
|
||||||
addStorageSlot(outputMain)
|
addStorageSlot(outputMain)
|
||||||
addStorageSlot(outputStacking)
|
addStorageSlot(outputStacking)
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.menu.matter
|
||||||
|
|
||||||
|
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.item.ItemStack
|
||||||
|
import ru.dbotthepony.mc.otm.block.entity.matter.MatterEntanglerBlockEntity
|
||||||
|
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||||
|
import ru.dbotthepony.mc.otm.container.MatteryCraftingContainer
|
||||||
|
import ru.dbotthepony.mc.otm.container.ShadowCraftingContainer
|
||||||
|
import ru.dbotthepony.mc.otm.container.get
|
||||||
|
import ru.dbotthepony.mc.otm.container.set
|
||||||
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
|
import ru.dbotthepony.mc.otm.item.IQuantumLinked
|
||||||
|
import ru.dbotthepony.mc.otm.menu.OutputSlot
|
||||||
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
|
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
||||||
|
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||||
|
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
||||||
|
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
||||||
|
import ru.dbotthepony.mc.otm.menu.makeSlots
|
||||||
|
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.registry.MMenus
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class MatterEntanglerMenu(
|
||||||
|
containerId: Int, inventory: Inventory, tile: MatterEntanglerBlockEntity? = null
|
||||||
|
) : MatteryPoweredMenu(MMenus.MATTER_ENTANGLER, containerId, inventory, tile) {
|
||||||
|
val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
|
||||||
|
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig)
|
||||||
|
val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy)
|
||||||
|
val profiledMatter = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter))
|
||||||
|
|
||||||
|
val progress = ProgressGaugeWidget(this, tile?.jobEventLoops?.get(0))
|
||||||
|
|
||||||
|
val inputs: List<MatterySlot> = makeSlots(tile?.inputs ?: object : MatteryCraftingContainer(3, 3) {
|
||||||
|
override fun getMaxStackSize(): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}) { it, i ->
|
||||||
|
object : MatterySlot(it, i) {
|
||||||
|
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||||
|
val shadow = ShadowCraftingContainer.shadow(it, i, itemStack)
|
||||||
|
val level = player.level()
|
||||||
|
|
||||||
|
return super.mayPlace(itemStack) && (level ?: return false)
|
||||||
|
.recipeManager
|
||||||
|
.byType(MRecipes.MATTER_ENTANGLER)
|
||||||
|
.values
|
||||||
|
.any { it.preemptivelyMatches(shadow, level) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val outputs = makeSlots(tile?.output ?: SimpleContainer(1), ::OutputSlot)
|
||||||
|
val upgrades = makeUpgradeSlots(3, tile?.upgrades)
|
||||||
|
|
||||||
|
private val entangling: Container = if (tile == null) object : SimpleContainer(2) {
|
||||||
|
override fun getMaxStackSize(): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
} else object : MatteryContainer(::rescan, 2) {
|
||||||
|
override fun getMaxStackSize(slot: Int, itemStack: ItemStack): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rescan() {
|
||||||
|
if (player is ServerPlayer && entangling[0].item is IQuantumLinked && entangling[1].item == entangling[0].item && entangling[0].isNotEmpty && entangling[1].isNotEmpty) {
|
||||||
|
entanglingC.container[0] = (entangling[0].item as IQuantumLinked).merge(entangling[0], entangling[1])
|
||||||
|
} else if (player is ServerPlayer) {
|
||||||
|
entanglingC.container[0] = ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class EntanglingInputSlot(index: Int) : MatterySlot(entangling, index) {
|
||||||
|
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||||
|
return super.mayPlace(itemStack) && itemStack.item is IQuantumLinked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val entanglingA: MatterySlot = EntanglingInputSlot(0)
|
||||||
|
val entanglingB: MatterySlot = EntanglingInputSlot(1)
|
||||||
|
val entanglingC: MatterySlot = object : MatterySlot(SimpleContainer(1), 0) {
|
||||||
|
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canTakeItemForPickAll(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tryRemove(p_150642_: Int, p_150643_: Int, p_150644_: Player): Optional<ItemStack> {
|
||||||
|
rescan()
|
||||||
|
return super.tryRemove(p_150642_, p_150643_, p_150644_)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTake(p_150645_: Player, p_150646_: ItemStack) {
|
||||||
|
if (p_150646_.isNotEmpty) {
|
||||||
|
entangling.removeItem(0, 1)
|
||||||
|
entangling.removeItem(1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onTake(p_150645_, p_150646_)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removed(p_38940_: Player) {
|
||||||
|
super.removed(p_38940_)
|
||||||
|
clearContainer(p_38940_, entangling)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
addSlot(outputs)
|
||||||
|
addSlot(entanglingA)
|
||||||
|
addSlot(entanglingB)
|
||||||
|
addSlot(entanglingC)
|
||||||
|
mapQuickMoveToInventory(entanglingA)
|
||||||
|
mapQuickMoveToInventory(entanglingB)
|
||||||
|
mapQuickMoveToInventory(entanglingC)
|
||||||
|
outputs.forEach(::mapQuickMoveToInventory)
|
||||||
|
addStorageSlot(inputs)
|
||||||
|
addInventorySlots()
|
||||||
|
}
|
||||||
|
}
|
@ -141,7 +141,7 @@ class MatterPanelMenu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val sorting: ItemSorter by mSynchronizer.ComputedField(
|
val sorting: ItemSorter by mSynchronizer.ComputedField(
|
||||||
getter = { tile?.getPlayerSettings(ply)?.sorter ?: ItemSorter.DEFAULT },
|
getter = { tile?.getPlayerSettings(player)?.sorter ?: ItemSorter.DEFAULT },
|
||||||
codec = ItemSorter::class.codec(),
|
codec = ItemSorter::class.codec(),
|
||||||
observer = {
|
observer = {
|
||||||
patterns.sortWith(actualComparator)
|
patterns.sortWith(actualComparator)
|
||||||
@ -151,7 +151,7 @@ class MatterPanelMenu(
|
|||||||
})
|
})
|
||||||
|
|
||||||
val isAscending: Boolean by mSynchronizer.ComputedField(
|
val isAscending: Boolean by mSynchronizer.ComputedField(
|
||||||
getter = { tile?.getPlayerSettings(ply)?.ascending ?: true },
|
getter = { tile?.getPlayerSettings(player)?.ascending ?: true },
|
||||||
codec = BooleanValueCodec,
|
codec = BooleanValueCodec,
|
||||||
observer = {
|
observer = {
|
||||||
patterns.sortWith(actualComparator)
|
patterns.sortWith(actualComparator)
|
||||||
@ -184,8 +184,8 @@ class MatterPanelMenu(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val changeIsAscending = booleanInput(allowSpectators = true) { tile?.getPlayerSettings(ply)?.ascending = it }
|
val changeIsAscending = booleanInput(allowSpectators = true) { tile?.getPlayerSettings(player)?.ascending = it }
|
||||||
val changeSorting = PlayerInput(ItemSorter::class.codec(), allowSpectators = true) { tile?.getPlayerSettings(ply)?.sorter = it }
|
val changeSorting = PlayerInput(ItemSorter::class.codec(), allowSpectators = true) { tile?.getPlayerSettings(player)?.sorter = it }
|
||||||
|
|
||||||
val sortingGS = GetterSetter.of(::sorting, changeSorting::accept)
|
val sortingGS = GetterSetter.of(::sorting, changeSorting::accept)
|
||||||
val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::accept)
|
val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::accept)
|
||||||
|
@ -10,7 +10,7 @@ import net.minecraft.world.SimpleContainer
|
|||||||
import ru.dbotthepony.mc.otm.container.CombinedContainer
|
import ru.dbotthepony.mc.otm.container.CombinedContainer
|
||||||
import ru.dbotthepony.mc.otm.core.immutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
import ru.dbotthepony.mc.otm.menu.OutputSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
||||||
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
||||||
@ -25,7 +25,7 @@ class MatterReplicatorMenu @JvmOverloads constructor(
|
|||||||
) : MatteryPoweredMenu(MMenus.MATTER_REPLICATOR, p_38852_, inventory, tile) {
|
) : MatteryPoweredMenu(MMenus.MATTER_REPLICATOR, p_38852_, inventory, tile) {
|
||||||
val matter = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter))
|
val matter = ProfiledLevelGaugeWidget(this, tile?.matter, LevelGaugeWidget(this, tile?.matter))
|
||||||
val progress = ProgressGaugeWidget(this, tile)
|
val progress = ProgressGaugeWidget(this, tile)
|
||||||
val storageSlots: List<MachineOutputSlot>
|
val storageSlots: List<OutputSlot>
|
||||||
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig)
|
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig)
|
||||||
val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
|
val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
|
||||||
val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget)
|
val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget)
|
||||||
@ -36,7 +36,7 @@ class MatterReplicatorMenu @JvmOverloads constructor(
|
|||||||
val container = CombinedContainer(tile?.outputContainer ?: SimpleContainer(3), tile?.dustContainer ?: SimpleContainer(2))
|
val container = CombinedContainer(tile?.outputContainer ?: SimpleContainer(3), tile?.dustContainer ?: SimpleContainer(2))
|
||||||
|
|
||||||
storageSlots = immutableList(5) {
|
storageSlots = immutableList(5) {
|
||||||
addStorageSlot(MachineOutputSlot(container, it, onTake = {
|
addStorageSlot(OutputSlot(container, it, onTake = {
|
||||||
if (inventory.player is ServerPlayer && it.isNotEmpty)
|
if (inventory.player is ServerPlayer && it.isNotEmpty)
|
||||||
TakeItemOutOfReplicatorTrigger.trigger(inventory.player as ServerPlayer, it) }))
|
TakeItemOutOfReplicatorTrigger.trigger(inventory.player as ServerPlayer, it) }))
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,8 @@ class DriveViewerMenu(
|
|||||||
val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
|
val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
|
||||||
|
|
||||||
val settings = object : DriveViewerBlockEntity.ISettings {
|
val settings = object : DriveViewerBlockEntity.ISettings {
|
||||||
override var sorting: ItemStorageStackSorter by EnumInputWithFeedback(this@DriveViewerMenu, true, tile?.let { it.getSettingsFor(ply)::sorting }).also { it.addListener { changes() } }
|
override var sorting: ItemStorageStackSorter by EnumInputWithFeedback(this@DriveViewerMenu, true, tile?.let { it.getSettingsFor(player)::sorting }).also { it.addListener { changes() } }
|
||||||
override var isAscending: Boolean by BooleanInputWithFeedback(this@DriveViewerMenu, true, tile?.let { it.getSettingsFor(ply)::isAscending }).also { it.addListener { changes() } }
|
override var isAscending: Boolean by BooleanInputWithFeedback(this@DriveViewerMenu, true, tile?.let { it.getSettingsFor(player)::isAscending }).also { it.addListener { changes() } }
|
||||||
|
|
||||||
private fun changes() {
|
private fun changes() {
|
||||||
if (isAscending) {
|
if (isAscending) {
|
||||||
|
@ -86,11 +86,11 @@ class ItemMonitorMenu(
|
|||||||
override val networkedItemView = NetworkedItemView(inventory.player, this, tile == null)
|
override val networkedItemView = NetworkedItemView(inventory.player, this, tile == null)
|
||||||
|
|
||||||
val settings = object : IItemMonitorPlayerSettings {
|
val settings = object : IItemMonitorPlayerSettings {
|
||||||
override var ingredientPriority by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(ply as ServerPlayer)::ingredientPriority })
|
override var ingredientPriority by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::ingredientPriority })
|
||||||
override var resultTarget by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(ply as ServerPlayer)::resultTarget })
|
override var resultTarget by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::resultTarget })
|
||||||
override var craftingAmount by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(ply as ServerPlayer)::craftingAmount })
|
override var craftingAmount by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::craftingAmount })
|
||||||
override var sorting by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(ply as ServerPlayer)::sorting }).also { it.addListener { changes() } }
|
override var sorting by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::sorting }).also { it.addListener { changes() } }
|
||||||
override var ascendingSort by BooleanInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(ply as ServerPlayer)::ascendingSort }).also { it.addListener { changes() } }
|
override var ascendingSort by BooleanInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::ascendingSort }).also { it.addListener { changes() } }
|
||||||
|
|
||||||
private fun changes() {
|
private fun changes() {
|
||||||
if (ascendingSort) {
|
if (ascendingSort) {
|
||||||
@ -140,7 +140,7 @@ class ItemMonitorMenu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!simulate && remaining.isNotEmpty) {
|
if (!simulate && remaining.isNotEmpty) {
|
||||||
ply.spawnAtLocation(remaining)
|
player.spawnAtLocation(remaining)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
|
@ -24,8 +24,8 @@ class AndroidStationMenu @JvmOverloads constructor(
|
|||||||
tile: AndroidStationBlockEntity? = null
|
tile: AndroidStationBlockEntity? = null
|
||||||
) : MatteryPoweredMenu(MMenus.ANDROID_STATION, containerID, inventory, tile) {
|
) : MatteryPoweredMenu(MMenus.ANDROID_STATION, containerID, inventory, tile) {
|
||||||
private fun container(target: (MatteryPlayerCapability) -> KMutableProperty0<ItemStack>): Container {
|
private fun container(target: (MatteryPlayerCapability) -> KMutableProperty0<ItemStack>): Container {
|
||||||
if (ply is ServerPlayer)
|
if (player is ServerPlayer)
|
||||||
return PartContainer(target.invoke(ply.matteryPlayer ?: throw NullPointerException("OTM player capability is missing")))
|
return PartContainer(target.invoke(player.matteryPlayer ?: throw NullPointerException("OTM player capability is missing")))
|
||||||
else
|
else
|
||||||
return SimpleContainer(1)
|
return SimpleContainer(1)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import net.minecraft.world.entity.player.Inventory
|
|||||||
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.CobblerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.CobblerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.core.immutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
import ru.dbotthepony.mc.otm.menu.OutputSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
||||||
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
||||||
@ -17,7 +17,7 @@ class CobblerMenu @JvmOverloads constructor(
|
|||||||
inventory: Inventory,
|
inventory: Inventory,
|
||||||
tile: CobblerBlockEntity? = null
|
tile: CobblerBlockEntity? = null
|
||||||
) : MatteryMenu(MMenus.COBBLESTONE_GENERATOR, p_38852_, inventory, tile) {
|
) : MatteryMenu(MMenus.COBBLESTONE_GENERATOR, p_38852_, inventory, tile) {
|
||||||
val storageSlots = (tile?.container ?: SimpleContainer(CobblerBlockEntity.CONTAINER_SIZE)).let { c -> immutableList(c.containerSize) { addStorageSlot(MachineOutputSlot(c, it)) } }
|
val storageSlots = (tile?.container ?: SimpleContainer(CobblerBlockEntity.CONTAINER_SIZE)).let { c -> immutableList(c.containerSize) { addStorageSlot(OutputSlot(c, it)) } }
|
||||||
val redstone = EnumInputWithFeedback<RedstoneSetting>(this)
|
val redstone = EnumInputWithFeedback<RedstoneSetting>(this)
|
||||||
val itemConfig = ItemConfigPlayerInput(this)
|
val itemConfig = ItemConfigPlayerInput(this)
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ class EssenceStorageMenu @JvmOverloads constructor(
|
|||||||
|
|
||||||
val storeLevels = intInput {
|
val storeLevels = intInput {
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
val ply = ply as ServerPlayer
|
val ply = player as ServerPlayer
|
||||||
tile!!
|
tile!!
|
||||||
|
|
||||||
if (it == 1) {
|
if (it == 1) {
|
||||||
@ -63,7 +63,7 @@ class EssenceStorageMenu @JvmOverloads constructor(
|
|||||||
|
|
||||||
val dispenseLevels = intInput {
|
val dispenseLevels = intInput {
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
val ply = ply as ServerPlayer
|
val ply = player as ServerPlayer
|
||||||
tile!!
|
tile!!
|
||||||
|
|
||||||
if (it == 1) {
|
if (it == 1) {
|
||||||
|
@ -4,7 +4,7 @@ import net.minecraft.server.level.ServerPlayer
|
|||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
import ru.dbotthepony.mc.otm.menu.OutputSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
||||||
@ -19,7 +19,7 @@ class PlatePressMenu @JvmOverloads constructor(
|
|||||||
tile: PlatePressBlockEntity? = null
|
tile: PlatePressBlockEntity? = null
|
||||||
) : MatteryPoweredMenu(MMenus.PLATE_PRESS, containerID, inventory, tile) {
|
) : MatteryPoweredMenu(MMenus.PLATE_PRESS, containerID, inventory, tile) {
|
||||||
val inputSlot = MatterySlot(tile?.inputContainer ?: SimpleContainer(1), 0)
|
val inputSlot = MatterySlot(tile?.inputContainer ?: SimpleContainer(1), 0)
|
||||||
val outputSlot = MachineOutputSlot(tile?.outputContainer ?: SimpleContainer(1), 0) { tile?.popExperience(ply as ServerPlayer) }
|
val outputSlot = OutputSlot(tile?.outputContainer ?: SimpleContainer(1), 0) { tile?.popExperience(player as ServerPlayer) }
|
||||||
|
|
||||||
val progressGauge = ProgressGaugeWidget(this, tile)
|
val progressGauge = ProgressGaugeWidget(this, tile)
|
||||||
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true)
|
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true)
|
||||||
|
@ -4,7 +4,7 @@ import net.minecraft.server.level.ServerPlayer
|
|||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.PoweredFurnaceBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.PoweredFurnaceBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.core.immutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
import ru.dbotthepony.mc.otm.menu.OutputSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||||
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
||||||
@ -21,7 +21,7 @@ class PoweredFurnaceMenu(
|
|||||||
tile: PoweredFurnaceBlockEntity? = null
|
tile: PoweredFurnaceBlockEntity? = null
|
||||||
) : MatteryPoweredMenu(MMenus.POWERED_FURNACE, containerID, inventory, tile) {
|
) : MatteryPoweredMenu(MMenus.POWERED_FURNACE, containerID, inventory, tile) {
|
||||||
val inputSlots = makeSlots(tile?.inputs, 2, ::MatterySlot)
|
val inputSlots = makeSlots(tile?.inputs, 2, ::MatterySlot)
|
||||||
val outputSlots = makeSlots(tile?.outputs, 2) { c, s -> MachineOutputSlot(c, s) { tile?.popExperience(ply as ServerPlayer) } }
|
val outputSlots = makeSlots(tile?.outputs, 2) { c, s -> OutputSlot(c, s) { tile?.popExperience(player as ServerPlayer) } }
|
||||||
|
|
||||||
val progressGauge = immutableList(2) { ProgressGaugeWidget(this, tile?.jobEventLoops?.get(it)) }
|
val progressGauge = immutableList(2) { ProgressGaugeWidget(this, tile?.jobEventLoops?.get(it)) }
|
||||||
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true)
|
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true)
|
||||||
|
@ -4,7 +4,7 @@ import net.minecraft.server.level.ServerPlayer
|
|||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
import ru.dbotthepony.mc.otm.menu.OutputSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||||
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
||||||
@ -21,7 +21,7 @@ class TwinPlatePressMenu @JvmOverloads constructor(
|
|||||||
tile: PlatePressBlockEntity? = null
|
tile: PlatePressBlockEntity? = null
|
||||||
) : MatteryPoweredMenu(MMenus.TWIN_PLATE_PRESS, containerID, inventory, tile) {
|
) : MatteryPoweredMenu(MMenus.TWIN_PLATE_PRESS, containerID, inventory, tile) {
|
||||||
val inputSlots = makeSlots(tile?.inputContainer ?: SimpleContainer(2), ::MatterySlot)
|
val inputSlots = makeSlots(tile?.inputContainer ?: SimpleContainer(2), ::MatterySlot)
|
||||||
val outputSlots = makeSlots(tile?.outputContainer ?: SimpleContainer(2)) { a, b -> MachineOutputSlot(a, b) { tile?.popExperience(ply as ServerPlayer) } }
|
val outputSlots = makeSlots(tile?.outputContainer ?: SimpleContainer(2)) { a, b -> OutputSlot(a, b) { tile?.popExperience(player as ServerPlayer) } }
|
||||||
|
|
||||||
val progressGauge0 = ProgressGaugeWidget(this, tile?.jobEventLoops?.get(0))
|
val progressGauge0 = ProgressGaugeWidget(this, tile?.jobEventLoops?.get(0))
|
||||||
val progressGauge1 = ProgressGaugeWidget(this, tile?.jobEventLoops?.get(1))
|
val progressGauge1 = ProgressGaugeWidget(this, tile?.jobEventLoops?.get(1))
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.recipe
|
||||||
|
|
||||||
|
import net.minecraft.core.NonNullList
|
||||||
|
import net.minecraft.world.Container
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient
|
||||||
|
import net.minecraft.world.item.crafting.Recipe
|
||||||
|
import net.minecraft.world.item.crafting.RecipeSerializer
|
||||||
|
import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer
|
||||||
|
|
||||||
|
// overrides all methods to fix Kotlin bug related to implementation delegation (to allow easy optics)
|
||||||
|
// https://youtrack.jetbrains.com/issue/KT-55080/Change-the-behavior-of-inheritance-delegation-to-delegates-implementing-Java-interfaces-with-default-methods
|
||||||
|
interface IMatteryRecipe<C : Container> : Recipe<C> {
|
||||||
|
override fun getRemainingItems(p_44004_: C): NonNullList<ItemStack> {
|
||||||
|
return super.getRemainingItems(p_44004_)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIngredients(): NonNullList<Ingredient> {
|
||||||
|
return super.getIngredients()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isSpecial(): Boolean {
|
||||||
|
return super.isSpecial()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showNotification(): Boolean {
|
||||||
|
return super.showNotification()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getGroup(): String {
|
||||||
|
return super.getGroup()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getToastSymbol(): ItemStack {
|
||||||
|
return super.getToastSymbol()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isIncomplete(): Boolean {
|
||||||
|
return super.isIncomplete()
|
||||||
|
}
|
||||||
|
}
|
151
src/main/kotlin/ru/dbotthepony/mc/otm/recipe/IngredientMatrix.kt
Normal file
151
src/main/kotlin/ru/dbotthepony/mc/otm/recipe/IngredientMatrix.kt
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.recipe
|
||||||
|
|
||||||
|
import net.minecraft.core.NonNullList
|
||||||
|
import net.minecraft.world.inventory.CraftingContainer
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient
|
||||||
|
import ru.dbotthepony.mc.otm.container.get
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.allEqual
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.any
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.flatMap
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
|
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
|
||||||
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
|
import java.util.function.Predicate
|
||||||
|
|
||||||
|
interface IIngredientMatrix : Predicate<CraftingContainer>, Iterable<Ingredient> {
|
||||||
|
val width: Int
|
||||||
|
val height: Int
|
||||||
|
val isEmpty: Boolean
|
||||||
|
get() = width == 0 || height == 0
|
||||||
|
|
||||||
|
val isIncomplete: Boolean
|
||||||
|
get() = iterator().any { it.isActuallyEmpty }
|
||||||
|
|
||||||
|
operator fun get(column: Int, row: Int): Ingredient
|
||||||
|
|
||||||
|
operator fun get(column: Int, row: Int, flop: Boolean): Ingredient {
|
||||||
|
return if (flop)
|
||||||
|
get(width - column - 1, row)
|
||||||
|
else
|
||||||
|
get(column, row)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun iterator(): Iterator<Ingredient> {
|
||||||
|
return (0 until width).iterator().flatMap { x ->
|
||||||
|
(0 until height).iterator().map { y ->
|
||||||
|
get(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val ingredients: NonNullList<Ingredient> get() {
|
||||||
|
val result = NonNullList.createWithCapacity<Ingredient>(width * height)
|
||||||
|
|
||||||
|
for (x in 0 until width) {
|
||||||
|
for (y in 0 until height) {
|
||||||
|
result.add(get(x, y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(t: CraftingContainer, fromColumn: Int, fromRow: Int, flop: Boolean): Boolean {
|
||||||
|
if (t.width - fromColumn < width || t.height - fromRow < height)
|
||||||
|
return false
|
||||||
|
|
||||||
|
for (column in 0 until width)
|
||||||
|
for (row in 0 until height)
|
||||||
|
if (!this[column, row, flop].test(t[fromColumn + column, fromRow + row, flop]))
|
||||||
|
return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun preemptiveTest(t: CraftingContainer, fromColumn: Int, fromRow: Int, flop: Boolean): Boolean {
|
||||||
|
if (t.width - fromColumn < width || t.height - fromRow < height)
|
||||||
|
return false
|
||||||
|
|
||||||
|
for (column in 0 until width) {
|
||||||
|
for (row in 0 until height) {
|
||||||
|
val item = t[fromColumn + column, fromRow + row, flop]
|
||||||
|
val ingredient = this[column, row, flop]
|
||||||
|
|
||||||
|
if (!ingredient.test(item) && item.isNotEmpty) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun test(t: CraftingContainer): Boolean {
|
||||||
|
if (t.width < width || t.height < height)
|
||||||
|
return false
|
||||||
|
|
||||||
|
for (column in 0 .. t.width - width)
|
||||||
|
for (row in 0 .. t.height - height)
|
||||||
|
if (test(t, column, row, false) || test(t, column, row, true))
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun preemptiveTest(t: CraftingContainer): Boolean {
|
||||||
|
if (t.width < width || t.height < height)
|
||||||
|
return false
|
||||||
|
|
||||||
|
for (column in 0 .. t.width - width)
|
||||||
|
for (row in 0 .. t.height - height)
|
||||||
|
if (preemptiveTest(t, column, row, false) || preemptiveTest(t, column, row, true))
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : IIngredientMatrix {
|
||||||
|
override val width: Int
|
||||||
|
get() = 0
|
||||||
|
override val height: Int
|
||||||
|
get() = 0
|
||||||
|
|
||||||
|
override fun get(column: Int, row: Int): Ingredient {
|
||||||
|
return Ingredient.EMPTY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IngredientMatrix(override val width: Int, override val height: Int) : IIngredientMatrix {
|
||||||
|
private val data = Array(width * height) { Ingredient.EMPTY }
|
||||||
|
|
||||||
|
override fun get(column: Int, row: Int): Ingredient {
|
||||||
|
require(column in 0 until width) { "Column out of bounds: $column (matrix width: $width)" }
|
||||||
|
require(row in 0 until height) { "Row out of bounds: $row > (matrix height: $height)" }
|
||||||
|
return data[column + row * width]
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(column: Int, row: Int, value: Ingredient) {
|
||||||
|
require(column in 0 until width) { "Column out of bounds: $column (matrix width: $width)" }
|
||||||
|
require(row in 0 until height) { "Row out of bounds: $row > (matrix height: $height)" }
|
||||||
|
data[column + row * width] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun of(vararg values: Collection<Ingredient>): IngredientMatrix {
|
||||||
|
if (!values.iterator().map { it.size }.allEqual()) {
|
||||||
|
throw IllegalArgumentException("One or more rows have different number of columns than the rest")
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = IngredientMatrix(values.first().size, values.size)
|
||||||
|
|
||||||
|
for ((y, l) in values.withIndex()) {
|
||||||
|
for ((x, i) in l.withIndex()) {
|
||||||
|
result[x, y] = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,170 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.recipe
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
|
import net.minecraft.core.NonNullList
|
||||||
|
import net.minecraft.core.RegistryAccess
|
||||||
|
import net.minecraft.core.UUIDUtil
|
||||||
|
import net.minecraft.data.recipes.FinishedRecipe
|
||||||
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
import net.minecraft.world.inventory.CraftingContainer
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient
|
||||||
|
import net.minecraft.world.item.crafting.Recipe
|
||||||
|
import net.minecraft.world.item.crafting.RecipeSerializer
|
||||||
|
import net.minecraft.world.item.crafting.RecipeType
|
||||||
|
import net.minecraft.world.level.Level
|
||||||
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
|
import ru.dbotthepony.mc.otm.capability.matter.matter
|
||||||
|
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
||||||
|
import ru.dbotthepony.mc.otm.container.iterator
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.filterNotNull
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.forEach
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
|
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||||
|
import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer
|
||||||
|
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||||
|
import ru.dbotthepony.mc.otm.data.IngredientMatrixCodec
|
||||||
|
import ru.dbotthepony.mc.otm.data.minRange
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||||
|
import java.util.Optional
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlin.jvm.optionals.getOrElse
|
||||||
|
|
||||||
|
interface IMatterEntanglerRecipe : IMatteryRecipe<CraftingContainer> {
|
||||||
|
val matter: Decimal
|
||||||
|
val ticks: Double
|
||||||
|
val ingredients: IIngredientMatrix
|
||||||
|
val result: ItemStack
|
||||||
|
|
||||||
|
fun preemptivelyMatches(container: CraftingContainer, level: Level): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
open class MatterEntanglerRecipe(
|
||||||
|
private val id: ResourceLocation,
|
||||||
|
override val ingredients: IIngredientMatrix,
|
||||||
|
override val matter: Decimal,
|
||||||
|
override val ticks: Double,
|
||||||
|
override val result: ItemStack,
|
||||||
|
val uuidKey: String = "uuid",
|
||||||
|
val fixedUuid: Optional<UUID> = Optional.empty()
|
||||||
|
) : IMatterEntanglerRecipe {
|
||||||
|
override fun matches(container: CraftingContainer, level: Level): Boolean {
|
||||||
|
if (isIncomplete) return false
|
||||||
|
return ingredients.test(container)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun preemptivelyMatches(container: CraftingContainer, level: Level): Boolean {
|
||||||
|
if (isIncomplete) return false
|
||||||
|
return ingredients.preemptiveTest(container)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun assemble(container: CraftingContainer, registry: RegistryAccess): ItemStack {
|
||||||
|
return result.copy().also {
|
||||||
|
it.tagNotNull[uuidKey] = fixedUuid.getOrElse { UUID.randomUUID() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canCraftInDimensions(width: Int, height: Int): Boolean {
|
||||||
|
return width >= ingredients.width && height >= ingredients.height
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getResultItem(registry: RegistryAccess): ItemStack {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getId(): ResourceLocation {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSerializer(): RecipeSerializer<*> {
|
||||||
|
return SERIALIZER
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getType(): RecipeType<*> {
|
||||||
|
return MRecipes.MATTER_ENTANGLER
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIngredients(): NonNullList<Ingredient> {
|
||||||
|
return ingredients.ingredients
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isIncomplete(): Boolean {
|
||||||
|
return result.isEmpty || ingredients.isIncomplete
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isSpecial(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toFinished(): FinishedRecipe {
|
||||||
|
return SERIALIZER.toFinished(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun energetic() = Energy(this)
|
||||||
|
fun matter() = Matter(this)
|
||||||
|
|
||||||
|
open class Energy(val parent: MatterEntanglerRecipe) : IMatterEntanglerRecipe by parent {
|
||||||
|
override fun assemble(container: CraftingContainer, registry: RegistryAccess): ItemStack {
|
||||||
|
return parent.assemble(container, registry).also { result ->
|
||||||
|
container.iterator().map { it.matteryEnergy }.filterNotNull().forEach {
|
||||||
|
result.matteryEnergy!!.batteryLevel += it.batteryLevel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toFinished(): FinishedRecipe {
|
||||||
|
return ENERGY_SERIALIZER.toFinished(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSerializer(): RecipeSerializer<*> {
|
||||||
|
return ENERGY_SERIALIZER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Matter(val parent: MatterEntanglerRecipe) : IMatterEntanglerRecipe by parent {
|
||||||
|
override fun assemble(container: CraftingContainer, registry: RegistryAccess): ItemStack {
|
||||||
|
return parent.assemble(container, registry).also { result ->
|
||||||
|
container.iterator().map { it.matter }.filterNotNull().forEach {
|
||||||
|
result.matter!!.storedMatter += it.storedMatter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toFinished(): FinishedRecipe {
|
||||||
|
return MATTER_SERIALIZER.toFinished(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSerializer(): RecipeSerializer<*> {
|
||||||
|
return MATTER_SERIALIZER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val SERIALIZER = Codec2RecipeSerializer<MatterEntanglerRecipe>(
|
||||||
|
MatterEntanglerRecipe(
|
||||||
|
ResourceLocation(OverdriveThatMatters.MOD_ID, "null"),
|
||||||
|
IIngredientMatrix.Companion,
|
||||||
|
Decimal.ZERO,
|
||||||
|
0.0,
|
||||||
|
ItemStack.EMPTY,
|
||||||
|
)
|
||||||
|
) { context ->
|
||||||
|
RecordCodecBuilder.create {
|
||||||
|
it.group(
|
||||||
|
IngredientMatrixCodec.fieldOf("ingredients").forGetter(MatterEntanglerRecipe::ingredients),
|
||||||
|
DecimalCodec.minRange(Decimal.ZERO).fieldOf("matter").forGetter(MatterEntanglerRecipe::matter),
|
||||||
|
Codec.DOUBLE.minRange(0.0).fieldOf("ticks").forGetter(MatterEntanglerRecipe::ticks),
|
||||||
|
ItemStack.CODEC.fieldOf("result").forGetter(MatterEntanglerRecipe::result),
|
||||||
|
Codec.STRING.optionalFieldOf("uuidKey", "uuid").forGetter(MatterEntanglerRecipe::uuidKey),
|
||||||
|
UUIDUtil.STRING_CODEC.optionalFieldOf("fixedUuid").forGetter(MatterEntanglerRecipe::fixedUuid)
|
||||||
|
).apply(it) { a, b, c, d, e, f -> MatterEntanglerRecipe(context.id, a, b, c, d, e, f) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val ENERGY_SERIALIZER = SERIALIZER.xmap(::Energy, Energy::parent)
|
||||||
|
val MATTER_SERIALIZER = SERIALIZER.xmap(::Matter, Matter::parent)
|
||||||
|
}
|
||||||
|
}
|
@ -125,7 +125,7 @@ class PainterRecipe(
|
|||||||
Codec.list(DyeColor.CODEC).xmap({ it.associateWith { 1 } }, { ArrayList(it.keys) }) to Predicate { it.values.all { it == 1 } },
|
Codec.list(DyeColor.CODEC).xmap({ it.associateWith { 1 } }, { ArrayList(it.keys) }) to Predicate { it.values.all { it == 1 } },
|
||||||
Codec.unboundedMap(DyeColor.CODEC, Codec.INT.minRange(1)) to Predicate { true }
|
Codec.unboundedMap(DyeColor.CODEC, Codec.INT.minRange(1)) to Predicate { true }
|
||||||
).fieldOf("dyes").forGetter(PainterRecipe::dyes),
|
).fieldOf("dyes").forGetter(PainterRecipe::dyes),
|
||||||
).apply(it) { a, b, c -> PainterRecipe(context.invoke(), a, b, c) }
|
).apply(it) { a, b, c -> PainterRecipe(context.id, a, b, c) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ class PlatePressRecipe(
|
|||||||
Codec.INT.minRange(1).optionalFieldOf("count", 1).forGetter(PlatePressRecipe::count),
|
Codec.INT.minRange(1).optionalFieldOf("count", 1).forGetter(PlatePressRecipe::count),
|
||||||
Codec.INT.minRange(0).optionalFieldOf("workTime", 200).forGetter(PlatePressRecipe::workTime),
|
Codec.INT.minRange(0).optionalFieldOf("workTime", 200).forGetter(PlatePressRecipe::workTime),
|
||||||
FloatProvider.CODEC.optionalFieldOf("experience", ConstantFloat.ZERO).forGetter(PlatePressRecipe::experience)
|
FloatProvider.CODEC.optionalFieldOf("experience", ConstantFloat.ZERO).forGetter(PlatePressRecipe::experience)
|
||||||
).apply(it) { a, b, c, d, e -> PlatePressRecipe(context.invoke(), a, b, c, d, e) }
|
).apply(it) { a, b, c, d, e -> PlatePressRecipe(context.id, a, b, c, d, e) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,7 @@ object MBlockEntities {
|
|||||||
val INFINITE_WATER_SOURCE by register(MNames.INFINITE_WATER_SOURCE, ::InfiniteWaterSourceBlockEntity, MBlocks::INFINITE_WATER_SOURCE)
|
val INFINITE_WATER_SOURCE by register(MNames.INFINITE_WATER_SOURCE, ::InfiniteWaterSourceBlockEntity, MBlocks::INFINITE_WATER_SOURCE)
|
||||||
val DEV_CHEST by register(MNames.DEV_CHEST, ::DevChestBlockEntity, MBlocks::DEV_CHEST)
|
val DEV_CHEST by register(MNames.DEV_CHEST, ::DevChestBlockEntity, MBlocks::DEV_CHEST)
|
||||||
val PAINTER by register(MNames.PAINTER, ::PainterBlockEntity, MBlocks::PAINTER)
|
val PAINTER by register(MNames.PAINTER, ::PainterBlockEntity, MBlocks::PAINTER)
|
||||||
|
val MATTER_ENTANGLER by register(MNames.MATTER_ENTANGLER, ::MatterEntanglerBlockEntity, MBlocks::MATTER_ENTANGLER)
|
||||||
|
|
||||||
val POWERED_FURNACE: BlockEntityType<PoweredFurnaceBlockEntity> by registry.register(MNames.POWERED_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_FURNACE).build(null) }
|
val POWERED_FURNACE: BlockEntityType<PoweredFurnaceBlockEntity> by registry.register(MNames.POWERED_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_FURNACE).build(null) }
|
||||||
val POWERED_BLAST_FURNACE: BlockEntityType<PoweredFurnaceBlockEntity> by registry.register(MNames.POWERED_BLAST_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_BLAST_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_BLAST_FURNACE).build(null) }
|
val POWERED_BLAST_FURNACE: BlockEntityType<PoweredFurnaceBlockEntity> by registry.register(MNames.POWERED_BLAST_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_BLAST_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_BLAST_FURNACE).build(null) }
|
||||||
|
@ -64,6 +64,7 @@ import ru.dbotthepony.mc.otm.block.tech.AndroidChargerBlock
|
|||||||
import ru.dbotthepony.mc.otm.block.tech.CobblerBlock
|
import ru.dbotthepony.mc.otm.block.tech.CobblerBlock
|
||||||
import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock
|
import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock
|
||||||
import ru.dbotthepony.mc.otm.block.decorative.PainterBlock
|
import ru.dbotthepony.mc.otm.block.decorative.PainterBlock
|
||||||
|
import ru.dbotthepony.mc.otm.block.matter.MatterEntanglerBlock
|
||||||
import ru.dbotthepony.mc.otm.block.tech.PoweredFurnaceBlock
|
import ru.dbotthepony.mc.otm.block.tech.PoweredFurnaceBlock
|
||||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
@ -102,6 +103,7 @@ object MBlocks {
|
|||||||
val ESSENCE_STORAGE: EssenceStorageBlock by registry.register(MNames.ESSENCE_STORAGE) { EssenceStorageBlock() }
|
val ESSENCE_STORAGE: EssenceStorageBlock by registry.register(MNames.ESSENCE_STORAGE) { EssenceStorageBlock() }
|
||||||
val MATTER_RECONSTRUCTOR: MatterReconstructorBlock by registry.register(MNames.MATTER_RECONSTRUCTOR) { MatterReconstructorBlock() }
|
val MATTER_RECONSTRUCTOR: MatterReconstructorBlock by registry.register(MNames.MATTER_RECONSTRUCTOR) { MatterReconstructorBlock() }
|
||||||
val PAINTER: PainterBlock by registry.register(MNames.PAINTER) { PainterBlock() }
|
val PAINTER: PainterBlock by registry.register(MNames.PAINTER) { PainterBlock() }
|
||||||
|
val MATTER_ENTANGLER: MatterEntanglerBlock by registry.register(MNames.MATTER_ENTANGLER) { MatterEntanglerBlock() }
|
||||||
|
|
||||||
val STORAGE_BUS: Block by registry.register(MNames.STORAGE_BUS) { StorageBusBlock() }
|
val STORAGE_BUS: Block by registry.register(MNames.STORAGE_BUS) { StorageBusBlock() }
|
||||||
val STORAGE_IMPORTER: Block by registry.register(MNames.STORAGE_IMPORTER) { StorageImporterBlock() }
|
val STORAGE_IMPORTER: Block by registry.register(MNames.STORAGE_IMPORTER) { StorageImporterBlock() }
|
||||||
|
@ -152,10 +152,11 @@ object MItems {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val PAINTER: BlockItem by registry.register(MNames.PAINTER) { BlockItem(MBlocks.PAINTER, DEFAULT_PROPERTIES) }
|
val PAINTER: BlockItem by registry.register(MNames.PAINTER) { BlockItem(MBlocks.PAINTER, DEFAULT_PROPERTIES) }
|
||||||
|
val MATTER_ENTANGLER: BlockItem by registry.register(MNames.MATTER_ENTANGLER) { BlockItem(MBlocks.MATTER_ENTANGLER, DEFAULT_PROPERTIES) }
|
||||||
|
|
||||||
val MACHINES = SupplierList(
|
val MACHINES = SupplierList(
|
||||||
::ANDROID_STATION, ::ANDROID_CHARGER, ::BATTERY_BANK, ::MATTER_DECOMPOSER, ::MATTER_CAPACITOR_BANK, ::MATTER_CABLE, ::PATTERN_STORAGE,
|
::ANDROID_STATION, ::ANDROID_CHARGER, ::BATTERY_BANK, ::MATTER_DECOMPOSER, ::MATTER_CAPACITOR_BANK, ::MATTER_CABLE, ::PATTERN_STORAGE,
|
||||||
::MATTER_SCANNER, ::MATTER_PANEL, ::MATTER_REPLICATOR, ::MATTER_BOTTLER, ::ENERGY_COUNTER, ::CHEMICAL_GENERATOR,
|
::MATTER_SCANNER, ::MATTER_PANEL, ::MATTER_REPLICATOR, ::MATTER_BOTTLER, ::MATTER_ENTANGLER, ::ENERGY_COUNTER, ::CHEMICAL_GENERATOR,
|
||||||
::MATTER_RECYCLER, ::PLATE_PRESS, ::TWIN_PLATE_PRESS, ::POWERED_FURNACE, ::POWERED_BLAST_FURNACE,
|
::MATTER_RECYCLER, ::PLATE_PRESS, ::TWIN_PLATE_PRESS, ::POWERED_FURNACE, ::POWERED_BLAST_FURNACE,
|
||||||
::POWERED_SMOKER,
|
::POWERED_SMOKER,
|
||||||
::STORAGE_BUS, ::STORAGE_IMPORTER, ::STORAGE_EXPORTER, ::DRIVE_VIEWER,
|
::STORAGE_BUS, ::STORAGE_IMPORTER, ::STORAGE_EXPORTER, ::DRIVE_VIEWER,
|
||||||
|
@ -17,6 +17,7 @@ import ru.dbotthepony.mc.otm.client.screen.matter.MatterReconstructorScreen
|
|||||||
import ru.dbotthepony.mc.otm.client.screen.matter.MatterBottlerScreen
|
import ru.dbotthepony.mc.otm.client.screen.matter.MatterBottlerScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.matter.MatterCapacitorBankScreen
|
import ru.dbotthepony.mc.otm.client.screen.matter.MatterCapacitorBankScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.matter.MatterDecomposerScreen
|
import ru.dbotthepony.mc.otm.client.screen.matter.MatterDecomposerScreen
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.matter.MatterEntanglerScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.matter.MatterPanelScreen
|
import ru.dbotthepony.mc.otm.client.screen.matter.MatterPanelScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.matter.MatterRecyclerScreen
|
import ru.dbotthepony.mc.otm.client.screen.matter.MatterRecyclerScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.matter.MatterReplicatorScreen
|
import ru.dbotthepony.mc.otm.client.screen.matter.MatterReplicatorScreen
|
||||||
@ -36,7 +37,7 @@ import ru.dbotthepony.mc.otm.client.screen.tech.CobblerScreen
|
|||||||
import ru.dbotthepony.mc.otm.client.screen.tech.EnergyCounterScreen
|
import ru.dbotthepony.mc.otm.client.screen.tech.EnergyCounterScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.tech.EnergyServoScreen
|
import ru.dbotthepony.mc.otm.client.screen.tech.EnergyServoScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.tech.EssenceStorageScreen
|
import ru.dbotthepony.mc.otm.client.screen.tech.EssenceStorageScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.tech.PainterScreen
|
import ru.dbotthepony.mc.otm.client.screen.decorative.PainterScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.tech.PlatePressScreen
|
import ru.dbotthepony.mc.otm.client.screen.tech.PlatePressScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.tech.PoweredFurnaceScreen
|
import ru.dbotthepony.mc.otm.client.screen.tech.PoweredFurnaceScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.tech.TwinPlatePressScreen
|
import ru.dbotthepony.mc.otm.client.screen.tech.TwinPlatePressScreen
|
||||||
@ -48,6 +49,7 @@ import ru.dbotthepony.mc.otm.menu.matter.MatterReconstructorMenu
|
|||||||
import ru.dbotthepony.mc.otm.menu.matter.MatterBottlerMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterBottlerMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.matter.MatterCapacitorBankMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterCapacitorBankMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.matter.MatterDecomposerMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterDecomposerMenu
|
||||||
|
import ru.dbotthepony.mc.otm.menu.matter.MatterEntanglerMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.matter.MatterPanelMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterPanelMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.matter.MatterRecyclerMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterRecyclerMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.matter.MatterReplicatorMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterReplicatorMenu
|
||||||
@ -67,7 +69,7 @@ import ru.dbotthepony.mc.otm.menu.tech.CobblerMenu
|
|||||||
import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu
|
import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.EnergyServoMenu
|
import ru.dbotthepony.mc.otm.menu.tech.EnergyServoMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.EssenceStorageMenu
|
import ru.dbotthepony.mc.otm.menu.tech.EssenceStorageMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.PainterMenu
|
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
|
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
|
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.TwinPlatePressMenu
|
import ru.dbotthepony.mc.otm.menu.tech.TwinPlatePressMenu
|
||||||
@ -103,6 +105,7 @@ object MMenus {
|
|||||||
val ITEM_REPAIER: MenuType<MatterReconstructorMenu> by registry.register(MNames.MATTER_RECONSTRUCTOR) { MenuType(::MatterReconstructorMenu, FeatureFlags.VANILLA_SET) }
|
val ITEM_REPAIER: MenuType<MatterReconstructorMenu> by registry.register(MNames.MATTER_RECONSTRUCTOR) { MenuType(::MatterReconstructorMenu, FeatureFlags.VANILLA_SET) }
|
||||||
val FLUID_TANK: MenuType<FluidTankMenu> by registry.register(MNames.FLUID_TANK) { MenuType(::FluidTankMenu, FeatureFlags.VANILLA_SET) }
|
val FLUID_TANK: MenuType<FluidTankMenu> by registry.register(MNames.FLUID_TANK) { MenuType(::FluidTankMenu, FeatureFlags.VANILLA_SET) }
|
||||||
val PAINTER: MenuType<PainterMenu> by registry.register(MNames.PAINTER) { MenuType(::PainterMenu, FeatureFlags.VANILLA_SET) }
|
val PAINTER: MenuType<PainterMenu> by registry.register(MNames.PAINTER) { MenuType(::PainterMenu, FeatureFlags.VANILLA_SET) }
|
||||||
|
val MATTER_ENTANGLER: MenuType<MatterEntanglerMenu> by registry.register(MNames.MATTER_ENTANGLER) { MenuType(::MatterEntanglerMenu, FeatureFlags.VANILLA_SET) }
|
||||||
|
|
||||||
val STORAGE_BUS: MenuType<StorageBusMenu> by registry.register(MNames.STORAGE_BUS) { MenuType(::StorageBusMenu, FeatureFlags.VANILLA_SET) }
|
val STORAGE_BUS: MenuType<StorageBusMenu> by registry.register(MNames.STORAGE_BUS) { MenuType(::StorageBusMenu, FeatureFlags.VANILLA_SET) }
|
||||||
val STORAGE_IMPORTER_EXPORTER: MenuType<StorageImporterExporterMenu> by registry.register(MNames.STORAGE_IMPORTER) { MenuType(::StorageImporterExporterMenu, FeatureFlags.VANILLA_SET) }
|
val STORAGE_IMPORTER_EXPORTER: MenuType<StorageImporterExporterMenu> by registry.register(MNames.STORAGE_IMPORTER) { MenuType(::StorageImporterExporterMenu, FeatureFlags.VANILLA_SET) }
|
||||||
@ -146,6 +149,7 @@ object MMenus {
|
|||||||
MenuScreens.register(FLUID_TANK, ::FluidTankScreen)
|
MenuScreens.register(FLUID_TANK, ::FluidTankScreen)
|
||||||
MenuScreens.register(POWERED_FURNACE, ::PoweredFurnaceScreen)
|
MenuScreens.register(POWERED_FURNACE, ::PoweredFurnaceScreen)
|
||||||
MenuScreens.register(PAINTER, ::PainterScreen)
|
MenuScreens.register(PAINTER, ::PainterScreen)
|
||||||
|
MenuScreens.register(MATTER_ENTANGLER, ::MatterEntanglerScreen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ object MNames {
|
|||||||
const val INFINITE_WATER_SOURCE = "infinite_water_source"
|
const val INFINITE_WATER_SOURCE = "infinite_water_source"
|
||||||
const val DEV_CHEST = "dev_chest"
|
const val DEV_CHEST = "dev_chest"
|
||||||
const val PAINTER = "painter"
|
const val PAINTER = "painter"
|
||||||
|
const val MATTER_ENTANGLER = "matter_entangler"
|
||||||
|
|
||||||
// blocks
|
// blocks
|
||||||
const val ANDROID_STATION = "android_station"
|
const val ANDROID_STATION = "android_station"
|
||||||
|
@ -10,6 +10,8 @@ import net.minecraftforge.registries.RegistryObject
|
|||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe
|
import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe
|
||||||
import ru.dbotthepony.mc.otm.recipe.ExplosiveHammerPrimingRecipe
|
import ru.dbotthepony.mc.otm.recipe.ExplosiveHammerPrimingRecipe
|
||||||
|
import ru.dbotthepony.mc.otm.recipe.IMatterEntanglerRecipe
|
||||||
|
import ru.dbotthepony.mc.otm.recipe.MatterEntanglerRecipe
|
||||||
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
|
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
|
||||||
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
|
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
|
||||||
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
|
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
|
||||||
@ -38,6 +40,7 @@ object MRecipes {
|
|||||||
|
|
||||||
val PLATE_PRESS by register<PlatePressRecipe>("plate_press")
|
val PLATE_PRESS by register<PlatePressRecipe>("plate_press")
|
||||||
val PAINTER by register<PainterRecipe>("painter")
|
val PAINTER by register<PainterRecipe>("painter")
|
||||||
|
val MATTER_ENTANGLER by register<IMatterEntanglerRecipe>("matter_entangler")
|
||||||
|
|
||||||
init {
|
init {
|
||||||
serializers.register("plate_press") { PlatePressRecipe.SERIALIZER }
|
serializers.register("plate_press") { PlatePressRecipe.SERIALIZER }
|
||||||
@ -45,5 +48,8 @@ object MRecipes {
|
|||||||
serializers.register("upgrade") { UpgradeRecipe.Companion }
|
serializers.register("upgrade") { UpgradeRecipe.Companion }
|
||||||
serializers.register("hammer_priming") { ExplosiveHammerPrimingRecipe.Companion }
|
serializers.register("hammer_priming") { ExplosiveHammerPrimingRecipe.Companion }
|
||||||
serializers.register("painter") { PainterRecipe.SERIALIZER }
|
serializers.register("painter") { PainterRecipe.SERIALIZER }
|
||||||
|
serializers.register("matter_entangler") { MatterEntanglerRecipe.SERIALIZER }
|
||||||
|
serializers.register("matter_entangler_energetic") { MatterEntanglerRecipe.ENERGY_SERIALIZER }
|
||||||
|
serializers.register("matter_entangler_matter") { MatterEntanglerRecipe.MATTER_SERIALIZER }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user