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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Added Simulate, which causes the next pattern drawn to be simulated (to check for mishaps) rather than executed ([#1194](https://github.com/FallingColors/HexMod/pull/1194)) @Robotgiggle
- Added the `hex_unbreakable` tag for blocks that should be immune to Break Block regardless of the configured mining tier ([#1186](https://github.com/FallingColors/HexMod/pull/1186)) @Robotgiggle @slava110
- Added a new Ancient Cypher hex that impulses nearby items towards the caster ([#1106](https://github.com/FallingColors/HexMod/pull/1106)) @IridescentVoid
- Added a recipe to copy a spellbook's contents into another blank spellbook using dragon's breath ([#1231](https://github.com/FallingColors/HexMod/pull/1231)) @Robotgiggle
- Added a recipe to fully erase a spellbook's contents using soul sand ([#1231](https://github.com/FallingColors/HexMod/pull/1231)) @Robotgiggle

### Changed

Expand All @@ -26,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

- Fixed Entity Iota comparison to use `equals` on entity IDs instead of reference equality ([#1101](https://github.com/FallingColors/HexMod/pull/1101)) @IridescentVoid
- Corrected field names of the codec for Pattern Iotas and add a graceful fallback for upgrading ([#1120](https://github.com/FallingColors/HexMod/pull/1120), [#1131](https://github.com/FallingColors/HexMod/pull/1131), [#1140](https://github.com/FallingColors/HexMod/pull/1140)) @Master-Bw3 @IridescentVoid
- Fixed the iota-holder sealing recipe also consuming anything else placed into the crafting grid ([#1231](https://github.com/FallingColors/HexMod/pull/1231)) @Robotgiggle

### Internal

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "hexcasting:copy_spellbook",
"category": "misc"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "hexcasting:erase_spellbook",
"category": "misc"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:dragon_breath"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:soul_sand"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public static final class Items {
public static final TagKey<Item> PHIAL_BASE = create("phial_base");
public static final TagKey<Item> GRANTS_ROOT_ADVANCEMENT = create("grants_root_advancement");
public static final TagKey<Item> SEAL_MATERIALS = create("seal_materials");
public static final TagKey<Item> SPELLBOOK_COPY_MATERIALS = create("spellbook_copy_materials");
public static final TagKey<Item> SPELLBOOK_ERASE_MATERIALS = create("spellbook_erase_materials");

public static final TagKey<Item> IMPETI = create("impeti");
public static final TagKey<Item> DIRECTRICES = create("directrices");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package at.petrak.hexcasting.common.recipe;

import at.petrak.hexcasting.api.mod.HexTags;
import at.petrak.hexcasting.common.lib.HexDataComponents;
import at.petrak.hexcasting.common.lib.HexItems;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.NonNullList;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;

public class CopySpellbookRecipe extends CustomRecipe {
public static final SimpleCraftingRecipeSerializer<CopySpellbookRecipe> SERIALIZER =
new SimpleCraftingRecipeSerializer<>(CopySpellbookRecipe::new);

public CopySpellbookRecipe(CraftingBookCategory category) {
super(category);
}

@Override
public boolean canCraftInDimensions(int width, int height) {
return width * height >= 2;
}

@Override
public boolean matches(CraftingInput container, Level level) {
boolean foundCopyMaterial = false;
boolean foundOriginal = false;
boolean foundBlank = false;

for (int i = 0; i < container.size(); i++) {
var stack = container.getItem(i);
if (stack.is(HexTags.Items.SPELLBOOK_COPY_MATERIALS)) {
if (foundCopyMaterial) return false;
foundCopyMaterial = true;
} else if (stack.is(HexItems.SPELLBOOK.get())) {
if (stack.has(HexDataComponents.SPELLBOOK_PAGES.get())) {
if (foundOriginal) return false;
foundOriginal = true;
} else {
if (foundBlank) return false;
foundBlank = true;
}
} else {
return false;
}
}

return foundCopyMaterial && foundOriginal && foundBlank;
}

@Override
public @NotNull ItemStack assemble(CraftingInput inv, HolderLookup.RegistryLookup.@NotNull Provider registryProvider) {
ItemStack output = ItemStack.EMPTY;
Integer variant = null;
for (int i = 0; i < inv.size(); i++) {
var stack = inv.getItem(i);
if (stack.is(HexItems.SPELLBOOK.get())) {
if (stack.has(HexDataComponents.SPELLBOOK_PAGES.get())) {
output = stack.copyWithCount(1);
} else {
variant = stack.get(HexDataComponents.ITEM_VARIANT.get());
}
}
}
if (variant != null && output != ItemStack.EMPTY) {
output.set(HexDataComponents.ITEM_VARIANT.get(), variant);
}
return output;
}

@Override
public @NotNull NonNullList<ItemStack> getRemainingItems(@NotNull CraftingInput craftingInput) {
NonNullList<ItemStack> remainingItems = NonNullList.withSize(craftingInput.size(), ItemStack.EMPTY);

for(int i = 0; i < remainingItems.size(); ++i) {
ItemStack stack = craftingInput.getItem(i);
if (stack.getItem().hasCraftingRemainingItem()) {
remainingItems.set(i, new ItemStack(stack.getItem().getCraftingRemainingItem()));
} else if (stack.is(HexItems.SPELLBOOK.get()) && stack.get(HexDataComponents.SPELLBOOK_PAGES.get()) != null) {
remainingItems.set(i, stack.copyWithCount(1));
}
}

return remainingItems;
}

@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return SERIALIZER;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package at.petrak.hexcasting.common.recipe;

import at.petrak.hexcasting.api.mod.HexTags;
import at.petrak.hexcasting.common.lib.HexDataComponents;
import at.petrak.hexcasting.common.lib.HexItems;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;

public class EraseSpellbookRecipe extends CustomRecipe {
public static final SimpleCraftingRecipeSerializer<EraseSpellbookRecipe> SERIALIZER =
new SimpleCraftingRecipeSerializer<>(EraseSpellbookRecipe::new);

public EraseSpellbookRecipe(CraftingBookCategory category) {
super(category);
}

@Override
public boolean canCraftInDimensions(int width, int height) {
return width * height >= 2;
}

@Override
public boolean matches(CraftingInput container, Level level) {
boolean foundEraseMaterial = false;
boolean foundSpellbook = false;

for (int i = 0; i < container.size(); i++) {
var stack = container.getItem(i);
if (stack.is(HexTags.Items.SPELLBOOK_ERASE_MATERIALS)) {
if (foundEraseMaterial) return false;
foundEraseMaterial = true;
} else if (stack.is(HexItems.SPELLBOOK.get()) && stack.has(HexDataComponents.SPELLBOOK_PAGES.get())) {
if (foundSpellbook) return false;
foundSpellbook = true;
} else {
return false;
}
}

return foundEraseMaterial && foundSpellbook;
}

@Override
public @NotNull ItemStack assemble(CraftingInput inv, HolderLookup.RegistryLookup.@NotNull Provider registryProvider) {
for (int i = 0; i < inv.size(); i++) {
var stack = inv.getItem(i);
if (stack.is(HexItems.SPELLBOOK.get()) && stack.has(HexDataComponents.SPELLBOOK_PAGES.get())) {
var output = new ItemStack(HexItems.SPELLBOOK.get(), 1);
var variant = stack.get(HexDataComponents.ITEM_VARIANT.get());
if (variant != null) {
output.set(HexDataComponents.ITEM_VARIANT.get(), variant);
}
return output;
}
}
return ItemStack.EMPTY;
}

@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return SERIALIZER;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public static void register() {
"seal_focus", () -> SealThingsRecipe.FOCUS_SERIALIZER);
public static final Supplier<RecipeSerializer<SealThingsRecipe>> SEAL_SPELLBOOK = REGISTER_SERIALIZER.register(
"seal_spellbook", () -> SealThingsRecipe.SPELLBOOK_SERIALIZER);
public static final Supplier<RecipeSerializer<CopySpellbookRecipe>> COPY_SPELLBOOK = REGISTER_SERIALIZER.register(
"copy_spellbook", () -> CopySpellbookRecipe.SERIALIZER);
public static final Supplier<RecipeSerializer<EraseSpellbookRecipe>> ERASE_SPELLBOOK = REGISTER_SERIALIZER.register(
"erase_spellbook", () -> EraseSpellbookRecipe.SERIALIZER);

public static Supplier<RecipeType<BrainsweepRecipe>> BRAINSWEEP_TYPE = REGISTER_RECIPE_TYPE.register("brainsweep", () ->
new RecipeType<BrainsweepRecipe>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public boolean canCraftInDimensions(int width, int height) {

@Override
public boolean matches(CraftingInput container, Level level) {
boolean foundComb = false;
boolean foundSealant = false;
boolean foundSealee = false;

for (int i = 0; i < container.size(); i++) {
Expand All @@ -44,12 +44,14 @@ public boolean matches(CraftingInput container, Level level) {
if (foundSealee) return false;
foundSealee = true;
} else if (stack.is(HexTags.Items.SEAL_MATERIALS)) {
if (foundComb) return false;
foundComb = true;
if (foundSealant) return false;
foundSealant = true;
} else {
return false;
}
}

return foundComb && foundSealee;
return foundSealant && foundSealee;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import at.petrak.hexcasting.common.items.pigment.ItemPridePigment;
import at.petrak.hexcasting.common.lib.HexBlocks;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.recipe.CopySpellbookRecipe;
import at.petrak.hexcasting.common.recipe.EraseSpellbookRecipe;
import at.petrak.hexcasting.common.recipe.SealThingsRecipe;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.EntityTypeIngredient;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.VillagerIngredient;
Expand Down Expand Up @@ -87,6 +89,8 @@ public HexplatRecipes(PackOutput output, CompletableFuture<HolderLookup.Provider
public void buildRecipes(RecipeOutput recipes) {
specialRecipe(recipes, SealThingsRecipe.FOCUS_SERIALIZER, SealThingsRecipe::focus);
specialRecipe(recipes, SealThingsRecipe.SPELLBOOK_SERIALIZER, SealThingsRecipe::spellbook);
specialRecipe(recipes, CopySpellbookRecipe.SERIALIZER, CopySpellbookRecipe::new);
specialRecipe(recipes, EraseSpellbookRecipe.SERIALIZER, EraseSpellbookRecipe::new);

staffRecipe(recipes, HexItems.STAFF_OAK.get(), Items.OAK_PLANKS);
staffRecipe(recipes, HexItems.STAFF_BIRCH.get(), Items.BIRCH_PLANKS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ protected void addTags(HolderLookup.Provider provider) {
HexItems.CHARGED_AMETHYST.get(), HexItems.CREATIVE_UNLOCKER.get());
add(tag(HexTags.Items.SEAL_MATERIALS),
Items.HONEYCOMB);
add(tag(HexTags.Items.SPELLBOOK_COPY_MATERIALS),
Items.DRAGON_BREATH);
add(tag(HexTags.Items.SPELLBOOK_ERASE_MATERIALS),
Items.SOUL_SAND);

this.copy(HexTags.Blocks.EDIFIED_LOGS, HexTags.Items.EDIFIED_LOGS);
this.copy(HexTags.Blocks.EDIFIED_PLANKS, HexTags.Items.EDIFIED_PLANKS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,8 @@
"1": "A $(l:items/spellbook)$(item)Spellbook/$ is the culmination of my art-- it acts like an entire library of $(l:items/focus)$(item)Foci/$. Up to $(thing)sixty-four/$ of them, to be exact.$(br2)Each page can hold a single iota, and I can select the active page (the page that iotas are saved to and copied from) by sneak-scrolling while holding it, or simply holding it in my off-hand and scrolling while casting a _Hex.",
"2": "Like a $(l:items/focus)$(item)Focus/$, there exists a simple method to prevent accidental overwriting. Crafting it with a $(item)Honeycomb/$ will lacquer the current page, preventing $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ from modifying its contents. Also like a $(l:items/focus)$(item)Focus/$, using $(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ will remove the lacquer along with the page's contents.$(br2)I can also name each page individually in an anvil. Naming it will change only the name of the currently selected page, for easy browsing.",
"crafting.desc": "$(italic)Wizards love words. Most of them read a great deal, and indeed one strong sign of a potential wizard is the inability to get to sleep without reading something first.",
"3.title": "Copying and Erasing",
"3": "Exposing a $(item)Spellbook/$ to $(item)Dragon’s Breath/$ renders the stored iotas volatile, allowing me to capture echoes of them in other receptive objects. I can use this to copy one $(item)Spellbook/$ into another empty one, simply by crafting them together with $(item)Dragon's Breath/$.$(br2)I can also craft a filled $(item)Spellbook/$ together with $(item)Soul Sand/$ to scrub the pages clean, leaving it completely empty.",
},

scroll: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
"type": "patchouli:crafting",
"recipe": "hexcasting:spellbook",
"text": "hexcasting.page.spellbook.crafting.desc"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.spellbook.3.title",
"text": "hexcasting.page.spellbook.3"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "hexcasting:copy_spellbook",
"category": "misc"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "hexcasting:erase_spellbook",
"category": "misc"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:dragon_breath"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:soul_sand"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "hexcasting:copy_spellbook",
"category": "misc"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "hexcasting:erase_spellbook",
"category": "misc"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:dragon_breath"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:soul_sand"
]
}
Loading