Skip to content

Commit

Permalink
feat: integration with Curios API on Forge
Browse files Browse the repository at this point in the history
part of #318
  • Loading branch information
RubixDev committed Mar 23, 2024
1 parent 5fc7ba2 commit 64c8723
Show file tree
Hide file tree
Showing 16 changed files with 1,091 additions and 1 deletion.
5 changes: 4 additions & 1 deletion common.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@ loom {
}

if (loader.isForge) {
forge.mixinConfigs = listOf("${props.mod_id}.mixins.json")
forge.mixinConfigs = listOf(
"${props.mod_id}.mixins.json",
"${props.mod_id}-forge.mixins.json",
)
// workaround for https://github.com/SpongePowered/Mixin/issues/560
// TODO: remove this when Mixin 0.8.6 is out or you find another proper fix
forge.useCustomMixin = false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package de.rubixdev.inventorio.mixin.forge.curios;

import com.llamalad7.mixinextras.sugar.Local;
import de.rubixdev.inventorio.integration.curios.ICuriosContainer;
import me.fallenbreath.conditionalmixin.api.annotation.Condition;
import me.fallenbreath.conditionalmixin.api.annotation.Restriction;
import net.minecraft.screen.ScreenHandler;
import net.minecraftforge.network.NetworkEvent;
import org.objectweb.asm.Opcodes;
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.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import top.theillusivec4.curios.common.network.client.CPacketScroll;

import java.util.function.Supplier;

@Restriction(require = @Condition("curios"))
@Mixin(CPacketScroll.class)
public abstract class CPacketScrollMixin {
@Shadow
private int index;

@Shadow
private int windowId;

@Inject(
method = "lambda$handle$0",
at = @At(value = "JUMP", opcode = Opcodes.IFEQ, shift = At.Shift.BEFORE, ordinal = 0),
slice = @Slice(
from = @At(
value = "FIELD",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;currentScreenHandler:Lnet/minecraft/screen/ScreenHandler;"
)
)
)
private static void inventorioScrollToIndex(
Supplier<NetworkEvent.Context> ctx,
CPacketScroll msg,
CallbackInfo ci,
@Local ScreenHandler container
) {
CPacketScrollMixin accessor = ((CPacketScrollMixin) (Object) msg);
// noinspection DataFlowIssue
if (container instanceof ICuriosContainer curiosContainer && container.syncId == accessor.windowId) {
curiosContainer.inventorio$scrollToIndex(accessor.index);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package de.rubixdev.inventorio.mixin.forge.curios;

import de.rubixdev.inventorio.integration.curios.ICuriosContainer;
import me.fallenbreath.conditionalmixin.api.annotation.Condition;
import me.fallenbreath.conditionalmixin.api.annotation.Restriction;
import net.minecraft.entity.player.PlayerEntity;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final;
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.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
import top.theillusivec4.curios.common.inventory.CurioStacksHandler;

@Restriction(require = @Condition("curios"))
@Mixin(CurioStacksHandler.class)
public class CurioStacksHandlerMixin {
@Shadow
@Final
private ICuriosItemHandler itemHandler;

@Inject(
method = "update",
at = @At(value = "JUMP", opcode = Opcodes.IFEQ, shift = At.Shift.BEFORE, ordinal = 0),
slice = @Slice(
from = @At(
value = "INVOKE",
target = "Lnet/minecraftforge/eventbus/api/IEventBus;post(Lnet/minecraftforge/eventbus/api/Event;)Z"
)
),
remap = false
)
private void inventorioResetSlots(CallbackInfo ci) {
if (
itemHandler.getWearer() instanceof PlayerEntity player
&& player.currentScreenHandler instanceof ICuriosContainer curiosContainer
) {
curiosContainer.inventorio$resetSlots();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package de.rubixdev.inventorio.mixin.forge.curios;

import de.rubixdev.inventorio.integration.curios.ICuriosContainer;
import me.fallenbreath.conditionalmixin.api.annotation.Condition;
import me.fallenbreath.conditionalmixin.api.annotation.Restriction;
import net.minecraft.server.network.ServerPlayerEntity;
import org.objectweb.asm.Opcodes;
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.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
import top.theillusivec4.curios.common.event.CuriosEventHandler;

@Restriction(require = @Condition("curios"))
@Mixin(CuriosEventHandler.class)
public class CuriosEventHandlerMixin {
@Inject(
method = "lambda$onDatapackSync$5",
at = @At(value = "JUMP", opcode = Opcodes.IFEQ, shift = At.Shift.BEFORE, ordinal = 0),
slice = @Slice(
from = @At(
value = "FIELD",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;currentScreenHandler:Lnet/minecraft/screen/ScreenHandler;"
)
)
)
private static void inventorioResetSlots2(ServerPlayerEntity player, ICuriosItemHandler handler, CallbackInfo ci) {
if (player.currentScreenHandler instanceof ICuriosContainer curiosContainer) {
curiosContainer.inventorio$resetSlots();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package de.rubixdev.inventorio.mixin.forge.curios;

import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import de.rubixdev.inventorio.integration.curios.ICuriosScreen;
import me.fallenbreath.conditionalmixin.api.annotation.Condition;
import me.fallenbreath.conditionalmixin.api.annotation.Restriction;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text;
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 top.theillusivec4.curios.common.inventory.CurioSlot;

@Restriction(require = @Condition("curios"))
@Mixin(HandledScreen.class)
public class HandledScreenMixin extends Screen {
protected HandledScreenMixin(Text title) {
super(title);
}

@ModifyReturnValue(method = "isPointOverSlot", at = @At("RETURN"))
private boolean dontRenderCuriosWhenClosed(boolean original, Slot slot) {
if (
this instanceof ICuriosScreen curiosScreen
&& slot instanceof CurioSlot
&& !curiosScreen.getInventorio$isCuriosOpen()
) {
return false;
}
return original;
}

@Inject(method = "drawSlot", at = @At("HEAD"), cancellable = true)
private void dontRenderCuriosWhenClosed(DrawContext context, Slot slot, CallbackInfo ci) {
if (
this instanceof ICuriosScreen curiosScreen
&& slot instanceof CurioSlot
&& !curiosScreen.getInventorio$isCuriosOpen()
) {
ci.cancel();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package de.rubixdev.inventorio.mixin.forge.curios;

import de.rubixdev.inventorio.integration.curios.ICuriosContainer;
import de.rubixdev.inventorio.integration.curios.InventorioScreenHandlerMixinHelper;
import de.rubixdev.inventorio.player.InventorioScreenHandler;
import me.fallenbreath.conditionalmixin.api.annotation.Condition;
import me.fallenbreath.conditionalmixin.api.annotation.Restriction;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.AbstractRecipeScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
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 top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;

@SuppressWarnings("UnresolvedMixinReference") // the Minecraft Dev plugin
// doesn't seem to like Kotlin
// target classes
@Restriction(require = @Condition("curios"))
@Mixin(InventorioScreenHandler.class)
public abstract class InventorioScreenHandlerMixin extends AbstractRecipeScreenHandler<CraftingInventory>
implements ICuriosContainer {
public InventorioScreenHandlerMixin(ScreenHandlerType<?> arg, int i) {
super(arg, i);
}

@SuppressWarnings("DataFlowIssue")
@Unique private final InventorioScreenHandler thiz = (InventorioScreenHandler) (AbstractRecipeScreenHandler<?>) this;

@Unique private InventorioScreenHandlerMixinHelper helper;

@Override
public void inventorio$resetSlots() {
helper.curios$resetSlots(thiz);
}

@Override
public void inventorio$scrollTo(float pos) {
helper.curios$scrollTo(thiz, pos);
}

@Override
public void inventorio$scrollToIndex(int indexIn) {
helper.curios$scrollToIndex(thiz, indexIn);
}

@Override
public boolean getInventorio$hasCosmeticColumn() { return helper.hasCosmeticColumn(); }

@Override
public boolean getInventorio$canScroll() { return helper.canScroll(); }

@Nullable @Override
public ICuriosItemHandler getInventorio$curiosHandler() { return helper.getCuriosHandler(); }

@Inject(method = "<init>(ILnet/minecraft/entity/player/PlayerInventory;)V", at = @At("RETURN"))
private void curios$init(int syncId, PlayerInventory inventory, CallbackInfo ci) {
helper = new InventorioScreenHandlerMixinHelper(thiz);
helper.curios$init(thiz);
}

@Inject(method = "setStackInSlot", at = @At("HEAD"), cancellable = true)
private void curios$setStackInSlot(int slot, int revision, ItemStack stack, CallbackInfo ci) {
helper.curios$setStackInSlot(thiz, slot, ci);
}

@Inject(method = "quickMoveInner", at = @At("HEAD"), cancellable = true)
private void curios$quickMoveInner(int sourceIndex, CallbackInfoReturnable<ItemStack> cir) {
helper.curios$quickMoveInner(thiz, sourceIndex, cir);
}
}
Loading

0 comments on commit 64c8723

Please sign in to comment.