diff --git a/README.md b/README.md index f402a69..8f02373 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,11 @@ Focusing only on server side for now. - Send events like advancements, join/leave, death, from the server to Discord. - Sync advancements completion, all players share the same advancement progress. - Discord commands to retrieve information about the server. -- Link items in the chat. +- Link items in the chat, via command or using `Left Shift + Alt` hovering over an item. ## TODO - Enable/disable modules, allow option to disable the relay but not the syncing. -- Maybe instead of appending to the save file, maybe rewrite it. - Maybe use a small database library for storage as it might be useful for other ideas. - Build system needs some work, shadowing is probably not done right, add sources to the artifacts. - Prevent toast from showing for synced players, at the moment the player that was synced will get a toast notification after completing the already completed advancement. diff --git a/common/src/main/java/com/cooptweaks/Client.java b/common/src/main/java/com/cooptweaks/Client.java new file mode 100644 index 0000000..c2f12e9 --- /dev/null +++ b/common/src/main/java/com/cooptweaks/Client.java @@ -0,0 +1,39 @@ +package com.cooptweaks; + +import com.cooptweaks.keybinds.misc.Link; +import dev.architectury.event.EventResult; +import dev.architectury.event.events.client.ClientScreenInputEvent; +import dev.architectury.platform.Platform; +import dev.architectury.registry.client.keymappings.KeyMappingRegistry; +import net.fabricmc.api.EnvType; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; + +public class Client { + public static final KeyBinding LINK_ITEM_KEY = new KeyBinding( + "key.cooptweaks.link_item", + InputUtil.Type.KEYSYM, + InputUtil.GLFW_KEY_LEFT_ALT, + "category.cooptweaks.misc" + ); + + public static void init() { + if (Platform.getEnv() != EnvType.CLIENT) { + return; + } + + KeyMappingRegistry.register(LINK_ITEM_KEY); + + ClientScreenInputEvent.KEY_RELEASED_POST.register((client, screen, key, scanCode, modifiers) -> { + if (screen instanceof HandledScreen) { + if (LINK_ITEM_KEY.matchesKey(key, scanCode) && Screen.hasShiftDown()) { + Link.sendPacket(client); + } + } + + return EventResult.pass(); + }); + } +} diff --git a/common/src/main/java/com/cooptweaks/Main.java b/common/src/main/java/com/cooptweaks/Main.java index c389516..b0e2e94 100644 --- a/common/src/main/java/com/cooptweaks/Main.java +++ b/common/src/main/java/com/cooptweaks/Main.java @@ -1,9 +1,12 @@ package com.cooptweaks; import com.cooptweaks.commands.advancements.Progress; -import com.cooptweaks.commands.misc.Link; +import com.cooptweaks.commands.misc.LinkCommand; +import com.cooptweaks.keybinds.misc.Link; +import com.cooptweaks.packets.LinkPacket; import dev.architectury.event.EventResult; import dev.architectury.event.events.common.*; +import dev.architectury.networking.NetworkManager; import net.minecraft.util.math.BlockPos; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -87,7 +90,9 @@ public static void init() { new Progress().register(dispatcher, registryAccess, environment); // Misc - new Link().register(dispatcher, registryAccess, environment); + new LinkCommand().register(dispatcher, registryAccess, environment); }); + + NetworkManager.registerReceiver(NetworkManager.Side.C2S, LinkPacket.PAYLOAD_ID, LinkPacket.CODEC, Link::handlePacket); } } diff --git a/common/src/main/java/com/cooptweaks/commands/misc/Link.java b/common/src/main/java/com/cooptweaks/commands/misc/LinkCommand.java similarity index 83% rename from common/src/main/java/com/cooptweaks/commands/misc/Link.java rename to common/src/main/java/com/cooptweaks/commands/misc/LinkCommand.java index 41d7c6e..ba69cfb 100644 --- a/common/src/main/java/com/cooptweaks/commands/misc/Link.java +++ b/common/src/main/java/com/cooptweaks/commands/misc/LinkCommand.java @@ -1,6 +1,7 @@ package com.cooptweaks.commands.misc; import com.cooptweaks.commands.ServerCommand; +import com.cooptweaks.keybinds.misc.Link; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; import net.minecraft.command.CommandRegistryAccess; @@ -8,10 +9,9 @@ import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.MutableText; import net.minecraft.text.Text; -public class Link implements ServerCommand { +public class LinkCommand implements ServerCommand { @Override public void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { dispatcher @@ -34,10 +34,7 @@ public int execute(CommandContext context) { return 1; } - MutableText text = Text.empty(); - text.append(player.getDisplayName()); - text.append(Text.literal(" linked ")); - text.append(item.toHoverableText()); + Text text = Link.getHoverableText(item.toHoverableText(), player.getDisplayName()); source.getServer().getPlayerManager().broadcast(text, false); return 0; diff --git a/common/src/main/java/com/cooptweaks/keybinds/misc/Link.java b/common/src/main/java/com/cooptweaks/keybinds/misc/Link.java new file mode 100644 index 0000000..29e1ea8 --- /dev/null +++ b/common/src/main/java/com/cooptweaks/keybinds/misc/Link.java @@ -0,0 +1,52 @@ +package com.cooptweaks.keybinds.misc; + +import com.cooptweaks.mixins.client.accessor.HandledScreenAccessor; +import com.cooptweaks.packets.LinkPacket; +import dev.architectury.networking.NetworkManager; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.slot.Slot; +import net.minecraft.server.MinecraftServer; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; + +public class Link { + public static void sendPacket(MinecraftClient client) { + if (client.player == null) { + return; + } + + if (client.currentScreen == null) { + return; + } + + Slot slot = ((HandledScreenAccessor) client.currentScreen).getFocusedSlot(); + + if (slot != null && slot.hasStack()) { + NetworkManager.sendToServer(new LinkPacket(slot.getStack())); + } + } + + public static void handlePacket(LinkPacket link, NetworkManager.PacketContext context) { + context.queue(() -> { + PlayerEntity player = context.getPlayer(); + MinecraftServer server = player.getServer(); + if (server == null) { + return; + } + + ItemStack stack = link.value(); + + server.getPlayerManager().broadcast(getHoverableText(stack.toHoverableText(), player.getDisplayName()), false); + }); + } + + public static Text getHoverableText(Text stack, Text player) { + MutableText text = Text.empty(); + text.append(player); + text.append(Text.literal(" linked ")); + text.append(stack); + return text; + } +} diff --git a/common/src/main/java/com/cooptweaks/mixins/client/accessor/HandledScreenAccessor.java b/common/src/main/java/com/cooptweaks/mixins/client/accessor/HandledScreenAccessor.java new file mode 100644 index 0000000..e6b2602 --- /dev/null +++ b/common/src/main/java/com/cooptweaks/mixins/client/accessor/HandledScreenAccessor.java @@ -0,0 +1,15 @@ +package com.cooptweaks.mixins.client.accessor; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.screen.slot.Slot; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Environment(EnvType.CLIENT) +@Mixin(HandledScreen.class) +public interface HandledScreenAccessor { + @Accessor("focusedSlot") + Slot getFocusedSlot(); +} diff --git a/common/src/main/java/com/cooptweaks/packets/LinkPacket.java b/common/src/main/java/com/cooptweaks/packets/LinkPacket.java new file mode 100644 index 0000000..9e274d1 --- /dev/null +++ b/common/src/main/java/com/cooptweaks/packets/LinkPacket.java @@ -0,0 +1,19 @@ +package com.cooptweaks.packets; + +import com.cooptweaks.Main; +import net.minecraft.item.ItemStack; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.packet.CustomPayload; +import net.minecraft.util.Identifier; + +public record LinkPacket(ItemStack value) implements CustomPayload { + private static final Identifier ID = Identifier.of(Main.MOD_ID, "link_item_packet"); + public static CustomPayload.Id PAYLOAD_ID = new Id<>(ID); + public static final PacketCodec CODEC = ItemStack.PACKET_CODEC.xmap(LinkPacket::new, LinkPacket::value).cast(); + + @Override + public Id getId() { + return PAYLOAD_ID; + } +} diff --git a/common/src/main/resources/assets/cooptweaks/lang/en_us.json b/common/src/main/resources/assets/cooptweaks/lang/en_us.json new file mode 100644 index 0000000..861d257 --- /dev/null +++ b/common/src/main/resources/assets/cooptweaks/lang/en_us.json @@ -0,0 +1,4 @@ +{ + "category.cooptweaks.misc": "Miscellaneous", + "key.cooptweaks.link_item": "Link Item" +} diff --git a/common/src/main/resources/cooptweaks.mixins.json b/common/src/main/resources/cooptweaks.mixins.json index 6b4f7d8..105bb22 100644 --- a/common/src/main/resources/cooptweaks.mixins.json +++ b/common/src/main/resources/cooptweaks.mixins.json @@ -4,6 +4,7 @@ "compatibilityLevel": "JAVA_21", "minVersion": "0.8", "client": [ + "client.accessor.HandledScreenAccessor" ], "mixins": [ "PlayerAdvancementTrackerMixin" diff --git a/fabric/src/main/java/com/cooptweaks/fabric/client/FabricClient.java b/fabric/src/main/java/com/cooptweaks/fabric/client/FabricClient.java index 67a2c27..ef02abc 100644 --- a/fabric/src/main/java/com/cooptweaks/fabric/client/FabricClient.java +++ b/fabric/src/main/java/com/cooptweaks/fabric/client/FabricClient.java @@ -1,9 +1,11 @@ package com.cooptweaks.fabric.client; +import com.cooptweaks.Client; import net.fabricmc.api.ClientModInitializer; public final class FabricClient implements ClientModInitializer { @Override public void onInitializeClient() { + Client.init(); } } diff --git a/neoforge/src/main/java/com/cooptweaks/neoforge/NeoForgeMain.java b/neoforge/src/main/java/com/cooptweaks/neoforge/NeoForgeMain.java index b2e40e9..5082788 100644 --- a/neoforge/src/main/java/com/cooptweaks/neoforge/NeoForgeMain.java +++ b/neoforge/src/main/java/com/cooptweaks/neoforge/NeoForgeMain.java @@ -1,11 +1,13 @@ package com.cooptweaks.neoforge; +import com.cooptweaks.Client; import com.cooptweaks.Main; import net.neoforged.fml.common.Mod; @Mod(Main.MOD_ID) public final class NeoForgeMain { public NeoForgeMain() { + Client.init(); Main.init(); } }