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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Fixed an error when trying to cast a Great Spell that no longer exists, such as when an addon has been removed ([#1335](https://github.com/FallingColors/HexMod/pull/1335)) @Robotgiggle
- Fixed a broken translation key when referring to a jump iota in a mishap message ([#1350](https://github.com/FallingColors/HexMod/pull/1350)) @hauveli
- Fixed Thoth's Gambit counting one extra pattern towards the pattern limit every iteration ([#1352](https://github.com/FallingColors/HexMod/pull/1352)) @Robotgiggle
- Fixed an exploit that let you read the pattern from a for-sale Ancient Scroll without buying it ([#1363](https://github.com/FallingColors/HexMod/pull/1363)) @Robotgiggle
- Fixed Erase Item not working properly on Ancient Scrolls ([#1363](https://github.com/FallingColors/HexMod/pull/1363)) @Robotgiggle

## `0.11.4` - 2026-08-26

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.utils.hasString
import at.petrak.hexcasting.api.utils.remove
import at.petrak.hexcasting.common.items.storage.ItemScroll
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.world.item.ItemStack

Expand Down Expand Up @@ -50,6 +53,9 @@ object OpErase : SpellAction {

if (datumHolder != null && datumHolder.writeIota(null, true))
datumHolder.writeIota(null, false)

if (stack.hasString(ItemScroll.TAG_OP_ID))
stack.remove(ItemScroll.TAG_OP_ID)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ public Component getName(ItemStack pStack) {

@Override
public void inventoryTick(ItemStack pStack, Level pLevel, Entity pEntity, int pSlotId, boolean pIsSelected) {
// the needs_purchase tag is used so you can't see the pattern on scrolls sold by a wandering trader
// once you put the scroll into your inventory, this removes the tag to reveal the pattern
// this tag applies the "purchase to show pattern" tooltip line to scrolls sold by wandering traders
// once you buy the scroll and put it in your inventory, the tag (and thus the tooltip) gets removed
if (NBTHelper.getBoolean(pStack, TAG_NEEDS_PURCHASE)) {
NBTHelper.remove(pStack, TAG_NEEDS_PURCHASE);
}
Expand Down Expand Up @@ -212,7 +212,7 @@ public void appendHoverText(ItemStack pStack, @Nullable Level pLevel, List<Compo
@Override
public Optional<TooltipComponent> getTooltipImage(ItemStack stack) {
var compound = NBTHelper.getCompound(stack, TAG_PATTERN);
if (compound != null && !NBTHelper.getBoolean(stack, TAG_NEEDS_PURCHASE)) {
if (compound != null) {
var pattern = HexPattern.fromNBT(compound);
return Optional.of(new PatternTooltip(
pattern,
Expand Down
18 changes: 5 additions & 13 deletions Common/src/main/java/at/petrak/hexcasting/common/lib/HexItems.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package at.petrak.hexcasting.common.lib;

import at.petrak.hexcasting.api.misc.MediaConstants;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.api.casting.ActionRegistryEntry;
import at.petrak.hexcasting.api.mod.HexTags;
import at.petrak.hexcasting.common.items.ItemJewelerHammer;
import at.petrak.hexcasting.common.items.ItemLens;
Expand All @@ -14,8 +12,6 @@
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import com.google.common.base.Suppliers;
import net.minecraft.Util;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.food.FoodProperties;
Expand Down Expand Up @@ -161,16 +157,12 @@ public static Item.Properties unstackable() {
}

private static void generateScrollEntries() {
var keyList = new ArrayList<ResourceKey<ActionRegistryEntry>>();
Registry<ActionRegistryEntry> regi = IXplatAbstractions.INSTANCE.getActionRegistry();
for (var key : regi.registryKeySet())
if (HexUtils.isOfTag(regi, key, HexTags.Actions.PER_WORLD_PATTERN))
keyList.add(key);
keyList.sort( (a, b) -> a.location().compareTo(b.location()) );
for (var key : keyList) {
var actionIDs = IXplatAbstractions.INSTANCE.getActionRegistry().getTag(HexTags.Actions.PER_WORLD_PATTERN)
.orElseThrow().stream().map(holder -> holder.unwrapKey().orElseThrow().location().toString())
.sorted().toList();
for (var id : actionIDs) {
addToTab(() -> ItemScroll.withPerWorldPattern(
new ItemStack(HexItems.SCROLL_LARGE),
key.location().toString()
new ItemStack(HexItems.SCROLL_LARGE), id
),HexCreativeTabs.SCROLLS);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package at.petrak.hexcasting.common.loot;

import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.casting.ActionRegistryEntry;
import at.petrak.hexcasting.api.mod.HexTags;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.casting.PatternRegistryManifest;
import at.petrak.hexcasting.common.items.storage.ItemScroll;
Expand All @@ -12,20 +10,15 @@
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import net.minecraft.core.Holder;
import net.minecraft.util.RandomSource;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction;
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;

import java.util.ArrayList;

/**
* Slap a random per-world pattern on the scroll.
* <p>
Expand All @@ -41,23 +34,17 @@ public AddPerWorldPatternToScrollFunc(LootItemCondition[] lootItemConditions) {
* This doesn't actually have any params so extract behaviour out for the benefit of forge
*/
public static ItemStack doStatic(ItemStack stack, RandomSource rand, ServerLevel overworld) {
var perWorldKeys = new ArrayList<ResourceKey<ActionRegistryEntry>>();
Registry<ActionRegistryEntry> regi = IXplatAbstractions.INSTANCE.getActionRegistry();
for (var key : regi.registryKeySet()) {
if (HexUtils.isOfTag(regi, key, HexTags.Actions.PER_WORLD_PATTERN)) {
perWorldKeys.add(key);
}
}
var patternKey = perWorldKeys.get(rand.nextInt(perWorldKeys.size()));
var patternID = patternKey.location().toString();
var pat = PatternRegistryManifest.getCanonicalStrokesPerWorld(patternKey, overworld);
var actionKey = IXplatAbstractions.INSTANCE.getActionRegistry().getTag(HexTags.Actions.PER_WORLD_PATTERN)
.flatMap(set -> set.getRandomElement(rand)).flatMap(Holder::unwrapKey).orElseThrow();
var actionID = actionKey.location().toString();
var pat = PatternRegistryManifest.getCanonicalStrokesPerWorld(actionKey, overworld);
if (pat == null) {
HexAPI.LOGGER.error("No per-world pattern found for action " + patternID + " while generating loot scroll! " +
HexAPI.LOGGER.error("No per-world pattern found for action " + actionID + " while generating loot scroll! " +
"Try running '/hexcasting recalcPatterns' to generate the patterns for this world.");
NBTHelper.putString(stack, ItemScroll.TAG_RECALC_WARNING, patternID);
NBTHelper.putString(stack, ItemScroll.TAG_RECALC_WARNING, actionID);
return stack;
}
NBTHelper.putString(stack, ItemScroll.TAG_OP_ID, patternID);
NBTHelper.putString(stack, ItemScroll.TAG_OP_ID, actionID);
NBTHelper.put(stack, ItemScroll.TAG_PATTERN, pat.serializeToNBT());
return stack;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package at.petrak.hexcasting.mixin;

import at.petrak.hexcasting.api.mod.HexTags;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.core.Holder;
import net.minecraft.world.entity.npc.WanderingTrader;
import net.minecraft.world.item.trading.MerchantOffers;
import net.minecraft.world.item.trading.MerchantOffer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.util.RandomSource;
import net.minecraft.server.MinecraftServer;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.loot.AddPerWorldPatternToScrollFunc;
import at.petrak.hexcasting.common.items.storage.ItemScroll;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
Expand All @@ -28,8 +29,10 @@ private void addNewTrades(CallbackInfo ci) {
return;
RandomSource rand = self.getRandom();
if (rand.nextFloat() < HexConfig.server().traderScrollChance() && self.getServer() != null) {
ItemStack scroll = new ItemStack(HexItems.SCROLL_LARGE);
AddPerWorldPatternToScrollFunc.doStatic(scroll, rand, self.getServer().overworld());
var actionID = IXplatAbstractions.INSTANCE.getActionRegistry().getTag(HexTags.Actions.PER_WORLD_PATTERN)
.flatMap(set -> set.getRandomElement(rand)).flatMap(Holder::unwrapKey)
.map(key -> key.location().toString()).orElseThrow();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.map(key -> key.location().toString()).orElseThrow();
.map(Identifier::location).orElseThrow().toString();

more beautiful :P

ItemStack scroll = ItemScroll.withPerWorldPattern(new ItemStack(HexItems.SCROLL_LARGE), actionID);
NBTHelper.putBoolean(scroll, ItemScroll.TAG_NEEDS_PURCHASE, true);
offerList.set(5, new MerchantOffer(new ItemStack(Items.EMERALD, 12), scroll, 1, 1, 1));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@

scroll_small: {
"": "Small Scroll",
of: "How did you get this item of %s",
of: "Ancient Scroll of %s",
empty: "Empty Small Scroll",
},

scroll_medium: {
"": "Medium Scroll",
of: "How did you get this item of %s",
of: "Ancient Scroll of %s",
empty: "Empty Medium Scroll",
},

Expand Down
Loading