diff --git a/gradle.properties b/gradle.properties index 774f12b90..7d7be97f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,8 +49,8 @@ smartbrainlib_version=1.14.5 smartbrainlib_version_range=[1.14.5,) almost_unified_version=0.5.0 almost_unified_version_range=[0.5.0,) -modonomicon_version=1.105.0 -modonomicon_version_range=[1.105.0,) +modonomicon_version=1.106.0 +modonomicon_version_range=[1.106.0,) theurgy_version=1.52.0 theurgy_version_range=[1.47.1,) per_viam_invenire_version_range=[0.1.57,) diff --git a/src/generated/resources/assets/occultism/lang/en_us.json b/src/generated/resources/assets/occultism/lang/en_us.json index 389c716e1..40bb627a1 100644 --- a/src/generated/resources/assets/occultism/lang/en_us.json +++ b/src/generated/resources/assets/occultism/lang/en_us.json @@ -157,6 +157,22 @@ "block.occultism.stripped_otherworld_log": "Stripped Otherworld Log", "block.occultism.stripped_otherworld_wood": "Stripped Otherworld Wood", "block.occultism.wither_skeleton_skull_dummy": "Wither Skeleton Skull", + "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.about.text": "A ritual satchel can hold items needed to create pentacles for rituals. Other items cannot be placed in the satchel.\n\\\nThe satchel allows to speed up setting pentacles by automatically choosing the right items from the satchel, instead of manually selecting chalks, candles and other items to place them.\n", + "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.about.title": "About", + "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.description": "Tired of so many chalks and paraphernalia? The Ritual Satchel is the solution!", + "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.name": "Apprentice Ritual Satchel", + "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.spotlight.text": " At first glance the satchel appears to be a normal bag, of moderate size and storage capacity. However, closer inspection reveals that a [#](AA00AA)Djinni[#]() is bound to the satchel, tasked with assisting the summoner in drawing pentacles for their rituals.\n", + "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.usage.text": "1. [#](55FF55)Shift-Right-Click[#]() to open the satchel and place chalks, candles, crystals, skulls and other items needed for rituals.\n2. Using this book, use the \"eye\" icon to preview the pentacle you want to set up in the world.\n3. [#](55FF55)Right-Click[#]() with this book to anchor the preview pentacle in the spot where you want to set it up.\n4. {2} with the satchel on a previewed chalk mark or block to automatically place it.\n5. Repeat until the pentacle is complete.\n", + "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.usage.title": "Usage", + "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.about.text": "A ritual satchel can hold items needed to create pentacles for rituals. Other items cannot be placed in the satchel.\n\\\nThe satchel sets up an entire pentacle at once, if all necessary items are present in the satchel.\\\nIt can also remove (intact) pentacles by [#](55FF55)Right-Clicking[#]() the [](item://occultism:golden_sacrificial_bowl) and store all blocks back in the satchel.\n", + "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.about.title": "About", + "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.description": "The Apprentice Ritual Satchel is still too slow? Let's get help from an Afrit!", + "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.name": "Artisanal Ritual Satchel", + "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.spotlight.text": " The artisanal satchel employs an [#](AA00AA)Afrit[#]() to assist the summoner in drawing pentacles for their rituals. Unlike [#](AA00AA)Djinni[#]() in the apprentice satchel, the bound [#](AA00AA)Afrit[#]() can set up an entire pentacle within a moments notice.\n \\\n Moreover, the spirit can also clean up the pentacle after the ritual is complete, leaving no trace of the ritual behind.\n", + "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.usage_cleaning.text": "1. Find a pentacle you want to remove. The pentacle needs to be intact (ready for a ritual).\n2. [#](55FF55)Right-Click[#]() the central [](item://occultism:golden_sacrificial_bowl) with the satchel.\n2. The satchel will remove all chalk marks, and pick up all paraphernalia blocks, such as candles or skulls, used in the pentacle.\n", + "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.usage_cleaning.title": "Usage (Cleaning)", + "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.usage_drawing.text": "1. [#](55FF55)Shift-Right-Click[#]() to open the satchel and place chalks, candles, crystals, skulls and other items needed for rituals.\n2. Using this book, use the \"eye\" icon to preview the pentacle you want to set up in the world.\n3. [#](55FF55)Right-Click[#]() with this book to anchor the preview pentacle in the spot where you want to set it up.\n4. {2} with the satchel on a previewed chalk mark or block to automatically place it.\n5. Repeat until the pentacle is complete.\n", + "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.usage_drawing.title": "Usage (Drawing)", "book.occultism.dictionary_of_spirits.crafting_rituals.craft_afrit_miner.name": "Afrit Miner", "book.occultism.dictionary_of_spirits.crafting_rituals.craft_afrit_miner.spotlight.text": "The [#](ad03fc)Afrit[#]() miner harvests ores, like djinni miners, and additionally mines deepslate ores. This miner is faster and more efficient than the djinnis, thus damaging the magic lamp even more slowly.\n", "book.occultism.dictionary_of_spirits.crafting_rituals.craft_dimensional_matrix.name": "Dimensional Matrix", @@ -504,6 +520,11 @@ "book.occultism.dictionary_of_spirits.getting_started.ritual_prep_chalk.usage.text": "Right-click on a block with the chalk to draw a single glyph. For decorative purposes you can repeatedly click a block to cycle through glyphs. The shown glyph does not matter for the ritual, only the color.\n", "book.occultism.dictionary_of_spirits.getting_started.ritual_prep_chalk.usage.title": "Usage", "book.occultism.dictionary_of_spirits.getting_started.ritual_prep_chalk.white_chalk.text": "White chalk is used to draw the most basic pentacles, such as for our first ritual.\n\\\n\\\nMore powerful summonings require appropriate more advanced chalk, see [Chalks](entry://occultism:dictionary_of_spirits/getting_started/chalks) for more information.\n", + "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.description": "Easier pentacle drawing with a Ritual Satchel", + "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.more.text": "Visit the entry about the [Apprentice Satchel](entry://crafting_rituals/apprentice_ritual_satchel) or the [Artisanal Satchel](entry://crafting_rituals/apprentice_ritual_satchel) in the [Binding Rituals Category](category://crafting_rituals) to learn how to enchant a satchel and use it for rituals.\n", + "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.more.title": "Obtaining a Satchel", + "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.name": "Ritual Satchels", + "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.spotlight.text": "Ritual satchels are bags that can hold items needed to create pentacles for rituals.\\\nMore importantly, they can automatically place the right items for a pentacle, removing the need to manually place chalks, candles, crystals, skulls and other items needed for rituals.\\\\\nThe Apprentice Satchel places pentacle blocks one by one.\\\nThe improved Artisanal Satchel places all pentacle blocks in a single action.\\\n", "book.occultism.dictionary_of_spirits.getting_started.spirit_fire.description": "Or does it?", "book.occultism.dictionary_of_spirits.getting_started.spirit_fire.main_uses.text": "The main uses of [](item://occultism:spirit_fire) are to convert [](item://minecraft:diamond) into [](item://occultism:spirit_attuned_gem),\nto get basic ingredients such as [](item://occultism:otherstone) and [Otherworld Saplings](item://occultism:otherworld_sapling_natural),\nand to purify impure chalks.\n", "book.occultism.dictionary_of_spirits.getting_started.spirit_fire.name": "It burns!", @@ -1339,6 +1360,15 @@ "item.occultism.ritual_dummy.summon_wild_parrot.tooltip": "Summons a Parrot that can be tamed by anyone, not just the summoner.", "item.occultism.ritual_dummy.summon_wild_silverfish": "Ritual: Summon The Wild Horde Silverfish", "item.occultism.ritual_dummy.summon_wild_silverfish.tooltip": "The Wild Horde Silverfish consists of a few Silverfishs that drop items related to ruins trails.", + "item.occultism.ritual_satchel.no_preview_block_targeted": "You need to aim the ritual satchel at a preview block.", + "item.occultism.ritual_satchel.no_preview_in_world": " You need to preview a pentacle using the Dictionary of Spirits.", + "item.occultism.ritual_satchel.no_valid_item_in_satchel": "There is no valid item in the satchel for this previewed block.", + "item.occultism.ritual_satchel_t1": "Apprentice Ritual Satchel", + "item.occultism.ritual_satchel_t1.auto_tooltip": "A basic ritual satchel that can place ritual circles block by block.\nRight-Click a preview block to place it out of the satchel.\nShift-Right-Click to open the satchel and add ritual ingredients.\n", + "item.occultism.ritual_satchel_t1.tooltip": "%s is bound to this satchel.", + "item.occultism.ritual_satchel_t2": "Artisanal Ritual Satchel", + "item.occultism.ritual_satchel_t2.auto_tooltip": "An improved ritual satchel that can place an entire ritual circle at once.\nRight-Click any preview block to place all preview blocks out of the satchel.\nShift-Right-Click to open the satchel and add ritual ingredients.\nRight-Click a Golden Bowl to remove the ritual circle and collect the ingredients.\n", + "item.occultism.ritual_satchel_t2.tooltip": "%s is bound to this satchel.", "item.occultism.satchel": "Surprisingly Substantial Satchel", "item.occultism.satchel.tooltip": "%s is bound to this satchel.", "item.occultism.silver_dust": "Silver Dust", diff --git a/src/generated/resources/assets/occultism/models/item/ritual_dummy/craft_ritual_satchel_t1.json b/src/generated/resources/assets/occultism/models/item/ritual_dummy/craft_ritual_satchel_t1.json new file mode 100644 index 000000000..1a5442cc2 --- /dev/null +++ b/src/generated/resources/assets/occultism/models/item/ritual_dummy/craft_ritual_satchel_t1.json @@ -0,0 +1,3 @@ +{ + "parent": "occultism:item/ritual_dummy" +} \ No newline at end of file diff --git a/src/generated/resources/assets/occultism/models/item/ritual_dummy/craft_ritual_satchel_t2.json b/src/generated/resources/assets/occultism/models/item/ritual_dummy/craft_ritual_satchel_t2.json new file mode 100644 index 000000000..1a5442cc2 --- /dev/null +++ b/src/generated/resources/assets/occultism/models/item/ritual_dummy/craft_ritual_satchel_t2.json @@ -0,0 +1,3 @@ +{ + "parent": "occultism:item/ritual_dummy" +} \ No newline at end of file diff --git a/src/generated/resources/assets/occultism/models/item/ritual_satchel_t1.json b/src/generated/resources/assets/occultism/models/item/ritual_satchel_t1.json new file mode 100644 index 000000000..62e6254c0 --- /dev/null +++ b/src/generated/resources/assets/occultism/models/item/ritual_satchel_t1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "occultism:item/ritual_satchel_t1" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/occultism/models/item/ritual_satchel_t2.json b/src/generated/resources/assets/occultism/models/item/ritual_satchel_t2.json new file mode 100644 index 000000000..7ee09b446 --- /dev/null +++ b/src/generated/resources/assets/occultism/models/item/ritual_satchel_t2.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "occultism:item/ritual_satchel_t2" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/skulls.json b/src/generated/resources/data/c/tags/item/skulls.json new file mode 100644 index 000000000..f6790f3c7 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/skulls.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:skeleton_skull", + "minecraft:wither_skeleton_skull" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/item/enchantable/durability.json b/src/generated/resources/data/minecraft/tags/item/enchantable/durability.json index 53149709e..ae70aebad 100644 --- a/src/generated/resources/data/minecraft/tags/item/enchantable/durability.json +++ b/src/generated/resources/data/minecraft/tags/item/enchantable/durability.json @@ -1,7 +1,7 @@ { "values": [ "#occultism:miners", - "#occultism:tools/chalks", + "#occultism:tools/chalk", "#occultism:tools/knife" ] } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/advancement/recipes/ritual/ritual/craft_ritual_satchel_t1.json b/src/generated/resources/data/occultism/advancement/recipes/ritual/ritual/craft_ritual_satchel_t1.json new file mode 100644 index 000000000..7a82b3702 --- /dev/null +++ b/src/generated/resources/data/occultism/advancement/recipes/ritual/ritual/craft_ritual_satchel_t1.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_bound_djinni": { + "conditions": { + "items": [ + { + "items": "occultism:book_of_binding_bound_djinni" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "occultism:ritual/craft_ritual_satchel_t1" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_bound_djinni" + ] + ], + "rewards": { + "recipes": [ + "occultism:ritual/craft_ritual_satchel_t1" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/advancement/recipes/ritual/ritual/craft_ritual_satchel_t2.json b/src/generated/resources/data/occultism/advancement/recipes/ritual/ritual/craft_ritual_satchel_t2.json new file mode 100644 index 000000000..b2d881bfb --- /dev/null +++ b/src/generated/resources/data/occultism/advancement/recipes/ritual/ritual/craft_ritual_satchel_t2.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_bound_afrit": { + "conditions": { + "items": [ + { + "items": "occultism:book_of_binding_bound_afrit" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "occultism:ritual/craft_ritual_satchel_t2" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_bound_afrit" + ] + ], + "rewards": { + "recipes": [ + "occultism:ritual/craft_ritual_satchel_t2" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/apprentice_ritual_satchel.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/apprentice_ritual_satchel.json new file mode 100644 index 000000000..d6cf21656 --- /dev/null +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/apprentice_ritual_satchel.json @@ -0,0 +1,73 @@ +{ + "background_u_index": 0, + "background_v_index": 0, + "category": "crafting_rituals", + "condition": { + "type": "modonomicon:true" + }, + "description": "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.description", + "hide_while_locked": false, + "icon": { + "item": "occultism:ritual_satchel_t1" + }, + "name": "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.name", + "pages": [ + { + "type": "modonomicon:spotlight", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "item": { + "item": "occultism:ritual_satchel_t1" + }, + "text": "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.spotlight.text", + "title": "" + }, + { + "type": "modonomicon:text", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.about.text", + "title": "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.about.title", + "use_markdown_in_title": false + }, + { + "type": "occultism:ritual_recipe", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "recipe_id_1": "occultism:ritual/craft_ritual_satchel_t1", + "text": "", + "title1": "", + "title2": "" + }, + { + "type": "modonomicon:text", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.usage.text", + "title": "book.occultism.dictionary_of_spirits.crafting_rituals.apprentice_ritual_satchel.usage.title", + "use_markdown_in_title": false + } + ], + "parents": [ + { + "draw_arrow": true, + "entry": "crafting_rituals/craft_satchel", + "line_enabled": true, + "line_reversed": false + } + ], + "show_when_any_parent_unlocked": false, + "sort_number": 19, + "x": 3, + "y": 1 +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/artisanal_ritual_satchel.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/artisanal_ritual_satchel.json new file mode 100644 index 000000000..f2092e27b --- /dev/null +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/artisanal_ritual_satchel.json @@ -0,0 +1,84 @@ +{ + "background_u_index": 0, + "background_v_index": 0, + "category": "crafting_rituals", + "condition": { + "type": "modonomicon:true" + }, + "description": "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.description", + "hide_while_locked": false, + "icon": { + "item": "occultism:ritual_satchel_t2" + }, + "name": "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.name", + "pages": [ + { + "type": "modonomicon:spotlight", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "item": { + "item": "occultism:ritual_satchel_t2" + }, + "text": "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.spotlight.text", + "title": "" + }, + { + "type": "modonomicon:text", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.about.text", + "title": "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.about.title", + "use_markdown_in_title": false + }, + { + "type": "occultism:ritual_recipe", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "recipe_id_1": "occultism:ritual/craft_ritual_satchel_t2", + "text": "", + "title1": "", + "title2": "" + }, + { + "type": "modonomicon:text", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.usage_drawing.text", + "title": "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.usage_drawing.title", + "use_markdown_in_title": false + }, + { + "type": "modonomicon:text", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.usage_cleaning.text", + "title": "book.occultism.dictionary_of_spirits.crafting_rituals.artisanal_ritual_satchel.usage_cleaning.title", + "use_markdown_in_title": false + } + ], + "parents": [ + { + "draw_arrow": true, + "entry": "crafting_rituals/apprentice_ritual_satchel", + "line_enabled": true, + "line_reversed": false + } + ], + "show_when_any_parent_unlocked": false, + "sort_number": 20, + "x": 5, + "y": 1 +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_afrit_miner.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_afrit_miner.json index 780c6836c..82e8fa57e 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_afrit_miner.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_afrit_miner.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 6, "x": 0, "y": -5 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_dimensional_matrix.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_dimensional_matrix.json index 0f54c51e1..c8b5b0292 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_dimensional_matrix.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_dimensional_matrix.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 9, "x": -2, "y": 1 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_dimensional_mineshaft.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_dimensional_mineshaft.json index a96ed3e99..905c90969 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_dimensional_mineshaft.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_dimensional_mineshaft.json @@ -56,7 +56,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 3, "x": -6, "y": -5 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_djinni_miner.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_djinni_miner.json index aa05df0b4..00cbace5b 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_djinni_miner.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_djinni_miner.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 5, "x": -2, "y": -5 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_familiar_ring.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_familiar_ring.json index 40c6cd692..a5d439bf0 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_familiar_ring.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_familiar_ring.json @@ -56,7 +56,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 22, "x": -2, "y": -3 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_foliot_miner.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_foliot_miner.json index 500b74056..3480c7636 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_foliot_miner.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_foliot_miner.json @@ -78,7 +78,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 4, "x": -4, "y": -5 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_infused_pickaxe.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_infused_pickaxe.json index a47e58c31..b271a0337 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_infused_pickaxe.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_infused_pickaxe.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 2, "x": -6, "y": -3 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_marid_miner.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_marid_miner.json index 3549a1ca9..5291b956b 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_marid_miner.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_marid_miner.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 7, "x": 2, "y": -5 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_otherworld_goggles.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_otherworld_goggles.json index 330433ed4..d3938b1d1 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_otherworld_goggles.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_otherworld_goggles.json @@ -101,7 +101,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 17, "x": -6, "y": 1 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_satchel.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_satchel.json index 8dba7cff5..75a494669 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_satchel.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_satchel.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 18, "x": 1, "y": 1 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_soul_gem.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_soul_gem.json index 8033c5ab8..e1168f568 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_soul_gem.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_soul_gem.json @@ -56,7 +56,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 21, "x": -4, "y": -3 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier1.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier1.json index 191f594f2..fe4dcce20 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier1.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier1.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 11, "x": -2, "y": 5 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier2.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier2.json index 75f332a0a..f18679255 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier2.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier2.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 12, "x": 0, "y": 5 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier3.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier3.json index c1e658612..8a8191f10 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier3.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier3.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 13, "x": 2, "y": 5 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier4.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier4.json index 3e0433db3..4619b39ee 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier4.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stabilizer_tier4.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 14, "x": 4, "y": 5 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stable_wormhole.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stable_wormhole.json index 3da7a7b91..ca95e89d0 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stable_wormhole.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_stable_wormhole.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 15, "x": 0, "y": 3 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_controller_base.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_controller_base.json index 46a05723f..66cbaf40a 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_controller_base.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_controller_base.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 10, "x": -2, "y": 3 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_remote.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_remote.json index 49826d1e5..ae1a9eef5 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_remote.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_remote.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 16, "x": 2, "y": 3 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_system.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_system.json index 9001d24bc..903c9e11a 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_system.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_storage_system.json @@ -34,7 +34,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 8, "x": -4, "y": 1 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_wild_trim.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_wild_trim.json index 01aab19dd..be5eb0e23 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_wild_trim.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/craft_wild_trim.json @@ -45,7 +45,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 23, "x": 1, "y": -3 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/overview.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/overview.json index 73dd352ef..a5d034cb3 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/overview.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/overview.json @@ -27,7 +27,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 0, "x": -8, "y": -1 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/return_to_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/return_to_rituals.json index 8ae040672..4faf76bc2 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/return_to_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/crafting_rituals/return_to_rituals.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 2, "category": "crafting_rituals", - "category_to_open": "occultism:rituals", + "category_to_open": "rituals", "condition": { "type": "modonomicon:true" }, @@ -23,7 +23,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 1, "x": -10, "y": -1 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/return_to_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/return_to_rituals.json index afa20d035..e0e5a6aeb 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/return_to_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/return_to_rituals.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 2, "category": "familiar_rituals", - "category_to_open": "occultism:rituals", + "category_to_open": "rituals", "condition": { "type": "modonomicon:true" }, diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_binding.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_binding.json index 9472081ce..f76f70667 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_binding.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_binding.json @@ -200,7 +200,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 11, "x": -3, - "y": 2 + "y": 4 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_binding_automation.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_binding_automation.json index 1c4fce703..cf9168b1b 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_binding_automation.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_binding_automation.json @@ -41,7 +41,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 12, "x": -3, - "y": 4 + "y": 6 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_calling.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_calling.json index c3da5ee64..b981a65e6 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_calling.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/books_of_calling.json @@ -74,7 +74,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 13, "x": -1, - "y": 4 + "y": 6 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/brush.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/brush.json index 1bc50e68a..3bf01db95 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/brush.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/brush.json @@ -41,7 +41,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 9, "x": -3, - "y": -4 + "y": -2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/candle.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/candle.json index 235e331c5..c51ac71ba 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/candle.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/candle.json @@ -87,7 +87,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 7, "x": -5, - "y": 0 + "y": 2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/chalks.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/chalks.json index c651eefe7..6689aa2d4 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/chalks.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/chalks.json @@ -251,7 +251,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 15, "x": 5, - "y": 0 + "y": 2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/crafting_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/crafting_rituals.json index 7065dc64c..c0d9b08a2 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/crafting_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/crafting_rituals.json @@ -43,7 +43,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 31, "x": 15, - "y": 4 + "y": 6 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/demons_dream.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/demons_dream.json index 3b3dcc57b..bc3baba5b 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/demons_dream.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/demons_dream.json @@ -135,7 +135,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 1, "x": -11, - "y": 0 + "y": 2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/divination_rod.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/divination_rod.json index 2c361cebc..ca338d128 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/divination_rod.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/divination_rod.json @@ -201,7 +201,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 5, "x": -7, - "y": -2 + "y": 0 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/familiar_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/familiar_rituals.json index 7b6776478..79e767039 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/familiar_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/familiar_rituals.json @@ -43,7 +43,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 29, "x": 11, - "y": 4 + "y": 6 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/first_ritual.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/first_ritual.json index 46bd28f12..4ae4bee53 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/first_ritual.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/first_ritual.json @@ -138,7 +138,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 14, "x": 1, - "y": 0 + "y": 2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/grey_particles.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/grey_particles.json index edf61391b..4e514f495 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/grey_particles.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/grey_particles.json @@ -30,7 +30,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 18, "x": 3, - "y": 4 + "y": 6 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/healing_spirits.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/healing_spirits.json index 62b8684e4..3920959e3 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/healing_spirits.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/healing_spirits.json @@ -55,7 +55,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 3, "x": -9, - "y": 2 + "y": 4 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/iesnium.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/iesnium.json index ad4d130fe..733782c77 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/iesnium.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/iesnium.json @@ -75,7 +75,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 22, "x": 9, "y": -2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/iesnium_pickaxe.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/iesnium_pickaxe.json index a733c27e3..ff5bb6bd7 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/iesnium_pickaxe.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/iesnium_pickaxe.json @@ -42,7 +42,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 23, "x": 9, "y": -4 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/infused_pickaxe.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/infused_pickaxe.json index 823a8e888..32aaed0b5 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/infused_pickaxe.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/infused_pickaxe.json @@ -64,7 +64,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 21, "x": 7, "y": -2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/intro.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/intro.json index 7753f09e4..d68b291cd 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/intro.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/intro.json @@ -33,7 +33,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 0, "x": -11, - "y": -2 + "y": 0 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/magic_lamps.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/magic_lamps.json index 87518aa48..c107fb08a 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/magic_lamps.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/magic_lamps.json @@ -42,7 +42,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 24, "x": 11, "y": -2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/mineshaft.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/mineshaft.json index 63d52780d..7329d10fa 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/mineshaft.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/mineshaft.json @@ -42,7 +42,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 26, "x": 13, "y": -4 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/more_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/more_rituals.json index 747a90e7a..2d0420ea5 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/more_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/more_rituals.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 1, "category": "getting_started", - "category_to_open": "occultism:rituals", + "category_to_open": "rituals", "description": "book.occultism.dictionary_of_spirits.getting_started.more_rituals.description", "hide_while_locked": false, "icon": { @@ -20,7 +20,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 17, "x": 5, - "y": 2 + "y": 4 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/otherworld_goggles.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/otherworld_goggles.json index f0b7af41b..31f67e4dc 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/otherworld_goggles.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/otherworld_goggles.json @@ -42,7 +42,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 20, "x": 5, "y": -2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/possession_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/possession_rituals.json index 86fb0f89e..52b292d1d 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/possession_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/possession_rituals.json @@ -43,7 +43,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 28, "x": 9, - "y": 4 + "y": 6 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_prep_bowl.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_prep_bowl.json index 6505bb209..59aac2f7f 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_prep_bowl.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_prep_bowl.json @@ -65,7 +65,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 10, "x": -1, - "y": -2 + "y": 0 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_prep_chalk.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_prep_chalk.json index 9efdfbc2e..5fa79b4f5 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_prep_chalk.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_prep_chalk.json @@ -97,7 +97,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 8, "x": -3, - "y": -2 + "y": 0 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_satchels.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_satchels.json new file mode 100644 index 000000000..9d842e75e --- /dev/null +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/ritual_satchels.json @@ -0,0 +1,48 @@ +{ + "background_u_index": 0, + "background_v_index": 0, + "category": "getting_started", + "description": "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.description", + "hide_while_locked": false, + "icon": { + "item": "occultism:ritual_satchel_t1" + }, + "name": "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.name", + "pages": [ + { + "type": "modonomicon:spotlight", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "item": { + "item": "occultism:ritual_satchel_t1" + }, + "text": "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.spotlight.text", + "title": "" + }, + { + "type": "modonomicon:text", + "anchor": "", + "condition": { + "type": "modonomicon:none" + }, + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.more.text", + "title": "book.occultism.dictionary_of_spirits.getting_started.ritual_satchels.more.title", + "use_markdown_in_title": false + } + ], + "parents": [ + { + "draw_arrow": true, + "entry": "getting_started/chalks", + "line_enabled": true, + "line_reversed": false + } + ], + "show_when_any_parent_unlocked": false, + "sort_number": 16, + "x": 9, + "y": 2 +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirit_fire.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirit_fire.json index a4aa36755..bebf199c7 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirit_fire.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirit_fire.json @@ -100,7 +100,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 2, "x": -7, - "y": 0 + "y": 2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirit_miners.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirit_miners.json index 40c9f4967..33f019c81 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirit_miners.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirit_miners.json @@ -42,7 +42,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 25, "x": 13, "y": -2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirits.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirits.json index 290193d92..6221c48a5 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirits.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/spirits.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 1, "category": "getting_started", - "category_to_open": "occultism:spirits", + "category_to_open": "spirits", "description": "", "hide_while_locked": false, "icon": { @@ -20,7 +20,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 19, "x": 5, - "y": 4 + "y": 6 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/storage.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/storage.json index 645fe8617..56c32a36a 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/storage.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/storage.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 1, "category": "getting_started", - "category_to_open": "occultism:storage", + "category_to_open": "storage", "description": "book.occultism.dictionary_of_spirits.getting_started.storage.description", "hide_while_locked": false, "icon": { @@ -18,7 +18,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 27, "x": 7, "y": 0 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/summoning_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/summoning_rituals.json index a719404a5..b0aba7de0 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/summoning_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/summoning_rituals.json @@ -43,7 +43,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 30, "x": 13, - "y": 4 + "y": 6 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/theurgy_divination_rod.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/theurgy_divination_rod.json index dae540390..457b578b1 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/theurgy_divination_rod.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/theurgy_divination_rod.json @@ -77,7 +77,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 6, "x": -7, - "y": -4 + "y": -2 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/third_eye.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/third_eye.json index 2a257fb18..61558fd31 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/third_eye.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/getting_started/third_eye.json @@ -55,7 +55,7 @@ } ], "show_when_any_parent_unlocked": false, - "sort_number": -1, + "sort_number": 4, "x": -11, - "y": 2 + "y": 4 } \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/possession_rituals/return_to_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/possession_rituals/return_to_rituals.json index a4d1e0f9b..b0b34f858 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/possession_rituals/return_to_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/possession_rituals/return_to_rituals.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 2, "category": "possession_rituals", - "category_to_open": "occultism:rituals", + "category_to_open": "rituals", "condition": { "type": "modonomicon:true" }, diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/crafting_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/crafting_rituals.json index 7ae74579d..cce49a6f7 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/crafting_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/crafting_rituals.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 1, "category": "rituals", - "category_to_open": "occultism:crafting_rituals", + "category_to_open": "crafting_rituals", "condition": { "type": "modonomicon:true" }, diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/familiar_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/familiar_rituals.json index a904cab51..841e4b9e8 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/familiar_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/familiar_rituals.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 1, "category": "rituals", - "category_to_open": "occultism:familiar_rituals", + "category_to_open": "familiar_rituals", "condition": { "type": "modonomicon:true" }, diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/possession_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/possession_rituals.json index 397ecdb9b..a74929bef 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/possession_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/possession_rituals.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 1, "category": "rituals", - "category_to_open": "occultism:possession_rituals", + "category_to_open": "possession_rituals", "condition": { "type": "modonomicon:true" }, diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/summoning_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/summoning_rituals.json index 64d371a5b..397fcaa35 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/summoning_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/rituals/summoning_rituals.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 1, "category": "rituals", - "category_to_open": "occultism:summoning_rituals", + "category_to_open": "summoning_rituals", "condition": { "type": "modonomicon:true" }, diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/spirits/return_to_getting_started.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/spirits/return_to_getting_started.json index b779490b1..2215a2349 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/spirits/return_to_getting_started.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/spirits/return_to_getting_started.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 2, "category": "spirits", - "category_to_open": "occultism:getting_started", + "category_to_open": "getting_started", "condition": { "type": "modonomicon:true" }, diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/summoning_rituals/return_to_rituals.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/summoning_rituals/return_to_rituals.json index 55ee972a4..ffd873452 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/summoning_rituals/return_to_rituals.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/summoning_rituals/return_to_rituals.json @@ -2,7 +2,7 @@ "background_u_index": 1, "background_v_index": 2, "category": "summoning_rituals", - "category_to_open": "occultism:rituals", + "category_to_open": "rituals", "condition": { "type": "modonomicon:true" }, diff --git a/src/generated/resources/data/occultism/recipe/ritual/craft_ritual_satchel_t1.json b/src/generated/resources/data/occultism/recipe/ritual/craft_ritual_satchel_t1.json new file mode 100644 index 000000000..4457168a9 --- /dev/null +++ b/src/generated/resources/data/occultism/recipe/ritual/craft_ritual_satchel_t1.json @@ -0,0 +1,43 @@ +{ + "type": "occultism:ritual", + "activation_item": { + "item": "occultism:book_of_binding_bound_djinni" + }, + "duration": 240, + "ingredients": [ + { + "item": "minecraft:hopper" + }, + { + "item": "minecraft:dispenser" + }, + { + "tag": "minecraft:wool" + }, + { + "tag": "minecraft:wool" + }, + { + "tag": "c:leathers" + }, + { + "tag": "c:leathers" + }, + { + "tag": "c:strings" + }, + { + "tag": "c:ingots/silver" + } + ], + "pentacle_id": "occultism:craft_djinni", + "result": { + "count": 1, + "id": "occultism:ritual_satchel_t1" + }, + "ritual_dummy": { + "count": 1, + "id": "occultism:ritual_dummy/craft_ritual_satchel_t1" + }, + "ritual_type": "occultism:craft_with_spirit_name" +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/recipe/ritual/craft_ritual_satchel_t2.json b/src/generated/resources/data/occultism/recipe/ritual/craft_ritual_satchel_t2.json new file mode 100644 index 000000000..492fa0d4d --- /dev/null +++ b/src/generated/resources/data/occultism/recipe/ritual/craft_ritual_satchel_t2.json @@ -0,0 +1,37 @@ +{ + "type": "occultism:ritual", + "activation_item": { + "item": "occultism:book_of_binding_bound_afrit" + }, + "duration": 240, + "ingredients": [ + { + "item": "occultism:ritual_satchel_t1" + }, + { + "item": "occultism:afrit_essence" + }, + { + "tag": "c:ender_pearls" + }, + { + "tag": "c:ender_pearls" + }, + { + "tag": "c:ender_pearls" + }, + { + "tag": "c:ender_pearls" + } + ], + "pentacle_id": "occultism:craft_djinni", + "result": { + "count": 1, + "id": "occultism:ritual_satchel_t2" + }, + "ritual_dummy": { + "count": 1, + "id": "occultism:ritual_dummy/craft_ritual_satchel_t2" + }, + "ritual_type": "occultism:craft_with_spirit_name" +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/tags/block/chalk_glyphs.json b/src/generated/resources/data/occultism/tags/block/chalk_glyphs.json new file mode 100644 index 000000000..1a653652a --- /dev/null +++ b/src/generated/resources/data/occultism/tags/block/chalk_glyphs.json @@ -0,0 +1,20 @@ +{ + "values": [ + "occultism:chalk_glyph_white", + "occultism:chalk_glyph_gold", + "occultism:chalk_glyph_purple", + "occultism:chalk_glyph_red", + "occultism:chalk_glyph_light_gray", + "occultism:chalk_glyph_gray", + "occultism:chalk_glyph_black", + "occultism:chalk_glyph_brown", + "occultism:chalk_glyph_orange", + "occultism:chalk_glyph_lime", + "occultism:chalk_glyph_green", + "occultism:chalk_glyph_cyan", + "occultism:chalk_glyph_light_blue", + "occultism:chalk_glyph_blue", + "occultism:chalk_glyph_magenta", + "occultism:chalk_glyph_pink" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/tags/block/pentacle_materials.json b/src/generated/resources/data/occultism/tags/block/pentacle_materials.json new file mode 100644 index 000000000..064238070 --- /dev/null +++ b/src/generated/resources/data/occultism/tags/block/pentacle_materials.json @@ -0,0 +1,15 @@ +{ + "values": [ + "#c:skulls", + "occultism:golden_sacrificial_bowl", + "occultism:spirit_attuned_crystal", + { + "id": "#occultism:candles", + "required": false + }, + { + "id": "#occultism:chalk_glyphs", + "required": false + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/tags/item/pentacle_materials.json b/src/generated/resources/data/occultism/tags/item/pentacle_materials.json new file mode 100644 index 000000000..2bbeab87b --- /dev/null +++ b/src/generated/resources/data/occultism/tags/item/pentacle_materials.json @@ -0,0 +1,19 @@ +{ + "values": [ + { + "id": "#occultism:tools/chalk", + "required": false + }, + "#c:skulls", + "occultism:golden_sacrificial_bowl", + "occultism:spirit_attuned_crystal", + { + "id": "#occultism:candles", + "required": false + }, + { + "id": "#occultism:chalk_glyphs", + "required": false + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/tags/item/tools/chalks.json b/src/generated/resources/data/occultism/tags/item/tools/chalk.json similarity index 100% rename from src/generated/resources/data/occultism/tags/item/tools/chalks.json rename to src/generated/resources/data/occultism/tags/item/tools/chalk.json diff --git a/src/main/java/com/klikli_dev/occultism/TranslationKeys.java b/src/main/java/com/klikli_dev/occultism/TranslationKeys.java index 09a7ec3e8..aed98570c 100644 --- a/src/main/java/com/klikli_dev/occultism/TranslationKeys.java +++ b/src/main/java/com/klikli_dev/occultism/TranslationKeys.java @@ -35,4 +35,8 @@ public class TranslationKeys { public static final String HUD_NO_PENTACLE_FOUND = "hud." + Occultism.MODID + ".no_pentacle_found"; public static final String HUD_PENTACLE_FOUND = "hud." + Occultism.MODID + ".pentacle_found"; + + public static final String RITUAL_SATCHEL_NO_PREVIEW_IN_WORLD = ITEM + ".ritual_satchel.no_preview_in_world"; + public static final String RITUAL_SATCHEL_NO_PREVIEW_BLOCK_TARGETED = ITEM + ".ritual_satchel.no_preview_block_targeted"; + public static final String RITUAL_SATCHEL_NO_VALID_ITEM_IN_SATCHEL = ITEM + ".ritual_satchel.no_valid_item_in_satchel"; } diff --git a/src/main/java/com/klikli_dev/occultism/client/gui/satchel/RitualSatchelScreen.java b/src/main/java/com/klikli_dev/occultism/client/gui/satchel/RitualSatchelScreen.java new file mode 100644 index 000000000..7dd97f900 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/client/gui/satchel/RitualSatchelScreen.java @@ -0,0 +1,72 @@ +/* + * MIT License + * + * Copyright 2020 klikli-dev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.klikli_dev.occultism.client.gui.satchel; + +import com.klikli_dev.occultism.Occultism; +import com.klikli_dev.occultism.common.container.satchel.AbstractSatchelContainer; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; + +public class RitualSatchelScreen extends AbstractContainerScreen { + protected static final ResourceLocation BACKGROUND = ResourceLocation.fromNamespaceAndPath(Occultism.MODID, + "textures/gui/inventory_ritual_satchel.png"); + + public RitualSatchelScreen(AbstractSatchelContainer screenContainer, Inventory inv, + Component titleIn) { + super(screenContainer, inv, titleIn); + + this.imageWidth = 176; + this.imageHeight = 166; + } + + @Override + protected void init() { + super.init(); + this.leftPos = (this.width - this.imageWidth) / 2; + this.topPos = Math.max(0, (this.height - this.imageHeight) / 2); + } + + @Override + public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) { +// this.renderBackground(guiGraphics); called in super + super.render(guiGraphics, mouseX, mouseY, partialTicks); + this.renderTooltip(guiGraphics, mouseX, mouseY); + } + + @Override + protected void renderLabels(GuiGraphics guiGraphics, int pMouseX, int pMouseY) { + //prevent default labels being rendered + } + + @Override + protected void renderBg(GuiGraphics guiGraphics, float partialTicks, int mouseX, + int mouseY) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + guiGraphics.blit(BACKGROUND, this.leftPos, this.topPos, 0, 0, this.imageWidth, + this.imageHeight); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/client/gui/storage/SatchelScreen.java b/src/main/java/com/klikli_dev/occultism/client/gui/satchel/SatchelScreen.java similarity index 90% rename from src/main/java/com/klikli_dev/occultism/client/gui/storage/SatchelScreen.java rename to src/main/java/com/klikli_dev/occultism/client/gui/satchel/SatchelScreen.java index 6fbe9b160..93d7696c1 100644 --- a/src/main/java/com/klikli_dev/occultism/client/gui/storage/SatchelScreen.java +++ b/src/main/java/com/klikli_dev/occultism/client/gui/satchel/SatchelScreen.java @@ -20,10 +20,10 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -package com.klikli_dev.occultism.client.gui.storage; +package com.klikli_dev.occultism.client.gui.satchel; import com.klikli_dev.occultism.Occultism; -import com.klikli_dev.occultism.common.container.storage.SatchelContainer; +import com.klikli_dev.occultism.common.container.satchel.AbstractSatchelContainer; import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; @@ -31,11 +31,11 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; -public class SatchelScreen extends AbstractContainerScreen { +public class SatchelScreen extends AbstractContainerScreen { protected static final ResourceLocation BACKGROUND = ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "textures/gui/inventory_satchel.png"); - public SatchelScreen(SatchelContainer screenContainer, Inventory inv, + public SatchelScreen(AbstractSatchelContainer screenContainer, Inventory inv, Component titleIn) { super(screenContainer, inv, titleIn); diff --git a/src/main/java/com/klikli_dev/occultism/client/keybindings/BackpackKeyConflictContext.java b/src/main/java/com/klikli_dev/occultism/client/keybindings/BackpackKeyConflictContext.java index 6f9521cee..c829a67a8 100644 --- a/src/main/java/com/klikli_dev/occultism/client/keybindings/BackpackKeyConflictContext.java +++ b/src/main/java/com/klikli_dev/occultism/client/keybindings/BackpackKeyConflictContext.java @@ -1,6 +1,6 @@ package com.klikli_dev.occultism.client.keybindings; -import com.klikli_dev.occultism.client.gui.storage.SatchelScreen; +import com.klikli_dev.occultism.client.gui.satchel.SatchelScreen; import net.minecraft.client.Minecraft; import net.neoforged.neoforge.client.settings.IKeyConflictContext; import net.neoforged.neoforge.client.settings.KeyConflictContext; diff --git a/src/main/java/com/klikli_dev/occultism/common/container/storage/SatchelContainer.java b/src/main/java/com/klikli_dev/occultism/common/container/satchel/AbstractSatchelContainer.java similarity index 76% rename from src/main/java/com/klikli_dev/occultism/common/container/storage/SatchelContainer.java rename to src/main/java/com/klikli_dev/occultism/common/container/satchel/AbstractSatchelContainer.java index e7fafe4b1..1015ef76f 100644 --- a/src/main/java/com/klikli_dev/occultism/common/container/storage/SatchelContainer.java +++ b/src/main/java/com/klikli_dev/occultism/common/container/satchel/AbstractSatchelContainer.java @@ -20,44 +20,44 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -package com.klikli_dev.occultism.common.container.storage; +package com.klikli_dev.occultism.common.container.satchel; -import com.klikli_dev.occultism.registry.OccultismContainers; import com.klikli_dev.occultism.registry.OccultismItems; import com.klikli_dev.occultism.util.CuriosUtil; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.Container; -import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -public class SatchelContainer extends AbstractContainerMenu { +import javax.annotation.Nullable; + +public abstract class AbstractSatchelContainer extends AbstractContainerMenu { - public static final int SATCHEL_SIZE = 13 * 9; protected Container satchelInventory; protected Inventory playerInventory; protected int selectedSlot; + protected ItemStack satchelStack; - public SatchelContainer(int id, Inventory playerInventory, Container satchelInventory, int selectedSlot) { - super(OccultismContainers.SATCHEL.get(), id); + public AbstractSatchelContainer(@Nullable MenuType menuType, int id, Inventory playerInventory, Container satchelInventory, int selectedSlot) { + super(menuType, id); this.satchelInventory = satchelInventory; this.playerInventory = playerInventory; this.selectedSlot = selectedSlot; + if (this.selectedSlot == -1) { + this.satchelStack = CuriosUtil.getBackpack(playerInventory.player); + } + + this.satchelStack = playerInventory.player.getInventory().getItem(this.selectedSlot).copy(); + this.setupSatchelSlots(); this.setupPlayerInventorySlots(); this.setupPlayerHotbar(); } - //region Static Methods - public static SatchelContainer createClientContainer(int id, Inventory playerInventory, FriendlyByteBuf buffer) { - final int selectedSlot = buffer.readVarInt(); - return new SatchelContainer(id, playerInventory, new SimpleContainer(SATCHEL_SIZE), selectedSlot); - } - @Override public void broadcastChanges() { if (this.satchelInventory instanceof SatchelInventory) { @@ -105,13 +105,12 @@ else if (!this.moveItemStackTo(itemstack1, 0, this.satchelInventory.getContainer @Override public boolean stillValid(Player player) { if (this.selectedSlot == -1) { - return CuriosUtil.getBackpack(player).getItem() == OccultismItems.SATCHEL.get(); + return CuriosUtil.getBackpack(player).getItem() == this.satchelStack.getItem(); } if (this.selectedSlot < 0 || this.selectedSlot >= player.getInventory().getContainerSize()) return false; - return player.getInventory().getItem(this.selectedSlot).getItem() == OccultismItems.SATCHEL.get(); + return player.getInventory().getItem(this.selectedSlot).getItem() == this.satchelStack.getItem(); } - //endregion Static Methods protected void setupPlayerInventorySlots() { int playerInventoryTop = 174; @@ -132,18 +131,6 @@ protected void setupPlayerHotbar() { } } - protected void setupSatchelSlots() { - //8x 8y for satchel - int height = 9; - int width = 13; - int x = 8; - int y = 8; - - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { - this.addSlot(new SatchelSlot(this.satchelInventory, j + i * width, x + j * 18, y + i * 18)); - } - } - } + protected abstract void setupSatchelSlots(); } diff --git a/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelContainer.java b/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelContainer.java new file mode 100644 index 000000000..4a6dccaa4 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelContainer.java @@ -0,0 +1,52 @@ +package com.klikli_dev.occultism.common.container.satchel; + +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; + +import javax.annotation.Nullable; + +public abstract class RitualSatchelContainer extends AbstractSatchelContainer { + public static final int SATCHEL_SIZE = 4 * 9; + + public RitualSatchelContainer(@Nullable MenuType menuType, int id, Inventory playerInventory, Container satchelInventory, int selectedSlot) { + super(menuType, id, playerInventory, satchelInventory, selectedSlot); + } + + @Override + protected void setupPlayerInventorySlots() { + int playerInventoryTop = 84; + int playerInventoryLeft = 8; + int hotbarSlots = 9; + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 9; j++) + this.addSlot(new Slot(this.playerInventory, j + i * 9 + hotbarSlots, playerInventoryLeft + j * 18, + playerInventoryTop + i * 18)); + } + + @Override + protected void setupPlayerHotbar() { + int hotbarTop = 142; + int hotbarLeft = 8; + for (int i = 0; i < 9; i++) { + this.addSlot(new Slot(this.playerInventory, i, hotbarLeft + i * 18, hotbarTop)); + } + } + + @Override + protected void setupSatchelSlots() { + //8x 8y for satchel + int height = 4; + int width = 9; + int x = 8; + int y = 8; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + this.addSlot(new RitualSatchelSlot(this.satchelInventory, j + i * width, x + j * 18, y + i * 18)); + } + } + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelSlot.java b/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelSlot.java new file mode 100644 index 000000000..56494fb1b --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelSlot.java @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright 2021 klikli-dev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.klikli_dev.occultism.common.container.satchel; + +import com.klikli_dev.occultism.registry.OccultismItems; +import com.klikli_dev.occultism.registry.OccultismTags; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +public class RitualSatchelSlot extends Slot { + public RitualSatchelSlot(Container inventoryIn, int index, int xPosition, int yPosition) { + super(inventoryIn, index, xPosition, yPosition); + } + + @Override + public boolean mayPlace(ItemStack stack) { + if(stack.is(OccultismItems.RITUAL_SATCHEL_T1) || stack.is(OccultismItems.RITUAL_SATCHEL_T2)) + return false; //technically not necessary because they are not in pentacle materials, but just to make sure no datapack messes it up by accident. + + if(!stack.is(OccultismTags.Items.PENTACLE_MATERIALS)) + return false; + + return super.mayPlace(stack); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelT1Container.java b/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelT1Container.java new file mode 100644 index 000000000..9ddca98ff --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelT1Container.java @@ -0,0 +1,18 @@ +package com.klikli_dev.occultism.common.container.satchel; + +import com.klikli_dev.occultism.registry.OccultismContainers; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; + +public class RitualSatchelT1Container extends RitualSatchelContainer { + public RitualSatchelT1Container(int id, Inventory playerInventory, Container satchelInventory, int selectedSlot) { + super(OccultismContainers.RITUAL_SATCHEL_T1.get(), id, playerInventory, satchelInventory, selectedSlot); + } + + public static RitualSatchelT1Container createClientContainer(int id, Inventory playerInventory, FriendlyByteBuf buffer) { + final int selectedSlot = buffer.readVarInt(); + return new RitualSatchelT1Container(id, playerInventory, new SimpleContainer(RitualSatchelContainer.SATCHEL_SIZE), selectedSlot); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelT2Container.java b/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelT2Container.java new file mode 100644 index 000000000..8494c1d45 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/container/satchel/RitualSatchelT2Container.java @@ -0,0 +1,18 @@ +package com.klikli_dev.occultism.common.container.satchel; + +import com.klikli_dev.occultism.registry.OccultismContainers; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; + +public class RitualSatchelT2Container extends RitualSatchelContainer { + public RitualSatchelT2Container(int id, Inventory playerInventory, Container satchelInventory, int selectedSlot) { + super(OccultismContainers.RITUAL_SATCHEL_T2.get(), id, playerInventory, satchelInventory, selectedSlot); + } + + public static RitualSatchelT2Container createClientContainer(int id, Inventory playerInventory, FriendlyByteBuf buffer) { + final int selectedSlot = buffer.readVarInt(); + return new RitualSatchelT2Container(id, playerInventory, new SimpleContainer(RitualSatchelContainer.SATCHEL_SIZE), selectedSlot); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/container/storage/SatchelInventory.java b/src/main/java/com/klikli_dev/occultism/common/container/satchel/SatchelInventory.java similarity index 97% rename from src/main/java/com/klikli_dev/occultism/common/container/storage/SatchelInventory.java rename to src/main/java/com/klikli_dev/occultism/common/container/satchel/SatchelInventory.java index a50ab4f7e..4882c682d 100644 --- a/src/main/java/com/klikli_dev/occultism/common/container/storage/SatchelInventory.java +++ b/src/main/java/com/klikli_dev/occultism/common/container/satchel/SatchelInventory.java @@ -20,7 +20,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -package com.klikli_dev.occultism.common.container.storage; +package com.klikli_dev.occultism.common.container.satchel; import net.minecraft.core.component.DataComponents; import net.minecraft.world.SimpleContainer; diff --git a/src/main/java/com/klikli_dev/occultism/common/container/satchel/StorageSatchelContainer.java b/src/main/java/com/klikli_dev/occultism/common/container/satchel/StorageSatchelContainer.java new file mode 100644 index 000000000..6d190d954 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/container/satchel/StorageSatchelContainer.java @@ -0,0 +1,57 @@ +package com.klikli_dev.occultism.common.container.satchel; + +import com.klikli_dev.occultism.registry.OccultismContainers; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.Slot; + +public class StorageSatchelContainer extends AbstractSatchelContainer { + public static final int SATCHEL_SIZE = 13 * 9; + + public StorageSatchelContainer(int id, Inventory playerInventory, Container satchelInventory, int selectedSlot) { + super(OccultismContainers.SATCHEL.get(), id, playerInventory, satchelInventory, selectedSlot); + } + + public static StorageSatchelContainer createClientContainer(int id, Inventory playerInventory, FriendlyByteBuf buffer) { + final int selectedSlot = buffer.readVarInt(); + return new StorageSatchelContainer(id, playerInventory, new SimpleContainer(SATCHEL_SIZE), selectedSlot); + } + + @Override + protected void setupPlayerInventorySlots() { + int playerInventoryTop = 174; + int playerInventoryLeft = 44; + int hotbarSlots = 9; + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 9; j++) + this.addSlot(new Slot(this.playerInventory, j + i * 9 + hotbarSlots, playerInventoryLeft + j * 18, + playerInventoryTop + i * 18)); + } + + @Override + protected void setupPlayerHotbar() { + int hotbarTop = 232; + int hotbarLeft = 44; + for (int i = 0; i < 9; i++) { + this.addSlot(new Slot(this.playerInventory, i, hotbarLeft + i * 18, hotbarTop)); + } + } + + @Override + protected void setupSatchelSlots() { + //8x 8y for satchel + int height = 9; + int width = 13; + int x = 8; + int y = 8; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + this.addSlot(new StorageSatchelSlot(this.satchelInventory, j + i * width, x + j * 18, y + i * 18)); + } + } + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/container/storage/SatchelSlot.java b/src/main/java/com/klikli_dev/occultism/common/container/satchel/StorageSatchelSlot.java similarity index 88% rename from src/main/java/com/klikli_dev/occultism/common/container/storage/SatchelSlot.java rename to src/main/java/com/klikli_dev/occultism/common/container/satchel/StorageSatchelSlot.java index e9b2b81bf..da9924df9 100644 --- a/src/main/java/com/klikli_dev/occultism/common/container/storage/SatchelSlot.java +++ b/src/main/java/com/klikli_dev/occultism/common/container/satchel/StorageSatchelSlot.java @@ -20,15 +20,15 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -package com.klikli_dev.occultism.common.container.storage; +package com.klikli_dev.occultism.common.container.satchel; import com.klikli_dev.occultism.registry.OccultismItems; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -public class SatchelSlot extends Slot { - public SatchelSlot(Container inventoryIn, int index, int xPosition, int yPosition) { +public class StorageSatchelSlot extends Slot { + public StorageSatchelSlot(Container inventoryIn, int index, int xPosition, int yPosition) { super(inventoryIn, index, xPosition, yPosition); } diff --git a/src/main/java/com/klikli_dev/occultism/common/item/storage/SatchelItem.java b/src/main/java/com/klikli_dev/occultism/common/item/storage/SatchelItem.java index bc29915e9..abdff2da0 100644 --- a/src/main/java/com/klikli_dev/occultism/common/item/storage/SatchelItem.java +++ b/src/main/java/com/klikli_dev/occultism/common/item/storage/SatchelItem.java @@ -22,11 +22,12 @@ package com.klikli_dev.occultism.common.item.storage; -import com.klikli_dev.occultism.common.container.storage.SatchelContainer; -import com.klikli_dev.occultism.common.container.storage.SatchelInventory; +import com.klikli_dev.occultism.common.container.satchel.AbstractSatchelContainer; +import com.klikli_dev.occultism.common.container.satchel.SatchelInventory; +import com.klikli_dev.occultism.common.container.satchel.StorageSatchelContainer; +import com.klikli_dev.occultism.registry.OccultismContainers; import com.klikli_dev.occultism.util.ItemNBTUtil; import com.klikli_dev.occultism.util.TextUtil; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.*; @@ -35,11 +36,12 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; -import org.jetbrains.annotations.Nullable; + import java.util.List; public class SatchelItem extends Item { + public SatchelItem(Properties properties) { super(properties); } @@ -54,7 +56,7 @@ public InteractionResultHolder use(Level level, Player player, Intera serverPlayer.openMenu( new SimpleMenuProvider((id, playerInventory, unused) -> { - return new SatchelContainer(id, playerInventory, + return new StorageSatchelContainer(id, playerInventory, this.getInventory((ServerPlayer) player, stack), selectedSlot); }, stack.getDisplayName()), buffer -> { buffer.writeVarInt(selectedSlot); @@ -74,7 +76,7 @@ public void appendHoverText(ItemStack pStack, TooltipContext pContext, List glyphBlock) { this.glyphBlock = glyphBlock; } + public Supplier getGlyphBlock() { + return this.glyphBlock; + } + @Override public InteractionResult useOn(UseOnContext context) { Level level = context.getLevel(); diff --git a/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/MultiBlockRitualSatchelItem.java b/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/MultiBlockRitualSatchelItem.java new file mode 100644 index 000000000..e843e4e48 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/MultiBlockRitualSatchelItem.java @@ -0,0 +1,169 @@ +package com.klikli_dev.occultism.common.item.tool.ritual_satchel; + +import com.klikli_dev.modonomicon.api.ModonomiconAPI; +import com.klikli_dev.modonomicon.multiblock.matcher.AnyMatcher; +import com.klikli_dev.modonomicon.multiblock.matcher.DisplayOnlyMatcher; +import com.klikli_dev.occultism.TranslationKeys; +import com.klikli_dev.occultism.common.blockentity.GoldenSacrificialBowlBlockEntity; +import com.klikli_dev.occultism.common.container.satchel.RitualSatchelContainer; +import com.klikli_dev.occultism.common.container.satchel.RitualSatchelT2Container; +import com.klikli_dev.occultism.registry.OccultismBlocks; +import com.klikli_dev.occultism.registry.OccultismRecipes; +import com.klikli_dev.occultism.registry.OccultismTags; +import com.klikli_dev.occultism.util.ItemNBTUtil; +import com.klikli_dev.occultism.util.TextUtil; +import com.mojang.datafixers.util.Function4; +import com.mojang.datafixers.util.Pair; +import net.minecraft.ChatFormatting; +import net.minecraft.Util; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.Container; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.component.ItemContainerContents; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.phys.BlockHitResult; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.level.BlockDropsEvent; +import net.neoforged.neoforge.items.ComponentItemHandler; +import net.neoforged.neoforge.items.ItemHandlerHelper; + +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Places all blocks of a multiblock ritual with just one click. + */ +public class MultiBlockRitualSatchelItem extends RitualSatchelItem { + + public MultiBlockRitualSatchelItem(Properties properties) { + super(properties); + } + + @Override + protected Function4 containerFactory() { + return RitualSatchelT2Container::new; + } + + @Override + protected InteractionResult useOnClientSide(UseOnContext context) { + //non-preview golden sacrifical bowl means we try to collect the ritual pentacle. + if (context.getLevel().getBlockState(context.getClickedPos()).is(OccultismBlocks.GOLDEN_SACRIFICIAL_BOWL.get())) + return InteractionResult.SUCCESS; + + return super.useOnClientSide(context); + } + + protected InteractionResult collectPentacle(UseOnContext context) { + var pentacles = context.getLevel().getRecipeManager().getAllRecipesFor(OccultismRecipes.RITUAL_TYPE.get()).stream() + //First deduplicate pentacles + .collect(Collectors.toMap( + r -> r.value().getPentacle().getId(), // Use pentacle ID as the key + r -> r.value().getPentacle(), // Keep the pentacle as value, this is what we actually want + (existing, replacement) -> existing // In case of key collision, keep the existing value + )).values().stream() + //find the pentacles that are valid for the given golden bowl and store their rotation + .map(pentacle -> Pair.of(pentacle, pentacle.validate(context.getLevel(), context.getClickedPos()))) + .filter(p -> p.getSecond() != null) + .toList(); + + var inventory = new ComponentItemHandler( + context.getItemInHand(), + DataComponents.CONTAINER, + RitualSatchelContainer.SATCHEL_SIZE + ); + + for(var pentacle : pentacles){ + var simulation = pentacle.getFirst().simulate(context.getLevel(), context.getClickedPos(), pentacle.getSecond(), false, false); + + for (var targetMatcher : simulation.getSecond()) { + + if(targetMatcher.getStateMatcher().getType().equals(AnyMatcher.TYPE) || targetMatcher.getStateMatcher().getType().equals(DisplayOnlyMatcher.TYPE)) + continue; + + //if we got here it means the block at the location of the matcher is a valid block for the pentacle. + //however that may also be an "any" or "air" matcher. + var blockState = context.getLevel().getBlockState(targetMatcher.getWorldPosition()); + + if(blockState.isAir()) + continue; + + if(!blockState.is(OccultismTags.Blocks.PENTACLE_MATERIALS)) + continue; + + var blockEntity = context.getLevel().getBlockEntity(targetMatcher.getWorldPosition()); + + var drops = Block.getDrops(blockState, (ServerLevel) context.getLevel(), targetMatcher.getWorldPosition(), blockEntity, null, ItemStack.EMPTY); + + //we might want to use blockdropsevent here (CommonHooks.handleBlockDrops), but it handles item entities, not items .. + + context.getLevel().setBlock(targetMatcher.getWorldPosition(), Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL); + + for(var drop : drops){ + //try to put into satchel, if full -> player inv + + var remainder = ItemHandlerHelper.insertItemStacked(inventory, drop, false); + if(!remainder.isEmpty()) + ItemHandlerHelper.giveItemToPlayer(context.getPlayer(), remainder); + } + } + } + + return InteractionResult.SUCCESS; + } + + @Override + protected InteractionResult useOnServerSide(UseOnContext context) { + if (context.getLevel().getBlockState(context.getClickedPos()).is(OccultismBlocks.GOLDEN_SACRIFICIAL_BOWL.get())) + return this.collectPentacle(context); + + var targetPentacle = this.targetPentacles().get(context.getPlayer().getUUID()); + if (targetPentacle == null || targetPentacle.timeWhenAdded() < context.getLevel().getGameTime() - 5) { + //no or outdated info + return InteractionResult.FAIL; + } + + if (!targetPentacle.target().equals(context.getClickedPos())) { + //silent fail -> the player clicked at two blocks in quick succession, the second block did not send anything to the server as it is not a chalk block, so we ignore. Client side already sent an error message for that second click! + return InteractionResult.FAIL; + } + + var multiblock = ModonomiconAPI.get().getMultiblock(targetPentacle.multiblock()); + var simulation = multiblock.simulate(context.getLevel(), targetPentacle.anchor(), targetPentacle.facing(), false, false); + + boolean placedAnything = false; + for (var targetMatcher : simulation.getSecond()) { + var localContext = new UseOnContext(context.getPlayer(), context.getHand(), + new BlockHitResult(targetMatcher.getWorldPosition().getCenter(), context.getClickedFace(), targetMatcher.getWorldPosition(), false)); + if (this.tryPlaceBlockForMatcher(localContext, targetMatcher)) { + placedAnything = true; + } + } + + if (!placedAnything) { + context.getPlayer().displayClientMessage(Component.translatable(TranslationKeys.RITUAL_SATCHEL_NO_VALID_ITEM_IN_SATCHEL).withStyle(ChatFormatting.YELLOW), true); + return InteractionResult.FAIL; + + } + + return InteractionResult.SUCCESS; + } + + @Override + public void appendHoverText(ItemStack pStack, TooltipContext pContext, List pTooltipComponents, TooltipFlag pTooltipFlag) { + super.appendHoverText(pStack, pContext, pTooltipComponents, pTooltipFlag); + + pTooltipComponents.add(Component.translatable(this.getDescriptionId() + ".tooltip", + TextUtil.formatDemonName(ItemNBTUtil.getBoundSpiritName(pStack)))); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/PentacleData.java b/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/PentacleData.java new file mode 100644 index 000000000..6944b229a --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/PentacleData.java @@ -0,0 +1,9 @@ +package com.klikli_dev.occultism.common.item.tool.ritual_satchel; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Rotation; + +public record PentacleData(ResourceLocation multiblock, BlockPos anchor, Rotation facing, BlockPos target, + long timeWhenAdded) { +} diff --git a/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/RitualSatchelItem.java b/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/RitualSatchelItem.java new file mode 100644 index 000000000..648e3249a --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/RitualSatchelItem.java @@ -0,0 +1,201 @@ +package com.klikli_dev.occultism.common.item.tool.ritual_satchel; + +import com.klikli_dev.modonomicon.api.ModonomiconAPI; +import com.klikli_dev.modonomicon.api.multiblock.Multiblock; +import com.klikli_dev.modonomicon.api.multiblock.StateMatcher; +import com.klikli_dev.modonomicon.multiblock.matcher.AnyMatcher; +import com.klikli_dev.modonomicon.multiblock.matcher.DisplayOnlyMatcher; +import com.klikli_dev.modonomicon.multiblock.matcher.Matchers; +import com.klikli_dev.occultism.TranslationKeys; +import com.klikli_dev.occultism.common.container.satchel.RitualSatchelContainer; +import com.klikli_dev.occultism.common.container.satchel.SatchelInventory; +import com.klikli_dev.occultism.common.item.tool.ChalkItem; +import com.klikli_dev.occultism.network.Networking; +import com.klikli_dev.occultism.network.messages.MessageSendPreviewedPentacle; +import com.mojang.datafixers.util.Function4; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.*; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.ItemContainerContents; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.items.ComponentItemHandler; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.UUID; + +public abstract class RitualSatchelItem extends Item { + private final Map targetPentacles = Object2ObjectMaps.synchronize(new Object2ObjectArrayMap<>()); + + public RitualSatchelItem(Properties properties) { + super(properties); + } + + public Map targetPentacles() { + return this.targetPentacles; + } + + public void setTargetPentacle(UUID player, ResourceLocation multiblock, BlockPos anchor, Rotation facing, BlockPos target, long timeWhenAdded) { + this.targetPentacles.put(player, new PentacleData(multiblock, anchor, facing, target, timeWhenAdded)); + } + + protected void openMenu(ServerPlayer player, ItemStack stack) { + int selectedSlot = player.getInventory().selected; + + player.openMenu( + new SimpleMenuProvider((id, playerInventory, unused) -> { + return this.containerFactory().apply(id, playerInventory, this.getInventory(player, stack), selectedSlot); + }, stack.getDisplayName()), buffer -> { + buffer.writeVarInt(selectedSlot); + }); + } + + public Container getInventory(ServerPlayer player, ItemStack stack) { + return new SatchelInventory(stack, RitualSatchelContainer.SATCHEL_SIZE); + } + + protected boolean tryPlaceBlockForMatcher(UseOnContext context, Multiblock.SimulateResult targetMatcher){ + if(targetMatcher.getStateMatcher().getType().equals(AnyMatcher.TYPE) || targetMatcher.getStateMatcher().getType().equals(DisplayOnlyMatcher.TYPE)) + return false; + + var statePredicate = targetMatcher.getStateMatcher().getStatePredicate(); + + var inventory = new ComponentItemHandler( + context.getItemInHand(), + DataComponents.CONTAINER, + RitualSatchelContainer.SATCHEL_SIZE + ); + + if(!context.getLevel().getBlockState(context.getClickedPos().above()).isAir()) + return false; + + for (int i = 0; i < inventory.getSlots(); i++) { + var stack = inventory.getStackInSlot(i); + + BlockState blockStateToPlace = null; + if (stack.getItem() instanceof BlockItem blockItem) { + var block = blockItem.getBlock(); + var blockPlaceContext = blockItem.updatePlacementContext(new BlockPlaceContext(context)); + if (blockPlaceContext == null) + continue; + + blockStateToPlace = block.getStateForPlacement(blockPlaceContext); + } else if (stack.getItem() instanceof ChalkItem chalkItem) { + var chalkBlock = chalkItem.getGlyphBlock().get(); + blockStateToPlace = chalkBlock.getStateForPlacement(new BlockPlaceContext(context)); + } + + if (blockStateToPlace == null) + continue; + + if (statePredicate.test(context.getLevel(), targetMatcher.getWorldPosition(), blockStateToPlace)) { + //simulate item use + stack.useOn(new UseOnContext(context.getLevel(), context.getPlayer(), context.getHand(), stack, context.getHitResult())); + inventory.setStackInSlot(i, stack); //to force an update of the container if the item was used up or stack size reduced. + return true; + } + } + return false; + } + + /** + * This identifies the pentacle preview and sends it to the server, where the child classes can handle it. + */ + protected InteractionResult useOnClientSide(UseOnContext context){ + Level level = context.getLevel(); + BlockPos pos = context.getClickedPos(); + Player player = context.getPlayer(); + var preview = ModonomiconAPI.get().getCurrentPreviewMultiblock(); + + //First, verify if we have a valid preview in the world + if (preview == null || !preview.isAnchored()) { + player.displayClientMessage(Component.translatable(TranslationKeys.RITUAL_SATCHEL_NO_PREVIEW_IN_WORLD).withStyle(ChatFormatting.YELLOW), true); + return InteractionResult.PASS; + } + + var simulation = preview.multiblock().simulate(level, preview.anchor(), preview.facing(), false, false); + + //Then, check if we are targeting any block of the preview + var targetMatcher = simulation.getSecond().stream().filter(p -> p.getWorldPosition().equals(pos)).findFirst(); + if (targetMatcher.isEmpty() || + targetMatcher.get().getStateMatcher().getType() == AnyMatcher.TYPE || + targetMatcher.get().getStateMatcher().getType() == DisplayOnlyMatcher.TYPE) { + player.sendSystemMessage(Component.translatable(TranslationKeys.RITUAL_SATCHEL_NO_PREVIEW_BLOCK_TARGETED).withStyle(ChatFormatting.YELLOW)); + return InteractionResult.PASS; + } + + Networking.sendToServer(new MessageSendPreviewedPentacle( + preview.multiblock().getId(), + preview.anchor(), + preview.facing(), + pos + )); + + return InteractionResult.SUCCESS; + } + + protected abstract Function4 containerFactory(); + + protected abstract InteractionResult useOnServerSide(UseOnContext context); + + @Override + public boolean isFoil(@NotNull ItemStack stack) { + return true; + } + + @Override + public @NotNull InteractionResultHolder use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) { + if (hand != InteractionHand.MAIN_HAND) + return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand)); + + if (!player.isShiftKeyDown()) + return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand)); + + final ItemStack stack = player.getItemInHand(hand); + + if (!level.isClientSide && player instanceof ServerPlayer serverPlayer) { + this.openMenu(serverPlayer, stack); + } + + return new InteractionResultHolder<>(InteractionResult.SUCCESS, stack); + } + + @Override + public @NotNull InteractionResult useOn(UseOnContext context) { + if (context.getHand() != InteractionHand.MAIN_HAND) + return InteractionResult.PASS; + + if (context.getLevel().isClientSide() && context.getPlayer().isShiftKeyDown()) { + //will allow to open satchel serverside + return InteractionResult.SUCCESS; + } + + if (context.getPlayer() instanceof ServerPlayer serverPlayer && !context.getLevel().isClientSide() && context.getPlayer().isShiftKeyDown()) { + this.openMenu(serverPlayer, context.getItemInHand()); + return InteractionResult.SUCCESS; + } + + if (context.getLevel().isClientSide) { + return this.useOnClientSide(context); + } else { + return this.useOnServerSide(context); + } + } + +} diff --git a/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/SingleBlockRitualSatchelItem.java b/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/SingleBlockRitualSatchelItem.java new file mode 100644 index 000000000..ec684f520 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/item/tool/ritual_satchel/SingleBlockRitualSatchelItem.java @@ -0,0 +1,73 @@ +package com.klikli_dev.occultism.common.item.tool.ritual_satchel; + +import com.klikli_dev.modonomicon.api.ModonomiconAPI; +import com.klikli_dev.occultism.TranslationKeys; +import com.klikli_dev.occultism.common.container.satchel.RitualSatchelT1Container; +import com.klikli_dev.occultism.util.ItemNBTUtil; +import com.klikli_dev.occultism.util.TextUtil; +import com.mojang.datafixers.util.Function4; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.Container; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; + +import java.util.List; + +/** + * Places a single block of a ritual multiblock. + */ +public class SingleBlockRitualSatchelItem extends RitualSatchelItem { + + public SingleBlockRitualSatchelItem(Properties properties) { + super(properties); + } + + @Override + protected Function4 containerFactory() { + return RitualSatchelT1Container::new; + } + + @Override + protected InteractionResult useOnServerSide(UseOnContext context) { + var targetPentacle = this.targetPentacles().get(context.getPlayer().getUUID()); + if (targetPentacle == null || targetPentacle.timeWhenAdded() < context.getLevel().getGameTime() - 5) { + //no or outdated info + return InteractionResult.FAIL; + } + + if (!targetPentacle.target().equals(context.getClickedPos())) { + //silent fail -> the player clicked at two blocks in quick succession, the second block did not send anything to the server as it is not a chalk block, so we ignore. Client side already sent an error message for that second click! + return InteractionResult.FAIL; + } + + var multiblock = ModonomiconAPI.get().getMultiblock(targetPentacle.multiblock()); + var simulation = multiblock.simulate(context.getLevel(), targetPentacle.anchor(), targetPentacle.facing(), false, false); + + var targetMatcher = simulation.getSecond().stream().filter(p -> p.getWorldPosition().equals(context.getClickedPos())).findFirst(); + if (targetMatcher.isEmpty()) { + //should not happen, player clicked a non-preview block + return InteractionResult.FAIL; + } + + if (this.tryPlaceBlockForMatcher(context, targetMatcher.get())) { + return InteractionResult.SUCCESS; + } + + context.getPlayer().displayClientMessage(Component.translatable(TranslationKeys.RITUAL_SATCHEL_NO_VALID_ITEM_IN_SATCHEL).withStyle(ChatFormatting.YELLOW), true); + + return InteractionResult.FAIL; + } + + @Override + public void appendHoverText(ItemStack pStack, TooltipContext pContext, List pTooltipComponents, TooltipFlag pTooltipFlag) { + super.appendHoverText(pStack, pContext, pTooltipComponents, pTooltipFlag); + + pTooltipComponents.add(Component.translatable(this.getDescriptionId() + ".tooltip", + TextUtil.formatDemonName(ItemNBTUtil.getBoundSpiritName(pStack)))); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/datagen/ItemModelsGenerator.java b/src/main/java/com/klikli_dev/occultism/datagen/ItemModelsGenerator.java index 700d955b7..b883e351d 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/ItemModelsGenerator.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/ItemModelsGenerator.java @@ -146,6 +146,8 @@ private void registerItemCommon() { this.name(OccultismItems.CHALK_RED.get()), this.name(OccultismItems.CHALK_RED_IMPURE.get()), this.name(OccultismItems.CHALK_WHITE.get()), + this.name(OccultismItems.RITUAL_SATCHEL_T1.get()), + this.name(OccultismItems.RITUAL_SATCHEL_T2.get()), this.name(OccultismItems.CHALK_WHITE_IMPURE.get()), this.name(OccultismItems.COPPER_DUST.get()), this.name(OccultismItems.CRUSHED_END_STONE.get()), diff --git a/src/main/java/com/klikli_dev/occultism/datagen/OccultismBookProvider.java b/src/main/java/com/klikli_dev/occultism/datagen/OccultismBookProvider.java index 7182d796a..23c33a373 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/OccultismBookProvider.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/OccultismBookProvider.java @@ -14,7 +14,9 @@ import com.klikli_dev.modonomicon.api.datagen.book.condition.BookTrueConditionModel; import com.klikli_dev.modonomicon.api.datagen.book.page.*; import com.klikli_dev.occultism.Occultism; +import com.klikli_dev.occultism.datagen.book.BindingRitualsCategory; import com.klikli_dev.occultism.datagen.book.FamiliarRitualsCategory; +import com.klikli_dev.occultism.datagen.book.GettingStartedCategory; import com.klikli_dev.occultism.integration.modonomicon.pages.*; import com.klikli_dev.occultism.registry.OccultismBlocks; import com.klikli_dev.occultism.registry.OccultismItems; @@ -41,7 +43,7 @@ protected void registerDefaultMacros() { @Override protected void generateCategories() { int sortNum = 1; - var gettingStartedCategory = this.add(this.makeGettingStartedCategory().withSortNumber(sortNum++)); + var gettingStartedCategory = this.add(new GettingStartedCategory(this).generate().withSortNumber(sortNum++)); var spiritsCategory = this.add(this.makeSpiritsSubcategory().withSortNumber(sortNum++)); var storageCategory = this.add(this.makeStorageCategory().withSortNumber(sortNum++)); @@ -50,7 +52,7 @@ protected void generateCategories() { var summoningRitualsCategory = this.add(this.makeSummoningRitualsSubcategory().withSortNumber(sortNum++)); var possessionRitualsCategory = this.add(this.makePossessionRitualsSubcategory().withSortNumber(sortNum++)); - var craftingRitualsCategory = this.add(this.makeCraftingRitualsSubcategory().withSortNumber(sortNum++)); + var craftingRitualsCategory = this.add(new BindingRitualsCategory(this).generate().withSortNumber(sortNum++)); var familiarRitualsCategory = this.add(new FamiliarRitualsCategory(this).generate().withSortNumber(sortNum++)); var pentaclesCategory = this.add(this.makePentaclesCategory().withSortNumber(sortNum++)); @@ -90,4089 +92,1271 @@ protected BookModel additionalSetup(BookModel book) { ; } - //region Getting Started - private BookCategoryModel makeGettingStartedCategory() { - this.context().category("getting_started"); - this.lang().add(this.context().categoryName(), "Getting Started"); + private BookEntryModel makeReturnToRitualsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("return_to_rituals"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/robe.png")) + .withCategoryToOpen(this.modLoc("rituals")) + .withEntryBackground(1, 2) + .withLocation(entryMap.get(icon)); + } + private BookCategoryModel makeSpiritsSubcategory() { + this.context().category("spirits"); + this.lang().add(this.context().categoryName(), "Spirits"); var entryMap = ModonomiconAPI.get().getEntryMap(); entryMap.setMap( - "______ŕ___t___B___________P___D___", - "__________________________________", - "______i___r___ç_b_____g_I_O_l_M___", - "__________________________________", - "______d___f_c_____R___a_s_________", - "__________________________________", - "______e_h_____ạ_______m___________", - "__________________________________", - "______________Á_C___p_S___w_x_y_z_" + "___________________________", + "___________________________", + "___<_0_n_u_w_______________", + "___________________________", + "_____d_____________________", + "___________________________", + "___________________________" ); - //B=brush, N=Next Steps, P=iesnium pick - //i=intro, r=divinationRod, ç = chalk, b=bowls, g=goggles, I=infused pick O= tier 2 otherworld materials - // l=lamps, M=miner, D=Dim Mineshaft - //d=demonsDream, h=healing, f=SpiritFire, c=candle, R=ritual, a=advancedChalks, - //e=thirdEye, ạ=books of binding, m=more ritual, s=storage - //C=book of calling, p=grey particles, S=spirits, w=possession, x=familiars, y=summoning, z=crafting - - var introEntry = this.makeIntroEntry(entryMap, 'i'); - - var demonsDreamEntry = this.makeDemonsDreamEntry(entryMap, 'd'); - demonsDreamEntry.withParent(BookEntryParentModel.create(introEntry.getId())); - - var spiritFireEntry = this.makeSpiritFireEntry(entryMap, 'f'); - spiritFireEntry.withParent(BookEntryParentModel.create(demonsDreamEntry.getId())); - - var healingSpiritsEntry = this.makeHealingSpiritsEntry(entryMap, 'h'); - healingSpiritsEntry.withParent(BookEntryParentModel.create(demonsDreamEntry.getId())); - - var thirdEyeEntry = this.makeThirdEyeEntry(entryMap, 'e'); - thirdEyeEntry.withParent(BookEntryParentModel.create(demonsDreamEntry.getId())); - - var divinationRodEntry = this.makeDivinationRodEntry(entryMap, 'r'); - divinationRodEntry.withParent(BookEntryParentModel.create(spiritFireEntry.getId())); - - var theurgyDivinationRodEntry = this.makeTheurgyDivinationRodsEntry(entryMap, 't'); - theurgyDivinationRodEntry - .withParent(BookEntryParentModel.create(divinationRodEntry.getId())) - .withCondition( - BookAndConditionModel.create().withChildren( - BookEntryReadConditionModel.create() - .withEntry(divinationRodEntry.getId()), - BookModLoadedConditionModel.create() - .withModId("theurgy") - ) - ) - .hideWhileLocked(true); - - var candleEntry = this.makeCandleEntry(entryMap, 'c'); - candleEntry.withParent(BookEntryParentModel.create(spiritFireEntry.getId())); - - var ritualPrepChalkEntry = this.makeRitualPrepChalkEntry(entryMap, 'ç'); - ritualPrepChalkEntry.withParent(BookEntryParentModel.create(candleEntry.getId())); - - var brushEntry = this.makeBrushEntry(entryMap, 'B'); - brushEntry.withParent(BookEntryParentModel.create(ritualPrepChalkEntry.getId())); - - var ritualPrepBowlEntry = this.makeRitualPrepBowlEntry(entryMap, 'b'); - ritualPrepBowlEntry.withParent(BookEntryParentModel.create(ritualPrepChalkEntry.getId())); - - var booksOfBinding = this.makeBooksOfBindingEntry(entryMap, 'ạ'); - booksOfBinding.withParent(BookEntryParentModel.create(candleEntry.getId())); - - var booksOfBindingAutomation = this.makeBooksOfBindingAutomationEntry(entryMap, 'Á'); - booksOfBindingAutomation.withParent(BookEntryParentModel.create(booksOfBinding.getId())); - - var booksOfCalling = this.makeBooksOfCallingEntry(entryMap, 'C'); - booksOfCalling.withParent(BookEntryParentModel.create(booksOfBinding.getId())); - - var ritualEntry = this.makeRitualEntry(entryMap, 'R'); - ritualEntry - .withParent(BookEntryParentModel.create(ritualPrepBowlEntry.getId())) - .withParent(BookEntryParentModel.create(booksOfBinding.getId())); - - var advancedChalksEntry = this.makeChalksEntry(entryMap, 'a'); - advancedChalksEntry.withParent(BookEntryParentModel.create(ritualEntry.getId())); - - var moreRitualsEntry = this.makeMoreRitualsEntry(entryMap, 'm'); - moreRitualsEntry.withParent(BookEntryParentModel.create(advancedChalksEntry.getId())); - - var greyParticlesEntry = this.makeGreyParticlesEntry(entryMap, 'p'); - greyParticlesEntry.withParent(BookEntryParentModel.create(ritualEntry.getId())); - - var spiritsSubcategory = this.makeSpiritsSubcategoryEntry(entryMap, 'S'); - spiritsSubcategory.withParent(BookEntryParentModel.create(greyParticlesEntry.getId())); - var otherworldGoggles = this.makeOtherworldGogglesEntry(entryMap, 'g'); - otherworldGoggles.withParent(BookEntryParentModel.create(advancedChalksEntry.getId())); - - var infusedPickaxe = this.makeInfusedPickaxeEntry(entryMap, 'I'); - infusedPickaxe.withParent(BookEntryParentModel.create(otherworldGoggles.getId())); - - var iesnium = this.makeIesniumEntry(entryMap, 'O'); - iesnium.withParent(BookEntryParentModel.create(infusedPickaxe.getId())); - - var iesniumPickaxe = this.makeIesniumPickaxeEntry(entryMap, 'P'); - iesniumPickaxe.withParent(BookEntryParentModel.create(iesnium.getId())); - - var magicLampsEntry = this.makeMagicLampsEntry(entryMap, 'l'); - magicLampsEntry.withParent(BookEntryParentModel.create(iesnium.getId())); + var overview = this.makeSpiritsOverviewEntry(entryMap, '0'); + var returnToGettingStarted = this.makeReturnToGettingStartedEntry(entryMap, '<'); + returnToGettingStarted.withParent(BookEntryParentModel.create(overview.getId())); + returnToGettingStarted.withCondition(BookTrueConditionModel.create()); - var spiritMinersEntry = this.makeSpiritMinersEntry(entryMap, 'M'); - spiritMinersEntry.withParent(BookEntryParentModel.create(magicLampsEntry.getId())); + var essenceDecay = this.makeEssenceDecayEntry(entryMap, 'd'); + essenceDecay.withParent(BookEntryParentModel.create(overview.getId())); - var mineshaftEntry = this.makeMineshaftEntry(entryMap, 'D'); - mineshaftEntry.withParent(BookEntryParentModel.create(spiritMinersEntry.getId())); + var trueNames = this.makeTrueNamesEntry(entryMap, 'n'); + trueNames.withParent(BookEntryParentModel.create(overview.getId())); - var storageEntry = this.makeStorageEntry(entryMap, 's'); - storageEntry.withParent(BookEntryParentModel.create(advancedChalksEntry.getId())); + var unboundSpirits = this.makeUnboundSpiritsEntry(entryMap, 'u'); + unboundSpirits.withParent(BookEntryParentModel.create(trueNames.getId())); - var possessionRitualsEntry = this.makePossessionRitualsEntry(entryMap, 'w'); - possessionRitualsEntry.withParent(BookEntryParentModel.create(moreRitualsEntry.getId())); - var familiarRitualsEntry = this.makeFamiliarRitualsEntry(entryMap, 'x'); - familiarRitualsEntry.withParent(BookEntryParentModel.create(moreRitualsEntry.getId())); - var summoningRitualsEntry = this.makeSummoningRitualsEntry(entryMap, 'y'); - summoningRitualsEntry.withParent(BookEntryParentModel.create(moreRitualsEntry.getId())); - var craftingRitualsEntry = this.makeCraftingRitualsEntry(entryMap, 'z'); - craftingRitualsEntry.withParent(BookEntryParentModel.create(moreRitualsEntry.getId())); + var wildHunt = this.makeWildHuntEntry(entryMap, 'w'); + wildHunt.withParent(BookEntryParentModel.create(unboundSpirits.getId())); return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) - .withIcon(OccultismItems.DICTIONARY_OF_SPIRITS_ICON.get()) + .withIcon(this.modLoc("textures/gui/book/spirits.png")) + .withShowCategoryButton(true) .withEntries( - introEntry, - demonsDreamEntry, - spiritFireEntry, - thirdEyeEntry, - healingSpiritsEntry, - divinationRodEntry, - theurgyDivinationRodEntry, - candleEntry, - ritualPrepChalkEntry, - ritualPrepBowlEntry, - booksOfBinding, - booksOfBindingAutomation, - ritualEntry, - brushEntry, - moreRitualsEntry, - greyParticlesEntry, - booksOfCalling, - spiritsSubcategory, - advancedChalksEntry, - otherworldGoggles, - infusedPickaxe, - iesnium, - iesniumPickaxe, - magicLampsEntry, - spiritMinersEntry, - mineshaftEntry, - storageEntry, - possessionRitualsEntry, - familiarRitualsEntry, - summoningRitualsEntry, - craftingRitualsEntry + overview, + returnToGettingStarted, + trueNames, + essenceDecay, + unboundSpirits, + wildHunt ); } - private BookEntryModel makeIntroEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("intro"); - this.lang().add(this.context().entryName(), "About"); - this.lang().add(this.context().entryDescription(), "About using the Dictionary of Spirits"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "About"); - this.lang().add(this.context().pageText(), - """ - This book aims to introduce the novice reader to the most common summoning rituals and equip them with a list of spirit names to summon. - The authors advise caution in the summoning of the listed entities and does not take responsibility for any harm caused. - """); - - this.context().page("help"); - var help = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Getting Help"); - this.lang().add(this.context().pageText(), - """ - If you run into any trouble while playing Occultism, please join our Discord server and ask for help. - \\ - \\ - [Join us at https://invite.gg/klikli](https://invite.gg/klikli) - """); + private BookEntryModel makeReturnToGettingStartedEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("return_to_getting_started"); + this.lang().add(this.context().entryName(), "Return to getting started"); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) .withIcon(OccultismItems.DICTIONARY_OF_SPIRITS_ICON.get()) - .withLocation(entryMap.get(icon)) - .withEntryBackground(0, 1) - .withPages( - intro, - help - ); + .withCategoryToOpen(this.modLoc("getting_started")) + .withEntryBackground(1, 2) + .withLocation(entryMap.get(icon)); } - private BookEntryModel makeDemonsDreamEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("demons_dream"); - this.lang().add(this.context().entryName(), "Lifting the Veil"); - this.lang().add(this.context().entryDescription(), "Learn about the Otherworld and the Third Eye."); + private BookEntryModel makeSpiritsOverviewEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("overview"); + this.lang().add(this.context().entryName(), "On Spirits"); + this.lang().add(this.context().entryDescription(), "An overview of the supernatural"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "The Otherworld"); + this.lang().add(this.context().pageTitle(), "On Spirits"); this.lang().add(this.context().pageText(), """ - Hidden from mere human eyes exists another plane of existence, another *dimension* if you will, the [#](%1$s)Otherworld[#](). - This world is populated with entities often referred to as [#](%1$s)Demons[#](). + [#](%1$s)Spirit[#](), commonly referred to also as [#](%1$s)Demon[#](), is a general term for a variety of supernatural entities usually residing in [#](%1$s)The Other Place[#](), a plane of existence entirely separate from our own. """.formatted(COLOR_PURPLE)); - this.context().page("intro2"); - var intro2 = BookTextPageModel.create() + this.context().page("shapes"); + var shapes = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Shapes"); this.lang().add(this.context().pageText(), """ - These Demons possess a wide variety of powers and useful skills, and for centuries magicians have sought to summon them for their own gain. - The first step on the journey to successfully summoning such an Entity is to learn how to interact with the Otherworld. - """); + When in our world Spirits can take a variety of forms, by morphing their essence into [#](%1$s)Chosen Forms[#](). Alternatively, they can inhabit objects or even living beings. + """.formatted(COLOR_PURPLE)); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.DATURA.get())) + this.context().page("tiers"); + var tiers = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Types of Spirits"); this.lang().add(this.context().pageText(), """ - %1$s is a herb that gives humans the [#](%2$s)Third Eye[#](), - allowing them to see where the [#](%2$s)Otherworld[#]() intersects with our own. - Seeds can be found **by breaking grass**. - **Consuming** the grown fruit activates the ability *with a certain chance*. - """.formatted(DEMONS_DREAM, COLOR_PURPLE)); + There are four major "ranks" of spirits identified by researchers, but there are a myriad spirits below and in between these ranks, and some great entities of terrible power, referred to only as [#](%1$s)Greater Spirits[#](), that are beyond classification. + """.formatted(COLOR_PURPLE)); - this.context().page("harvest_effect"); - var harvestEffect = BookTextPageModel.create() + this.context().page("foliot"); + var foliot = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Foliot"); this.lang().add(this.context().pageText(), """ - An additional side effect of %1$s, is **the ability to interact with [#](%2$s)Otherworld[#]() materials**. - This is unique to %1$s, other ways to obtain [#](%2$s)Third Eye[#]() do not yield this ability. - While under the effect of %1$s you are able to **harvest** Otherstone as well as Otherworld trees. - """.formatted(DEMONS_DREAM, COLOR_PURPLE)); - - this.context().page("datura_screenshot"); - var datureScreenshot = BookImagePageModel.create() - .withImages(this.modLoc("textures/gui/book/datura_effect.png")); - //no text + The lowest identified class of spirit. Equipped with some intelligence and a modicum of power they are most often used for manual labor or minor artifacts. + """.formatted(COLOR_PURPLE)); - this.context().page("note_on_spirit_fire"); - var spiritFire = BookTextPageModel.create() + this.context().page("djinni"); + var djinni = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Djinni"); this.lang().add(this.context().pageText(), """ - **Hint**: The otherworld materials you obtain by harvesting under the effects of[#](%2$s)Third Eye[#]() **can be obtained more easily using [](item://occultism:spirit_fire)**. Proceed with the next entry in this book to learn more about spirit fire. - """.formatted(DEMONS_DREAM, COLOR_PURPLE)); + The most commonly summoned class. There is a great variety of Djinni, differing both in intelligence and power. Djinni can be used for a variety of task, ranging from higher artifacts over possession of living beings to carrying out tasks in their Chosen Form. + """.formatted(COLOR_PURPLE)); - this.context().page("spotlight2"); - var spotlight2 = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.DEMONS_DREAM_ESSENCE.get())) + this.context().page("afrit"); + var afrit = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Afrit"); this.lang().add(this.context().pageText(), """ - Multiple Demon's Dream fruits or seeds can be compressed into an essence that is much more potent. It *guarantees* the [#](%2$s)Third Eye[#]() and provides it for a longer amount of time, but comes with a lot of (positive and negative) side effects. - """.formatted(DEMONS_DREAM, COLOR_PURPLE) - ); + Even more powerful than Djinni, Afrit are used for the creation of major artifacts and the possession of powerful beings. + """.formatted(COLOR_PURPLE)); - this.context().page("recipe_essence"); - var recipeEssence = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/demons_dream_essence_from_fruit_or_seed")) + + this.context().page("marid"); + var marid = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Marid"); this.lang().add(this.context().pageText(), """ - Fruit and seeds can be mixed freely to create the essence. - """ - ); + The strongest identified class of spirits. Due to their power and vast intellect attempting a summoning is extremely dangerous and usually only carried out by the most experienced summoners, and even then usually in groups. + """.formatted(COLOR_PURPLE)); - this.context().page("spotlight3"); - var spotlight3 = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.DEMONS_DREAM_ESSENCE.get())) + this.context().page("greater_spirits"); + var greaterSpirits = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Greater Spirits"); this.lang().add(this.context().pageText(), """ - The essence can be purified in spirit fire (more on that later!) to obtain a version free from all negative side effects, while retaining the positive. - """.formatted(DEMONS_DREAM, COLOR_PURPLE) - ); + Spirits of power so great it is beyond measure. No summons have been attempted in living memory, and records of summonings in ancient times are mostly considered apocryphal. + """.formatted(COLOR_PURPLE)); - this.context().page("recipe_essence_pure"); - var recipeEssencePure = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/otherworld_essence")); - //no text return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.DATURA.get()) + .withIcon(this.modLoc("textures/gui/book/spirits.png")) .withLocation(entryMap.get(icon)) + .withEntryBackground(0, 1) .withPages( intro, - intro2, - spotlight, - harvestEffect, - datureScreenshot, - spiritFire, - spotlight2, - recipeEssence, - spotlight3, - recipeEssencePure + shapes, + tiers, + foliot, + djinni, + afrit, + marid, + greaterSpirits ); } - private BookEntryModel makeSpiritFireEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("spirit_fire"); - this.lang().add(this.context().entryName(), "It burns!"); - this.lang().add(this.context().entryDescription(), "Or does it?"); + private BookEntryModel makeEssenceDecayEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("essence_decay"); + this.lang().add(this.context().entryName(), "Essence Decay"); + this.lang().add(this.context().entryDescription(), "Even the immortal are not immune to time."); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.SPIRIT_FIRE.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Essence Decay"); this.lang().add(this.context().pageText(), """ - [#](%1$s)Spiritfire[#]() is a special type of fire that exists mostly in [#](%1$s)The Other Place[#]() - and does not harm living beings. Its special properties allow to use it to purify and convert - certain materials by burning them, without consuming them. + When residing in our plane of existence, spirits experience [#](%1$s)Essence Decay[#](), the slow rot of their "body". The more powerful the spirit, the slower the decay, but only the most powerful can stop it entirely. Once fully decayed they are returned to [#](%1$s)The Other Place[#]() and can only be re-summoned once fully recovered. """.formatted(COLOR_PURPLE)); - this.context().page("spirit_fire_screenshot"); - var spiritFireScreenshot = BookImagePageModel.create() - .withImages(this.modLoc("textures/gui/book/spiritfire_instructions.png")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Throw [](item://occultism:datura) to the ground and light it on fire with [](item://minecraft:flint_and_steel). - """); - - this.context().page("main_uses"); - var mainUses = BookTextPageModel.create() + this.context().page("countermeasures"); + var countermeasures = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Countermeasures"); this.lang().add(this.context().pageText(), """ - The main uses of [](item://occultism:spirit_fire) are to convert [](item://minecraft:diamond) into [](item://occultism:spirit_attuned_gem), - to get basic ingredients such as [](item://occultism:otherstone) and [Otherworld Saplings](item://occultism:otherworld_sapling_natural), - and to purify impure chalks. - """); + The summoner can slow or even stop essence decay by binding the spirit into an object, or summoning it into a living being. Additionally the pentacle used can influence the effects of essence decay to a degree. + """.formatted(COLOR_PURPLE)); - this.context().page("otherstone_recipe"); - var otherstoneRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/otherstone")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - An easier way to obtain [](item://occultism:otherstone) than via divination. - """); - this.context().page("otherworld_sapling_natural_recipe"); - var otherworldSaplingNaturalRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/otherworld_sapling_natural")) + this.context().page("affected_spirits"); + var affectedSpirits = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Affected Spirits"); this.lang().add(this.context().pageText(), """ - An easier way to obtain [Otherworld Saplings](item://occultism:otherworld_sapling_natural) than via divination. - """); - - this.context().page("otherworld_ashes_recipe"); - var otherworldAshesRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/otherworld_ashes")); - //no text - - this.context().page("gem_recipe"); - var gemRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/spirit_attuned_gem")); - //no text - + Only tier 1 spirits are affected by essence decay, by default. All higher tiers are immune and will not despawn. Modpacks may modify this behaviour. + """.formatted(COLOR_PURPLE)); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.SPIRIT_FIRE.get()) + .withIcon(Items.ROTTEN_FLESH) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - spiritFireScreenshot, - mainUses, - otherstoneRecipe, - otherworldSaplingNaturalRecipe, - otherworldAshesRecipe, - gemRecipe + intro, + countermeasures, + affectedSpirits ); } - private BookEntryModel makeHealingSpiritsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("healing_spirits"); - this.lang().add(this.context().entryName(), "Healing Spirits"); - this.lang().add(this.context().entryDescription(), "Fix up your spirit!"); + private BookEntryModel makeTrueNamesEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("true_names"); + this.lang().add(this.context().entryName(), "True Names"); + this.lang().add(this.context().entryDescription(), "How to call spirits."); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.DATURA.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "True Names"); this.lang().add(this.context().pageText(), """ - Right-click a spirit with [](item://occultism:datura) to heal it. + To summon a spirit the magician needs to know their [#](%1$s)True Name[#](). By calling the true naming during the summoning ritual the Spirit is drawn forth from [#](%1$s)The Other Place[#]() and forced to do the summoners bidding. \\ \\ - This will work on **Familiars**, **Summoned Spirits** and also **Possessed Mobs**. - """); + *It should be noted, that it does not matter which spirit name is used in summoning, only the spirit tier is relevant.* + """.formatted(COLOR_PURPLE)); - this.context().page("spotlight2"); - var spotlight2 = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.DEMONS_DREAM_ESSENCE.get())) + this.context().page("finding_names"); + var findingNames = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Finding Names"); this.lang().add(this.context().pageText(), """ - When compressing Demon's Dream fruits or seeds into essence, a much stronger instant healing effect can be achieved. This comes at the cost of efficiency: Feeding 9 fruits to a spirit in succession will heal it more than feeding it 9 fruits worth of essence. - """); + In ancient summoners had to research and experiment to find [#](%1$s)True Names[#](). Some spirits can be convinced to share their knowledge of true names of other demons, either by promising a swift return to [#](%1$s)The Other Place[#](), or by more ... *persuasive* measures. + """.formatted(COLOR_PURPLE)); - this.context().page("spotlight3"); - var spotlight3 = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.OTHERWORLD_ESSENCE.get())) + this.context().page("using_names"); + var usingNames = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Using Names to Summon a Spirit"); this.lang().add(this.context().pageText(), """ - Purifying the Demon's Dream Essence will yield a version that heals even more, negating the efficiency loss. - """); + For your convenience, in this work you will find the known names of spirits of all 4 ranks, as well as some beyond that. To summon a spirit, copy their name from this book into the appropriate book of binding, then use this bound book of binding to activate a ritual. + """.formatted(COLOR_PURPLE)); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) .withDescription(this.context().entryDescription()) - .withIcon(Items.SPLASH_POTION) + .withIcon(Items.WRITABLE_BOOK) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - spotlight2, - spotlight3 + intro, + findingNames, + usingNames ); } - private BookEntryModel makeThirdEyeEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("third_eye"); - this.lang().add(this.context().entryName(), "The Third Eye"); - this.lang().add(this.context().entryDescription(), "Do you see now?"); + private BookEntryModel makeUnboundSpiritsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("unbound_spirits"); + this.lang().add(this.context().entryName(), "Unbound Spirits"); + this.lang().add(this.context().entryDescription(), "Try not to lose your spirits!"); - this.context().page("about"); - var about = BookTextPageModel.create() + this.context().page("intro"); + var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Third Eye"); + this.lang().add(this.context().pageTitle(), "Unbound Spirits"); this.lang().add(this.context().pageText(), """ - The ability to see beyond the physical world is referred to as [#](%1$s)Third Eye[#](). - Humans do not possess such an ability to see [#](%1$s)beyond the veil[#](), - however with certain substances and contraptions the knowledgeable summoner can work around this limitation. - """.formatted(COLOR_PURPLE)); + Generally spirits are summoned [#](%1$s)bound[#](), which refers to any condition that keeps them under control of the summoner. A side effect of binding spells is that part of the spirit remains in [#](%1$s)The Other Place[#](), robbing them of large portions of the power, but at the same time also protecting their essence from foreign access in this world. + """.formatted(COLOR_PURPLE)); - this.context().page("how_to_obtain"); - var howToObtain = BookTextPageModel.create() + this.context().page("unbound"); + var unbound = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Forego the Leash"); this.lang().add(this.context().pageText(), """ - The most comfortable, and most *expensive*, way to obtain this ability, is to wear spectacles - infused with spirits, that *lend* their sight to the wearer. - A slightly more nauseating, but **very affordable** alternative is the consumption of certain herbs, - [%1$s](entry://occultism:dictionary_of_spirits/getting_started/demons_dream) most prominent among them. - """.formatted(DEMONS_DREAM)); + In order to access a spirit's essence, or unleash it's full destructive power, it needs to be summoned [#](%1$s)unbound[#](). Unbound summonings use pentacles that are intentionally incomplete or unstable, allowing to call on the spirit, but not putting any constraints on it. + """.formatted(COLOR_PURPLE)); - this.context().page("otherworld_goggles"); - var otherworldGoggles = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.OTHERWORLD_GOGGLES.get())) + this.context().page("unbound2"); + var unbound2 = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Beware!"); this.lang().add(this.context().pageText(), """ - [These goggles](entry://occultism:dictionary_of_spirits/crafting_rituals/craft_otherworld_goggles) allow to see even more hidden Otherworld blocks, - however they do not allow harvesting those materials. - Low-tier materials can be harvested by consuming [%1$s](entry://occultism:dictionary_of_spirits/getting_started/demons_dream), - but more valuable materials require special tools. - """.formatted(DEMONS_DREAM)); + The lack of restraints when summoning spirits unbound makes these rituals incredibly dangerous, but you may find that the rewards are worth the risk - and often there is no way around them to achieve certain results. + """.formatted(COLOR_PURPLE)); - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + this.context().page("essence"); + var essence = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Spirit Essence"); + this.lang().add(this.context().pageText(), + """ + Unbound summonings are the only way to obtain [Afrit Essence](entry://summoning_rituals/afrit_essence), a powerful substance required for crafting [](item://occultism:chalk_red) which is used for the most powerful binding pentacles. + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) .withDescription(this.context().entryDescription()) - .withIcon(this.modLoc("textures/mob_effect/third_eye.png")) + .withIcon(this.modLoc("textures/gui/book/unbound_spirits.png")) .withLocation(entryMap.get(icon)) - .withPages(about, howToObtain, otherworldGoggles); + .withPages( + intro, + unbound, + unbound2, + essence + ); } - private BookEntryModel makeDivinationRodEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("divination_rod"); - this.lang().add(this.context().entryName(), "Divination Rod"); - this.lang().add(this.context().entryDescription(), "Obtaining otherworld materials"); - + private BookEntryModel makeWildHuntEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("wild_hunt"); + this.lang().add(this.context().entryName(), "The Wild Hunt"); + this.lang().add(this.context().entryDescription(), "You better watch out, you better not cry ..."); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Divination"); + this.lang().add(this.context().pageTitle(), "The Wild Hunt"); this.lang().add(this.context().pageText(), """ - To make it easier to get started, the materials obtained by divination now also have crafting recipes. - **If you want the full experience, skip the following recipe page and move on to the - [divination instructions](entry://occultism:dictionary_of_spirits/getting_started/divination_rod@divination_instructions).** - """); - - this.context().page("otherstone_recipe"); - var otherstoneRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/otherstone")); - //no text + A group of legendary Greater Spirits, usually appearing in the form of wither skeletons, with their skeleton minions. The Greater Spirits are bound to their minions in such fashion that they are virtually invulnerable until their minions have been sent back to [#](%1$s)The Other Place[#](). + """.formatted(COLOR_PURPLE)); - this.context().page("otherworld_sapling_natural_recipe"); - var otherworldSaplingNaturalRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/otherworld_sapling_natural")) + this.context().page("wither_skull"); + var witherSkull = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Wither Skeleton Skulls"); this.lang().add(this.context().pageText(), """ - **Beware**: the tree growing from the sapling will look like a normal oak tree. - You need to activate the [Third Eye](entry://occultism:dictionary_of_spirits/getting_started/demons_dream) - to harvest the Otherworld Logs and Leaves. - """); + While it is incredibly dangerous to call on the Wild Hunt, some summoners have been known to do so for quick access to the rare wither skeleton skulls they are known to leave behind. Summoning the wild hunt is described in detail on the page on obtaining [Wither Skeleton Skulls](entry://summoning_rituals/wither_skull). + """.formatted(COLOR_PURPLE)); - this.context().page("divination_rod"); - var divinationRod = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.DIVINATION_ROD.get())) - .withText(this.context().pageText()) - .withAnchor("divination_instructions"); - this.lang().add(this.context().pageText(), - """ - Otherworld materials play an important role in interacting with spirits. - As they are rare and not visible to the naked eye, finding them requires special tools. - The divination rod allows to find Otherworld materials based on their similarities to materials common to our world. - """); + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(this.modLoc("textures/gui/book/wild_hunt.png")) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + witherSkull + ); + } - this.context().page("spirit_attuned_gem_recipe"); - var spiritAttunedGemRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/spirit_attuned_gem")); + //endregion - this.context().page("divination_rod_recipe"); - var divinationRodRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/divination_rod")); + private BookCategoryModel makePentaclesCategory() { + this.context().category("pentacles"); - this.context().page("about_divination_rod"); - var aboutDivinationRod = BookTextPageModel.create() - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - The divination rod uses a spirit attuned gem attached to a wooden rod. - The gem resonates with the chosen material, and this movement is amplified by the wooden rod, - allowing to detect nearby Otherworld materials. \s - \s - \s - The rod works by detecting resonance between real world and Otherworld materials. - Attuned the rod to a real world material, and it will find the corresponding Otherworld block. - """); - - this.context().page("how_to_use"); - var howToUse = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Use of the Rod"); - this.lang().add(this.context().pageText(), - """ - [#](%1$s)Shift-right-click[#]() a block to attune the rod to the corresponding Otherworld block. - - [](item://minecraft:andesite): [](item://occultism:otherstone) - - [](item://minecraft:oak_wood): [](item://occultism:otherworld_log) - - [](item://minecraft:oak_leaves): [](item://occultism:otherworld_leaves) - - [](item://minecraft:netherrack): [](item://occultism:iesnium_ore) + var entryMap = ModonomiconAPI.get().getEntryMap(); + entryMap.setMap( + "____________________", + "__p_a_b_c_d_e_f_____", //paraphernalia, summon foliot, summon djinni, summon wild afrit, summon afrit, summon marid, summon wild greater spirit + "____________________", + "__o___g_h_i_________", //overview, possess foliot, possess djinni, possess afrit + "____________________", + "__u_j_k_l_m_________", //uses of chalks, craft foliot, craft djinni, craft afrit, craft marid + "____________________" + ); + + var overview = this.makePentaclesOverviewEntry(entryMap, 'o'); + var paraphernalia = this.makeParaphernaliaEntry(entryMap, 'p'); + paraphernalia.withParent(BookEntryParentModel.create(overview.getId())); + var chalkUses = this.makeChalkUsesEntry(entryMap, 'u'); + chalkUses.withParent(BookEntryParentModel.create(overview.getId())); + + var summonFoliot = this.makeSummonFoliotEntry(entryMap, 'a'); + summonFoliot.withParent(BookEntryParentModel.create(overview.getId())); + var summonDjinni = this.makeSummonDjinniEntry(entryMap, 'b'); + summonDjinni.withParent(BookEntryParentModel.create(summonFoliot.getId())); + var summonWildAfrit = this.makeSummonWildAfritEntry(entryMap, 'c'); + summonWildAfrit.withParent(BookEntryParentModel.create(summonDjinni.getId())); + var summonAfrit = this.makeSummonAfritEntry(entryMap, 'd'); + summonAfrit.withParent(BookEntryParentModel.create(summonWildAfrit.getId())); + var summonMarid = this.makeSummonMaridEntry(entryMap, 'e'); + summonMarid.withParent(BookEntryParentModel.create(summonAfrit.getId())); + var summonWildGreaterSpirit = this.makeSummonWildGreaterSpiritEntry(entryMap, 'f'); + summonWildGreaterSpirit.withParent(BookEntryParentModel.create(summonMarid.getId())); + + var possessFoliot = this.makePossessFoliotEntry(entryMap, 'g'); + possessFoliot.withParent(BookEntryParentModel.create(overview.getId())); + var possessDjinni = this.makePossessDjinniEntry(entryMap, 'h'); + possessDjinni.withParent(BookEntryParentModel.create(possessFoliot.getId())); + var possessAfrit = this.makePossessAfritEntry(entryMap, 'i'); + possessAfrit.withParent(BookEntryParentModel.create(possessDjinni.getId())); + + var craftFoliot = this.makeCraftFoliotEntry(entryMap, 'j'); + craftFoliot.withParent(BookEntryParentModel.create(overview.getId())); + var craftDjinni = this.makeCraftDjinniEntry(entryMap, 'k'); + craftDjinni.withParent(BookEntryParentModel.create(craftFoliot.getId())); + var craftAfrit = this.makeCraftAfritEntry(entryMap, 'l'); + craftAfrit.withParent(BookEntryParentModel.create(craftDjinni.getId())); + var craftMarid = this.makeCraftMaridEntry(entryMap, 'm'); + craftMarid.withParent(BookEntryParentModel.create(craftAfrit.getId())); + + //add true condition to all entries to enable them by default + overview.withCondition(BookTrueConditionModel.create()); + paraphernalia.withCondition(BookTrueConditionModel.create()); + chalkUses.withCondition(BookTrueConditionModel.create()); + summonFoliot.withCondition(BookTrueConditionModel.create()); + summonDjinni.withCondition(BookTrueConditionModel.create()); + summonWildAfrit.withCondition(BookTrueConditionModel.create()); + summonAfrit.withCondition(BookTrueConditionModel.create()); + summonMarid.withCondition(BookTrueConditionModel.create()); + summonWildGreaterSpirit.withCondition(BookTrueConditionModel.create()); + possessFoliot.withCondition(BookTrueConditionModel.create()); + possessDjinni.withCondition(BookTrueConditionModel.create()); + possessAfrit.withCondition(BookTrueConditionModel.create()); + craftFoliot.withCondition(BookTrueConditionModel.create()); + craftDjinni.withCondition(BookTrueConditionModel.create()); + craftAfrit.withCondition(BookTrueConditionModel.create()); + craftMarid.withCondition(BookTrueConditionModel.create()); + + return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) + .withIcon(OccultismItems.PENTACLE.get()) + .withEntries( + overview, + paraphernalia, + chalkUses, + + summonFoliot, + summonDjinni, + summonWildAfrit, + summonAfrit, + summonMarid, + summonWildGreaterSpirit, + + possessFoliot, + possessDjinni, + possessAfrit, + + craftFoliot, + craftDjinni, + craftAfrit, + craftMarid + ); + } - Then [#](%1$s)right-click[#]() and hold until the rod animation finishes.""".formatted(COLOR_PURPLE)); + private BookEntryModel makePentaclesOverviewEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("pentacles_overview"); - this.context().page("how_to_use2"); - var howToUse2 = BookTextPageModel.create() + this.context().page("intro1"); + var intro1 = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - After the animation finishes, the closest **found block will be highlighted - with white lines and can be seen through other blocks**. - Additionally you can watch the crystals for hints: a white crystal indicates no target blocks found, - a fully purple block means the found block is nearby. Mixes between white and purple show - that the target is rather far away."""); - this.context().page("how_to_use3"); - var howToUse3 = BookTextPageModel.create() + this.context().page("intro2"); + var intro2 = BookTextPageModel.create() .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - [#](%1$s)Right-clicking[#]() without holding after a successful search will show the last found target block again. - \\ - \\ - If the mod *"Theurgy"* is installed the rod will not highlight the target block, but instead send a particle effect in the direction of the target block. - """.formatted(COLOR_PURPLE)); - this.context().page("divination_rod_screenshots"); - var divinationRodScreenshots = BookImagePageModel.create() - .withImages( - this.modLoc("textures/gui/book/rod_far.png"), - this.modLoc("textures/gui/book/rod_mid.png"), - this.modLoc("textures/gui/book/rod_near.png") - ) + this.context().page("intro3"); + var intro3 = BookTextPageModel.create() .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - White means nothing was found. - The more purple you see, the closer you are. - """); - this.context().page("troubleshooting"); - var troubleshooting = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) + this.context().page("intro4"); + var intro4 = BookTextPageModel.create() .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Troubleshooting"); - this.lang().add(this.context().pageText(), - """ - If the rod does not create highlighted blocks for you, you can try to: - - install theurgy, then a particle effect will be used instead - - Open occultism-client.toml in your instance's /config folder and set useAlternativeDivinationRodRenderer = true - """); + //exact copy found in first ritual entry + this.context().page("bowl_placement"); + var bowlPlacementImage = BookImagePageModel.create() + .withImages(this.modLoc("textures/gui/book/bowl_placement.png")) + .withBorder(true); - this.context().page("otherworld_groves"); - var otherworldGroves = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) + //exact copy found in first ritual entry + this.context().page("bowl_text"); + var bowlText = BookTextPageModel.create() .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Otherworld Groves"); - this.lang().add(this.context().pageText(), - """ - Otherworld Groves are lush, overgrown caves, with [#](%1$s)Otherworld Trees[#](), - and walls of [](item://occultism:otherstone), and represent the fastest way to get everything one - needs to get set up as a summoner. - To find them, attune your divination rod to Otherworld leaves - or logs, as unlike Otherstone, they only spawn in these groves. - """.formatted(COLOR_PURPLE)); - this.context().page("otherworld_groves_2"); - var otherworldGroves2 = BookTextPageModel.create() + this.context().page("summoning_pentacles"); + var summoningPentacles = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - **Hint:** In the Overworld, look **down**. - """); - this.context().page("otherworld_trees"); - var otherworldTrees = BookTextPageModel.create() + this.context().page("infusion_pentacles"); + var infusionPentacles = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Otherworld Trees"); - this.lang().add(this.context().pageText(), - """ - Otherworld trees grow naturally in Otherworld Groves. To the naked eye they appear as oak trees, - but to the Third Eye they reveal their true nature. \s - **Important:** Otherworld Saplings can only be obtained by breaking the leaves manually, naturally only oak saplings drop. - """); - this.context().page("otherworld_trees_2"); - var otherworldTrees2 = BookTextPageModel.create() + this.context().page("possession_pentacles"); + var possessionPentacles = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Trees grown from Stable Otherworld Saplings as obtained from spirit traders do not have that limitation. - """); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.DIVINATION_ROD.get()) + .withIcon(OccultismBlocks.SPIRIT_ATTUNED_CRYSTAL.get()) .withLocation(entryMap.get(icon)) + .withEntryBackground(0, 1) .withPages( - intro, - otherstoneRecipe, - otherworldSaplingNaturalRecipe, - divinationRod, - spiritAttunedGemRecipe, - divinationRodRecipe, - aboutDivinationRod, - howToUse, - howToUse2, - howToUse3, - divinationRodScreenshots, - troubleshooting, - otherworldGroves, - otherworldGroves2, - otherworldTrees, - otherworldTrees2); + intro1, + intro2, + intro3, + intro4, + bowlPlacementImage, + bowlText, + summoningPentacles, + infusionPentacles, + possessionPentacles + ); } - - private BookEntryModel makeTheurgyDivinationRodsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("theurgy_divination_rod"); - - this.lang().add(this.context().entryName(), "More Divination Rods"); - this.lang().add(this.context().entryDescription(), "Finding other ores and resources."); + private BookEntryModel makeParaphernaliaEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("paraphernalia"); this.context().page("intro"); - var intro = BookSpotlightPageModel.create() - .withItem(Ingredient.of(ItemRegistry.DIVINATION_ROD_T1.get())) + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - While the [](item://occultism:divination_rod) is a great tool for finding [#](%1$s)Otherworld Materials[#](), it would be useful to have a way to find *all other* ores and resources as well. - \\ - \\ - This is where the Theurgy Divination Rod comes in. - """.formatted(COLOR_PURPLE)); + this.context().page("candle"); + var candle = BookSpotlightPageModel.create() + .withText(this.context().pageText()) + .withItem(Ingredient.of(OccultismBlocks.LARGE_CANDLE.get())); - this.context().page("recipe_rod"); - var recipeRod = BookCraftingRecipePageModel.create() - .withRecipeId1("theurgy:crafting/shaped/divination_rod_t1"); + this.context().page("crystal"); + var crystal = BookSpotlightPageModel.create() + .withText(this.context().pageText()) + .withItem(Ingredient.of(OccultismBlocks.SPIRIT_ATTUNED_CRYSTAL.get())); - this.context().page("more_info"); - var moreInfo = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); + this.context().page("gem_recipe"); + var gemRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/spirit_attuned_gem")); - this.lang().add(this.context().pageTitle(), "More Information"); - this.lang().add(this.context().pageText(), - """ - To find out more about the Theurgy Divination Rod, check out *"The Hermetica"*, the Guidebook for Theurgy. - [This Entry](entry://theurgy:the_hermetica/getting_started/about_divination_rods) has more information about the Theurgy Divination Rod. - """); + this.context().page("crystal_recipe"); + var crystalRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/spirit_attuned_crystal")); - this.context().page("recipe_hermetica"); - var recipeHermetica = BookCraftingRecipePageModel.create() - .withRecipeId1("theurgy:crafting/shapeless/the_hermetica"); + this.context().page("skeleton_skull"); + var skeletonSkull = BookSpotlightPageModel.create() + .withText(this.context().pageText()) + .withItem(Ingredient.of(Blocks.SKELETON_SKULL)); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(ItemRegistry.DIVINATION_ROD_T1.get()) + .withIcon(Blocks.SKELETON_SKULL) .withLocation(entryMap.get(icon)) .withPages( intro, - recipeRod, - moreInfo, - recipeHermetica - ); - } - - private BookEntryModel makeCandleEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("candle"); - this.lang().add(this.context().entryName(), "Candles"); - this.lang().add(this.context().entryDescription(), "Let there be light!"); - - this.context().page("intro"); - var intro = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.LARGE_CANDLE.get())) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Candles provide stability to rituals and are an important part of almost all pentacles. - **Large Candles also act like bookshelves for enchantment purposes.** - \\ - \\ - Candles from Minecraft and other Mods may be used in place of Occultism candles. - """); - - this.context().page("tallow"); - var tallow = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.TALLOW.get())) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Key ingredient for large candles. Kill large animals like pigs, cows or sheep with a [](item://occultism:butcher_knife) - to harvest [](item://occultism:tallow). - """); - - this.context().page("cleaver_recipe"); - var cleaverRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/butcher_knife")); - //no text - - this.context().page("candle_recipe"); - var candleRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/large_candle")); - //no text - - this.context().page("color_candle"); - var colorCandle = BookTextPageModel.create() - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - You can use a dye and the [](item://occultism:large_candle) to mix then in shapeless craft process to get a colored large candle. - \\ - Available in all the 16 minecraft dyes. - """); - - this.context().page("lit_candle"); - var litCandle = BookTextPageModel.create() - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Just like the candles from Minecraft, [](item://occultism:large_candle) and colored versions can be lit, turning in a great light source. - \\ - In addiction, you can use a [](item://minecraft:torch), [](item://minecraft:soul_torch), [](item://minecraft:redstone_torch) or [](item://occultism:spirit_torch) to change the type of fire. - \\ - Also can be waterlogged. - """); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismBlocks.LARGE_CANDLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - tallow, - cleaverRecipe, - candleRecipe, - colorCandle, - litCandle + candle, + crystal, + gemRecipe, + crystalRecipe, + skeletonSkull ); } - private BookEntryModel makeRitualPrepChalkEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("ritual_prep_chalk"); - this.lang().add(this.context().entryName(), "Ritual Preparations: Chalks"); - this.lang().add(this.context().entryDescription(), "Signs to find them, Signs to bring them all, and in the darkness bind them."); + private BookEntryModel makeChalkUsesEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("chalk_uses"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Ritual Preparations: Chalks"); - this.lang().add(this.context().pageText(), - """ - To summon spirits from the [#](%1$s)Other Place[#]() in *relative* safety, - you need to draw a fitting pentacle using chalk to contain their powers. - """.formatted(COLOR_PURPLE)); + + this.context().page("intro2"); + var intro2 = BookTextPageModel.create() + .withText(this.context().pageText()); this.context().page("white_chalk"); - var whiteChalkSpotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.CHALK_WHITE.get())) + var whiteChalk = BookSpotlightPageModel.create() .withText(this.context().pageText()) - .withAnchor("white_chalk"); - this.lang().add(this.context().pageText(), - """ - White chalk is used to draw the most basic pentacles, such as for our first ritual. - \\ - \\ - More powerful summonings require appropriate more advanced chalk, see [Chalks](entry://occultism:dictionary_of_spirits/getting_started/chalks) for more information. - """); - - this.context().page("burnt_otherstone_recipe"); - var burntOtherstoneRecipe = BookSmeltingRecipePageModel.create() - .withRecipeId1(this.modLoc("smelting/burnt_otherstone")); - //no text - - this.context().page("otherworld_ashes_recipe"); - var otherworldAshesRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/otherworld_ashes")); - //no text - this.context().page("impure_white_chalk_recipe"); - var impureWhiteChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_white_impure")); - //no text - - this.context().page("white_chalk_recipe"); - var whiteChalkRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/chalk_white")); - //no text + .withItem(Ingredient.of(OccultismItems.CHALK_WHITE.get())); - this.context().page("usage"); - var usage = BookTextPageModel.create() + this.context().page("white_chalk_uses"); + var whiteChalkUses = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Usage"); - this.lang().add(this.context().pageText(), - """ - Right-click on a block with the chalk to draw a single glyph. For decorative purposes you can repeatedly click a block to cycle through glyphs. The shown glyph does not matter for the ritual, only the color. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.CHALK_WHITE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - whiteChalkSpotlight, - burntOtherstoneRecipe, - otherworldAshesRecipe, - impureWhiteChalkRecipe, - whiteChalkRecipe, - usage - ); - } - - private BookEntryModel makeRitualPrepBowlEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("ritual_prep_bowl"); - this.lang().add(this.context().entryName(), "Ritual Preparations: Sacrificial Bowls"); - this.lang().add(this.context().entryDescription(), "There is no power without sacrifice."); - this.context().page("sacrificial_bowl"); - var sacrificialBowlSpotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.SACRIFICIAL_BOWL.get())) + this.context().page("white_chalk_uses2"); + var whiteChalkUses2 = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Ritual Preparations: Sacrificial Bowls"); - this.lang().add(this.context().pageText(), - """ - These bowls are used to place the items we will sacrifice as part of a ritual and you will need a handful of them. - Note: Their exact placement in the ritual does not matter - just keep them within 8 blocks horizontally of the pentacle center! - """); - - this.context().page("sacrificial_bowl_recipe"); - var sacrificialBowlRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/sacrificial_bowl")); - //no text - - - this.context().page("golden_sacrificial_bowl"); - var goldenSacrificialBowlSpotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.GOLDEN_SACRIFICIAL_BOWL.get())) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Once everything has been set up and you are ready to start, this special sacrificial bowl is used to activate the ritual by [#](%1$s)right-clicking[#]() it with the activation item, - usually a [Book of Binding](entry://getting_started/books_of_binding). - """.formatted(COLOR_PURPLE)); - - this.context().page("golden_sacrificial_bowl_recipe"); - var goldenSacrificialBowlRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/golden_sacrificial_bowl")); - //no text - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismBlocks.GOLDEN_SACRIFICIAL_BOWL.get()) - .withLocation(entryMap.get(icon)) - .withPages( - sacrificialBowlSpotlight, - sacrificialBowlRecipe, - goldenSacrificialBowlSpotlight, - goldenSacrificialBowlRecipe - ); - } - private BookEntryModel makeBooksOfBindingEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("books_of_binding"); - this.lang().add(this.context().entryName(), "Books of Binding"); - this.lang().add(this.context().entryDescription(), "Or how to identify your spirit"); + this.context().page("golden_chalk"); + var goldChalk = BookSpotlightPageModel.create() + .withText(this.context().pageText()) + .withItem(Ingredient.of(OccultismItems.CHALK_GOLD.get())); - this.context().page("intro"); - var intro = BookTextPageModel.create() + this.context().page("golden_chalk_uses"); + var goldChalkUses = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Books of Binding"); - this.lang().add(this.context().pageText(), - """ - To call forth a spirit, a [#](%1$s)Book of Binding[#]() must be used in the ritual. - There is a type of book corresponding to each type (or tier) of spirit. - To identify a spirit to summon, it's name must be written in the [#](%1$s)Book of Binding[#](), resulting in a [#](%1$s)Bound Book of Binding[#]() that can be used in the ritual. - """.formatted(COLOR_PURPLE)); - - this.context().page("intro2"); - var intro2 = BookTextPageModel.create() - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - **Note:** *The spirit names are eye candy only*, that means they are not relevant for the recipe. As long as you have the right spirit type in your book of binding it can be used. - """.formatted(COLOR_PURPLE)); - - this.context().page("purified_ink_recipe"); - var purifiedInkRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/purified_ink")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - In order to craft [#](%1$s)Books of Binding[#]() to summon spirits, you need purified ink. Simply drop any black dye into [](item://occultism:spirit_fire) to purify it. - """.formatted(COLOR_PURPLE)); - - this.context().page("awakened_feather_recipe"); - var awakenedFeatherRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/awakened_feather")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - In order to craft [#](%1$s)Books of Binding[#]() to summon spirits, you also need awakened feather. Simply drop any feather into [](item://occultism:spirit_fire) to awakened it. - """.formatted(COLOR_PURPLE)); - - this.context().page("taboo_book_recipe"); - var tabooBookRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/taboo_book")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Lastly you need taboo book to craft [#](%1$s)Books of Binding[#]() to summon spirits. Simply drop a book into [](item://occultism:spirit_fire) to get it. - """.formatted(COLOR_PURPLE)); - - this.context().page("book_of_binding_foliot_recipe"); - var bookOfBindingFoliotRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/book_of_binding_foliot")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Craft a book of binding that will be used to call forth a [#](%1$s)Foliot[#]() spirit. - """.formatted(COLOR_PURPLE)); - - this.context().page("book_of_binding_bound_foliot_recipe"); - var bookOfBindingBoundFoliotRecipe = BookBindingCraftingRecipePageModel.create() - .withRecipeId1() - .withUnboundBook(OccultismItems.BOOK_OF_BINDING_FOLIOT.toStack()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Add the name of the spirit to summon to your book of binding by crafting it with the Dictionary of Spirits. The Dictionary will not be used up. - """); - - this.context().page("book_of_binding_djinni_recipe"); - var bookOfBindingDjinniRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/book_of_binding_djinni")); - - this.context().page("book_of_binding_bound_djinni_recipe"); - var bookOfBoundBindingDjinniRecipe = BookBindingCraftingRecipePageModel.create() - .withRecipeId1() - .withUnboundBook(OccultismItems.BOOK_OF_BINDING_DJINNI.toStack()); - //no text - - this.context().page("book_of_binding_afrit_recipe"); - var bookOfBindingAfritRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/book_of_binding_afrit")); - //no text - - this.context().page("book_of_binding_bound_afrit_recipe"); - var bookOfBoundBindingAfritRecipe = BookBindingCraftingRecipePageModel.create() - .withRecipeId1() - .withUnboundBook(OccultismItems.BOOK_OF_BINDING_AFRIT.toStack()); - //no text - - this.context().page("book_of_binding_marid_recipe"); - var bookOfBindingMaridRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/book_of_binding_marid")); - //no text - - this.context().page("book_of_binding_bound_marid_recipe"); - var bookOfBoundBindingMaridRecipe = BookBindingCraftingRecipePageModel.create() - .withRecipeId1() - .withUnboundBook(OccultismItems.BOOK_OF_BINDING_MARID.toStack()); - //no text - - this.context().page("book_of_binding_empty"); - var alternativeBooks = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/book_of_binding_empty")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Alternatively, you can directly use the Binding Book: Empty instead of the previous three items. There are two ways to obtain this book. Place this book in the center of dyes to get specific book of binding. - """.formatted(COLOR_PURPLE)); - - this.context().page("book_of_binding_empty_recipe"); - var bookOfBindingEmptyRecipe = BookCraftingRecipePageModel.create() - .withRecipeId2(this.modLoc("crafting/book_of_binding_empty")); - //no text - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.BOOK_OF_BINDING_BOUND_FOLIOT.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - intro2, - purifiedInkRecipe, - awakenedFeatherRecipe, - tabooBookRecipe, - bookOfBindingFoliotRecipe, - bookOfBindingBoundFoliotRecipe, - bookOfBindingDjinniRecipe, - bookOfBoundBindingDjinniRecipe, - bookOfBindingAfritRecipe, - bookOfBoundBindingAfritRecipe, - bookOfBindingMaridRecipe, - bookOfBoundBindingMaridRecipe, - alternativeBooks, - bookOfBindingEmptyRecipe - ); - } - private BookEntryModel makeBooksOfBindingAutomationEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("books_of_binding_automation"); - this.lang().add(this.context().entryName(), "Books of Binding in Automation"); - this.lang().add(this.context().entryDescription(), "Tips for using books of binding in Crafting Automation such as AE2 or RS"); + this.context().page("purple_chalk"); + var purpleChalk = BookSpotlightPageModel.create() + .withText(this.context().pageText()) + .withItem(Ingredient.of(OccultismItems.CHALK_PURPLE.get())); - this.context().page("intro"); - var intro = BookTextPageModel.create() + this.context().page("purple_chalk_uses"); + var purpleChalkUses = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "The Problem"); - this.lang().add(this.context().pageText(), - """ - Bound Books of Binding are generated with a random spirit name. This tricks many automated crafting processes into no longer recognizing the item as the requested crafting result, because it does not expect NBT/Data Components on the item. - \\ - \\ - This leads to stuck crafting processes. - """ - ); - this.context().page("solution"); - var solution = BookTextPageModel.create() + this.context().page("red_chalk"); + var redChalk = BookSpotlightPageModel.create() + .withText(this.context().pageText()) + .withItem(Ingredient.of(OccultismItems.CHALK_RED.get())); + + this.context().page("red_chalk_uses"); + var redChalkUses = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "The Solution"); - this.lang().add(this.context().pageText(), - """ - 1. Put a dictionary of spirits into an anvil and give it a name. This will be the name of all spirits summoned in the future. - 2. Use this dictionary to configure crafting patterns (if your automation mod requires it). - 3. Use this dictionary to craft the Bound Books of Binding in the automation system. As usual, the dictionary will not be used up. - 4. All crafted books will now have the same name and will be recognized by your automation system. - """ - ); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(Items.CRAFTER) + .withIcon(OccultismItems.CHALK_PURPLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - solution + intro2, + whiteChalk, + whiteChalkUses, + whiteChalkUses2, + goldChalk, + goldChalkUses, + purpleChalk, + purpleChalkUses, + redChalk, + redChalkUses ); } - private BookEntryModel makeBooksOfCallingEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("books_of_calling"); - this.lang().add(this.context().entryName(), "Books of Calling"); - this.lang().add(this.context().entryDescription(), "Telling your spirits what to do"); + private BookEntryModel makeSummonFoliotEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_foliot"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Books of Calling"); - this.lang().add(this.context().pageText(), - """ - Books of Calling allow to control a summoned spirit, and to store it to prevent essence decay or move it more easily. - \\ - \\ - Only spirits that require precise instructions - such as a work area or drop-off storage - come with a book of calling. - """); - - this.context().page("usage"); - var usage = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Usage"); - this.lang().add(this.context().pageText(), - """ - - [#](%1$s)Right-click[#]() air to open the configuration screen - - [#](%1$s)Shift-right-click[#]() a block to apply the action selected in the configuration screen - - [#](%1$s)Shift-right-click[#]() a spirit to capture it (must be of the same type) - - [#](%1$s)Right-click[#]() with a book with a captured spirit to release it - """.formatted(COLOR_PURPLE)); - - this.context().page("obtaining"); - var obtaining = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "How to obtain Books of Calling"); - this.lang().add(this.context().pageText(), - """ - If a summoned spirit supports the use of a Book of Calling, the summoning ritual will automatically spawn a book in the world alongside the spirit. - \\ - \\ - If you **lose the book**, there are also crafting recipes that just provide the book (without summoning a spirit). - """.formatted(COLOR_PURPLE)); - this.context().page("obtaining2"); - var obtaining2 = BookTextPageModel.create() - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - The recipes can be found in this book or via JEI. - \\ - \\ - [#](%1$s)Shift-right-click[#]() the spirit with the crafted book to assign it. - """.formatted(COLOR_PURPLE)); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("summon_foliot")); - this.context().page("storage"); - var storage = BookTextPageModel.create() + this.context().page("uses"); + var uses = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Storing Spirits"); - this.lang().add(this.context().pageText(), - """ - To store spirits that do not have a fitting book of calling, you can use a [Soul Gem](entry://crafting_rituals/craft_soul_gem). - Soul gems are much more versatile and allow to store almost all types of entities even animals and monsters, but not players or bosses. - """); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.BOOK_OF_CALLING_DJINNI_MANAGE_MACHINE.get()) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - usage, - obtaining, - obtaining2, - storage + multiblock, + uses ); } - private BookEntryModel makeRitualEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("first_ritual"); - this.lang().add(this.context().entryName(), "First Ritual"); - this.lang().add(this.context().entryDescription(), "We're actually getting started now!"); + private BookEntryModel makePossessFoliotEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("possess_foliot"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "The Ritual (tm)"); - this.lang().add(this.context().pageText(), - """ - These pages will walk the gentle reader through the process of the [first ritual](entry://summoning_rituals/summon_crusher_t1) step by step. - \\ - We **start** by placing the [](item://occultism:golden_sacrificial_bowl) and drawing the appropriate pentacle, [Aviar's Circle](entry://pentacles/summon_foliot) as seen on the left around it. - """.formatted(COLOR_PURPLE)); this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("summon_foliot")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Only the color and location of the chalk marks is relevant, not the glyph/sign. - """.formatted(COLOR_PURPLE)); - - this.context().page("bowl_text"); - var bowlText = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Sacrificial Bowls"); - this.lang().add(this.context().pageText(), - """ - Next, place *at least* 4 [Sacrificial Bowls](item://occultism:sacrificial_bowl) close to the pentacle. - \\ - \\ - They must be placed **anywhere** within 8 blocks of the central [](item://occultism:golden_sacrificial_bowl). **The exact location does not matter.** - """.formatted(COLOR_PURPLE)); - - this.context().page("bowl_placement"); - var bowlPlacementImage = BookImagePageModel.create() - .withImages(this.modLoc("textures/gui/book/bowl_placement.png")) - .withBorder(true) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Possible locations for the sacrificial bowls. - """.formatted(COLOR_PURPLE)); - - this.context().page("ritual_text"); - var ritualText = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Placing Ingredients"); - this.lang().add(this.context().pageText(), - """ - Now it is time to place the ingredients you see on the next page in the (regular, not golden) sacrificial bowls. The ingredients will be consumed from the bowls as the ritual progresses. - """.formatted(COLOR_PURPLE)); - - this.context().page("ritual_recipe"); - var ritualRecipe = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_foliot_crusher")); - //no text - - this.context().page("pentacle_link_hint"); - var pentacleLinkHint = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "A Note about Ritual Recipes"); - this.lang().add(this.context().pageText(), - """ - Ritual recipe pages, such as the previous pageshow not only the ingredients, but also the pentacle that you need to draw with chalk in order to use the ritual. - \\ - \\ - **To show the pentacle, click the blue link** at the center top of the ritual page. You can then even preview it in-world. - """.formatted(COLOR_PURPLE)); - - this.context().page("start_ritual"); - var startRitualText = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Let there be ... spirits!"); - this.lang().add(this.context().pageText(), - """ - Finally, [#](%1$s)right-click[#]() the [](item://occultism:golden_sacrificial_bowl) with the **bound** book of binding you created before and wait until the crusher spawns. - \\ - \\ - Now all that remains is to drop appropriate ores near the crusher and wait for it to turn it into dust. - """.formatted(COLOR_PURPLE)); - - this.context().page("automation"); - var automationText = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Automatic Rituals"); - this.lang().add(this.context().pageText(), - """ - Instead of right-clicking the golden sacrificial bowl with the final ingredient, you can also use a Hopper or any type of pipe to insert the item into the bowl. The ritual will start automatically.\\ - Note that any rituals that summon tamed animals or familiars will summon them untamed instead. - """.formatted(COLOR_PURPLE)); - - this.context().page("redstone"); - var redstoneText = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Redstone"); - this.lang().add(this.context().pageText(), - """ - Depending on the ritual state the golden bowl will emit a different redstone level: - - **0** if no ritual is active - - **1** if the ritual is active, but waiting for a sacrifice - - **2** if the ritual is active, but waiting for an item to be used - - **4** if the ritual is active and running - """.formatted(COLOR_PURPLE)); - - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - bowlText, - bowlPlacementImage, - ritualText, - ritualRecipe, - pentacleLinkHint, - startRitualText, - automationText, - redstoneText - ); - } - - private BookEntryModel makeBrushEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("brush"); - this.lang().add(this.context().entryName(), "Brush"); - this.lang().add(this.context().entryDescription(), "Cleaning up!"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Next Steps"); - this.lang().add(this.context().pageText(), - """ - Chalk is a pain to clean up, by [#](%1$s)right-clicking[#]() with a brush you can remove it from the world much more easily. - """.formatted(COLOR_PURPLE)); - - this.context().page("brushRecipe"); - var brushRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/brush")); - //no text - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.BRUSH.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - brushRecipe - ); - } - - private BookEntryModel makeMoreRitualsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("more_rituals"); - this.lang().add(this.context().entryName(), "More Rituals"); - this.lang().add(this.context().entryDescription(), "Ready for new challenges?"); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(this.modLoc("textures/gui/book/robe.png")) - .withLocation(entryMap.get(icon)) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withCategoryToOpen(this.modLoc("rituals")); - } - - private BookEntryModel makeGreyParticlesEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("grey_particles"); - this.lang().add(this.context().entryName(), "Grey particles?"); - this.lang().add(this.context().entryDescription(), "What to do when a ritual seems stuck!"); - - this.context().page("text"); - var text = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Ritual stuck?"); - this.lang().add(this.context().pageText(), - """ - If a ritual appears stuck - no items being consumed - you should see grey particles around the [](item://occultism:golden_sacrificial_bowl). If this is the case the ritual requires you to either [use a specific item](entry://rituals/item_use) or [sacrifice a specific mob](entry://rituals/sacrifice). - \\ - \\ - Find the ritual in the [Rituals](category://rituals) category and check for instructions. - """); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(Items.GRAY_DYE) - .withLocation(entryMap.get(icon)) - .withPages(text); - } - - private BookEntryModel makeSpiritsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("spirits"); - this.lang().add(this.context().entryName(), "About Spirits"); - this.lang().add(this.context().entryDescription(), "Learn more about Spirits."); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/spirits.png")) - .withCategoryToOpen(this.modLoc("spirits")) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withLocation(entryMap.get(icon)); - } - - private BookEntryModel makeChalksEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("chalks"); - this.lang().add(this.context().entryName(), "More Chalks"); - this.lang().add(this.context().entryDescription(), "Better chalks for better rituals!"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "More Chalks"); - this.lang().add(this.context().pageText(), - """ - For more advanced rituals the basic [White Chalk](entry://occultism:dictionary_of_spirits/getting_started/ritual_prep_chalk) is not sufficient. Instead chalks made from more arcane materials are required. - """); - - this.context().page("impure_gold_chalk_recipe"); - var impureGoldChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_gold_impure")); - //no text - - this.context().page("gold_chalk_recipe"); - var goldChalkRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/chalk_gold")); - //no text - - this.context().page("impure_purple_chalk_recipe"); - var impurePurpleChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_purple_impure")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - You do not need to visit the [#](%1$s)The End[#]() to obtain Endstone. You can summon a [Possessed Endermite](entry://possession_rituals/possess_endermite) which has a high chance to drop it. - """.formatted(COLOR_PURPLE)); - - this.context().page("purple_chalk_recipe"); - var purpleChalkRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/chalk_purple")); - //no text - - this.context().page("impure_red_chalk_recipe"); - var impureRedChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_red_impure")); - //no text - - this.context().page("red_chalk_recipe"); - var redChalkRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/chalk_red")); - //no text - - this.context().page("afrit_essence"); - var afritEssenceSpotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.AFRIT_ESSENCE.get())) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - To obtain the essence of an [#](%1$s)Afrit[#]() for [](item://occultism:chalk_red) you need to [summon and kill an Unbound Afrit](entry://summoning_rituals/afrit_essence). - """.formatted(COLOR_PURPLE)); - - this.context().page("decoColors"); - var decoColors = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Decorative Chalks"); - this.lang().add(this.context().pageText(), - """ - Other colored chalks (for now) only have decorative purposes, you can check the recipes in next pages. All needs to be purified in spirit fire. - """); - - this.context().page("impure_light_gray_chalk_recipe"); - var impureLightGrayChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_light_gray_impure")); - //no text - - this.context().page("impure_gray_chalk_recipe"); - var impureGrayChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_gray_impure")); - //no text - - this.context().page("impure_Black_chalk_recipe"); - var impureBlackChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_black_impure")); - //no text - - this.context().page("impure_brown_chalk_recipe"); - var impureBrownChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_brown_impure")); - //no text - this.context().page("impure_orange_chalk_recipe"); - var impureOrangeChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_orange_impure")); - //no text - this.context().page("impure_lime_chalk_recipe"); - var impureLimeChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_lime_impure")); - //no text - this.context().page("impure_green_chalk_recipe"); - var impureGreenChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_green_impure")); - //no text - this.context().page("impure_cyan_chalk_recipe"); - var impureCyanChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_cyan_impure")); - //no text - this.context().page("impure_blue_chalk_recipe"); - var impureBlueChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_blue_impure")); - //no text - this.context().page("impure_light_blue_chalk_recipe"); - var impureLightBlueChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_light_blue_impure")); - //no text - this.context().page("impure_pink_chalk_recipe"); - var impurePinkChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_pink_impure")); - //no text - this.context().page("impure_magenta_chalk_recipe"); - var impureMagentaChalkRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/chalk_magenta_impure")); - //no text - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.CHALK_GOLD.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - impureGoldChalkRecipe, - goldChalkRecipe, - impurePurpleChalkRecipe, - purpleChalkRecipe, - impureRedChalkRecipe, - redChalkRecipe, - afritEssenceSpotlight, - decoColors, - impureLightGrayChalkRecipe, - impureGrayChalkRecipe, - impureBlackChalkRecipe, - impureBrownChalkRecipe, - impureOrangeChalkRecipe, - impureLimeChalkRecipe, - impureGreenChalkRecipe, - impureCyanChalkRecipe, - impureBlueChalkRecipe, - impureLightBlueChalkRecipe, - impurePinkChalkRecipe, - impureMagentaChalkRecipe - ); - } - - private BookEntryModel makeOtherworldGogglesEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("otherworld_goggles"); - this.lang().add(this.context().entryName(), "Otherworld Goggles"); - this.lang().add(this.context().entryDescription(), "Say no to drugs!"); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.OTHERWORLD_GOGGLES.get())) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - The [](item://occultism:otherworld_goggles) are what advanced summoners use to see the [#](%1$s)Otherworld[#](), to avoid the negative side effects of [](entry://occultism:dictionary_of_spirits/getting_started/demons_dream). - \\ - \\ - Making your first pair of these is seen by many as a rite of passage. - """.formatted(COLOR_PURPLE)); - - this.context().page("crafting"); - var crafting = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Crafting Goggles"); - this.lang().add(this.context().pageText(), - """ - Crafting these goggles is a multi-step process described in detail in the Entry about [Crafting Otherworld Goggles](entry://crafting_rituals/craft_otherworld_goggles). - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.OTHERWORLD_GOGGLES.get()) - .withLocation(entryMap.get(icon)) - .withPages( - spotlight, - crafting - ); - } - - private BookEntryModel makeInfusedPickaxeEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("infused_pickaxe"); - this.lang().add(this.context().entryName(), "Infused Pickaxe"); - this.lang().add(this.context().entryDescription(), "Tackling Otherworld Ores"); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.INFUSED_PICKAXE.get())) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Beyond [](item://occultism:otherworld_log) and [](item://occultism:otherstone) there are also otherworld materials that require special tools to harvest. - \\ - \\ - This pickaxe is rather brittle, but it will do the job. - """); - - this.context().page("gem_recipe"); - var gemRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/spirit_attuned_gem")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - These gems, when infused with a spirit, can be used to interact with Otherword materials and are the key to crafting the pickaxe. - """); - - this.context().page("head_recipe"); - var headRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/spirit_attuned_pickaxe_head")); - //no text - - this.context().page("crafting"); - var crafting = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Crafting"); - this.lang().add(this.context().pageText(), - """ - After preparing the raw materials, the pickaxe needs to be infused with a spirit. - \\ - \\ - Follow the instructions at [Craft Infuse Pickaxe](entry://crafting_rituals/craft_infused_pickaxe) - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.INFUSED_PICKAXE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - spotlight, - gemRecipe, - headRecipe, - crafting - ); - } - - private BookEntryModel makeIesniumEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("iesnium"); - this.lang().add(this.context().entryName(), "Iesnium Ore"); - this.lang().add(this.context().entryDescription(), "Myterious metals ..."); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.IESNIUM_ORE.get())) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - This is a rare metal that, to the naked eye, looks like [](item://minecraft:netherrack) and cannot be mined with a regular pickaxe. - \\ - \\ - When mined with the correct tools, it can be used to craft powerful items (you will learn more about that later). - """.formatted(COLOR_PURPLE)); - - this.context().page("where"); - var where = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Where to find it"); - this.lang().add(this.context().pageText(), - """ - Like Netherrack, Iesnium can be found in the Nether. In order to **see** it, you need to wear [Otherworld Goggles](entry://getting_started/otherworld_goggles). - \\ - \\ - To make searching for it simpler, attune a [Divination Rod](entry://getting_started/divination_rod) to it and righ-click and hold in the nether until it highlights a nearby block, which will hold the ore. - """.formatted(COLOR_PURPLE)); - - this.context().page("how"); - var how = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "How to mine it"); - this.lang().add(this.context().pageText(), - """ - Iesnium can only be mined with the [Infused Pickaxe](entry://getting_started/infused_pickaxe) or an [](item://occultism:iesnium_pickaxe) (about which you will learn later). - \\ - \\ - After identifying a block that holds Iesnium, you can mine it with the pickaxe you created in the previous step. - """.formatted(COLOR_PURPLE)); - - this.context().page("processing"); - var processing = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Processing"); - this.lang().add(this.context().pageText(), - """ - Iesnium Ore, after mining, can be smelted directly into ingots, or placed down. When placed, it will not turn back into it's netherrack form. Consequently it can also be mined with any pickaxe then. This visible form of the Ore, when mined, will drop [](item://occultism:raw_iesnium). - """.formatted(COLOR_PURPLE)); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Uses"); - this.lang().add(this.context().pageText(), - """ - Iesnium can be used to craft an improved pickaxe, spirit lamps, and other powerful items. Follow the progress in this book to learn more about it. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismBlocks.IESNIUM_ORE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - spotlight, - where, - how, - processing, - uses - ); - } - - private BookEntryModel makeIesniumPickaxeEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("iesnium_pickaxe"); - this.lang().add(this.context().entryName(), "Iesnium Pickaxe"); - this.lang().add(this.context().entryDescription(), "A more durable otherworld-appropriate pickaxe"); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.IESNIUM_PICKAXE.get())) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - Like the [Infused Pickaxe](entry://getting_started/infused_pickaxe), this pickaxe can be used to mine Tier 2 Otherworld Materials such as [](item://occultism:iesnium_ore). As it is made from metal, instead of brittle [](item://occultism:spirit_attuned_gem), it is very durable and can be used for a long time. - """.formatted(COLOR_PURPLE)); - - this.context().page("crafting"); - var crafting = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/iesnium_pickaxe")); - //no text - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.IESNIUM_PICKAXE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - spotlight, - crafting - ); - } - - private BookEntryModel makeMagicLampsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("magic_lamps"); - this.lang().add(this.context().entryName(), "Magic Lamps"); - this.lang().add(this.context().entryDescription(), "Three wishes? Close, but not quite.."); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.MAGIC_LAMP_EMPTY.get())) - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Magic Lamps"); - this.lang().add(this.context().pageText(), - """ - Magic Lamps can be used to keep spirits safe from [#](%1$s)Essence Decay[#](), while still having access to some of their powers. Most commonly they are used to access a [#](%1$s)Mining Dimension[#]() and act as (*lag free*) [#](%1$s)Void Miners[#](). - """.formatted(COLOR_PURPLE)); - - this.context().page("crafting"); - var crafting = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/magic_lamp_empty")); - //no text - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.MAGIC_LAMP_EMPTY.get()) - .withLocation(entryMap.get(icon)) - .withPages( - spotlight, - crafting - ); - } - - private BookEntryModel makeSpiritMinersEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("spirit_miners"); - this.lang().add(this.context().entryName(), "Spirit Miners"); - this.lang().add(this.context().entryDescription(), "It's Free Real Estate (-> Resources)"); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.MINER_FOLIOT_UNSPECIALIZED.get())) - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Spirit Miners"); - this.lang().add(this.context().pageText(), - """ - By summoning a spirit into a Magic Lamp and placing it in a [Dimensional Mineshaft (see next step)](entry://getting_started/mineshaft) it can be made to mine for you in a [#](%1$s)Mining Dimension[#](). This is a great way to get resources without having to go mining in the overworld (or other dimesions) yourself. - """.formatted(COLOR_PURPLE)); - - this.context().page("crafting"); - var crafting = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Crafting"); - this.lang().add(this.context().pageText(), - """ - See [Foliot Miner](entry://crafting_rituals/craft_foliot_miner) and the subsequent entries for information on how to craft spirit miners. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismItems.MINER_FOLIOT_UNSPECIALIZED.get()) - .withLocation(entryMap.get(icon)) - .withPages( - spotlight, - crafting - ); - } - - private BookEntryModel makeMineshaftEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("mineshaft"); - this.lang().add(this.context().entryName(), "Dimensional Mineshaft"); - this.lang().add(this.context().entryDescription(), "Ethically questionable, but very profitable"); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.DIMENSIONAL_MINESHAFT.get())) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - This block acts as a portal, for spirits only, to the [#](%1$s)Mining Dimension[#](). Place a Magic Lamp with a Miner Spirit in it, to make it mine for you. - """.formatted(COLOR_PURPLE)); - - this.context().page("crafting"); - var crafting = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Crafting"); - this.lang().add(this.context().pageText(), - """ - See [Dimensional Mineshaft](entry://crafting_rituals/craft_dimensional_mineshaft) in the [Binding Rituals](category://crafting_rituals) Category. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismBlocks.DIMENSIONAL_MINESHAFT.get()) - .withLocation(entryMap.get(icon)) - .withPages( - spotlight, - crafting - ); - } - - private BookEntryModel makeStorageEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("storage"); - this.lang().add(this.context().entryName(), "Magic Storage"); - this.lang().add(this.context().entryDescription(), "Looking for much much much more storage? Look no further!"); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(OccultismBlocks.STORAGE_CONTROLLER.get()) - .withLocation(entryMap.get(icon)) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withCategoryToOpen(this.modLoc("storage")); - } - - private BookEntryModel makePossessionRitualsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("possession_rituals"); - this.lang().add(this.context().entryName(), "Possession Rituals"); - this.lang().add(this.context().entryDescription(), "A different way to get rare drops ..."); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Possession Rituals"); - this.lang().add(this.context().pageText(), - """ - Possessed mobs are controlled by spirits, allowing the summoner to determine some of their properties. They usually have **high drop rates** for rare drops, but are generally harder to kill. - \\ - \\ - You probably will want to start by summoning a [Possessed Endermite](entry://possession_rituals/possess_endermite) to get [](item://minecraft:end_stone) to craft [Advanced Chalks](entry://getting_started/chalks). - """.formatted(COLOR_PURPLE)); - - this.context().page("more"); - var more = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "More Information"); - this.lang().add(this.context().pageText(), - """ - To find out more about Possession Rituals, see the [Possession Rituals](category://possession_rituals) Category. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(this.modLoc("textures/gui/book/possession.png")) - .withLocation(entryMap.get(icon)) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withPages( - intro, - more - ); - } - - private BookEntryModel makeFamiliarRitualsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_rituals"); - this.lang().add(this.context().entryName(), "Familiar Rituals"); - this.lang().add(this.context().entryDescription(), "Personal helpers that provide buffs or fight for you"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Familiar Rituals"); - this.lang().add(this.context().pageText(), - """ - Familiars provide a variety of bonus effects, such as feather falling, water breathing, jump boosts and more, and may also assist you in combat. - \\ - \\ - Store them in a [Familiar Ring](entry://crafting_rituals/craft_familiar_ring) to equip them as a curio. - """.formatted(COLOR_PURPLE)); - - this.context().page("more"); - var more = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "More Information"); - this.lang().add(this.context().pageText(), - """ - To find more about Familiars, see the [Familiar Rituals](category://familiar_rituals) Category. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(this.modLoc("textures/gui/book/parrot.png")) - .withLocation(entryMap.get(icon)) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withPages( - intro, - more - ); - } - - private BookEntryModel makeSummoningRitualsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summoning_rituals"); - this.lang().add(this.context().entryName(), "Summoning Rituals"); - this.lang().add(this.context().entryDescription(), "Spirit helpers for your daily work life"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Summoning Rituals"); - this.lang().add(this.context().pageText(), - """ - Summoning Rituals allow you to summon spirits to work for you. Unlike familiars, they are not personally bound to you, meaning they will not follow you around, but they will perform various work tasks for you. In fact the first ritual you performed, the [Foliot Crusher](entry://getting_started/first_ritual), was a summoning ritual. - """.formatted(COLOR_PURPLE)); - - this.context().page("more"); - var more = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "More Information"); - this.lang().add(this.context().pageText(), - """ - To find more about Summoning Rituals, see the [Summoning Rituals](category://summoning_rituals) Category. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(this.modLoc("textures/gui/book/summoning.png")) - .withLocation(entryMap.get(icon)) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withPages( - intro, - more - ); - } - - private BookEntryModel makeCraftingRitualsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("crafting_rituals"); - this.lang().add(this.context().entryName(), "Infusion Rituals"); - this.lang().add(this.context().entryDescription(), "Infuse spirits into items to create powerful tools"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Infusion Rituals"); - this.lang().add(this.context().pageText(), - """ - Infusion rituals are all about crafting powerful items, by binding ("infusing") spirits into objects.The spirits will provide special functionality to the items. - """.formatted(COLOR_PURPLE)); - - this.context().page("more"); - var more = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "More Information"); - this.lang().add(this.context().pageText(), - """ - To find more about Infusing items, see the [Infusion Rituals](category://crafting_rituals) Category. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(this.modLoc("textures/gui/book/infusion.png")) - .withLocation(entryMap.get(icon)) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withPages( - intro, - more - ); - } - - //endregion - - private BookCategoryModel makeSpiritsSubcategory() { - this.context().category("spirits"); - this.lang().add(this.context().categoryName(), "Spirits"); - var entryMap = ModonomiconAPI.get().getEntryMap(); - entryMap.setMap( - "___________________________", - "___________________________", - "___<_0_n_u_w_______________", - "___________________________", - "_____d_____________________", - "___________________________", - "___________________________" - ); - - var overview = this.makeSpiritsOverviewEntry(entryMap, '0'); - var returnToGettingStarted = this.makeReturnToGettingStartedEntry(entryMap, '<'); - returnToGettingStarted.withParent(BookEntryParentModel.create(overview.getId())); - returnToGettingStarted.withCondition(BookTrueConditionModel.create()); - - var essenceDecay = this.makeEssenceDecayEntry(entryMap, 'd'); - essenceDecay.withParent(BookEntryParentModel.create(overview.getId())); - - var trueNames = this.makeTrueNamesEntry(entryMap, 'n'); - trueNames.withParent(BookEntryParentModel.create(overview.getId())); - - var unboundSpirits = this.makeUnboundSpiritsEntry(entryMap, 'u'); - unboundSpirits.withParent(BookEntryParentModel.create(trueNames.getId())); - - var wildHunt = this.makeWildHuntEntry(entryMap, 'w'); - wildHunt.withParent(BookEntryParentModel.create(unboundSpirits.getId())); - - return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) - .withIcon(this.modLoc("textures/gui/book/spirits.png")) - .withShowCategoryButton(true) - .withEntries( - overview, - returnToGettingStarted, - trueNames, - essenceDecay, - unboundSpirits, - wildHunt - ); - } - - private BookEntryModel makeReturnToGettingStartedEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("return_to_getting_started"); - this.lang().add(this.context().entryName(), "Return to getting started"); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.DICTIONARY_OF_SPIRITS_ICON.get()) - .withCategoryToOpen(this.modLoc("getting_started")) - .withEntryBackground(1, 2) - .withLocation(entryMap.get(icon)); - } - - private BookEntryModel makeSpiritsOverviewEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("overview"); - this.lang().add(this.context().entryName(), "On Spirits"); - this.lang().add(this.context().entryDescription(), "An overview of the supernatural"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "On Spirits"); - this.lang().add(this.context().pageText(), - """ - [#](%1$s)Spirit[#](), commonly referred to also as [#](%1$s)Demon[#](), is a general term for a variety of supernatural entities usually residing in [#](%1$s)The Other Place[#](), a plane of existence entirely separate from our own. - """.formatted(COLOR_PURPLE)); - - this.context().page("shapes"); - var shapes = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Shapes"); - this.lang().add(this.context().pageText(), - """ - When in our world Spirits can take a variety of forms, by morphing their essence into [#](%1$s)Chosen Forms[#](). Alternatively, they can inhabit objects or even living beings. - """.formatted(COLOR_PURPLE)); - - this.context().page("tiers"); - var tiers = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Types of Spirits"); - this.lang().add(this.context().pageText(), - """ - There are four major "ranks" of spirits identified by researchers, but there are a myriad spirits below and in between these ranks, and some great entities of terrible power, referred to only as [#](%1$s)Greater Spirits[#](), that are beyond classification. - """.formatted(COLOR_PURPLE)); - - this.context().page("foliot"); - var foliot = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Foliot"); - this.lang().add(this.context().pageText(), - """ - The lowest identified class of spirit. Equipped with some intelligence and a modicum of power they are most often used for manual labor or minor artifacts. - """.formatted(COLOR_PURPLE)); - - this.context().page("djinni"); - var djinni = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Djinni"); - this.lang().add(this.context().pageText(), - """ - The most commonly summoned class. There is a great variety of Djinni, differing both in intelligence and power. Djinni can be used for a variety of task, ranging from higher artifacts over possession of living beings to carrying out tasks in their Chosen Form. - """.formatted(COLOR_PURPLE)); - - this.context().page("afrit"); - var afrit = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Afrit"); - this.lang().add(this.context().pageText(), - """ - Even more powerful than Djinni, Afrit are used for the creation of major artifacts and the possession of powerful beings. - """.formatted(COLOR_PURPLE)); - - - this.context().page("marid"); - var marid = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Marid"); - this.lang().add(this.context().pageText(), - """ - The strongest identified class of spirits. Due to their power and vast intellect attempting a summoning is extremely dangerous and usually only carried out by the most experienced summoners, and even then usually in groups. - """.formatted(COLOR_PURPLE)); - - this.context().page("greater_spirits"); - var greaterSpirits = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Greater Spirits"); - this.lang().add(this.context().pageText(), - """ - Spirits of power so great it is beyond measure. No summons have been attempted in living memory, and records of summonings in ancient times are mostly considered apocryphal. - """.formatted(COLOR_PURPLE)); - - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(this.modLoc("textures/gui/book/spirits.png")) - .withLocation(entryMap.get(icon)) - .withEntryBackground(0, 1) - .withPages( - intro, - shapes, - tiers, - foliot, - djinni, - afrit, - marid, - greaterSpirits - ); - } - - private BookEntryModel makeEssenceDecayEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("essence_decay"); - this.lang().add(this.context().entryName(), "Essence Decay"); - this.lang().add(this.context().entryDescription(), "Even the immortal are not immune to time."); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Essence Decay"); - this.lang().add(this.context().pageText(), - """ - When residing in our plane of existence, spirits experience [#](%1$s)Essence Decay[#](), the slow rot of their "body". The more powerful the spirit, the slower the decay, but only the most powerful can stop it entirely. Once fully decayed they are returned to [#](%1$s)The Other Place[#]() and can only be re-summoned once fully recovered. - """.formatted(COLOR_PURPLE)); - - this.context().page("countermeasures"); - var countermeasures = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Countermeasures"); - this.lang().add(this.context().pageText(), - """ - The summoner can slow or even stop essence decay by binding the spirit into an object, or summoning it into a living being. Additionally the pentacle used can influence the effects of essence decay to a degree. - """.formatted(COLOR_PURPLE)); - - - this.context().page("affected_spirits"); - var affectedSpirits = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Affected Spirits"); - this.lang().add(this.context().pageText(), - """ - Only tier 1 spirits are affected by essence decay, by default. All higher tiers are immune and will not despawn. Modpacks may modify this behaviour. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(Items.ROTTEN_FLESH) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - countermeasures, - affectedSpirits - ); - } - - private BookEntryModel makeTrueNamesEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("true_names"); - this.lang().add(this.context().entryName(), "True Names"); - this.lang().add(this.context().entryDescription(), "How to call spirits."); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "True Names"); - this.lang().add(this.context().pageText(), - """ - To summon a spirit the magician needs to know their [#](%1$s)True Name[#](). By calling the true naming during the summoning ritual the Spirit is drawn forth from [#](%1$s)The Other Place[#]() and forced to do the summoners bidding. - \\ - \\ - *It should be noted, that it does not matter which spirit name is used in summoning, only the spirit tier is relevant.* - """.formatted(COLOR_PURPLE)); - - this.context().page("finding_names"); - var findingNames = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Finding Names"); - this.lang().add(this.context().pageText(), - """ - In ancient summoners had to research and experiment to find [#](%1$s)True Names[#](). Some spirits can be convinced to share their knowledge of true names of other demons, either by promising a swift return to [#](%1$s)The Other Place[#](), or by more ... *persuasive* measures. - """.formatted(COLOR_PURPLE)); - - this.context().page("using_names"); - var usingNames = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Using Names to Summon a Spirit"); - this.lang().add(this.context().pageText(), - """ - For your convenience, in this work you will find the known names of spirits of all 4 ranks, as well as some beyond that. To summon a spirit, copy their name from this book into the appropriate book of binding, then use this bound book of binding to activate a ritual. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(Items.WRITABLE_BOOK) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - findingNames, - usingNames - ); - } - - private BookEntryModel makeUnboundSpiritsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("unbound_spirits"); - this.lang().add(this.context().entryName(), "Unbound Spirits"); - this.lang().add(this.context().entryDescription(), "Try not to lose your spirits!"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Unbound Spirits"); - this.lang().add(this.context().pageText(), - """ - Generally spirits are summoned [#](%1$s)bound[#](), which refers to any condition that keeps them under control of the summoner. A side effect of binding spells is that part of the spirit remains in [#](%1$s)The Other Place[#](), robbing them of large portions of the power, but at the same time also protecting their essence from foreign access in this world. - """.formatted(COLOR_PURPLE)); - - this.context().page("unbound"); - var unbound = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Forego the Leash"); - this.lang().add(this.context().pageText(), - """ - In order to access a spirit's essence, or unleash it's full destructive power, it needs to be summoned [#](%1$s)unbound[#](). Unbound summonings use pentacles that are intentionally incomplete or unstable, allowing to call on the spirit, but not putting any constraints on it. - """.formatted(COLOR_PURPLE)); - - this.context().page("unbound2"); - var unbound2 = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Beware!"); - this.lang().add(this.context().pageText(), - """ - The lack of restraints when summoning spirits unbound makes these rituals incredibly dangerous, but you may find that the rewards are worth the risk - and often there is no way around them to achieve certain results. - """.formatted(COLOR_PURPLE)); - - this.context().page("essence"); - var essence = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Spirit Essence"); - this.lang().add(this.context().pageText(), - """ - Unbound summonings are the only way to obtain [Afrit Essence](entry://summoning_rituals/afrit_essence), a powerful substance required for crafting [](item://occultism:chalk_red) which is used for the most powerful binding pentacles. - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(this.modLoc("textures/gui/book/unbound_spirits.png")) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - unbound, - unbound2, - essence - ); - } - - private BookEntryModel makeWildHuntEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("wild_hunt"); - this.lang().add(this.context().entryName(), "The Wild Hunt"); - this.lang().add(this.context().entryDescription(), "You better watch out, you better not cry ..."); - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "The Wild Hunt"); - this.lang().add(this.context().pageText(), - """ - A group of legendary Greater Spirits, usually appearing in the form of wither skeletons, with their skeleton minions. The Greater Spirits are bound to their minions in such fashion that they are virtually invulnerable until their minions have been sent back to [#](%1$s)The Other Place[#](). - """.formatted(COLOR_PURPLE)); - - this.context().page("wither_skull"); - var witherSkull = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Wither Skeleton Skulls"); - this.lang().add(this.context().pageText(), - """ - While it is incredibly dangerous to call on the Wild Hunt, some summoners have been known to do so for quick access to the rare wither skeleton skulls they are known to leave behind. Summoning the wild hunt is described in detail on the page on obtaining [Wither Skeleton Skulls](entry://summoning_rituals/wither_skull). - """.formatted(COLOR_PURPLE)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withDescription(this.context().entryDescription()) - .withIcon(this.modLoc("textures/gui/book/wild_hunt.png")) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - witherSkull - ); - } - - //endregion - - private BookCategoryModel makePentaclesCategory() { - this.context().category("pentacles"); - - var entryMap = ModonomiconAPI.get().getEntryMap(); - entryMap.setMap( - "____________________", - "__p_a_b_c_d_e_f_____", //paraphernalia, summon foliot, summon djinni, summon wild afrit, summon afrit, summon marid, summon wild greater spirit - "____________________", - "__o___g_h_i_________", //overview, possess foliot, possess djinni, possess afrit - "____________________", - "__u_j_k_l_m_________", //uses of chalks, craft foliot, craft djinni, craft afrit, craft marid - "____________________" - ); - - var overview = this.makePentaclesOverviewEntry(entryMap, 'o'); - var paraphernalia = this.makeParaphernaliaEntry(entryMap, 'p'); - paraphernalia.withParent(BookEntryParentModel.create(overview.getId())); - var chalkUses = this.makeChalkUsesEntry(entryMap, 'u'); - chalkUses.withParent(BookEntryParentModel.create(overview.getId())); - - var summonFoliot = this.makeSummonFoliotEntry(entryMap, 'a'); - summonFoliot.withParent(BookEntryParentModel.create(overview.getId())); - var summonDjinni = this.makeSummonDjinniEntry(entryMap, 'b'); - summonDjinni.withParent(BookEntryParentModel.create(summonFoliot.getId())); - var summonWildAfrit = this.makeSummonWildAfritEntry(entryMap, 'c'); - summonWildAfrit.withParent(BookEntryParentModel.create(summonDjinni.getId())); - var summonAfrit = this.makeSummonAfritEntry(entryMap, 'd'); - summonAfrit.withParent(BookEntryParentModel.create(summonWildAfrit.getId())); - var summonMarid = this.makeSummonMaridEntry(entryMap, 'e'); - summonMarid.withParent(BookEntryParentModel.create(summonAfrit.getId())); - var summonWildGreaterSpirit = this.makeSummonWildGreaterSpiritEntry(entryMap, 'f'); - summonWildGreaterSpirit.withParent(BookEntryParentModel.create(summonMarid.getId())); - - var possessFoliot = this.makePossessFoliotEntry(entryMap, 'g'); - possessFoliot.withParent(BookEntryParentModel.create(overview.getId())); - var possessDjinni = this.makePossessDjinniEntry(entryMap, 'h'); - possessDjinni.withParent(BookEntryParentModel.create(possessFoliot.getId())); - var possessAfrit = this.makePossessAfritEntry(entryMap, 'i'); - possessAfrit.withParent(BookEntryParentModel.create(possessDjinni.getId())); - - var craftFoliot = this.makeCraftFoliotEntry(entryMap, 'j'); - craftFoliot.withParent(BookEntryParentModel.create(overview.getId())); - var craftDjinni = this.makeCraftDjinniEntry(entryMap, 'k'); - craftDjinni.withParent(BookEntryParentModel.create(craftFoliot.getId())); - var craftAfrit = this.makeCraftAfritEntry(entryMap, 'l'); - craftAfrit.withParent(BookEntryParentModel.create(craftDjinni.getId())); - var craftMarid = this.makeCraftMaridEntry(entryMap, 'm'); - craftMarid.withParent(BookEntryParentModel.create(craftAfrit.getId())); - - //add true condition to all entries to enable them by default - overview.withCondition(BookTrueConditionModel.create()); - paraphernalia.withCondition(BookTrueConditionModel.create()); - chalkUses.withCondition(BookTrueConditionModel.create()); - summonFoliot.withCondition(BookTrueConditionModel.create()); - summonDjinni.withCondition(BookTrueConditionModel.create()); - summonWildAfrit.withCondition(BookTrueConditionModel.create()); - summonAfrit.withCondition(BookTrueConditionModel.create()); - summonMarid.withCondition(BookTrueConditionModel.create()); - summonWildGreaterSpirit.withCondition(BookTrueConditionModel.create()); - possessFoliot.withCondition(BookTrueConditionModel.create()); - possessDjinni.withCondition(BookTrueConditionModel.create()); - possessAfrit.withCondition(BookTrueConditionModel.create()); - craftFoliot.withCondition(BookTrueConditionModel.create()); - craftDjinni.withCondition(BookTrueConditionModel.create()); - craftAfrit.withCondition(BookTrueConditionModel.create()); - craftMarid.withCondition(BookTrueConditionModel.create()); - - return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withEntries( - overview, - paraphernalia, - chalkUses, - - summonFoliot, - summonDjinni, - summonWildAfrit, - summonAfrit, - summonMarid, - summonWildGreaterSpirit, - - possessFoliot, - possessDjinni, - possessAfrit, - - craftFoliot, - craftDjinni, - craftAfrit, - craftMarid - ); - } - - private BookEntryModel makePentaclesOverviewEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("pentacles_overview"); - - this.context().page("intro1"); - var intro1 = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("intro2"); - var intro2 = BookTextPageModel.create() - .withText(this.context().pageText()); - - this.context().page("intro3"); - var intro3 = BookTextPageModel.create() - .withText(this.context().pageText()); - - this.context().page("intro4"); - var intro4 = BookTextPageModel.create() - .withText(this.context().pageText()); - - //exact copy found in first ritual entry - this.context().page("bowl_placement"); - var bowlPlacementImage = BookImagePageModel.create() - .withImages(this.modLoc("textures/gui/book/bowl_placement.png")) - .withBorder(true); - - //exact copy found in first ritual entry - this.context().page("bowl_text"); - var bowlText = BookTextPageModel.create() - .withText(this.context().pageText()); - - this.context().page("summoning_pentacles"); - var summoningPentacles = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("infusion_pentacles"); - var infusionPentacles = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("possession_pentacles"); - var possessionPentacles = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.SPIRIT_ATTUNED_CRYSTAL.get()) - .withLocation(entryMap.get(icon)) - .withEntryBackground(0, 1) - .withPages( - intro1, - intro2, - intro3, - intro4, - bowlPlacementImage, - bowlText, - summoningPentacles, - infusionPentacles, - possessionPentacles - ); - } - - private BookEntryModel makeParaphernaliaEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("paraphernalia"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("candle"); - var candle = BookSpotlightPageModel.create() - .withText(this.context().pageText()) - .withItem(Ingredient.of(OccultismBlocks.LARGE_CANDLE.get())); - - this.context().page("crystal"); - var crystal = BookSpotlightPageModel.create() - .withText(this.context().pageText()) - .withItem(Ingredient.of(OccultismBlocks.SPIRIT_ATTUNED_CRYSTAL.get())); - - this.context().page("gem_recipe"); - var gemRecipe = BookSpiritFireRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_fire/spirit_attuned_gem")); - - this.context().page("crystal_recipe"); - var crystalRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/spirit_attuned_crystal")); - - this.context().page("skeleton_skull"); - var skeletonSkull = BookSpotlightPageModel.create() - .withText(this.context().pageText()) - .withItem(Ingredient.of(Blocks.SKELETON_SKULL)); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Blocks.SKELETON_SKULL) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - candle, - crystal, - gemRecipe, - crystalRecipe, - skeletonSkull - ); - } - - private BookEntryModel makeChalkUsesEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("chalk_uses"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("intro2"); - var intro2 = BookTextPageModel.create() - .withText(this.context().pageText()); - - this.context().page("white_chalk"); - var whiteChalk = BookSpotlightPageModel.create() - .withText(this.context().pageText()) - .withItem(Ingredient.of(OccultismItems.CHALK_WHITE.get())); - - this.context().page("white_chalk_uses"); - var whiteChalkUses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("white_chalk_uses2"); - var whiteChalkUses2 = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("golden_chalk"); - var goldChalk = BookSpotlightPageModel.create() - .withText(this.context().pageText()) - .withItem(Ingredient.of(OccultismItems.CHALK_GOLD.get())); - - this.context().page("golden_chalk_uses"); - var goldChalkUses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("purple_chalk"); - var purpleChalk = BookSpotlightPageModel.create() - .withText(this.context().pageText()) - .withItem(Ingredient.of(OccultismItems.CHALK_PURPLE.get())); - - this.context().page("purple_chalk_uses"); - var purpleChalkUses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("red_chalk"); - var redChalk = BookSpotlightPageModel.create() - .withText(this.context().pageText()) - .withItem(Ingredient.of(OccultismItems.CHALK_RED.get())); - - this.context().page("red_chalk_uses"); - var redChalkUses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.CHALK_PURPLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - intro2, - whiteChalk, - whiteChalkUses, - whiteChalkUses2, - goldChalk, - goldChalkUses, - purpleChalk, - purpleChalkUses, - redChalk, - redChalkUses - ); - } - - private BookEntryModel makeSummonFoliotEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_foliot"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("summon_foliot")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makePossessFoliotEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("possess_foliot"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("possess_foliot")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makeCraftFoliotEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_foliot"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("craft_foliot")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makeSummonDjinniEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_djinni"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("summon_djinni")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makePossessDjinniEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("possess_djinni"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("possess_djinni")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("uses2"); - var uses2 = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses, - uses2 - ); - } - - private BookEntryModel makeCraftDjinniEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_djinni"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("craft_djinni")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makeSummonAfritEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_afrit"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("summon_afrit")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makeSummonWildAfritEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_wild_afrit"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("summon_wild_afrit")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makePossessAfritEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("possess_afrit"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("possess_afrit")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makeCraftAfritEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_afrit"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("craft_afrit")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makeSummonMaridEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_marid"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("summon_marid")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makeCraftMaridEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_marid"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("craft_marid")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - - private BookEntryModel makeSummonWildGreaterSpiritEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_wild_greater_spirit"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("multiblock"); - var multiblock = BookMultiblockPageModel.create() - .withMultiblockId(this.modLoc("summon_wild_greater_spirit")); - - this.context().page("uses"); - var uses = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.PENTACLE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - multiblock, - uses - ); - } - //endregion - - private BookCategoryModel makeRitualsCategory() { - this.context().category("rituals"); - - var entryMap = ModonomiconAPI.get().getEntryMap(); - entryMap.setMap( - "___________________", - "______________p_s__", - "___________________", - "________o_i_k______", - "___________________", - "______________c_f__", - "___________________" - ); - - var ritualOverview = this.makeRitualOverviewEntry(entryMap, 'o'); - var itemUse = this.makeItemUseEntry(entryMap, 'i'); - itemUse.withParent(BookEntryParentModel.create(ritualOverview.getId())); - var sacrifice = this.makeSacrificeEntry(entryMap, 'k'); - sacrifice.withParent(BookEntryParentModel.create(itemUse.getId())); - - var summoning = this.makeSummoningRitualsSubcategoryEntry(entryMap, 's'); - summoning.withParent(BookEntryParentModel.create(sacrifice.getId())); - var possession = this.makePossessionRitualsSubcategoryEntry(entryMap, 'p'); - possession.withParent(BookEntryParentModel.create(sacrifice.getId())); - var crafting = this.makeCraftingRitualsSubcategoryEntry(entryMap, 'c'); - crafting.withParent(BookEntryParentModel.create(sacrifice.getId())); - var familiars = this.makeFamiliarRitualsSubcategoryEntry(entryMap, 'f'); - familiars.withParent(BookEntryParentModel.create(sacrifice.getId())); - - //enable all entries by default - itemUse.withCondition(BookTrueConditionModel.create()); - sacrifice.withCondition(BookTrueConditionModel.create()); - summoning.withCondition(BookTrueConditionModel.create()); - possession.withCondition(BookTrueConditionModel.create()); - crafting.withCondition(BookTrueConditionModel.create()); - familiars.withCondition(BookTrueConditionModel.create()); - - return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) - .withIcon(this.modLoc("textures/gui/book/robe.png")) - .withEntries( - ritualOverview, - itemUse, - sacrifice, - summoning, - possession, - crafting, - familiars - ); - } - - private BookEntryModel makeRitualOverviewEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("overview"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("steps"); - var steps = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("additional_requirements"); - var additional_requirements = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/robe.png")) - .withLocation(entryMap.get(icon)) - .withEntryBackground(0, 1) - .withPages( - intro, - steps, - additional_requirements - ); - } - - private BookEntryModel makeSacrificeEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("sacrifice"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.IRON_SWORD) - .withLocation(entryMap.get(icon)) - .withPages( - intro - ); - } - - private BookEntryModel makeItemUseEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("item_use"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.FLINT_AND_STEEL) - .withLocation(entryMap.get(icon)) - .withPages( - intro - ); - } - - private BookEntryModel makeSummoningRitualsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summoning_rituals"); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/summoning.png")) - .withCategoryToOpen(this.modLoc("summoning_rituals")) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withLocation(entryMap.get(icon)); - } - - private BookEntryModel makePossessionRitualsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("possession_rituals"); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/possession.png")) - .withCategoryToOpen(this.modLoc("possession_rituals")) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withLocation(entryMap.get(icon)); - } - - private BookEntryModel makeCraftingRitualsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("crafting_rituals"); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/infusion.png")) - .withCategoryToOpen(this.modLoc("crafting_rituals")) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withLocation(entryMap.get(icon)); - } - - private BookEntryModel makeFamiliarRitualsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_rituals"); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/parrot.png")) - .withCategoryToOpen(this.modLoc("familiar_rituals")) - .withEntryBackground(1, 1) //silver background and wavey entry shape - .withLocation(entryMap.get(icon)); - } - - private BookEntryModel makeReturnToRitualsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("return_to_rituals"); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/robe.png")) - .withCategoryToOpen(this.modLoc("rituals")) - .withEntryBackground(1, 2) - .withLocation(entryMap.get(icon)); - } - //endregion - - //region Summoning Rituals - private BookCategoryModel makeSummoningRitualsSubcategory() { - this.context().category("summoning_rituals"); - - var entryMap = ModonomiconAPI.get().getEntryMap(); - entryMap.setMap( - "___________b___l______", - "______________________", - "_________c_d_h_k______", - "______________________", - "___r_o________________", - "______________________", - "_________1_e_i_a_m___", - "______________________", - "_________2_f___I______", - "______________________", - "_________3_g_j________", - "______________________", - "_________4____________" - ); - - var overview = this.makeSummoningRitualsOverviewEntry(entryMap, 'o'); - var returnToRituals = this.makeReturnToRitualsEntry(entryMap, 'r'); - returnToRituals.withParent(BookEntryParentModel.create(overview.getId())); - returnToRituals.withCondition(BookTrueConditionModel.create()); - - var summonT1Crusher = this.makeSummonCrusherT1Entry(entryMap, '1'); - summonT1Crusher.withParent(BookEntryParentModel.create(overview.getId())); - var summonT2Crusher = this.makeSummonCrusherT2Entry(entryMap, '2'); - summonT2Crusher.withParent(BookEntryParentModel.create(summonT1Crusher.getId())); - var summonT3Crusher = this.makeSummonCrusherT3Entry(entryMap, '3'); - summonT3Crusher.withParent(BookEntryParentModel.create(summonT2Crusher.getId())); - var summonT4Crusher = this.makeSummonCrusherT4Entry(entryMap, '4'); - summonT4Crusher.withParent(BookEntryParentModel.create(summonT3Crusher.getId())); - - var summonLumberjack = this.makeSummonLumberjackEntry(entryMap, 'c'); - summonLumberjack.withParent(BookEntryParentModel.create(overview.getId())); - - var summonTransportItems = this.makeSummonTransportItemsEntry(entryMap, 'd'); - summonTransportItems.withParent(BookEntryParentModel.create(overview.getId())); - var summonCleaner = this.makeSummonCleanerEntry(entryMap, 'b'); - summonCleaner.withParent(BookEntryParentModel.create(summonTransportItems.getId())); - var summonManageMachine = this.makeSummonManageMachineEntry(entryMap, 'h'); - summonManageMachine.withParent(BookEntryParentModel.create(summonTransportItems.getId())); - - var tradeSpirits = this.makeTradeSpiritsEntry(entryMap, 'e'); - tradeSpirits.withParent(BookEntryParentModel.create(overview.getId())); - var summonOtherworldSaplingTrader = this.makeSummonOtherworldSaplingTraderEntry(entryMap, 'f'); - summonOtherworldSaplingTrader.withParent(BookEntryParentModel.create(tradeSpirits.getId())); - var summonOtherstoneTrader = this.makeSummonOtherstoneTraderEntry(entryMap, 'g'); - summonOtherstoneTrader.withParent(BookEntryParentModel.create(summonOtherworldSaplingTrader.getId())); - - var summonWildParrot = this.makeSummonWildParrotEntry(entryMap, 'i'); - summonWildParrot.withParent(BookEntryParentModel.create(overview.getId())); - var summonWildOtherworldBird = this.makeSummonWildOtherworldBirdEntry(entryMap, 'j'); - summonWildOtherworldBird.withParent(BookEntryParentModel.create(summonWildParrot.getId())); - - var summonRandomAnimal = this.makeSummonRandomAnimalEntry(entryMap, 'I'); - summonRandomAnimal.withParent(BookEntryParentModel.create(summonWildParrot.getId()).withLineReversed(true)); - - var weatherMagic = this.makeWeatherMagicEntry(entryMap, 'k'); - weatherMagic.withParent(BookEntryParentModel.create(overview.getId())); - var timeMagic = this.makeTimeMagicEntry(entryMap, 'l'); - timeMagic.withParent(BookEntryParentModel.create(weatherMagic.getId())); - - var afritEssence = this.makeAfritEssenceEntry(entryMap, 'a'); - afritEssence.withParent(BookEntryParentModel.create(overview.getId())); - - var witherSkull = this.makeWitherSkullEntry(entryMap, 'm'); - witherSkull.withParent(BookEntryParentModel.create(overview.getId())); - - //add true condition to all entries to enable them by default - overview.withCondition(BookTrueConditionModel.create()); - summonT1Crusher.withCondition(BookTrueConditionModel.create()); - summonT2Crusher.withCondition(BookTrueConditionModel.create()); - summonT3Crusher.withCondition(BookTrueConditionModel.create()); - summonT4Crusher.withCondition(BookTrueConditionModel.create()); - summonLumberjack.withCondition(BookTrueConditionModel.create()); - summonTransportItems.withCondition(BookTrueConditionModel.create()); - summonCleaner.withCondition(BookTrueConditionModel.create()); - summonManageMachine.withCondition(BookTrueConditionModel.create()); - tradeSpirits.withCondition(BookTrueConditionModel.create()); - summonOtherworldSaplingTrader.withCondition(BookTrueConditionModel.create()); - summonOtherstoneTrader.withCondition(BookTrueConditionModel.create()); - summonWildParrot.withCondition(BookTrueConditionModel.create()); - summonRandomAnimal.withCondition(BookTrueConditionModel.create()); - summonWildOtherworldBird.withCondition(BookTrueConditionModel.create()); - weatherMagic.withCondition(BookTrueConditionModel.create()); - timeMagic.withCondition(BookTrueConditionModel.create()); - afritEssence.withCondition(BookTrueConditionModel.create()); - witherSkull.withCondition(BookTrueConditionModel.create()); - - return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) - .withIcon(this.modLoc("textures/gui/book/summoning.png")) - .withShowCategoryButton(true) - .withEntries( - overview, - returnToRituals, - afritEssence, - summonCleaner, - summonT1Crusher, - summonT2Crusher, - summonT3Crusher, - summonT4Crusher, - summonLumberjack, - summonManageMachine, - summonTransportItems, - tradeSpirits, - summonOtherstoneTrader, - summonOtherworldSaplingTrader, - summonWildOtherworldBird, - summonWildParrot, - summonRandomAnimal, - timeMagic, - weatherMagic, - witherSkull, - afritEssence - ); - } - - private BookEntryModel makeSummoningRitualsOverviewEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("overview"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/summoning.png")) - .withLocation(entryMap.get(icon)) - .withEntryBackground(0, 1) - .withPages( - intro - ); - } - - private BookEntryModel makeAfritEssenceEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("afrit_essence"); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_wild_afrit")); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.AFRIT_ESSENCE.get()) - .withLocation(entryMap.get(icon)) - .withPages( - intro, - ritual - ); - } - - private BookEntryModel makeSummonCrusherT1Entry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_crusher_t1"); - this.lang().add(this.context().entryName(), "Summon Foliot Crusher"); - - this.context().page("about_crushers"); - var aboutCrushers = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Crusher Spirits"); - this.lang().add(this.context().pageText(), - """ - Crusher spirits are summoned to crush ores into dusts, effectively multiplying the metal output. They will pick up appropriate ores and drop the resulting dusts into the world. A purple particle effect and a crushing sound indicate the crusher is at work. - """); - - this.context().page("automation"); - var automation = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Automation"); - this.lang().add(this.context().pageText(), - """ - To ease automation, try summoning a [Transporter Spirit](entry://occultism:dictionary_of_spirits/summoning_rituals/summon_transport_items) - to place items from chests in the crusher's inventory, and a [Janitor Spirit](entry://occultism:dictionary_of_spirits/summoning_rituals/summon_cleaner) to collect the processed items. - """); - - this.context().page("intro"); - var intro = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Foliot Crusher"); - this.lang().add(this.context().pageText(), - """ - The foliot crusher is the most basic crusher spirit. - \\ - \\ - It will crush **one** ore into **two** corresponding dusts. - """); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_foliot_crusher")); - //no text - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.COPPER_DUST.get()) - .withLocation(entryMap.get(icon)) - .withPages( - aboutCrushers, - automation, - intro, - ritual - ); - } - - private BookEntryModel makeSummonCrusherT2Entry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_crusher_t2"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("possess_foliot")); - this.context().page("intro"); - var intro = BookTextPageModel.create() + this.context().page("uses"); + var uses = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_djinni_crusher")); - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.IRON_DUST.get()) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - ritual + multiblock, + uses ); } - private BookEntryModel makeSummonCrusherT3Entry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_crusher_t3"); + private BookEntryModel makeCraftFoliotEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_foliot"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_afrit_crusher")); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("craft_foliot")); + + this.context().page("uses"); + var uses = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.SILVER_DUST.get()) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - ritual + multiblock, + uses ); } - private BookEntryModel makeSummonCrusherT4Entry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_crusher_t4"); + private BookEntryModel makeSummonDjinniEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_djinni"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_marid_crusher")); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("summon_djinni")); + + this.context().page("uses"); + var uses = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.GOLD_DUST.get()) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - ritual + multiblock, + uses ); } - private BookEntryModel makeSummonLumberjackEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_lumberjack"); - this.lang().add(this.context().entryName(), "Summon Foliot Lumberjack"); + private BookEntryModel makePossessDjinniEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("possess_djinni"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Foliot Lumberjack"); - this.lang().add(this.context().pageText(), - """ - The lumberjack will harvest trees in it's working area. If a deposit location is set it will collect the dropped items into the specified chest, and re-plant saplings. - """); - - this.context().page("prerequisites"); - var prerequisites = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Prerequisites"); - this.lang().add(this.context().pageText(), - """ - Summoning the lumberjack requires a [Stable Otherworld Sapling](item://occultism:otherworld_sapling). You can obtain it by summoning an [Otherworld Sapling Trader](entry://summoning_rituals/summon_otherworld_sapling_trader). - """ - ); - - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_foliot_lumberjack")); - //no text - this.context().page("book_of_calling"); - var bookOfCalling = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/book_of_calling_foliot_lumberjack")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - If you lose the book of calling, you can craft a new one. - [#](%1$s)Shift-right-click[#]() the spirit with the crafted book to assign it. - """.formatted(COLOR_PURPLE)); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("possess_djinni")); - this.context().page("usage"); - var usage = BookTextPageModel.create() + this.context().page("uses"); + var uses = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Usage"); - this.lang().add(this.context().pageText(), - """ - Use the book of calling to set the work area and deposit location of the lumberjack. - \\ - \\ - See [Books of Calling](entry://getting_started/books_of_calling) for more information. - """); - this.context().page("usage2"); - var usage2 = BookTextPageModel.create() + this.context().page("uses2"); + var uses2 = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Lazy Lumberjack?"); - this.lang().add(this.context().pageText(), - """ - The spirit might pause for a few minutes after clearing his work area, even if trees have regrown since. This is a performance-saving measure and not a bug, he will continue on his own. - \\ - \\ - Set the work area again to make him continue work immediately. - """); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.BRUSH.get()) - .withIcon(Items.IRON_AXE) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - prerequisites, - ritual, - bookOfCalling, - usage, - usage2 + multiblock, + uses, + uses2 ); } - private BookEntryModel makeSummonTransportItemsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_transport_items"); - this.lang().add(this.context().entryName(), "Summon Foliot Transporter"); + private BookEntryModel makeCraftDjinniEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_djinni"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Foliot Transporter"); - this.lang().add(this.context().pageText(), - """ - The transporter is useful in that you don't need a train of hoppers transporting stuff, and can use any inventory to take from and deposit. - \\ - \\ - To make it take from an inventory simply sneak and interact with it's book of calling on the inventory you want. - """); - - this.context().page("intro2"); - var intro2 = BookTextPageModel.create() - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - You can also dictate which inventory it deposits to in the same way. - \\ - The transporter will move all items it can access from one inventory to another, including machines. It can also deposit into the inventories of other spirits. By setting the extract and insert side they can be used to automate various transport tasks. - """); - this.context().page("spirit_inventories"); - var spirit_inventories = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Spirit Inventories"); - this.lang().add(this.context().pageText(), - """ - The Transporter can also interact with the inventories of other spirits. This is especially useful to automatically supply a [Crusher spirit](entry://summoning_rituals/summon_crusher_t1) with items to crush. - """); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("craft_djinni")); - this.context().page("item_filters"); - var itemFilters = BookTextPageModel.create() + this.context().page("uses"); + var uses = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Item Filters"); - this.lang().add(this.context().pageText(), - """ - By default the Transporter is in "Whitelist" mode and will not move anything. Shift-click the transporter to open the config UI. You can then add items to the filter list to make it move only those items, or set it to "Blacklist" to move everything *except* the filtered items. You can also enter a tag in the text field below to filter by tag. - """); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_foliot_transport_items")); - //no text - - this.context().page("book_of_calling"); - var bookOfCalling = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/book_of_calling_foliot_transport_items")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - If you lose the book of calling, you can craft a new one. - [#](%1$s)Shift-right-click[#]() the spirit with the crafted book to assign it. - """.formatted(COLOR_PURPLE)); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.MINECART) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - intro2, - spirit_inventories, - itemFilters, - ritual, - bookOfCalling + multiblock, + uses ); } - private BookEntryModel makeSummonCleanerEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_cleaner"); - this.lang().add(this.context().entryName(), "Summon Foliot Janitor"); + private BookEntryModel makeSummonAfritEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_afrit"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Foliot Janitor"); - this.lang().add(this.context().pageText(), - """ - The janitor will pick up dropped items and deposit them into a target inventory. You can configure an allow/block list to specify which items to pick up or ignore. **Warning**: By default it is set to "allow" mode, so it will only pick up items you specify in the allow list. - You can use tags to handle whole groups of items. - """); - this.context().page("intro2"); - var intro2 = BookTextPageModel.create() - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - To bind the janitor to an inventory simply sneak and interact with the janitor book of calling on that inventory. You can also interact with a block while holding the janitor book of calling to have it deposit items there. You can also have it wander around a select area by pulling up that interface. To configure an allow/block list sneak and interact with the janitor. - """); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("summon_afrit")); - this.context().page("tip"); - var tip = BookTextPageModel.create() + this.context().page("uses"); + var uses = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.lang().add(this.context().pageTitle(), "Pro tip"); - this.lang().add(this.context().pageText(), - """ - The Janitor will pick up crushed items from a [Crusher spirit](entry://summoning_rituals/summon_crusher_t1) and deposit them into a chest. - \\ - \\ - Combine that with a [Transporter Spirit](entry://summoning_rituals/summon_transport_items) to automate the whole process. - """); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_foliot_cleaner")); - //no text - - this.context().page("book_of_calling"); - var bookOfCalling = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/book_of_calling_foliot_cleaner")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), - """ - If you lose the book of calling, you can craft a new one. - [#](%1$s)Shift-right-click[#]() the spirit with the crafted book to assign it. - """.formatted(COLOR_PURPLE)); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.BRUSH.get()) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - intro2, - tip, - ritual, - bookOfCalling + multiblock, + uses ); } - private BookEntryModel makeSummonManageMachineEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_manage_machine"); + private BookEntryModel makeSummonWildAfritEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_wild_afrit"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("tutorial"); - var tutorial = BookTextPageModel.create() - .withText(this.context().pageText()); - - this.context().page("tutorial2"); - var tutorial2 = BookTextPageModel.create() - .withText(this.context().pageText()); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_djinni_manage_machine")); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("summon_wild_afrit")); - this.context().page("book_of_calling"); - var bookOfCalling = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/book_of_calling_djinni_manage_machine")) + this.context().page("uses"); + var uses = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.LEVER) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - tutorial, - tutorial2, - ritual, - bookOfCalling + multiblock, + uses ); } - private BookEntryModel makeTradeSpiritsEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("trade_spirits"); + private BookEntryModel makePossessAfritEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("possess_afrit"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("intro2"); - var intro2 = BookTextPageModel.create() + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("possess_afrit")); + + this.context().page("uses"); + var uses = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/cash.png")) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - intro2 + multiblock, + uses ); } - private BookEntryModel makeSummonOtherstoneTraderEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_otherstone_trader"); + private BookEntryModel makeCraftAfritEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_afrit"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("trade"); - var trade = BookSpiritTradeRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_trade/stone_to_otherstone")); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("craft_afrit")); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_foliot_otherstone_trader")); + this.context().page("uses"); + var uses = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.OTHERSTONE.get()) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - trade, - ritual + multiblock, + uses ); } - private BookEntryModel makeSummonOtherworldSaplingTraderEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_otherworld_sapling_trader"); + private BookEntryModel makeSummonMaridEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_marid"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("trade"); - var trade = BookSpiritTradeRecipePageModel.create() - .withRecipeId1(this.modLoc("spirit_trade/otherworld_sapling")) - .withText(this.context().pageText()); - this.lang().add(this.context().pageText(), """ - To trade, drop an your offered item next to the trader, he will pick it up and drop the exchanged item. - """); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("summon_marid")); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_foliot_sapling_trader")); + this.context().page("uses"); + var uses = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.OTHERWORLD_SAPLING.get()) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - trade, - ritual + multiblock, + uses ); } - private BookEntryModel makeSummonWildParrotEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_wild_parrot"); + private BookEntryModel makeCraftMaridEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_marid"); - this.context().page("entity"); - var entity = BookEntityPageModel.create() - .withEntityId("minecraft:parrot") + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_wild_parrot")); - - this.context().page("description"); - var description = BookTextPageModel.create() - .withText(this.context().pageText()); + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("craft_marid")); - this.context().page("description2"); - var description2 = BookTextPageModel.create() + this.context().page("uses"); + var uses = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/parrot.png")) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( - entity, - ritual, - description, - description2 + intro, + multiblock, + uses ); } - private BookEntryModel makeSummonRandomAnimalEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_random_animal"); - this.add(this.context().entryName(), "Summon Random Animal"); + private BookEntryModel makeSummonWildGreaterSpiritEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_wild_greater_spirit"); - this.context().page("entity"); - var entity = BookEntityPageModel.create() - .withEntityId("minecraft:cow") - .withEntityName(this.context().pageTitle()) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.add(this.context().pageTitle(), "Summon Random Animal"); - this.add(this.context().pageText(), - """ - **Provides**: A random animal - """ - ); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_random_animal")); - //no text + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("summon_wild_greater_spirit")); - this.context().page("description"); - var description = BookTextPageModel.create() + this.context().page("uses"); + var uses = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.add(this.context().pageText(), - """ - In this ritual a [#](%1$s)Foliot[#]() is summoned **as an untamed spirit** to take the shape of a random animal. - \\ - \\ - The animal can be interacted with as it's natural counterpart, including taming, breeding and loot. - """.formatted(COLOR_PURPLE)); - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.COW_SPAWN_EGG) + .withIcon(OccultismItems.PENTACLE.get()) .withLocation(entryMap.get(icon)) .withPages( - entity, - ritual, - description + intro, + multiblock, + uses ); } + //endregion - private BookEntryModel makeSummonWildOtherworldBirdEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("summon_wild_otherworld_bird"); + private BookCategoryModel makeRitualsCategory() { + this.context().category("rituals"); - this.context().page("entity"); - var entity = BookEntityPageModel.create() - .withEntityId("occultism:otherworld_bird") - .withText(this.context().pageText()); + var entryMap = ModonomiconAPI.get().getEntryMap(); + entryMap.setMap( + "___________________", + "______________p_s__", + "___________________", + "________o_i_k______", + "___________________", + "______________c_f__", + "___________________" + ); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_wild_otherworld_bird")); + var ritualOverview = this.makeRitualOverviewEntry(entryMap, 'o'); + var itemUse = this.makeItemUseEntry(entryMap, 'i'); + itemUse.withParent(BookEntryParentModel.create(ritualOverview.getId())); + var sacrifice = this.makeSacrificeEntry(entryMap, 'k'); + sacrifice.withParent(BookEntryParentModel.create(itemUse.getId())); - this.context().page("description"); - var description = BookTextPageModel.create() - .withText(this.context().pageText()); + var summoning = this.makeSummoningRitualsSubcategoryEntry(entryMap, 's'); + summoning.withParent(BookEntryParentModel.create(sacrifice.getId())); + var possession = this.makePossessionRitualsSubcategoryEntry(entryMap, 'p'); + possession.withParent(BookEntryParentModel.create(sacrifice.getId())); + var crafting = this.makeCraftingRitualsSubcategoryEntry(entryMap, 'c'); + crafting.withParent(BookEntryParentModel.create(sacrifice.getId())); + var familiars = this.makeFamiliarRitualsSubcategoryEntry(entryMap, 'f'); + familiars.withParent(BookEntryParentModel.create(sacrifice.getId())); - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/otherworld_bird.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description + //enable all entries by default + itemUse.withCondition(BookTrueConditionModel.create()); + sacrifice.withCondition(BookTrueConditionModel.create()); + summoning.withCondition(BookTrueConditionModel.create()); + possession.withCondition(BookTrueConditionModel.create()); + crafting.withCondition(BookTrueConditionModel.create()); + familiars.withCondition(BookTrueConditionModel.create()); + + return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) + .withIcon(this.modLoc("textures/gui/book/robe.png")) + .withEntries( + ritualOverview, + itemUse, + sacrifice, + summoning, + possession, + crafting, + familiars ); } - private BookEntryModel makeWeatherMagicEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("weather_magic"); + private BookEntryModel makeRitualOverviewEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("overview"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("ritual_clear"); - var ritualClear = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_djinni_clear_weather")) - .withAnchor("clear"); - - this.context().page("ritual_rain"); - var ritualRain = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_afrit_rain_weather")) - .withAnchor("rain"); - - this.context().page("ritual_thunder"); - var ritualThunder = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_afrit_thunder_weather")) - .withAnchor("thunder"); - + this.context().page("steps"); + var steps = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + this.context().page("additional_requirements"); + var additional_requirements = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.WHEAT) + .withIcon(this.modLoc("textures/gui/book/robe.png")) .withLocation(entryMap.get(icon)) + .withEntryBackground(0, 1) .withPages( intro, - ritualClear, - ritualRain, - ritualThunder + steps, + additional_requirements ); } - private BookEntryModel makeTimeMagicEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("time_magic"); + private BookEntryModel makeSacrificeEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("sacrifice"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("ritual_day"); - var ritualDay = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_djinni_day_time")) - .withAnchor("day"); - - this.context().page("ritual_night"); - var ritualNight = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_djinni_night_time")) - .withAnchor("night"); - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.CLOCK) + .withIcon(Items.IRON_SWORD) .withLocation(entryMap.get(icon)) .withPages( - intro, - ritualDay, - ritualNight + intro ); } - private BookEntryModel makeWitherSkullEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("wither_skull"); + private BookEntryModel makeItemUseEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("item_use"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/summon_wild_hunt")); - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.WITHER_SKELETON_SKULL) + .withIcon(Items.FLINT_AND_STEEL) .withLocation(entryMap.get(icon)) .withPages( - intro, - ritual + intro ); } + + private BookEntryModel makeSummoningRitualsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summoning_rituals"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/summoning.png")) + .withCategoryToOpen(this.modLoc("summoning_rituals")) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withLocation(entryMap.get(icon)); + } + + private BookEntryModel makePossessionRitualsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("possession_rituals"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/possession.png")) + .withCategoryToOpen(this.modLoc("possession_rituals")) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withLocation(entryMap.get(icon)); + } + + private BookEntryModel makeCraftingRitualsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("crafting_rituals"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/infusion.png")) + .withCategoryToOpen(this.modLoc("crafting_rituals")) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withLocation(entryMap.get(icon)); + } + + private BookEntryModel makeFamiliarRitualsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_rituals"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/parrot.png")) + .withCategoryToOpen(this.modLoc("familiar_rituals")) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withLocation(entryMap.get(icon)); + } + + //endregion - //region Crafting Rituals - private BookCategoryModel makeCraftingRitualsSubcategory() { - this.context().category("crafting_rituals"); + //region Summoning Rituals + private BookCategoryModel makeSummoningRitualsSubcategory() { + this.context().category("summoning_rituals"); var entryMap = ModonomiconAPI.get().getEntryMap(); entryMap.setMap( - "___________________________", - "_______b_e_x_p_q___________", - "___________________________", - "_______d_h_c__w____________", - "___________________________", - "___9_0_____________________", - "___________________________", - "_______f_z_a__g____________", - "___________________________", - "___________n_m_o___________", - "___________________________", - "___________i_j_k_l_________", - "___________________________" + "___________b___l______", + "______________________", + "_________c_d_h_k______", + "______________________", + "___r_o________________", + "______________________", + "_________1_e_i_a_m___", + "______________________", + "_________2_f___I______", + "______________________", + "_________3_g_j________", + "______________________", + "_________4____________" ); - var overview = this.makeCraftingRitualsOverviewEntry(entryMap, '0'); - var returnToRituals = this.makeReturnToRitualsEntry(entryMap, '9'); + var overview = this.makeSummoningRitualsOverviewEntry(entryMap, 'o'); + var returnToRituals = this.makeReturnToRitualsEntry(entryMap, 'r'); returnToRituals.withParent(BookEntryParentModel.create(overview.getId())); returnToRituals.withCondition(BookTrueConditionModel.create()); - var craftInfusedPickaxe = this.makeCraftInfusedPickaxeEntry(entryMap, 'd'); - craftInfusedPickaxe.withParent(BookEntryParentModel.create(overview.getId())); - var craftDimensionalMineshaft = this.makeCraftDimensionalMineshaftEntry(entryMap, 'b'); - craftDimensionalMineshaft.withParent(BookEntryParentModel.create(craftInfusedPickaxe.getId())); - var craftFoliotMiner = this.makeCraftFoliotMinerEntry(entryMap, 'e'); - craftFoliotMiner.withParent(BookEntryParentModel.create(craftDimensionalMineshaft.getId())); - var craftDjinniMiner = this.makeCraftDjinniMinerEntry(entryMap, 'x'); - craftDjinniMiner.withParent(BookEntryParentModel.create(craftFoliotMiner.getId())); - var craftAfritMiner = this.makeCraftAfritMinerEntry(entryMap, 'p'); - craftAfritMiner.withParent(BookEntryParentModel.create(craftDjinniMiner.getId())); - var craftMaridMiner = this.makeCraftMaridMinerEntry(entryMap, 'q'); - craftMaridMiner.withParent(BookEntryParentModel.create(craftAfritMiner.getId())); - - var craftStorageSystem = this.makeCraftStorageSystemEntry(entryMap, 'z'); - craftStorageSystem.withParent(BookEntryParentModel.create(overview.getId())); - - var craftDimensionalMatrix = this.makeCraftDimensionalMatrixEntry(entryMap, 'a'); - craftDimensionalMatrix.withParent(BookEntryParentModel.create(craftStorageSystem.getId())); - var craftStorageControllerBase = this.makeCraftStorageControllerBaseEntry(entryMap, 'n'); - craftStorageControllerBase.withParent(BookEntryParentModel.create(craftDimensionalMatrix.getId())); - var craftStabilizerTier1 = this.makeCraftStabilizerTier1Entry(entryMap, 'i'); - craftStabilizerTier1.withParent(BookEntryParentModel.create(craftStorageControllerBase.getId())); - var craftStabilizerTier2 = this.makeCraftStabilizerTier2Entry(entryMap, 'j'); - craftStabilizerTier2.withParent(BookEntryParentModel.create(craftStabilizerTier1.getId())); - var craftStabilizerTier3 = this.makeCraftStabilizerTier3Entry(entryMap, 'k'); - craftStabilizerTier3.withParent(BookEntryParentModel.create(craftStabilizerTier2.getId())); - var craftStabilizerTier4 = this.makeCraftStabilizerTier4Entry(entryMap, 'l'); - craftStabilizerTier4.withParent(BookEntryParentModel.create(craftStabilizerTier3.getId())); - - var craftStableWormhole = this.makeCraftStableWormholeEntry(entryMap, 'm'); - craftStableWormhole.withParent(BookEntryParentModel.create(craftStorageControllerBase.getId())); - var craftStorageRemote = this.makeCraftStorageRemoteEntry(entryMap, 'o'); - craftStorageRemote.withParent(BookEntryParentModel.create(craftStableWormhole.getId())); - - var craftOtherworldGoggles = this.makeCraftOtherworldGogglesEntry(entryMap, 'f'); - craftOtherworldGoggles.withParent(BookEntryParentModel.create(overview.getId())); - - var craftSatchel = this.makeCraftSatchelEntry(entryMap, 'g'); - craftSatchel.withParent(BookEntryParentModel.create(overview.getId())); - - var craftSoulGem = this.makeCraftSoulGemEntry(entryMap, 'h'); - craftSoulGem.withParent(BookEntryParentModel.create(overview.getId())); - var craftFamiliarRing = this.makeCraftFamiliarRingEntry(entryMap, 'c'); - craftFamiliarRing.withParent(BookEntryParentModel.create(craftSoulGem.getId())); - - var craftWildTrim = this.makeCraftWildTrimEntry(entryMap, 'w'); - craftWildTrim.withParent(BookEntryParentModel.create(overview.getId())); + var summonT1Crusher = this.makeSummonCrusherT1Entry(entryMap, '1'); + summonT1Crusher.withParent(BookEntryParentModel.create(overview.getId())); + var summonT2Crusher = this.makeSummonCrusherT2Entry(entryMap, '2'); + summonT2Crusher.withParent(BookEntryParentModel.create(summonT1Crusher.getId())); + var summonT3Crusher = this.makeSummonCrusherT3Entry(entryMap, '3'); + summonT3Crusher.withParent(BookEntryParentModel.create(summonT2Crusher.getId())); + var summonT4Crusher = this.makeSummonCrusherT4Entry(entryMap, '4'); + summonT4Crusher.withParent(BookEntryParentModel.create(summonT3Crusher.getId())); + + var summonLumberjack = this.makeSummonLumberjackEntry(entryMap, 'c'); + summonLumberjack.withParent(BookEntryParentModel.create(overview.getId())); + + var summonTransportItems = this.makeSummonTransportItemsEntry(entryMap, 'd'); + summonTransportItems.withParent(BookEntryParentModel.create(overview.getId())); + var summonCleaner = this.makeSummonCleanerEntry(entryMap, 'b'); + summonCleaner.withParent(BookEntryParentModel.create(summonTransportItems.getId())); + var summonManageMachine = this.makeSummonManageMachineEntry(entryMap, 'h'); + summonManageMachine.withParent(BookEntryParentModel.create(summonTransportItems.getId())); + + var tradeSpirits = this.makeTradeSpiritsEntry(entryMap, 'e'); + tradeSpirits.withParent(BookEntryParentModel.create(overview.getId())); + var summonOtherworldSaplingTrader = this.makeSummonOtherworldSaplingTraderEntry(entryMap, 'f'); + summonOtherworldSaplingTrader.withParent(BookEntryParentModel.create(tradeSpirits.getId())); + var summonOtherstoneTrader = this.makeSummonOtherstoneTraderEntry(entryMap, 'g'); + summonOtherstoneTrader.withParent(BookEntryParentModel.create(summonOtherworldSaplingTrader.getId())); + + var summonWildParrot = this.makeSummonWildParrotEntry(entryMap, 'i'); + summonWildParrot.withParent(BookEntryParentModel.create(overview.getId())); + var summonWildOtherworldBird = this.makeSummonWildOtherworldBirdEntry(entryMap, 'j'); + summonWildOtherworldBird.withParent(BookEntryParentModel.create(summonWildParrot.getId())); + + var summonRandomAnimal = this.makeSummonRandomAnimalEntry(entryMap, 'I'); + summonRandomAnimal.withParent(BookEntryParentModel.create(summonWildParrot.getId()).withLineReversed(true)); + + var weatherMagic = this.makeWeatherMagicEntry(entryMap, 'k'); + weatherMagic.withParent(BookEntryParentModel.create(overview.getId())); + var timeMagic = this.makeTimeMagicEntry(entryMap, 'l'); + timeMagic.withParent(BookEntryParentModel.create(weatherMagic.getId())); + + var afritEssence = this.makeAfritEssenceEntry(entryMap, 'a'); + afritEssence.withParent(BookEntryParentModel.create(overview.getId())); + + var witherSkull = this.makeWitherSkullEntry(entryMap, 'm'); + witherSkull.withParent(BookEntryParentModel.create(overview.getId())); //add true condition to all entries to enable them by default overview.withCondition(BookTrueConditionModel.create()); - craftInfusedPickaxe.withCondition(BookTrueConditionModel.create()); - craftDimensionalMineshaft.withCondition(BookTrueConditionModel.create()); - craftFoliotMiner.withCondition(BookTrueConditionModel.create()); - craftDjinniMiner.withCondition(BookTrueConditionModel.create()); - craftAfritMiner.withCondition(BookTrueConditionModel.create()); - craftMaridMiner.withCondition(BookTrueConditionModel.create()); - craftStorageSystem.withCondition(BookTrueConditionModel.create()); - craftDimensionalMatrix.withCondition(BookTrueConditionModel.create()); - craftStorageControllerBase.withCondition(BookTrueConditionModel.create()); - craftStabilizerTier1.withCondition(BookTrueConditionModel.create()); - craftStabilizerTier2.withCondition(BookTrueConditionModel.create()); - craftStabilizerTier3.withCondition(BookTrueConditionModel.create()); - craftStabilizerTier4.withCondition(BookTrueConditionModel.create()); - craftStableWormhole.withCondition(BookTrueConditionModel.create()); - craftStorageRemote.withCondition(BookTrueConditionModel.create()); - craftOtherworldGoggles.withCondition(BookTrueConditionModel.create()); - craftSatchel.withCondition(BookTrueConditionModel.create()); - craftSoulGem.withCondition(BookTrueConditionModel.create()); - craftFamiliarRing.withCondition(BookTrueConditionModel.create()); - craftWildTrim.withCondition(BookTrueConditionModel.create()); + summonT1Crusher.withCondition(BookTrueConditionModel.create()); + summonT2Crusher.withCondition(BookTrueConditionModel.create()); + summonT3Crusher.withCondition(BookTrueConditionModel.create()); + summonT4Crusher.withCondition(BookTrueConditionModel.create()); + summonLumberjack.withCondition(BookTrueConditionModel.create()); + summonTransportItems.withCondition(BookTrueConditionModel.create()); + summonCleaner.withCondition(BookTrueConditionModel.create()); + summonManageMachine.withCondition(BookTrueConditionModel.create()); + tradeSpirits.withCondition(BookTrueConditionModel.create()); + summonOtherworldSaplingTrader.withCondition(BookTrueConditionModel.create()); + summonOtherstoneTrader.withCondition(BookTrueConditionModel.create()); + summonWildParrot.withCondition(BookTrueConditionModel.create()); + summonRandomAnimal.withCondition(BookTrueConditionModel.create()); + summonWildOtherworldBird.withCondition(BookTrueConditionModel.create()); + weatherMagic.withCondition(BookTrueConditionModel.create()); + timeMagic.withCondition(BookTrueConditionModel.create()); + afritEssence.withCondition(BookTrueConditionModel.create()); + witherSkull.withCondition(BookTrueConditionModel.create()); return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) - .withIcon(this.modLoc("textures/gui/book/infusion.png")) + .withIcon(this.modLoc("textures/gui/book/summoning.png")) .withShowCategoryButton(true) .withEntries( overview, returnToRituals, - craftStorageSystem, - craftDimensionalMatrix, - craftDimensionalMineshaft, - craftInfusedPickaxe, - craftFoliotMiner, - craftDjinniMiner, - craftAfritMiner, - craftMaridMiner, - craftOtherworldGoggles, - craftSatchel, - craftSoulGem, - craftFamiliarRing, - craftStabilizerTier1, - craftStabilizerTier2, - craftStabilizerTier3, - craftStabilizerTier4, - craftStableWormhole, - craftStorageControllerBase, - craftStorageRemote, - craftWildTrim + afritEssence, + summonCleaner, + summonT1Crusher, + summonT2Crusher, + summonT3Crusher, + summonT4Crusher, + summonLumberjack, + summonManageMachine, + summonTransportItems, + tradeSpirits, + summonOtherstoneTrader, + summonOtherworldSaplingTrader, + summonWildOtherworldBird, + summonWildParrot, + summonRandomAnimal, + timeMagic, + weatherMagic, + witherSkull, + afritEssence ); } - private BookEntryModel makeCraftingRitualsOverviewEntry(CategoryEntryMap entryMap, char icon) { + private BookEntryModel makeSummoningRitualsOverviewEntry(CategoryEntryMap entryMap, char icon) { this.context().entry("overview"); this.context().page("intro"); @@ -4181,7 +1365,7 @@ private BookEntryModel makeCraftingRitualsOverviewEntry(CategoryEntryMap entryMa .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/infusion.png")) + .withIcon(this.modLoc("textures/gui/book/summoning.png")) .withLocation(entryMap.get(icon)) .withEntryBackground(0, 1) .withPages( @@ -4189,484 +1373,661 @@ private BookEntryModel makeCraftingRitualsOverviewEntry(CategoryEntryMap entryMa ); } - private BookEntryModel makeCraftStorageSystemEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_storage_system"); + private BookEntryModel makeAfritEssenceEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("afrit_essence"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.STORAGE_CONTROLLER.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/summon_wild_afrit")); + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.CHEST) + .withIcon(OccultismItems.AFRIT_ESSENCE.get()) .withLocation(entryMap.get(icon)) .withPages( - spotlight + intro, + ritual ); } + private BookEntryModel makeSummonCrusherT1Entry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_crusher_t1"); + this.lang().add(this.context().entryName(), "Summon Foliot Crusher"); + + this.context().page("about_crushers"); + var aboutCrushers = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Crusher Spirits"); + this.lang().add(this.context().pageText(), + """ + Crusher spirits are summoned to crush ores into dusts, effectively multiplying the metal output. They will pick up appropriate ores and drop the resulting dusts into the world. A purple particle effect and a crushing sound indicate the crusher is at work. + """); - private BookEntryModel makeCraftDimensionalMatrixEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_dimensional_matrix"); + this.context().page("automation"); + var automation = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Automation"); + this.lang().add(this.context().pageText(), + """ + To ease automation, try summoning a [Transporter Spirit](entry://occultism:dictionary_of_spirits/summoning_rituals/summon_transport_items) + to place items from chests in the crusher's inventory, and a [Janitor Spirit](entry://occultism:dictionary_of_spirits/summoning_rituals/summon_cleaner) to collect the processed items. + """); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.DIMENSIONAL_MATRIX.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Foliot Crusher"); + this.lang().add(this.context().pageText(), + """ + The foliot crusher is the most basic crusher spirit. + \\ + \\ + It will crush **one** ore into **two** corresponding dusts. + """); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_dimensional_matrix")); + .withRecipeId1(this.modLoc("ritual/summon_foliot_crusher")); + //no text return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.DIMENSIONAL_MATRIX.get()) + .withIcon(OccultismItems.COPPER_DUST.get()) .withLocation(entryMap.get(icon)) .withPages( - spotlight, + aboutCrushers, + automation, + intro, ritual ); } - private BookEntryModel makeCraftDimensionalMineshaftEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_dimensional_mineshaft"); + private BookEntryModel makeSummonCrusherT2Entry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_crusher_t2"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.DIMENSIONAL_MINESHAFT.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_dimensional_mineshaft")); - - this.context().page("description"); - var description = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); + .withRecipeId1(this.modLoc("ritual/summon_djinni_crusher")); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.DIMENSIONAL_MINESHAFT.get()) + .withIcon(OccultismItems.IRON_DUST.get()) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - ritual, - description + intro, + ritual ); } - private BookEntryModel makeCraftInfusedPickaxeEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_infused_pickaxe"); + private BookEntryModel makeSummonCrusherT3Entry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_crusher_t3"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.INFUSED_PICKAXE.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_infused_pickaxe")); + .withRecipeId1(this.modLoc("ritual/summon_afrit_crusher")); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.INFUSED_PICKAXE.get()) + .withIcon(OccultismItems.SILVER_DUST.get()) .withLocation(entryMap.get(icon)) .withPages( - spotlight, + intro, ritual ); } - private BookEntryModel makeCraftStorageControllerBaseEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_storage_controller_base"); + private BookEntryModel makeSummonCrusherT4Entry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_crusher_t4"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.STORAGE_CONTROLLER_BASE.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_storage_controller_base")); + .withRecipeId1(this.modLoc("ritual/summon_marid_crusher")); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.STORAGE_CONTROLLER_BASE.get()) + .withIcon(OccultismItems.GOLD_DUST.get()) .withLocation(entryMap.get(icon)) .withPages( - spotlight, + intro, ritual ); } - private BookEntryModel makeCraftStabilizerTier1Entry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_stabilizer_tier1"); + private BookEntryModel makeSummonLumberjackEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_lumberjack"); + this.lang().add(this.context().entryName(), "Summon Foliot Lumberjack"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Foliot Lumberjack"); + this.lang().add(this.context().pageText(), + """ + The lumberjack will harvest trees in it's working area. If a deposit location is set it will collect the dropped items into the specified chest, and re-plant saplings. + """); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.STORAGE_STABILIZER_TIER1.get())) + this.context().page("prerequisites"); + var prerequisites = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Prerequisites"); + this.lang().add(this.context().pageText(), + """ + Summoning the lumberjack requires a [Stable Otherworld Sapling](item://occultism:otherworld_sapling). You can obtain it by summoning an [Otherworld Sapling Trader](entry://summoning_rituals/summon_otherworld_sapling_trader). + """ + ); + this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_stabilizer_tier1")); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.STORAGE_STABILIZER_TIER1.get()) - .withLocation(entryMap.get(icon)) - .withPages( - spotlight, - ritual - ); - } + .withRecipeId1(this.modLoc("ritual/summon_foliot_lumberjack")); + //no text - private BookEntryModel makeCraftStabilizerTier2Entry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_stabilizer_tier2"); + this.context().page("book_of_calling"); + var bookOfCalling = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/book_of_calling_foliot_lumberjack")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + If you lose the book of calling, you can craft a new one. + [#](%1$s)Shift-right-click[#]() the spirit with the crafted book to assign it. + """.formatted(COLOR_PURPLE)); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.STORAGE_STABILIZER_TIER2.get())) + this.context().page("usage"); + var usage = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Usage"); + this.lang().add(this.context().pageText(), + """ + Use the book of calling to set the work area and deposit location of the lumberjack. + \\ + \\ + See [Books of Calling](entry://getting_started/books_of_calling) for more information. + """); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_stabilizer_tier2")); + this.context().page("usage2"); + var usage2 = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Lazy Lumberjack?"); + this.lang().add(this.context().pageText(), + """ + The spirit might pause for a few minutes after clearing his work area, even if trees have regrown since. This is a performance-saving measure and not a bug, he will continue on his own. + \\ + \\ + Set the work area again to make him continue work immediately. + """); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.STORAGE_STABILIZER_TIER2.get()) + .withIcon(OccultismItems.BRUSH.get()) + .withIcon(Items.IRON_AXE) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - ritual + intro, + prerequisites, + ritual, + bookOfCalling, + usage, + usage2 ); } - private BookEntryModel makeCraftStabilizerTier3Entry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_stabilizer_tier3"); + private BookEntryModel makeSummonTransportItemsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_transport_items"); + this.lang().add(this.context().entryName(), "Summon Foliot Transporter"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.STORAGE_STABILIZER_TIER3.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Foliot Transporter"); + this.lang().add(this.context().pageText(), + """ + The transporter is useful in that you don't need a train of hoppers transporting stuff, and can use any inventory to take from and deposit. + \\ + \\ + To make it take from an inventory simply sneak and interact with it's book of calling on the inventory you want. + """); + + this.context().page("intro2"); + var intro2 = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + You can also dictate which inventory it deposits to in the same way. + \\ + The transporter will move all items it can access from one inventory to another, including machines. It can also deposit into the inventories of other spirits. By setting the extract and insert side they can be used to automate various transport tasks. + """); + + this.context().page("spirit_inventories"); + var spirit_inventories = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Spirit Inventories"); + this.lang().add(this.context().pageText(), + """ + The Transporter can also interact with the inventories of other spirits. This is especially useful to automatically supply a [Crusher spirit](entry://summoning_rituals/summon_crusher_t1) with items to crush. + """); + + this.context().page("item_filters"); + var itemFilters = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Item Filters"); + this.lang().add(this.context().pageText(), + """ + By default the Transporter is in "Whitelist" mode and will not move anything. Shift-click the transporter to open the config UI. You can then add items to the filter list to make it move only those items, or set it to "Blacklist" to move everything *except* the filtered items. You can also enter a tag in the text field below to filter by tag. + """); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_stabilizer_tier3")); + .withRecipeId1(this.modLoc("ritual/summon_foliot_transport_items")); + //no text + + this.context().page("book_of_calling"); + var bookOfCalling = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/book_of_calling_foliot_transport_items")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + If you lose the book of calling, you can craft a new one. + [#](%1$s)Shift-right-click[#]() the spirit with the crafted book to assign it. + """.formatted(COLOR_PURPLE)); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.STORAGE_STABILIZER_TIER3.get()) + .withIcon(Items.MINECART) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - ritual + intro, + intro2, + spirit_inventories, + itemFilters, + ritual, + bookOfCalling ); } - private BookEntryModel makeCraftStabilizerTier4Entry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_stabilizer_tier4"); + private BookEntryModel makeSummonCleanerEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_cleaner"); + this.lang().add(this.context().entryName(), "Summon Foliot Janitor"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.STORAGE_STABILIZER_TIER4.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Foliot Janitor"); + this.lang().add(this.context().pageText(), + """ + The janitor will pick up dropped items and deposit them into a target inventory. You can configure an allow/block list to specify which items to pick up or ignore. **Warning**: By default it is set to "allow" mode, so it will only pick up items you specify in the allow list. + You can use tags to handle whole groups of items. + """); + + this.context().page("intro2"); + var intro2 = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + To bind the janitor to an inventory simply sneak and interact with the janitor book of calling on that inventory. You can also interact with a block while holding the janitor book of calling to have it deposit items there. You can also have it wander around a select area by pulling up that interface. To configure an allow/block list sneak and interact with the janitor. + """); + + this.context().page("tip"); + var tip = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Pro tip"); + this.lang().add(this.context().pageText(), + """ + The Janitor will pick up crushed items from a [Crusher spirit](entry://summoning_rituals/summon_crusher_t1) and deposit them into a chest. + \\ + \\ + Combine that with a [Transporter Spirit](entry://summoning_rituals/summon_transport_items) to automate the whole process. + """); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_stabilizer_tier4")); + .withRecipeId1(this.modLoc("ritual/summon_foliot_cleaner")); + //no text + + this.context().page("book_of_calling"); + var bookOfCalling = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/book_of_calling_foliot_cleaner")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + If you lose the book of calling, you can craft a new one. + [#](%1$s)Shift-right-click[#]() the spirit with the crafted book to assign it. + """.formatted(COLOR_PURPLE)); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.STORAGE_STABILIZER_TIER4.get()) + .withIcon(OccultismItems.BRUSH.get()) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - ritual + intro, + intro2, + tip, + ritual, + bookOfCalling ); } - private BookEntryModel makeCraftStableWormholeEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_stable_wormhole"); + private BookEntryModel makeSummonManageMachineEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_manage_machine"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismBlocks.STABLE_WORMHOLE.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + this.context().page("tutorial"); + var tutorial = BookTextPageModel.create() + .withText(this.context().pageText()); + + this.context().page("tutorial2"); + var tutorial2 = BookTextPageModel.create() .withText(this.context().pageText()); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_stable_wormhole")); + .withRecipeId1(this.modLoc("ritual/summon_djinni_manage_machine")); + + this.context().page("book_of_calling"); + var bookOfCalling = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/book_of_calling_djinni_manage_machine")) + .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismBlocks.STABLE_WORMHOLE.get()) + .withIcon(Items.LEVER) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - ritual + intro, + tutorial, + tutorial2, + ritual, + bookOfCalling ); } - private BookEntryModel makeCraftStorageRemoteEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_storage_remote"); + private BookEntryModel makeTradeSpiritsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("trade_spirits"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.STORAGE_REMOTE.get())) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_storage_remote")); + this.context().page("intro2"); + var intro2 = BookTextPageModel.create() + .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.STORAGE_REMOTE.get()) + .withIcon(this.modLoc("textures/gui/book/cash.png")) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - ritual + intro, + intro2 ); } - private BookEntryModel makeCraftFoliotMinerEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_foliot_miner"); + private BookEntryModel makeSummonOtherstoneTraderEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_otherstone_trader"); this.context().page("intro"); var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("magic_lamp"); - var lamp = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()); - - this.context().page("magic_lamp_recipe"); - var lampRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/magic_lamp_empty")); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.MINER_FOLIOT_UNSPECIALIZED.get())) - .withText(this.context().pageText()); + this.context().page("trade"); + var trade = BookSpiritTradeRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_trade/stone_to_otherstone")); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_miner_foliot_unspecialized")); + .withRecipeId1(this.modLoc("ritual/summon_foliot_otherstone_trader")); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.MINER_FOLIOT_UNSPECIALIZED.get()) + .withIcon(OccultismBlocks.OTHERSTONE.get()) .withLocation(entryMap.get(icon)) .withPages( intro, - lamp, - lampRecipe, - spotlight, + trade, ritual ); } - private BookEntryModel makeCraftDjinniMinerEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_djinni_miner"); + private BookEntryModel makeSummonOtherworldSaplingTraderEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_otherworld_sapling_trader"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.MINER_DJINNI_ORES.get())) + this.context().page("trade"); + var trade = BookSpiritTradeRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_trade/otherworld_sapling")) .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), """ + To trade, drop an your offered item next to the trader, he will pick it up and drop the exchanged item. + """); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_miner_djinni_ores")); + .withRecipeId1(this.modLoc("ritual/summon_foliot_sapling_trader")); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.MINER_DJINNI_ORES.get()) + .withIcon(OccultismBlocks.OTHERWORLD_SAPLING.get()) .withLocation(entryMap.get(icon)) .withPages( - spotlight, + intro, + trade, ritual ); } - private BookEntryModel makeCraftAfritMinerEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_afrit_miner"); + private BookEntryModel makeSummonWildParrotEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_wild_parrot"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.MINER_AFRIT_DEEPS.get())) + this.context().page("entity"); + var entity = BookEntityPageModel.create() + .withEntityId("minecraft:parrot") .withText(this.context().pageText()); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_miner_afrit_deeps")); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.MINER_AFRIT_DEEPS.get()) - .withLocation(entryMap.get(icon)) - .withPages( - spotlight, - ritual - ); - } + .withRecipeId1(this.modLoc("ritual/summon_wild_parrot")); - private BookEntryModel makeCraftMaridMinerEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_marid_miner"); + this.context().page("description"); + var description = BookTextPageModel.create() + .withText(this.context().pageText()); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.MINER_MARID_MASTER.get())) + this.context().page("description2"); + var description2 = BookTextPageModel.create() .withText(this.context().pageText()); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_miner_marid_master")); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.MINER_MARID_MASTER.get()) + .withIcon(this.modLoc("textures/gui/book/parrot.png")) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - ritual + entity, + ritual, + description, + description2 ); } - private BookEntryModel makeCraftSatchelEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_satchel"); + private BookEntryModel makeSummonRandomAnimalEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_random_animal"); + this.add(this.context().entryName(), "Summon Random Animal"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.SATCHEL.get())) + this.context().page("entity"); + var entity = BookEntityPageModel.create() + .withEntityId("minecraft:cow") + .withEntityName(this.context().pageTitle()) .withText(this.context().pageText()); + this.add(this.context().pageTitle(), "Summon Random Animal"); + this.add(this.context().pageText(), + """ + **Provides**: A random animal + """ + ); + this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_satchel")); + .withRecipeId1(this.modLoc("ritual/summon_random_animal")); + //no text + + this.context().page("description"); + var description = BookTextPageModel.create() + .withText(this.context().pageText()); + this.add(this.context().pageText(), + """ + In this ritual a [#](%1$s)Foliot[#]() is summoned **as an untamed spirit** to take the shape of a random animal. + \\ + \\ + The animal can be interacted with as it's natural counterpart, including taming, breeding and loot. + """.formatted(COLOR_PURPLE)); + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.SATCHEL.get()) + .withIcon(Items.COW_SPAWN_EGG) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - ritual + entity, + ritual, + description ); } - private BookEntryModel makeCraftSoulGemEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_soul_gem"); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.SOUL_GEM_ITEM.get())) - .withText(this.context().pageText()); + private BookEntryModel makeSummonWildOtherworldBirdEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summon_wild_otherworld_bird"); - this.context().page("usage"); - var usage = BookTextPageModel.create() - .withTitle(this.context().pageTitle()) + this.context().page("entity"); + var entity = BookEntityPageModel.create() + .withEntityId("occultism:otherworld_bird") .withText(this.context().pageText()); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_soul_gem")); + .withRecipeId1(this.modLoc("ritual/summon_wild_otherworld_bird")); + + this.context().page("description"); + var description = BookTextPageModel.create() + .withText(this.context().pageText()); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.SOUL_GEM_ITEM.get()) + .withIcon(this.modLoc("textures/gui/book/otherworld_bird.png")) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - usage, - ritual + entity, + ritual, + description ); } - private BookEntryModel makeCraftFamiliarRingEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_familiar_ring"); - - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.FAMILIAR_RING.get())) - .withText(this.context().pageText()); + private BookEntryModel makeWeatherMagicEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("weather_magic"); - this.context().page("usage"); - var usage = BookTextPageModel.create() + this.context().page("intro"); + var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_familiar_ring")); + this.context().page("ritual_clear"); + var ritualClear = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/summon_djinni_clear_weather")) + .withAnchor("clear"); + + this.context().page("ritual_rain"); + var ritualRain = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/summon_afrit_rain_weather")) + .withAnchor("rain"); + + this.context().page("ritual_thunder"); + var ritualThunder = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/summon_afrit_thunder_weather")) + .withAnchor("thunder"); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.FAMILIAR_RING.get()) + .withIcon(Items.WHEAT) .withLocation(entryMap.get(icon)) .withPages( - spotlight, - usage, - ritual + intro, + ritualClear, + ritualRain, + ritualThunder ); } - private BookEntryModel makeCraftOtherworldGogglesEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_otherworld_goggles"); - - this.context().page("goggles_spotlight"); - var gogglesSpotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.OTHERWORLD_GOGGLES.get())) - .withText(this.context().pageText()); - - this.context().page("goggles_more"); - var gogglesMore = BookTextPageModel.create() - .withText(this.context().pageText()); - - this.context().page("lenses_spotlight"); - var lensesSpotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(OccultismItems.LENSES.get())) - .withText(this.context().pageText()); + private BookEntryModel makeTimeMagicEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("time_magic"); - this.context().page("lenses_more"); - var lensesMore = BookTextPageModel.create() + this.context().page("intro"); + var intro = BookTextPageModel.create() .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); - this.context().page("lenses_recipe"); - var lensesRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/lenses")); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_infused_lenses")); + this.context().page("ritual_day"); + var ritualDay = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/summon_djinni_day_time")) + .withAnchor("day"); - this.context().page("goggles_recipe"); - var gogglesRecipe = BookCraftingRecipePageModel.create() - .withRecipeId1(this.modLoc("crafting/goggles")); + this.context().page("ritual_night"); + var ritualNight = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/summon_djinni_night_time")) + .withAnchor("night"); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(OccultismItems.OTHERWORLD_GOGGLES.get()) + .withIcon(Items.CLOCK) .withLocation(entryMap.get(icon)) .withPages( - gogglesSpotlight, - gogglesMore, - lensesSpotlight, - lensesMore, - lensesRecipe, - ritual, - gogglesRecipe + intro, + ritualDay, + ritualNight ); } - private BookEntryModel makeCraftWildTrimEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("craft_wild_trim"); + private BookEntryModel makeWitherSkullEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("wither_skull"); - this.context().page("spotlight"); - var spotlight = BookSpotlightPageModel.create() - .withItem(Ingredient.of(Items.WILD_ARMOR_TRIM_SMITHING_TEMPLATE)) + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) .withText(this.context().pageText()); this.context().page("ritual"); var ritual = BookRitualRecipePageModel.create() - .withRecipeId1(this.modLoc("ritual/craft_wild_trim")); + .withRecipeId1(this.modLoc("ritual/summon_wild_hunt")); return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(Items.WILD_ARMOR_TRIM_SMITHING_TEMPLATE) + .withIcon(Items.WITHER_SKELETON_SKULL) .withLocation(entryMap.get(icon)) .withPages( - spotlight, + intro, ritual ); } - //endregion //region Possession Rituals @@ -5460,23 +2821,25 @@ private BookCategoryModel makeStorageCategory() { storageStabilizer.withParent(BookEntryParentModel.create(storageController.getId())); this.context().category("crafting_rituals"); //re-use existing entries - var craftStabilizerTier1 = this.makeCraftStabilizerTier1Entry(entryMap, '1'); + var bindingRitualsCategory = new BindingRitualsCategory(this); + + var craftStabilizerTier1 = bindingRitualsCategory.makeCraftStabilizerTier1Entry(entryMap, '1'); craftStabilizerTier1.withParent(BookEntryParentModel.create(storageStabilizer.getId())); - var craftStabilizerTier2 = this.makeCraftStabilizerTier2Entry(entryMap, '2'); + var craftStabilizerTier2 = bindingRitualsCategory.makeCraftStabilizerTier2Entry(entryMap, '2'); craftStabilizerTier2.withParent(BookEntryParentModel.create( ResourceLocation.fromNamespaceAndPath( craftStabilizerTier1.getId().getNamespace(), "storage/" + craftStabilizerTier1.getId().getPath() ) )); - var craftStabilizerTier3 = this.makeCraftStabilizerTier3Entry(entryMap, '3'); + var craftStabilizerTier3 = bindingRitualsCategory.makeCraftStabilizerTier3Entry(entryMap, '3'); craftStabilizerTier3.withParent(BookEntryParentModel.create( ResourceLocation.fromNamespaceAndPath( craftStabilizerTier2.getId().getNamespace(), "storage/" + craftStabilizerTier2.getId().getPath() ) )); - var craftStabilizerTier4 = this.makeCraftStabilizerTier4Entry(entryMap, '4'); + var craftStabilizerTier4 = bindingRitualsCategory.makeCraftStabilizerTier4Entry(entryMap, '4'); craftStabilizerTier4.withParent(BookEntryParentModel.create( ResourceLocation.fromNamespaceAndPath( craftStabilizerTier3.getId().getNamespace(), @@ -5484,9 +2847,9 @@ private BookCategoryModel makeStorageCategory() { ) )); - var craftStableWormhole = this.makeCraftStableWormholeEntry(entryMap, 'w'); + var craftStableWormhole = bindingRitualsCategory.makeCraftStableWormholeEntry(entryMap, 'w'); craftStableWormhole.withParent(BookEntryParentModel.create(storageController.getId())); - var craftStorageRemote = this.makeCraftStorageRemoteEntry(entryMap, 'r'); + var craftStorageRemote = bindingRitualsCategory.makeCraftStorageRemoteEntry(entryMap, 'r'); craftStorageRemote.withParent(BookEntryParentModel.create( ResourceLocation.fromNamespaceAndPath( craftStableWormhole.getId().getNamespace(), diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/BindingRitualsCategory.java b/src/main/java/com/klikli_dev/occultism/datagen/book/BindingRitualsCategory.java new file mode 100644 index 000000000..b2a5daa02 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/BindingRitualsCategory.java @@ -0,0 +1,629 @@ +package com.klikli_dev.occultism.datagen.book; + +import com.klikli_dev.modonomicon.api.datagen.CategoryEntryMap; +import com.klikli_dev.modonomicon.api.datagen.CategoryProvider; +import com.klikli_dev.modonomicon.api.datagen.book.BookEntryModel; +import com.klikli_dev.modonomicon.api.datagen.book.BookEntryParentModel; +import com.klikli_dev.modonomicon.api.datagen.book.BookIconModel; +import com.klikli_dev.modonomicon.api.datagen.book.condition.BookTrueConditionModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookCraftingRecipePageModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookSpotlightPageModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookTextPageModel; +import com.klikli_dev.occultism.datagen.OccultismBookProvider; +import com.klikli_dev.occultism.datagen.book.binding_rituals.ApprenticeRitualSatchelEntry; +import com.klikli_dev.occultism.datagen.book.binding_rituals.ArtisanalRitualSatchelEntry; +import com.klikli_dev.occultism.integration.modonomicon.pages.BookRitualRecipePageModel; +import com.klikli_dev.occultism.registry.OccultismBlocks; +import com.klikli_dev.occultism.registry.OccultismItems; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; + +public class BindingRitualsCategory extends CategoryProvider { + public static final String CATEGORY_ID = "crafting_rituals"; + + public BindingRitualsCategory(OccultismBookProvider parent) { + super(parent); + } + + @Override + protected String[] generateEntryMap() { + return new String[]{ + "___________________________", + "_______b_e_x_p_q___________", + "___________________________", + "_______d_h_c__w____________", + "___________________________", + "___9_0_____________________", + "___________________________", + "_______f_z_a__g_ĝ_ğ________", + "___________________________", + "___________n_m_o___________", + "___________________________", + "___________i_j_k_l_________", + "___________________________" + }; + } + + @Override + protected void generateEntries() { + var overview = this.add(this.makeCraftingRitualsOverviewEntry(this.entryMap, '0')); + var returnToRituals = this.add(this.makeReturnToRitualsEntry(this.entryMap, '9')); + returnToRituals.withParent(BookEntryParentModel.create(overview.getId())); + + var craftInfusedPickaxe = this.add(this.makeCraftInfusedPickaxeEntry(this.entryMap, 'd')); + craftInfusedPickaxe.withParent(BookEntryParentModel.create(overview.getId())); + var craftDimensionalMineshaft = this.add(this.makeCraftDimensionalMineshaftEntry(this.entryMap, 'b')); + craftDimensionalMineshaft.withParent(BookEntryParentModel.create(craftInfusedPickaxe.getId())); + var craftFoliotMiner = this.add(this.makeCraftFoliotMinerEntry(this.entryMap, 'e')); + craftFoliotMiner.withParent(BookEntryParentModel.create(craftDimensionalMineshaft.getId())); + var craftDjinniMiner = this.add(this.makeCraftDjinniMinerEntry(this.entryMap, 'x')); + craftDjinniMiner.withParent(BookEntryParentModel.create(craftFoliotMiner.getId())); + var craftAfritMiner = this.add(this.makeCraftAfritMinerEntry(this.entryMap, 'p')); + craftAfritMiner.withParent(BookEntryParentModel.create(craftDjinniMiner.getId())); + var craftMaridMiner = this.add(this.makeCraftMaridMinerEntry(this.entryMap, 'q')); + craftMaridMiner.withParent(BookEntryParentModel.create(craftAfritMiner.getId())); + + var craftStorageSystem = this.add(this.makeCraftStorageSystemEntry(this.entryMap, 'z')); + craftStorageSystem.withParent(BookEntryParentModel.create(overview.getId())); + + var craftDimensionalMatrix = this.add(this.makeCraftDimensionalMatrixEntry(this.entryMap, 'a')); + craftDimensionalMatrix.withParent(BookEntryParentModel.create(craftStorageSystem.getId())); + var craftStorageControllerBase = this.add(this.makeCraftStorageControllerBaseEntry(this.entryMap, 'n')); + craftStorageControllerBase.withParent(BookEntryParentModel.create(craftDimensionalMatrix.getId())); + var craftStabilizerTier1 = this.add(this.makeCraftStabilizerTier1Entry(this.entryMap, 'i')); + craftStabilizerTier1.withParent(BookEntryParentModel.create(craftStorageControllerBase.getId())); + var craftStabilizerTier2 = this.add(this.makeCraftStabilizerTier2Entry(this.entryMap, 'j')); + craftStabilizerTier2.withParent(BookEntryParentModel.create(craftStabilizerTier1.getId())); + var craftStabilizerTier3 = this.add(this.makeCraftStabilizerTier3Entry(this.entryMap, 'k')); + craftStabilizerTier3.withParent(BookEntryParentModel.create(craftStabilizerTier2.getId())); + var craftStabilizerTier4 = this.add(this.makeCraftStabilizerTier4Entry(this.entryMap, 'l')); + craftStabilizerTier4.withParent(BookEntryParentModel.create(craftStabilizerTier3.getId())); + + var craftStableWormhole = this.add(this.makeCraftStableWormholeEntry(this.entryMap, 'm')); + craftStableWormhole.withParent(BookEntryParentModel.create(craftStorageControllerBase.getId())); + var craftStorageRemote = this.add(this.makeCraftStorageRemoteEntry(this.entryMap, 'o')); + craftStorageRemote.withParent(BookEntryParentModel.create(craftStableWormhole.getId())); + + var craftOtherworldGoggles = this.add(this.makeCraftOtherworldGogglesEntry(this.entryMap, 'f')); + craftOtherworldGoggles.withParent(BookEntryParentModel.create(overview.getId())); + + var craftSatchel = this.add(this.makeCraftSatchelEntry(this.entryMap, 'g')); + craftSatchel.withParent(BookEntryParentModel.create(overview.getId())); + + var apprenticeRitualSatchel = this.add(new ApprenticeRitualSatchelEntry(this).generate('ĝ')); + apprenticeRitualSatchel.withParent(craftSatchel); + + var artisanalRitualSatchel = this.add(new ArtisanalRitualSatchelEntry(this).generate('ğ')); + artisanalRitualSatchel.withParent(apprenticeRitualSatchel); + + var craftSoulGem = this.add(this.makeCraftSoulGemEntry(this.entryMap, 'h')); + craftSoulGem.withParent(BookEntryParentModel.create(overview.getId())); + var craftFamiliarRing = this.add(this.makeCraftFamiliarRingEntry(this.entryMap, 'c')); + craftFamiliarRing.withParent(BookEntryParentModel.create(craftSoulGem.getId())); + + var craftWildTrim = this.add(this.makeCraftWildTrimEntry(this.entryMap, 'w')); + craftWildTrim.withParent(BookEntryParentModel.create(overview.getId())); + + //Note: by default entries get an "entry read" condition for their parent entry, but we want to show all of these right away + this.category.getEntries().forEach(entry -> entry.withCondition(BookTrueConditionModel.create())); + } + + @Override + protected String categoryName() { + return "Binding Rituals"; + } + + @Override + protected BookIconModel categoryIcon() { + return BookIconModel.create(this.modLoc("textures/gui/book/infusion.png")); + } + + @Override + public String categoryId() { + return CATEGORY_ID; + } + + private BookEntryModel makeReturnToRitualsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("return_to_rituals"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/robe.png")) + .withCategoryToOpen(this.modLoc("rituals")) + .withEntryBackground(1, 2) + .withLocation(entryMap.get(icon)); + } + + private BookEntryModel makeCraftingRitualsOverviewEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("overview"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/infusion.png")) + .withLocation(entryMap.get(icon)) + .withEntryBackground(0, 1) + .withPages( + intro + ); + } + + private BookEntryModel makeCraftStorageSystemEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_storage_system"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.STORAGE_CONTROLLER.get())) + .withText(this.context().pageText()); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(Items.CHEST) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight + ); + } + + private BookEntryModel makeCraftDimensionalMatrixEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_dimensional_matrix"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.DIMENSIONAL_MATRIX.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_dimensional_matrix")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.DIMENSIONAL_MATRIX.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + private BookEntryModel makeCraftDimensionalMineshaftEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_dimensional_mineshaft"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.DIMENSIONAL_MINESHAFT.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_dimensional_mineshaft")); + + this.context().page("description"); + var description = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismBlocks.DIMENSIONAL_MINESHAFT.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual, + description + ); + } + + private BookEntryModel makeCraftInfusedPickaxeEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_infused_pickaxe"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.INFUSED_PICKAXE.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_infused_pickaxe")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.INFUSED_PICKAXE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + public BookEntryModel makeCraftStorageControllerBaseEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_storage_controller_base"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.STORAGE_CONTROLLER_BASE.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_storage_controller_base")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismBlocks.STORAGE_CONTROLLER_BASE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + public BookEntryModel makeCraftStabilizerTier1Entry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_stabilizer_tier1"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.STORAGE_STABILIZER_TIER1.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_stabilizer_tier1")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismBlocks.STORAGE_STABILIZER_TIER1.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + public BookEntryModel makeCraftStabilizerTier2Entry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_stabilizer_tier2"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.STORAGE_STABILIZER_TIER2.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_stabilizer_tier2")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismBlocks.STORAGE_STABILIZER_TIER2.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + public BookEntryModel makeCraftStabilizerTier3Entry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_stabilizer_tier3"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.STORAGE_STABILIZER_TIER3.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_stabilizer_tier3")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismBlocks.STORAGE_STABILIZER_TIER3.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + public BookEntryModel makeCraftStabilizerTier4Entry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_stabilizer_tier4"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.STORAGE_STABILIZER_TIER4.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_stabilizer_tier4")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismBlocks.STORAGE_STABILIZER_TIER4.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + public BookEntryModel makeCraftStableWormholeEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_stable_wormhole"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.STABLE_WORMHOLE.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_stable_wormhole")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismBlocks.STABLE_WORMHOLE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + public BookEntryModel makeCraftStorageRemoteEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_storage_remote"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.STORAGE_REMOTE.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_storage_remote")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.STORAGE_REMOTE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + private BookEntryModel makeCraftFoliotMinerEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_foliot_miner"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + this.context().page("magic_lamp"); + var lamp = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + this.context().page("magic_lamp_recipe"); + var lampRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/magic_lamp_empty")); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.MINER_FOLIOT_UNSPECIALIZED.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_miner_foliot_unspecialized")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.MINER_FOLIOT_UNSPECIALIZED.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + lamp, + lampRecipe, + spotlight, + ritual + ); + } + + private BookEntryModel makeCraftDjinniMinerEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_djinni_miner"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.MINER_DJINNI_ORES.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_miner_djinni_ores")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.MINER_DJINNI_ORES.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + private BookEntryModel makeCraftAfritMinerEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_afrit_miner"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.MINER_AFRIT_DEEPS.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_miner_afrit_deeps")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.MINER_AFRIT_DEEPS.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + private BookEntryModel makeCraftMaridMinerEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_marid_miner"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.MINER_MARID_MASTER.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_miner_marid_master")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.MINER_MARID_MASTER.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + private BookEntryModel makeCraftSatchelEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_satchel"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.SATCHEL.get())) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_satchel")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.SATCHEL.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } + + private BookEntryModel makeCraftSoulGemEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_soul_gem"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.SOUL_GEM_ITEM.get())) + .withText(this.context().pageText()); + + this.context().page("usage"); + var usage = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_soul_gem")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.SOUL_GEM_ITEM.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + usage, + ritual + ); + } + + private BookEntryModel makeCraftFamiliarRingEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_familiar_ring"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.FAMILIAR_RING.get())) + .withText(this.context().pageText()); + + this.context().page("usage"); + var usage = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_familiar_ring")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.FAMILIAR_RING.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + usage, + ritual + ); + } + + private BookEntryModel makeCraftOtherworldGogglesEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_otherworld_goggles"); + + this.context().page("goggles_spotlight"); + var gogglesSpotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.OTHERWORLD_GOGGLES.get())) + .withText(this.context().pageText()); + + this.context().page("goggles_more"); + var gogglesMore = BookTextPageModel.create() + .withText(this.context().pageText()); + + this.context().page("lenses_spotlight"); + var lensesSpotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.LENSES.get())) + .withText(this.context().pageText()); + + this.context().page("lenses_more"); + var lensesMore = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + this.context().page("lenses_recipe"); + var lensesRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/lenses")); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_infused_lenses")); + + this.context().page("goggles_recipe"); + var gogglesRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/goggles")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(OccultismItems.OTHERWORLD_GOGGLES.get()) + .withLocation(entryMap.get(icon)) + .withPages( + gogglesSpotlight, + gogglesMore, + lensesSpotlight, + lensesMore, + lensesRecipe, + ritual, + gogglesRecipe + ); + } + + private BookEntryModel makeCraftWildTrimEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("craft_wild_trim"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(Items.WILD_ARMOR_TRIM_SMITHING_TEMPLATE)) + .withText(this.context().pageText()); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_wild_trim")); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(Items.WILD_ARMOR_TRIM_SMITHING_TEMPLATE) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + ritual + ); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/FamiliarRitualsCategory.java b/src/main/java/com/klikli_dev/occultism/datagen/book/FamiliarRitualsCategory.java index 341351f0b..3bf622f7b 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/book/FamiliarRitualsCategory.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/FamiliarRitualsCategory.java @@ -9,8 +9,8 @@ import com.klikli_dev.modonomicon.api.datagen.book.page.BookEntityPageModel; import com.klikli_dev.modonomicon.api.datagen.book.page.BookTextPageModel; import com.klikli_dev.occultism.datagen.OccultismBookProvider; -import com.klikli_dev.occultism.datagen.book.familiarrituals.DemonicPartnerEntry; -import com.klikli_dev.occultism.datagen.book.familiarrituals.ResurrectionEntry; +import com.klikli_dev.occultism.datagen.book.familiar_rituals.DemonicPartnerEntry; +import com.klikli_dev.occultism.datagen.book.familiar_rituals.ResurrectionEntry; import com.klikli_dev.occultism.integration.modonomicon.pages.BookRitualRecipePageModel; public class FamiliarRitualsCategory extends CategoryProvider { diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/GettingStartedCategory.java b/src/main/java/com/klikli_dev/occultism/datagen/book/GettingStartedCategory.java new file mode 100644 index 000000000..0c8c9f3cc --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/GettingStartedCategory.java @@ -0,0 +1,2040 @@ +package com.klikli_dev.occultism.datagen.book; + +import com.klikli_dev.modonomicon.api.datagen.CategoryEntryMap; +import com.klikli_dev.modonomicon.api.datagen.CategoryProvider; +import com.klikli_dev.modonomicon.api.datagen.ModonomiconProviderBase; +import com.klikli_dev.modonomicon.api.datagen.book.BookEntryModel; +import com.klikli_dev.modonomicon.api.datagen.book.BookEntryParentModel; +import com.klikli_dev.modonomicon.api.datagen.book.BookIconModel; +import com.klikli_dev.modonomicon.api.datagen.book.condition.BookAndConditionModel; +import com.klikli_dev.modonomicon.api.datagen.book.condition.BookEntryReadConditionModel; +import com.klikli_dev.modonomicon.api.datagen.book.condition.BookModLoadedConditionModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.*; +import com.klikli_dev.occultism.datagen.book.getting_started.RitualSatchelsEntry; +import com.klikli_dev.occultism.integration.modonomicon.pages.BookBindingCraftingRecipePageModel; +import com.klikli_dev.occultism.integration.modonomicon.pages.BookRitualRecipePageModel; +import com.klikli_dev.occultism.integration.modonomicon.pages.BookSpiritFireRecipePageModel; +import com.klikli_dev.occultism.registry.OccultismBlocks; +import com.klikli_dev.occultism.registry.OccultismItems; +import com.klikli_dev.theurgy.registry.ItemRegistry; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; + +public class GettingStartedCategory extends CategoryProvider { + + public static final String COLOR_PURPLE = "ad03fc"; + public static final String DEMONS_DREAM = "Demon's Dream"; + + public static final String CATEGORY_ID = "getting_started"; + + public GettingStartedCategory(ModonomiconProviderBase parent) { + super(parent); + } + + @Override + protected String[] generateEntryMap() { + //B=brush, N=Next Steps, P=iesnium pick + //i=intro, r=divinationRod, ç = chalk, b=bowls, g=goggles, I=infused pick O= tier 2 otherworld materials + // l=lamps, M=miner, D=Dim Mineshaft + //d=demonsDream, h=healing, f=SpiritFire, c=candle, R=ritual, a=advancedChalks, ĝ=ritualsatchels + //e=thirdEye, ạ=books of binding, m=more ritual, s=storage + //C=book of calling, p=grey particles, S=spirits, w=possession, x=familiars, y=summoning, z=crafting + return new String[]{ + "__________________________________", + "__________________________________", + "__________________________________", + "__________________________P___D___", + "__________________________________", + "______ŕ___t___B_______g_I_O_l_M___", + "__________________________________", + "______i___r___ç_b_______s_________", + "__________________________________", + "______d___f_c_____R___a___ĝ_______", + "__________________________________", + "______e_h_____ạ_______m___________", + "__________________________________", + "______________Á_C___p_S___w_x_y_z_" + }; + } + + @Override + protected void generateEntries() { + var introEntry = this.add(this.makeIntroEntry(this.entryMap, 'i')); + + var demonsDreamEntry = this.add(this.makeDemonsDreamEntry(this.entryMap, 'd')); + demonsDreamEntry.withParent(BookEntryParentModel.create(introEntry.getId())); + + var spiritFireEntry = this.add(this.makeSpiritFireEntry(this.entryMap, 'f')); + spiritFireEntry.withParent(BookEntryParentModel.create(demonsDreamEntry.getId())); + + var healingSpiritsEntry = this.add(this.makeHealingSpiritsEntry(this.entryMap, 'h')); + healingSpiritsEntry.withParent(BookEntryParentModel.create(demonsDreamEntry.getId())); + + var thirdEyeEntry = this.add(this.makeThirdEyeEntry(this.entryMap, 'e')); + thirdEyeEntry.withParent(BookEntryParentModel.create(demonsDreamEntry.getId())); + + var divinationRodEntry = this.add(this.makeDivinationRodEntry(this.entryMap, 'r')); + divinationRodEntry.withParent(BookEntryParentModel.create(spiritFireEntry.getId())); + + var theurgyDivinationRodEntry = this.add(this.makeTheurgyDivinationRodsEntry(this.entryMap, 't')); + theurgyDivinationRodEntry + .withParent(BookEntryParentModel.create(divinationRodEntry.getId())) + .withCondition( + BookAndConditionModel.create().withChildren( + BookEntryReadConditionModel.create() + .withEntry(divinationRodEntry.getId()), + BookModLoadedConditionModel.create() + .withModId("theurgy") + ) + ) + .hideWhileLocked(true); + + var candleEntry = this.add(this.makeCandleEntry(this.entryMap, 'c')); + candleEntry.withParent(BookEntryParentModel.create(spiritFireEntry.getId())); + + var ritualPrepChalkEntry = this.add(this.makeRitualPrepChalkEntry(this.entryMap, 'ç')); + ritualPrepChalkEntry.withParent(BookEntryParentModel.create(candleEntry.getId())); + + var brushEntry = this.add(this.makeBrushEntry(this.entryMap, 'B')); + brushEntry.withParent(BookEntryParentModel.create(ritualPrepChalkEntry.getId())); + + var ritualPrepBowlEntry = this.add(this.makeRitualPrepBowlEntry(this.entryMap, 'b')); + ritualPrepBowlEntry.withParent(BookEntryParentModel.create(ritualPrepChalkEntry.getId())); + + var booksOfBinding = this.add(this.makeBooksOfBindingEntry(this.entryMap, 'ạ')); + booksOfBinding.withParent(BookEntryParentModel.create(candleEntry.getId())); + + var booksOfBindingAutomation = this.add(this.makeBooksOfBindingAutomationEntry(this.entryMap, 'Á')); + booksOfBindingAutomation.withParent(BookEntryParentModel.create(booksOfBinding.getId())); + + var booksOfCalling = this.add(this.makeBooksOfCallingEntry(this.entryMap, 'C')); + booksOfCalling.withParent(BookEntryParentModel.create(booksOfBinding.getId())); + + var ritualEntry = this.add(this.makeRitualEntry(this.entryMap, 'R')); + ritualEntry + .withParent(BookEntryParentModel.create(ritualPrepBowlEntry.getId())) + .withParent(BookEntryParentModel.create(booksOfBinding.getId())); + + var advancedChalksEntry = this.add(this.makeChalksEntry(this.entryMap, 'a')); + advancedChalksEntry.withParent(BookEntryParentModel.create(ritualEntry.getId())); + + var ritualSatchelsEntry = this.add(new RitualSatchelsEntry(this).generate('ĝ')); + ritualSatchelsEntry.withParent(BookEntryParentModel.create(advancedChalksEntry.getId())); + + var moreRitualsEntry = this.add(this.makeMoreRitualsEntry(this.entryMap, 'm')); + moreRitualsEntry.withParent(BookEntryParentModel.create(advancedChalksEntry.getId())); + + var greyParticlesEntry = this.add(this.makeGreyParticlesEntry(this.entryMap, 'p')); + greyParticlesEntry.withParent(BookEntryParentModel.create(ritualEntry.getId())); + + var spiritsSubcategory = this.add(this.makeSpiritsSubcategoryEntry(this.entryMap, 'S')); + spiritsSubcategory.withParent(BookEntryParentModel.create(greyParticlesEntry.getId())); + + var otherworldGoggles = this.add(this.makeOtherworldGogglesEntry(this.entryMap, 'g')); + otherworldGoggles.withParent(BookEntryParentModel.create(advancedChalksEntry.getId())); + + var infusedPickaxe = this.add(this.makeInfusedPickaxeEntry(this.entryMap, 'I')); + infusedPickaxe.withParent(BookEntryParentModel.create(otherworldGoggles.getId())); + + var iesnium = this.add(this.makeIesniumEntry(this.entryMap, 'O')); + iesnium.withParent(BookEntryParentModel.create(infusedPickaxe.getId())); + + var iesniumPickaxe = this.add(this.makeIesniumPickaxeEntry(this.entryMap, 'P')); + iesniumPickaxe.withParent(BookEntryParentModel.create(iesnium.getId())); + + var magicLampsEntry = this.add(this.makeMagicLampsEntry(this.entryMap, 'l')); + magicLampsEntry.withParent(BookEntryParentModel.create(iesnium.getId())); + + var spiritMinersEntry = this.add(this.makeSpiritMinersEntry(this.entryMap, 'M')); + spiritMinersEntry.withParent(BookEntryParentModel.create(magicLampsEntry.getId())); + + var mineshaftEntry = this.add(this.makeMineshaftEntry(this.entryMap, 'D')); + mineshaftEntry.withParent(BookEntryParentModel.create(spiritMinersEntry.getId())); + + var storageEntry = this.add(this.makeStorageEntry(this.entryMap, 's')); + storageEntry.withParent(BookEntryParentModel.create(advancedChalksEntry.getId())); + + var possessionRitualsEntry = this.add(this.makePossessionRitualsEntry(this.entryMap, 'w')); + possessionRitualsEntry.withParent(BookEntryParentModel.create(moreRitualsEntry.getId())); + + var familiarRitualsEntry = this.add(this.makeFamiliarRitualsEntry(this.entryMap, 'x')); + familiarRitualsEntry.withParent(BookEntryParentModel.create(moreRitualsEntry.getId())); + + var summoningRitualsEntry = this.add(this.makeSummoningRitualsEntry(this.entryMap, 'y')); + summoningRitualsEntry.withParent(BookEntryParentModel.create(moreRitualsEntry.getId())); + + var craftingRitualsEntry = this.add(this.makeCraftingRitualsEntry(this.entryMap, 'z')); + craftingRitualsEntry.withParent(BookEntryParentModel.create(moreRitualsEntry.getId())); + } + + @Override + protected String categoryName() { + return "Getting Started"; + } + + @Override + protected BookIconModel categoryIcon() { + return BookIconModel.create(OccultismItems.DICTIONARY_OF_SPIRITS_ICON); + } + + @Override + public String categoryId() { + return CATEGORY_ID; + } + + private BookEntryModel makeIntroEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("intro"); + this.lang().add(this.context().entryName(), "About"); + this.lang().add(this.context().entryDescription(), "About using the Dictionary of Spirits"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "About"); + this.lang().add(this.context().pageText(), + """ + This book aims to introduce the novice reader to the most common summoning rituals and equip them with a list of spirit names to summon. + The authors advise caution in the summoning of the listed entities and does not take responsibility for any harm caused. + """); + + this.context().page("help"); + var help = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Getting Help"); + this.lang().add(this.context().pageText(), + """ + If you run into any trouble while playing Occultism, please join our Discord server and ask for help. + \\ + \\ + [Join us at https://invite.gg/klikli](https://invite.gg/klikli) + """); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.DICTIONARY_OF_SPIRITS_ICON.get()) + .withLocation(entryMap.get(icon)) + .withEntryBackground(0, 1) + .withPages( + intro, + help + ); + } + + private BookEntryModel makeDemonsDreamEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("demons_dream"); + this.lang().add(this.context().entryName(), "Lifting the Veil"); + this.lang().add(this.context().entryDescription(), "Learn about the Otherworld and the Third Eye."); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "The Otherworld"); + this.lang().add(this.context().pageText(), + """ + Hidden from mere human eyes exists another plane of existence, another *dimension* if you will, the [#](%1$s)Otherworld[#](). + This world is populated with entities often referred to as [#](%1$s)Demons[#](). + """.formatted(COLOR_PURPLE)); + + this.context().page("intro2"); + var intro2 = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + These Demons possess a wide variety of powers and useful skills, and for centuries magicians have sought to summon them for their own gain. + The first step on the journey to successfully summoning such an Entity is to learn how to interact with the Otherworld. + """); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.DATURA.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + %1$s is a herb that gives humans the [#](%2$s)Third Eye[#](), + allowing them to see where the [#](%2$s)Otherworld[#]() intersects with our own. + Seeds can be found **by breaking grass**. + **Consuming** the grown fruit activates the ability *with a certain chance*. + """.formatted(DEMONS_DREAM, COLOR_PURPLE)); + + this.context().page("harvest_effect"); + var harvestEffect = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + An additional side effect of %1$s, is **the ability to interact with [#](%2$s)Otherworld[#]() materials**. + This is unique to %1$s, other ways to obtain [#](%2$s)Third Eye[#]() do not yield this ability. + While under the effect of %1$s you are able to **harvest** Otherstone as well as Otherworld trees. + """.formatted(DEMONS_DREAM, COLOR_PURPLE)); + + this.context().page("datura_screenshot"); + var datureScreenshot = BookImagePageModel.create() + .withImages(this.modLoc("textures/gui/book/datura_effect.png")); + //no text + + this.context().page("note_on_spirit_fire"); + var spiritFire = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + **Hint**: The otherworld materials you obtain by harvesting under the effects of[#](%2$s)Third Eye[#]() **can be obtained more easily using [](item://occultism:spirit_fire)**. Proceed with the next entry in this book to learn more about spirit fire. + """.formatted(DEMONS_DREAM, COLOR_PURPLE)); + + this.context().page("spotlight2"); + var spotlight2 = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.DEMONS_DREAM_ESSENCE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Multiple Demon's Dream fruits or seeds can be compressed into an essence that is much more potent. It *guarantees* the [#](%2$s)Third Eye[#]() and provides it for a longer amount of time, but comes with a lot of (positive and negative) side effects. + """.formatted(DEMONS_DREAM, COLOR_PURPLE) + ); + + this.context().page("recipe_essence"); + var recipeEssence = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/demons_dream_essence_from_fruit_or_seed")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Fruit and seeds can be mixed freely to create the essence. + """ + ); + + this.context().page("spotlight3"); + var spotlight3 = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.DEMONS_DREAM_ESSENCE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + The essence can be purified in spirit fire (more on that later!) to obtain a version free from all negative side effects, while retaining the positive. + """.formatted(DEMONS_DREAM, COLOR_PURPLE) + ); + + this.context().page("recipe_essence_pure"); + var recipeEssencePure = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/otherworld_essence")); + //no text + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.DATURA.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + intro2, + spotlight, + harvestEffect, + datureScreenshot, + spiritFire, + spotlight2, + recipeEssence, + spotlight3, + recipeEssencePure + ); + } + + private BookEntryModel makeSpiritFireEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("spirit_fire"); + this.lang().add(this.context().entryName(), "It burns!"); + this.lang().add(this.context().entryDescription(), "Or does it?"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.SPIRIT_FIRE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + [#](%1$s)Spiritfire[#]() is a special type of fire that exists mostly in [#](%1$s)The Other Place[#]() + and does not harm living beings. Its special properties allow to use it to purify and convert + certain materials by burning them, without consuming them. + """.formatted(COLOR_PURPLE)); + + this.context().page("spirit_fire_screenshot"); + var spiritFireScreenshot = BookImagePageModel.create() + .withImages(this.modLoc("textures/gui/book/spiritfire_instructions.png")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Throw [](item://occultism:datura) to the ground and light it on fire with [](item://minecraft:flint_and_steel). + """); + + this.context().page("main_uses"); + var mainUses = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + The main uses of [](item://occultism:spirit_fire) are to convert [](item://minecraft:diamond) into [](item://occultism:spirit_attuned_gem), + to get basic ingredients such as [](item://occultism:otherstone) and [Otherworld Saplings](item://occultism:otherworld_sapling_natural), + and to purify impure chalks. + """); + + this.context().page("otherstone_recipe"); + var otherstoneRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/otherstone")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + An easier way to obtain [](item://occultism:otherstone) than via divination. + """); + + this.context().page("otherworld_sapling_natural_recipe"); + var otherworldSaplingNaturalRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/otherworld_sapling_natural")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + An easier way to obtain [Otherworld Saplings](item://occultism:otherworld_sapling_natural) than via divination. + """); + + this.context().page("otherworld_ashes_recipe"); + var otherworldAshesRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/otherworld_ashes")); + //no text + + this.context().page("gem_recipe"); + var gemRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/spirit_attuned_gem")); + //no text + + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.SPIRIT_FIRE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + spiritFireScreenshot, + mainUses, + otherstoneRecipe, + otherworldSaplingNaturalRecipe, + otherworldAshesRecipe, + gemRecipe + ); + } + + private BookEntryModel makeHealingSpiritsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("healing_spirits"); + this.lang().add(this.context().entryName(), "Healing Spirits"); + this.lang().add(this.context().entryDescription(), "Fix up your spirit!"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.DATURA.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Right-click a spirit with [](item://occultism:datura) to heal it. + \\ + \\ + This will work on **Familiars**, **Summoned Spirits** and also **Possessed Mobs**. + """); + + this.context().page("spotlight2"); + var spotlight2 = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.DEMONS_DREAM_ESSENCE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + When compressing Demon's Dream fruits or seeds into essence, a much stronger instant healing effect can be achieved. This comes at the cost of efficiency: Feeding 9 fruits to a spirit in succession will heal it more than feeding it 9 fruits worth of essence. + """); + + this.context().page("spotlight3"); + var spotlight3 = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.OTHERWORLD_ESSENCE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Purifying the Demon's Dream Essence will yield a version that heals even more, negating the efficiency loss. + """); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(Items.SPLASH_POTION) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + spotlight2, + spotlight3 + ); + } + + private BookEntryModel makeThirdEyeEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("third_eye"); + this.lang().add(this.context().entryName(), "The Third Eye"); + this.lang().add(this.context().entryDescription(), "Do you see now?"); + + this.context().page("about"); + var about = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Third Eye"); + this.lang().add(this.context().pageText(), + """ + The ability to see beyond the physical world is referred to as [#](%1$s)Third Eye[#](). + Humans do not possess such an ability to see [#](%1$s)beyond the veil[#](), + however with certain substances and contraptions the knowledgeable summoner can work around this limitation. + """.formatted(COLOR_PURPLE)); + + this.context().page("how_to_obtain"); + var howToObtain = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + The most comfortable, and most *expensive*, way to obtain this ability, is to wear spectacles + infused with spirits, that *lend* their sight to the wearer. + A slightly more nauseating, but **very affordable** alternative is the consumption of certain herbs, + [%1$s](entry://occultism:dictionary_of_spirits/getting_started/demons_dream) most prominent among them. + """.formatted(DEMONS_DREAM)); + + this.context().page("otherworld_goggles"); + var otherworldGoggles = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.OTHERWORLD_GOGGLES.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + [These goggles](entry://occultism:dictionary_of_spirits/crafting_rituals/craft_otherworld_goggles) allow to see even more hidden Otherworld blocks, + however they do not allow harvesting those materials. + Low-tier materials can be harvested by consuming [%1$s](entry://occultism:dictionary_of_spirits/getting_started/demons_dream), + but more valuable materials require special tools. + """.formatted(DEMONS_DREAM)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(this.modLoc("textures/mob_effect/third_eye.png")) + .withLocation(entryMap.get(icon)) + .withPages(about, howToObtain, otherworldGoggles); + } + + private BookEntryModel makeDivinationRodEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("divination_rod"); + this.lang().add(this.context().entryName(), "Divination Rod"); + this.lang().add(this.context().entryDescription(), "Obtaining otherworld materials"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Divination"); + this.lang().add(this.context().pageText(), + """ + To make it easier to get started, the materials obtained by divination now also have crafting recipes. + **If you want the full experience, skip the following recipe page and move on to the + [divination instructions](entry://occultism:dictionary_of_spirits/getting_started/divination_rod@divination_instructions).** + """); + + this.context().page("otherstone_recipe"); + var otherstoneRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/otherstone")); + //no text + + this.context().page("otherworld_sapling_natural_recipe"); + var otherworldSaplingNaturalRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/otherworld_sapling_natural")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + **Beware**: the tree growing from the sapling will look like a normal oak tree. + You need to activate the [Third Eye](entry://occultism:dictionary_of_spirits/getting_started/demons_dream) + to harvest the Otherworld Logs and Leaves. + """); + + this.context().page("divination_rod"); + var divinationRod = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.DIVINATION_ROD.get())) + .withText(this.context().pageText()) + .withAnchor("divination_instructions"); + this.lang().add(this.context().pageText(), + """ + Otherworld materials play an important role in interacting with spirits. + As they are rare and not visible to the naked eye, finding them requires special tools. + The divination rod allows to find Otherworld materials based on their similarities to materials common to our world. + """); + + this.context().page("spirit_attuned_gem_recipe"); + var spiritAttunedGemRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/spirit_attuned_gem")); + + this.context().page("divination_rod_recipe"); + var divinationRodRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/divination_rod")); + + this.context().page("about_divination_rod"); + var aboutDivinationRod = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + The divination rod uses a spirit attuned gem attached to a wooden rod. + The gem resonates with the chosen material, and this movement is amplified by the wooden rod, + allowing to detect nearby Otherworld materials. \s + \s + \s + The rod works by detecting resonance between real world and Otherworld materials. + Attuned the rod to a real world material, and it will find the corresponding Otherworld block. + """); + + this.context().page("how_to_use"); + var howToUse = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Use of the Rod"); + this.lang().add(this.context().pageText(), + """ + [#](%1$s)Shift-right-click[#]() a block to attune the rod to the corresponding Otherworld block. + - [](item://minecraft:andesite): [](item://occultism:otherstone) + - [](item://minecraft:oak_wood): [](item://occultism:otherworld_log) + - [](item://minecraft:oak_leaves): [](item://occultism:otherworld_leaves) + - [](item://minecraft:netherrack): [](item://occultism:iesnium_ore) + + Then [#](%1$s)right-click[#]() and hold until the rod animation finishes.""".formatted(COLOR_PURPLE)); + + this.context().page("how_to_use2"); + var howToUse2 = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + After the animation finishes, the closest **found block will be highlighted + with white lines and can be seen through other blocks**. + Additionally you can watch the crystals for hints: a white crystal indicates no target blocks found, + a fully purple block means the found block is nearby. Mixes between white and purple show + that the target is rather far away."""); + + this.context().page("how_to_use3"); + var howToUse3 = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + [#](%1$s)Right-clicking[#]() without holding after a successful search will show the last found target block again. + \\ + \\ + If the mod *"Theurgy"* is installed the rod will not highlight the target block, but instead send a particle effect in the direction of the target block. + """.formatted(COLOR_PURPLE)); + + this.context().page("divination_rod_screenshots"); + var divinationRodScreenshots = BookImagePageModel.create() + .withImages( + this.modLoc("textures/gui/book/rod_far.png"), + this.modLoc("textures/gui/book/rod_mid.png"), + this.modLoc("textures/gui/book/rod_near.png") + ) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + White means nothing was found. + The more purple you see, the closer you are. + """); + + this.context().page("troubleshooting"); + var troubleshooting = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Troubleshooting"); + this.lang().add(this.context().pageText(), + """ + If the rod does not create highlighted blocks for you, you can try to: + - install theurgy, then a particle effect will be used instead + - Open occultism-client.toml in your instance's /config folder and set useAlternativeDivinationRodRenderer = true + """); + + + this.context().page("otherworld_groves"); + var otherworldGroves = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Otherworld Groves"); + this.lang().add(this.context().pageText(), + """ + Otherworld Groves are lush, overgrown caves, with [#](%1$s)Otherworld Trees[#](), + and walls of [](item://occultism:otherstone), and represent the fastest way to get everything one + needs to get set up as a summoner. + To find them, attune your divination rod to Otherworld leaves + or logs, as unlike Otherstone, they only spawn in these groves. + """.formatted(COLOR_PURPLE)); + + this.context().page("otherworld_groves_2"); + var otherworldGroves2 = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + **Hint:** In the Overworld, look **down**. + """); + + this.context().page("otherworld_trees"); + var otherworldTrees = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Otherworld Trees"); + this.lang().add(this.context().pageText(), + """ + Otherworld trees grow naturally in Otherworld Groves. To the naked eye they appear as oak trees, + but to the Third Eye they reveal their true nature. \s + **Important:** Otherworld Saplings can only be obtained by breaking the leaves manually, naturally only oak saplings drop. + """); + + this.context().page("otherworld_trees_2"); + var otherworldTrees2 = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Trees grown from Stable Otherworld Saplings as obtained from spirit traders do not have that limitation. + """); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.DIVINATION_ROD.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + otherstoneRecipe, + otherworldSaplingNaturalRecipe, + divinationRod, + spiritAttunedGemRecipe, + divinationRodRecipe, + aboutDivinationRod, + howToUse, + howToUse2, + howToUse3, + divinationRodScreenshots, + troubleshooting, + otherworldGroves, + otherworldGroves2, + otherworldTrees, + otherworldTrees2); + } + + + private BookEntryModel makeTheurgyDivinationRodsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("theurgy_divination_rod"); + + this.lang().add(this.context().entryName(), "More Divination Rods"); + this.lang().add(this.context().entryDescription(), "Finding other ores and resources."); + + this.context().page("intro"); + var intro = BookSpotlightPageModel.create() + .withItem(Ingredient.of(ItemRegistry.DIVINATION_ROD_T1.get())) + .withText(this.context().pageText()); + + this.lang().add(this.context().pageText(), + """ + While the [](item://occultism:divination_rod) is a great tool for finding [#](%1$s)Otherworld Materials[#](), it would be useful to have a way to find *all other* ores and resources as well. + \\ + \\ + This is where the Theurgy Divination Rod comes in. + """.formatted(COLOR_PURPLE)); + + this.context().page("recipe_rod"); + var recipeRod = BookCraftingRecipePageModel.create() + .withRecipeId1("theurgy:crafting/shaped/divination_rod_t1"); + + this.context().page("more_info"); + var moreInfo = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + + this.lang().add(this.context().pageTitle(), "More Information"); + this.lang().add(this.context().pageText(), + """ + To find out more about the Theurgy Divination Rod, check out *"The Hermetica"*, the Guidebook for Theurgy. + [This Entry](entry://theurgy:the_hermetica/getting_started/about_divination_rods) has more information about the Theurgy Divination Rod. + """); + + this.context().page("recipe_hermetica"); + var recipeHermetica = BookCraftingRecipePageModel.create() + .withRecipeId1("theurgy:crafting/shapeless/the_hermetica"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(ItemRegistry.DIVINATION_ROD_T1.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + recipeRod, + moreInfo, + recipeHermetica + ); + } + + private BookEntryModel makeCandleEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("candle"); + this.lang().add(this.context().entryName(), "Candles"); + this.lang().add(this.context().entryDescription(), "Let there be light!"); + + this.context().page("intro"); + var intro = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.LARGE_CANDLE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Candles provide stability to rituals and are an important part of almost all pentacles. + **Large Candles also act like bookshelves for enchantment purposes.** + \\ + \\ + Candles from Minecraft and other Mods may be used in place of Occultism candles. + """); + + this.context().page("tallow"); + var tallow = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.TALLOW.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Key ingredient for large candles. Kill large animals like pigs, cows or sheep with a [](item://occultism:butcher_knife) + to harvest [](item://occultism:tallow). + """); + + this.context().page("cleaver_recipe"); + var cleaverRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/butcher_knife")); + //no text + + this.context().page("candle_recipe"); + var candleRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/large_candle")); + //no text + + this.context().page("color_candle"); + var colorCandle = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + You can use a dye and the [](item://occultism:large_candle) to mix then in shapeless craft process to get a colored large candle. + \\ + Available in all the 16 minecraft dyes. + """); + + this.context().page("lit_candle"); + var litCandle = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Just like the candles from Minecraft, [](item://occultism:large_candle) and colored versions can be lit, turning in a great light source. + \\ + In addiction, you can use a [](item://minecraft:torch), [](item://minecraft:soul_torch), [](item://minecraft:redstone_torch) or [](item://occultism:spirit_torch) to change the type of fire. + \\ + Also can be waterlogged. + """); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismBlocks.LARGE_CANDLE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + tallow, + cleaverRecipe, + candleRecipe, + colorCandle, + litCandle + ); + } + + private BookEntryModel makeRitualPrepChalkEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("ritual_prep_chalk"); + this.lang().add(this.context().entryName(), "Ritual Preparations: Chalks"); + this.lang().add(this.context().entryDescription(), "Signs to find them, Signs to bring them all, and in the darkness bind them."); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Ritual Preparations: Chalks"); + this.lang().add(this.context().pageText(), + """ + To summon spirits from the [#](%1$s)Other Place[#]() in *relative* safety, + you need to draw a fitting pentacle using chalk to contain their powers. + """.formatted(COLOR_PURPLE)); + + this.context().page("white_chalk"); + var whiteChalkSpotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.CHALK_WHITE.get())) + .withText(this.context().pageText()) + .withAnchor("white_chalk"); + this.lang().add(this.context().pageText(), + """ + White chalk is used to draw the most basic pentacles, such as for our first ritual. + \\ + \\ + More powerful summonings require appropriate more advanced chalk, see [Chalks](entry://occultism:dictionary_of_spirits/getting_started/chalks) for more information. + """); + + this.context().page("burnt_otherstone_recipe"); + var burntOtherstoneRecipe = BookSmeltingRecipePageModel.create() + .withRecipeId1(this.modLoc("smelting/burnt_otherstone")); + //no text + + this.context().page("otherworld_ashes_recipe"); + var otherworldAshesRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/otherworld_ashes")); + //no text + this.context().page("impure_white_chalk_recipe"); + var impureWhiteChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_white_impure")); + //no text + + this.context().page("white_chalk_recipe"); + var whiteChalkRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/chalk_white")); + //no text + + this.context().page("usage"); + var usage = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Usage"); + this.lang().add(this.context().pageText(), + """ + Right-click on a block with the chalk to draw a single glyph. For decorative purposes you can repeatedly click a block to cycle through glyphs. The shown glyph does not matter for the ritual, only the color. + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.CHALK_WHITE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + whiteChalkSpotlight, + burntOtherstoneRecipe, + otherworldAshesRecipe, + impureWhiteChalkRecipe, + whiteChalkRecipe, + usage + ); + } + + private BookEntryModel makeRitualPrepBowlEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("ritual_prep_bowl"); + this.lang().add(this.context().entryName(), "Ritual Preparations: Sacrificial Bowls"); + this.lang().add(this.context().entryDescription(), "There is no power without sacrifice."); + + this.context().page("sacrificial_bowl"); + var sacrificialBowlSpotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.SACRIFICIAL_BOWL.get())) + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Ritual Preparations: Sacrificial Bowls"); + this.lang().add(this.context().pageText(), + """ + These bowls are used to place the items we will sacrifice as part of a ritual and you will need a handful of them. + Note: Their exact placement in the ritual does not matter - just keep them within 8 blocks horizontally of the pentacle center! + """); + + this.context().page("sacrificial_bowl_recipe"); + var sacrificialBowlRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/sacrificial_bowl")); + //no text + + + this.context().page("golden_sacrificial_bowl"); + var goldenSacrificialBowlSpotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.GOLDEN_SACRIFICIAL_BOWL.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Once everything has been set up and you are ready to start, this special sacrificial bowl is used to activate the ritual by [#](%1$s)right-clicking[#]() it with the activation item, + usually a [Book of Binding](entry://getting_started/books_of_binding). + """.formatted(COLOR_PURPLE)); + + this.context().page("golden_sacrificial_bowl_recipe"); + var goldenSacrificialBowlRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/golden_sacrificial_bowl")); + //no text + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismBlocks.GOLDEN_SACRIFICIAL_BOWL.get()) + .withLocation(entryMap.get(icon)) + .withPages( + sacrificialBowlSpotlight, + sacrificialBowlRecipe, + goldenSacrificialBowlSpotlight, + goldenSacrificialBowlRecipe + ); + } + + private BookEntryModel makeBooksOfBindingEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("books_of_binding"); + this.lang().add(this.context().entryName(), "Books of Binding"); + this.lang().add(this.context().entryDescription(), "Or how to identify your spirit"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Books of Binding"); + this.lang().add(this.context().pageText(), + """ + To call forth a spirit, a [#](%1$s)Book of Binding[#]() must be used in the ritual. + There is a type of book corresponding to each type (or tier) of spirit. + To identify a spirit to summon, it's name must be written in the [#](%1$s)Book of Binding[#](), resulting in a [#](%1$s)Bound Book of Binding[#]() that can be used in the ritual. + """.formatted(COLOR_PURPLE)); + + this.context().page("intro2"); + var intro2 = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + **Note:** *The spirit names are eye candy only*, that means they are not relevant for the recipe. As long as you have the right spirit type in your book of binding it can be used. + """.formatted(COLOR_PURPLE)); + + this.context().page("purified_ink_recipe"); + var purifiedInkRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/purified_ink")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + In order to craft [#](%1$s)Books of Binding[#]() to summon spirits, you need purified ink. Simply drop any black dye into [](item://occultism:spirit_fire) to purify it. + """.formatted(COLOR_PURPLE)); + + this.context().page("awakened_feather_recipe"); + var awakenedFeatherRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/awakened_feather")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + In order to craft [#](%1$s)Books of Binding[#]() to summon spirits, you also need awakened feather. Simply drop any feather into [](item://occultism:spirit_fire) to awakened it. + """.formatted(COLOR_PURPLE)); + + this.context().page("taboo_book_recipe"); + var tabooBookRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/taboo_book")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Lastly you need taboo book to craft [#](%1$s)Books of Binding[#]() to summon spirits. Simply drop a book into [](item://occultism:spirit_fire) to get it. + """.formatted(COLOR_PURPLE)); + + this.context().page("book_of_binding_foliot_recipe"); + var bookOfBindingFoliotRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/book_of_binding_foliot")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Craft a book of binding that will be used to call forth a [#](%1$s)Foliot[#]() spirit. + """.formatted(COLOR_PURPLE)); + + this.context().page("book_of_binding_bound_foliot_recipe"); + var bookOfBindingBoundFoliotRecipe = BookBindingCraftingRecipePageModel.create() + .withRecipeId1() + .withUnboundBook(OccultismItems.BOOK_OF_BINDING_FOLIOT.toStack()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Add the name of the spirit to summon to your book of binding by crafting it with the Dictionary of Spirits. The Dictionary will not be used up. + """); + + this.context().page("book_of_binding_djinni_recipe"); + var bookOfBindingDjinniRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/book_of_binding_djinni")); + + this.context().page("book_of_binding_bound_djinni_recipe"); + var bookOfBoundBindingDjinniRecipe = BookBindingCraftingRecipePageModel.create() + .withRecipeId1() + .withUnboundBook(OccultismItems.BOOK_OF_BINDING_DJINNI.toStack()); + //no text + + this.context().page("book_of_binding_afrit_recipe"); + var bookOfBindingAfritRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/book_of_binding_afrit")); + //no text + + this.context().page("book_of_binding_bound_afrit_recipe"); + var bookOfBoundBindingAfritRecipe = BookBindingCraftingRecipePageModel.create() + .withRecipeId1() + .withUnboundBook(OccultismItems.BOOK_OF_BINDING_AFRIT.toStack()); + //no text + + this.context().page("book_of_binding_marid_recipe"); + var bookOfBindingMaridRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/book_of_binding_marid")); + //no text + + this.context().page("book_of_binding_bound_marid_recipe"); + var bookOfBoundBindingMaridRecipe = BookBindingCraftingRecipePageModel.create() + .withRecipeId1() + .withUnboundBook(OccultismItems.BOOK_OF_BINDING_MARID.toStack()); + //no text + + this.context().page("book_of_binding_empty"); + var alternativeBooks = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/book_of_binding_empty")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Alternatively, you can directly use the Binding Book: Empty instead of the previous three items. There are two ways to obtain this book. Place this book in the center of dyes to get specific book of binding. + """.formatted(COLOR_PURPLE)); + + this.context().page("book_of_binding_empty_recipe"); + var bookOfBindingEmptyRecipe = BookCraftingRecipePageModel.create() + .withRecipeId2(this.modLoc("crafting/book_of_binding_empty")); + //no text + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.BOOK_OF_BINDING_BOUND_FOLIOT.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + intro2, + purifiedInkRecipe, + awakenedFeatherRecipe, + tabooBookRecipe, + bookOfBindingFoliotRecipe, + bookOfBindingBoundFoliotRecipe, + bookOfBindingDjinniRecipe, + bookOfBoundBindingDjinniRecipe, + bookOfBindingAfritRecipe, + bookOfBoundBindingAfritRecipe, + bookOfBindingMaridRecipe, + bookOfBoundBindingMaridRecipe, + alternativeBooks, + bookOfBindingEmptyRecipe + ); + } + + private BookEntryModel makeBooksOfBindingAutomationEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("books_of_binding_automation"); + this.lang().add(this.context().entryName(), "Books of Binding in Automation"); + this.lang().add(this.context().entryDescription(), "Tips for using books of binding in Crafting Automation such as AE2 or RS"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "The Problem"); + this.lang().add(this.context().pageText(), + """ + Bound Books of Binding are generated with a random spirit name. This tricks many automated crafting processes into no longer recognizing the item as the requested crafting result, because it does not expect NBT/Data Components on the item. + \\ + \\ + This leads to stuck crafting processes. + """ + ); + + this.context().page("solution"); + var solution = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "The Solution"); + this.lang().add(this.context().pageText(), + """ + 1. Put a dictionary of spirits into an anvil and give it a name. This will be the name of all spirits summoned in the future. + 2. Use this dictionary to configure crafting patterns (if your automation mod requires it). + 3. Use this dictionary to craft the Bound Books of Binding in the automation system. As usual, the dictionary will not be used up. + 4. All crafted books will now have the same name and will be recognized by your automation system. + """ + ); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(Items.CRAFTER) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + solution + ); + } + + private BookEntryModel makeBooksOfCallingEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("books_of_calling"); + this.lang().add(this.context().entryName(), "Books of Calling"); + this.lang().add(this.context().entryDescription(), "Telling your spirits what to do"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Books of Calling"); + this.lang().add(this.context().pageText(), + """ + Books of Calling allow to control a summoned spirit, and to store it to prevent essence decay or move it more easily. + \\ + \\ + Only spirits that require precise instructions - such as a work area or drop-off storage - come with a book of calling. + """); + + this.context().page("usage"); + var usage = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Usage"); + this.lang().add(this.context().pageText(), + """ + - [#](%1$s)Right-click[#]() air to open the configuration screen + - [#](%1$s)Shift-right-click[#]() a block to apply the action selected in the configuration screen + - [#](%1$s)Shift-right-click[#]() a spirit to capture it (must be of the same type) + - [#](%1$s)Right-click[#]() with a book with a captured spirit to release it + """.formatted(COLOR_PURPLE)); + + this.context().page("obtaining"); + var obtaining = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "How to obtain Books of Calling"); + this.lang().add(this.context().pageText(), + """ + If a summoned spirit supports the use of a Book of Calling, the summoning ritual will automatically spawn a book in the world alongside the spirit. + \\ + \\ + If you **lose the book**, there are also crafting recipes that just provide the book (without summoning a spirit). + """.formatted(COLOR_PURPLE)); + + this.context().page("obtaining2"); + var obtaining2 = BookTextPageModel.create() + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + The recipes can be found in this book or via JEI. + \\ + \\ + [#](%1$s)Shift-right-click[#]() the spirit with the crafted book to assign it. + """.formatted(COLOR_PURPLE)); + + this.context().page("storage"); + var storage = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Storing Spirits"); + this.lang().add(this.context().pageText(), + """ + To store spirits that do not have a fitting book of calling, you can use a [Soul Gem](entry://crafting_rituals/craft_soul_gem). + Soul gems are much more versatile and allow to store almost all types of entities even animals and monsters, but not players or bosses. + """); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.BOOK_OF_CALLING_DJINNI_MANAGE_MACHINE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + usage, + obtaining, + obtaining2, + storage + ); + } + + private BookEntryModel makeRitualEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("first_ritual"); + this.lang().add(this.context().entryName(), "First Ritual"); + this.lang().add(this.context().entryDescription(), "We're actually getting started now!"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "The Ritual (tm)"); + this.lang().add(this.context().pageText(), + """ + These pages will walk the gentle reader through the process of the [first ritual](entry://summoning_rituals/summon_crusher_t1) step by step. + \\ + We **start** by placing the [](item://occultism:golden_sacrificial_bowl) and drawing the appropriate pentacle, [Aviar's Circle](entry://pentacles/summon_foliot) as seen on the left around it. + """.formatted(COLOR_PURPLE)); + + this.context().page("multiblock"); + var multiblock = BookMultiblockPageModel.create() + .withMultiblockId(this.modLoc("summon_foliot")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Only the color and location of the chalk marks is relevant, not the glyph/sign. + """.formatted(COLOR_PURPLE)); + + this.context().page("bowl_text"); + var bowlText = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Sacrificial Bowls"); + this.lang().add(this.context().pageText(), + """ + Next, place *at least* 4 [Sacrificial Bowls](item://occultism:sacrificial_bowl) close to the pentacle. + \\ + \\ + They must be placed **anywhere** within 8 blocks of the central [](item://occultism:golden_sacrificial_bowl). **The exact location does not matter.** + """.formatted(COLOR_PURPLE)); + + this.context().page("bowl_placement"); + var bowlPlacementImage = BookImagePageModel.create() + .withImages(this.modLoc("textures/gui/book/bowl_placement.png")) + .withBorder(true) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Possible locations for the sacrificial bowls. + """.formatted(COLOR_PURPLE)); + + this.context().page("ritual_text"); + var ritualText = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Placing Ingredients"); + this.lang().add(this.context().pageText(), + """ + Now it is time to place the ingredients you see on the next page in the (regular, not golden) sacrificial bowls. The ingredients will be consumed from the bowls as the ritual progresses. + """.formatted(COLOR_PURPLE)); + + this.context().page("ritual_recipe"); + var ritualRecipe = BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/summon_foliot_crusher")); + //no text + + this.context().page("pentacle_link_hint"); + var pentacleLinkHint = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "A Note about Ritual Recipes"); + this.lang().add(this.context().pageText(), + """ + Ritual recipe pages, such as the previous pageshow not only the ingredients, but also the pentacle that you need to draw with chalk in order to use the ritual. + \\ + \\ + **To show the pentacle, click the blue link** at the center top of the ritual page. You can then even preview it in-world. + """.formatted(COLOR_PURPLE)); + + this.context().page("start_ritual"); + var startRitualText = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Let there be ... spirits!"); + this.lang().add(this.context().pageText(), + """ + Finally, [#](%1$s)right-click[#]() the [](item://occultism:golden_sacrificial_bowl) with the **bound** book of binding you created before and wait until the crusher spawns. + \\ + \\ + Now all that remains is to drop appropriate ores near the crusher and wait for it to turn it into dust. + """.formatted(COLOR_PURPLE)); + + this.context().page("automation"); + var automationText = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Automatic Rituals"); + this.lang().add(this.context().pageText(), + """ + Instead of right-clicking the golden sacrificial bowl with the final ingredient, you can also use a Hopper or any type of pipe to insert the item into the bowl. The ritual will start automatically.\\ + Note that any rituals that summon tamed animals or familiars will summon them untamed instead. + """.formatted(COLOR_PURPLE)); + + this.context().page("redstone"); + var redstoneText = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Redstone"); + this.lang().add(this.context().pageText(), + """ + Depending on the ritual state the golden bowl will emit a different redstone level: + - **0** if no ritual is active + - **1** if the ritual is active, but waiting for a sacrifice + - **2** if the ritual is active, but waiting for an item to be used + - **4** if the ritual is active and running + """.formatted(COLOR_PURPLE)); + + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.PENTACLE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + multiblock, + bowlText, + bowlPlacementImage, + ritualText, + ritualRecipe, + pentacleLinkHint, + startRitualText, + automationText, + redstoneText + ); + } + + private BookEntryModel makeBrushEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("brush"); + this.lang().add(this.context().entryName(), "Brush"); + this.lang().add(this.context().entryDescription(), "Cleaning up!"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Next Steps"); + this.lang().add(this.context().pageText(), + """ + Chalk is a pain to clean up, by [#](%1$s)right-clicking[#]() with a brush you can remove it from the world much more easily. + """.formatted(COLOR_PURPLE)); + + this.context().page("brushRecipe"); + var brushRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/brush")); + //no text + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.BRUSH.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + brushRecipe + ); + } + + private BookEntryModel makeMoreRitualsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("more_rituals"); + this.lang().add(this.context().entryName(), "More Rituals"); + this.lang().add(this.context().entryDescription(), "Ready for new challenges?"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(this.modLoc("textures/gui/book/robe.png")) + .withLocation(entryMap.get(icon)) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withCategoryToOpen(this.modLoc("rituals")); + } + + private BookEntryModel makeGreyParticlesEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("grey_particles"); + this.lang().add(this.context().entryName(), "Grey particles?"); + this.lang().add(this.context().entryDescription(), "What to do when a ritual seems stuck!"); + + this.context().page("text"); + var text = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Ritual stuck?"); + this.lang().add(this.context().pageText(), + """ + If a ritual appears stuck - no items being consumed - you should see grey particles around the [](item://occultism:golden_sacrificial_bowl). If this is the case the ritual requires you to either [use a specific item](entry://rituals/item_use) or [sacrifice a specific mob](entry://rituals/sacrifice). + \\ + \\ + Find the ritual in the [Rituals](category://rituals) category and check for instructions. + """); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(Items.GRAY_DYE) + .withLocation(entryMap.get(icon)) + .withPages(text); + } + + private BookEntryModel makeSpiritsSubcategoryEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("spirits"); + this.lang().add(this.context().entryName(), "About Spirits"); + this.lang().add(this.context().entryDescription(), "Learn more about Spirits."); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/spirits.png")) + .withCategoryToOpen(this.modLoc("spirits")) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withLocation(entryMap.get(icon)); + } + + private BookEntryModel makeChalksEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("chalks"); + this.lang().add(this.context().entryName(), "More Chalks"); + this.lang().add(this.context().entryDescription(), "Better chalks for better rituals!"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "More Chalks"); + this.lang().add(this.context().pageText(), + """ + For more advanced rituals the basic [White Chalk](entry://occultism:dictionary_of_spirits/getting_started/ritual_prep_chalk) is not sufficient. Instead chalks made from more arcane materials are required. + """); + + this.context().page("impure_gold_chalk_recipe"); + var impureGoldChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_gold_impure")); + //no text + + this.context().page("gold_chalk_recipe"); + var goldChalkRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/chalk_gold")); + //no text + + this.context().page("impure_purple_chalk_recipe"); + var impurePurpleChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_purple_impure")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + You do not need to visit the [#](%1$s)The End[#]() to obtain Endstone. You can summon a [Possessed Endermite](entry://possession_rituals/possess_endermite) which has a high chance to drop it. + """.formatted(COLOR_PURPLE)); + + this.context().page("purple_chalk_recipe"); + var purpleChalkRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/chalk_purple")); + //no text + + this.context().page("impure_red_chalk_recipe"); + var impureRedChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_red_impure")); + //no text + + this.context().page("red_chalk_recipe"); + var redChalkRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/chalk_red")); + //no text + + this.context().page("afrit_essence"); + var afritEssenceSpotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.AFRIT_ESSENCE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + To obtain the essence of an [#](%1$s)Afrit[#]() for [](item://occultism:chalk_red) you need to [summon and kill an Unbound Afrit](entry://summoning_rituals/afrit_essence). + """.formatted(COLOR_PURPLE)); + + this.context().page("decoColors"); + var decoColors = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Decorative Chalks"); + this.lang().add(this.context().pageText(), + """ + Other colored chalks (for now) only have decorative purposes, you can check the recipes in next pages. All needs to be purified in spirit fire. + """); + + this.context().page("impure_light_gray_chalk_recipe"); + var impureLightGrayChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_light_gray_impure")); + //no text + + this.context().page("impure_gray_chalk_recipe"); + var impureGrayChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_gray_impure")); + //no text + + this.context().page("impure_Black_chalk_recipe"); + var impureBlackChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_black_impure")); + //no text + + this.context().page("impure_brown_chalk_recipe"); + var impureBrownChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_brown_impure")); + //no text + this.context().page("impure_orange_chalk_recipe"); + var impureOrangeChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_orange_impure")); + //no text + this.context().page("impure_lime_chalk_recipe"); + var impureLimeChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_lime_impure")); + //no text + this.context().page("impure_green_chalk_recipe"); + var impureGreenChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_green_impure")); + //no text + this.context().page("impure_cyan_chalk_recipe"); + var impureCyanChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_cyan_impure")); + //no text + this.context().page("impure_blue_chalk_recipe"); + var impureBlueChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_blue_impure")); + //no text + this.context().page("impure_light_blue_chalk_recipe"); + var impureLightBlueChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_light_blue_impure")); + //no text + this.context().page("impure_pink_chalk_recipe"); + var impurePinkChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_pink_impure")); + //no text + this.context().page("impure_magenta_chalk_recipe"); + var impureMagentaChalkRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/chalk_magenta_impure")); + //no text + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.CHALK_GOLD.get()) + .withLocation(entryMap.get(icon)) + .withPages( + intro, + impureGoldChalkRecipe, + goldChalkRecipe, + impurePurpleChalkRecipe, + purpleChalkRecipe, + impureRedChalkRecipe, + redChalkRecipe, + afritEssenceSpotlight, + decoColors, + impureLightGrayChalkRecipe, + impureGrayChalkRecipe, + impureBlackChalkRecipe, + impureBrownChalkRecipe, + impureOrangeChalkRecipe, + impureLimeChalkRecipe, + impureGreenChalkRecipe, + impureCyanChalkRecipe, + impureBlueChalkRecipe, + impureLightBlueChalkRecipe, + impurePinkChalkRecipe, + impureMagentaChalkRecipe + ); + } + + private BookEntryModel makeOtherworldGogglesEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("otherworld_goggles"); + this.lang().add(this.context().entryName(), "Otherworld Goggles"); + this.lang().add(this.context().entryDescription(), "Say no to drugs!"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.OTHERWORLD_GOGGLES.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + The [](item://occultism:otherworld_goggles) are what advanced summoners use to see the [#](%1$s)Otherworld[#](), to avoid the negative side effects of [](entry://occultism:dictionary_of_spirits/getting_started/demons_dream). + \\ + \\ + Making your first pair of these is seen by many as a rite of passage. + """.formatted(COLOR_PURPLE)); + + this.context().page("crafting"); + var crafting = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Crafting Goggles"); + this.lang().add(this.context().pageText(), + """ + Crafting these goggles is a multi-step process described in detail in the Entry about [Crafting Otherworld Goggles](entry://crafting_rituals/craft_otherworld_goggles). + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.OTHERWORLD_GOGGLES.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + crafting + ); + } + + private BookEntryModel makeInfusedPickaxeEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("infused_pickaxe"); + this.lang().add(this.context().entryName(), "Infused Pickaxe"); + this.lang().add(this.context().entryDescription(), "Tackling Otherworld Ores"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.INFUSED_PICKAXE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Beyond [](item://occultism:otherworld_log) and [](item://occultism:otherstone) there are also otherworld materials that require special tools to harvest. + \\ + \\ + This pickaxe is rather brittle, but it will do the job. + """); + + this.context().page("gem_recipe"); + var gemRecipe = BookSpiritFireRecipePageModel.create() + .withRecipeId1(this.modLoc("spirit_fire/spirit_attuned_gem")) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + These gems, when infused with a spirit, can be used to interact with Otherword materials and are the key to crafting the pickaxe. + """); + + this.context().page("head_recipe"); + var headRecipe = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/spirit_attuned_pickaxe_head")); + //no text + + this.context().page("crafting"); + var crafting = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Crafting"); + this.lang().add(this.context().pageText(), + """ + After preparing the raw materials, the pickaxe needs to be infused with a spirit. + \\ + \\ + Follow the instructions at [Craft Infuse Pickaxe](entry://crafting_rituals/craft_infused_pickaxe) + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.INFUSED_PICKAXE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + gemRecipe, + headRecipe, + crafting + ); + } + + private BookEntryModel makeIesniumEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("iesnium"); + this.lang().add(this.context().entryName(), "Iesnium Ore"); + this.lang().add(this.context().entryDescription(), "Myterious metals ..."); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.IESNIUM_ORE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + This is a rare metal that, to the naked eye, looks like [](item://minecraft:netherrack) and cannot be mined with a regular pickaxe. + \\ + \\ + When mined with the correct tools, it can be used to craft powerful items (you will learn more about that later). + """.formatted(COLOR_PURPLE)); + + this.context().page("where"); + var where = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Where to find it"); + this.lang().add(this.context().pageText(), + """ + Like Netherrack, Iesnium can be found in the Nether. In order to **see** it, you need to wear [Otherworld Goggles](entry://getting_started/otherworld_goggles). + \\ + \\ + To make searching for it simpler, attune a [Divination Rod](entry://getting_started/divination_rod) to it and righ-click and hold in the nether until it highlights a nearby block, which will hold the ore. + """.formatted(COLOR_PURPLE)); + + this.context().page("how"); + var how = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "How to mine it"); + this.lang().add(this.context().pageText(), + """ + Iesnium can only be mined with the [Infused Pickaxe](entry://getting_started/infused_pickaxe) or an [](item://occultism:iesnium_pickaxe) (about which you will learn later). + \\ + \\ + After identifying a block that holds Iesnium, you can mine it with the pickaxe you created in the previous step. + """.formatted(COLOR_PURPLE)); + + this.context().page("processing"); + var processing = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Processing"); + this.lang().add(this.context().pageText(), + """ + Iesnium Ore, after mining, can be smelted directly into ingots, or placed down. When placed, it will not turn back into it's netherrack form. Consequently it can also be mined with any pickaxe then. This visible form of the Ore, when mined, will drop [](item://occultism:raw_iesnium). + """.formatted(COLOR_PURPLE)); + + this.context().page("uses"); + var uses = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Uses"); + this.lang().add(this.context().pageText(), + """ + Iesnium can be used to craft an improved pickaxe, spirit lamps, and other powerful items. Follow the progress in this book to learn more about it. + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismBlocks.IESNIUM_ORE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + where, + how, + processing, + uses + ); + } + + private BookEntryModel makeIesniumPickaxeEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("iesnium_pickaxe"); + this.lang().add(this.context().entryName(), "Iesnium Pickaxe"); + this.lang().add(this.context().entryDescription(), "A more durable otherworld-appropriate pickaxe"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.IESNIUM_PICKAXE.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + Like the [Infused Pickaxe](entry://getting_started/infused_pickaxe), this pickaxe can be used to mine Tier 2 Otherworld Materials such as [](item://occultism:iesnium_ore). As it is made from metal, instead of brittle [](item://occultism:spirit_attuned_gem), it is very durable and can be used for a long time. + """.formatted(COLOR_PURPLE)); + + this.context().page("crafting"); + var crafting = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/iesnium_pickaxe")); + //no text + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.IESNIUM_PICKAXE.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + crafting + ); + } + + private BookEntryModel makeMagicLampsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("magic_lamps"); + this.lang().add(this.context().entryName(), "Magic Lamps"); + this.lang().add(this.context().entryDescription(), "Three wishes? Close, but not quite.."); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.MAGIC_LAMP_EMPTY.get())) + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Magic Lamps"); + this.lang().add(this.context().pageText(), + """ + Magic Lamps can be used to keep spirits safe from [#](%1$s)Essence Decay[#](), while still having access to some of their powers. Most commonly they are used to access a [#](%1$s)Mining Dimension[#]() and act as (*lag free*) [#](%1$s)Void Miners[#](). + """.formatted(COLOR_PURPLE)); + + this.context().page("crafting"); + var crafting = BookCraftingRecipePageModel.create() + .withRecipeId1(this.modLoc("crafting/magic_lamp_empty")); + //no text + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.MAGIC_LAMP_EMPTY.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + crafting + ); + } + + private BookEntryModel makeSpiritMinersEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("spirit_miners"); + this.lang().add(this.context().entryName(), "Spirit Miners"); + this.lang().add(this.context().entryDescription(), "It's Free Real Estate (-> Resources)"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.MINER_FOLIOT_UNSPECIALIZED.get())) + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Spirit Miners"); + this.lang().add(this.context().pageText(), + """ + By summoning a spirit into a Magic Lamp and placing it in a [Dimensional Mineshaft (see next step)](entry://getting_started/mineshaft) it can be made to mine for you in a [#](%1$s)Mining Dimension[#](). This is a great way to get resources without having to go mining in the overworld (or other dimesions) yourself. + """.formatted(COLOR_PURPLE)); + + this.context().page("crafting"); + var crafting = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Crafting"); + this.lang().add(this.context().pageText(), + """ + See [Foliot Miner](entry://crafting_rituals/craft_foliot_miner) and the subsequent entries for information on how to craft spirit miners. + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismItems.MINER_FOLIOT_UNSPECIALIZED.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + crafting + ); + } + + private BookEntryModel makeMineshaftEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("mineshaft"); + this.lang().add(this.context().entryName(), "Dimensional Mineshaft"); + this.lang().add(this.context().entryDescription(), "Ethically questionable, but very profitable"); + + this.context().page("spotlight"); + var spotlight = BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismBlocks.DIMENSIONAL_MINESHAFT.get())) + .withText(this.context().pageText()); + this.lang().add(this.context().pageText(), + """ + This block acts as a portal, for spirits only, to the [#](%1$s)Mining Dimension[#](). Place a Magic Lamp with a Miner Spirit in it, to make it mine for you. + """.formatted(COLOR_PURPLE)); + + this.context().page("crafting"); + var crafting = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Crafting"); + this.lang().add(this.context().pageText(), + """ + See [Dimensional Mineshaft](entry://crafting_rituals/craft_dimensional_mineshaft) in the [Binding Rituals](category://crafting_rituals) Category. + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismBlocks.DIMENSIONAL_MINESHAFT.get()) + .withLocation(entryMap.get(icon)) + .withPages( + spotlight, + crafting + ); + } + + private BookEntryModel makeStorageEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("storage"); + this.lang().add(this.context().entryName(), "Magic Storage"); + this.lang().add(this.context().entryDescription(), "Looking for much much much more storage? Look no further!"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(OccultismBlocks.STORAGE_CONTROLLER.get()) + .withLocation(entryMap.get(icon)) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withCategoryToOpen(this.modLoc("storage")); + } + + private BookEntryModel makePossessionRitualsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("possession_rituals"); + this.lang().add(this.context().entryName(), "Possession Rituals"); + this.lang().add(this.context().entryDescription(), "A different way to get rare drops ..."); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Possession Rituals"); + this.lang().add(this.context().pageText(), + """ + Possessed mobs are controlled by spirits, allowing the summoner to determine some of their properties. They usually have **high drop rates** for rare drops, but are generally harder to kill. + \\ + \\ + You probably will want to start by summoning a [Possessed Endermite](entry://possession_rituals/possess_endermite) to get [](item://minecraft:end_stone) to craft [Advanced Chalks](entry://getting_started/chalks). + """.formatted(COLOR_PURPLE)); + + this.context().page("more"); + var more = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "More Information"); + this.lang().add(this.context().pageText(), + """ + To find out more about Possession Rituals, see the [Possession Rituals](category://possession_rituals) Category. + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(this.modLoc("textures/gui/book/possession.png")) + .withLocation(entryMap.get(icon)) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withPages( + intro, + more + ); + } + + private BookEntryModel makeFamiliarRitualsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_rituals"); + this.lang().add(this.context().entryName(), "Familiar Rituals"); + this.lang().add(this.context().entryDescription(), "Personal helpers that provide buffs or fight for you"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Familiar Rituals"); + this.lang().add(this.context().pageText(), + """ + Familiars provide a variety of bonus effects, such as feather falling, water breathing, jump boosts and more, and may also assist you in combat. + \\ + \\ + Store them in a [Familiar Ring](entry://crafting_rituals/craft_familiar_ring) to equip them as a curio. + """.formatted(COLOR_PURPLE)); + + this.context().page("more"); + var more = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "More Information"); + this.lang().add(this.context().pageText(), + """ + To find more about Familiars, see the [Familiar Rituals](category://familiar_rituals) Category. + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(this.modLoc("textures/gui/book/parrot.png")) + .withLocation(entryMap.get(icon)) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withPages( + intro, + more + ); + } + + private BookEntryModel makeSummoningRitualsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("summoning_rituals"); + this.lang().add(this.context().entryName(), "Summoning Rituals"); + this.lang().add(this.context().entryDescription(), "Spirit helpers for your daily work life"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Summoning Rituals"); + this.lang().add(this.context().pageText(), + """ + Summoning Rituals allow you to summon spirits to work for you. Unlike familiars, they are not personally bound to you, meaning they will not follow you around, but they will perform various work tasks for you. In fact the first ritual you performed, the [Foliot Crusher](entry://getting_started/first_ritual), was a summoning ritual. + """.formatted(COLOR_PURPLE)); + + this.context().page("more"); + var more = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "More Information"); + this.lang().add(this.context().pageText(), + """ + To find more about Summoning Rituals, see the [Summoning Rituals](category://summoning_rituals) Category. + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(this.modLoc("textures/gui/book/summoning.png")) + .withLocation(entryMap.get(icon)) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withPages( + intro, + more + ); + } + + private BookEntryModel makeCraftingRitualsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("crafting_rituals"); + this.lang().add(this.context().entryName(), "Infusion Rituals"); + this.lang().add(this.context().entryDescription(), "Infuse spirits into items to create powerful tools"); + + this.context().page("intro"); + var intro = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "Infusion Rituals"); + this.lang().add(this.context().pageText(), + """ + Infusion rituals are all about crafting powerful items, by binding ("infusing") spirits into objects.The spirits will provide special functionality to the items. + """.formatted(COLOR_PURPLE)); + + this.context().page("more"); + var more = BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()); + this.lang().add(this.context().pageTitle(), "More Information"); + this.lang().add(this.context().pageText(), + """ + To find more about Infusing items, see the [Infusion Rituals](category://crafting_rituals) Category. + """.formatted(COLOR_PURPLE)); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withDescription(this.context().entryDescription()) + .withIcon(this.modLoc("textures/gui/book/infusion.png")) + .withLocation(entryMap.get(icon)) + .withEntryBackground(1, 1) //silver background and wavey entry shape + .withPages( + intro, + more + ); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/binding_rituals/ApprenticeRitualSatchelEntry.java b/src/main/java/com/klikli_dev/occultism/datagen/book/binding_rituals/ApprenticeRitualSatchelEntry.java new file mode 100644 index 000000000..44b7e41c0 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/binding_rituals/ApprenticeRitualSatchelEntry.java @@ -0,0 +1,92 @@ +package com.klikli_dev.occultism.datagen.book.binding_rituals; + +import com.klikli_dev.modonomicon.api.datagen.CategoryProvider; +import com.klikli_dev.modonomicon.api.datagen.EntryBackground; +import com.klikli_dev.modonomicon.api.datagen.EntryProvider; +import com.klikli_dev.modonomicon.api.datagen.book.BookIconModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookSpotlightPageModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookTextPageModel; +import com.klikli_dev.occultism.integration.modonomicon.pages.BookRitualRecipePageModel; +import com.klikli_dev.occultism.registry.OccultismItems; +import com.mojang.datafixers.util.Pair; +import net.minecraft.ChatFormatting; +import net.minecraft.world.item.crafting.Ingredient; + +public class ApprenticeRitualSatchelEntry extends EntryProvider { + + public static final String ENTRY_ID = "apprentice_ritual_satchel"; + + + public ApprenticeRitualSatchelEntry(CategoryProvider parent) { + super(parent); + } + + @Override + protected void generatePages() { + + this.page("spotlight", () -> BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.RITUAL_SATCHEL_T1.get())) + .withText(this.context().pageText())); + this.pageText(""" + At first glance the satchel appears to be a normal bag, of moderate size and storage capacity. However, closer inspection reveals that a {0} is bound to the satchel, tasked with assisting the summoner in drawing pentacles for their rituals. + """, + this.color("Djinni", ChatFormatting.DARK_PURPLE) + + ); + + this.page("about", () -> BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText())); + this.pageTitle("About"); + this.pageText(""" + A ritual satchel can hold items needed to create pentacles for rituals. Other items cannot be placed in the satchel. + \\ + The satchel allows to speed up setting pentacles by automatically choosing the right items from the satchel, instead of manually selecting chalks, candles and other items to place them. + """); + + this.page("crafting", () -> BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_ritual_satchel_t1")) + ); + //no text + + this.page("usage", () -> BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText())); + this.pageTitle("Usage"); + this.pageText(""" + 1. {0} to open the satchel and place chalks, candles, crystals, skulls and other items needed for rituals. + 2. Using this book, use the "eye" icon to preview the pentacle you want to set up in the world. + 3. {1} with this book to anchor the preview pentacle in the spot where you want to set it up. + 4. {2} with the satchel on a previewed chalk mark or block to automatically place it. + 5. Repeat until the pentacle is complete. + """, + this.color("Shift-Right-Click", ChatFormatting.GREEN), + this.color("Right-Click", ChatFormatting.GREEN) + ); + } + + @Override + protected String entryName() { + return "Apprentice Ritual Satchel"; + } + + @Override + protected String entryDescription() { + return "Tired of so many chalks and paraphernalia? The Ritual Satchel is the solution!"; + } + + @Override + protected Pair entryBackground() { + return EntryBackground.DEFAULT; + } + + @Override + protected BookIconModel entryIcon() { + return BookIconModel.create(OccultismItems.RITUAL_SATCHEL_T1.get()); + } + + @Override + protected String entryId() { + return ENTRY_ID; + } +} diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/binding_rituals/ArtisanalRitualSatchelEntry.java b/src/main/java/com/klikli_dev/occultism/datagen/book/binding_rituals/ArtisanalRitualSatchelEntry.java new file mode 100644 index 000000000..9a8546636 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/binding_rituals/ArtisanalRitualSatchelEntry.java @@ -0,0 +1,111 @@ +package com.klikli_dev.occultism.datagen.book.binding_rituals; + +import com.klikli_dev.modonomicon.api.datagen.CategoryProvider; +import com.klikli_dev.modonomicon.api.datagen.EntryBackground; +import com.klikli_dev.modonomicon.api.datagen.EntryProvider; +import com.klikli_dev.modonomicon.api.datagen.book.BookIconModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookSpotlightPageModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookTextPageModel; +import com.klikli_dev.occultism.integration.modonomicon.pages.BookRitualRecipePageModel; +import com.klikli_dev.occultism.registry.OccultismBlocks; +import com.klikli_dev.occultism.registry.OccultismItems; +import com.mojang.datafixers.util.Pair; +import net.minecraft.ChatFormatting; +import net.minecraft.world.item.crafting.Ingredient; + +public class ArtisanalRitualSatchelEntry extends EntryProvider { + + public static final String ENTRY_ID = "artisanal_ritual_satchel"; + + + public ArtisanalRitualSatchelEntry(CategoryProvider parent) { + super(parent); + } + + @Override + protected void generatePages() { + this.page("spotlight", () -> BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.RITUAL_SATCHEL_T2.get())) + .withText(this.context().pageText())); + this.pageText(""" + The artisanal satchel employs an {0} to assist the summoner in drawing pentacles for their rituals. Unlike {1} in the apprentice satchel, the bound {0} can set up an entire pentacle within a moment's notice. + \\ + Moreover, the spirit can also clean up the pentacle after the ritual is complete, leaving no trace of the ritual behind. + """, + this.color("Afrit", ChatFormatting.DARK_PURPLE), + this.color("Djinni", ChatFormatting.DARK_PURPLE) + ); + + this.page("about", () -> BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText())); + this.pageTitle("About"); + this.pageText(""" + A ritual satchel can hold items needed to create pentacles for rituals. Other items cannot be placed in the satchel. + \\ + The satchel sets up an entire pentacle at once, if all necessary items are present in the satchel.\\ + It can also remove (intact) pentacles by {0} the {1} and store all blocks back in the satchel. + """, + this.color("Right-Clicking", ChatFormatting.GREEN), + this.itemLink(OccultismBlocks.GOLDEN_SACRIFICIAL_BOWL) + ); + + this.page("crafting", () -> BookRitualRecipePageModel.create() + .withRecipeId1(this.modLoc("ritual/craft_ritual_satchel_t2")) + ); + //no text + + this.page("usage_drawing", () -> BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText())); + this.pageTitle("Usage (Drawing)"); + this.pageText(""" + 1. {0} to open the satchel and place chalks, candles, crystals, skulls and other items needed for rituals. + 2. Using this book, use the "eye" icon to preview the pentacle you want to set up in the world. + 3. {1} with this book to anchor the preview pentacle in the spot where you want to set it up. + 4. {2} with the satchel on a previewed chalk mark or block to automatically place it. + 5. Repeat until the pentacle is complete. + """, + this.color("Shift-Right-Click", ChatFormatting.GREEN), + this.color("Right-Click", ChatFormatting.GREEN) + ); + + this.page("usage_cleaning", () -> BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText())); + this.pageTitle("Usage (Cleaning)"); + this.pageText(""" + 1. Find a pentacle you want to remove. The pentacle needs to be intact (ready for a ritual). + 2. {0} the central {1} with the satchel. + 2. The satchel will remove all chalk marks, and pick up all paraphernalia blocks, such as candles or skulls, used in the pentacle. + """, + this.color("Right-Click", ChatFormatting.GREEN), + this.itemLink(OccultismBlocks.GOLDEN_SACRIFICIAL_BOWL) + ); + } + + @Override + protected String entryName() { + return "Artisanal Ritual Satchel"; + } + + @Override + protected String entryDescription() { + return "The Apprentice Ritual Satchel is still too slow? Let's get help from an Afrit!"; + } + + @Override + protected Pair entryBackground() { + return EntryBackground.DEFAULT; + } + + @Override + protected BookIconModel entryIcon() { + return BookIconModel.create(OccultismItems.RITUAL_SATCHEL_T2.get()); + } + + @Override + protected String entryId() { + return ENTRY_ID; + } +} diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/DemonicPartnerEntry.java b/src/main/java/com/klikli_dev/occultism/datagen/book/familiar_rituals/DemonicPartnerEntry.java similarity index 98% rename from src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/DemonicPartnerEntry.java rename to src/main/java/com/klikli_dev/occultism/datagen/book/familiar_rituals/DemonicPartnerEntry.java index ab1714508..52708e917 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/DemonicPartnerEntry.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/familiar_rituals/DemonicPartnerEntry.java @@ -1,4 +1,4 @@ -package com.klikli_dev.occultism.datagen.book.familiarrituals; +package com.klikli_dev.occultism.datagen.book.familiar_rituals; import com.klikli_dev.modonomicon.api.datagen.CategoryProvider; import com.klikli_dev.modonomicon.api.datagen.EntryBackground; diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/ResurrectionEntry.java b/src/main/java/com/klikli_dev/occultism/datagen/book/familiar_rituals/ResurrectionEntry.java similarity index 98% rename from src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/ResurrectionEntry.java rename to src/main/java/com/klikli_dev/occultism/datagen/book/familiar_rituals/ResurrectionEntry.java index 3149738fc..3a0483b82 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/ResurrectionEntry.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/familiar_rituals/ResurrectionEntry.java @@ -1,4 +1,4 @@ -package com.klikli_dev.occultism.datagen.book.familiarrituals; +package com.klikli_dev.occultism.datagen.book.familiar_rituals; import com.klikli_dev.modonomicon.api.datagen.CategoryProvider; import com.klikli_dev.modonomicon.api.datagen.EntryBackground; diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/getting_started/RitualSatchelsEntry.java b/src/main/java/com/klikli_dev/occultism/datagen/book/getting_started/RitualSatchelsEntry.java new file mode 100644 index 000000000..b1d981e70 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/getting_started/RitualSatchelsEntry.java @@ -0,0 +1,78 @@ +package com.klikli_dev.occultism.datagen.book.getting_started; + +import com.klikli_dev.modonomicon.api.datagen.CategoryProvider; +import com.klikli_dev.modonomicon.api.datagen.EntryBackground; +import com.klikli_dev.modonomicon.api.datagen.EntryProvider; +import com.klikli_dev.modonomicon.api.datagen.book.BookIconModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookSpotlightPageModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookTextPageModel; +import com.klikli_dev.occultism.datagen.book.BindingRitualsCategory; +import com.klikli_dev.occultism.datagen.book.binding_rituals.ApprenticeRitualSatchelEntry; +import com.klikli_dev.occultism.integration.modonomicon.pages.BookRitualRecipePageModel; +import com.klikli_dev.occultism.registry.OccultismItems; +import com.mojang.datafixers.util.Pair; +import net.minecraft.ChatFormatting; +import net.minecraft.world.item.crafting.Ingredient; + +public class RitualSatchelsEntry extends EntryProvider { + + public static final String ENTRY_ID = "ritual_satchels"; + + + public RitualSatchelsEntry(CategoryProvider parent) { + super(parent); + } + + @Override + protected void generatePages() { + + this.page("spotlight", () -> BookSpotlightPageModel.create() + .withItem(Ingredient.of(OccultismItems.RITUAL_SATCHEL_T1.get())) + .withText(this.context().pageText())); + this.pageText(""" + Ritual satchels are bags that can hold items needed to create pentacles for rituals.\\ + More importantly, they can automatically place the right items for a pentacle, removing the need to manually place chalks, candles, crystals, skulls and other items needed for rituals.\\\\ + The Apprentice Satchel places pentacle blocks one by one.\\ + The improved Artisanal Satchel places all pentacle blocks in a single action.\\ + """ + ); + + this.page("more", () -> BookTextPageModel.create() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText())); + this.pageTitle("Obtaining a Satchel"); + this.pageText(""" + Visit the entry about the {0} or the {1} in the {2} to learn how to enchant a satchel and use it for rituals. + """, + this.entryLink("Apprentice Satchel", BindingRitualsCategory.CATEGORY_ID, ApprenticeRitualSatchelEntry.ENTRY_ID), + this.entryLink("Artisanal Satchel", BindingRitualsCategory.CATEGORY_ID, ApprenticeRitualSatchelEntry.ENTRY_ID), + this.categoryLink("Binding Rituals Category", BindingRitualsCategory.CATEGORY_ID) + ); + + } + + @Override + protected String entryName() { + return "Ritual Satchels"; + } + + @Override + protected String entryDescription() { + return "Easier pentacle drawing with a Ritual Satchel"; + } + + @Override + protected Pair entryBackground() { + return EntryBackground.DEFAULT; + } + + @Override + protected BookIconModel entryIcon() { + return BookIconModel.create(OccultismItems.RITUAL_SATCHEL_T1.get()); + } + + @Override + protected String entryId() { + return ENTRY_ID; + } +} diff --git a/src/main/java/com/klikli_dev/occultism/datagen/lang/ENUSProvider.java b/src/main/java/com/klikli_dev/occultism/datagen/lang/ENUSProvider.java index 32f0d7aea..05e94cd32 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/lang/ENUSProvider.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/lang/ENUSProvider.java @@ -127,6 +127,8 @@ public void addItemTooltips() { this.add(OccultismItems.SOUL_GEM_ITEM.get().getDescriptionId() + ".tooltip_filled", "Contains a captured %s."); this.add(OccultismItems.SOUL_GEM_ITEM.get().getDescriptionId() + ".tooltip_empty", "Use on a creature to capture it."); this.add(OccultismItems.SATCHEL.get().getDescriptionId() + ".tooltip", "%s is bound to this satchel."); + this.add(OccultismItems.RITUAL_SATCHEL_T1.get().getDescriptionId() + ".tooltip", "%s is bound to this satchel."); + this.add(OccultismItems.RITUAL_SATCHEL_T2.get().getDescriptionId() + ".tooltip", "%s is bound to this satchel."); this.add(OccultismItems.SOUL_SHARD_ITEM.get().getDescriptionId() + ".tooltip_filled", "Contains the soul of a %s.\nCan be used to resurrect it."); this.add(OccultismItems.SOUL_SHARD_ITEM.get().getDescriptionId() + ".tooltip_empty", "Dropped by a Familiar after their untimely death. Can be used to resurrect it."); @@ -148,6 +150,28 @@ private void addItems() { this.addItem(OccultismItems.DEBUG_DJINNI_MANAGE_MACHINE, "Summon Debug Djinni Manage Machine"); this.addItem(OccultismItems.DEBUG_DJINNI_TEST, "Summon Debug Djinni Test"); + this.addItem(OccultismItems.RITUAL_SATCHEL_T1, "Apprentice Ritual Satchel"); + this.addAutoTooltip(OccultismItems.RITUAL_SATCHEL_T1.get(), + """ + A basic ritual satchel that can place ritual circles block by block. + Right-Click a preview block to place it out of the satchel. + Shift-Right-Click to open the satchel and add ritual ingredients. + """ + ); + this.addItem(OccultismItems.RITUAL_SATCHEL_T2, "Artisanal Ritual Satchel"); + this.addAutoTooltip(OccultismItems.RITUAL_SATCHEL_T2.get(), + """ + An improved ritual satchel that can place an entire ritual circle at once. + Right-Click any preview block to place all preview blocks out of the satchel. + Shift-Right-Click to open the satchel and add ritual ingredients. + Right-Click a Golden Bowl to remove the ritual circle and collect the ingredients. + """ + ); + + this.add(TranslationKeys.RITUAL_SATCHEL_NO_PREVIEW_IN_WORLD, " You need to preview a pentacle using the Dictionary of Spirits."); + this.add(TranslationKeys.RITUAL_SATCHEL_NO_PREVIEW_BLOCK_TARGETED, "You need to aim the ritual satchel at a preview block."); + this.add(TranslationKeys.RITUAL_SATCHEL_NO_VALID_ITEM_IN_SATCHEL, "There is no valid item in the satchel for this previewed block."); + this.addItem(OccultismItems.CHALK_GOLD, "Yellow Chalk"); this.addItem(OccultismItems.CHALK_PURPLE, "Purple Chalk"); this.addItem(OccultismItems.CHALK_RED, "Red Chalk"); @@ -1964,7 +1988,7 @@ private void addPossessionRitualsCategory(BookContextHelper helper) { private void addCraftingRitualsCategory(BookContextHelper helper) { helper.category("crafting_rituals"); - this.add(helper.categoryName(), "Binding Rituals"); +// this.add(helper.categoryName(), "Binding Rituals"); //done via the category provider for the rituals category helper.entry("return_to_rituals"); this.add(helper.entryName(), "Return to Rituals Category"); @@ -2775,8 +2799,8 @@ When upgraded by a blacksmith familiar, it regains a limb (can only be done once this.add(helper.pageTitle(), "Description"); this.add(helper.pageText(), """ - Purify a Vex to an Allay on a resurrection process that reveals its true name. - """.formatted(COLOR_PURPLE)); + Purify a Vex to an Allay on a resurrection process that reveals its true name. + """.formatted(COLOR_PURPLE)); } @@ -3299,79 +3323,82 @@ private void advancementDescr(String name, String s) { private void addTags() { // Block tags - this.addBlockTag(OccultismTags.Blocks.OTHERWORLD_SAPLINGS,"Otherworld Saplings"); - this.addBlockTag(OccultismTags.Blocks.CANDLES,"Candles"); - this.addBlockTag(OccultismTags.Blocks.CAVE_WALL_BLOCKS,"Cave Wall Blocks"); - this.addBlockTag(OccultismTags.Blocks.NETHERRACK,"Netherrack"); - this.addBlockTag(OccultismTags.Blocks.STORAGE_STABILIZER,"Storage Stabilizer Blocks"); - this.addBlockTag(OccultismTags.Blocks.TREE_SOIL,"Tree Soil Blocks"); - this.addBlockTag(OccultismTags.Blocks.WORLDGEN_BLACKLIST,"Worldgen Blacklisted Blocks"); - this.addBlockTag(OccultismTags.Blocks.IESNIUM_ORE,"Iesnium Ore"); - this.addBlockTag(OccultismTags.Blocks.SILVER_ORE,"Silver Ore"); - this.addBlockTag(OccultismTags.Blocks.STORAGE_BLOCKS_IESNIUM,"Iesnium Storage Blocks"); - this.addBlockTag(OccultismTags.Blocks.STORAGE_BLOCKS_SILVER,"Silver Storage Blocks"); - this.addBlockTag(OccultismTags.Blocks.STORAGE_BLOCKS_RAW_IESNIUM,"Raw Iesnium Storage Blocks"); - this.addBlockTag(OccultismTags.Blocks.STORAGE_BLOCKS_RAW_SILVER,"Raw Silver Storage Blocks"); + this.addBlockTag(OccultismTags.Blocks.OTHERWORLD_SAPLINGS, "Otherworld Saplings"); + this.addBlockTag(OccultismTags.Blocks.CANDLES, "Candles"); + this.addBlockTag(OccultismTags.Blocks.CAVE_WALL_BLOCKS, "Cave Wall Blocks"); + this.addBlockTag(OccultismTags.Blocks.NETHERRACK, "Netherrack"); + this.addBlockTag(OccultismTags.Blocks.STORAGE_STABILIZER, "Storage Stabilizer Blocks"); + this.addBlockTag(OccultismTags.Blocks.TREE_SOIL, "Tree Soil Blocks"); + this.addBlockTag(OccultismTags.Blocks.WORLDGEN_BLACKLIST, "Worldgen Blacklisted Blocks"); + this.addBlockTag(OccultismTags.Blocks.IESNIUM_ORE, "Iesnium Ore"); + this.addBlockTag(OccultismTags.Blocks.SILVER_ORE, "Silver Ore"); + this.addBlockTag(OccultismTags.Blocks.STORAGE_BLOCKS_IESNIUM, "Iesnium Storage Blocks"); + this.addBlockTag(OccultismTags.Blocks.STORAGE_BLOCKS_SILVER, "Silver Storage Blocks"); + this.addBlockTag(OccultismTags.Blocks.STORAGE_BLOCKS_RAW_IESNIUM, "Raw Iesnium Storage Blocks"); + this.addBlockTag(OccultismTags.Blocks.STORAGE_BLOCKS_RAW_SILVER, "Raw Silver Storage Blocks"); // Item tags - this.addItemTag(OccultismTags.Items.OTHERWORLD_SAPLINGS,"Otherworld Saplings"); - this.addItemTag(OccultismTags.Items.BOOK_OF_CALLING_DJINNI,"Book of Calling Djinni"); - this.addItemTag(OccultismTags.Items.BOOK_OF_CALLING_FOLIOT,"Book of Calling Foliot"); - this.addItemTag(OccultismTags.Items.BOOKS_OF_BINDING,"Books of Binding"); - this.addItemTag(OccultismTags.Items.Miners.BASIC_RESOURCES,"Basic Resource Miners"); - this.addItemTag(OccultismTags.Items.Miners.DEEPS,"Deepslate Miners"); - this.addItemTag(OccultismTags.Items.Miners.MASTER,"Rare Resource Miners"); - this.addItemTag(OccultismTags.Items.Miners.ORES,"General Miners"); - this.addItemTag(OccultismTags.Items.TOOLS_KNIFE,"Knives"); - this.addItemTag(OccultismTags.Items.ELYTRA,"Elytras"); - this.addItemTag(OccultismTags.Items.OTHERWORLD_GOGGLES,"Otherworld Goggles"); - this.addItemTag(OccultismTags.Items.DATURA_SEEDS,"Demon's Dream Seeds"); - this.addItemTag(OccultismTags.Items.DATURA_CROP,"Demon's Dream"); - this.addItemTag(OccultismTags.Items.COPPER_DUST,"Copper Dust"); - this.addItemTag(OccultismTags.Items.GOLD_DUST,"Gold Dust"); - this.addItemTag(OccultismTags.Items.IESNIUM_DUST,"Iesnium Dust"); - this.addItemTag(OccultismTags.Items.IRON_DUST,"Iron Dust"); - this.addItemTag(OccultismTags.Items.SILVER_DUST,"Silver Dust"); - this.addItemTag(OccultismTags.Items.END_STONE_DUST,"Crushed End Stone"); - this.addItemTag(OccultismTags.Items.OBSIDIAN_DUST,"Crushed Obsidian"); - this.addItemTag(OccultismTags.Items.IESNIUM_INGOT,"Iesnium Ingot"); - this.addItemTag(OccultismTags.Items.SILVER_INGOT,"Silver Ingot"); - this.addItemTag(OccultismTags.Items.IESNIUM_NUGGET,"Iesnium Nugget"); - this.addItemTag(OccultismTags.Items.SILVER_NUGGET,"Silver Nugget"); - this.addItemTag(OccultismTags.Items.IESNIUM_ORE,"Iesnium Ore"); - this.addItemTag(OccultismTags.Items.SILVER_ORE,"Silver Ore"); - this.addItemTag(OccultismTags.Items.RAW_IESNIUM,"Raw Iesnium"); - this.addItemTag(OccultismTags.Items.RAW_SILVER,"Raw Silver"); - this.addItemTag(OccultismTags.Items.STORAGE_BLOCK_IESNIUM,"Iesnium Storage Blocks"); - this.addItemTag(OccultismTags.Items.STORAGE_BLOCK_SILVER,"Silver Storage Blocks"); - this.addItemTag(OccultismTags.Items.STORAGE_BLOCK_RAW_IESNIUM,"Raw Iesnium Storage Blocks"); - this.addItemTag(OccultismTags.Items.STORAGE_BLOCK_RAW_SILVER,"Raw Silver Storage Blocks"); - this.addItemTag(OccultismTags.Items.TALLOW,"Tallow"); - this.addItemTag(OccultismTags.Items.METAL_AXES,"Metal Axes"); - this.addItemTag(OccultismTags.Items.MAGMA,"Magma"); - this.addItemTag(OccultismTags.Items.BOOKS,"Books"); - this.addItemTag(OccultismTags.Items.FRUITS,"Fruits"); + this.addItemTag(OccultismTags.Items.OTHERWORLD_SAPLINGS, "Otherworld Saplings"); + this.addItemTag(OccultismTags.Items.BOOK_OF_CALLING_DJINNI, "Book of Calling Djinni"); + this.addItemTag(OccultismTags.Items.BOOK_OF_CALLING_FOLIOT, "Book of Calling Foliot"); + this.addItemTag(OccultismTags.Items.BOOKS_OF_BINDING, "Books of Binding"); + this.addItemTag(OccultismTags.Items.Miners.BASIC_RESOURCES, "Basic Resource Miners"); + this.addItemTag(OccultismTags.Items.Miners.DEEPS, "Deepslate Miners"); + this.addItemTag(OccultismTags.Items.Miners.MASTER, "Rare Resource Miners"); + this.addItemTag(OccultismTags.Items.Miners.ORES, "General Miners"); + this.addItemTag(OccultismTags.Items.TOOLS_KNIFE, "Knives"); + this.addItemTag(OccultismTags.Items.ELYTRA, "Elytras"); + this.addItemTag(OccultismTags.Items.OTHERWORLD_GOGGLES, "Otherworld Goggles"); + this.addItemTag(OccultismTags.Items.DATURA_SEEDS, "Demon's Dream Seeds"); + this.addItemTag(OccultismTags.Items.DATURA_CROP, "Demon's Dream"); + this.addItemTag(OccultismTags.Items.COPPER_DUST, "Copper Dust"); + this.addItemTag(OccultismTags.Items.GOLD_DUST, "Gold Dust"); + this.addItemTag(OccultismTags.Items.IESNIUM_DUST, "Iesnium Dust"); + this.addItemTag(OccultismTags.Items.IRON_DUST, "Iron Dust"); + this.addItemTag(OccultismTags.Items.SILVER_DUST, "Silver Dust"); + this.addItemTag(OccultismTags.Items.END_STONE_DUST, "Crushed End Stone"); + this.addItemTag(OccultismTags.Items.OBSIDIAN_DUST, "Crushed Obsidian"); + this.addItemTag(OccultismTags.Items.IESNIUM_INGOT, "Iesnium Ingot"); + this.addItemTag(OccultismTags.Items.SILVER_INGOT, "Silver Ingot"); + this.addItemTag(OccultismTags.Items.IESNIUM_NUGGET, "Iesnium Nugget"); + this.addItemTag(OccultismTags.Items.SILVER_NUGGET, "Silver Nugget"); + this.addItemTag(OccultismTags.Items.IESNIUM_ORE, "Iesnium Ore"); + this.addItemTag(OccultismTags.Items.SILVER_ORE, "Silver Ore"); + this.addItemTag(OccultismTags.Items.RAW_IESNIUM, "Raw Iesnium"); + this.addItemTag(OccultismTags.Items.RAW_SILVER, "Raw Silver"); + this.addItemTag(OccultismTags.Items.STORAGE_BLOCK_IESNIUM, "Iesnium Storage Blocks"); + this.addItemTag(OccultismTags.Items.STORAGE_BLOCK_SILVER, "Silver Storage Blocks"); + this.addItemTag(OccultismTags.Items.STORAGE_BLOCK_RAW_IESNIUM, "Raw Iesnium Storage Blocks"); + this.addItemTag(OccultismTags.Items.STORAGE_BLOCK_RAW_SILVER, "Raw Silver Storage Blocks"); + this.addItemTag(OccultismTags.Items.TALLOW, "Tallow"); + this.addItemTag(OccultismTags.Items.METAL_AXES, "Metal Axes"); + this.addItemTag(OccultismTags.Items.MAGMA, "Magma"); + this.addItemTag(OccultismTags.Items.BOOKS, "Books"); + this.addItemTag(OccultismTags.Items.FRUITS, "Fruits"); } private void addItemTag(ResourceLocation resourceLocation, String string) { - this.add("tag.item."+resourceLocation.getNamespace()+"."+resourceLocation.getPath().replace("/","."), string); + this.add("tag.item." + resourceLocation.getNamespace() + "." + resourceLocation.getPath().replace("/", "."), string); } + private void addBlockTag(TagKey block, String string) { - this.addBlockTag(block.location(),string); + this.addBlockTag(block.location(), string); } + private void addItemTag(TagKey item, String string) { - this.addItemTag(item.location(),string); + this.addItemTag(item.location(), string); } + private void addBlockTag(ResourceLocation resourceLocation, String string) { - this.add("tag.block."+resourceLocation.getNamespace()+"."+resourceLocation.getPath().replace("/","."), string); + this.add("tag.block." + resourceLocation.getNamespace() + "." + resourceLocation.getPath().replace("/", "."), string); } private void addEmiTranslations() { - this.add("emi.category.occultism.spirit_fire","Spirit Fire"); - this.add("emi.category.occultism.crushing","Crushing"); - this.add("emi.category.occultism.miner","Dimensional Mineshaft"); - this.add("emi.category.occultism.ritual","Rituals"); + this.add("emi.category.occultism.spirit_fire", "Spirit Fire"); + this.add("emi.category.occultism.crushing", "Crushing"); + this.add("emi.category.occultism.miner", "Dimensional Mineshaft"); + this.add("emi.category.occultism.ritual", "Rituals"); this.add("emi.occultism.item_to_use", "Item to use: %s"); } @@ -3457,9 +3484,10 @@ private void addConfigurationTranslations() { this.addConfig("anyOreDivinationRod", "Divination c:ores"); } - private void addConfig(String key, String name){ + private void addConfig(String key, String name) { this.add(Occultism.MODID + ".configuration." + key, name); } + @Override protected void addTranslations() { this.addAdvancements(); diff --git a/src/main/java/com/klikli_dev/occultism/datagen/recipe/RitualRecipes.java b/src/main/java/com/klikli_dev/occultism/datagen/recipe/RitualRecipes.java index a71363db8..2eab1c354 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/recipe/RitualRecipes.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/recipe/RitualRecipes.java @@ -18,6 +18,7 @@ import net.minecraft.world.item.Items; import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Blocks; import net.neoforged.neoforge.common.Tags; @@ -64,6 +65,10 @@ private static ItemStack makeLoreSpawnEgg(Item item, String key) { return output; } + private static ItemStack makeRitualDummy(ItemLike item) { + return new ItemStack(item); + } + private static ItemStack makeRitualDummy(ResourceLocation location) { return new ItemStack(BuiltInRegistries.ITEM.get(location)); } @@ -1229,6 +1234,40 @@ private static void craftingRituals(RecipeOutput recipeOutput) { .unlockedBy("has_bound_foliot", has(OccultismItems.BOOK_OF_BINDING_BOUND_FOLIOT.get())) .save(recipeOutput, ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "ritual/craft_satchel")); + RitualRecipeBuilder.ritualRecipeBuilder(Ingredient.of(OccultismItems.BOOK_OF_BINDING_BOUND_DJINNI.get()), + new ItemStack(OccultismItems.RITUAL_SATCHEL_T1.get()), + makeRitualDummy(OccultismItems.RITUAL_DUMMY_CRAFT_RITUAL_SATCHEL_T1.get()), + 240, + RITUAL_CRAFT_WITH_SPIRIT_NAME, + PENTACLE_CRAFT_DJINNI, + Ingredient.of(Items.HOPPER), + Ingredient.of(Items.DISPENSER), + Ingredient.of(ItemTags.WOOL), + Ingredient.of(ItemTags.WOOL), + Ingredient.of(Tags.Items.LEATHERS), + Ingredient.of(Tags.Items.LEATHERS), + Ingredient.of(Tags.Items.STRINGS), + Ingredient.of(OccultismTags.Items.SILVER_INGOT)) + .unlockedBy("has_bound_djinni", has(OccultismItems.BOOK_OF_BINDING_BOUND_DJINNI.get())) + .save(recipeOutput, ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "ritual/craft_ritual_satchel_t1")); + + RitualRecipeBuilder.ritualRecipeBuilder(Ingredient.of(OccultismItems.BOOK_OF_BINDING_BOUND_AFRIT.get()), + new ItemStack(OccultismItems.RITUAL_SATCHEL_T2.get()), + makeRitualDummy(OccultismItems.RITUAL_DUMMY_CRAFT_RITUAL_SATCHEL_T2.get()), + 240, + RITUAL_CRAFT_WITH_SPIRIT_NAME, + PENTACLE_CRAFT_DJINNI, + Ingredient.of(OccultismItems.RITUAL_SATCHEL_T1.get()), + Ingredient.of(OccultismItems.AFRIT_ESSENCE.get()), + Ingredient.of(Tags.Items.ENDER_PEARLS), + Ingredient.of(Tags.Items.ENDER_PEARLS), + Ingredient.of(Tags.Items.ENDER_PEARLS), + Ingredient.of(Tags.Items.ENDER_PEARLS) + ) + .unlockedBy("has_bound_afrit", has(OccultismItems.BOOK_OF_BINDING_BOUND_AFRIT.get())) + .save(recipeOutput, ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "ritual/craft_ritual_satchel_t2")); + + RitualRecipeBuilder.ritualRecipeBuilder(Ingredient.of(OccultismItems.BOOK_OF_BINDING_BOUND_DJINNI.get()), new ItemStack(OccultismItems.SOUL_GEM_ITEM.get()), makeRitualDummy(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "ritual_dummy/craft_soul_gem")), diff --git a/src/main/java/com/klikli_dev/occultism/datagen/tags/OccultismBlockTagProvider.java b/src/main/java/com/klikli_dev/occultism/datagen/tags/OccultismBlockTagProvider.java index 401b10ce4..998b4e0f2 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/tags/OccultismBlockTagProvider.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/tags/OccultismBlockTagProvider.java @@ -118,6 +118,14 @@ protected void addTags(HolderLookup.Provider provider) { } private void addOccultismTags(HolderLookup.Provider provider) { + this.tag(OccultismTags.Blocks.PENTACLE_MATERIALS) + .addTag(Tags.Blocks.SKULLS) + .add(OccultismBlocks.GOLDEN_SACRIFICIAL_BOWL.get()) + .add(OccultismBlocks.SPIRIT_ATTUNED_CRYSTAL.get()) + .addOptionalTag(OccultismTags.Blocks.OCCULTISM_CANDLES) + .addOptionalTag(OccultismTags.Blocks.CHALK_GLYPHS) + .replace(false); + this.tag(OccultismTags.Blocks.OTHERWORLD_SAPLINGS) .add(OccultismBlocks.OTHERWORLD_SAPLING.get(), OccultismBlocks.OTHERWORLD_SAPLING_NATURAL.get()).replace(false); this.tag(OccultismTags.Blocks.OCCULTISM_CANDLES).add( @@ -139,6 +147,25 @@ private void addOccultismTags(HolderLookup.Provider provider) { OccultismBlocks.LARGE_CANDLE_MAGENTA.get(), OccultismBlocks.LARGE_CANDLE_PURPLE.get() ).replace(false); + + this.tag(OccultismTags.Blocks.CHALK_GLYPHS) + .add(OccultismBlocks.CHALK_GLYPH_WHITE.get()) + .add(OccultismBlocks.CHALK_GLYPH_GOLD.get()) + .add(OccultismBlocks.CHALK_GLYPH_PURPLE.get()) + .add(OccultismBlocks.CHALK_GLYPH_RED.get()) + .add(OccultismBlocks.CHALK_GLYPH_LIGHT_GRAY.get()) + .add(OccultismBlocks.CHALK_GLYPH_GRAY.get()) + .add(OccultismBlocks.CHALK_GLYPH_BLACK.get()) + .add(OccultismBlocks.CHALK_GLYPH_BROWN.get()) + .add(OccultismBlocks.CHALK_GLYPH_ORANGE.get()) + .add(OccultismBlocks.CHALK_GLYPH_LIME.get()) + .add(OccultismBlocks.CHALK_GLYPH_GREEN.get()) + .add(OccultismBlocks.CHALK_GLYPH_CYAN.get()) + .add(OccultismBlocks.CHALK_GLYPH_LIGHT_BLUE.get()) + .add(OccultismBlocks.CHALK_GLYPH_BLUE.get()) + .add(OccultismBlocks.CHALK_GLYPH_MAGENTA.get()) + .add(OccultismBlocks.CHALK_GLYPH_PINK.get()).replace(false); + this.tag(OccultismTags.Blocks.CAVE_WALL_BLOCKS).add(Blocks.STONE, Blocks.GRANITE, Blocks.DIORITE, Blocks.ANDESITE).replace(false); this.tag(OccultismTags.Blocks.NETHERRACK).add(Blocks.NETHERRACK).replace(false); this.tag(OccultismTags.Blocks.STORAGE_STABILIZER) diff --git a/src/main/java/com/klikli_dev/occultism/datagen/tags/OccultismItemTagProvider.java b/src/main/java/com/klikli_dev/occultism/datagen/tags/OccultismItemTagProvider.java index f82c34a34..76c85ef53 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/tags/OccultismItemTagProvider.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/tags/OccultismItemTagProvider.java @@ -80,6 +80,17 @@ private void addCuriosTags(HolderLookup.Provider provider) { } private void addOccultismTags(HolderLookup.Provider provider) { + this.tag(OccultismTags.Items.SKULLS) + .add(Items.SKELETON_SKULL) + .add(Items.WITHER_SKELETON_SKULL) + .replace(false); + + this.copy(OccultismTags.Blocks.PENTACLE_MATERIALS, OccultismTags.Items.PENTACLE_MATERIALS); + this.tag(OccultismTags.Items.PENTACLE_MATERIALS) + .addOptionalTag(OccultismTags.Items.TOOLS_CHALK) + .replace(false); + + this.tag(OccultismTags.Items.DEMONIC_PARTNER_FOOD) .addTag(ItemTags.MEAT); @@ -109,7 +120,7 @@ private void addOccultismTags(HolderLookup.Provider provider) { .addTag(OccultismTags.Items.Miners.MASTER) .addTag(OccultismTags.Items.Miners.ORES).replace(false); - this.tag(OccultismTags.Items.TOOLS_CHALKS) + this.tag(OccultismTags.Items.TOOLS_CHALK) .add(OccultismItems.CHALK_GOLD.get()) .add(OccultismItems.CHALK_WHITE.get()) .add(OccultismItems.CHALK_RED.get()) @@ -153,7 +164,7 @@ private void addMinecraftTags(HolderLookup.Provider provider) { this.tag(ItemTags.BOOKSHELF_BOOKS).add(OccultismItems.BOOK_OF_BINDING_EMPTY.get()); this.tag(ItemTags.DURABILITY_ENCHANTABLE).addTag(OccultismTags.Items.Miners.MINERS); - this.tag(ItemTags.DURABILITY_ENCHANTABLE).addTag(OccultismTags.Items.TOOLS_CHALKS); + this.tag(ItemTags.DURABILITY_ENCHANTABLE).addTag(OccultismTags.Items.TOOLS_CHALK); this.tag(ItemTags.DURABILITY_ENCHANTABLE).addTag(OccultismTags.Items.TOOLS_KNIFE); this.tag(ItemTags.SHARP_WEAPON_ENCHANTABLE).addTag(OccultismTags.Items.TOOLS_KNIFE); this.tag(ItemTags.SWORD_ENCHANTABLE).addTag(OccultismTags.Items.TOOLS_KNIFE); diff --git a/src/main/java/com/klikli_dev/occultism/handlers/ClientPlayerEventHandler.java b/src/main/java/com/klikli_dev/occultism/handlers/ClientPlayerEventHandler.java index f29fd9dd7..a0330d466 100644 --- a/src/main/java/com/klikli_dev/occultism/handlers/ClientPlayerEventHandler.java +++ b/src/main/java/com/klikli_dev/occultism/handlers/ClientPlayerEventHandler.java @@ -23,7 +23,7 @@ package com.klikli_dev.occultism.handlers; import com.klikli_dev.occultism.Occultism; -import com.klikli_dev.occultism.client.gui.storage.SatchelScreen; +import com.klikli_dev.occultism.client.gui.satchel.SatchelScreen; import com.klikli_dev.occultism.client.gui.storage.StorageRemoteGui; import com.klikli_dev.occultism.network.Networking; import com.klikli_dev.occultism.network.messages.MessageDoubleJump; diff --git a/src/main/java/com/klikli_dev/occultism/handlers/ClientSetupEventHandler.java b/src/main/java/com/klikli_dev/occultism/handlers/ClientSetupEventHandler.java index 1514bb4d7..9077d352f 100644 --- a/src/main/java/com/klikli_dev/occultism/handlers/ClientSetupEventHandler.java +++ b/src/main/java/com/klikli_dev/occultism/handlers/ClientSetupEventHandler.java @@ -24,6 +24,8 @@ import com.klikli_dev.occultism.Occultism; import com.klikli_dev.occultism.client.gui.DimensionalMineshaftScreen; +import com.klikli_dev.occultism.client.gui.satchel.RitualSatchelScreen; +import com.klikli_dev.occultism.client.gui.satchel.SatchelScreen; import com.klikli_dev.occultism.client.gui.spirit.SpiritGui; import com.klikli_dev.occultism.client.gui.spirit.SpiritTransporterGui; import com.klikli_dev.occultism.client.gui.storage.*; @@ -229,6 +231,8 @@ public static void onRegisterMenuScreens(RegisterMenuScreensEvent event) { event.register(OccultismContainers.SPIRIT_TRANSPORTER.get(), SpiritTransporterGui::new); event.register(OccultismContainers.OTHERWORLD_MINER.get(), DimensionalMineshaftScreen::new); event.register(OccultismContainers.SATCHEL.get(), SatchelScreen::new); + event.register(OccultismContainers.RITUAL_SATCHEL_T1.get(), RitualSatchelScreen::new); + event.register(OccultismContainers.RITUAL_SATCHEL_T2.get(), RitualSatchelScreen::new); } public static void onRegisterClientExtensions(RegisterClientExtensionsEvent event) { diff --git a/src/main/java/com/klikli_dev/occultism/network/Networking.java b/src/main/java/com/klikli_dev/occultism/network/Networking.java index e8a18beb3..18f0544ad 100644 --- a/src/main/java/com/klikli_dev/occultism/network/Networking.java +++ b/src/main/java/com/klikli_dev/occultism/network/Networking.java @@ -57,6 +57,8 @@ public static void register(final RegisterPayloadHandlersEvent event) { registrar.playToServer(MessageTakeItem.TYPE, MessageTakeItem.STREAM_CODEC, MessageHandler::handle); registrar.playToServer(MessageToggleFamiliarSettings.TYPE, MessageToggleFamiliarSettings.STREAM_CODEC, MessageHandler::handle); registrar.playToServer(MessageUpdateStorageSettings.TYPE, MessageUpdateStorageSettings.STREAM_CODEC, MessageHandler::handle); + registrar.playToServer(MessageSendPreviewedPentacle.TYPE, MessageSendPreviewedPentacle.STREAM_CODEC, MessageHandler::handle); + //to client registrar.playToClient(MessageBeholderAttack.TYPE, MessageBeholderAttack.STREAM_CODEC, MessageHandler::handle); registrar.playToClient(MessageFairySupport.TYPE, MessageFairySupport.STREAM_CODEC, MessageHandler::handle); diff --git a/src/main/java/com/klikli_dev/occultism/network/messages/MessageOpenSatchel.java b/src/main/java/com/klikli_dev/occultism/network/messages/MessageOpenSatchel.java index 0d269e2ba..cd01c7ec3 100644 --- a/src/main/java/com/klikli_dev/occultism/network/messages/MessageOpenSatchel.java +++ b/src/main/java/com/klikli_dev/occultism/network/messages/MessageOpenSatchel.java @@ -23,9 +23,11 @@ package com.klikli_dev.occultism.network.messages; import com.klikli_dev.occultism.Occultism; -import com.klikli_dev.occultism.common.container.storage.SatchelContainer; +import com.klikli_dev.occultism.common.container.satchel.AbstractSatchelContainer; +import com.klikli_dev.occultism.common.container.satchel.StorageSatchelContainer; import com.klikli_dev.occultism.common.item.storage.SatchelItem; import com.klikli_dev.occultism.network.IMessage; +import com.klikli_dev.occultism.registry.OccultismContainers; import com.klikli_dev.occultism.util.CuriosUtil; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; @@ -68,7 +70,7 @@ public void onServerReceived(MinecraftServer minecraftServer, ServerPlayer playe int finalSelectedSlot = selectedSlot; player.openMenu( new SimpleMenuProvider((id, playerInventory, unused) -> { - return new SatchelContainer(id, playerInventory, + return new StorageSatchelContainer(id, playerInventory, ((SatchelItem) finalBackpackStack.getItem()).getInventory(player, finalBackpackStack), finalSelectedSlot); }, backpackStack.getDisplayName()), buffer -> { diff --git a/src/main/java/com/klikli_dev/occultism/network/messages/MessageSendPreviewedPentacle.java b/src/main/java/com/klikli_dev/occultism/network/messages/MessageSendPreviewedPentacle.java new file mode 100644 index 000000000..aa99ac522 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/network/messages/MessageSendPreviewedPentacle.java @@ -0,0 +1,66 @@ +package com.klikli_dev.occultism.network.messages; + +import com.klikli_dev.occultism.network.IMessage; +import com.klikli_dev.occultism.registry.OccultismItems; +import com.klikli_dev.theurgy.Theurgy; +import net.minecraft.core.BlockPos; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.block.Rotation; +import net.neoforged.neoforge.network.codec.NeoForgeStreamCodecs; +import org.jetbrains.annotations.NotNull; + +public class MessageSendPreviewedPentacle implements IMessage { + + public static final Type TYPE = new Type<>(Theurgy.loc("send_previewed_pentacle")); + + public static final StreamCodec STREAM_CODEC = + StreamCodec.composite( + ResourceLocation.STREAM_CODEC, + m -> m.multiblock, + BlockPos.STREAM_CODEC, + m -> m.anchor, + NeoForgeStreamCodecs.enumCodec(Rotation.class), + m -> m.facing, + BlockPos.STREAM_CODEC, + m -> m.target, + MessageSendPreviewedPentacle::new + ); + + public ResourceLocation multiblock; + public BlockPos anchor; + public Rotation facing; + public BlockPos target; + + public MessageSendPreviewedPentacle(ResourceLocation multiblock, BlockPos anchor, Rotation facing, BlockPos target) { + this.multiblock = multiblock; + this.anchor = anchor; + this.facing = facing; + this.target = target; + } + + @Override + public void onServerReceived(MinecraftServer minecraftServer, ServerPlayer player) { + OccultismItems.RITUAL_SATCHEL_T1.get().setTargetPentacle(player.getUUID(), this.multiblock, this.anchor, this.facing, this.target, player.level().getGameTime()); + OccultismItems.RITUAL_SATCHEL_T2.get().setTargetPentacle(player.getUUID(), this.multiblock, this.anchor, this.facing, this.target, player.level().getGameTime()); + } + + @Override + public void encode(RegistryFriendlyByteBuf buf) { + //noop -> stream codec handles this + } + + @Override + public void decode(RegistryFriendlyByteBuf buf) { + //noop -> stream codec handles this + } + + @Override + public @NotNull Type type() { + return TYPE; + } +} diff --git a/src/main/java/com/klikli_dev/occultism/registry/OccultismContainers.java b/src/main/java/com/klikli_dev/occultism/registry/OccultismContainers.java index cbec94125..91538c820 100644 --- a/src/main/java/com/klikli_dev/occultism/registry/OccultismContainers.java +++ b/src/main/java/com/klikli_dev/occultism/registry/OccultismContainers.java @@ -27,9 +27,12 @@ import com.klikli_dev.occultism.common.blockentity.StableWormholeBlockEntity; import com.klikli_dev.occultism.common.blockentity.StorageControllerBlockEntity; import com.klikli_dev.occultism.common.container.DimensionalMineshaftContainer; +import com.klikli_dev.occultism.common.container.satchel.RitualSatchelT1Container; +import com.klikli_dev.occultism.common.container.satchel.RitualSatchelT2Container; +import com.klikli_dev.occultism.common.container.satchel.StorageSatchelContainer; import com.klikli_dev.occultism.common.container.spirit.SpiritContainer; import com.klikli_dev.occultism.common.container.spirit.SpiritTransporterContainer; -import com.klikli_dev.occultism.common.container.storage.SatchelContainer; +import com.klikli_dev.occultism.common.container.satchel.AbstractSatchelContainer; import com.klikli_dev.occultism.common.container.storage.StableWormholeContainer; import com.klikli_dev.occultism.common.container.storage.StorageControllerContainer; import com.klikli_dev.occultism.common.container.storage.StorageRemoteContainer; @@ -88,7 +91,12 @@ public class OccultismContainers { (DimensionalMineshaftBlockEntity) inv.player.level().getBlockEntity( data.readBlockPos())))); - public static final Supplier> SATCHEL = - CONTAINERS.register("satchel", () -> IMenuTypeExtension.create(SatchelContainer::createClientContainer)); + public static final Supplier> SATCHEL = + CONTAINERS.register("satchel", () -> IMenuTypeExtension.create(StorageSatchelContainer::createClientContainer)); + public static final Supplier> RITUAL_SATCHEL_T1 = + CONTAINERS.register("ritual_satchel_t1", () -> IMenuTypeExtension.create(RitualSatchelT1Container::createClientContainer)); + + public static final Supplier> RITUAL_SATCHEL_T2 = + CONTAINERS.register("ritual_satchel_t2", () -> IMenuTypeExtension.create(RitualSatchelT2Container::createClientContainer)); } diff --git a/src/main/java/com/klikli_dev/occultism/registry/OccultismItems.java b/src/main/java/com/klikli_dev/occultism/registry/OccultismItems.java index 1a88f54da..415efd258 100644 --- a/src/main/java/com/klikli_dev/occultism/registry/OccultismItems.java +++ b/src/main/java/com/klikli_dev/occultism/registry/OccultismItems.java @@ -32,6 +32,8 @@ import com.klikli_dev.occultism.common.item.storage.*; import com.klikli_dev.occultism.common.item.tool.BrushItem; import com.klikli_dev.occultism.common.item.tool.*; +import com.klikli_dev.occultism.common.item.tool.ritual_satchel.MultiBlockRitualSatchelItem; +import com.klikli_dev.occultism.common.item.tool.ritual_satchel.SingleBlockRitualSatchelItem; import com.klikli_dev.occultism.util.TextUtil; import net.minecraft.core.Direction; import net.minecraft.core.component.DataComponents; @@ -181,6 +183,21 @@ public class OccultismItems { public static final DeferredItem STORAGE_REMOTE = ITEMS.register("storage_remote", () -> new StorageRemoteItem(defaultProperties().stacksTo(1))); + + public static final DeferredItem RITUAL_SATCHEL_T1 = ITEMS.register("ritual_satchel_t1", + () -> new SingleBlockRitualSatchelItem(defaultProperties() + .stacksTo(1).rarity(Rarity.RARE) + .component(DataComponents.CONTAINER, ItemContainerContents.EMPTY) + .component(OccultismDataComponents.SPIRIT_NAME, "(Not yet known)") + )); + + public static final DeferredItem RITUAL_SATCHEL_T2 = ITEMS.register("ritual_satchel_t2", + () -> new MultiBlockRitualSatchelItem(defaultProperties() + .stacksTo(1).rarity(Rarity.RARE) + .component(DataComponents.CONTAINER, ItemContainerContents.EMPTY) + .component(OccultismDataComponents.SPIRIT_NAME, "(Not yet known)") + )); + public static final DeferredItem CHALK_WHITE = ITEMS.register("chalk_white", () -> new ChalkItem(defaultProperties().setNoRepair().durability(256), () -> OccultismBlocks.CHALK_GLYPH_WHITE.get())); @@ -487,6 +504,8 @@ public class OccultismItems { public static final DeferredItem RITUAL_DUMMY_RESURRECT_FAMILIAR = ITEMS.register("ritual_dummy/resurrect_familiar", () -> new DummyTooltipItem(defaultProperties())); public static final DeferredItem RITUAL_DUMMY_SUMMON_RANDOM_ANIMAL = ITEMS.register("ritual_dummy/summon_random_animal", () -> new DummyTooltipItem(defaultProperties())); + public static final DeferredItem RITUAL_DUMMY_CRAFT_RITUAL_SATCHEL_T1 = ITEMS.register("ritual_dummy/craft_ritual_satchel_t1", () -> new DummyTooltipItem(defaultProperties())); + public static final DeferredItem RITUAL_DUMMY_CRAFT_RITUAL_SATCHEL_T2 = ITEMS.register("ritual_dummy/craft_ritual_satchel_t2", () -> new DummyTooltipItem(defaultProperties())); //Ritual Dummy Items static { @@ -600,6 +619,8 @@ public static boolean shouldPregenerateSpiritName(Item item) { || item == BOOK_OF_CALLING_DJINNI_MANAGE_MACHINE.get() || item == DIMENSIONAL_MATRIX.get() || item == SATCHEL.get() + || item == RITUAL_SATCHEL_T1.get() + || item == RITUAL_SATCHEL_T2.get() || item == FAMILIAR_RING.get() || item == INFUSED_PICKAXE.get() || item == MINER_FOLIOT_UNSPECIALIZED.get() diff --git a/src/main/java/com/klikli_dev/occultism/registry/OccultismTags.java b/src/main/java/com/klikli_dev/occultism/registry/OccultismTags.java index 7772be6c8..b43ef6454 100644 --- a/src/main/java/com/klikli_dev/occultism/registry/OccultismTags.java +++ b/src/main/java/com/klikli_dev/occultism/registry/OccultismTags.java @@ -34,6 +34,8 @@ public class OccultismTags { public static class Blocks { + public static final TagKey PENTACLE_MATERIALS = makeBlockTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "pentacle_materials")); + // Block Tags public static final TagKey TREE_SOIL = makeBlockTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "tree_soil")); public static final TagKey CAVE_WALL_BLOCKS = makeBlockTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "cave_wall_blocks")); @@ -41,6 +43,7 @@ public static class Blocks { public static final TagKey NETHERRACK = makeBlockTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "netherrack")); public static final TagKey CANDLES = makeBlockTag(ResourceLocation.fromNamespaceAndPath("minecraft", "candles")); + public static final TagKey CHALK_GLYPHS = makeBlockTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "chalk_glyphs")); public static final TagKey IESNIUM_ORE = makeBlockTag(ResourceLocation.fromNamespaceAndPath("c", "ores/iesnium")); public static final TagKey SILVER_ORE = makeBlockTag(ResourceLocation.fromNamespaceAndPath("c", "ores/silver")); // Storage Bock Tags @@ -57,6 +60,9 @@ public static class Blocks { public static class Items { + public static final TagKey PENTACLE_MATERIALS = makeItemTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "pentacle_materials")); + public static final TagKey SKULLS = makeItemTag(ResourceLocation.fromNamespaceAndPath("c", "skulls")); + public static final TagKey DEMONIC_PARTNER_FOOD = makeItemTag(ResourceLocation.fromNamespaceAndPath("occultism", "demonic_partner_food")); public static final TagKey IESNIUM_ORE = makeItemTag(ResourceLocation.fromNamespaceAndPath("c", "ores/iesnium")); @@ -121,7 +127,7 @@ public static class Miners { public static final TagKey ORES = makeItemTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "miners/ores")); } - public static final TagKey TOOLS_CHALKS = makeItemTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "tools/chalks")); + public static final TagKey TOOLS_CHALK = makeItemTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "tools/chalk")); public static final TagKey OTHERWORLD_LOGS = makeItemTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "otherworld_logs")); public static final TagKey OTHERSTONE = makeItemTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "otherstone")); public static final TagKey OTHERCOBBLESTONE = makeItemTag(ResourceLocation.fromNamespaceAndPath(Occultism.MODID, "othercobblestone")); diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 34587ae22..8c9f0ffff 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -11,4 +11,5 @@ public net.minecraft.world.entity.LivingEntity getCurrentSwingDuration()I # getC public-f net.minecraft.world.level.block.TorchBlock flameParticle public net.minecraft.world.item.crafting.AbstractCookingRecipe ingredient public-f net.minecraft.world.level.block.entity.BlockEntityType validBlocks -public net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl connection # for jei - otherwise jei causes a startup crash \ No newline at end of file +public net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl connection # for jei - otherwise jei causes a startup crash +public net.minecraft.world.item.context.UseOnContext getHitResult()Lnet/minecraft/world/phys/BlockHitResult; # getHitResult \ No newline at end of file diff --git a/src/main/resources/assets/occultism/textures/gui/inventory_ritual_satchel.png b/src/main/resources/assets/occultism/textures/gui/inventory_ritual_satchel.png new file mode 100644 index 000000000..b1df1e48e Binary files /dev/null and b/src/main/resources/assets/occultism/textures/gui/inventory_ritual_satchel.png differ diff --git a/src/main/resources/assets/occultism/textures/item/auto_chalk.png b/src/main/resources/assets/occultism/textures/item/auto_chalk.png new file mode 100644 index 000000000..0a2cb5e1d Binary files /dev/null and b/src/main/resources/assets/occultism/textures/item/auto_chalk.png differ diff --git a/src/main/resources/assets/occultism/textures/item/full_pentacle_auto_chalk.png b/src/main/resources/assets/occultism/textures/item/full_pentacle_auto_chalk.png new file mode 100644 index 000000000..04b663322 Binary files /dev/null and b/src/main/resources/assets/occultism/textures/item/full_pentacle_auto_chalk.png differ diff --git a/src/main/resources/assets/occultism/textures/item/ritual_satchel_t1.png b/src/main/resources/assets/occultism/textures/item/ritual_satchel_t1.png new file mode 100644 index 000000000..6769dfae8 Binary files /dev/null and b/src/main/resources/assets/occultism/textures/item/ritual_satchel_t1.png differ diff --git a/src/main/resources/assets/occultism/textures/item/ritual_satchel_t2.png b/src/main/resources/assets/occultism/textures/item/ritual_satchel_t2.png new file mode 100644 index 000000000..9e83b76b9 Binary files /dev/null and b/src/main/resources/assets/occultism/textures/item/ritual_satchel_t2.png differ