diff --git a/build.gradle b/build.gradle index 39fc1f5..a738863 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id 'org.ajoberstar.grgit' version '5.0.0' - id 'fabric-loom' version '1.6-SNAPSHOT' + id 'fabric-loom' version '1.7-SNAPSHOT' } base { diff --git a/gradle.properties b/gradle.properties index 64c088a..54accfb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,13 +1,13 @@ org.gradle.jvmargs=-Xmx4G # Fabric (https://fabricmc.net/versions.html) -minecraft_version=1.20.6 -yarn_mappings=1.20.6+build.1 -loader_version=0.15.10 +minecraft_version=1.21 +yarn_mappings=1.21+build.2 +loader_version=0.15.11 # Mod Properties -mod_version=1.4.5 +mod_version=1.4.6 maven_group=maxsuperman.addons archives_base_name=villager-roller -meteor_version=0.5.7-SNAPSHOT +meteor_version=0.5.8-SNAPSHOT diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23..a441313 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/maxsuperman/addons/roller/gui/screens/EnchantmentSelectScreen.java b/src/main/java/maxsuperman/addons/roller/gui/screens/EnchantmentSelectScreen.java index 0f11d09..ff75659 100644 --- a/src/main/java/maxsuperman/addons/roller/gui/screens/EnchantmentSelectScreen.java +++ b/src/main/java/maxsuperman/addons/roller/gui/screens/EnchantmentSelectScreen.java @@ -10,12 +10,16 @@ import meteordevelopment.meteorclient.utils.misc.Names; import net.minecraft.enchantment.Enchantment; import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.registry.tag.EnchantmentTags; import net.minecraft.util.Identifier; import java.util.List; +import static meteordevelopment.meteorclient.MeteorClient.mc; + public class EnchantmentSelectScreen extends WindowScreen { - private final List available = Registries.ENCHANTMENT.stream().filter(Enchantment::isAvailableForEnchantedBookOffer).toList(); private final GuiTheme theme; private final EnchantmentSelectCallback callback; private String filterText = ""; @@ -61,14 +65,24 @@ public void initWidgets() { } private void fillTable(WTable table) { - for (Enchantment e : available.stream().sorted((o1, o2) -> Names.get(o1).compareToIgnoreCase(Names.get(o2))).toList()) { + if (mc.world == null) { + return; + } + var reg = mc.world.getRegistryManager().get(RegistryKeys.ENCHANTMENT); + List> available; + var l = reg.getEntryList(EnchantmentTags.TRADEABLE); + if (l.isEmpty()) { + return; + } + available = l.get().stream().toList(); + for (RegistryEntry e : available.stream().sorted((o1, o2) -> Names.get(o1).compareToIgnoreCase(Names.get(o2))).toList()) { if (!filterText.isEmpty() && !Names.get(e).toLowerCase().startsWith(filterText.toLowerCase())) { continue; } table.add(theme.label(Names.get(e))).expandCellX(); WButton a = table.add(theme.button("Select")).widget(); a.action = () -> { - callback.selection(new VillagerRoller.RollingEnchantment(Registries.ENCHANTMENT.getId(e), e.getMaxLevel(), VillagerRoller.getMinimumPrice(e, e.getMaxLevel()), true)); + callback.selection(new VillagerRoller.RollingEnchantment(reg.getId(e.value()), e.value().getMaxLevel(), VillagerRoller.getMinimumPrice(e), true)); close(); }; table.row(); diff --git a/src/main/java/maxsuperman/addons/roller/modules/VillagerRoller.java b/src/main/java/maxsuperman/addons/roller/modules/VillagerRoller.java index a44f0da..2085c1c 100644 --- a/src/main/java/maxsuperman/addons/roller/modules/VillagerRoller.java +++ b/src/main/java/maxsuperman/addons/roller/modules/VillagerRoller.java @@ -34,10 +34,11 @@ import net.minecraft.block.Blocks; import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.ItemEnchantmentsComponent; import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.Enchantments; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.EnchantmentLevelEntry; import net.minecraft.entity.passive.VillagerEntity; +import net.minecraft.item.EnchantedBookItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; @@ -45,7 +46,10 @@ import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtList; import net.minecraft.network.packet.s2c.play.SetTradeOffersS2CPacket; -import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.registry.tag.EnchantmentTags; import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvents; import net.minecraft.util.Hand; @@ -61,11 +65,9 @@ import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; +import java.util.*; + +import static meteordevelopment.meteorclient.MeteorClient.mc; public class VillagerRoller extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); @@ -347,15 +349,27 @@ private void fillWidget(GuiTheme theme, WVerticalList list) { searchingEnchants.sort(Comparator.comparing(o -> o.enchantment)); } + Registry reg; + if (mc.world != null) { + reg = mc.world.getRegistryManager().get(RegistryKeys.ENCHANTMENT); + } else { + reg = null; + } + for (int i = 0; i < searchingEnchants.size(); i++) { RollingEnchantment e = searchingEnchants.get(i); + Optional> en; + if (reg != null) { + en = reg.getEntry(e.enchantment); + } else { + en = Optional.empty(); + } final int si = i; ItemStack book = Items.ENCHANTED_BOOK.getDefaultStack(); int maxlevel = 255; - if (e.isVanilla()) { - Enchantment ench = Registries.ENCHANTMENT.get(e.enchantment); - maxlevel = e.getMaxLevel(); - book.addEnchantment(ench, e.minLevel == 0 ? maxlevel : e.minLevel); + if (en.isPresent()) { + book = EnchantedBookItem.forEnchantment(new EnchantmentLevelEntry(en.get(), en.get().value().getMaxLevel())); + maxlevel = en.get().value().getMaxLevel(); } table.add(theme.item(book)); @@ -366,10 +380,10 @@ private void fillWidget(GuiTheme theme, WVerticalList list) { list.clear(); fillWidget(theme, list); })); - if (e.isCustom()) { - label.add(theme.label(e.enchantment.toString())); + if (en.isPresent()) { + label.add(theme.label(Names.get(en.get()))); } else { - Registries.ENCHANTMENT.getOrEmpty(e.enchantment).ifPresent(en -> label.add(theme.label(Names.get(en)))); + label.add(theme.label(e.enchantment.toString())); } table.add(label); @@ -386,15 +400,13 @@ private void fillWidget(GuiTheme theme, WVerticalList list) { setOptimal.tooltip = "Set to optimal price (5 + maxLevel*3) (double if treasure) (if known)"; setOptimal.action = () -> { list.clear(); - if (e.isVanilla()) { - e.maxCost = getMinimumPrice(Registries.ENCHANTMENT.get(e.enchantment), e.getMaxLevel()); - } + en.ifPresent(enchantmentReference -> e.maxCost = getMinimumPrice(enchantmentReference)); fillWidget(theme, list); }; - WCheckbox en = table.add(theme.checkbox(e.enabled)).widget(); - en.action = () -> e.enabled = en.checked; - en.tooltip = "Enabled?"; + WCheckbox enabled = table.add(theme.checkbox(e.enabled)).widget(); + enabled.action = () -> e.enabled = enabled.checked; + enabled.tooltip = "Enabled?"; WMinus del = table.add(theme.minus()).widget(); del.action = () -> { @@ -416,10 +428,8 @@ private void fillWidget(GuiTheme theme, WVerticalList list) { WButton add = controls.add(theme.button("Add")).expandX().widget(); add.action = () -> mc.setScreen(new EnchantmentSelectScreen(theme, e -> { - if (e.isVanilla()) { - e.minLevel = e.getMaxLevel(); - e.maxCost = getMinimumPrice(Registries.ENCHANTMENT.get(e.enchantment), e.minLevel); - } + e.minLevel = 1; + e.maxCost = 64; e.enabled = true; searchingEnchants.add(e); list.clear(); @@ -430,8 +440,10 @@ private void fillWidget(GuiTheme theme, WVerticalList list) { addAll.action = () -> { list.clear(); searchingEnchants.clear(); - for (Enchantment e : Registries.ENCHANTMENT.stream().filter(Enchantment::isAvailableForEnchantedBookOffer).toList()) { - searchingEnchants.add(new RollingEnchantment(Registries.ENCHANTMENT.getId(e), e.getMaxLevel(), getMinimumPrice(e, e.getMaxLevel()), false)); + if (reg != null) { + for (RegistryEntry e : getTradableEnchants()) { + searchingEnchants.add(new RollingEnchantment(reg.getId(e.value()), e.value().getMaxLevel(), getMinimumPrice(e), true)); + } } fillWidget(theme, list); }; @@ -440,10 +452,9 @@ private void fillWidget(GuiTheme theme, WVerticalList list) { WButton setOptimalForAll = controls.add(theme.button("Set optimal for all")).expandX().widget(); setOptimalForAll.action = () -> { list.clear(); - for (RollingEnchantment e : searchingEnchants) { - if (e.isVanilla()) { - Enchantment ench = Registries.ENCHANTMENT.get(e.enchantment); - e.maxCost = getMinimumPrice(ench, e.getMaxLevel()); + if (reg != null) { + for (RollingEnchantment e : searchingEnchants) { + reg.getEntry(e.enchantment).ifPresent(enchantmentReference -> e.maxCost = getMinimumPrice(enchantmentReference)); } } fillWidget(theme, list); @@ -498,9 +509,19 @@ private void fillWidget(GuiTheme theme, WVerticalList list) { } - public static int getMinimumPrice(Enchantment e, int l) { + public List> getTradableEnchants() { + if (mc.world == null) { + return Collections.emptyList(); + } + var reg = mc.world.getRegistryManager().get(RegistryKeys.ENCHANTMENT); + List> available; + var l = reg.getEntryList(EnchantmentTags.TRADEABLE); + return l.map(registryEntries -> registryEntries.stream().toList()).orElse(Collections.emptyList()); + } + + public static int getMinimumPrice(RegistryEntry e) { if (e == null) return 0; - return e.isTreasure() ? (2 + 3 * l) * 2 : 2 + 3 * l; + return e.isIn(EnchantmentTags.DOUBLE_TRADE_PRICE) ? (2 + 3 * e.value().getMaxLevel()) * 2 : 2 + 3 * e.value().getMaxLevel(); } public void triggerInteract() { @@ -511,14 +532,11 @@ public void triggerInteract() { } } - public List> getEnchants(ItemStack stack) { - List> ret; - - ItemEnchantmentsComponent enchantmentsComponent = stack.get(DataComponentTypes.STORED_ENCHANTMENTS); - ret = enchantmentsComponent.getEnchantmentsMap().stream() - .map(entry -> ObjectIntImmutablePair.of(Registries.ENCHANTMENT.getId(entry.getKey().value()), entry.getIntValue())) - .collect(Collectors.toList()); - + public List, Integer>> getEnchants(ItemStack stack) { + List, Integer>> ret = new ArrayList<>(); + for (var e : EnchantmentHelper.getEnchantments(stack).getEnchantmentEntries()) { + ret.add(ObjectIntImmutablePair.of(e.getKey(), e.getIntValue())); + } return ret; } @@ -535,19 +553,19 @@ public void triggerTradeCheck(TradeOfferList l) { if (!sellItem.isOf(Items.ENCHANTED_BOOK) || sellItem.get(DataComponentTypes.STORED_ENCHANTMENTS) == null) break; - for (Pair enchant : getEnchants(sellItem)) { + for (Pair, Integer> enchant : getEnchants(sellItem)) { int enchantLevel = enchant.right(); - Identifier enchantId = enchant.left(); - String enchantName = getEnchantmentName(enchantId); - String enchantIdString = enchantId.toString(); + var reg = mc.world.getRegistryManager().get(RegistryKeys.ENCHANTMENT); + String enchantIdString = reg.getId(enchant.key().value()).toString(); + String enchantName = Names.get(enchant.key()); boolean found = false; for (RollingEnchantment e : searchingEnchants) { if (!e.enabled || !e.enchantment.toString().equals(enchantIdString)) continue; found = true; if (e.minLevel <= 0) { - int ml = e.getMaxLevel(); - if (!e.isCustom() && enchantLevel != ml) { + int ml = enchant.key().value().getMaxLevel(); + if (enchantLevel < ml) { info(String.format("Found enchant %s but it is not max level: %d (max) > %d (found)", enchantName, ml, enchantLevel)); continue; @@ -676,12 +694,6 @@ private void onTick(TickEvent.Pre event) { } } - public String getEnchantmentName(Identifier id) { - return Registries.ENCHANTMENT.getOrEmpty(id) - .map(Names::get) - .orElse(id.toString()); - } - public static class RollingEnchantment implements ISerializable { private Identifier enchantment; private int minLevel; @@ -696,7 +708,7 @@ public RollingEnchantment(Identifier enchantment, int minLevel, int maxCost, boo } public RollingEnchantment() { - enchantment = Registries.ENCHANTMENT.getId(Enchantments.PROTECTION); + enchantment = Identifier.of("minecraft", "protection"); minLevel = 0; maxCost = 0; enabled = false; @@ -720,25 +732,5 @@ public RollingEnchantment fromTag(NbtCompound tag) { enabled = tag.getBoolean("enabled"); return this; } - - public boolean isCustom() { - return !Registries.ENCHANTMENT.containsId(enchantment); - } - - public boolean isVanilla() { - return Registries.ENCHANTMENT.containsId(enchantment); - } - - public int getMaxLevel() { - return Registries.ENCHANTMENT.getOrEmpty(enchantment) - .map(Enchantment::getMaxLevel) - .orElse(0); - } - - public String getName() { - return Registries.ENCHANTMENT.getOrEmpty(enchantment) - .map(Names::get) - .orElse(enchantment.toString()); - } } }