Skip to content

Commit

Permalink
Merge pull request #238 from AzureAaron/armour-trims
Browse files Browse the repository at this point in the history
Custom Armour Trims
  • Loading branch information
Aaron committed Aug 15, 2023
2 parents ada74ef + 99b3c44 commit 5fb9f5b
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 22 deletions.
2 changes: 2 additions & 0 deletions src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import me.xmrvizzy.skyblocker.skyblock.dungeon.LividColor;
import me.xmrvizzy.skyblocker.skyblock.dwarven.DwarvenHud;
import me.xmrvizzy.skyblocker.skyblock.item.CustomArmorDyeColors;
import me.xmrvizzy.skyblocker.skyblock.item.CustomArmorTrims;
import me.xmrvizzy.skyblocker.skyblock.item.CustomItemNames;
import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip;
import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup;
Expand Down Expand Up @@ -92,6 +93,7 @@ public void onInitializeClient() {
TeleportOverlay.init();
CustomItemNames.init();
CustomArmorDyeColors.init();
CustomArmorTrims.init();
containerSolverManager.init();
scheduler.scheduleCyclic(Utils::update, 20);
scheduler.scheduleCyclic(DiscordRPCManager::updateDataAndPresence, 100);
Expand Down
28 changes: 17 additions & 11 deletions src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package me.xmrvizzy.skyblocker.config;

import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import me.shedaniel.autoconfig.AutoConfig;
import me.shedaniel.autoconfig.ConfigData;
import me.shedaniel.autoconfig.annotation.Config;
Expand All @@ -14,12 +13,14 @@
import me.shedaniel.autoconfig.serializer.GsonConfigSerializer;
import me.xmrvizzy.skyblocker.SkyblockerMod;
import me.xmrvizzy.skyblocker.chat.ChatFilterResult;
import me.xmrvizzy.skyblocker.skyblock.item.CustomArmorTrims;
import me.xmrvizzy.skyblocker.utils.Scheduler;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -196,10 +197,15 @@ public static class General {

@ConfigEntry.Gui.Excluded
public List<Integer> lockedSlots = new ArrayList<>();


@ConfigEntry.Gui.Excluded
public Object2ObjectOpenHashMap<String, Text> customItemNames = new Object2ObjectOpenHashMap<>();


@ConfigEntry.Gui.Excluded
public Object2IntOpenHashMap<String> customDyeColors = new Object2IntOpenHashMap<>();

@ConfigEntry.Gui.Excluded
public Object2ObjectOpenHashMap<String, CustomArmorTrims.ArmorTrimId> customArmorTrims = new Object2ObjectOpenHashMap<>();
}

public static class TabHudConf {
Expand All @@ -213,11 +219,10 @@ public static class TabHudConf {
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
@ConfigEntry.Gui.Tooltip
public NameSorting nameSorting = NameSorting.DEFAULT;

}

public enum NameSorting {
DEFAULT,
DEFAULT,
ALPHABETICAL;

@Override
Expand Down Expand Up @@ -549,10 +554,11 @@ public static void init() {
.setPrettyPrinting()
.registerTypeHierarchyAdapter(Text.class, new Text.Serializer())
.registerTypeHierarchyAdapter(Style.class, new Style.Serializer())
.registerTypeHierarchyAdapter(Identifier.class, new Identifier.Serializer())
.create();

ConfigSerializer.Factory<SkyblockerConfig> serializer = (cfg, cfgClass) -> new GsonConfigSerializer<>(cfg, cfgClass, gson);

AutoConfig.register(SkyblockerConfig.class, serializer);
ClientCommandRegistrationCallback.EVENT.register(((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(optionsLiteral("config")).then(optionsLiteral("options")))));
}
Expand All @@ -571,7 +577,7 @@ private static LiteralArgumentBuilder<FabricClientCommandSource> optionsLiteral(
public static SkyblockerConfig get() {
return AutoConfig.getConfigHolder(SkyblockerConfig.class).getConfig();
}

public static void save() {
AutoConfig.getConfigHolder(SkyblockerConfig.class).save();
}
Expand Down
37 changes: 37 additions & 0 deletions src/main/java/me/xmrvizzy/skyblocker/mixin/ArmorTrimMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package me.xmrvizzy.skyblocker.mixin;

import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
import me.xmrvizzy.skyblocker.skyblock.item.CustomArmorTrims;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.minecraft.item.ItemStack;
import net.minecraft.item.trim.ArmorTrim;
import net.minecraft.nbt.NbtCompound;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

import java.util.Optional;

@Mixin(ArmorTrim.class)
public class ArmorTrimMixin {

@ModifyReturnValue(method = "getTrim", at = @At("RETURN"))
private static Optional<ArmorTrim> skyblocker$customArmorTrims(@SuppressWarnings("OptionalUsedAsFieldOrParameterType") Optional<ArmorTrim> original, @Local ItemStack stack) {
NbtCompound nbt = stack.getNbt();

if (Utils.isOnSkyblock() && nbt != null && nbt.contains("ExtraAttributes")) {
Object2ObjectOpenHashMap<String, CustomArmorTrims.ArmorTrimId> customTrims = SkyblockerConfig.get().general.customArmorTrims;
NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes");
String itemUuid = extraAttributes.contains("uuid") ? extraAttributes.getString("uuid") : null;

if (customTrims.containsKey(itemUuid)) {
CustomArmorTrims.ArmorTrimId trimKey = customTrims.get(itemUuid);
return CustomArmorTrims.TRIMS_CACHE.getOrDefault(trimKey, original);
}
}

return original;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.item.DyeableArmorItem;
import net.minecraft.item.DyeableItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.Text;
Expand All @@ -22,10 +22,11 @@ public static void init() {

private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
dispatcher.register(ClientCommandManager.literal("skyblocker")
.then(ClientCommandManager.literal("dyeColor")
.executes(context -> customizeDyeColor(context.getSource(), null))
.then(ClientCommandManager.argument("hexCode", StringArgumentType.string())
.executes(context -> customizeDyeColor(context.getSource(), StringArgumentType.getString(context, "hexCode"))))));
.then(ClientCommandManager.literal("custom")
.then(ClientCommandManager.literal("dyeColor")
.executes(context -> customizeDyeColor(context.getSource(), null))
.then(ClientCommandManager.argument("hexCode", StringArgumentType.string())
.executes(context -> customizeDyeColor(context.getSource(), StringArgumentType.getString(context, "hexCode")))))));
}

@SuppressWarnings("SameReturnValue")
Expand All @@ -39,7 +40,7 @@ private static int customizeDyeColor(FabricClientCommandSource source, String he
}

if (Utils.isOnSkyblock() && heldItem != null) {
if (heldItem.getItem() instanceof DyeableArmorItem) {
if (heldItem.getItem() instanceof DyeableItem) {
if (nbt != null && nbt.contains("ExtraAttributes")) {
NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes");
String itemUuid = extraAttributes.contains("uuid") ? extraAttributes.getString("uuid") : null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package me.xmrvizzy.skyblocker.skyblock.item;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
import me.xmrvizzy.skyblocker.utils.SkyblockEvents;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource;
import net.minecraft.command.argument.IdentifierArgumentType;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.trim.ArmorTrim;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtOps;
import net.minecraft.registry.*;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;

public class CustomArmorTrims {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomArmorTrims.class);
public static final Object2ObjectOpenHashMap<ArmorTrimId, Optional<ArmorTrim>> TRIMS_CACHE = new Object2ObjectOpenHashMap<>();
private static boolean trimsInitialized = false;

public static void init() {
SkyblockEvents.JOIN.register(CustomArmorTrims::initializeTrimCache);
ClientCommandRegistrationCallback.EVENT.register(CustomArmorTrims::registerCommand);
}

private static void initializeTrimCache() {
ClientPlayerEntity player = MinecraftClient.getInstance().player;
if (!trimsInitialized && player != null) {
TRIMS_CACHE.clear();
DynamicRegistryManager registryManager = player.networkHandler.getRegistryManager();
for (Identifier material : registryManager.get(RegistryKeys.TRIM_MATERIAL).getIds()) {
for (Identifier pattern : registryManager.get(RegistryKeys.TRIM_PATTERN).getIds()) {
NbtCompound compound = new NbtCompound();
compound.putString("material", material.toString());
compound.putString("pattern", pattern.toString());

ArmorTrim trim = ArmorTrim.CODEC.parse(RegistryOps.of(NbtOps.INSTANCE, registryManager), compound).resultOrPartial(LOGGER::error).orElse(null);

// Something went terribly wrong
if (trim == null) throw new IllegalStateException("Trim shouldn't be null! [" + "\"" + material + "\",\"" + pattern + "\"]");

TRIMS_CACHE.put(new ArmorTrimId(material, pattern), Optional.of(trim));
}
}

LOGGER.info("[Skyblocker] Successfully cached all armor trims!");
trimsInitialized = true;
}
}

private static void registerCommand(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
dispatcher.register(ClientCommandManager.literal("skyblocker")
.then(ClientCommandManager.literal("custom")
.then(ClientCommandManager.literal("armorTrim")
.executes(context -> customizeTrim(context.getSource(), null, null))
.then(ClientCommandManager.argument("material", IdentifierArgumentType.identifier())
.suggests(getIdSuggestionProvider(RegistryKeys.TRIM_MATERIAL))
.executes(context -> customizeTrim(context.getSource(), context.getArgument("material", Identifier.class), null))
.then(ClientCommandManager.argument("pattern", IdentifierArgumentType.identifier())
.suggests(getIdSuggestionProvider(RegistryKeys.TRIM_PATTERN))
.executes(context -> customizeTrim(context.getSource(), context.getArgument("material", Identifier.class), context.getArgument("pattern", Identifier.class))))))));
}

@NotNull
private static SuggestionProvider<FabricClientCommandSource> getIdSuggestionProvider(RegistryKey<? extends Registry<?>> registryKey) {
return (context, builder) -> context.getSource().listIdSuggestions(registryKey, CommandSource.SuggestedIdType.ELEMENTS, builder, context);
}

@SuppressWarnings("SameReturnValue")
private static int customizeTrim(FabricClientCommandSource source, Identifier material, Identifier pattern) {
ItemStack heldItem = source.getPlayer().getMainHandStack();
NbtCompound nbt = (heldItem != null) ? heldItem.getNbt() : null;

if (Utils.isOnSkyblock() && heldItem != null) {
if (heldItem.getItem() instanceof ArmorItem) {
if (nbt != null && nbt.contains("ExtraAttributes")) {
NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes");
String itemUuid = extraAttributes.contains("uuid") ? extraAttributes.getString("uuid") : null;

if (itemUuid != null) {
Object2ObjectOpenHashMap<String, ArmorTrimId> customArmorTrims = SkyblockerConfig.get().general.customArmorTrims;

if (material == null && pattern == null) {
if (customArmorTrims.containsKey(itemUuid)) {
customArmorTrims.remove(itemUuid);
SkyblockerConfig.save();
source.sendFeedback(Text.translatable("skyblocker.customArmorTrims.removed"));
} else {
source.sendFeedback(Text.translatable("skyblocker.customArmorTrims.neverHad"));
}
} else {
// Ensure that the material & trim are valid
ArmorTrimId trimId = new ArmorTrimId(material, pattern);
if (TRIMS_CACHE.get(trimId) == null) {
source.sendError(Text.translatable("skyblocker.customArmorTrims.invalidMaterialOrPattern"));

return Command.SINGLE_SUCCESS;
}

customArmorTrims.put(itemUuid, trimId);
SkyblockerConfig.save();
source.sendFeedback(Text.translatable("skyblocker.customArmorTrims.added"));
}
} else {
source.sendError(Text.translatable("skyblocker.customArmorTrims.noItemUuid"));
}
}
} else {
source.sendError(Text.translatable("skyblocker.customArmorTrims.notAnArmorPiece"));
return Command.SINGLE_SUCCESS;
}
} else {
source.sendError(Text.translatable("skyblocker.customArmorTrims.unableToSetTrim"));
}

return Command.SINGLE_SUCCESS;
}

public record ArmorTrimId(Identifier material, Identifier pattern) implements Pair<Identifier, Identifier> {
@Override
public Identifier left() {
return material();
}

@Override
public Identifier right() {
return pattern();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import net.minecraft.command.argument.TextArgumentType;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.MutableText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;

public class CustomItemNames {
Expand All @@ -21,10 +23,11 @@ public static void init() {

private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
dispatcher.register(ClientCommandManager.literal("skyblocker")
.then(ClientCommandManager.literal("renameItem")
.executes(context -> renameItem(context.getSource(), null))
.then(ClientCommandManager.argument("textComponent", TextArgumentType.text())
.executes(context -> renameItem(context.getSource(), context.getArgument("textComponent", Text.class))))));
.then(ClientCommandManager.literal("custom")
.then(ClientCommandManager.literal("renameItem")
.executes(context -> renameItem(context.getSource(), null))
.then(ClientCommandManager.argument("textComponent", TextArgumentType.text())
.executes(context -> renameItem(context.getSource(), context.getArgument("textComponent", Text.class)))))));
}

@SuppressWarnings("SameReturnValue")
Expand All @@ -50,6 +53,11 @@ private static int renameItem(FabricClientCommandSource source, Text text) {
}
} else {
//If the text is provided then set the item's custom name to it

//Set italic to false if it hasn't been changed (or was already false)
Style currentStyle = text.getStyle();
((MutableText) text).setStyle(currentStyle.withItalic((currentStyle.isItalic() ? true : false)));

customItemNames.put(itemUuid, text);
SkyblockerConfig.save();
source.sendFeedback(Text.translatable("skyblocker.customItemNames.added"));
Expand Down
10 changes: 9 additions & 1 deletion src/main/resources/assets/skyblocker/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -306,5 +306,13 @@
"skyblocker.customDyeColors.neverHad": "§b[§6Skyblocker§b] §fThis item doesn't have a custom dye color set, but why not add one? ;)",
"skyblocker.customDyeColors.added": "§b[§6Skyblocker§b] §fSet a custom dye color for your currently held item!",
"skyblocker.customDyeColors.noItemUuid": "§b[§6Skyblocker§b] §cYou must be holding an item that has a uuid in order to set a custom dye color!",
"skyblocker.customDyeColors.unableToSetColor": "§b[§6Skyblocker§b] §cUnable to set a custom dye color :( (Are you in skyblock?)"
"skyblocker.customDyeColors.unableToSetColor": "§b[§6Skyblocker§b] §cUnable to set a custom dye color :( (Are you in skyblock?, are you holding an item?)",

"skyblocker.customArmorTrims.invalidMaterialOrPattern": "§b[§6Skyblocker§b] §cYou supplied either an invalid material, or an invalid trim pattern!",
"skyblocker.customArmorTrims.notAnArmorPiece": "§b[§6Skyblocker§b] §cThis item isn't an armor piece!",
"skyblocker.customArmorTrims.removed": "§b[§6Skyblocker§b] §fRemoved this item's custom armor trim.",
"skyblocker.customArmorTrims.neverHad": "§b[§6Skyblocker§b] §fThis item doesn't have a armor trim set, but why not add one? ;)",
"skyblocker.customArmorTrims.added": "§b[§6Skyblocker§b] §fSet a custom armor trim for your currently held item!",
"skyblocker.customArmorTrims.noItemUuid": "§b[§6Skyblocker§b] §cYou must be holding an item that has a uuid in order to set a custom armor trim!",
"skyblocker.customArmorTrims.unableToSetTrim": "§b[§6Skyblocker§b] §cUnable to set a custom armor trim :( (Are you in skyblock?, are you holding an item?)"
}
1 change: 1 addition & 0 deletions src/main/resources/skyblocker.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"package": "me.xmrvizzy.skyblocker.mixin",
"compatibilityLevel": "JAVA_17",
"client": [
"ArmorTrimMixin",
"ClientPlayerEntityMixin",
"ClientPlayNetworkHandlerMixin",
"DrawContextMixin",
Expand Down

0 comments on commit 5fb9f5b

Please sign in to comment.