diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockModels.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockModels.kt index 0919c9a83..a6b3eb704 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockModels.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockModels.kt @@ -10,12 +10,20 @@ fun addBlockModels(provider: MatteryBlockModelProvider) { resourceCubeAll(MBlocks.DEEPSLATE_TRITANIUM_ORE) resourceCubeAll(MBlocks.TRITANIUM_INGOT_BLOCK) + cable("crude_energy_cable", "block/power_cable_0") + cable("regular_energy_cable", "block/power_cable_1") + cable("advanced_energy_cable", "block/power_cable_2") + cable("superconductor_energy_cable", "block/power_cable_3") + cable("storage_cable", "block/storage_cable") + colored(MBlocks.COBBLESTONE_GENERATOR, listOf("0", "particle")) - colored(MBlocks.ESSENCE_STORAGE, listOf("0", "particle")) colored(MBlocks.ITEM_MONITOR, listOf("0", "particle")) colored(MBlocks.MATTER_RECONSTRUCTOR, listOf("0", "particle")) colored(MBlocks.ENERGY_SERVO, listOf("0", "particle")) + colored("essence_storage", "_empty", listOf("0")) + colored("essence_storage", "_filled", listOf("0")) + colored("matter_capacitor_bank", listOf("1", "particle"), "mattercapacitorbank_frame") colored("battery_bank", listOf("0", "particle"), "batterybank_frame") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockStates.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockStates.kt index e9de264e2..68846f7b9 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockStates.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockStates.kt @@ -8,6 +8,7 @@ import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock import ru.dbotthepony.mc.otm.block.tech.AndroidChargerBlock +import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom import ru.dbotthepony.mc.otm.core.math.xRotationBlockstateNorth import ru.dbotthepony.mc.otm.core.math.xRotationBlockstateSouth @@ -112,7 +113,22 @@ fun addBlockStates(provider: MatteryBlockStateProvider) { provider.block(MBlocks.MATTER_RECONSTRUCTOR.values) provider.block(MBlocks.ENERGY_SERVO.values) provider.block(MBlocks.COBBLESTONE_GENERATOR.values) - provider.block(MBlocks.ESSENCE_STORAGE.values) + + provider.exec { + for (block in MBlocks.ESSENCE_STORAGE.values) { + provider.getVariantBuilder(block).forAllStates { + return@forAllStates arrayOf( + ConfiguredModel.builder() + .modelFile(provider.models().getExistingFile( + modLocation("${block.registryName!!.path}_${if (it.getValue( + EssenceStorageBlock.FILLED)) "filled" else "empty"}") + )) + .rotationY(it.getValue(BlockRotationFreedom.HORIZONTAL.property).front.yRotationBlockstateNorth()) + .buildLast() + ) + } + } + } provider.exec { for (crate in MRegistry.CARGO_CRATES.allBlocks.values) { @@ -191,5 +207,49 @@ fun addBlockStates(provider: MatteryBlockStateProvider) { part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core"))) .addModel().end() } + + with(provider.getMultipartBuilder(MBlocks.MATTER_CABLE)) { + for (dir in BlockRotationFreedom.DIRECTIONAL.possibleValues) { + part().modelFile(provider.models().getExistingFile(modLocation("matter_cable_connection"))) + .rotationX(dir.front.xRotationBlockstateSouth()) + .rotationY(dir.front.yRotationBlockstateSouth()) + .addModel() + .condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true) + .end() + } + + part().modelFile(provider.models().getExistingFile(modLocation("matter_cable_core"))) + .addModel().end() + } + + with(provider.getMultipartBuilder(MBlocks.STORAGE_CABLE)) { + for (dir in BlockRotationFreedom.DIRECTIONAL.possibleValues) { + part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection"))) + .rotationX(dir.front.xRotationBlockstateSouth()) + .rotationY(dir.front.yRotationBlockstateSouth()) + .addModel() + .condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true) + .end() + } + + part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core"))) + .addModel().end() + } + + for (block in MBlocks.ENERGY_CABLES) { + with(provider.getMultipartBuilder(block.value)) { + for (dir in BlockRotationFreedom.DIRECTIONAL.possibleValues) { + part().modelFile(provider.models().getExistingFile(modLocation("${block.value.registryName!!.path}_connection"))) + .rotationX(dir.front.xRotationBlockstateSouth()) + .rotationY(dir.front.yRotationBlockstateSouth()) + .addModel() + .condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true) + .end() + } + + part().modelFile(provider.models().getExistingFile(modLocation("${block.value.registryName!!.path}_core"))) + .addModel().end() + } + } } } diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt index 943705f7f..c2359c3a7 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt @@ -172,10 +172,8 @@ fun addItemModels(provider: MatteryItemModelProvider) { provider.coloredWithBaseBlock(MItems.MATTER_SCANNER, "matter_scanner", "_idle") provider.coloredWithBaseBlock(MItems.MATTER_REPLICATOR, "matter_replicator", "_idle") provider.coloredWithBaseBlock(MItems.DRIVE_VIEWER, "drive_viewer", "_idle") - provider.block(MItems.MATTER_CABLE, "matter_cable_core") provider.coloredWithBaseBlock(MItems.MATTER_DECOMPOSER, "matter_decomposer", "_idle") provider.coloredWithBaseBlock(MItems.ENERGY_SERVO, "energy_servo") - provider.coloredWithBaseBlock(MItems.ESSENCE_STORAGE, "essence_storage") provider.coloredWithBaseBlock(MItems.MATTER_RECONSTRUCTOR, "matter_reconstructor") provider.coloredWithBaseBlock(MItems.POWERED_BLAST_FURNACE, "powered_blast_furnace", "_idle") @@ -188,10 +186,23 @@ fun addItemModels(provider: MatteryItemModelProvider) { provider.coloredWithBaseBlock(MItems.MATTER_RECYCLER, "matter_recycler", "_idle") provider.coloredWithBaseBlock(MItems.COBBLESTONE_GENERATOR, "cobblestone_generator") + provider.exec { + provider.withExistingParent("essence_storage", modLocation("block/essence_storage_empty")) + .override() + .predicate(modLocation("is_filled"), 1f) + .model(provider.withExistingParent("essence_storage_filled", modLocation("block/essence_storage_filled"))) + .end() + } + for (dye in DyeColor.entries) { provider.exec { provider.withExistingParent("android_charger_${dye.name.lowercase()}", modLocation("item/android_charger")).texture("0", modLocation("block/android_charger/${dye.name.lowercase()}")) provider.withExistingParent("matter_panel_${dye.name.lowercase()}", modLocation("item/matter_panel")).texture("texture", modLocation("block/matter_panel/${dye.name.lowercase()}")) + provider.withExistingParent("essence_storage_${dye.name.lowercase()}", modLocation("block/essence_storage_${dye.name.lowercase()}_empty")) + .override() + .predicate(modLocation("is_filled"), 1f) + .model(provider.withExistingParent("essence_storage_${dye.name.lowercase()}_filled", modLocation("block/essence_storage_${dye.name.lowercase()}_filled"))) + .end() } } diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt index c86a0526d..2140cb5ed 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt @@ -608,8 +608,8 @@ private fun items(provider: MatteryLanguageProvider) { add(MItems.ESSENCE_CAPSULE, "Essence Capsule") add(MItems.ESSENCE_DRIVE, "Essence Memory Holotape") add(MItems.ESSENCE_SERVO, "Essence Servo") - add(MItems.ESSENCE_SERVO, "desc", "Allows to 'pump' essence involving fleshy humanoids") - add(MItems.ESSENCE_SERVO, "desc2", "Can be used standalone, or as tool inside Essence Servo") + add(MItems.ESSENCE_SERVO, "desc", "Allows to absorb nearby experience orbs directly into essence storage") + add(MItems.ESSENCE_SERVO, "desc2", "Can be used as a tool to pump essence manually") add(MItems.NUTRIENT_PASTE, "Nutrient Paste") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt index 579fac976..b975b1b16 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt @@ -612,8 +612,8 @@ private fun items(provider: MatteryLanguageProvider) { add(MItems.ESSENCE_CAPSULE, "Капсула эссенции") add(MItems.ESSENCE_DRIVE, "Голодиск воспоминаний андроида") add(MItems.ESSENCE_SERVO, "Помпа эссенции") - add(MItems.ESSENCE_SERVO, "desc", "Позволяет 'перекачивать' эссенцию гуманоидов из плоти") - add(MItems.ESSENCE_SERVO, "desc2", "Может быть использовано напрямую, или как инструмент внутри хранилища эссенции") + add(MItems.ESSENCE_SERVO, "desc", "Позволяет всасывать близлежащие сферы опыта напрямую в хранилище эссенции") + add(MItems.ESSENCE_SERVO, "desc2", "Может использоваться как инструмент для ручной перекачки эссенции") add(MItems.NUTRIENT_PASTE, "Питательная паста") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelProvider.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelProvider.kt index 6384439fb..63ec5c1f1 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelProvider.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelProvider.kt @@ -142,4 +142,17 @@ class MatteryBlockModelProvider(event: GatherDataEvent) : BlockModelProvider(eve colored(modelName, state, textureKeys.associateWith { modelName }) } } + + fun cable(modelName: String, textureName: String) { + exec { + withExistingParent("block/${modelName}_core", modLocation("block/base_cable_core")) + .texture("0", textureName) + + withExistingParent("block/${modelName}_connection", modLocation("block/base_cable_connection")) + .texture("0", textureName) + + withExistingParent("item/${modelName}", modLocation("item/base_cable")) + .texture("0", textureName) + } + } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/BlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/BlockEntityMixin.java new file mode 100644 index 000000000..860683f11 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/BlockEntityMixin.java @@ -0,0 +1,24 @@ +package ru.dbotthepony.mc.otm.mixin; + +import net.minecraft.world.level.block.entity.BlockEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import ru.dbotthepony.mc.otm.core.MultiblockKt; + +// because i know +// someone +// somewhere +// will try to break the system +// either on purpose or accidentally because of other mod +@Mixin(BlockEntity.class) +public abstract class BlockEntityMixin { + @Inject( + at = @At("TAIL"), + method = "setRemoved()V" + ) + public void setRemovedListener(CallbackInfo ci) { + MultiblockKt.onBlockEntityInvalidated((BlockEntity) (Object) this); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/SplashManagerMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/SplashManagerMixin.java new file mode 100644 index 000000000..99e17c70e --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/SplashManagerMixin.java @@ -0,0 +1,40 @@ +package ru.dbotthepony.mc.otm.mixin; + +import net.minecraft.client.resources.SplashManager; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.profiling.ProfilerFiller; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(SplashManager.class) +public abstract class SplashManagerMixin { + @Shadow + public List splashes; + + @Inject( + at = @At("TAIL"), + method = "apply(Ljava/util/List;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V" + ) + public void otmSplashes(List splashes, ResourceManager p_118879_, ProfilerFiller p_118880_, CallbackInfo ci) { + this.splashes.add("42 is the answer!"); + this.splashes.add("Now with matter!"); + this.splashes.add("Now with four dimensions!"); + this.splashes.add("Now with more ways to slice Creepers!"); + this.splashes.add("Batteries not included!"); + this.splashes.add("As it was 13 nanoseconds ago!"); + this.splashes.add("Smart AI is smart enough to fail Turing test!"); + this.splashes.add("Neural computing!"); + this.splashes.add("Swimming through quantum field!"); + this.splashes.add("For biological and digital alike!"); + this.splashes.add("Digital is the next form of Biological!"); + + this.splashes.add("Also try Starbound!"); + this.splashes.add("Also try No Man's Sky!"); + this.splashes.add("Also try Factorio!"); + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/MultiblockTestBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/MultiblockTestBlock.kt new file mode 100644 index 000000000..20997844e --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/MultiblockTestBlock.kt @@ -0,0 +1,23 @@ +package ru.dbotthepony.mc.otm.block + +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.entity.MultiblockTestBlockEntity + +class MultiblockTestBlock : MatteryBlock(), EntityBlock { + override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity { + return MultiblockTestBlockEntity(blockPos, blockState) + } + + override fun getTicker(level: Level, blockState: BlockState, blockEntityType: BlockEntityType): BlockEntityTicker? { + if (level.isClientSide) + return null + + return BlockEntityTicker { _, _, _, tile -> if (tile is MultiblockTestBlockEntity) tile.tick() } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MultiblockTestBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MultiblockTestBlockEntity.kt new file mode 100644 index 000000000..a5bdd18f7 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MultiblockTestBlockEntity.kt @@ -0,0 +1,75 @@ +package ru.dbotthepony.mc.otm.block.entity + +import net.minecraft.core.BlockPos +import net.minecraft.tags.BlockTags +import net.minecraft.world.level.block.Blocks +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.entity.FurnaceBlockEntity +import net.minecraft.world.level.block.entity.HopperBlockEntity +import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.mc.otm.core.multiblockConfiguration +import ru.dbotthepony.mc.otm.core.multiblockEntity +import ru.dbotthepony.mc.otm.registry.MBlockEntities +import ru.dbotthepony.mc.otm.registry.MBlocks + +class MultiblockTestBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.MULTIBLOCK_TEST, blockPos, blockState) { + val config = CONFIG.create(blockPos) + + override fun tick() { + super.tick() + + if (config.update(level!!)) { + println("It matches!") + println("hopper block entities: ${config.blockEntities(HOPPERS)}") + } + } + + companion object { + private val HOPPERS = multiblockEntity() + private val FURNACES = multiblockEntity() + + val CONFIG = multiblockConfiguration { + block(MBlocks.MULTIBLOCK_TEST) + + and { + top { + or { + block(Blocks.HOPPER) + block(Blocks.CHEST) + block(BlockTags.PLANKS) + } + + tag(HOPPERS) + } + + left(Blocks.FURNACE) { + tag(FURNACES) + + top { + or { + block(Blocks.HOPPER) + block(Blocks.CHEST) + block(BlockTags.PLANKS) + } + + tag(HOPPERS) + } + } + + right(Blocks.FURNACE) { + tag(FURNACES) + + top { + or { + block(Blocks.HOPPER) + block(Blocks.CHEST) + block(BlockTags.PLANKS) + } + + tag(HOPPERS) + } + } + } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/PainterBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/PainterBlockEntity.kt index 7a65e1450..5b594f8de 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/PainterBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/PainterBlockEntity.kt @@ -66,8 +66,8 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe } override fun fill(resource: FluidStack, action: IFluidHandler.FluidAction): Int { - if (resource.isEmpty || resource.fluid != Fluids.WATER || waterStored() >= MAX_WATER_STORAGE) return 0 - val diff = (waterStored() + resource.amount).coerceAtMost(MAX_WATER_STORAGE) - waterStored() + if (resource.amount <= 0 || resource.fluid != Fluids.WATER || waterStored() >= MAX_WATER_STORAGE) return 0 + val diff = ((waterStored().toLong() + resource.amount.toLong()).coerceAtMost(MAX_WATER_STORAGE.toLong()) - waterStored().toLong()).toInt() if (action.simulate() || diff == 0) return diff dyeStored[null] = waterStored() + diff return diff diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt index a7326c9c2..485c31d7e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt @@ -143,8 +143,8 @@ sealed class AbstractPoweredFurnaceBlockEntity

0 + + if (isFilledState != filled) { + level?.setBlock(blockPos, blockState.setValue(EssenceStorageBlock.FILLED, filled), Block.UPDATE_CLIENTS) + } } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EssenceStorageBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EssenceStorageBlock.kt index e71867ec1..6fbb1dab5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EssenceStorageBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EssenceStorageBlock.kt @@ -9,11 +9,14 @@ import net.minecraft.world.entity.player.Player import net.minecraft.world.item.DyeColor import net.minecraft.world.level.BlockGetter import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block 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 net.minecraft.world.level.block.state.StateDefinition +import net.minecraft.world.level.block.state.properties.BooleanProperty import net.minecraft.world.level.material.Material import net.minecraft.world.level.material.PushReaction import net.minecraft.world.phys.BlockHitResult @@ -44,6 +47,8 @@ class EssenceStorageBlock(val color: DyeColor?) : RotatableMatteryBlock(Properti acceptor(TranslatableComponent("otm.gui.experience_levels", getLevelFromXp(l.asLong)).withStyle(ChatFormatting.GRAY)) } } + + registerDefaultState(getStateDefinition().any().setValue(FILLED, false)) } override fun newBlockEntity(pPos: BlockPos, pState: BlockState): BlockEntity { return EssenceStorageBlockEntity(pPos, pState) @@ -70,6 +75,11 @@ class EssenceStorageBlock(val color: DyeColor?) : RotatableMatteryBlock(Properti return PushReaction.BLOCK } + override fun createBlockStateDefinition(builder: StateDefinition.Builder) { + super.createBlockStateDefinition(builder) + builder.add(FILLED) + } + private val shapes = getShapeForEachState(rotationProperty) { BlockShapes.ESSENCE_STORAGE.rotateFromNorth(it[rotationProperty]).computeShape() } @Suppress("override_deprecation") @@ -81,4 +91,8 @@ class EssenceStorageBlock(val color: DyeColor?) : RotatableMatteryBlock(Properti ): VoxelShape { return shapes[state]!! } + + companion object { + val FILLED = BooleanProperty.create("filled") + } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt index 8999e8f91..1835e22a0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt @@ -157,8 +157,8 @@ object Widgets18 { } } - val LEFT_CONTROLS = SideControls() val RIGHT_CONTROLS = SideControls() + val LEFT_CONTROLS = SideControls() val TOP_CONTROLS = SideControls() val BOTTOM_CONTROLS = SideControls() val FRONT_CONTROLS = SideControls() 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 cc3358134..5eff8cfc2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt @@ -219,7 +219,21 @@ object MachinesConfig : AbstractConfig("machines") { } } + object EssenceStorage { + init { + builder.push(MNames.ESSENCE_STORAGE) + } + + val RADIUS_HORIZONTAL: Double by builder.defineInRange("RADIUS_HORIZONTAL", 5.0, 0.0, Double.MAX_VALUE / 4.0) + val RADIUS_VERTICAL: Double by builder.defineInRange("RADIUS_VERTICAL", 2.0, 0.0, Double.MAX_VALUE / 4.0) + + init { + builder.pop() + } + } + init { Upgrades + EssenceStorage } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/CombinedContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/CombinedContainer.kt index 36e2aa9d8..992139a7a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/CombinedContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/CombinedContainer.kt @@ -16,6 +16,7 @@ import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.container.util.IContainerSlot import ru.dbotthepony.mc.otm.container.util.containerSlot import ru.dbotthepony.mc.otm.container.util.iterator +import ru.dbotthepony.mc.otm.container.util.slotIterator import ru.dbotthepony.mc.otm.core.collect.concatIterators import ru.dbotthepony.mc.otm.core.collect.filter import ru.dbotthepony.mc.otm.core.collect.flatMap @@ -154,6 +155,9 @@ class CombinedContainer(containers: Stream>>) : IM } override fun iterator(nonEmpty: Boolean): Iterator { + if (notFullCoverage.isEmpty()) + return fullCoverage.iterator().flatMap { it.iterator(nonEmpty) } + return concatIterators( fullCoverage.iterator().flatMap { it.iterator(nonEmpty) }, notFullCoverage.values.iterator().flatMap { it.iterator() }.map { it.item }.let { if (nonEmpty) it.filter { it.isNotEmpty } else it } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/ISubscripable.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/ISubscripable.kt index 5bbd7b52e..75f487e45 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/ISubscripable.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/ISubscripable.kt @@ -66,6 +66,44 @@ interface ISubscriptable { } } +interface IUnitSubscripable : ISubscriptable { + fun addListener(listener: Runnable): ISubscriptable.L + + override fun addListener(listener: Consumer): ISubscriptable.L { + return addListener(Runnable { listener.accept(Unit) }) + } + + class Impl : IUnitSubscripable, Runnable { + private inner class L(val callback: Runnable) : ISubscriptable.L { + private var isRemoved = false + + init { + subscribers.add(this) + } + + override fun remove() { + if (!isRemoved) { + isRemoved = true + queue.add(this) + } + } + } + + private val subscribers = ReferenceLinkedOpenHashSet(0) + private val queue = ReferenceArraySet(0) + + override fun addListener(listener: Runnable): ISubscriptable.L { + return L(listener) + } + + override fun run() { + queue.forEach { subscribers.remove(it) } + queue.clear() + subscribers.forEach { it.callback.run() } + } + } +} + interface IFloatSubcripable : ISubscriptable { @Deprecated("Use type specific listener") override fun addListener(listener: Consumer): ISubscriptable.L { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt new file mode 100644 index 000000000..6637b2fdf --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt @@ -0,0 +1,681 @@ +package ru.dbotthepony.mc.otm.core + +import com.google.common.collect.ImmutableList +import com.google.common.collect.ImmutableSet +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap +import it.unimi.dsi.fastutil.objects.Object2ObjectFunction +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import it.unimi.dsi.fastutil.objects.ObjectArraySet +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.core.Vec3i +import net.minecraft.tags.TagKey +import net.minecraft.world.level.Level +import net.minecraft.world.level.LevelAccessor +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.Rotation +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.mc.otm.core.collect.WeakHashSet +import ru.dbotthepony.mc.otm.core.collect.collect +import ru.dbotthepony.mc.otm.core.collect.map +import ru.dbotthepony.mc.otm.core.math.RelativeSide +import ru.dbotthepony.mc.otm.core.math.plus +import java.util.Collections +import java.util.WeakHashMap +import java.util.function.Predicate +import kotlin.reflect.KClass + +private val blockEntityListeners = WeakHashMap>>() + +fun onBlockEntityInvalidated(blockEntity: BlockEntity) { + blockEntityListeners[blockEntity.level]?.get(blockEntity)?.forEach { it.blockEntityRemoved(blockEntity) } + blockEntityListeners[blockEntity.level]?.remove(blockEntity) +} + +fun interface BlockPredicate { + fun test(pos: BlockPos, access: LevelAccessor): Boolean + + fun and(other: BlockPredicate): BlockPredicate { + return BlockPredicate { pos, access -> test(pos, access) && other.test(pos, access) } + } + + fun or(other: BlockPredicate): BlockPredicate { + return BlockPredicate { pos, access -> test(pos, access) || other.test(pos, access) } + } + + fun offset(offset: BlockPos): Positioned { + return Positioned(offset, this) + } + + fun offset(offset: Vec3i): Positioned { + return offset(BlockPos(offset)) + } + + data class Positioned(val offset: BlockPos, val parent: BlockPredicate) : BlockPredicate { + override fun test(pos: BlockPos, access: LevelAccessor): Boolean { + return parent.test(offset + pos, access) + } + + override fun offset(offset: BlockPos): Positioned { + return Positioned(this.offset + offset, parent) + } + } + + data class And(val nodes: ImmutableSet) : BlockPredicate { + constructor(vararg nodes: BlockPredicate) : this(ImmutableSet.copyOf(nodes)) + constructor(nodes: Set) : this(ImmutableSet.copyOf(nodes)) + + override fun test(pos: BlockPos, access: LevelAccessor): Boolean { + return nodes.all { it.test(pos, access) } + } + } + + data class Or(val nodes: ImmutableSet) : BlockPredicate { + constructor(vararg nodes: BlockPredicate) : this(ImmutableSet.copyOf(nodes)) + constructor(nodes: Set) : this(ImmutableSet.copyOf(nodes)) + + override fun test(pos: BlockPos, access: LevelAccessor): Boolean { + return nodes.any { it.test(pos, access) } + } + } + + object Air : BlockPredicate { + override fun test(pos: BlockPos, access: LevelAccessor): Boolean { + return access.isEmptyBlock(pos) + } + } + + object NotAir : BlockPredicate { + override fun test(pos: BlockPos, access: LevelAccessor): Boolean { + return !access.isEmptyBlock(pos) + } + } +} + +inline fun multiblockConfiguration(configurator: MultiblockBuilder.Node.() -> Unit): MultiblockFactory { + val builder = MultiblockBuilder() + configurator.invoke(builder.root()) + return builder.build() +} + +inline fun multiblockEntity(): MultiblockBuilder.EntityTag { + return MultiblockBuilder.EntityTag(T::class) +} + +class MultiblockBuilder { + private val nodes = Object2ObjectOpenHashMap() + + // not data classes to allow having multiple tags with same target + class EntityTag(val clazz: KClass) : Predicate { + override fun test(t: BlockEntity): Boolean { + return clazz.isInstance(t) + } + } + + enum class Strategy { + OR, AND + } + + @Suppress("unchecked_cast") + abstract class BlockPredicates> { + val predicates = ObjectArraySet() + val children = ObjectArraySet>() + + val blockStateTags = ObjectArraySet() + val blockTags = ObjectArraySet() + val blockEntityTags = ObjectArraySet>() + + fun tagBlockState(value: Any): T { + blockStateTags.add(value) + return this as T + } + + fun tagBlock(value: Any): T { + blockTags.add(value) + return this as T + } + + fun tag(value: EntityTag<*>): T { + blockEntityTags.add(value) + return this as T + } + + fun clear(): T { + predicates.clear() + return this as T + } + + fun predicate(predicate: BlockPredicate): T { + predicates.add(predicate) + return this as T + } + + fun block(block: Block): T { + predicates.add { pos, access -> access.getBlockState(pos).`is`(block) } + return this as T + } + + fun block(block: TagKey): T { + predicates.add { pos, access -> access.getBlockState(pos).`is`(block) } + return this as T + } + + fun air(): T { + predicate(BlockPredicate.Air) + return this as T + } + + fun block(state: BlockState): T { + predicates.add { pos, access -> access.getBlockState(pos) == state } + return this as T + } + + fun and(): And { + return And(this as T) + } + + fun or(): Or { + return Or(this as T) + } + + fun and(configurator: And.() -> Unit): And { + return And(this as T).also(configurator) + } + + fun or(configurator: Or.() -> Unit): Or { + return Or(this as T).also(configurator) + } + + protected fun build(pos: BlockPos): MultiblockFactory.Part { + return MultiblockFactory.Part( + pos, strategy, ImmutableList.copyOf(predicates), + children.stream().map { it.build(pos) }.collect(ImmutableList.toImmutableList()), + ImmutableSet.copyOf(blockStateTags), + ImmutableSet.copyOf(blockTags), + ImmutableSet.copyOf(blockEntityTags), + ) + } + + abstract val strategy: Strategy + } + + class And

>(val parent: P) : BlockPredicates>() { + init { + parent.children.add(this) + } + + fun end() = parent + + override val strategy: Strategy + get() = Strategy.AND + } + + class Or

>(val parent: P) : BlockPredicates>() { + init { + parent.children.add(this) + } + + fun end() = parent + + override val strategy: Strategy + get() = Strategy.OR + } + + /** + * Behaves as if being [Or] node + */ + inner class Node(val pos: BlockPos) : BlockPredicates() { + init { + check(nodes.put(pos, this) == null) { "Trying to create new node at $pos while already having one" } + } + + fun relative(diff: Vec3i): Node { + return node(pos + diff) + } + + fun relative(dir: Direction): Node { + return relative(dir.normal) + } + + fun relative(dir: RelativeSide): Node { + return relative(dir.default) + } + + fun front() = relative(RelativeSide.FRONT) + fun back() = relative(RelativeSide.BACK) + fun left() = relative(RelativeSide.LEFT) + fun right() = relative(RelativeSide.RIGHT) + fun top() = relative(RelativeSide.TOP) + fun bottom() = relative(RelativeSide.BOTTOM) + + fun front(block: Block) = relative(RelativeSide.FRONT).also { it.block(block) } + fun back(block: Block) = relative(RelativeSide.BACK).also { it.block(block) } + fun left(block: Block) = relative(RelativeSide.LEFT).also { it.block(block) } + fun right(block: Block) = relative(RelativeSide.RIGHT).also { it.block(block) } + fun top(block: Block) = relative(RelativeSide.TOP).also { it.block(block) } + fun bottom(block: Block) = relative(RelativeSide.BOTTOM).also { it.block(block) } + + fun front(block: BlockState) = relative(RelativeSide.FRONT).also { it.block(block) } + fun back(block: BlockState) = relative(RelativeSide.BACK).also { it.block(block) } + fun left(block: BlockState) = relative(RelativeSide.LEFT).also { it.block(block) } + fun right(block: BlockState) = relative(RelativeSide.RIGHT).also { it.block(block) } + fun top(block: BlockState) = relative(RelativeSide.TOP).also { it.block(block) } + fun bottom(block: BlockState) = relative(RelativeSide.BOTTOM).also { it.block(block) } + + fun front(predicate: BlockPredicate) = relative(RelativeSide.FRONT).also { it.predicate(predicate) } + fun back(predicate: BlockPredicate) = relative(RelativeSide.BACK).also { it.predicate(predicate) } + fun left(predicate: BlockPredicate) = relative(RelativeSide.LEFT).also { it.predicate(predicate) } + fun right(predicate: BlockPredicate) = relative(RelativeSide.RIGHT).also { it.predicate(predicate) } + fun top(predicate: BlockPredicate) = relative(RelativeSide.TOP).also { it.predicate(predicate) } + fun bottom(predicate: BlockPredicate) = relative(RelativeSide.BOTTOM).also { it.predicate(predicate) } + + fun front(configurator: Node.() -> Unit) = relative(RelativeSide.FRONT).also(configurator) + fun back(configurator: Node.() -> Unit) = relative(RelativeSide.BACK).also(configurator) + fun left(configurator: Node.() -> Unit) = relative(RelativeSide.LEFT).also(configurator) + fun right(configurator: Node.() -> Unit) = relative(RelativeSide.RIGHT).also(configurator) + fun top(configurator: Node.() -> Unit) = relative(RelativeSide.TOP).also(configurator) + fun bottom(configurator: Node.() -> Unit) = relative(RelativeSide.BOTTOM).also(configurator) + + fun front(block: Block, configurator: Node.() -> Unit) = relative(RelativeSide.FRONT).also { it.block(block) }.also(configurator) + fun back(block: Block, configurator: Node.() -> Unit) = relative(RelativeSide.BACK).also { it.block(block) }.also(configurator) + fun left(block: Block, configurator: Node.() -> Unit) = relative(RelativeSide.LEFT).also { it.block(block) }.also(configurator) + fun right(block: Block, configurator: Node.() -> Unit) = relative(RelativeSide.RIGHT).also { it.block(block) }.also(configurator) + fun top(block: Block, configurator: Node.() -> Unit) = relative(RelativeSide.TOP).also { it.block(block) }.also(configurator) + fun bottom(block: Block, configurator: Node.() -> Unit) = relative(RelativeSide.BOTTOM).also { it.block(block) }.also(configurator) + + fun front(block: BlockState, configurator: Node.() -> Unit) = relative(RelativeSide.FRONT).also { it.block(block) }.also(configurator) + fun back(block: BlockState, configurator: Node.() -> Unit) = relative(RelativeSide.BACK).also { it.block(block) }.also(configurator) + fun left(block: BlockState, configurator: Node.() -> Unit) = relative(RelativeSide.LEFT).also { it.block(block) }.also(configurator) + fun right(block: BlockState, configurator: Node.() -> Unit) = relative(RelativeSide.RIGHT).also { it.block(block) }.also(configurator) + fun top(block: BlockState, configurator: Node.() -> Unit) = relative(RelativeSide.TOP).also { it.block(block) }.also(configurator) + fun bottom(block: BlockState, configurator: Node.() -> Unit) = relative(RelativeSide.BOTTOM).also { it.block(block) }.also(configurator) + + fun front(predicate: BlockPredicate, configurator: Node.() -> Unit) = relative(RelativeSide.FRONT).also { it.predicate(predicate) }.also(configurator) + fun back(predicate: BlockPredicate, configurator: Node.() -> Unit) = relative(RelativeSide.BACK).also { it.predicate(predicate) }.also(configurator) + fun left(predicate: BlockPredicate, configurator: Node.() -> Unit) = relative(RelativeSide.LEFT).also { it.predicate(predicate) }.also(configurator) + fun right(predicate: BlockPredicate, configurator: Node.() -> Unit) = relative(RelativeSide.RIGHT).also { it.predicate(predicate) }.also(configurator) + fun top(predicate: BlockPredicate, configurator: Node.() -> Unit) = relative(RelativeSide.TOP).also { it.predicate(predicate) }.also(configurator) + fun bottom(predicate: BlockPredicate, configurator: Node.() -> Unit) = relative(RelativeSide.BOTTOM).also { it.predicate(predicate) }.also(configurator) + + fun build(): MultiblockFactory.Part { + return build(pos) + } + + override var strategy: Strategy = Strategy.OR + } + + fun node(at: BlockPos): Node { + return nodes[at] ?: Node(at) + } + + fun root() = node(BlockPos.ZERO) + fun root(configurator: Node.() -> Unit) = node(BlockPos.ZERO).also(configurator) + + fun copy(): MultiblockBuilder { + val copied = MultiblockBuilder() + + for ((k, v) in nodes) { + val node = copied.Node(k) + copied.nodes[k] = node + node.predicates.addAll(v.predicates) + } + + return copied + } + + fun build(): MultiblockFactory { + return MultiblockFactory(nodes.values.iterator().map { it.build() }.collect(ImmutableSet.toImmutableSet())) + } +} + +class MultiblockFactory(val north: ImmutableSet) { + data class Part( + val pos: BlockPos, + val strategy: MultiblockBuilder.Strategy, + val predicate: ImmutableList, + val children: ImmutableList, + val blockStateTags: ImmutableSet, + val blockTags: ImmutableSet, + val blockEntityTags: ImmutableSet>, + ) + + fun create(pos: BlockPos): Multiblock { + return Multiblock( + pos, + north, + south, + west, + east, + ) + } + + val south: ImmutableSet = north.iterator().map { it.copy(pos = it.pos.rotate(Rotation.CLOCKWISE_180)) }.collect(ImmutableSet.toImmutableSet()) + val west: ImmutableSet = north.iterator().map { it.copy(pos = it.pos.rotate(Rotation.COUNTERCLOCKWISE_90)) }.collect(ImmutableSet.toImmutableSet()) + val east: ImmutableSet = north.iterator().map { it.copy(pos = it.pos.rotate(Rotation.CLOCKWISE_90)) }.collect(ImmutableSet.toImmutableSet()) +} + +class Multiblock( + pos: BlockPos, + north: Collection, + south: Collection, + west: Collection, + east: Collection, +) { + var isValid = false + private set + + private val configurations = ArrayList() + + private inner class BEList(val tag: MultiblockBuilder.EntityTag) { + val list = ArrayList() + val set = ObjectArraySet() + val setView: Set = Collections.unmodifiableSet(set) + + fun add(blockEntity: BlockEntity) { + if (tag.test(blockEntity)) { + if (set.add(blockEntity as T)) { + blockEntityListeners + .computeIfAbsent(blockEntity.level) { WeakHashMap() } + .computeIfAbsent(blockEntity) { WeakHashSet() } + .add(this@Multiblock) + } + + list.add(blockEntity) + } + } + + fun remove(blockEntity: BlockEntity) { + if (tag.test(blockEntity)) { + check(list.remove(blockEntity as T)) { "Unable to remove $blockEntity from tag $tag" } + + if (blockEntity !in list) { + set.remove(blockEntity) + + val getSet = blockEntityListeners[blockEntity.level]?.get(blockEntity) + + if (getSet != null) { + getSet.remove(this@Multiblock) + + if (getSet.isEmpty()) { + blockEntityListeners[blockEntity.level]?.remove(blockEntity) + } + } + } + } + } + + fun blockEntityRemoved(blockEntity: BlockEntity): Boolean { + if (blockEntity in list) { + while (list.remove(blockEntity)) {} + set.remove(blockEntity) + + return true + } + + return false + } + + fun clear() { + set.forEach { + val getSet = checkNotNull(blockEntityListeners[it.level]) { "Consistency check failed: No subscriber lists for level ${it.level}" }.get(it) + checkNotNull(getSet) { "Consistency check failed: No subscriber list for $it" } + check(getSet.remove(this@Multiblock)) { "Consistency check failed: Can't remove ${this@Multiblock} from $it subscriber list" } + + if (getSet.isEmpty()) { + blockEntityListeners[it.level]?.remove(it) + } + } + + list.clear() + set.clear() + } + } + + private inner class Config(val pos: BlockPos, parts: Collection) { + private inner class Part(val pos: BlockPos, val prototype: MultiblockFactory.Part) { + private var blockEntity: BlockEntity? = null + private var blockState: BlockState? = null + private val assignedBlockEntityLists = ArrayList>(prototype.blockEntityTags.size) + private val assignedBlockStateLists = ArrayList>() + private val assignedBlockLists = ArrayList>() + private val children: ImmutableList = prototype.children.stream().map { Part(pos, it) }.collect(ImmutableList.toImmutableList()) + + init { + prototype.blockEntityTags.forEach { + assignedBlockEntityLists.add(tag2BlockEntity.computeIfAbsent(it, Object2ObjectFunction { _ -> BEList(it as MultiblockBuilder.EntityTag).also { blockEntityLists.add(it) } })) + } + + prototype.blockStateTags.forEach { + assignedBlockStateLists.add(tag2BlockState.computeIfAbsent(it, Object2ObjectFunction { Reference2IntOpenHashMap().also { blockStateLists.add(it) } })) + } + + prototype.blockTags.forEach { + assignedBlockLists.add(tag2Block.computeIfAbsent(it, Object2ObjectFunction { Object2IntOpenHashMap().also { blockLists.add(it) } })) + } + } + + private var lastSuccessfulPathPredicate = -1 + private var lastSuccessfulPathChildren = -1 + + fun test(levelAccessor: LevelAccessor): Boolean { + val test = when (prototype.strategy) { + MultiblockBuilder.Strategy.OR -> { + var status = true + + if (prototype.predicate.isNotEmpty()) { + if (lastSuccessfulPathPredicate != -1 && !prototype.predicate[lastSuccessfulPathPredicate].test(pos, levelAccessor)) { + lastSuccessfulPathPredicate = -1 + } + + if (lastSuccessfulPathPredicate == -1) { + lastSuccessfulPathPredicate = prototype.predicate.indexOfFirst { it.test(pos, levelAccessor) } + status = lastSuccessfulPathPredicate != -1 + } + } + + if (status && children.isNotEmpty()) { + if (lastSuccessfulPathChildren != -1 && !children[lastSuccessfulPathChildren].test(levelAccessor)) { + lastSuccessfulPathChildren = -1 + } + + if (lastSuccessfulPathChildren == -1) { + lastSuccessfulPathChildren = children.indexOfFirst { it.test(levelAccessor) } + status = lastSuccessfulPathChildren != -1 + } + } + + status + } + + MultiblockBuilder.Strategy.AND -> prototype.predicate.all { it.test(pos, levelAccessor) } && children.all { it.test(levelAccessor) } + } + + if (test) { + if (assignedBlockEntityLists.isNotEmpty()) { + val be1 = blockEntity + val be2 = levelAccessor.getBlockEntity(pos) + + if (be1 != be2) { + if (be1 != null) { + assignedBlockEntityLists.forEach { it.remove(be1) } + } + + if (be2 != null) { + assignedBlockEntityLists.forEach { it.add(be2) } + } + + blockEntity = be2 + } + } + + if (assignedBlockStateLists.isNotEmpty() || assignedBlockLists.isNotEmpty()) { + val state = levelAccessor.getBlockState(pos) + val old = blockState + + if (state != old) { + if (old != null) { + assignedBlockStateLists.forEach { + it[old] = it.getInt(old) - 1 + check(it.getInt(old) >= 0) { "Consistency check failed: Counter for block state $old turned negative" } + } + + assignedBlockLists.forEach { + it[old.block] = it.getInt(old.block) - 1 + check(it.getInt(old.block) >= 0) { "Consistency check failed: Counter for block ${old.block.registryName} turned negative" } + } + } + + assignedBlockStateLists.forEach { + it[state] = it.getInt(state) + 1 + } + + assignedBlockLists.forEach { + it[state.block] = it.getInt(state.block) + 1 + } + + blockState = state + } + } + } else { + clearFull() + } + + return test + } + + private fun clearFull() { + val blockEntity = blockEntity + + if (blockEntity != null) { + assignedBlockEntityLists.forEach { it.remove(blockEntity) } + } + + val blockState = blockState + + if (blockState != null) { + assignedBlockStateLists.forEach { + it[blockState] = it.getInt(blockState) - 1 + check(it.getInt(blockState) >= 0) { "Consistency check failed: Counter for block state $blockState turned negative" } + } + + assignedBlockLists.forEach { + it[blockState.block] = it.getInt(blockState.block) - 1 + check(it.getInt(blockState.block) >= 0) { "Consistency check failed: Counter for block ${blockState.block.registryName} turned negative" } + } + } + + this.blockEntity = null + this.blockState = null + + lastSuccessfulPathPredicate = -1 + lastSuccessfulPathChildren = -1 + + // avoid allocating iterator when empty + if (children.isNotEmpty()) + children.forEach { it.clearFull() } + } + + fun clear() { + blockEntity = null + blockState = null + + lastSuccessfulPathPredicate = -1 + lastSuccessfulPathChildren = -1 + + children.forEach { it.clear() } + } + } + + private val tag2BlockEntity = Object2ObjectOpenHashMap, BEList<*>>() + private val tag2BlockState = Object2ObjectOpenHashMap>() + private val tag2Block = Object2ObjectOpenHashMap>() + + private val blockEntityLists = ArrayList>() + private val blockStateLists = ArrayList>() + private val blockLists = ArrayList>() + + private val parts: ImmutableSet = parts.stream().map { Part(it.pos + pos, it) }.collect(ImmutableSet.toImmutableSet()) + + fun clear() { + blockEntityLists.forEach { it.clear() } + blockStateLists.forEach { it.clear() } + blockLists.forEach { it.clear() } + parts.forEach { it.clear() } + } + + fun update(levelAccessor: LevelAccessor): Boolean { + var valid = true + + for (part in parts) { + valid = part.test(levelAccessor) + if (!valid) break + } + + if (!valid) + clear() + + return valid + } + + fun blockEntities(tag: MultiblockBuilder.EntityTag): Set { + return (tag2BlockEntity[tag]?.setView ?: setOf()) as Set + } + + fun blockEntityRemoved(blockEntity: BlockEntity): Boolean { + var any = false + + blockEntityLists.forEach { + any = it.blockEntityRemoved(blockEntity) || any + } + + return any + } + } + + private val north = Config(pos, north).also { configurations.add(it) } + private val south = Config(pos, south).also { configurations.add(it) } + private val west = Config(pos, west).also { configurations.add(it) } + private val east = Config(pos, east).also { configurations.add(it) } + + private var activeConfig: Config? = null + + fun blockEntities(tag: MultiblockBuilder.EntityTag): Set { + if (!isValid) return emptySet() + return activeConfig?.blockEntities(tag) ?: setOf() + } + + fun blockEntityRemoved(blockEntity: BlockEntity) { + activeConfig?.blockEntityRemoved(blockEntity) + } + + fun update(levelAccessor: LevelAccessor): Boolean { + val activeConfig = activeConfig + + if (activeConfig != null && activeConfig.update(levelAccessor)) { + return true + } else if (activeConfig != null) { + for (config in configurations) { + if (config !== activeConfig && config.update(levelAccessor)) { + this.activeConfig = config + return true + } + } + + this.activeConfig = null + this.isValid = false + return false + } else { + for (config in configurations) { + if (config.update(levelAccessor)) { + this.activeConfig = config + this.isValid = true + return true + } + } + + return false + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/math/BlockRotation.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/math/BlockRotation.kt index 1985f0925..fee43c2be 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/math/BlockRotation.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/math/BlockRotation.kt @@ -1,6 +1,5 @@ package ru.dbotthepony.mc.otm.core.math -import com.google.common.collect.ImmutableMap import net.minecraft.core.BlockPos import net.minecraft.core.Direction import net.minecraft.core.Vec3i @@ -27,8 +26,8 @@ operator fun BlockPos.plus(other: BlockRotation): BlockPos { return this + other.normal } -enum class RelativeSide { - FRONT, BACK, LEFT, RIGHT, TOP, BOTTOM +enum class RelativeSide(val default: Direction) { + FRONT(Direction.NORTH), BACK(Direction.SOUTH), LEFT(Direction.WEST), RIGHT(Direction.EAST), TOP(Direction.UP), BOTTOM(Direction.DOWN) } /** 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 fea6ebb36..4db354925 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt @@ -44,6 +44,10 @@ object MBlockEntities { return registry.register(name) { BlockEntityType.Builder.of(factory, *blocks.map { it.get() }.toTypedArray()).build(null) } } + private fun register(name: String, factory: BlockEntityType.BlockEntitySupplier, blocks: Supplier): MDeferredRegister<*>.Entry> { + return registry.register(name) { BlockEntityType.Builder.of(factory, blocks.get()).build(null) } + } + private fun register(name: String, factory: BlockEntityType.BlockEntitySupplier, blocks: Map<*, Block>): MDeferredRegister<*>.Entry> { return registry.register(name) { BlockEntityType.Builder.of(factory, *blocks.values.toTypedArray()).build(null) } } @@ -87,6 +91,8 @@ object MBlockEntities { val POWERED_BLAST_FURNACE by register(MNames.POWERED_BLAST_FURNACE, ::PoweredBlastFurnaceBlockEntity, MBlocks.POWERED_BLAST_FURNACE) val POWERED_SMOKER by register(MNames.POWERED_SMOKER, ::PoweredSmokerBlockEntity, MBlocks.POWERED_SMOKER) + val MULTIBLOCK_TEST by register("multiblock_test", ::MultiblockTestBlockEntity, MBlocks::MULTIBLOCK_TEST) + val ENERGY_CABLES: Map> = SupplierMap(CablesConfig.E.entries.map { conf -> var selfFeed: Supplier> = Supplier { TODO() } selfFeed = register("${conf.name.lowercase()}_energy_cable", { a, b -> SimpleEnergyCableBlockEntity(selfFeed.get(), a, b, conf) }) as Supplier> 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 74f842ce9..aaefc4f18 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt @@ -31,6 +31,7 @@ import ru.dbotthepony.mc.otm.block.BlockSphereDebugger import ru.dbotthepony.mc.otm.block.EnergyCableBlock import ru.dbotthepony.mc.otm.block.MatterCableBlock import ru.dbotthepony.mc.otm.block.MatteryBlock +import ru.dbotthepony.mc.otm.block.MultiblockTestBlock import ru.dbotthepony.mc.otm.block.StorageCableBlock import ru.dbotthepony.mc.otm.block.addSimpleDescription import ru.dbotthepony.mc.otm.block.decorative.DevChestBlock @@ -220,7 +221,7 @@ object MBlocks { .sound(SoundType.BASALT) .requiresCorrectToolForDrops() .explosionResistance(80f) - .strength(4f) + .destroyTime(2.5f) ) } val TRITANIUM_STRIPED_STAIRS: Block by registry.register(MNames.TRITANIUM_STRIPED_STAIRS) { StairBlock( @@ -241,9 +242,11 @@ object MBlocks { .sound(SoundType.BASALT) .requiresCorrectToolForDrops() .explosionResistance(40f) - .strength(3f) + .destroyTime(1.5f) ) } + val MULTIBLOCK_TEST by registry.register("multiblock_test") { MultiblockTestBlock() } + init { MRegistry.registerBlocks(registry) } 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 6c980deaf..2c51aae6e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt @@ -161,6 +161,7 @@ object MItems { val DEBUG_EXPLOSION_SMALL: Item by registry.register(MNames.DEBUG_EXPLOSION_SMALL) { BlockItem(MBlocks.DEBUG_EXPLOSION_SMALL, Item.Properties().stacksTo(64)) } val DEBUG_SPHERE_POINTS: Item by registry.register(MNames.DEBUG_SPHERE_POINTS) { BlockItem(MBlocks.DEBUG_SPHERE_POINTS, Item.Properties().stacksTo(64)) } + val MULTIBLOCK_TEST by registry.register("multiblock_test") { BlockItem(MBlocks.MULTIBLOCK_TEST, Properties().stacksTo(64)) } val TRITANIUM_ANVIL: List 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 59afb04dd..506dfa6d6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt @@ -10,10 +10,12 @@ import net.minecraft.client.renderer.item.ItemProperties import net.minecraft.core.BlockPos import net.minecraft.core.cauldron.CauldronInteraction import net.minecraft.core.registries.Registries +import net.minecraft.nbt.CompoundTag import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.ai.village.poi.PoiType import net.minecraft.world.entity.ai.village.poi.PoiTypes +import net.minecraft.world.item.BlockItem import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeableArmorItem import net.minecraft.world.item.ItemStack @@ -393,6 +395,18 @@ object MRegistry : IBlockItemRegistryAcceptor { } } } + + for (item in MItems.ESSENCE_STORAGE.values) { + ItemProperties.register(item, ResourceLocation(OverdriveThatMatters.MOD_ID, "is_filled")) { stack, _, _, _ -> + val tag = (stack.tag?.get(BlockItem.BLOCK_ENTITY_TAG) as? CompoundTag)?: return@register 0f + + if (tag.contains("experienceStored") && tag.getLong("experienceStored") > 0.0) { + 1f + } else { + 0f + } + } + } } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index cdac62ced..8bfb41b28 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -168,6 +168,8 @@ public net.minecraft.world.entity.boss.wither.WitherBoss f_31432_ # TARGETING_CO public-f net.minecraft.world.entity.boss.wither.WitherBoss f_31431_ # LIVING_ENTITY_SELECTOR public net.minecraft.world.entity.ai.targeting.TargetingConditions f_26879_ # selector +public net.minecraft.world.entity.ExperienceOrb f_147072_ # count + public net.minecraft.advancements.critereon.InventoryChangeTrigger$TriggerInstance f_43179_ public net.minecraft.advancements.critereon.InventoryChangeTrigger$TriggerInstance f_43178_ public net.minecraft.advancements.critereon.InventoryChangeTrigger$TriggerInstance f_43177_ diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/advanced_energy_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/advanced_energy_cable.json deleted file mode 100644 index ae8a815be..000000000 --- a/src/main/resources/assets/overdrive_that_matters/blockstates/advanced_energy_cable.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "multipart": [ - { - "apply": { - "model": "overdrive_that_matters:block/storage_cable_core" - } - }, - - { - "when": { - "connect_south": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection" - } - }, - - { - "when": { - "connect_west": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 90 - } - }, - - { - "when": { - "connect_north": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 180 - } - }, - - { - "when": { - "connect_east": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 270 - } - }, - - { - "when": { - "connect_up": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 90 - } - }, - - { - "when": { - "connect_down": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 270 - } - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/crude_energy_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/crude_energy_cable.json deleted file mode 100644 index ae8a815be..000000000 --- a/src/main/resources/assets/overdrive_that_matters/blockstates/crude_energy_cable.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "multipart": [ - { - "apply": { - "model": "overdrive_that_matters:block/storage_cable_core" - } - }, - - { - "when": { - "connect_south": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection" - } - }, - - { - "when": { - "connect_west": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 90 - } - }, - - { - "when": { - "connect_north": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 180 - } - }, - - { - "when": { - "connect_east": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 270 - } - }, - - { - "when": { - "connect_up": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 90 - } - }, - - { - "when": { - "connect_down": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 270 - } - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/matter_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/matter_cable.json deleted file mode 100644 index e751d40ea..000000000 --- a/src/main/resources/assets/overdrive_that_matters/blockstates/matter_cable.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "multipart": [ - { - "apply": { - "model": "overdrive_that_matters:block/matter_cable_core" - } - }, - - { - "when": { - "connect_south": true - }, - - "apply": { - "model": "overdrive_that_matters:block/matter_cable_connection" - } - }, - - { - "when": { - "connect_west": true - }, - - "apply": { - "model": "overdrive_that_matters:block/matter_cable_connection", - "y": 90 - } - }, - - { - "when": { - "connect_north": true - }, - - "apply": { - "model": "overdrive_that_matters:block/matter_cable_connection", - "y": 180 - } - }, - - { - "when": { - "connect_east": true - }, - - "apply": { - "model": "overdrive_that_matters:block/matter_cable_connection", - "y": 270 - } - }, - - { - "when": { - "connect_up": true - }, - - "apply": { - "model": "overdrive_that_matters:block/matter_cable_connection", - "x": 90 - } - }, - - { - "when": { - "connect_down": true - }, - - "apply": { - "model": "overdrive_that_matters:block/matter_cable_connection", - "x": 270 - } - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/regular_energy_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/regular_energy_cable.json deleted file mode 100644 index ae8a815be..000000000 --- a/src/main/resources/assets/overdrive_that_matters/blockstates/regular_energy_cable.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "multipart": [ - { - "apply": { - "model": "overdrive_that_matters:block/storage_cable_core" - } - }, - - { - "when": { - "connect_south": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection" - } - }, - - { - "when": { - "connect_west": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 90 - } - }, - - { - "when": { - "connect_north": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 180 - } - }, - - { - "when": { - "connect_east": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 270 - } - }, - - { - "when": { - "connect_up": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 90 - } - }, - - { - "when": { - "connect_down": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 270 - } - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/storage_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/storage_cable.json deleted file mode 100644 index ae8a815be..000000000 --- a/src/main/resources/assets/overdrive_that_matters/blockstates/storage_cable.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "multipart": [ - { - "apply": { - "model": "overdrive_that_matters:block/storage_cable_core" - } - }, - - { - "when": { - "connect_south": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection" - } - }, - - { - "when": { - "connect_west": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 90 - } - }, - - { - "when": { - "connect_north": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 180 - } - }, - - { - "when": { - "connect_east": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 270 - } - }, - - { - "when": { - "connect_up": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 90 - } - }, - - { - "when": { - "connect_down": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 270 - } - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/superconductor_energy_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/superconductor_energy_cable.json deleted file mode 100644 index ae8a815be..000000000 --- a/src/main/resources/assets/overdrive_that_matters/blockstates/superconductor_energy_cable.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "multipart": [ - { - "apply": { - "model": "overdrive_that_matters:block/storage_cable_core" - } - }, - - { - "when": { - "connect_south": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection" - } - }, - - { - "when": { - "connect_west": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 90 - } - }, - - { - "when": { - "connect_north": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 180 - } - }, - - { - "when": { - "connect_east": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "y": 270 - } - }, - - { - "when": { - "connect_up": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 90 - } - }, - - { - "when": { - "connect_down": true - }, - - "apply": { - "model": "overdrive_that_matters:block/storage_cable_connection", - "x": 270 - } - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/base_cable_connection.json b/src/main/resources/assets/overdrive_that_matters/models/block/base_cable_connection.json new file mode 100644 index 000000000..c774f91ee --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/models/block/base_cable_connection.json @@ -0,0 +1,19 @@ +{ + "parent": "block/block", + "texture_size": [16, 16], + "textures": { + "particle": "#0" + }, + "elements": [ + { + "from": [ 5, 5, 11 ], + "to": [ 11, 11, 16 ], + "faces": { + "down": {"uv": [6, 0, 11, 6],"rotation": 90, "texture": "#0" }, + "up": {"uv": [6, 0, 11, 6],"rotation": 90, "texture": "#0" }, + "west": {"uv": [6, 0, 11, 6], "texture": "#0" }, + "east": {"uv": [6, 0, 11, 6], "texture": "#0" } + } + } + ] +} diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/base_cable_core.json b/src/main/resources/assets/overdrive_that_matters/models/block/base_cable_core.json new file mode 100644 index 000000000..353685030 --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/models/block/base_cable_core.json @@ -0,0 +1,21 @@ +{ + "parent": "block/block", + "texture_size": [16, 16], + "textures": { + "particle": "#0" + }, + "elements": [ + { + "from": [ 5, 5, 5 ], + "to": [ 11, 11, 11 ], + "faces": { + "down": {"uv": [0, 0, 6, 6], "texture": "#0" }, + "up": {"uv": [0, 0, 6, 6], "texture": "#0" }, + "north": {"uv": [0, 0, 6, 6], "texture": "#0" }, + "south": {"uv": [0, 0, 6, 6], "texture": "#0" }, + "west": {"uv": [0, 0, 6, 6], "texture": "#0" }, + "east": {"uv": [0, 0, 6, 6], "texture": "#0" } + } + } + ] +} diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/essence_storage_empty.json b/src/main/resources/assets/overdrive_that_matters/models/block/essence_storage_empty.json new file mode 100644 index 000000000..edbee1f08 --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/models/block/essence_storage_empty.json @@ -0,0 +1,124 @@ +{ + "parent": "block/block", + "credit": "Made with Blockbench", + "render_type": "cutout", + "texture_size": [32, 64], + "textures": { + "0": "overdrive_that_matters:block/essence_storage", + "particle": "#0" + }, + "elements": [ + { + "name": "body", + "from": [0, 0, 0], + "to": [16, 2, 16], + "faces": { + "north": {"uv": [0, 4, 8, 4.5], "texture": "#0"}, + "east": {"uv": [0, 4, 8, 4.5], "texture": "#0"}, + "south": {"uv": [0, 4, 8, 4.5], "texture": "#0"}, + "west": {"uv": [0, 4, 8, 4.5], "texture": "#0"}, + "up": {"uv": [0, 0, 8, 4], "texture": "#0"}, + "down": {"uv": [0, 0, 8, 4], "texture": "#0"} + } + }, + { + "name": "body", + "from": [0, 3, 0], + "to": [16, 5, 16], + "faces": { + "north": {"uv": [8, 7.25, 16, 7.75], "texture": "#0"}, + "east": {"uv": [8, 7.25, 16, 7.75], "texture": "#0"}, + "south": {"uv": [8, 7.25, 16, 7.75], "texture": "#0"}, + "west": {"uv": [8, 7.25, 16, 7.75], "texture": "#0"}, + "up": {"uv": [0, 7.25, 8, 11.25], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 0, 8, 4], "texture": "#0"} + } + }, + { + "name": "body", + "from": [9, 5, 0], + "to": [16, 16, 14], + "faces": { + "north": {"uv": [12, 0, 15.5, 2.75], "texture": "#0"}, + "east": {"uv": [9, 7.75, 16, 10.5], "texture": "#0"}, + "south": {"uv": [11, 4.5, 14.5, 7.25], "texture": "#0"}, + "west": {"uv": [0, 4.5, 7, 7.25], "texture": "#0"}, + "up": {"uv": [0, 7.75, 3.5, 11.25], "rotation": 180, "texture": "#0"} + } + }, + { + "name": "body", + "from": [0, 10, 14], + "to": [16, 16, 16], + "faces": { + "east": {"uv": [8, 7.75, 9, 9.25], "texture": "#0"}, + "south": {"uv": [0, 11.25, 8, 12.75], "texture": "#0"}, + "west": {"uv": [14.5, 4.5, 15.5, 6], "texture": "#0"}, + "up": {"uv": [0, 7.25, 8, 7.75], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 7.25, 8, 7.75], "texture": "#0"} + } + }, + { + "name": "body", + "from": [0, 5, 9], + "to": [9, 16, 14], + "faces": { + "north": {"uv": [7, 4.5, 11.5, 7.25], "texture": "#0"}, + "south": {"uv": [5, 4.5, 9.5, 7.25], "texture": "#0"}, + "west": {"uv": [12, 4.5, 14.5, 7.25], "texture": "#0"}, + "up": {"uv": [3.5, 7.75, 8, 9], "rotation": 180, "texture": "#0"} + } + }, + { + "name": "body", + "from": [1, 2, 1], + "to": [15, 3, 15], + "faces": { + "north": {"uv": [0.5, 4.25, 7.5, 4.5], "texture": "#0"}, + "east": {"uv": [0.5, 4.25, 7.5, 4.5], "texture": "#0"}, + "south": {"uv": [0.5, 4.25, 7.5, 4.5], "texture": "#0"}, + "west": {"uv": [0.5, 4.25, 7.5, 4.5], "texture": "#0"} + } + }, + { + "name": "body", + "from": [1, 5, 14], + "to": [15, 10, 15], + "faces": { + "east": {"uv": [15.5, 10.5, 16, 11.75], "texture": "#0"}, + "south": {"uv": [8.5, 10.5, 15.5, 11.75], "texture": "#0"}, + "west": {"uv": [8, 10.5, 8.5, 11.75], "texture": "#0"} + } + }, + { + "name": "bottle", + "from": [1, 13, 1], + "to": [9, 15, 9], + "faces": { + "north": {"uv": [8, 2, 12, 2.5], "texture": "#0"}, + "west": {"uv": [8, 2, 12, 2.5], "texture": "#0"}, + "up": {"uv": [8, 0, 12, 2], "texture": "#0"}, + "down": {"uv": [8, 0, 12, 2], "texture": "#0"} + } + }, + { + "name": "bottle", + "from": [1, 5, 1], + "to": [9, 6, 9], + "faces": { + "north": {"uv": [8, 4.25, 12, 4.5], "texture": "#0"}, + "west": {"uv": [8, 4.25, 12, 4.5], "texture": "#0"}, + "up": {"uv": [8, 0, 12, 2], "texture": "#0"} + } + }, + { + "name": "bottle", + "from": [1, 6, 1], + "to": [9, 13, 9], + "faces": { + "north": {"uv": [8, 2.5, 12, 4.25], "texture": "#0"}, + "west": {"uv": [8, 2.5, 12, 4.25], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/essence_storage.json b/src/main/resources/assets/overdrive_that_matters/models/block/essence_storage_filled.json similarity index 76% rename from src/main/resources/assets/overdrive_that_matters/models/block/essence_storage.json rename to src/main/resources/assets/overdrive_that_matters/models/block/essence_storage_filled.json index b8cd1d055..f9420d560 100644 --- a/src/main/resources/assets/overdrive_that_matters/models/block/essence_storage.json +++ b/src/main/resources/assets/overdrive_that_matters/models/block/essence_storage_filled.json @@ -1,10 +1,12 @@ { + "parent": "block/block", "credit": "Made with Blockbench", "render_type": "cutout", "texture_size": [32, 64], "textures": { "0": "overdrive_that_matters:block/essence_storage", - "particle": "overdrive_that_matters:block/essence_storage" + "1": "overdrive_that_matters:block/liquid_xp_still", + "particle": "#0" }, "elements": [ { @@ -92,15 +94,15 @@ { "name": "experience", "from": [1.5, 5, 1.5], - "to": [8.5, 11, 8.5], + "to": [8.5, 13, 8.5], "faces": { - "north": {"uv": [8, 14.5, 11.5, 16], "texture": "#0"}, - "east": {"uv": [12.5, 12, 16, 13.5], "texture": "#0"}, - "south": {"uv": [9, 12, 12.5, 13.5], "texture": "#0"}, - "west": {"uv": [11.5, 14.5, 15, 16], "texture": "#0"}, - "up": {"uv": [9.5, 12.5, 13, 14.25], "texture": "#0"} + "north": {"uv": [7.5, 3, 14.5, 11], "texture": "#1"}, + "west": {"uv": [1.5, 3, 8.5, 11], "texture": "#1"} }, - "forge_data": { "block_light": 15, "sky_light": 15 } + "forge_data": { + "block_light": 15, + "sky_light": 15 + } }, { "name": "bottle", @@ -132,36 +134,5 @@ "west": {"uv": [8, 2.5, 12, 4.25], "texture": "#0"} } } - ], - "display": { - "thirdperson_righthand": { - "rotation": [75, 45, 0], - "translation": [0, 2.5, 0], - "scale": [0.375, 0.375, 0.375] - }, - "thirdperson_lefthand": { - "rotation": [75, 45, 0], - "translation": [0, 2.5, 0], - "scale": [0.375, 0.375, 0.375] - }, - "firstperson_righthand": { - "rotation": [0, 45, 0], - "scale": [0.4, 0.4, 0.4] - }, - "firstperson_lefthand": { - "rotation": [0, 225, 0], - "scale": [0.4, 0.4, 0.4] - }, - "ground": { - "translation": [0, 3, 0], - "scale": [0.25, 0.25, 0.25] - }, - "gui": { - "rotation": [30, 225, 0], - "scale": [0.625, 0.625, 0.625] - }, - "fixed": { - "scale": [0.5, 0.5, 0.5] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/storage_cable_connection.json b/src/main/resources/assets/overdrive_that_matters/models/block/storage_cable_connection.json deleted file mode 100644 index 21034ce5a..000000000 --- a/src/main/resources/assets/overdrive_that_matters/models/block/storage_cable_connection.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "parent": "block/block", - "texture_size": [16, 16], - "textures": { - "connection": "overdrive_that_matters:block/storage_cable", - "particle": "overdrive_that_matters:block/storage_cable" - }, - "elements": [ - { - "from": [ 5, 5, 11 ], - "to": [ 11, 11, 16 ], - "faces": { - "down": {"uv": [6, 0, 11, 6],"rotation": 90, "texture": "#connection" }, - "up": {"uv": [6, 0, 11, 6],"rotation": 90, "texture": "#connection" }, - "west": {"uv": [6, 0, 11, 6], "texture": "#connection" }, - "east": {"uv": [6, 0, 11, 6], "texture": "#connection" } - } - } - ] -} diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/storage_cable_core.json b/src/main/resources/assets/overdrive_that_matters/models/block/storage_cable_core.json deleted file mode 100644 index 82ce8a212..000000000 --- a/src/main/resources/assets/overdrive_that_matters/models/block/storage_cable_core.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "parent": "block/block", - "texture_size": [16, 16], - "textures": { - "core": "overdrive_that_matters:block/storage_cable", - "particle": "overdrive_that_matters:block/storage_cable" - }, - "elements": [ - { - "from": [ 5, 5, 5 ], - "to": [ 11, 11, 11 ], - "faces": { - "down": {"uv": [0, 0, 6, 6], "texture": "#core" }, - "up": {"uv": [0, 0, 6, 6], "texture": "#core" }, - "north": {"uv": [0, 0, 6, 6], "texture": "#core" }, - "south": {"uv": [0, 0, 6, 6], "texture": "#core" }, - "west": {"uv": [0, 0, 6, 6], "texture": "#core" }, - "east": {"uv": [0, 0, 6, 6], "texture": "#core" } - } - } - ] -} diff --git a/src/main/resources/assets/overdrive_that_matters/models/item/base_cable.json b/src/main/resources/assets/overdrive_that_matters/models/item/base_cable.json new file mode 100644 index 000000000..80b3fb46b --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/models/item/base_cable.json @@ -0,0 +1,49 @@ +{ + "parent": "block/block", + "texture_size": [16, 16], + "textures": { + "particle": "#0" + }, + "elements": [ + { + "from": [5, 5, 5], + "to": [11, 11, 11], + "faces": { + "north": {"uv": [0, 0, 6, 6], "texture": "#0"}, + "south": {"uv": [0, 0, 6, 6], "texture": "#0"}, + "up": {"uv": [0, 0, 6, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 0, 6, 6], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [0, 5, 5], + "to": [5, 11, 11], + "faces": { + "north": {"uv": [6, 0, 11, 6], "texture": "#0"}, + "south": {"uv": [6, 6, 11, 0], "rotation": 180, "texture": "#0"}, + "west": {"uv": [0, 0, 6, 6], "texture": "#0"}, + "up": {"uv": [6, 0, 11, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [6, 0, 11, 6], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [11, 5, 5], + "to": [16, 11, 11], + "faces": { + "north": {"uv": [11, 0, 16, 6], "texture": "#0"}, + "east": {"uv": [0, 0, 6, 6], "texture": "#0"}, + "south": {"uv": [11, 6, 16, 0], "rotation": 180, "texture": "#0"}, + "up": {"uv": [11, 0, 16, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [11, 0, 16, 6], "rotation": 180, "texture": "#0"} + } + } + ], + "gui_light": "front", + "display": { + "gui": { + "rotation": [0, 0, 0], + "translation": [0, 0, 0], + "scale": [1, 1, 1] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/models/item/storage_cable.json b/src/main/resources/assets/overdrive_that_matters/models/item/storage_cable.json deleted file mode 100644 index e0355ccb3..000000000 --- a/src/main/resources/assets/overdrive_that_matters/models/item/storage_cable.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "parent": "block/block", - "texture_size": [16, 16], - "textures": { - "core": "overdrive_that_matters:block/storage_cable", - "particle": "overdrive_that_matters:block/storage_cable" - }, - "elements": [ - { - "from": [ 6, 6, 6 ], - "to": [ 10, 10, 10 ], - "faces": { - "down": {"uv": [0, 0, 4, 4], "texture": "#core" }, - "up": {"uv": [0, 0, 4, 4], "texture": "#core" }, - "north": {"uv": [0, 0, 4, 4], "texture": "#core" }, - "south": {"uv": [0, 0, 4, 4], "texture": "#core" }, - "west": {"uv": [0, 0, 4, 4], "texture": "#core" }, - "east": {"uv": [0, 0, 4, 4], "texture": "#core" } - } - } - ] -} diff --git a/src/main/resources/overdrive_that_matters.mixins.json b/src/main/resources/overdrive_that_matters.mixins.json index b812f9335..96af5c1d5 100644 --- a/src/main/resources/overdrive_that_matters.mixins.json +++ b/src/main/resources/overdrive_that_matters.mixins.json @@ -6,6 +6,7 @@ "minVersion": "0.8", "refmap": "overdrive_that_matters.refmap.json", "mixins": [ + "BlockEntityMixin", "EnchantmentHelperMixin", "FoodDataMixin", "MixinPatchProjectileFinder", @@ -21,6 +22,7 @@ ], "client": [ "MixinGameRenderer", - "MixinMinecraft" + "MixinMinecraft", + "SplashManagerMixin" ] }