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 3b3405b2a..aad27f026 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt @@ -63,6 +63,7 @@ abstract class MatteryBlock @JvmOverloads constructor( return super.use(blockState, level, blockPos, ply, hand, blockHitResult) } + @Suppress("OVERRIDE_DEPRECATION") override fun neighborChanged( state: BlockState, level: Level, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/StorageInterfaces.kt index f79cc290c..a4ee0cc68 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/StorageInterfaces.kt @@ -10,6 +10,7 @@ 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.addPreWorldTickerOnce +import ru.dbotthepony.mc.otm.block.entity.StorageExporterBlockEntity import ru.dbotthepony.mc.otm.block.entity.StorageImporterBlockEntity import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.unaryMinus @@ -57,3 +58,47 @@ class StorageImporterBlock : RotatableMatteryBlock(), EntityBlock { } } } + +class StorageExporterBlock : RotatableMatteryBlock(), EntityBlock { + override val hasFreeRotation: Boolean get() = true + + override fun newBlockEntity(p_153215_: BlockPos, p_153216_: BlockState): BlockEntity { + return StorageExporterBlockEntity(p_153215_, p_153216_) + } + + override fun getTicker( + p_153212_: Level, + p_153213_: BlockState, + p_153214_: BlockEntityType + ): BlockEntityTicker? { + if (p_153212_.isClientSide || p_153214_ !== MBlockEntities.STORAGE_EXPORTER) + return null + + return BlockEntityTicker { _, _, _, tile -> if (tile is StorageExporterBlockEntity) tile.tick() } + } + + override fun getStateForPlacement(context: BlockPlaceContext): BlockState? { + return super.getStateForPlacement(context)?.setValue(FACING_FULL, -context.clickedFace) + } + + override fun neighborChanged( + state: BlockState, + level: Level, + pos: BlockPos, + sender: Block, + sender_pos: BlockPos, + flag: Boolean + ) { + super.neighborChanged(state, level, pos, sender, sender_pos, flag) + + if (!level.isClientSide) { + val tile = level.getBlockEntity(pos) + + if (tile is StorageExporterBlockEntity) { + addPreWorldTickerOnce(level) { + tile.checkSurroundings() + } + } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/StorageInterfaces.kt index 843f45d8f..6b5602095 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/StorageInterfaces.kt @@ -17,17 +17,16 @@ import net.minecraftforge.items.CapabilityItemHandler import net.minecraftforge.items.IItemHandler import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock -import ru.dbotthepony.mc.otm.capability.BlockEnergyStorageImpl -import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage -import ru.dbotthepony.mc.otm.capability.extractStepInner +import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.plus +import ru.dbotthepony.mc.otm.core.toImpreciseFraction import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph import ru.dbotthepony.mc.otm.orThrow import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MNames +import ru.dbotthepony.mc.otm.storage.IStorageTuple import ru.dbotthepony.mc.otm.storage.ITEM_STORAGE import ru.dbotthepony.mc.otm.storage.ItemStackWrapper import ru.dbotthepony.mc.otm.unaryMinus @@ -92,7 +91,6 @@ abstract class AbstractStorageImportExport( } companion object { - const val MAX_MOVE_PER_OPERATION = 4 val MAX_POWER = ImpreciseFraction(10_000) } } @@ -108,7 +106,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : A private var lastSlot = 0 private var nextTick = INTERVAL - private val enoughEnergy get() = energy.batteryLevel >= OverdriveThatMatters.INSTANCE.ITEM_STORAGE().energyPerOperation + private val enoughEnergy get() = energy.batteryLevel >= ITEM_STORAGE.energyPerOperation override val targetCapability: Capability get() = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY @@ -153,7 +151,85 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : A } companion object { + const val MAX_MOVE_PER_OPERATION = 4 private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_IMPORTER}") private const val INTERVAL = 5 } } + +class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : AbstractStorageImportExport(MBlockEntities.STORAGE_EXPORTER, blockPos, blockState) { + override val defaultDisplayName: Component + get() = MACHINE_NAME + + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? { + return null + } + + private var lastSlot = 0 + private var nextTick = INTERVAL + private val enoughEnergy get() = energy.batteryLevel >= ITEM_STORAGE.energyPerOperation + + override val targetCapability: Capability + get() = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY + + private val exportStacks: List> + get() = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE)?.getStacks() ?: emptyList() + + fun tick() { + batteryChargeLoop() + cell.tickEnergyDemanding() + + nextTick-- + + if (nextTick <= 0 && target.isPresent && enoughEnergy) { + val graph = cell.storageGraph ?: return + val items = graph.getVirtualComponent(ITEM_STORAGE) + + val resolved = target.orThrow() + + if (lastSlot >= resolved.slots) { + lastSlot = 0 + } + + var hit = false + + for (stack in exportStacks) { + val exportAmountA = items.extractStack(stack.id, stack.stack.count.toInt().coerceAtMost(MAX_MOVE_PER_OPERATION).toImpreciseFraction(), true).count.toInt() + + if (exportAmountA == 0) { + continue + } + + var exportAmount = energy.extractStepInner(ITEM_STORAGE.energyPerOperation, exportAmountA, true) + + if (exportAmount == 0) { + break + } + + val leftover = resolved.insertItem(lastSlot, stack.stack.stack.also { it.count = exportAmount }, true) + + if (leftover.count != exportAmount) { + hit = true + exportAmount = items.extractStack(stack.id, ImpreciseFraction(exportAmount - leftover.count), false).count.toInt() + resolved.insertItem(lastSlot, stack.stack.stack.also { it.count = exportAmount }, false) + energy.extractStepInner(ITEM_STORAGE.energyPerOperation, exportAmount, false) + break + } + } + + if (!hit) { + lastSlot++ + } + } + + if (nextTick <= 0) { + nextTick = INTERVAL + } + } + + companion object { + const val MAX_MOVE_PER_OPERATION = 4 + private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_EXPORTER}") + private const val INTERVAL = 5 + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt index 4533ec489..533389318 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt @@ -209,3 +209,11 @@ fun Number.toImpreciseFraction(): ImpreciseFraction { else -> throw ClassCastException("Can not turn $this into ImpreciseFraction") } } + +fun Float.toImpreciseFraction() = ImpreciseFraction(this) +fun Double.toImpreciseFraction() = ImpreciseFraction(this) +fun Int.toImpreciseFraction() = ImpreciseFraction(this) +fun Byte.toImpreciseFraction() = ImpreciseFraction(this) +fun Short.toImpreciseFraction() = ImpreciseFraction(this) +fun Long.toImpreciseFraction() = ImpreciseFraction(this) +fun ImpreciseFraction.toImpreciseFraction() = this diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt index a17a55460..b7a53a5df 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt @@ -42,6 +42,7 @@ object MBlockEntities { val STORAGE_BUS: BlockEntityType<*> by registry.register(MNames.STORAGE_BUS) { BlockEntityType.Builder.of(::StorageBusBlockEntity, MBlocks.STORAGE_BUS).build(null) } val STORAGE_IMPORTER: BlockEntityType<*> by registry.register(MNames.STORAGE_IMPORTER) { BlockEntityType.Builder.of(::StorageImporterBlockEntity, MBlocks.STORAGE_IMPORTER).build(null) } + val STORAGE_EXPORTER: BlockEntityType<*> by registry.register(MNames.STORAGE_EXPORTER) { BlockEntityType.Builder.of(::StorageExporterBlockEntity, MBlocks.STORAGE_EXPORTER).build(null) } val STORAGE_POWER_SUPPLIER: BlockEntityType<*> by registry.register(MNames.STORAGE_POWER_SUPPLIER) { BlockEntityType.Builder.of(::StoragePowerSupplierBlockEntity, MBlocks.STORAGE_POWER_SUPPLIER).build(null) } val DEBUG_EXPLOSION_SMALL: BlockEntityType<*> by registry.register(MNames.DEBUG_EXPLOSION_SMALL) { BlockEntityType.Builder.of(::BlockEntityExplosionDebugger, MBlocks.DEBUG_EXPLOSION_SMALL).build(null) } 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 e9a7424ec..b004ed796 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt @@ -54,6 +54,7 @@ object MBlocks { val STORAGE_BUS: Block by registry.register(MNames.STORAGE_BUS) { StorageBusBlock() } val STORAGE_IMPORTER: Block by registry.register(MNames.STORAGE_IMPORTER) { StorageImporterBlock() } + val STORAGE_EXPORTER: Block by registry.register(MNames.STORAGE_EXPORTER) { StorageExporterBlock() } val DRIVE_VIEWER: Block by registry.register(MNames.DRIVE_VIEWER) { DriveViewerBlock() } val DRIVE_RACK: Block by registry.register(MNames.DRIVE_RACK) { DriveRackBlock() } 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 a385c526f..1b1ddbcf5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt @@ -48,6 +48,7 @@ object MItems { val STORAGE_BUS: Item by registry.register(MNames.STORAGE_BUS) { BlockItem(MBlocks.STORAGE_BUS, DEFAULT_PROPERTIES) } val STORAGE_IMPORTER: Item by registry.register(MNames.STORAGE_IMPORTER) { BlockItem(MBlocks.STORAGE_IMPORTER, DEFAULT_PROPERTIES) } + val STORAGE_EXPORTER: Item by registry.register(MNames.STORAGE_EXPORTER) { BlockItem(MBlocks.STORAGE_EXPORTER, DEFAULT_PROPERTIES) } val DRIVE_VIEWER: Item by registry.register(MNames.DRIVE_VIEWER) { BlockItem(MBlocks.DRIVE_VIEWER, DEFAULT_PROPERTIES) } val DRIVE_RACK: Item by registry.register(MNames.DRIVE_RACK) { BlockItem(MBlocks.DRIVE_RACK, DEFAULT_PROPERTIES) } val ITEM_MONITOR: Item by registry.register(MNames.ITEM_MONITOR) { BlockItem(MBlocks.ITEM_MONITOR, DEFAULT_PROPERTIES) } diff --git a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json index 3df748e1f..8a8da36ff 100644 --- a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json +++ b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json @@ -239,6 +239,7 @@ "block.overdrive_that_matters.storage_power_supplier": "Storage Power Supplier", "block.overdrive_that_matters.storage_bus": "Storage Bus", "block.overdrive_that_matters.storage_importer": "Storage Importer", + "block.overdrive_that_matters.storage_exporter": "Storage Exporter", "item.overdrive_that_matters.pill_android": "Android Pill", "item.overdrive_that_matters.pill_humane": "Humane Pill",