Skip to content

Commit

Permalink
Sack Item Autocomplete
Browse files Browse the repository at this point in the history
  • Loading branch information
AzureAaron committed Nov 22, 2024
1 parent 96d7cc8 commit b8ed605
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;

import de.hysky.skyblocker.skyblock.SackItemAutocomplete;
import de.hysky.skyblocker.skyblock.WarpAutocomplete;
import de.hysky.skyblocker.utils.Utils;
import net.minecraft.command.CommandSource;
Expand All @@ -11,11 +13,18 @@

@Mixin(targets = "net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket$CommandTree")
public class CommandTreeS2CPacketMixin {
@ModifyExpressionValue(method = "getNode", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/CommandTreeS2CPacket$CommandTree;getNode(I)Lcom/mojang/brigadier/tree/CommandNode;", ordinal = 1))
public CommandNode<? extends CommandSource> modifyCommandSuggestions(CommandNode<CommandSource> original) {
if (Utils.isOnHypixel() && WarpAutocomplete.commandNode != null && original instanceof LiteralCommandNode<?> literalCommandNode && literalCommandNode.getLiteral().equals("warp")) {
return WarpAutocomplete.commandNode;
}
return original;
}
@ModifyExpressionValue(method = "getNode", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/CommandTreeS2CPacket$CommandTree;getNode(I)Lcom/mojang/brigadier/tree/CommandNode;", ordinal = 1))
public CommandNode<? extends CommandSource> modifyCommandSuggestions(CommandNode<CommandSource> original) {
if (Utils.isOnHypixel() && original instanceof LiteralCommandNode<?> literalCommandNode) {
return switch (literalCommandNode.getLiteral()) {
case String s when s.equals("warp") && WarpAutocomplete.commandNode != null -> WarpAutocomplete.commandNode;
case String s when s.equals("getfromsacks") && SackItemAutocomplete.longCommandNode != null -> SackItemAutocomplete.longCommandNode;
case String s when s.equals("gfs") && SackItemAutocomplete.shortCommandNode != null -> SackItemAutocomplete.shortCommandNode;

default -> original;
};
}

return original;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package de.hysky.skyblocker.skyblock;

import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;

import java.io.InputStream;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.logging.LogUtils;

import de.hysky.skyblocker.annotations.Init;
import de.hysky.skyblocker.utils.NEURepoManager;
import de.hysky.skyblocker.utils.Utils;
import io.github.moulberry.repo.data.NEUItem;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.command.CommandSource;
import net.minecraft.util.Formatting;

public class SackItemAutocomplete {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Pattern BAD_CHARACTERS = Pattern.compile("[α☘☠✎✧❁❂❈❤⸕]");

@Nullable
public static LiteralCommandNode<FabricClientCommandSource> longCommandNode;
@Nullable
public static LiteralCommandNode<FabricClientCommandSource> shortCommandNode;

@Init
public static void init() {
NEURepoManager.runAsyncAfterLoad(SackItemAutocomplete::loadSackItems);
}

private static void loadSackItems() {
try (InputStream stream = NEURepoManager.NEU_REPO.file("constants/sacks.json").stream()) {
JsonObject sacks = JsonParser.parseString(new String(stream.readAllBytes())).getAsJsonObject().getAsJsonObject("sacks");

Set<String> sackItemIds = sacks.entrySet().stream()
.map(entry -> entry.getValue().getAsJsonObject())
.map(sack -> sack.getAsJsonArray("contents"))
.map(JsonArray::asList)
.flatMap(List::stream)
.map(JsonElement::getAsString)
.collect(Collectors.toUnmodifiableSet());
Set<String> sackItems = sackItemIds.stream()
.map(neuId -> {
NEUItem stack = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(neuId);

return stack != null ? Formatting.strip(stack.getDisplayName()) : neuId;
})
.map(name -> BAD_CHARACTERS.matcher(name).replaceAll("").trim())
.collect(Collectors.toUnmodifiableSet());

longCommandNode = createCommandNode("getfromsacks", sackItems);
shortCommandNode = createCommandNode("gfs", sackItems);
} catch (Exception e) {
LOGGER.error("[Skyblocker Sack Item Autocomplete] Failed to load sacks data from the NEU Repo.", e);
}
}

private static LiteralCommandNode<FabricClientCommandSource> createCommandNode(String command, Set<String> sackItems) {
return literal(command)
.requires(fccs -> Utils.isOnSkyblock())
.then(argument("item", StringArgumentType.greedyString()) //I guess this can also cover the input of the amount
.suggests((context, builder) -> CommandSource.suggestMatching(sackItems, builder)))
.build();
}
}

0 comments on commit b8ed605

Please sign in to comment.