Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ jobs:
build:
uses: JamCoreModding/.github/.github/workflows/mod.yml@main
with:
java-version: 21
java-version: 25
3 changes: 1 addition & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
- Sync slot sorting trigger preference (#26).
- Prevent double-syncs when updating preferences server side.
- Update to 26.1.x
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2025 Jamalam
Copyright 2026 Jamalam

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
17 changes: 4 additions & 13 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.13-SNAPSHOT" apply false
id "architectury-plugin" version "3.5-SNAPSHOT"
id "dev.architectury.loom-no-remap" version "1.14-SNAPSHOT" apply false
id "me.shedaniel.unified-publishing" version "0.1.+" apply false
id "com.github.breadmoirai.github-release" version "2.4.1"
}
Expand All @@ -22,7 +22,7 @@ if (System.getenv("GITHUB_TOKEN") != null) {
}

subprojects {
apply plugin: "dev.architectury.loom"
apply plugin: "dev.architectury.loom-no-remap"

loom {
silentMojangMappingsLicense()
Expand All @@ -48,10 +48,6 @@ subprojects {

dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
mappings loom.layered() {
officialMojangMappings()
parchment "org.parchmentmc.data:parchment-${libs.versions.parchment.minecraft.get()}:${libs.versions.parchment.asProvider().get()}@zip"
}
}
}

Expand All @@ -75,11 +71,6 @@ allprojects {
name = "Jamalam's Maven"
url = "https://maven.jamalam.tech/releases"
}

maven {
name = "ParchmentMC"
url = "https://maven.parchmentmc.org"
}
}

base {
Expand All @@ -88,7 +79,7 @@ allprojects {

tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
options.release = 21
options.release = 25
}

tasks.create("prepareWorkspace") {}
Expand Down
22 changes: 19 additions & 3 deletions common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,25 @@ loom {
}

dependencies {
modImplementation libs.fabric.loader
modImplementation libs.architectury.common
modImplementation libs.jamlib.common
implementation libs.fabric.loader
implementation libs.jamlib.common
}

tasks.register('mergedJar', Jar) {
from sourceSets.main.output
from sourceSets.client.output
archiveClassifier = 'merged'
}

configurations {
mergedElements {
canBeResolved = false
canBeConsumed = true
}
}

artifacts {
mergedElements tasks.mergedJar
}

tasks.processResources.dependsOn("updateServerTranslationsHelper")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package io.github.jamalam360.sort_it_out.client;

import dev.architectury.networking.NetworkManager;
import io.github.jamalam360.jamlib.config.ConfigExtensions;
import io.github.jamalam360.jamlib.config.ConfigManager;
import io.github.jamalam360.jamlib.api.config.ConfigExtensions;
import io.github.jamalam360.jamlib.api.config.ConfigManager;
import io.github.jamalam360.jamlib.api.network.Network;
import io.github.jamalam360.sort_it_out.network.BidirectionalUserPreferencesUpdatePacket;
import io.github.jamalam360.sort_it_out.SortItOut;
import io.github.jamalam360.sort_it_out.preference.UserPreferences;
Expand Down Expand Up @@ -52,12 +52,12 @@ public void afterSave() {
public void sync() {
if (this.shouldSync()) {
SortItOut.LOGGER.info("Sending updated preferences to server");
NetworkManager.sendToServer(new BidirectionalUserPreferencesUpdatePacket.C2S(this));
Network.sendToServer(BidirectionalUserPreferencesUpdatePacket.C2S.TYPE, new BidirectionalUserPreferencesUpdatePacket.C2S(this));
}
}

private boolean shouldSync() {
return NetworkManager.canServerReceive(BidirectionalUserPreferencesUpdatePacket.C2S.TYPE) && // Only send if the server has SIO installed
return Network.getServerCapability().canReceive(BidirectionalUserPreferencesUpdatePacket.C2S.TYPE) && // Only send if the server has SIO installed
Minecraft.getInstance().getSingleplayerServer() == null; // and we are not in single player or hosting a LAN server
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package io.github.jamalam360.sort_it_out.client;

import com.mojang.blaze3d.platform.InputConstants;
import dev.architectury.event.EventResult;
import dev.architectury.event.events.client.ClientCommandRegistrationEvent;
import dev.architectury.event.events.client.ClientGuiEvent;
import dev.architectury.event.events.client.ClientScreenInputEvent;
import dev.architectury.event.events.client.ClientTickEvent;
import dev.architectury.networking.NetworkManager;
import dev.architectury.registry.ReloadListenerRegistry;
import dev.architectury.registry.client.keymappings.KeyMappingRegistry;
import io.github.jamalam360.jamlib.config.ConfigManager;
import io.github.jamalam360.jamlib.events.client.ClientPlayLifecycleEvents;
import io.github.jamalam360.jamlib.api.config.ConfigManager;
import io.github.jamalam360.jamlib.api.network.Network;
import io.github.jamalam360.jamlib.api.pack.PackReloadListenerRegistry;
import io.github.jamalam360.jamlib.client.api.command.ClientCommandRegistrationEvent;
import io.github.jamalam360.jamlib.client.api.events.ClientConnectionEvents;
import io.github.jamalam360.jamlib.client.api.events.ClientContainerRenderEvents;
import io.github.jamalam360.jamlib.client.api.events.ClientLevelTickEvents;
import io.github.jamalam360.jamlib.client.api.keymapping.KeyMappingRegistry;
import io.github.jamalam360.jamlib.client.api.network.ClientNetworkEvents;
import io.github.jamalam360.sort_it_out.SortItOut;
import io.github.jamalam360.sort_it_out.client.button.ScreenSortButtonsLoader;
import io.github.jamalam360.sort_it_out.client.mixin.AbstractContainerScreenAccessor;
Expand All @@ -22,11 +20,8 @@
import io.github.jamalam360.sort_it_out.util.CreativeModeTabLookup;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.input.KeyEvent;
import net.minecraft.client.input.MouseButtonEvent;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
Expand All @@ -36,7 +31,7 @@
import net.minecraft.world.inventory.Slot;
import org.lwjgl.glfw.GLFW;

import static dev.architectury.event.events.client.ClientCommandRegistrationEvent.literal;
import static io.github.jamalam360.jamlib.client.api.command.ClientCommandBuilders.literal;

public class SortItOutClient {
public static final ConfigManager<Config> CONFIG = new ConfigManager<>(SortItOut.MOD_ID, "client_preferences", Config.class);
Expand All @@ -47,17 +42,15 @@ public class SortItOutClient {

public static void init() {
ServerUserPreferences.INSTANCE.setClientUserPreferences(CONFIG);
ReloadListenerRegistry.register(PackType.CLIENT_RESOURCES, ScreenSortButtonsLoader.INSTANCE, SortItOut.id("sort_button_reloader"));
PackReloadListenerRegistry.register(PackType.CLIENT_RESOURCES, SortItOut.id("sort_button_reloader"), ScreenSortButtonsLoader.INSTANCE);
sortKeyMapping = new KeyMapping("key.sort_it_out.sort", GLFW.GLFW_KEY_I, KeyMapping.Category.register(SortItOut.id("sort_it_out")));
KeyMappingRegistry.register(sortKeyMapping);
ClientTickEvent.CLIENT_LEVEL_POST.register(SortItOutClient::postLevelTick);
ClientPlayLifecycleEvents.JOIN.register((mc) -> CONFIG.get().sync());
ClientPlayLifecycleEvents.JOIN.register((mc) -> CreativeModeTabLookup.INSTANCE.buildLookup(mc.level));
ClientScreenInputEvent.KEY_RELEASED_PRE.register(SortItOutClient::keyReleased);
ClientScreenInputEvent.MOUSE_RELEASED_PRE.register(SortItOutClient::mouseReleased);
ClientGuiEvent.RENDER_CONTAINER_FOREGROUND.register(SortItOutClient::renderContainerForeground);
KeyMappingRegistry.register(sortKeyMapping, true);
ClientLevelTickEvents.POST_TICK.listen(SortItOutClient::postLevelTick);
ClientNetworkEvents.SERVER_CAPABILITIES_HANDSHAKE_COMPLETED.listen(() -> CONFIG.get().sync());
ClientConnectionEvents.CONNECT.listen((mc) -> CreativeModeTabLookup.INSTANCE.buildLookup(mc.level));
ClientContainerRenderEvents.RENDER_FOREGROUND.listen(SortItOutClient::renderContainerForeground);

NetworkManager.registerReceiver(NetworkManager.Side.S2C, BidirectionalUserPreferencesUpdatePacket.S2C.TYPE, BidirectionalUserPreferencesUpdatePacket.S2C.STREAM_CODEC, (prefs, ctx) -> {
Network.registerHandler(Network.Direction.CLIENT_BOUND, BidirectionalUserPreferencesUpdatePacket.S2C.TYPE, (ctx, prefs) -> {
justReceivedFromServer = true;
CONFIG.get().invertSorting = prefs.preferences().invertSorting;
CONFIG.get().slotSortingTrigger = prefs.preferences().slotSortingTrigger;
Expand All @@ -66,28 +59,28 @@ public static void init() {
SortItOut.LOGGER.info("Received updated preferences from server (via config-edit commands)");
});

ClientCommandRegistrationEvent.EVENT.register(((dispatcher, context) -> dispatcher.register(
ClientCommandRegistrationEvent.EVENT.listen(((dispatcher, context) -> dispatcher.register(
literal("sortitoutc")
.then(literal("toggle_force_client_sort")
.executes((ctx) -> {
isClientSortingForced = !isClientSortingForced;
ctx.getSource().arch$sendSuccess(() -> Component.literal("Client Sorting Forced: " + isClientSortingForced), false);
ctx.getSource().client$sendSuccess(Component.literal("Client Sorting Forced: " + isClientSortingForced));
return 0;
})
)
.then(literal("toggle_slot_index_debug_renderer")
.executes((ctx) -> {
isSlotIndexOverlayEnabled = !isSlotIndexOverlayEnabled;
ctx.getSource().arch$sendSuccess(() -> Component.literal("Slot Index Debug Overlay: " + isSlotIndexOverlayEnabled), false);
ctx.getSource().client$sendSuccess(Component.literal("Slot Index Debug Overlay: " + isSlotIndexOverlayEnabled));
return 0;
})
)
)));
}

public static void sortOnEitherSide(AbstractContainerMenu menu, Slot slot) {
if (NetworkManager.canServerReceive(C2SRequestSortPacket.TYPE) && !isClientSortingForced) {
NetworkManager.sendToServer(new C2SRequestSortPacket(menu.containerId, slot.index));
if (Network.getServerCapability().canReceive(C2SRequestSortPacket.TYPE) && !isClientSortingForced) {
Network.sendToServer(C2SRequestSortPacket.TYPE, new C2SRequestSortPacket(menu.containerId, slot.index));
} else if (!ClientSortWorker.INSTANCE.isWorking()) {
ContainerSorterUtil.sortWithSelectionSort(slot.container, new ClientSortableContainer(slot.container), CONFIG.get());
} else {
Expand All @@ -113,7 +106,7 @@ private static void postLevelTick(ClientLevel level) {
}
}

private static void renderContainerForeground(AbstractContainerScreen<?> screen, GuiGraphics graphics, int mouseX, int mouseY, float delta) {
private static void renderContainerForeground(AbstractContainerScreen<?> screen, GuiGraphicsExtractor graphics, int mouseX, int mouseY, double delta) {
if (isSlotIndexOverlayEnabled) {
Identifier type;

Expand All @@ -123,31 +116,12 @@ private static void renderContainerForeground(AbstractContainerScreen<?> screen,
type = null;
}

graphics.drawCenteredString(Minecraft.getInstance().font, "" + type, ((AbstractContainerScreenAccessor) screen).getImageWidth() / 2, -50, 0xFFFFFF);
graphics.drawCenteredString(Minecraft.getInstance().font, screen.getClass().getName(), ((AbstractContainerScreenAccessor) screen).getImageWidth() / 2, -40, 0xFFFFFF);
graphics.centeredText(Minecraft.getInstance().font, "" + type, ((AbstractContainerScreenAccessor) screen).getImageWidth() / 2, -50, 0xFFFFFF);
graphics.centeredText(Minecraft.getInstance().font, screen.getClass().getName(), ((AbstractContainerScreenAccessor) screen).getImageWidth() / 2, -40, 0xFFFFFF);

for (Slot slot : screen.getMenu().slots) {
graphics.drawString(Minecraft.getInstance().font, "" + slot.index, slot.x, slot.y, 0xFFFFFF);
graphics.text(Minecraft.getInstance().font, "" + slot.index, slot.x, slot.y, 0xFFFFFF);
}
}
}

// Make the keybind work in containers
private static EventResult keyReleased(Minecraft minecraft, Screen screen, KeyEvent ev) {
if (sortKeyMapping.matches(ev)) {
KeyMapping.click(InputConstants.Type.KEYSYM.getOrCreate(ev.key()));
return EventResult.interruptTrue();
}

return EventResult.pass();
}

private static EventResult mouseReleased(Minecraft minecraft, Screen screen, MouseButtonEvent ev) {
if (sortKeyMapping.matchesMouse(ev)) {
KeyMapping.click(InputConstants.Type.MOUSE.getOrCreate(ev.input()));
return EventResult.interruptTrue();
}

return EventResult.pass();
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
package io.github.jamalam360.sort_it_out.client.mixin;

import dev.architectury.networking.NetworkManager;
import io.github.jamalam360.jamlib.api.network.Network;
import io.github.jamalam360.sort_it_out.client.SortItOutClient;
import io.github.jamalam360.sort_it_out.client.button.ScreenSortButton;
import io.github.jamalam360.sort_it_out.client.button.ScreenSortButtonsLoader;
import io.github.jamalam360.sort_it_out.client.gui.SortButton;
import io.github.jamalam360.sort_it_out.network.BidirectionalUserPreferencesUpdatePacket;
import io.github.jamalam360.sort_it_out.util.AbstractContainerMenuMixinImpl;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
import net.minecraft.client.gui.screens.inventory.InventoryScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.ContainerInput;
import net.minecraft.world.inventory.Slot;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -40,6 +38,7 @@ public abstract class AbstractContainerScreenMixin extends Screen {

@Shadow @Final protected AbstractContainerMenu menu;

@Final
@Shadow protected int imageHeight;

@Unique
Expand All @@ -55,7 +54,6 @@ protected AbstractContainerScreenMixin(Component title) {
super(title);
}

@SuppressWarnings("ConstantValue")
@Inject(
method = "init",
at = @At("TAIL")
Expand All @@ -78,16 +76,16 @@ protected AbstractContainerScreenMixin(Component title) {
method = "slotClicked",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/multiplayer/MultiPlayerGameMode;handleInventoryMouseClick(IIILnet/minecraft/world/inventory/ClickType;Lnet/minecraft/world/entity/player/Player;)V"
target = "Lnet/minecraft/client/multiplayer/MultiPlayerGameMode;handleContainerInput(IIILnet/minecraft/world/inventory/ContainerInput;Lnet/minecraft/world/entity/player/Player;)V"
),
cancellable = true
)
private void sort_it_out$triggerSortOnMiddleClick(Slot slot, int slotId, int mouseButton, ClickType type, CallbackInfo ci) {
if (slotId < 0 || slotId >= this.menu.slots.size() || NetworkManager.canServerReceive(BidirectionalUserPreferencesUpdatePacket.C2S.TYPE)) {
private void sort_it_out$triggerSortOnMiddleClick(Slot slot, int slotId, int buttonNum, ContainerInput containerInput, CallbackInfo ci) {
if (slotId < 0 || slotId >= this.menu.slots.size() || Network.getServerCapability().canReceive(BidirectionalUserPreferencesUpdatePacket.C2S.TYPE)) {
return;
}

if (this.sort_it_out$impl.shouldSort(this.menu.getSlot(slotId), mouseButton, type, this.menu.getCarried(), Minecraft.getInstance().player)) {
if (this.sort_it_out$impl.shouldSort(this.menu.getSlot(slotId), buttonNum, containerInput, this.menu.getCarried(), Minecraft.getInstance().player)) {
SortItOutClient.sortOnEitherSide(this.menu, this.menu.getSlot(slotId));
ci.cancel();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import io.github.jamalam360.sort_it_out.SortItOut;
import net.minecraft.client.Minecraft;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.ContainerInput;
import net.minecraft.world.item.ItemStack;
import org.lwjgl.glfw.GLFW;

Expand All @@ -14,11 +14,11 @@ public record ClickAction(
ItemStack newCarriedItem
) {
public boolean execute(Minecraft minecraft) {
minecraft.gameMode.handleInventoryMouseClick(
minecraft.gameMode.handleContainerInput(
this.containerId(),
this.slotId(),
getPlaceButton(newSlotItem, newCarriedItem),
ClickType.PICKUP,
ContainerInput.PICKUP,
minecraft.player
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package io.github.jamalam360.sort_it_out;

import dev.architectury.event.events.common.LifecycleEvent;
import io.github.jamalam360.jamlib.JamLib;
import io.github.jamalam360.sort_it_out.command.SortItOutCommands;
import io.github.jamalam360.sort_it_out.network.PacketHandlers;
import io.github.jamalam360.sort_it_out.util.CreativeModeTabLookup;
import net.minecraft.network.protocol.game.ClientboundSoundPacket;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerPlayer;
Expand All @@ -23,19 +21,19 @@ public static void init() {
JamLib.checkForJarRenaming(SortItOut.class);
SortItOutCommands.register();
PacketHandlers.register();
LifecycleEvent.SERVER_STARTED.register((server) -> CreativeModeTabLookup.INSTANCE.buildLookup(server.overworld()));
// LifecycleEvent.SERVER_STARTED.register((server) -> CreativeModeTabLookup.INSTANCE.buildLookup(server.overworld()));
}

public static Identifier id(String path) {
return Identifier.fromNamespaceAndPath(MOD_ID, path);
}

public static void playSortSound(Player player) {
float vol = 0.4f + (0.5f * player.level().random.nextFloat());
float pitch = 0.75f + (0.5f * player.level().random.nextFloat());
float vol = 0.4f + (0.5f * player.level().getRandom().nextFloat());
float pitch = 0.75f + (0.5f * player.level().getRandom().nextFloat());

if (player instanceof ServerPlayer serverPlayer) {
serverPlayer.connection.send(new ClientboundSoundPacket(SoundEvents.UI_BUTTON_CLICK, SoundSource.BLOCKS, player.getX(), player.getY(), player.getZ(), vol, pitch, player.level().random.nextLong()));
serverPlayer.connection.send(new ClientboundSoundPacket(SoundEvents.UI_BUTTON_CLICK, SoundSource.BLOCKS, player.getX(), player.getY(), player.getZ(), vol, pitch, player.level().getRandom().nextLong()));
} else {
player.playSound(SoundEvents.UI_BUTTON_CLICK.value(), vol, pitch);
}
Expand Down
Loading
Loading