From 9621356682b586e096b6f89d6cc2751d2aab1bcd Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Tue, 7 Jan 2025 18:17:03 +0700 Subject: [PATCH] Captain Redstone Keyes --- .../mc/otm/datagen/lang/English.kt | 5 + .../mc/otm/datagen/lang/Russian.kt | 5 + .../datagen/recipes/CraftingTableRecipes.kt | 5 + .../mc/otm/mixin/BlockStateBaseMixin.java | 36 +++++ .../dbotthepony/mc/otm/GlobalEventHandler.kt | 15 +- .../mc/otm/OverdriveThatMatters.kt | 3 + .../block/decorative/ComputerTerminalBlock.kt | 23 +-- .../dbotthepony/mc/otm/core/util/TickList.kt | 15 +- .../otm/item/tool/RedstoneInteractorItem.kt | 132 ++++++++++++++++++ .../mc/otm/registry/MCreativeTabs.kt | 1 + .../mc/otm/registry/MDataComponentTypes.kt | 2 + .../ru/dbotthepony/mc/otm/registry/MItems.kt | 3 + .../overdrive_that_matters.mixins.json | 3 +- 13 files changed, 218 insertions(+), 30 deletions(-) create mode 100644 src/main/java/ru/dbotthepony/mc/otm/mixin/BlockStateBaseMixin.java create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/item/tool/RedstoneInteractorItem.kt 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 db6ca0492..7271e56c4 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 @@ -633,6 +633,11 @@ private fun blocks(provider: MatteryLanguageProvider) { private fun items(provider: MatteryLanguageProvider) { with(provider.english) { + add(MItems.REDSTONE_INTERACTOR, "Redstone Key") + add(MItems.REDSTONE_INTERACTOR, "desc", "Allows to 'send' redstone signal out of any block") + add(MItems.REDSTONE_INTERACTOR, "desc1", "In other words, allows to temporarily activate redstone mechanisms, such as opening Iron Doors") + add(MItems.REDSTONE_INTERACTOR, "desc2", "Use while sneaking to set redstone timer") + add(MItems.PROCEDURAL_BATTERY, "Mythical Battery") add(MItems.PROCEDURAL_BATTERY, "desc", "These batteries are found in dungeons with randomized stats") 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 ddd28c7af..ccdba5415 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 @@ -634,6 +634,11 @@ private fun blocks(provider: MatteryLanguageProvider) { private fun items(provider: MatteryLanguageProvider) { with(provider.russian) { + add(MItems.REDSTONE_INTERACTOR, "Ключ красного камня") + add(MItems.REDSTONE_INTERACTOR, "desc", "'Посылает' сигнал красного камня из блока, с которым взаимодействует") + add(MItems.REDSTONE_INTERACTOR, "desc1", "Другими словами, позволяет активировать механизмы красного камня, такие как железные двери") + add(MItems.REDSTONE_INTERACTOR, "desc2", "Для настройки таймера используйте будучи крадясь") + add(MItems.PROCEDURAL_BATTERY, "Загадочный аккумулятор") add(MItems.PROCEDURAL_BATTERY, "desc", "Данные аккумуляторы можно найти в подземельях, со случайными характеристиками") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt index 839579ea7..40837f197 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt @@ -522,4 +522,9 @@ fun addCraftingTableRecipes(consumer: RecipeOutput) { .rowB(MItemTags.TRITANIUM_PLATES) .build(consumer, "grill_alt_c/${color?.name?.lowercase() ?: "default"}") } + + MatteryRecipe(MItems.REDSTONE_INTERACTOR, category = RecipeCategory.TOOLS) + .rowAB(Items.LEVER, Tags.Items.NUGGETS_IRON) + .rowB(Tags.Items.DUSTS_REDSTONE) + .build(consumer) } diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/BlockStateBaseMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/BlockStateBaseMixin.java new file mode 100644 index 000000000..99edff58e --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/BlockStateBaseMixin.java @@ -0,0 +1,36 @@ +package ru.dbotthepony.mc.otm.mixin; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +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.CallbackInfoReturnable; +import ru.dbotthepony.mc.otm.item.tool.RedstoneInteractorItem; + +@Mixin(BlockBehaviour.BlockStateBase.class) +public abstract class BlockStateBaseMixin { + @Shadow + protected abstract BlockState asState(); + + @Inject( + method = "getSignal(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;)I", + at = @At("HEAD"), + cancellable = true, + remap = false + ) + public void getSignal(BlockGetter p_60747_, BlockPos p_60748_, Direction p_60749_, CallbackInfoReturnable info) { + if (p_60747_ instanceof Level level) { + int hookResult = RedstoneInteractorItem.Companion.getSignalHook(level, this.asState(), p_60748_, p_60749_); + + if (hookResult != -1) { + info.setReturnValue(hookResult); + } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt index 2665e4b7a..b1eb6560a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt @@ -9,9 +9,6 @@ import net.minecraft.core.HolderLookup import net.minecraft.server.MinecraftServer import net.minecraft.world.level.Level import net.neoforged.api.distmarker.Dist -import net.neoforged.bus.api.EventPriority -import net.neoforged.bus.api.SubscribeEvent -import net.neoforged.fml.common.EventBusSubscriber import net.neoforged.fml.loading.FMLLoader import net.neoforged.neoforge.event.server.ServerAboutToStartEvent import net.neoforged.neoforge.event.server.ServerStoppedEvent @@ -19,7 +16,6 @@ import net.neoforged.neoforge.event.server.ServerStoppingEvent import net.neoforged.neoforge.event.tick.LevelTickEvent import net.neoforged.neoforge.event.tick.ServerTickEvent import org.apache.logging.log4j.LogManager -import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.core.collect.WeakHashSet @@ -226,6 +222,17 @@ fun tickServer(ticker: IConditionalTickable) { postServerTick.add(ticker, SERVER_IS_LIVE, "Server is stopping") } +fun Level.timer(time: Int, ticker: Runnable): TickList.Timer? { + if (this.isClientSide) return null + + if (!SERVER_IS_LIVE) { + LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping")) + return null + } + + return postWorldTick.computeIfAbsent(this) { TickList() }.timer(time, ticker) +} + fun Level.once(ticker: ITickable) { if (this.isClientSide) return diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt index 10b22710f..c805360ac 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt @@ -56,6 +56,7 @@ import ru.dbotthepony.mc.otm.item.tool.ExplosiveHammerItem import ru.dbotthepony.mc.otm.item.armor.TritaniumArmorItem import ru.dbotthepony.mc.otm.item.QuantumBatteryItem import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem +import ru.dbotthepony.mc.otm.item.tool.RedstoneInteractorItem import ru.dbotthepony.mc.otm.matter.AbstractRegistryAction import ru.dbotthepony.mc.otm.matter.IMatterFunction import ru.dbotthepony.mc.otm.matter.MatterManager @@ -200,6 +201,8 @@ object OverdriveThatMatters { FORGE_BUS.addListener(EventPriority.NORMAL, MCommands::register) + FORGE_BUS.addListener(EventPriority.NORMAL, RedstoneInteractorItem::onUse) + if (isCuriosLoaded) { FORGE_BUS.addListener(EventPriority.NORMAL, ::onCuriosSlotModifiersUpdated) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/ComputerTerminalBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/ComputerTerminalBlock.kt index 16fa1bcf5..c51b064ce 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/ComputerTerminalBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/ComputerTerminalBlock.kt @@ -32,6 +32,7 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.get import ru.dbotthepony.mc.otm.core.math.plus import ru.dbotthepony.mc.otm.core.set +import ru.dbotthepony.mc.otm.item.tool.RedstoneInteractorItem import ru.dbotthepony.mc.otm.shapes.BlockShapes class ComputerTerminalBlock(val color: DyeColor?) : RotatableMatteryBlock( @@ -44,7 +45,7 @@ class ComputerTerminalBlock(val color: DyeColor?) : RotatableMatteryBlock( private val shapes = getShapeForEachState(rotationProperty) { BlockShapes.COMPUTER_TERMINAL.rotateFromNorth(it[rotationProperty]).computeShape() } init { - registerDefaultState(defaultBlockState().set(BlockStateProperties.POWERED, false).set(TICKS, TickTimer.TICK_20)) + registerDefaultState(defaultBlockState().set(BlockStateProperties.POWERED, false).set(TICKS, RedstoneInteractorItem.TickTimer.TICK_20)) } override fun createBlockStateDefinition(builder: StateDefinition.Builder) { @@ -86,9 +87,9 @@ class ComputerTerminalBlock(val color: DyeColor?) : RotatableMatteryBlock( ): InteractionResult { if (ply.isShiftKeyDown) { val current = blockState[TICKS] - val next = TickTimer.entries.getOrElse(current.ordinal + 1) { TickTimer.TICK_2 } + val next = RedstoneInteractorItem.TickTimer.entries.getOrElse(current.ordinal + 1) { RedstoneInteractorItem.TickTimer.TICK_2 } - level.playSound(ply, blockPos, SoundEvents.DISPENSER_FAIL, SoundSource.BLOCKS, 1f, 1f) + level.playSound(ply, blockPos, SoundEvents.DISPENSER_FAIL, SoundSource.BLOCKS, 0.3f, 1.1f) level.gameEvent(ply, GameEvent.BLOCK_ACTIVATE, blockPos) if (!level.isClientSide) { @@ -141,21 +142,7 @@ class ComputerTerminalBlock(val color: DyeColor?) : RotatableMatteryBlock( return shapes[state]!! } - enum class TickTimer(val ticks: Int) : StringRepresentable { - TICK_2(2), - TICK_10(10), - TICK_20(20), - TICK_30(30), - TICK_40(40); - - private val str = ticks.toString() - - override fun getSerializedName(): String { - return str - } - } - companion object { - val TICKS: EnumProperty = EnumProperty.create("ticks", TickTimer::class.java) + val TICKS: EnumProperty = EnumProperty.create("ticks", RedstoneInteractorItem.TickTimer::class.java) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt index 4b8c244ab..3077e2350 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt @@ -19,12 +19,9 @@ class TickList : ITickable { private var nextSometime = 0 - inner class Timer(val timerTicks: Int, val runnable: Runnable) : Comparable { + inner class Timer(timerTicks: Int, private var runnable: Runnable?) : Comparable { val ringAt = ticks + timerTicks - var finished = false - private set - init { timers.add(this) } @@ -33,10 +30,14 @@ class TickList : ITickable { return ringAt.compareTo(other.ringAt) } + fun cancel() { + runnable = null + timers.remove(this) + } + fun execute() { - if (finished) return - runnable.run() - finished = true + runnable?.run() + runnable = null } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/tool/RedstoneInteractorItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/tool/RedstoneInteractorItem.kt new file mode 100644 index 000000000..76b313dd3 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/tool/RedstoneInteractorItem.kt @@ -0,0 +1,132 @@ +package ru.dbotthepony.mc.otm.item.tool + +import com.mojang.serialization.Codec +import net.minecraft.ChatFormatting +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.sounds.SoundEvents +import net.minecraft.sounds.SoundSource +import net.minecraft.util.StringRepresentable +import net.minecraft.world.InteractionHand +import net.minecraft.world.InteractionResult +import net.minecraft.world.InteractionResultHolder +import net.minecraft.world.ItemInteractionResult +import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.context.UseOnContext +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.gameevent.GameEvent +import net.neoforged.neoforge.event.entity.player.UseItemOnBlockEvent +import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.core.math.component1 +import ru.dbotthepony.mc.otm.core.math.component2 +import ru.dbotthepony.mc.otm.core.math.component3 +import ru.dbotthepony.mc.otm.core.math.plus +import ru.dbotthepony.mc.otm.core.util.TickList +import ru.dbotthepony.mc.otm.item.MatteryItem +import ru.dbotthepony.mc.otm.registry.MDataComponentTypes +import ru.dbotthepony.mc.otm.timer +import java.util.* + +class RedstoneInteractorItem : MatteryItem(Properties().stacksTo(1)) { + init { + tooltips.add { TranslatableComponent("$descriptionId.desc").withStyle(ChatFormatting.GRAY) } + tooltips.add { TranslatableComponent("$descriptionId.desc1").withStyle(ChatFormatting.GRAY) } + tooltips.add { TranslatableComponent("$descriptionId.desc2").withStyle(ChatFormatting.GRAY) } + } + + private fun updateTickTimer(level: Level, player: Player, itemStack: ItemStack) { + val current = itemStack[MDataComponentTypes.TICK_TIMER] ?: TickTimer.TICK_30 + val next = TickTimer.entries.getOrElse(current.ordinal + 1) { RedstoneInteractorItem.TickTimer.TICK_2 } + + if (level.isClientSide) { + player.sendSystemMessage(TranslatableComponent("otm.gui.tick_timer_set", next.ticks.toString())) + // play sound in front of player so it sounds properly with HRTF enabled + val (x, y, z) = player.getEyePosition(1f) + player.getViewVector(1f) + level.playSound(player, x, y, z, SoundEvents.DISPENSER_FAIL, SoundSource.PLAYERS, 0.1f, 1.1f) + } + + itemStack[MDataComponentTypes.TICK_TIMER] = next + } + + override fun use(level: Level, player: Player, hand: InteractionHand): InteractionResultHolder { + if (player.isShiftKeyDown) { + val itemStack = player.getItemInHand(hand) + updateTickTimer(level, player, itemStack) + return InteractionResultHolder.success(itemStack) + } + + return super.use(level, player, hand) + } + + override fun useOn(context: UseOnContext): InteractionResult { + if (context.player?.isShiftKeyDown == true) { + updateTickTimer(context.level, context.player!!, context.itemInHand) + return InteractionResult.sidedSuccess(context.level.isClientSide()) + } + + context.level.playSound(context.player, context.clickedPos, SoundEvents.STONE_BUTTON_CLICK_ON, SoundSource.BLOCKS, 1f, 1f) + context.level.gameEvent(context.player, GameEvent.BLOCK_ACTIVATE, context.clickedPos) + + if (context.level.isClientSide) + return InteractionResult.SUCCESS + + val map = signals.computeIfAbsent(context.level) { HashMap() } + val positions = Direction.entries.map { context.clickedPos + it.normal }.toMutableList() + positions.add(context.clickedPos) + + for (pos in positions) { + val shouldSendUpdate = pos !in map + + val timer = context.level.timer(context.itemInHand.getOrDefault(MDataComponentTypes.TICK_TIMER, TickTimer.TICK_30).ticks) { + map.remove(pos) + context.level.updateNeighborsAt(pos, context.level.getBlockState(pos).block) + } ?: throw RuntimeException("Timer unexpectedly ended up being null") + + map.put(pos, timer)?.cancel() + + if (shouldSendUpdate) { + context.level.updateNeighborsAt(pos, context.level.getBlockState(pos).block) + } + } + + return InteractionResult.CONSUME + } + + enum class TickTimer(val ticks: Int) : StringRepresentable { + TICK_2(2), + TICK_10(10), + TICK_20(20), + TICK_30(30), + TICK_40(40); + + private val str = ticks.toString() + + override fun getSerializedName(): String { + return str + } + + companion object { + val CODEC: Codec = StringRepresentable.fromEnum(TickTimer::values) + } + } + + companion object { + private val signals = WeakHashMap>() + + fun getSignalHook(level: Level, blockState: BlockState, blockPos: BlockPos, direction: Direction): Int { + if (signals[level]?.containsKey(blockPos) == true) + return 15 + + return -1 + } + + fun onUse(event: UseItemOnBlockEvent) { + if (event.itemStack.item is RedstoneInteractorItem) { + if ((event.itemStack.item as RedstoneInteractorItem).useOn(event.useOnContext).consumesAction()) + event.cancelWithResult(ItemInteractionResult.sidedSuccess(event.level.isClientSide())) + } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt index 5b6f57e45..730f28e94 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt @@ -167,6 +167,7 @@ private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) { energized(MItems.ENERGY_SWORD) + accept(MItems.REDSTONE_INTERACTOR) accept(MItems.EXPLOSIVE_HAMMER) accept(ItemStack(MItems.EXPLOSIVE_HAMMER).also { MItems.EXPLOSIVE_HAMMER.prime(it) }) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MDataComponentTypes.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MDataComponentTypes.kt index c015eca46..1a70a9b75 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MDataComponentTypes.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MDataComponentTypes.kt @@ -14,6 +14,7 @@ import ru.dbotthepony.mc.otm.capability.matter.PatternState import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.data.DecimalCodec +import ru.dbotthepony.mc.otm.item.tool.RedstoneInteractorItem import ru.dbotthepony.mc.otm.network.StreamCodecs import java.util.UUID @@ -60,6 +61,7 @@ object MDataComponentTypes { } val ITEM_FILTER: DataComponentType by registry.register("item_filter") { DataComponentType.builder().persistent(ItemFilter.CODEC).build() } + val TICK_TIMER: DataComponentType by registry.register("tick_timer") { DataComponentType.builder().persistent(RedstoneInteractorItem.TickTimer.CODEC).build() } val EXPERIENCE: DataComponentType by registry.register("experience") { DataComponentType.builder().persistent(Codec.LONG).networkSynchronized(StreamCodecs.LONG).build() } 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 dad58de9d..9032d1df8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt @@ -68,6 +68,7 @@ import ru.dbotthepony.mc.otm.item.matter.MatterDustItem import ru.dbotthepony.mc.otm.item.matter.PatternStorageItem import ru.dbotthepony.mc.otm.item.tool.ExplosiveHammerItem import ru.dbotthepony.mc.otm.item.tool.MatteryAxeItem +import ru.dbotthepony.mc.otm.item.tool.RedstoneInteractorItem import ru.dbotthepony.mc.otm.item.weapon.EnergySwordItem import java.util.function.Supplier @@ -320,6 +321,8 @@ object MItems { val TRITANIUM_INGOT_BLOCK: BlockItem by registry.register(MNames.TRITANIUM_INGOT_BLOCK) { BlockItem(MBlocks.TRITANIUM_INGOT_BLOCK, DEFAULT_PROPERTIES) } val TRITANIUM_BARS: BlockItem by registry.register(MNames.TRITANIUM_BARS) { BlockItem(MBlocks.TRITANIUM_BARS, DEFAULT_PROPERTIES) } + val REDSTONE_INTERACTOR: RedstoneInteractorItem by registry.register("redstone_interactor") { RedstoneInteractorItem() } + val ESSENCE_SERVO: EssenceServoItem by registry.register("essence_servo") { EssenceServoItem() } val ESSENCE_CAPSULE: EssenceCapsuleItem by registry.register("essence_capsule") { EssenceCapsuleItem(false) } val ESSENCE_DRIVE: EssenceCapsuleItem by registry.register("essence_drive") { EssenceCapsuleItem(true) } diff --git a/src/main/resources/overdrive_that_matters.mixins.json b/src/main/resources/overdrive_that_matters.mixins.json index 2e3093e58..934ead87e 100644 --- a/src/main/resources/overdrive_that_matters.mixins.json +++ b/src/main/resources/overdrive_that_matters.mixins.json @@ -17,7 +17,8 @@ "MixinPlayer", "HopperBlockEntityMixin", "DispenserBlockEntityMixin", - "GuiGraphicsMixin" + "GuiGraphicsMixin", + "BlockStateBaseMixin" ], "client": [ "MixinGameRenderer",