From 70255794a8cd4ab683285a67d4074d06039fa024 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 9 Sep 2022 00:26:13 +0700 Subject: [PATCH] Laboratory Lamp, Danger Stripe Block, Metal Beam #70 --- .../ru/dbotthepony/mc/otm/datagen/DataGen.kt | 37 +++- .../mc/otm/datagen/lang/English.kt | 4 + .../mc/otm/datagen/loot/LootTablesData.kt | 4 + .../dbotthepony/mc/otm/datagen/tags/Tags.kt | 4 + .../dbotthepony/mc/otm/GlobalEventHandler.kt | 30 +++ .../mc/otm/block/BatteryBankBlock.kt | 8 +- .../mc/otm/block/ChemicalGeneratorBlock.kt | 8 +- .../mc/otm/block/EnergyCounterBlock.kt | 8 +- .../otm/block/GravitationStabilizerBlock.kt | 16 +- .../mc/otm/block/LaboratoryLamp.kt | 174 ++++++++++++++++++ .../dbotthepony/mc/otm/block/MatteryBlock.kt | 9 +- .../mc/otm/block/storage/StorageBusBlock.kt | 8 +- .../mc/otm/block/storage/StorageInterfaces.kt | 16 +- .../ru/dbotthepony/mc/otm/core/EuclidMath.kt | 1 + .../kotlin/ru/dbotthepony/mc/otm/core/Ext.kt | 6 + .../ru/dbotthepony/mc/otm/registry/MBlocks.kt | 10 +- .../ru/dbotthepony/mc/otm/registry/MItems.kt | 4 + .../ru/dbotthepony/mc/otm/registry/MNames.kt | 5 + .../dbotthepony/mc/otm/registry/MRegistry.kt | 8 +- .../block/decorative/danger_stripe_block.png | Bin 0 -> 2437 bytes .../decorative/laboratory_lamp_front.png | Bin 0 -> 2437 bytes .../block/decorative/metal_beam_side.png | Bin 0 -> 2437 bytes .../block/decorative/metal_beam_top.png | Bin 0 -> 2437 bytes 23 files changed, 307 insertions(+), 53 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/block/LaboratoryLamp.kt create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/decorative/danger_stripe_block.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/decorative/laboratory_lamp_front.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/decorative/metal_beam_side.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/decorative/metal_beam_top.png diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt index cadd756d3..e5ed70933 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt @@ -76,8 +76,8 @@ object DataGen { blockStateProvider.simpleBlockM(*blocks) } - private fun decorativeColumn(block: Block, side: String, end: String) { - blockModelProvider.decorativeColumn(block, side, end) + private fun decorativeColumn(block: Block, side: String, top: String) { + blockModelProvider.decorativeColumn(block, side, top) blockStateProvider.simpleBlockM(block) } @@ -134,11 +134,11 @@ object DataGen { } private fun decoratives(list: DecorativeBlock) { - for (block in list.blocks.values) { + for (block in list.allBlocks.values) { decorativeCubeAll(block) } - for (item in list.items.values) { + for (item in list.allItems.values) { itemModelProvider.block(item) } } @@ -154,11 +154,11 @@ object DataGen { } private fun decoratives(subdir: String, list: DecorativeBlock) { - for (block in list.blocks.values) { + for (block in list.allBlocks.values) { decorativeCubeAll(subdir, block) } - for (item in list.items.values) { + for (item in list.allItems.values) { itemModelProvider.block(item) } } @@ -174,11 +174,11 @@ object DataGen { } private fun decoratives(subdir: String, suffix: String, list: DecorativeBlock) { - for (block in list.blocks.values) { + for (block in list.allBlocks.values) { decorativeCubeAll(subdir, suffix, block) } - for (item in list.items.values) { + for (item in list.allItems.values) { itemModelProvider.block(item) } } @@ -246,6 +246,27 @@ object DataGen { blockModelProvider.resourceCubeAll(MBlocks.TRITANIUM_RAW_BLOCK) blockModelProvider.resourceCubeAll(MBlocks.DEEPSLATE_TRITANIUM_ORE) + decorativeCubeAll(MBlocks.DANGER_STRIPE_BLOCK) + decorativeColumn(MBlocks.METAL_BEAM, "metal_beam_side", "metal_beam_top") + + blockModelProvider.exec { + it.cube( + MBlocks.LABORATORY_LAMP.registryName!!.path, + ResourceLocation(MOD_ID, "block/decorative/metal_beam_top"), + ResourceLocation(MOD_ID, "block/decorative/metal_beam_top"), + ResourceLocation(MOD_ID, "block/decorative/laboratory_lamp_front"), + ResourceLocation(MOD_ID, "block/decorative/metal_beam_top"), + ResourceLocation(MOD_ID, "block/decorative/metal_beam_top"), + ResourceLocation(MOD_ID, "block/decorative/metal_beam_top"), + ) + } + + itemModelProvider.block(MItems.LABORATORY_LAMP) + itemModelProvider.block(MItems.DANGER_STRIPE_BLOCK) + itemModelProvider.block(MItems.METAL_BEAM) + + blockStateProvider.block(MBlocks.LABORATORY_LAMP) + blockModelProvider.exec { for (crate in MRegistry.CARGO_CRATES.blocks.values) { it.withExistingParent("${crate.registryName!!.path}_closed", ResourceLocation(OverdriveThatMatters.MOD_ID, "${MNames.CARGO_CRATE}_closed")) 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 b0e57ff4c..58815441f 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 @@ -313,6 +313,10 @@ private fun blocks(provider: MatteryLanguageProvider) { add(MBlocks.GRAVITATION_STABILIZER, "desc2", "Requires no power to operate") add(MBlocks.GRAVITATION_STABILIZER, "desc3", "Keep in mind the effect of multiple stabilizers produce exponentially increasing result") add(MBlocks.GRAVITATION_STABILIZER, "desc4", "Too weak gravitation field will cause singularity to melt and evaporate away very fast") + + add(MBlocks.LABORATORY_LAMP, "Laboratory Lamp") + add(MBlocks.DANGER_STRIPE_BLOCK, "Danger Stripes") + add(MBlocks.METAL_BEAM, "Metal Beam") } } diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt index 4b3dd5b04..0e065fe97 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt @@ -32,6 +32,10 @@ fun addLootTables(lootTables: LootTables) { lootTables.dropsSelf(MBlocks.GRAVITATION_STABILIZER) lootTables.dropsOther(MBlocks.GRAVITATION_STABILIZER_LENS, MBlocks.GRAVITATION_STABILIZER) + lootTables.dropsSelf(MBlocks.LABORATORY_LAMP) + lootTables.dropsSelf(MBlocks.DANGER_STRIPE_BLOCK) + lootTables.dropsSelf(MBlocks.METAL_BEAM) + lootTables.tile(MBlocks.ENERGY_COUNTER, EnergyCounterBlockEntity.IO_LIMIT_KEY, EnergyCounterBlockEntity.PASSED_ENERGY_KEY, EnergyCounterBlockEntity.POWER_HISTORY_KEY, EnergyCounterBlockEntity.POWER_HISTORY_POINTER_KEY) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt index c99398a8f..759bf487e 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt @@ -74,6 +74,10 @@ fun addTags(tagsProvider: TagsProvider) { tagsProvider.requiresPickaxe(MRegistry.INDUSTRIAL_GLASS_PANE.allBlocks.values, Tiers.STONE) tagsProvider.requiresPickaxe(MRegistry.DECORATIVE_CRATE.allBlocks.values, Tiers.STONE) + tagsProvider.requiresPickaxe(MBlocks.LABORATORY_LAMP, Tiers.IRON) + tagsProvider.requiresPickaxe(MBlocks.METAL_BEAM, Tiers.IRON) + tagsProvider.requiresPickaxe(MBlocks.DANGER_STRIPE_BLOCK) + tagsProvider.requiresPickaxe(listOf( MBlocks.GRAVITATION_STABILIZER, MBlocks.GRAVITATION_STABILIZER_LENS, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt index 3544166c0..eb05a7323 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt @@ -260,6 +260,36 @@ fun addPostWorldTickerOnce(level: Level, ticker: ITickable) { postWorldTick.computeIfAbsent(level) { TickList() }.add(ticker) } +fun Level.until(ticker: () -> Boolean) { + addPostWorldTicker(this, object : IConditionalTickable { + override var canTick: Boolean = true + private set + + override fun tick() { + canTick = !ticker.invoke() + } + }) +} + +fun Level.untilPre(ticker: () -> Boolean) { + addPreWorldTicker(this, object : IConditionalTickable { + override var canTick: Boolean = true + private set + + override fun tick() { + canTick = !ticker.invoke() + } + }) +} + +fun Level.once(ticker: ITickable) { + addPostWorldTickerOnce(this, ticker) +} + +fun Level.oncePre(ticker: ITickable) { + addPreWorldTickerOnce(this, ticker) +} + private fun clear() { preServerTickTimers.clear() postServerTickTimers.clear() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BatteryBankBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BatteryBankBlock.kt index d752836ff..4922db754 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BatteryBankBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BatteryBankBlock.kt @@ -71,11 +71,11 @@ class BatteryBankBlock : RotatableMatteryBlock(), EntityBlock { state: BlockState, level: Level, pos: BlockPos, - sender: Block, - sender_pos: BlockPos, - flag: Boolean + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean ) { - super.neighborChanged(state, level, pos, sender, sender_pos, flag) + super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) val blockEntity = level.getBlockEntity(pos) as? BatteryBankBlockEntity ?: return diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/ChemicalGeneratorBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/ChemicalGeneratorBlock.kt index 79784fab9..308fd2918 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/ChemicalGeneratorBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/ChemicalGeneratorBlock.kt @@ -44,11 +44,11 @@ class ChemicalGeneratorBlock : RotatableMatteryBlock(), EntityBlock { state: BlockState, level: Level, pos: BlockPos, - sender: Block, - sender_pos: BlockPos, - flag: Boolean + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean ) { - super.neighborChanged(state, level, pos, sender, sender_pos, flag) + super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) if (!level.isClientSide) { val tile = level.getBlockEntity(pos) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/EnergyCounterBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/EnergyCounterBlock.kt index dbf9db5bf..328671c46 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/EnergyCounterBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/EnergyCounterBlock.kt @@ -65,11 +65,11 @@ class EnergyCounterBlock : MatteryBlock(), EntityBlock { state: BlockState, level: Level, pos: BlockPos, - sender: Block, - sender_pos: BlockPos, - flag: Boolean + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean ) { - super.neighborChanged(state, level, pos, sender, sender_pos, flag) + super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) if (!level.isClientSide && !SERVER_IS_DYING) { (level.getBlockEntity(pos) as? EnergyCounterBlockEntity)?.checkSurroundings() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/GravitationStabilizerBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/GravitationStabilizerBlock.kt index 5e1766dee..f36191971 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/GravitationStabilizerBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/GravitationStabilizerBlock.kt @@ -114,11 +114,11 @@ class BlockGravitationStabilizer : RotatableMatteryBlock(props), EntityBlock { state: BlockState, level: Level, pos: BlockPos, - sender: Block, - sender_pos: BlockPos, - flag: Boolean + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean ) { - super.neighborChanged(state, level, pos, sender, sender_pos, flag) + super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) addPreWorldTickerOnce(level) { if (level.getBlockState(pos).block !is BlockGravitationStabilizer) return@addPreWorldTickerOnce @@ -175,11 +175,11 @@ class BlockGravitationStabilizerLens : RotatableMatteryBlock(props) { state: BlockState, level: Level, pos: BlockPos, - sender: Block, - sender_pos: BlockPos, - flag: Boolean + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean ) { - super.neighborChanged(state, level, pos, sender, sender_pos, flag) + super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) addPreWorldTickerOnce(level) { if (level.getBlockState(pos).block !is BlockGravitationStabilizerLens) return@addPreWorldTickerOnce diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/LaboratoryLamp.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/LaboratoryLamp.kt new file mode 100644 index 000000000..3478af23a --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/LaboratoryLamp.kt @@ -0,0 +1,174 @@ +package ru.dbotthepony.mc.otm.block + +import net.minecraft.core.BlockPos +import net.minecraft.world.item.Items +import net.minecraft.world.item.context.BlockPlaceContext +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.Blocks +import net.minecraft.world.level.block.RenderShape +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.block.state.StateDefinition +import net.minecraft.world.level.block.state.properties.BlockStateProperties +import net.minecraft.world.level.material.Material +import net.minecraft.world.phys.shapes.CollisionContext +import net.minecraft.world.phys.shapes.Shapes +import net.minecraft.world.phys.shapes.VoxelShape +import ru.dbotthepony.mc.otm.core.get +import ru.dbotthepony.mc.otm.core.plus +import ru.dbotthepony.mc.otm.core.times +import ru.dbotthepony.mc.otm.core.unaryMinus +import ru.dbotthepony.mc.otm.once +import ru.dbotthepony.mc.otm.registry.MBlocks + +const val LIGHT_LENGTH = 6 + +class LaboratoryLampLight : Block(Properties.of(Material.AIR).strength(-1.0F, 3600000.8F).noLootTable().noOcclusion().lightLevel { 15 }) { + override fun createBlockStateDefinition(builder: StateDefinition.Builder) { + super.createBlockStateDefinition(builder) + builder.add(RotatableMatteryBlock.FACING_FULL) + } + + override fun hasDynamicShape(): Boolean { + return true + } + + @Suppress("OVERRIDE_DEPRECATION") + override fun getShape( + p_60555_: BlockState, + p_60556_: BlockGetter, + p_60557_: BlockPos, + p_60558_: CollisionContext + ): VoxelShape { + return if (p_60558_.isHoldingItem(Items.LIGHT)) Shapes.block() else Shapes.empty() + } + + @Suppress("OVERRIDE_DEPRECATION") + override fun getRenderShape(p_60550_: BlockState): RenderShape { + return RenderShape.INVISIBLE + } + + override fun propagatesSkylightDown(p_49928_: BlockState, p_49929_: BlockGetter, p_49930_: BlockPos): Boolean { + return true + } + + @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) + + level.once { + if (level.getBlockState(pos) != state) + return@once + + val facing = state[RotatableMatteryBlock.FACING_FULL] + + var hit = false + + for (i in 1 .. LIGHT_LENGTH) { + val target = pos + facing * i + val targetState = level.getBlockState(target) + + if (targetState.block == MBlocks.LABORATORY_LAMP && targetState[BlockStateProperties.LIT]) { + hit = true + (targetState.block as LaboratoryLamp).doTick(targetState, level, target) + break + } else if (targetState.block != MBlocks.LABORATORY_LAMP_LIGHT && !targetState.isAir) { + break + } + } + + if (!hit) { + level.setBlockAndUpdate(pos, Blocks.AIR.defaultBlockState()) + } + } + } +} + +class LaboratoryLamp : Block(Properties.of(Material.METAL).explosionResistance(12f).destroyTime(2f).requiresCorrectToolForDrops()) { + init { + registerDefaultState(stateDefinition.any().setValue(BlockStateProperties.LIT, true)) + } + + override fun createBlockStateDefinition(builder: StateDefinition.Builder) { + super.createBlockStateDefinition(builder) + builder.add(RotatableMatteryBlock.FACING_FULL) + builder.add(BlockStateProperties.LIT) + } + + override fun getStateForPlacement(context: BlockPlaceContext): BlockState { + return super.getStateForPlacement(context)!!.setValue(BlockStateProperties.LIT, true).setValue(RotatableMatteryBlock.FACING_FULL, context.nearestLookingDirection) + } + + @Suppress("OVERRIDE_DEPRECATION") + override fun onPlace( + state: BlockState, + level: Level, + pos: BlockPos, + oldState: BlockState, + movedByPiston: Boolean + ) { + super.onPlace(state, level, pos, oldState, movedByPiston) + + doTick(state, level, pos) + } + + fun doTick( + state: BlockState, + level: Level, + pos: BlockPos, + ) { + level.once { + if (level.getBlockState(pos) != state) + return@once + + val lit = state[BlockStateProperties.LIT] + val shouldBeLit = !level.hasNeighborSignal(pos) + + if (lit != shouldBeLit) { + level.setBlockAndUpdate(pos, state.setValue(BlockStateProperties.LIT, shouldBeLit)) + } + + val facing = state[RotatableMatteryBlock.FACING_FULL] + + for (i in 1 .. LIGHT_LENGTH) { + val target = pos + facing * i + val targetState = level.getBlockState(target) + + if (!targetState.isAir && targetState.block != MBlocks.LABORATORY_LAMP_LIGHT) { + break + } + + if (shouldBeLit) { + if (targetState.isAir && targetState.block != MBlocks.LABORATORY_LAMP_LIGHT) { + level.setBlockAndUpdate(target, MBlocks.LABORATORY_LAMP_LIGHT.defaultBlockState().setValue(RotatableMatteryBlock.FACING_FULL, -facing)) + } + } else { + if (targetState.block == MBlocks.LABORATORY_LAMP_LIGHT) { + level.setBlockAndUpdate(target, Blocks.AIR.defaultBlockState()) + } + } + } + } + } + + @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) + doTick(state, level, pos) + } +} 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 5900bee1b..f688b262d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt @@ -46,6 +46,7 @@ abstract class MatteryBlock @JvmOverloads constructor( super.setPlacedBy(level, blockPos, blockState, entity, itemStack) } + @Suppress("OVERRIDE_DEPRECATION") override fun use( blockState: BlockState, level: Level, @@ -74,11 +75,11 @@ abstract class MatteryBlock @JvmOverloads constructor( state: BlockState, level: Level, pos: BlockPos, - sender: Block, - sender_pos: BlockPos, - flag: Boolean + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean ) { - super.neighborChanged(state, level, pos, sender, sender_pos, flag) + super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) if (this is EntityBlock && !level.isClientSide) { val tile = level.getBlockEntity(pos) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageBusBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageBusBlock.kt index baf657dbf..d18042d68 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageBusBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageBusBlock.kt @@ -97,11 +97,11 @@ class StorageBusBlock : RotatableMatteryBlock(), EntityBlock { state: BlockState, level: Level, pos: BlockPos, - sender: Block, - sender_pos: BlockPos, - flag: Boolean + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean ) { - super.neighborChanged(state, level, pos, sender, sender_pos, flag) + super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) if (!level.isClientSide) { val tile = level.getBlockEntity(pos) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt index 35a169791..23604cfd1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt @@ -98,11 +98,11 @@ class StorageImporterBlock : RotatableMatteryBlock(), EntityBlock { state: BlockState, level: Level, pos: BlockPos, - sender: Block, - sender_pos: BlockPos, - flag: Boolean + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean ) { - super.neighborChanged(state, level, pos, sender, sender_pos, flag) + super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) if (!level.isClientSide) { val tile = level.getBlockEntity(pos) @@ -189,11 +189,11 @@ class StorageExporterBlock : RotatableMatteryBlock(), EntityBlock { state: BlockState, level: Level, pos: BlockPos, - sender: Block, - sender_pos: BlockPos, - flag: Boolean + neighbour: Block, + neighbourPos: BlockPos, + movedByPiston: Boolean ) { - super.neighborChanged(state, level, pos, sender, sender_pos, flag) + super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) if (!level.isClientSide) { val tile = level.getBlockEntity(pos) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt index d398711fa..d089dced4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt @@ -373,6 +373,7 @@ operator fun Vec3i.plus(direction: Direction): Vec3i = this.offset(direction.nor operator fun Vec3i.minus(direction: Vec3i): Vec3i = this.subtract(direction) operator fun Vec3i.minus(direction: Direction): Vec3i = this.subtract(direction.normal) operator fun Vec3i.times(int: Int): Vec3i = this.multiply(int) +operator fun Direction.times(int: Int): Vec3i = this.normal.multiply(int) operator fun Vec3i.times(double: Double): Vector = Vector(x * double, y * double, z * double) fun BlockPos.asVector(): Vector { 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 e8688386c..02ea06a9a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt @@ -14,6 +14,8 @@ import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.Entity import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.block.state.StateHolder +import net.minecraft.world.level.block.state.properties.Property import net.minecraft.world.phys.Vec3 import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.items.IItemHandler @@ -325,3 +327,7 @@ fun FriendlyByteBuf.writeItemType(value: Item) { fun FriendlyByteBuf.readItemType(): Item? { return ForgeRegistries.ITEMS.getValue(readInt()) } + +operator fun > StateHolder<*, *>.get(value: Property): T { + return getValue(value) +} 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 14a09a346..d5552d669 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt @@ -1,8 +1,5 @@ package ru.dbotthepony.mc.otm.registry -import com.google.common.collect.ImmutableList -import net.minecraft.client.renderer.ItemBlockRenderTypes -import net.minecraft.client.renderer.RenderType import net.minecraft.util.valueproviders.UniformInt import net.minecraft.world.item.DyeColor import net.minecraft.world.level.block.Block @@ -12,8 +9,6 @@ import net.minecraft.world.level.block.state.BlockBehaviour import net.minecraft.world.level.material.Material import net.minecraft.world.level.material.MaterialColor import net.minecraftforge.eventbus.api.IEventBus -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.ForgeRegistries import ru.dbotthepony.mc.otm.OverdriveThatMatters @@ -81,6 +76,11 @@ object MBlocks { .requiresCorrectToolForDrops() ) } + val LABORATORY_LAMP: Block by registry.register(MNames.LABORATORY_LAMP) { LaboratoryLamp() } + val LABORATORY_LAMP_LIGHT: Block by registry.register(MNames.LABORATORY_LAMP_LIGHT) { LaboratoryLampLight() } + val DANGER_STRIPE_BLOCK: Block by registry.register(MNames.DANGER_STRIPE_BLOCK) { Block(BlockBehaviour.Properties.of(Material.METAL, DyeColor.GRAY).explosionResistance(6f).destroyTime(1.5f).requiresCorrectToolForDrops()) } + val METAL_BEAM: Block by registry.register(MNames.METAL_BEAM) { Block(BlockBehaviour.Properties.of(Material.METAL, DyeColor.GRAY).explosionResistance(14f).destroyTime(2.5f).requiresCorrectToolForDrops()) } + init { MRegistry.CARGO_CRATES.registerBlocks(registry) MRegistry.TRITANIUM_BLOCK.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 46eda9d98..2ffa34490 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt @@ -260,6 +260,10 @@ object MItems { val NUTRIENT_PASTE: Item by registry.register(MNames.NUTRIENT_PASTE) { Item(Item.Properties().stacksTo(64).food( FoodProperties.Builder().meat().nutrition(8).saturationMod(0.9F).build()).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) } + val LABORATORY_LAMP: Item by registry.register(MNames.LABORATORY_LAMP) { BlockItem(MBlocks.LABORATORY_LAMP, DEFAULT_PROPERTIES_DECORATIVE) } + val DANGER_STRIPE_BLOCK: Item by registry.register(MNames.DANGER_STRIPE_BLOCK) { BlockItem(MBlocks.DANGER_STRIPE_BLOCK, DEFAULT_PROPERTIES_DECORATIVE) } + val METAL_BEAM: Item by registry.register(MNames.METAL_BEAM) { BlockItem(MBlocks.METAL_BEAM, DEFAULT_PROPERTIES_DECORATIVE) } + init { MRegistry.CARGO_CRATES.registerItems(registry) MRegistry.TRITANIUM_BLOCK.registerItems(registry) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt index fc8e2d99e..966c7e53a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt @@ -4,6 +4,11 @@ import net.minecraft.resources.ResourceLocation import ru.dbotthepony.mc.otm.OverdriveThatMatters object MNames { + const val LABORATORY_LAMP = "laboratory_lamp" + const val LABORATORY_LAMP_LIGHT = "laboratory_lamp_light" + const val DANGER_STRIPE_BLOCK = "danger_stripe_block" + const val METAL_BEAM = "metal_beam" + // blocks const val ANDROID_STATION = "android_station" // без рецепта const val BATTERY_BANK = "battery_bank" // нужен рецепт 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 722734f55..0cda2d2ae 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt @@ -106,7 +106,7 @@ object MRegistry { .sound(SoundType.METAL) .requiresCorrectToolForDrops() .explosionResistance(10f) - .strength(1f) + .destroyTime(1f) }) val TRITANIUM_BLOCK = DecorativeBlock.simple(MNames.TRITANIUM_BLOCK, { @@ -114,7 +114,7 @@ object MRegistry { .sound(SoundType.BASALT) .requiresCorrectToolForDrops() .explosionResistance(80f) - .strength(2.5f) + .destroyTime(2.5f) }) val VENT = DecorativeBlock.simple(MNames.VENT, { @@ -122,7 +122,7 @@ object MRegistry { .sound(SoundType.BASALT) .requiresCorrectToolForDrops() .explosionResistance(20f) - .strength(1.5f) + .destroyTime(1.5f) }) val VENT_ALTERNATIVE = DecorativeBlock.simple(MNames.VENT_ALTERNATIVE, { @@ -130,7 +130,7 @@ object MRegistry { .sound(SoundType.BASALT) .requiresCorrectToolForDrops() .explosionResistance(20f) - .strength(1.5f) + .destroyTime(1.5f) }) val FLOOR_TILES = ColoredDecorativeBlock.simple(MNames.FLOOR_TILES, { diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/decorative/danger_stripe_block.png b/src/main/resources/assets/overdrive_that_matters/textures/block/decorative/danger_stripe_block.png new file mode 100644 index 0000000000000000000000000000000000000000..d36635b4d3d72a5dd2644f4bd55341d6da866d5b GIT binary patch literal 2437 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