diff --git a/build.gradle b/build.gradle index 6720eb236..1555a49a2 100644 --- a/build.gradle +++ b/build.gradle @@ -116,6 +116,8 @@ subprojects { dependencies { minecraft "com.mojang:minecraft:${minecraft_version}" + implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.3.5")) + // layered mappings - Mojmap names, parchment and QM docs and parameters mappings(loom.layered { it.parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip") diff --git a/common/build.gradle b/common/build.gradle index 62678b8f5..2cde51d93 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -23,7 +23,6 @@ sourceSets { dependencies { modImplementation("net.fabricmc:fabric-loader:${fabric_loader_version}") - implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.3.5")) implementation(annotationProcessor("com.github.bawnorton.mixinsquared:mixinsquared-fabric:0.3.7-beta.1")) implementation(("io.github.llamalad7:mixinextras-common:0.4.1")) diff --git a/common/src/main/java/org/valkyrienskies/clockwork/LinkedControllerClientHandlerMixinStorage.java b/common/src/main/java/org/valkyrienskies/clockwork/LinkedControllerClientHandlerMixinStorage.java new file mode 100644 index 000000000..36da7aa9e --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/clockwork/LinkedControllerClientHandlerMixinStorage.java @@ -0,0 +1,15 @@ +package org.valkyrienskies.clockwork; + +import net.minecraft.core.Direction; + +/** + * This rather sus class exists for the purpose of storing a public static variable (clicked face) + * to be set in MixinLinkedControllerItem and accessed from MixinLinkedControllerClientHandler + */ +public class LinkedControllerClientHandlerMixinStorage { + public static Direction face; + + public static void doNothing() { + System.out.println("I hate kotlin sometimes"); + } +} diff --git a/common/src/main/java/org/valkyrienskies/clockwork/mixin/content/flap_bearing/MixinLinkedControllerClientHandler.java b/common/src/main/java/org/valkyrienskies/clockwork/mixin/content/flap_bearing/MixinLinkedControllerClientHandler.java new file mode 100644 index 000000000..651423392 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/clockwork/mixin/content/flap_bearing/MixinLinkedControllerClientHandler.java @@ -0,0 +1,75 @@ +package org.valkyrienskies.clockwork.mixin.content.flap_bearing; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.simibubi.create.content.redstone.link.LinkBehaviour; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerClientHandler; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerItem; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import org.apache.commons.lang3.tuple.Pair; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Coerce; +import org.valkyrienskies.clockwork.ClockworkBlocks; +import org.valkyrienskies.clockwork.ClockworkPackets; +import org.valkyrienskies.clockwork.LinkedControllerClientHandlerMixinStorage; +import org.valkyrienskies.clockwork.content.contraptions.flap.smart_flap.FlapLinkedControllerBindPacket; + + +@Mixin(LinkedControllerClientHandler.class) +public class MixinLinkedControllerClientHandler { + + @Shadow + private static BlockPos selectedLocation; + + @WrapOperation( + method = "tick", + at = @At(value = "INVOKE", target = "Lcom/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour;get(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lcom/simibubi/create/foundation/blockEntity/behaviour/BehaviourType;)Lcom/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour;"), + remap = false + ) + private static T wrapGetBehaviour(BlockGetter be, BlockPos e, BehaviourType reader, Operation original) { + // Clockwork flap bearing will never return the LinkBehaviour create is wanting, since it's using a custom behaviour. + // However, we still have to pass a null check, hence the weird sus null LinkBehaviour. + if (!ClockworkBlocks.SMART_FLAP_BEARING.has(be.getBlockState(e))) return original.call(be, e, reader); + + // Just needs to be a not-null be behaviour to pass a null check + return (T) LinkBehaviour.receiver(null, Pair.of(null, null), null); + } + + + @WrapOperation( + method = "tick", + at = @At(value = "INVOKE", target = "Lme/pepperbell/simplenetworking/SimpleChannel;sendToServer(Lme/pepperbell/simplenetworking/C2SPacket;)V", ordinal = 3), + require = 0, + remap = false + ) + private static void wrapSendToServerFabric(@Coerce Object instance, @Coerce Object packet, Operation original, @Local LinkBehaviour l, @Local Integer button) { + wrapSendToServerCommon(instance, packet, original, l, button); + } + + @WrapOperation( + method = "tick", + at = @At(value = "INVOKE", target = "Lnet/minecraftforge/network/simple/SimpleChannel;sendToServer(Ljava/lang/Object;)V", ordinal = 3), + require = 0, + remap = false + ) + private static void wrapSendToServerForge(@Coerce Object instance, @Coerce Object packet, Operation original, @Local LinkBehaviour l, @Local Integer button) { + wrapSendToServerCommon(instance, packet, original, l, button); + } + + @Unique + private static void wrapSendToServerCommon(Object instance, Object packet, Operation original, LinkBehaviour l, Integer button) { + // No one else should be stupid enough to be passing in a LinkBehaviour with a null be + if (l.blockEntity != null) { + original.call(instance, packet); + return; + } + ClockworkPackets.sendToServer(new FlapLinkedControllerBindPacket(button, selectedLocation, LinkedControllerClientHandlerMixinStorage.face, LinkedControllerItem.class.getName())); + } +} diff --git a/common/src/main/java/org/valkyrienskies/clockwork/mixin/content/flap_bearing/MixinLinkedControllerItem.java b/common/src/main/java/org/valkyrienskies/clockwork/mixin/content/flap_bearing/MixinLinkedControllerItem.java new file mode 100644 index 000000000..0b385ffaf --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/clockwork/mixin/content/flap_bearing/MixinLinkedControllerItem.java @@ -0,0 +1,81 @@ +package org.valkyrienskies.clockwork.mixin.content.flap_bearing; + +import com.simibubi.create.content.redstone.link.controller.LinkedControllerClientHandler; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerItem; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import net.createmod.catnip.data.Iterate; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +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 org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.clockwork.ClockworkBlocks; +import org.valkyrienskies.clockwork.LinkedControllerClientHandlerMixinStorage; +import org.valkyrienskies.clockwork.content.contraptions.flap.dual_link.DualLinkBehaviour; +import org.valkyrienskies.clockwork.platform.PlatformUtils; + +import static org.valkyrienskies.clockwork.content.contraptions.flap.dual_link.DualLinkHandler.getFrontFacing; + +@Mixin(LinkedControllerItem.class) +public class MixinLinkedControllerItem { + @Shadow + private void toggleBindMode(BlockPos pos) {} + + @Unique + public Direction clickedFace = null; + + @Inject( + method = "onItemUseFirst", + at = @At("HEAD"), + remap = false, + cancellable = true + ) + private void injectStateCheck(ItemStack stack, UseOnContext ctx, CallbackInfoReturnable cir) { + // region Copied from beginning of create method + Player player = ctx.getPlayer(); + if (player == null) return; + Level world = ctx.getLevel(); + BlockPos pos = ctx.getClickedPos(); + BlockState hitState = world.getBlockState(pos); + // endregion + + if (!player.mayBuild()) return; + if (player.isShiftKeyDown()) return; + + if (ClockworkBlocks.SMART_FLAP_BEARING.has(hitState)) { + clickedFace = ctx.getClickedFace(); + + if (!(clickedFace == getFrontFacing(hitState) || clickedFace == getFrontFacing(hitState).getOpposite())) return; + + if (world.isClientSide) + PlatformUtils.getEnvExecutor(() -> () -> toggleBindMode(ctx.getClickedPos())); + player.getCooldowns() + .addCooldown((Item)(Object)this, 2); + cir.setReturnValue(InteractionResult.SUCCESS); + cir.cancel(); + } + + } + + @Inject( + method = "toggleBindMode", + at = @At("HEAD"), + remap = false + ) + private void injectToggleBindMode(BlockPos pos, CallbackInfo ci) { + LinkedControllerClientHandlerMixinStorage.face = clickedFace; + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkPackets.kt b/common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkPackets.kt index 0dec1d886..56bd8b433 100644 --- a/common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkPackets.kt +++ b/common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkPackets.kt @@ -6,6 +6,7 @@ import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Entity import net.minecraft.world.level.Level import org.valkyrienskies.clockwork.client.render.airpocket.AirpocketSyncPacket +import org.valkyrienskies.clockwork.content.contraptions.flap.smart_flap.FlapLinkedControllerBindPacket import org.valkyrienskies.clockwork.content.curiosities.altmeter.UpdateAltMeterPacket import org.valkyrienskies.clockwork.content.contraptions.phys.infuser.PhysicsInfuserSyncPacket import org.valkyrienskies.clockwork.content.contraptions.phys.slicker.SlickerAttachmentSyncPacket @@ -76,7 +77,9 @@ enum class ClockworkPackets( NODE_SYNC(KNodeSyncPacket::class.java, ::KNodeSyncPacket), UNIVERSAL_JOINT_ITEM_PACKET(UniversalJointItemPacket::class.java, ::UniversalJointItemPacket), - AIRPOCKET_SYNC_PACKET(AirpocketSyncPacket::class.java, ::AirpocketSyncPacket) + AIRPOCKET_SYNC_PACKET(AirpocketSyncPacket::class.java, ::AirpocketSyncPacket), + + FLAP_LINKED_CONTROLLER_BIND_PACKET(FlapLinkedControllerBindPacket::class.java, ::FlapLinkedControllerBindPacket), ; diff --git a/common/src/main/kotlin/org/valkyrienskies/clockwork/content/contraptions/flap/dual_link/DualLinkHandler.kt b/common/src/main/kotlin/org/valkyrienskies/clockwork/content/contraptions/flap/dual_link/DualLinkHandler.kt index 9c9b6ac84..2af9c8c98 100644 --- a/common/src/main/kotlin/org/valkyrienskies/clockwork/content/contraptions/flap/dual_link/DualLinkHandler.kt +++ b/common/src/main/kotlin/org/valkyrienskies/clockwork/content/contraptions/flap/dual_link/DualLinkHandler.kt @@ -51,13 +51,10 @@ object DualLinkHandler { if (!state.hasProperty(BlockStateProperties.FACING) || !state.hasProperty(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) return EventResult.pass() - val type: BehaviourType if (face == getFrontFacing(state)) type = DualLinkBehaviour.FRONT_TYPE else type = DualLinkBehaviour.BACK_TYPE - - val behaviour = BlockEntityBehaviour.get(world, pos, type) ?: return EventResult.pass() diff --git a/common/src/main/kotlin/org/valkyrienskies/clockwork/content/contraptions/flap/smart_flap/FlapLinkedControllerBindPacket.kt b/common/src/main/kotlin/org/valkyrienskies/clockwork/content/contraptions/flap/smart_flap/FlapLinkedControllerBindPacket.kt new file mode 100644 index 000000000..e59dd974d --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/clockwork/content/contraptions/flap/smart_flap/FlapLinkedControllerBindPacket.kt @@ -0,0 +1,75 @@ +package org.valkyrienskies.clockwork.content.contraptions.flap.smart_flap + +import com.simibubi.create.AllItems +import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler +import com.simibubi.create.content.redstone.link.controller.LinkedControllerItem +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.nbt.Tag +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.world.InteractionHand +import net.minecraft.world.item.ItemStack +import org.valkyrienskies.clockwork.LinkedControllerClientHandlerMixinStorage +import org.valkyrienskies.clockwork.LinkedControllerClientHandlerMixinStorage.doNothing +import org.valkyrienskies.clockwork.content.contraptions.flap.dual_link.DualLinkBehaviour +import org.valkyrienskies.clockwork.content.contraptions.flap.dual_link.DualLinkHandler.getFrontFacing +import org.valkyrienskies.clockwork.platform.api.network.C2SCWPacket +import org.valkyrienskies.clockwork.platform.api.network.ServerNetworkContext + +class FlapLinkedControllerBindPacket(var button: Int, var linkLocation: BlockPos, var face: Direction, var itemClassName: String): C2SCWPacket { + constructor(buffer: FriendlyByteBuf) : this(buffer.readVarInt(), buffer.readBlockPos(), buffer.readEnum(Direction::class.java), buffer.readUtf()) + + override fun write(buffer: FriendlyByteBuf) { + buffer.writeVarInt(button) + buffer.writeBlockPos(linkLocation) + buffer.writeEnum(face) + buffer.writeUtf(itemClassName) + } + + override fun handle(context: ServerNetworkContext) { + context.enqueueWork { + val player = context.sender + if (player.isSpectator) return@enqueueWork + + var controller = player.mainHandItem + + // We use reflection for this as a lazy way to use TweakedLinkedControllerItem instead of LinkedControllerItem + // (also we have to use reflection on it later anyway, so we might as well) + val itemClass = Class.forName(itemClassName) + + if (!itemClass.isInstance(controller.item)) { + controller = player.offhandItem + if (!itemClass.isInstance(controller.item)) return@enqueueWork + } + + doNothing() + + val getFrequencyItems = itemClass.getDeclaredMethod("getFrequencyItems", ItemStack::class.java) + + val frequencyItems = getFrequencyItems.invoke(null, controller) + + val type: BehaviourType = + if (face == getFrontFacing(player.level().getBlockState(linkLocation))) DualLinkBehaviour.FRONT_TYPE + else DualLinkBehaviour.BACK_TYPE + + val linkBehaviour = BlockEntityBehaviour.get(player.level(), linkLocation, type) ?: return@enqueueWork + + // For some BRAIN DEAD REASON, the package for ItemHandler in porting lib and ItemHandler in forge are DIFFERENT + // They don't even extend a common class, so I'm just using reflection because fuck it. + val setStackInSlot = frequencyItems::class.java.getDeclaredMethod("setStackInSlot", Integer::class.javaPrimitiveType, ItemStack::class.java) + val serializeNbt = frequencyItems::class.java.getDeclaredMethod("serializeNBT") + + linkBehaviour.networkKey + .forEachWithContext { f: RedstoneLinkNetworkHandler.Frequency, first: Boolean -> + setStackInSlot.invoke(frequencyItems, button * 2 + (if (first) 0 else 1), f.stack + .copy()) + } + + controller.tag!! + .put("Items", serializeNbt.invoke(frequencyItems) as Tag) + } + context.setPacketHandled(true) + } +} \ No newline at end of file diff --git a/common/src/main/resources/vs_clockwork-common.mixins.json b/common/src/main/resources/vs_clockwork-common.mixins.json index 8a23ff444..7033aee30 100644 --- a/common/src/main/resources/vs_clockwork-common.mixins.json +++ b/common/src/main/resources/vs_clockwork-common.mixins.json @@ -16,6 +16,8 @@ "content.blade.RepairItemRecipeMixin", "content.blade.SawBladeRecipeMixin", "content.exhaust.MixinAirCurrent", + "content.flap_bearing.MixinLinkedControllerClientHandler", + "content.flap_bearing.MixinLinkedControllerItem", "content.gas.MixinBacktankUtil", "content.gas.MixinComposterBlock", "content.gas_engine.MixinSteamEngineBlock", diff --git a/fabric/build.gradle b/fabric/build.gradle index 3ae98d0b5..98fc7886f 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -112,8 +112,9 @@ dependencies { exclude(group: "net.fabricmc.fabric-api") } - modCompileOnly("cc.tweaked:cc-tweaked-${minecraft_version}-fabric-api:${cc_version}") - //modRuntimeOnly("cc.tweaked:cc-tweaked-${minecraft_version}-fabric:${cc_version}") + + modCompileOnly("cc.tweaked:cc-tweaked-$minecraft_version-fabric-api:$cc_version") + modRuntimeOnly("cc.tweaked:cc-tweaked-$minecraft_version-fabric:$cc_version") //JEI //modRuntimeOnly("mezz.jei:jei-${minecraft_version}-fabric:${jei_version_fabric}") @@ -169,6 +170,7 @@ components.java { } } + publishing { publications { mavenFabric(MavenPublication) { diff --git a/forge/build.gradle b/forge/build.gradle index ac392d522..676f2c026 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -64,6 +64,18 @@ repositories { } } maven { url = "https://jitpack.io/" } + + exclusiveContent { + forRepository { + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + } + filter { + includeGroup "maven.modrinth" + } + } } } @@ -109,6 +121,7 @@ dependencies { modCompileOnly("dev.engine-room.flywheel:flywheel-forge-api-${minecraft_version}:${flywheel_forge_version}") modRuntimeOnly("dev.engine-room.flywheel:flywheel-forge-${minecraft_version}:${flywheel_forge_version}") + // JOML compileOnly("org.joml:joml:1.10.4") compileOnly("org.joml:joml-primitives:1.10.0") @@ -121,6 +134,9 @@ dependencies { modCompileOnly("cc.tweaked:cc-tweaked-$minecraft_version-forge-api:$cc_version") modRuntimeOnly("cc.tweaked:cc-tweaked-$minecraft_version-forge:$cc_version") + //modRuntimeOnly("maven.modrinth:create-connected:saiZ8AwJ") + modImplementation ("maven.modrinth:create-tweaked-controllers:aHqvR8LC") + //Spark profiler //modRuntimeOnly("maven.modrinth:spark:1.10.53-forge") diff --git a/forge/src/main/java/org/valkyrienskies/clockwork/forge/mixin/MixinTweakedLinkedControllerClientHandler.java b/forge/src/main/java/org/valkyrienskies/clockwork/forge/mixin/MixinTweakedLinkedControllerClientHandler.java new file mode 100644 index 000000000..0ebf657f3 --- /dev/null +++ b/forge/src/main/java/org/valkyrienskies/clockwork/forge/mixin/MixinTweakedLinkedControllerClientHandler.java @@ -0,0 +1,72 @@ +package org.valkyrienskies.clockwork.forge.mixin; + +import com.getitemfromblock.create_tweaked_controllers.controller.TweakedLinkedControllerClientHandler; +import com.getitemfromblock.create_tweaked_controllers.item.TweakedLinkedControllerItem; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.simibubi.create.content.redstone.link.LinkBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import org.apache.commons.lang3.tuple.Pair; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Coerce; +import org.valkyrienskies.clockwork.ClockworkBlocks; +import org.valkyrienskies.clockwork.ClockworkPackets; +import org.valkyrienskies.clockwork.LinkedControllerClientHandlerMixinStorage; +import org.valkyrienskies.clockwork.content.contraptions.flap.smart_flap.FlapLinkedControllerBindPacket; + +@Mixin(TweakedLinkedControllerClientHandler.class) +public class MixinTweakedLinkedControllerClientHandler { + @Shadow + private static BlockPos selectedLocation; + + @WrapOperation( + method = "tick", + at = @At(value = "INVOKE", target = "Lcom/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour;get(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lcom/simibubi/create/foundation/blockEntity/behaviour/BehaviourType;)Lcom/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour;"), + remap = false + ) + private static T wrapGetBehaviour(BlockGetter be, BlockPos e, BehaviourType reader, Operation original) { + // Clockwork flap bearing will never return the LinkBehaviour create is wanting, since it's using a custom behaviour. + // However, we still have to pass a null check, hence the weird sus null LinkBehaviour. + if (!ClockworkBlocks.SMART_FLAP_BEARING.has(be.getBlockState(e))) return original.call(be, e, reader); + + // Just needs to be a not-null be behaviour to pass a null check + return (T) LinkBehaviour.receiver(null, Pair.of(null, null), null); + } + + @WrapOperation( + method = "tick", + at = @At(value = "INVOKE", target = "Lnet/minecraftforge/network/simple/SimpleChannel;sendToServer(Ljava/lang/Object;)V", ordinal = 5), + require = 0, + remap = false + ) + private static void wrapSendToServerA(@Coerce Object instance, @Coerce Object packet, Operation original, @Local LinkBehaviour l, @Local int button) { + wrapSendToServerCommon(instance, packet, original, l, button); + } + + @WrapOperation( + method = "tick", + at = @At(value = "INVOKE", target = "Lnet/minecraftforge/network/simple/SimpleChannel;sendToServer(Ljava/lang/Object;)V", ordinal = 6), + require = 0, + remap = false + ) + private static void wrapSendToServerB(@Coerce Object instance, @Coerce Object packet, Operation original, @Local LinkBehaviour l, @Local(name = "a") int button) { + wrapSendToServerCommon(instance, packet, original, l, button+15); + } + + @Unique + private static void wrapSendToServerCommon(Object instance, Object packet, Operation original, LinkBehaviour l, Integer button) { + // No one else should be stupid enough to be passing in a LinkBehaviour with a null be + if (l.blockEntity != null) { + original.call(instance, packet); + return; + } + ClockworkPackets.sendToServer(new FlapLinkedControllerBindPacket(button, selectedLocation, LinkedControllerClientHandlerMixinStorage.face, TweakedLinkedControllerItem.class.getName())); + } +} diff --git a/forge/src/main/java/org/valkyrienskies/clockwork/forge/mixin/MixinTweakedLinkedControllerItem.java b/forge/src/main/java/org/valkyrienskies/clockwork/forge/mixin/MixinTweakedLinkedControllerItem.java new file mode 100644 index 000000000..6817a4737 --- /dev/null +++ b/forge/src/main/java/org/valkyrienskies/clockwork/forge/mixin/MixinTweakedLinkedControllerItem.java @@ -0,0 +1,75 @@ +package org.valkyrienskies.clockwork.forge.mixin; + +import com.getitemfromblock.create_tweaked_controllers.item.TweakedLinkedControllerItem; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +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 org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.clockwork.ClockworkBlocks; +import org.valkyrienskies.clockwork.LinkedControllerClientHandlerMixinStorage; +import org.valkyrienskies.clockwork.platform.PlatformUtils; + +import static org.valkyrienskies.clockwork.content.contraptions.flap.dual_link.DualLinkHandler.getFrontFacing; + +@Mixin(TweakedLinkedControllerItem.class) +public class MixinTweakedLinkedControllerItem { + @Shadow + private void toggleBindMode(BlockPos pos) {} + + @Unique + public Direction clickedFace = null; + + @Inject( + method = "onItemUseFirst", + at = @At("HEAD"), + remap = false, + cancellable = true + ) + private void injectStateCheck(ItemStack stack, UseOnContext ctx, CallbackInfoReturnable cir) { + // region Copied from beginning of create method + Player player = ctx.getPlayer(); + if (player == null) return; + Level world = ctx.getLevel(); + BlockPos pos = ctx.getClickedPos(); + BlockState hitState = world.getBlockState(pos); + // endregion + + if (!player.mayBuild()) return; + if (player.isShiftKeyDown()) return; + + if (ClockworkBlocks.SMART_FLAP_BEARING.has(hitState)) { + clickedFace = ctx.getClickedFace(); + + if (!(clickedFace == getFrontFacing(hitState) || clickedFace == getFrontFacing(hitState).getOpposite())) return; + + if (world.isClientSide) + PlatformUtils.getEnvExecutor(() -> () -> toggleBindMode(ctx.getClickedPos())); + player.getCooldowns() + .addCooldown((Item)(Object)this, 2); + cir.setReturnValue(InteractionResult.SUCCESS); + cir.cancel(); + } + + } + + @Inject( + method = "toggleBindMode", + at = @At("HEAD"), + remap = false + ) + private void injectToggleBindMode(BlockPos pos, CallbackInfo ci) { + LinkedControllerClientHandlerMixinStorage.face = clickedFace; + } +} diff --git a/forge/src/main/resources/vs_clockwork.mixins.json b/forge/src/main/resources/vs_clockwork.mixins.json index 69f9de14a..06343e39c 100644 --- a/forge/src/main/resources/vs_clockwork.mixins.json +++ b/forge/src/main/resources/vs_clockwork.mixins.json @@ -4,6 +4,8 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "MixinFireBlock", + "MixinTweakedLinkedControllerClientHandler", + "MixinTweakedLinkedControllerItem", "accessors.ItemAccessor" ], "client": [