From 1e2c505fbdb420d87b24bdf20b05b7ae7cd3fc32 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 22 Dec 2023 20:08:12 +0700 Subject: [PATCH] Unify experience storage in machines, Liquid XP --- .../datagen/recipes/MatterEntanglerRecipes.kt | 6 +- .../dbotthepony/mc/otm/block/MatteryBlock.kt | 19 ++- .../mc/otm/block/entity/ExperienceStorage.kt | 154 ++++++++++++++++++ .../mc/otm/block/entity/MatteryBlockEntity.kt | 18 +- .../matter/MatterEntanglerBlockEntity.kt | 14 +- .../entity/tech/EssenceStorageBlockEntity.kt | 62 ++++++- .../entity/tech/PlatePressBlockEntity.kt | 47 +----- .../entity/tech/PoweredFurnaceBlockEntity.kt | 43 +---- .../mc/otm/block/tech/PlatePressBlock.kt | 20 --- .../mc/otm/block/tech/PoweredFurnaceBlock.kt | 20 --- .../mc/otm/config/AbstractConfig.kt | 2 + .../mc/otm/config/BalanceValues.kt | 1 + .../mc/otm/config/MachinesConfig.kt | 13 +- .../mc/otm/menu/matter/MatterEntanglerMenu.kt | 2 +- .../mc/otm/menu/tech/PlatePressMenu.kt | 4 +- .../mc/otm/menu/tech/PoweredFurnaceMenu.kt | 2 +- .../mc/otm/menu/tech/TwinPlatePressMenu.kt | 4 +- .../mc/otm/recipe/MatterEntanglerRecipe.kt | 3 + .../ru/dbotthepony/mc/otm/registry/MBlocks.kt | 42 +++-- .../ru/dbotthepony/mc/otm/registry/MFluids.kt | 66 ++++++++ .../ru/dbotthepony/mc/otm/registry/MItems.kt | 1 + .../dbotthepony/mc/otm/registry/MRegistry.kt | 1 + 22 files changed, 388 insertions(+), 156 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ExperienceStorage.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/registry/MFluids.kt diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/MatterEntanglerRecipes.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/MatterEntanglerRecipes.kt index 9dbf0ec82..19378ec84 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/MatterEntanglerRecipes.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/MatterEntanglerRecipes.kt @@ -21,7 +21,8 @@ fun addMatterEntanglerRecipes(consumer: RecipeOutput) { ), Decimal(40), 400.0, - ItemStack(MItems.QUANTUM_CAPACITOR, 2) + ItemStack(MItems.QUANTUM_CAPACITOR, 2), + experience = 15f ).energetic().toFinished(modLocation("quantum_capacitor")) ) @@ -34,7 +35,8 @@ fun addMatterEntanglerRecipes(consumer: RecipeOutput) { ), Decimal(120), 600.0, - ItemStack(MItems.QUANTUM_BATTERY, 2) + ItemStack(MItems.QUANTUM_BATTERY, 2), + experience = 20f ).energetic().toFinished(modLocation("quantum_battery")) ) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt index e234863ad..ac83b83c9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt @@ -23,7 +23,6 @@ import net.minecraft.world.level.block.state.properties.Property import net.minecraft.world.level.material.MapColor import net.minecraft.world.phys.BlockHitResult import net.minecraft.world.phys.shapes.VoxelShape -import ru.dbotthepony.mc.otm.SERVER_IS_LIVE import ru.dbotthepony.mc.otm.block.entity.IRedstoneControlled import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity @@ -60,9 +59,20 @@ fun Block.getShapeForEachState(property: Property<*>, fn: (BlockState) -> VoxelS return getShapeForEachState(listOf(property), fn) } +fun interface INeighbourChangeListener { + fun neighborChanged( + state: BlockState, + level: Level, + pos: BlockPos, + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean + ) +} + abstract class MatteryBlock @JvmOverloads constructor( properties: Properties = DEFAULT_PROPERTIES -) : Block(properties) { +) : Block(properties), INeighbourChangeListener { override fun setPlacedBy( level: Level, blockPos: BlockPos, @@ -168,7 +178,6 @@ abstract class MatteryBlock @JvmOverloads constructor( return null } - @Suppress("OVERRIDE_DEPRECATION") override fun neighborChanged( state: BlockState, level: Level, @@ -188,8 +197,8 @@ abstract class MatteryBlock @JvmOverloads constructor( if (tile is IRedstoneControlled) tile.redstoneControl.redstoneSignal = level.getBestNeighborSignal(pos) - if (tile is MatteryBlockEntity && SERVER_IS_LIVE) - tile.neighborChanged(neighbour, neighbourPos, movedByPiston) + if (tile is MatteryBlockEntity) + tile.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ExperienceStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ExperienceStorage.kt new file mode 100644 index 000000000..310f47590 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ExperienceStorage.kt @@ -0,0 +1,154 @@ +package ru.dbotthepony.mc.otm.block.entity + +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.nbt.DoubleTag +import net.minecraft.server.level.ServerLevel +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.entity.ExperienceOrb +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.common.util.INBTSerializable +import net.minecraftforge.fluids.FluidStack +import net.minecraftforge.fluids.capability.IFluidHandler +import ru.dbotthepony.mc.otm.block.INeighbourChangeListener +import ru.dbotthepony.mc.otm.block.entity.tech.EssenceStorageBlockEntity +import ru.dbotthepony.mc.otm.core.math.plus +import ru.dbotthepony.mc.otm.registry.MFluids +import java.util.function.DoubleSupplier + +class ExperienceStorage(val maxExperience: DoubleSupplier = DoubleSupplier { Double.POSITIVE_INFINITY }) : IFluidHandler, INBTSerializable, INeighbourChangeListener { + constructor(max: Double) : this({ max }) + + var experience = 0.0 + private set(value) { + require(value >= 0.0) { "Negative experience: $value" } + field = value + } + + fun popExperience(player: ServerPlayer) { + val whole = experience.toInt() + + if (whole > 0) { + experience -= whole + ExperienceOrb.award(player.level() as ServerLevel, player.position(), whole) + } + } + + fun storeExperience(experience: Double): Boolean { + check(experience >= 0.0) { "Invalid experience amount to store: $experience" } + val max = maxExperience.asDouble + val overflow = this.experience + experience > max + this.experience = if (overflow) max else this.experience + experience + return !overflow + } + + fun storeExperience(experience: Float): Boolean { + return storeExperience(experience.toDouble()) + } + + fun storeExperience(experience: Double, pointOfReference: BlockEntity): Boolean { + check(experience >= 0.0) { "Invalid experience amount to store: $experience" } + this.experience += experience + + for (dir in Direction.entries) { + val tile = pointOfReference.level?.getBlockEntity(pointOfReference.blockPos + dir) + + if (tile is EssenceStorageBlockEntity) { + tile.experienceStored += this.experience.toLong() + this.experience %= 1.0 + break + } + } + + val max = maxExperience.asDouble + val overflow = this.experience > max + if (overflow) this.experience = max + return !overflow + } + + fun storeExperience(experience: Float, pointOfReference: BlockEntity): Boolean { + return storeExperience(experience.toDouble(), pointOfReference) + } + + fun tryTransferExperience(pointOfReference: BlockEntity) { + if (experience >= 1.0) { + for (dir in Direction.entries) { + val tile = pointOfReference.level?.getBlockEntity(pointOfReference.blockPos + dir) + + if (tile is EssenceStorageBlockEntity) { + tile.experienceStored += experience.toLong() + experience %= 1.0 + break + } + } + } + } + + override fun neighborChanged(state: BlockState, level: Level, pos: BlockPos, neighbour: Block, neighbourPos: BlockPos, movedByPiston: Boolean) { + if (experience >= 1.0) { + val tile = level.getBlockEntity(neighbourPos) + + if (tile is EssenceStorageBlockEntity) { + tile.experienceStored += experience.toLong() + experience %= 1.0 + } + } + } + + override fun serializeNBT(): DoubleTag { + return DoubleTag.valueOf(experience) + } + + override fun deserializeNBT(nbt: DoubleTag?) { + experience = (nbt?.asDouble ?: 0.0).coerceAtLeast(0.0) + } + + override fun getTanks(): Int { + return 1 + } + + override fun getFluidInTank(tank: Int): FluidStack { + if (tank != 0) + return FluidStack.EMPTY + + return FluidStack(MFluids.LIQUID_XP, (experience * XP_TO_LIQUID_RATIO).toInt()) + } + + override fun getTankCapacity(tank: Int): Int { + return if (tank == 0) (maxExperience.asDouble * XP_TO_LIQUID_RATIO).toInt() else 0 + } + + override fun isFluidValid(tank: Int, stack: FluidStack): Boolean { + return tank == 0 && stack.fluid.fluidType == MFluids.LIQUID_XP_TYPE + } + + override fun fill(resource: FluidStack, action: IFluidHandler.FluidAction): Int { + return 0 + } + + override fun drain(resource: FluidStack, action: IFluidHandler.FluidAction): FluidStack { + if (resource.fluid.fluidType != MFluids.LIQUID_XP_TYPE) + return FluidStack.EMPTY + + return drain(resource.amount, action) + } + + override fun drain(maxDrain: Int, action: IFluidHandler.FluidAction): FluidStack { + val actualDrain = maxDrain.coerceAtMost((experience * XP_TO_LIQUID_RATIO).toInt()).let { it / XP_TO_LIQUID_RATIO * XP_TO_LIQUID_RATIO } + + if (actualDrain <= 0) + return FluidStack.EMPTY + + if (action.execute()) + experience -= actualDrain / XP_TO_LIQUID_RATIO + + return FluidStack(MFluids.LIQUID_XP, actualDrain) + } + + companion object { + const val XP_TO_LIQUID_RATIO = 10 + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt index c63c5b0cf..27718dd70 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt @@ -12,7 +12,6 @@ import net.minecraft.core.Direction import net.minecraft.core.SectionPos import net.minecraft.core.Vec3i import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerPlayer import net.minecraft.world.Container @@ -28,7 +27,6 @@ import net.minecraft.world.level.chunk.LevelChunk import net.minecraft.world.phys.Vec3 import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.ForgeCapabilities -import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.energy.IEnergyStorage import net.minecraftforge.event.TickEvent.LevelTickEvent @@ -37,6 +35,7 @@ import net.minecraftforge.event.level.ChunkWatchEvent import net.minecraftforge.event.level.LevelEvent import net.minecraftforge.event.server.ServerStoppingEvent import ru.dbotthepony.mc.otm.SERVER_IS_LIVE +import ru.dbotthepony.mc.otm.block.INeighbourChangeListener import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage @@ -65,12 +64,11 @@ import java.util.function.Supplier import java.util.stream.Stream import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty -import kotlin.reflect.KProperty0 /** * Absolute barebone (lol) block entity class in Overdrive that Matters, providing bare minimum (lulmao, minecraft engine) functionality */ -abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(p_155228_, p_155229_, p_155230_) { +abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(p_155228_, p_155229_, p_155230_), INeighbourChangeListener { private var isSynchronizing = false /** @@ -83,12 +81,21 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } private val _droppableContainers = ObjectArraySet() + private val _neighbourChangeListeners = ObjectArraySet() val droppableContainers: Set = Collections.unmodifiableSet(_droppableContainers) + val neighbourChangeListeners: Set = Collections.unmodifiableSet(_neighbourChangeListeners) protected fun addDroppableContainer(container: Container) { _droppableContainers.add(container) } + protected fun addNeighbourListener(listener: INeighbourChangeListener) { + if (listener === this) + throw IllegalArgumentException("are you drunk") + + _neighbourChangeListeners.add(listener) + } + open fun beforeDroppingItems(oldBlockState: BlockState, level: Level, blockPos: BlockPos, newBlockState: BlockState, movedByPiston: Boolean) {} open fun beforeDestroyedByPlayer(level: Level, blockPos: BlockPos, blockState: BlockState, player: Player) {} @@ -441,7 +448,8 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } } - fun neighborChanged(neighbour: Block, neighbourPos: BlockPos, movedByPiston: Boolean) { + override fun neighborChanged(state: BlockState, level: Level, pos: BlockPos, neighbour: Block, neighbourPos: BlockPos, movedByPiston: Boolean) { + _neighbourChangeListeners.forEach { it.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) } val dir = vec2Dir[vecKey(neighbourPos - blockPos)] ?: return _sides[blockRotation.dir2Side(dir)]!!.updateTracked() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterEntanglerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterEntanglerBlockEntity.kt index bcd29a5e4..40c2212b5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterEntanglerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterEntanglerBlockEntity.kt @@ -9,6 +9,8 @@ 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 net.minecraftforge.common.capabilities.ForgeCapabilities +import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage import ru.dbotthepony.mc.otm.block.entity.ItemJob import ru.dbotthepony.mc.otm.block.entity.JobContainer import ru.dbotthepony.mc.otm.block.entity.JobStatus @@ -35,7 +37,7 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MRecipes class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryWorkerBlockEntity(MBlockEntities.MATTER_ENTANGLER, blockPos, blockState, Job.CODEC) { - class Job(itemStack: ItemStack, val matter: Decimal, ticks: Double) : ItemJob(itemStack, ticks, MachinesConfig.MATTER_ENTANGLER.energyConsumption) { + class Job(itemStack: ItemStack, val matter: Decimal, ticks: Double, experience: Float) : ItemJob(itemStack, ticks, MachinesConfig.MATTER_ENTANGLER.energyConsumption, experience = experience) { val matterPerTick = matter / ticks companion object { @@ -44,6 +46,7 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M 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), + Codec.FLOAT.minRange(0f).optionalFieldOf("experience", 0f).forGetter(Job::experience) ).apply(it, ::Job) } } @@ -54,6 +57,7 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M val matter = ProfiledMatterStorage(MatterStorageImpl(::markDirtyFast, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MATTER_ENTANGLER::matterCapacity))) val node = MatterNode() + val experience = ExperienceStorage(MachinesConfig.MATTER_ENTANGLER::maxExperienceStored).also(::addNeighbourListener) val energyConfig = ConfigurableEnergy(energy) val inputs = object : MatteryCraftingContainer(::itemContainerUpdated, 3, 3) { @@ -88,11 +92,14 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M ) init { + exposeGlobally(ForgeCapabilities.FLUID_HANDLER, experience) + savetables.stateful(::energy, ENERGY_KEY) savetables.stateful(::matter, MATTER_STORAGE_KEY) savetables.stateful(::upgrades) savetables.stateful(::inputs) savetables.stateful(::output) + savetables.stateful(::experience) exposeGlobally(MatteryCapability.MATTER_NODE, node) exposeGlobally(MatteryCapability.MATTER, matter) @@ -128,6 +135,8 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M override fun onJobFinish(status: JobStatus, id: Int) { if (!output.fullyAddItem(status.job.itemStack)) { status.noItem() + } else { + experience.storeExperience(status.job.experience, this) } } @@ -150,7 +159,8 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M Job( result, recipe.value.matter, - recipe.value.ticks * MachinesConfig.MATTER_ENTANGLER.workTimeMultiplier + recipe.value.ticks * MachinesConfig.MATTER_ENTANGLER.workTimeMultiplier, + recipe.value.experience ) ) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EssenceStorageBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EssenceStorageBlockEntity.kt index a591f74d8..5acf1f262 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EssenceStorageBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EssenceStorageBlockEntity.kt @@ -7,6 +7,9 @@ import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack import net.minecraft.world.item.enchantment.Enchantments import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.fluids.FluidStack +import net.minecraftforge.fluids.capability.IFluidHandler +import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage.Companion.XP_TO_LIQUID_RATIO import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.capability.item.CombinedItemHandler import ru.dbotthepony.mc.otm.container.HandlerFilter @@ -14,8 +17,9 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.item.EssenceCapsuleItem import ru.dbotthepony.mc.otm.menu.tech.EssenceStorageMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities +import ru.dbotthepony.mc.otm.registry.MFluids -class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.ESSENCE_STORAGE, blockPos, blockState) { +class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.ESSENCE_STORAGE, blockPos, blockState), IFluidHandler { var experienceStored = 0L set(value) { require(value >= 0L) { "Negative experience: $value" } @@ -57,6 +61,62 @@ class EssenceStorageBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma ) ) + override fun getTanks(): Int { + return 1 + } + + override fun getFluidInTank(tank: Int): FluidStack { + if (tank != 0) + return FluidStack.EMPTY + + if (experienceStored >= 2_000_000_000L) + return FluidStack(MFluids.LIQUID_XP, 2_000_000_000) + + return FluidStack(MFluids.LIQUID_XP, experienceStored.toInt()) + } + + override fun getTankCapacity(tank: Int): Int { + if (tank != 0) return 0 + return Int.MAX_VALUE + } + + override fun isFluidValid(tank: Int, stack: FluidStack): Boolean { + return tank == 0 && stack.fluid.fluidType == MFluids.LIQUID_XP_TYPE + } + + override fun fill(resource: FluidStack, action: IFluidHandler.FluidAction): Int { + if (resource.fluid.fluidType != MFluids.LIQUID_XP_TYPE || resource.amount <= 0) + return 0 + + val actualFill = resource.amount / XP_TO_LIQUID_RATIO * XP_TO_LIQUID_RATIO + + if (action.execute()) + experienceStored += actualFill / XP_TO_LIQUID_RATIO + + return actualFill + } + + override fun drain(resource: FluidStack, action: IFluidHandler.FluidAction): FluidStack { + if (resource.fluid.fluidType != MFluids.LIQUID_XP_TYPE) + return FluidStack.EMPTY + + return drain(resource.amount, action) + } + + override fun drain(maxDrain: Int, action: IFluidHandler.FluidAction): FluidStack { + val stored = experienceStored * XP_TO_LIQUID_RATIO + val actualStored = if (stored >= Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt() + val actualDrain = maxDrain.coerceAtMost(actualStored).let { it / XP_TO_LIQUID_RATIO * XP_TO_LIQUID_RATIO } + + if (actualDrain <= 0) + return FluidStack.EMPTY + + if (action.execute()) + experienceStored -= actualDrain / XP_TO_LIQUID_RATIO + + return FluidStack(MFluids.LIQUID_XP, actualDrain) + } + override fun tick() { super.tick() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt index 081471a0b..5cfc76190 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PlatePressBlockEntity.kt @@ -2,14 +2,12 @@ package ru.dbotthepony.mc.otm.block.entity.tech import it.unimi.dsi.fastutil.ints.IntArrayList import net.minecraft.core.BlockPos -import net.minecraft.core.Direction -import net.minecraft.server.level.ServerLevel -import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.entity.ExperienceOrb import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.common.capabilities.ForgeCapabilities +import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage import ru.dbotthepony.mc.otm.block.entity.JobContainer import ru.dbotthepony.mc.otm.block.entity.JobStatus import ru.dbotthepony.mc.otm.block.entity.ItemJob @@ -39,39 +37,7 @@ class PlatePressBlockEntity( val inputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer) val outputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer) - var experience = 0.0 - private set - - fun popExperience(player: ServerPlayer) { - val whole = experience.toInt() - - if (whole > 0) { - experience -= whole - ExperienceOrb.award(player.level() as ServerLevel, player.position(), whole) - } - } - - fun tryStoreExperience(essenceStorage: EssenceStorageBlockEntity?) { - if (experience <= 0.0) return - - if (essenceStorage != null) { - essenceStorage.experienceStored += experience.toLong() - experience = 0.0 - - return - } - - for (dir in Direction.entries) { - val tile = level?.getBlockEntity(blockPos.relative(dir)) ?: continue - - if (tile is EssenceStorageBlockEntity) { - tryStoreExperience(tile) - - break - } - } - } - + val experience = ExperienceStorage(MachinesConfig.PLATE_PRESS::maxExperienceStored).also(::addNeighbourListener) val energyConfig = ConfigurableEnergy(energy) val itemConfig = ConfigurableItemHandler( input = inputContainer.handler(HandlerFilter.OnlyIn), @@ -79,10 +45,12 @@ class PlatePressBlockEntity( ) init { + exposeGlobally(ForgeCapabilities.FLUID_HANDLER, experience) + savetables.stateful(::energy, ENERGY_KEY) savetables.stateful(::inputContainer) savetables.stateful(::outputContainer) - savetables.double(::experience) + savetables.stateful(::experience) savetables.stateful(::upgrades) } @@ -100,8 +68,7 @@ class PlatePressBlockEntity( if (!outputContainer.fullyAddItem(status.job.itemStack, slots = IntArrayList.of(id)) && !outputContainer.fullyAddItem(status.job.itemStack)) return status.noItem() - experience = (experience + status.experience).coerceAtMost(100.0) - tryStoreExperience(null) + experience.storeExperience(status.experience, this) } override fun computeNextJob(id: Int): JobContainer { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PoweredFurnaceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PoweredFurnaceBlockEntity.kt index 2226d0829..b1c6c4abe 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PoweredFurnaceBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/PoweredFurnaceBlockEntity.kt @@ -12,6 +12,8 @@ import net.minecraft.world.item.crafting.AbstractCookingRecipe import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.common.capabilities.ForgeCapabilities +import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage import ru.dbotthepony.mc.otm.block.entity.JobContainer import ru.dbotthepony.mc.otm.block.entity.JobStatus import ru.dbotthepony.mc.otm.block.entity.ItemJob @@ -53,6 +55,7 @@ class PoweredFurnaceBlockEntity( outputs.forEach { addDroppableContainer(it) } } + val experience = ExperienceStorage(config::maxExperienceStored).also(::addNeighbourListener) val energyConfig = ConfigurableEnergy(energy) val itemConfig = ConfigurableItemHandler( input = CombinedItemHandler(inputs.map { it.handler(HandlerFilter.OnlyIn) }), @@ -60,44 +63,13 @@ class PoweredFurnaceBlockEntity( battery = batteryItemHandler ) - var experience = 0.0 - private set - - fun popExperience(player: ServerPlayer) { - val whole = experience.toInt() - - if (whole > 0) { - experience -= whole - ExperienceOrb.award(player.level() as ServerLevel, player.position(), whole) - } - } - - fun tryStoreExperience(essenceStorage: EssenceStorageBlockEntity?) { - if (experience <= 0.0) return - - if (essenceStorage != null) { - essenceStorage.experienceStored += experience.toLong() - experience = 0.0 - - return - } - - for (dir in Direction.entries) { - val tile = level?.getBlockEntity(blockPos.relative(dir)) ?: continue - - if (tile is EssenceStorageBlockEntity) { - tryStoreExperience(tile) - - break - } - } - } - init { + exposeGlobally(ForgeCapabilities.FLUID_HANDLER, experience) + savetables.stateful(::upgrades) savetables.stateful(::energy) - savetables.double(::experience) + savetables.stateful(::experience) savetables.stateful(inputs, "input") savetables.stateful(outputs, "output") @@ -124,8 +96,7 @@ class PoweredFurnaceBlockEntity( override fun onJobFinish(status: JobStatus, id: Int) { if (outputs[id].fullyAddItem(status.job.itemStack)) { - experience += status.experience - tryStoreExperience(null) + experience.storeExperience(status.experience, this) } else { status.noItem() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/PlatePressBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/PlatePressBlock.kt index 83428bc32..740271336 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/PlatePressBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/PlatePressBlock.kt @@ -66,24 +66,4 @@ class PlatePressBlock(properties: Properties = DEFAULT_PROPERTIES, val isTwin: B ): VoxelShape { return shapes[state]!! } - - @Suppress("OVERRIDE_DEPRECATION") - override fun neighborChanged( - state: BlockState, - level: Level, - pos: BlockPos, - neighbour: Block, - neighbourPos: BlockPos, - movedByPiston: Boolean - ) { - super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) - - val tile = level.getBlockEntity(pos) ?: return - val neighbourTile = level.getBlockEntity(neighbourPos) ?: return - - if (tile.isRemoved || neighbourTile.isRemoved) return - if (tile is PlatePressBlockEntity && neighbourTile is EssenceStorageBlockEntity) { - tile.tryStoreExperience(neighbourTile) - } - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/PoweredFurnaceBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/PoweredFurnaceBlock.kt index 556a230ae..1f1be51a0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/PoweredFurnaceBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/PoweredFurnaceBlock.kt @@ -61,24 +61,4 @@ class PoweredFurnaceBlock( return BlockEntityTicker { _, _, _, tile -> if (tile is PoweredFurnaceBlockEntity) tile.tick() } } - - @Suppress("OVERRIDE_DEPRECATION") - override fun neighborChanged( - state: BlockState, - level: Level, - pos: BlockPos, - neighbour: Block, - neighbourPos: BlockPos, - movedByPiston: Boolean - ) { - super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) - - val tile = level.getBlockEntity(pos) ?: return - val neighbourTile = level.getBlockEntity(neighbourPos) ?: return - - if (tile.isRemoved || neighbourTile.isRemoved) return - if (tile is PoweredFurnaceBlockEntity && neighbourTile is EssenceStorageBlockEntity) { - tile.tryStoreExperience(neighbourTile) - } - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/AbstractConfig.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/AbstractConfig.kt index 7cf624353..24b64492f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/AbstractConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/AbstractConfig.kt @@ -51,6 +51,7 @@ abstract class AbstractConfig(private val configName: String, private val type: workTimeMultiplier: Double? = 1.0, energyConsumption: Decimal?, matterCapacity: Decimal? = null, + maxExperience: Double? = null, configurator: ForgeConfigSpec.Builder.() -> Unit = {} ): WorkerBalanceValues { builder.push(name) @@ -61,6 +62,7 @@ abstract class AbstractConfig(private val configName: String, private val type: override val energyConsumption: Decimal by (if (energyConsumption == null) GetterSetter.box(Decimal.ZERO) else builder.defineDecimal("ENERGY_CONSUMPTION", energyConsumption, minimum = Decimal.ONE)) override val matterCapacity: Decimal by (if (matterCapacity == null) GetterSetter.box(Decimal.ZERO) else builder.defineDecimal("MATTER_CAPACITY", matterCapacity, minimum = Decimal.ONE)) override val workTimeMultiplier: Double by (if (workTimeMultiplier == null) GetterSetter.box(1.0) else builder.defineInRange("WORK_TIME_MULTIPLIER", workTimeMultiplier, 0.0)) + override val maxExperienceStored: Double by (if (maxExperience == null) GetterSetter.box(Double.POSITIVE_INFINITY) else builder.defineInRange("MAX_EXPERIENCE_STORED", maxExperience, 0.0)) } configurator.invoke(builder) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/BalanceValues.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/BalanceValues.kt index 1a0a59e3e..ea3cbac7d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/BalanceValues.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/BalanceValues.kt @@ -11,6 +11,7 @@ interface WorkerBalanceValues : EnergyBalanceValues { val workTimeMultiplier: Double val energyConsumption: Decimal val matterCapacity: Decimal + val maxExperienceStored: Double } interface VerboseEnergyBalanceValues { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt index d0bc04a44..3fc705cbd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt @@ -10,7 +10,8 @@ object MachinesConfig : AbstractConfig("machines") { MNames.PLATE_PRESS, energyStorage = Decimal(40_000), energyThroughput = Decimal(200), - energyConsumption = Decimal(15) + energyConsumption = Decimal(15), + maxExperience = 200.0, ) val MATTER_ENTANGLER = workerValues( @@ -19,6 +20,7 @@ object MachinesConfig : AbstractConfig("machines") { energyThroughput = Decimal(400), energyConsumption = Decimal(120), matterCapacity = Decimal(60), + maxExperience = 400.0, ) val MATTER_DECOMPOSER = workerValues( @@ -169,7 +171,8 @@ object MachinesConfig : AbstractConfig("machines") { energyStorage = Decimal(40_000), energyThroughput = Decimal(200), energyConsumption = Decimal(20), - workTimeMultiplier = 0.75 + workTimeMultiplier = 0.75, + maxExperience = 200.0 ) val POWERED_BLAST_FURNACE = workerValues( @@ -177,7 +180,8 @@ object MachinesConfig : AbstractConfig("machines") { energyStorage = Decimal(40_000), energyThroughput = Decimal(200), energyConsumption = Decimal(20), - workTimeMultiplier = 0.75 + workTimeMultiplier = 0.75, + maxExperience = 200.0 ) val POWERED_SMOKER = workerValues( @@ -185,7 +189,8 @@ object MachinesConfig : AbstractConfig("machines") { energyStorage = Decimal(40_000), energyThroughput = Decimal(200), energyConsumption = Decimal(10), - workTimeMultiplier = 0.75 + workTimeMultiplier = 0.75, + maxExperience = 200.0 ) object Upgrades { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterEntanglerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterEntanglerMenu.kt index 2c452c85f..7b3884ee5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterEntanglerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterEntanglerMenu.kt @@ -57,7 +57,7 @@ class MatterEntanglerMenu( } } - val outputs = makeSlots(tile?.output ?: SimpleContainer(1), ::OutputSlot) + val outputs = makeSlots(tile?.output ?: SimpleContainer(1)) { a, b -> OutputSlot(a, b) { tile?.experience?.popExperience(player as ServerPlayer) } } val upgrades = makeUpgradeSlots(3, tile?.upgrades) private val entangling: Container = if (tile == null) object : SimpleContainer(2) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt index 2d3bc8512..35269557b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PlatePressMenu.kt @@ -13,13 +13,13 @@ import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus -class PlatePressMenu @JvmOverloads constructor( +class PlatePressMenu( containerID: Int, inventory: Inventory, tile: PlatePressBlockEntity? = null ) : MatteryPoweredMenu(MMenus.PLATE_PRESS, containerID, inventory, tile) { val inputSlot = MatterySlot(tile?.inputContainer ?: SimpleContainer(1), 0) - val outputSlot = OutputSlot(tile?.outputContainer ?: SimpleContainer(1), 0) { tile?.popExperience(player as ServerPlayer) } + val outputSlot = OutputSlot(tile?.outputContainer ?: SimpleContainer(1), 0) { tile?.experience?.popExperience(player as ServerPlayer) } val progressGauge = ProgressGaugeWidget(this, tile) val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PoweredFurnaceMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PoweredFurnaceMenu.kt index a39411c6c..e547464ab 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PoweredFurnaceMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PoweredFurnaceMenu.kt @@ -23,7 +23,7 @@ class PoweredFurnaceMenu( tile: PoweredFurnaceBlockEntity? = null ) : MatteryPoweredMenu(type, containerID, inventory, tile) { val inputSlots = makeSlots(tile?.inputs, 2, ::MatterySlot) - val outputSlots = makeSlots(tile?.outputs, 2) { c, s -> OutputSlot(c, s) { tile?.popExperience(player as ServerPlayer) } } + val outputSlots = makeSlots(tile?.outputs, 2) { c, s -> OutputSlot(c, s) { tile?.experience?.popExperience(player as ServerPlayer) } } val progressGauge = immutableList(2) { ProgressGaugeWidget(this, tile?.jobEventLoops?.get(it)) } val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig, allowPush = true) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/TwinPlatePressMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/TwinPlatePressMenu.kt index 8533dd864..244b9bc13 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/TwinPlatePressMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/TwinPlatePressMenu.kt @@ -15,13 +15,13 @@ import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.registry.MMenus -class TwinPlatePressMenu @JvmOverloads constructor( +class TwinPlatePressMenu( containerID: Int, inventory: Inventory, tile: PlatePressBlockEntity? = null ) : MatteryPoweredMenu(MMenus.TWIN_PLATE_PRESS, containerID, inventory, tile) { val inputSlots = makeSlots(tile?.inputContainer ?: SimpleContainer(2), ::MatterySlot) - val outputSlots = makeSlots(tile?.outputContainer ?: SimpleContainer(2)) { a, b -> OutputSlot(a, b) { tile?.popExperience(player as ServerPlayer) } } + val outputSlots = makeSlots(tile?.outputContainer ?: SimpleContainer(2)) { a, b -> OutputSlot(a, b) { tile?.experience?.popExperience(player as ServerPlayer) } } val progressGauge0 = ProgressGaugeWidget(this, tile?.jobEventLoops?.get(0)) val progressGauge1 = ProgressGaugeWidget(this, tile?.jobEventLoops?.get(1)) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/MatterEntanglerRecipe.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/MatterEntanglerRecipe.kt index b9daa6882..a8dc68f98 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/MatterEntanglerRecipe.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/recipe/MatterEntanglerRecipe.kt @@ -36,6 +36,7 @@ interface IMatterEntanglerRecipe : IMatteryRecipe { val ticks: Double val ingredients: IIngredientMatrix val result: ItemStack + val experience: Float fun preemptivelyMatches(container: CraftingContainer, level: Level): Boolean } @@ -45,6 +46,7 @@ open class MatterEntanglerRecipe( override val matter: Decimal, override val ticks: Double, override val result: ItemStack, + override val experience: Float = 0f, val uuidKey: String = "uuid", val fixedUuid: Optional = Optional.empty() ) : IMatterEntanglerRecipe { @@ -147,6 +149,7 @@ open class MatterEntanglerRecipe( 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.FLOAT.minRange(0f).optionalFieldOf("experience", 0f).forGetter(MatterEntanglerRecipe::experience), Codec.STRING.optionalFieldOf("uuidKey", "uuid").forGetter(MatterEntanglerRecipe::uuidKey), UUIDUtil.STRING_CODEC.optionalFieldOf("fixedUuid").forGetter(MatterEntanglerRecipe::fixedUuid) ).apply(it, ::MatterEntanglerRecipe) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt index 98380836b..8e64746f7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt @@ -12,7 +12,17 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.item.TooltipFlag import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.level.BlockGetter -import net.minecraft.world.level.block.* +import net.minecraft.world.level.block.AnvilBlock +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.DoorBlock +import net.minecraft.world.level.block.DropExperienceBlock +import net.minecraft.world.level.block.IronBarsBlock +import net.minecraft.world.level.block.LiquidBlock +import net.minecraft.world.level.block.SlabBlock +import net.minecraft.world.level.block.SoundType +import net.minecraft.world.level.block.StairBlock +import net.minecraft.world.level.block.TrapDoorBlock +import net.minecraft.world.level.block.WallBlock import net.minecraft.world.level.block.state.BlockBehaviour import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.properties.BlockSetType @@ -23,32 +33,25 @@ import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.ForgeRegistries import ru.dbotthepony.mc.otm.OverdriveThatMatters -import ru.dbotthepony.mc.otm.block.tech.AndroidStationBlock -import ru.dbotthepony.mc.otm.block.tech.BatteryBankBlock import ru.dbotthepony.mc.otm.block.BlackHoleBlock import ru.dbotthepony.mc.otm.block.BlockExplosionDebugger -import ru.dbotthepony.mc.otm.block.tech.BlockGravitationStabilizer -import ru.dbotthepony.mc.otm.block.tech.BlockGravitationStabilizerLens import ru.dbotthepony.mc.otm.block.BlockSphereDebugger -import ru.dbotthepony.mc.otm.block.tech.ChemicalGeneratorBlock -import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock -import ru.dbotthepony.mc.otm.block.tech.EnergyServoBlock -import ru.dbotthepony.mc.otm.block.decorative.LaboratoryLamp -import ru.dbotthepony.mc.otm.block.decorative.LaboratoryLampLight import ru.dbotthepony.mc.otm.block.MatterCableBlock -import ru.dbotthepony.mc.otm.block.tech.PhantomAttractorBlock -import ru.dbotthepony.mc.otm.block.tech.PlatePressBlock import ru.dbotthepony.mc.otm.block.StorageCableBlock import ru.dbotthepony.mc.otm.block.decorative.DevChestBlock import ru.dbotthepony.mc.otm.block.decorative.EngineBlock import ru.dbotthepony.mc.otm.block.decorative.FluidTankBlock import ru.dbotthepony.mc.otm.block.decorative.HoloSignBlock import ru.dbotthepony.mc.otm.block.decorative.InfiniteWaterSourceBlock -import ru.dbotthepony.mc.otm.block.matter.MatterReconstructorBlock +import ru.dbotthepony.mc.otm.block.decorative.LaboratoryLamp +import ru.dbotthepony.mc.otm.block.decorative.LaboratoryLampLight +import ru.dbotthepony.mc.otm.block.decorative.PainterBlock import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock import ru.dbotthepony.mc.otm.block.matter.MatterCapacitorBankBlock import ru.dbotthepony.mc.otm.block.matter.MatterDecomposerBlock +import ru.dbotthepony.mc.otm.block.matter.MatterEntanglerBlock import ru.dbotthepony.mc.otm.block.matter.MatterPanelBlock +import ru.dbotthepony.mc.otm.block.matter.MatterReconstructorBlock import ru.dbotthepony.mc.otm.block.matter.MatterRecyclerBlock import ru.dbotthepony.mc.otm.block.matter.MatterReplicatorBlock import ru.dbotthepony.mc.otm.block.matter.MatterScannerBlock @@ -61,10 +64,17 @@ import ru.dbotthepony.mc.otm.block.storage.StorageExporterBlock import ru.dbotthepony.mc.otm.block.storage.StorageImporterBlock import ru.dbotthepony.mc.otm.block.storage.StoragePowerSupplierBlock import ru.dbotthepony.mc.otm.block.tech.AndroidChargerBlock +import ru.dbotthepony.mc.otm.block.tech.AndroidStationBlock +import ru.dbotthepony.mc.otm.block.tech.BatteryBankBlock +import ru.dbotthepony.mc.otm.block.tech.BlockGravitationStabilizer +import ru.dbotthepony.mc.otm.block.tech.BlockGravitationStabilizerLens +import ru.dbotthepony.mc.otm.block.tech.ChemicalGeneratorBlock import ru.dbotthepony.mc.otm.block.tech.CobblerBlock +import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock +import ru.dbotthepony.mc.otm.block.tech.EnergyServoBlock import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock -import ru.dbotthepony.mc.otm.block.decorative.PainterBlock -import ru.dbotthepony.mc.otm.block.matter.MatterEntanglerBlock +import ru.dbotthepony.mc.otm.block.tech.PhantomAttractorBlock +import ru.dbotthepony.mc.otm.block.tech.PlatePressBlock import ru.dbotthepony.mc.otm.block.tech.PoweredFurnaceBlock import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.core.TranslatableComponent @@ -126,6 +136,8 @@ object MBlocks { val FLUID_TANK: FluidTankBlock by registry.register(MNames.FLUID_TANK) { FluidTankBlock() } val DEV_CHEST: DevChestBlock by registry.register(MNames.DEV_CHEST) { DevChestBlock() } + val LIQUID_XP: LiquidBlock by registry.register("liquid_xp") { LiquidBlock(MFluids::LIQUID_XP, BlockBehaviour.Properties.of().mapColor(MapColor.EMERALD).replaceable().noCollission().strength(100.0f).pushReaction(PushReaction.DESTROY).noLootTable().liquid().sound(SoundType.EMPTY)) } + val TRITANIUM_ORE: Block by registry.register(MNames.TRITANIUM_ORE) { DropExperienceBlock( BlockBehaviour.Properties.of() .mapColor(MapColor.STONE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MFluids.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MFluids.kt new file mode 100644 index 000000000..d42923a95 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MFluids.kt @@ -0,0 +1,66 @@ +package ru.dbotthepony.mc.otm.registry + +import net.minecraft.resources.ResourceLocation +import net.minecraft.sounds.SoundEvents +import net.minecraft.world.item.Rarity +import net.minecraft.world.level.material.Fluid +import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions +import net.minecraftforge.common.SoundActions +import net.minecraftforge.eventbus.api.IEventBus +import net.minecraftforge.fluids.FluidType +import net.minecraftforge.fluids.ForgeFlowingFluid +import net.minecraftforge.registries.DeferredRegister +import net.minecraftforge.registries.ForgeRegistries +import ru.dbotthepony.mc.otm.OverdriveThatMatters +import java.util.function.Consumer + +object MFluids { + private val types: DeferredRegister = DeferredRegister.create(ForgeRegistries.FLUID_TYPES, OverdriveThatMatters.MOD_ID) + private val fluids: DeferredRegister = DeferredRegister.create(ForgeRegistries.FLUIDS, OverdriveThatMatters.MOD_ID) + + internal fun register(bus: IEventBus) { + types.register(bus) + fluids.register(bus) + } + + private fun makeXpProps(): ForgeFlowingFluid.Properties { + return ForgeFlowingFluid.Properties(::LIQUID_XP_TYPE, ::LIQUID_XP, ::LIQUID_XP_FLOWING).bucket(MItems::LIQUID_XP_BUCKET).block(MBlocks::LIQUID_XP) + } + + private val xpProps = makeXpProps() + + val LIQUID_XP_TYPE: FluidType by types.register("liquid_xp") { + object : FluidType( + Properties.create() + .rarity(Rarity.UNCOMMON) + .canDrown(true) + .canExtinguish(false) + .canSwim(true) + .canHydrate(false) + .canPushEntity(true) + .canConvertToSource(false) + .fallDistanceModifier(0f) + .sound(SoundActions.BUCKET_FILL, SoundEvents.BUCKET_FILL) + .sound(SoundActions.BUCKET_EMPTY, SoundEvents.BUCKET_EMPTY) + .sound(SoundActions.FLUID_VAPORIZE, SoundEvents.FIRE_EXTINGUISH) + .descriptionId("block.overdrive_that_matters.liquid_xp") + ) { + override fun initializeClient(consumer: Consumer) { + val path = ResourceLocation(OverdriveThatMatters.MOD_ID, "block/ph_kitty") + + consumer.accept(object : IClientFluidTypeExtensions { + override fun getStillTexture(): ResourceLocation { + return path + } + + override fun getFlowingTexture(): ResourceLocation { + return path + } + }) + } + } + } + + val LIQUID_XP: ForgeFlowingFluid.Source by fluids.register("liquid_xp") { ForgeFlowingFluid.Source(xpProps) } + val LIQUID_XP_FLOWING: ForgeFlowingFluid.Flowing by fluids.register("liquid_xp_flowing") { ForgeFlowingFluid.Flowing(xpProps) } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt index c914e5f4a..d9cffe638 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt @@ -290,6 +290,7 @@ object MItems { val FLUID_CAPSULE: FluidCapsuleItem by registry.register("fluid_capsule") { FluidCapsuleItem(ItemsConfig::FLUID_CAPSULE_CAPACITY) } val FLUID_TANK: FluidTankItem by registry.register(MNames.FLUID_TANK) { FluidTankItem(MBlocks.FLUID_TANK, Item.Properties().stacksTo(1), ItemsConfig::FLUID_TANK_CAPACITY) } + val LIQUID_XP_BUCKET: BucketItem by registry.register("liquid_xp_bucket") { BucketItem(MFluids::LIQUID_XP, Item.Properties().stacksTo(1).rarity(Rarity.UNCOMMON)) } val TRITANIUM_COMPONENT: ForgeTier = ForgeTier( Tiers.IRON.level, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt index c54781d2f..0555c6d59 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt @@ -275,6 +275,7 @@ object MRegistry { IMatterFunction.register(bus) MBlocks.register(bus) + MFluids.register(bus) MBlockEntities.register(bus) MEntityTypes.register(bus) MMenus.register(bus)