Skip to content

Commit

Permalink
Add QuickShulker support
Browse files Browse the repository at this point in the history
This is client-side only, and likely works with older versions
A network desync may cause weirdness
Closes #19
  • Loading branch information
opekope2 committed Aug 28, 2023
1 parent d91ead3 commit 4c29b10
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 0 deletions.
16 changes: 16 additions & 0 deletions Extra/src/main/java/opekope2/optigui/extra/Util.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package opekope2.optigui.extra;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

public class Util {
private Util() {
}

public static <TKey, TValue> Map<TKey, TValue> buildMap(Consumer<Map<TKey, TValue>> mapFiller) {
Map<TKey, TValue> map = new HashMap<>();
mapFiller.accept(map);
return map;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package opekope2.optigui.extra.quickshulker;

import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import net.kyrptonaught.quickshulker.QuickShulkerMod;
import net.kyrptonaught.quickshulker.api.Util;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
import opekope2.lilac.api.registry.IRegistryLookup;
import opekope2.optigui.api.IOptiGuiApi;
import opekope2.optigui.api.interaction.IInteractionTarget;
import opekope2.optigui.api.interaction.IInteractor;
import opekope2.optigui.properties.impl.CommonProperties;
import opekope2.optigui.properties.impl.GeneralProperties;
import opekope2.optigui.properties.impl.IndependentProperties;

import java.time.LocalDate;
import java.util.function.Consumer;

public class QuickShulkerRightClickHandler implements ClientModInitializer, UseItemCallback {
private static final IInteractor interactor = IOptiGuiApi.getImplementation().getInteractor();
private static final IRegistryLookup lookup = IRegistryLookup.getInstance();
private static Consumer<Screen> screenChangeHandler = QuickShulkerRightClickHandler::dummyScreenConsumer;

@Override
public void onInitializeClient() {
UseItemCallback.EVENT.register(this);
}

@Override
public TypedActionResult<ItemStack> interact(PlayerEntity player, World world, Hand hand) {
ItemStack stack = player.getStackInHand(hand);
if (world.isClient) {
if (QuickShulkerMod.getConfig().rightClickToOpen && Util.isOpenableItem(stack) && Util.canOpenInHand(stack)) {
triggerInteraction(player, world, hand, stack);
}
}

return TypedActionResult.pass(stack);
}

public static void waitForScreen(Consumer<Screen> handler) {
screenChangeHandler = handler;
}

public static void onScreenChanged(Screen screen) {
screenChangeHandler.accept(screen);
screenChangeHandler = QuickShulkerRightClickHandler::dummyScreenConsumer;
}

private static void dummyScreenConsumer(Screen screen) {
}

public static void triggerInteraction(PlayerEntity player, World world, Hand hand, ItemStack stack) {
interactor.interact(
player,
world,
hand,
new IInteractionTarget.ComputedTarget(getInteractionTargetData(player, world, stack)),
null
);
}

private static Object getInteractionTargetData(PlayerEntity player, World world, ItemStack stack) {
Identifier biome = lookup.lookupBiomeId(world, player.getBlockPos());
String name = stack.hasCustomName() ? stack.getName().getString() : null;

return new CommonProperties(
new GeneralProperties(
Registries.ITEM.getId(stack.getItem()),
name,
biome,
player.getBlockY()
),
new IndependentProperties(
LocalDate.now()
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package opekope2.optigui.extra.quickshulker.mixin;

import net.kyrptonaught.quickshulker.client.ClientUtil;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.*;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import opekope2.lilac.api.registry.IRegistryLookup;
import opekope2.optigui.extra.Util;
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.CallbackInfoReturnable;

import java.util.Map;
import java.util.Objects;

import static opekope2.optigui.extra.quickshulker.QuickShulkerRightClickHandler.triggerInteraction;
import static opekope2.optigui.extra.quickshulker.QuickShulkerRightClickHandler.waitForScreen;

@Mixin(ClientUtil.class)
public abstract class ClientUtilMixin {
@Unique
private static final MinecraftClient mc = MinecraftClient.getInstance();
@Unique
private static final IRegistryLookup lookup = IRegistryLookup.getInstance();

@Unique
private static final Map<Identifier, Class<? extends HandledScreen<?>>> containerScreenMapping = Util.buildMap(map -> {
map.put(new Identifier("shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("white_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("orange_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("magenta_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("light_blue_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("yellow_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("lime_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("pink_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("gray_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("light_gray_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("cyan_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("purple_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("blue_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("brown_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("green_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("red_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("black_shulker_box"), ShulkerBoxScreen.class);
map.put(new Identifier("ender_chest"), GenericContainerScreen.class);
map.put(new Identifier("crafting_table"), CraftingScreen.class);
map.put(new Identifier("stonecutter"), StonecutterScreen.class);
map.put(new Identifier("smithing_table"), SmithingScreen.class);
});

@Inject(
method = "CheckAndSend",
at = @At(value = "INVOKE", target = "Lnet/kyrptonaught/quickshulker/client/ClientUtil;SendOpenPacket(I)V")
)
private static void handlePacketSendFromOffHand(ItemStack stack, int slot, CallbackInfoReturnable<Boolean> cir) {
var player = Objects.requireNonNull(mc.player);
var world = Objects.requireNonNull(mc.world);
var screenClass = containerScreenMapping.get(lookup.lookupItemId(stack.getItem()));
if (screenClass == null) return;

waitForScreen(screen -> {
if (screenClass.equals(screen.getClass())) {
triggerInteraction(player, world, stack == mc.player.getOffHandStack() ? Hand.OFF_HAND : Hand.MAIN_HAND, stack);
}
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package opekope2.optigui.extra.quickshulker.mixin;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import opekope2.optigui.extra.quickshulker.QuickShulkerRightClickHandler;
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;

@Mixin(value = MinecraftClient.class, priority = 925)
abstract class MinecraftClientMixin {
@Inject(method = "setScreen(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("TAIL"))
private void setScreenMixin(Screen screen, CallbackInfo ci) {
if (screen != null) {
QuickShulkerRightClickHandler.onScreenChanged(screen);
}
}
}
8 changes: 8 additions & 0 deletions Extra/src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
"license": "MIT",
"icon": "assets/optigui-extra/icon.png",
"environment": "client",
"entrypoints": {
"client": [
"opekope2.optigui.extra.quickshulker.QuickShulkerRightClickHandler"
]
},
"mixins": [
"optigui-extra.quickshulker.mixins.json"
],
"depends": {
"fabricloader": ">=${fabricloader}",
"fabric-events-interaction-v0": "*",
Expand Down
12 changes: 12 additions & 0 deletions Extra/src/main/resources/optigui-extra.quickshulker.mixins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"required": true,
"package": "opekope2.optigui.extra.quickshulker.mixin",
"compatibilityLevel": "JAVA_${java}",
"injectors": {
"defaultRequire": 1
},
"client": [
"ClientUtilMixin",
"MinecraftClientMixin"
]
}

0 comments on commit 4c29b10

Please sign in to comment.