From de5682a96049d50adccbead18002addb0465b0a8 Mon Sep 17 00:00:00 2001 From: WinDanesz <31292708+windanesz@users.noreply.github.com> Date: Tue, 30 Dec 2025 18:35:35 +0100 Subject: [PATCH] Add colorized bookmarks based on book element, requires spells to be discovered. It can be turned off in the Client settings. Another tweak setting can make it depend on the Archivist's Eyeglass artefact --- .../electroblob/wizardry/CommonProxy.java | 4 ++ .../java/electroblob/wizardry/Settings.java | 19 ++++++ .../java/electroblob/wizardry/Wizardry.java | 2 + .../wizardry/client/ClientProxy.java | 64 +++++++++++++++++- .../client/WizardryClientEventHandler.java | 14 +++- .../assets/ebwizardry/lang/en_us.lang | 5 ++ .../ebwizardry/models/item/spell_book.json | 11 +-- .../models/item/spell_book_discovered.json | 7 ++ .../models/item/spell_book_undiscovered.json | 6 ++ .../textures/items/spell_book_overlay.png | Bin 0 -> 157 bytes 10 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 src/main/resources/assets/ebwizardry/models/item/spell_book_discovered.json create mode 100644 src/main/resources/assets/ebwizardry/models/item/spell_book_undiscovered.json create mode 100644 src/main/resources/assets/ebwizardry/textures/items/spell_book_overlay.png diff --git a/src/main/java/electroblob/wizardry/CommonProxy.java b/src/main/java/electroblob/wizardry/CommonProxy.java index 9220e64f..e13fcc28 100644 --- a/src/main/java/electroblob/wizardry/CommonProxy.java +++ b/src/main/java/electroblob/wizardry/CommonProxy.java @@ -43,6 +43,10 @@ public class CommonProxy { public void registerRenderers(){} + public void registerItemColorHandlers(){} + + public void registerModelProperties(){} + public void initialiseLayers(){} public void initialiseAnimations(){} diff --git a/src/main/java/electroblob/wizardry/Settings.java b/src/main/java/electroblob/wizardry/Settings.java index ffa84f2a..8b075bd5 100644 --- a/src/main/java/electroblob/wizardry/Settings.java +++ b/src/main/java/electroblob/wizardry/Settings.java @@ -355,6 +355,8 @@ public final class Settings { * velocity-based one. */ public boolean replaceVanillaFallDamage = true; + /** [Synchronised] Whether spell book colors are only shown when the player has the Archivist's Eyeglass equipped. */ + public boolean spellBookColorsRequireArchivistsEyeglass = false; /** [Synchronised] Chance of 'misreading' an undiscovered spell and triggering a forfeit instead. */ public double forfeitChance = 0.2; /** [Synchronised] Progression requirements for upgrading a wand to each tier. */ @@ -461,6 +463,8 @@ public final class Settings { public static final String DEFAULT_HUD_SKIN_KEY = "default"; // Defined here so it's not in a client-only class. /** [Client-only] The string identifier of the skin used for the spell HUD. */ public String spellHUDSkin = DEFAULT_HUD_SKIN_KEY; + /** [Client-only] Whether to show elemental colors on spell books for discovered spells. */ + public boolean spellBookColors = true; /** Set of constants for each of the eight positions that the spell HUD can be in. */ public enum GuiPosition { @@ -1103,6 +1107,13 @@ public final class Settings { replaceVanillaFallDamage = property.getBoolean(); propOrder.add(property.getName()); + property = config.get(TWEAKS_CATEGORY, "spellBookColorsRequireArchivistsEyeglass", false, + "If true, spell book colors are only shown when the player has the charm of spell discovery equipped."); + property.setLanguageKey("config." + Wizardry.MODID + ".spell_book_colors_require_charm"); + Wizardry.proxy.setToNamedBooleanEntry(property); + spellBookColorsRequireArchivistsEyeglass = property.getBoolean(); + propOrder.add(property.getName()); + property = config.get(TWEAKS_CATEGORY, "blindnessTweak", true, "Whether to tweak the blindness effect to reduce follow distance when used on non-players. This automatically disables itself in favour of Potion Core's implementation if installed."); property.setLanguageKey("config." + Wizardry.MODID + ".blindness_tweak"); @@ -1487,6 +1498,14 @@ public final class Settings { Wizardry.proxy.setToNamedBooleanEntry(property); showChargeMeter = property.getBoolean(); propOrder.add(property.getName()); + + property = config.get(CLIENT_CATEGORY, "spellBookColors", true, "Whether to show elemental colors on spell books for discovered spells."); + property.setLanguageKey("config." + Wizardry.MODID + ".spell_book_colors"); + property.setRequiresWorldRestart(false); + Wizardry.proxy.setToNamedBooleanEntry(property); + spellBookColors = property.getBoolean(); + propOrder.add(property.getName()); + property = config.get(CLIENT_CATEGORY, "loadHandbook", true, "Whether to initialise the in-game handbook. Setting this to false will brick the in-game handbook, but it might help if you have startup crashes."); property.setLanguageKey("config." + Wizardry.MODID + ".load_handbook"); property.setRequiresWorldRestart(false); diff --git a/src/main/java/electroblob/wizardry/Wizardry.java b/src/main/java/electroblob/wizardry/Wizardry.java index 41279087..c7497ceb 100644 --- a/src/main/java/electroblob/wizardry/Wizardry.java +++ b/src/main/java/electroblob/wizardry/Wizardry.java @@ -198,6 +198,8 @@ public class Wizardry { // Client-side stuff (via proxies) proxy.initGuiBits(); proxy.registerParticles(); + proxy.registerItemColorHandlers(); + proxy.registerModelProperties(); proxy.registerSoundEventListener(); } diff --git a/src/main/java/electroblob/wizardry/client/ClientProxy.java b/src/main/java/electroblob/wizardry/client/ClientProxy.java index 7e9545dd..4915fe45 100644 --- a/src/main/java/electroblob/wizardry/client/ClientProxy.java +++ b/src/main/java/electroblob/wizardry/client/ClientProxy.java @@ -1,7 +1,6 @@ package electroblob.wizardry.client; import electroblob.wizardry.CommonProxy; -import electroblob.wizardry.Settings; import electroblob.wizardry.Wizardry; import electroblob.wizardry.block.BlockBookshelf; import electroblob.wizardry.client.animation.ActionAnimation; @@ -19,6 +18,8 @@ import electroblob.wizardry.client.model.ModelRobeArmour; import electroblob.wizardry.client.model.ModelSageArmour; import electroblob.wizardry.client.model.ModelWizardArmour; import electroblob.wizardry.client.particle.*; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.client.particle.ParticleWizardry.IWizardryParticleFactory; import electroblob.wizardry.client.renderer.RenderSpectralGolem; import electroblob.wizardry.client.renderer.entity.*; @@ -38,6 +39,7 @@ import electroblob.wizardry.entity.projectile.*; import electroblob.wizardry.event.SpellCastEvent; import electroblob.wizardry.event.SpellCastEvent.Source; import electroblob.wizardry.integration.antiqueatlas.WizardryAntiqueAtlasIntegration; +import electroblob.wizardry.item.ItemArtefact; import electroblob.wizardry.item.ItemScroll; import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.item.ItemWand; @@ -877,4 +879,64 @@ public class ClientProxy extends CommonProxy { ClientRegistry.bindTileEntitySpecialRenderer(TileEntityImbuementAltar.class, new RenderImbuementAltar()); } + + public void registerItemColorHandlers() { + Minecraft.getMinecraft().getItemColors().registerItemColorHandler((stack, tintIndex) -> { + if (Wizardry.settings.spellBookColors && tintIndex == 1) { // layer 1 is the overlay + Spell spell = Spell.byMetadata(stack.getMetadata()); + + if (shouldDisplayDiscovered(spell, stack)) { + // Even if the spell is discovered, the charm might be required for colouration + if(Wizardry.settings.spellBookColorsRequireArchivistsEyeglass && !ItemArtefact.isArtefactActive(getThePlayer(), WizardryItems.charm_spell_discovery)) { + return -1; + } + + Element element = spell.getElement(); + if (element != null) { + switch (element) { + case MAGIC: + return 0xAAAAAA; // GRAY + case FIRE: + return 0xAA0000; // DARK_RED + case ICE: + return 0x55FFFF; // AQUA + case LIGHTNING: + return 0x00AAAA; // DARK_AQUA + case NECROMANCY: + return 0xAA00AA; // DARK_PURPLE + case EARTH: + return 0x00AA00; // DARK_GREEN + case SORCERY: + return 0x55FF55; // GREEN + case HEALING: + return 0xFFFF55; // YELLOW + } + } + } + } + return -1; + }, WizardryItems.spell_book); + } + + public void registerModelProperties() { + Item spellBook = WizardryItems.spell_book; + ResourceLocation discoveredProperty = new ResourceLocation(Wizardry.MODID, "discovered"); + + spellBook.addPropertyOverride(discoveredProperty, (stack, world, entity) -> { + if (!Wizardry.settings.spellBookColors) return 0.0f; + + boolean discovered = shouldDisplayDiscovered(Spell.byMetadata(stack.getMetadata()), stack); + + if(discovered && Wizardry.settings.spellBookColorsRequireArchivistsEyeglass){ + // Entity can be null so we have to check + if(entity instanceof EntityPlayer){ + return ItemArtefact.isArtefactActive((EntityPlayer)entity, WizardryItems.charm_spell_discovery) ? 1.0f : 0.0f; + } + // If there's no entity, there's no charm, so no colour + return 0.0f; + } + + return discovered ? 1.0f : 0.0f; + }); + } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java b/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java index 258c15be..6b899c6d 100644 --- a/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java +++ b/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java @@ -1,5 +1,6 @@ package electroblob.wizardry.client; +import electroblob.wizardry.Wizardry; import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect; import electroblob.wizardry.data.DispenserCastingData; import electroblob.wizardry.data.SpellEmitterData; @@ -13,7 +14,6 @@ import electroblob.wizardry.spell.SixthSense; import electroblob.wizardry.spell.SlowTime; import electroblob.wizardry.spell.Transience; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.BufferBuilder; @@ -31,6 +31,9 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.relauncher.Side; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; import org.lwjgl.opengl.GL11; import java.util.ArrayList; @@ -196,6 +199,15 @@ public final class WizardryClientEventHandler { } } + @SubscribeEvent + public static void onItemTooltip(ItemTooltipEvent event) { + if (event.getItemStack().getItem() == WizardryItems.charm_spell_discovery) { + if (Wizardry.settings.spellBookColorsRequireArchivistsEyeglass) { + event.getToolTip().add(TextFormatting.GRAY + I18n.format("item.ebwizardry:charm_spell_discovery.desc.color")); + } + } + } + /** * Renders an overlay across the entire screen. * @param resolution The screen resolution diff --git a/src/main/resources/assets/ebwizardry/lang/en_us.lang b/src/main/resources/assets/ebwizardry/lang/en_us.lang index cd93fd80..ecf9d1f8 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_us.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_us.lang @@ -524,6 +524,7 @@ item.ebwizardry\:charm_move_speed.name=Icarus Medallion item.ebwizardry\:charm_move_speed.desc=Move at near-full speed when casting spells item.ebwizardry\:charm_spell_discovery.name=Archivist's Eyeglass item.ebwizardry\:charm_spell_discovery.desc=Spell books found in chests are much more likely to be ones you have not yet discovered +item.ebwizardry\:charm_spell_discovery.desc.color=When equipped, you can see the element of a known spell book by the color of its bookmark item.ebwizardry\:charm_auto_smelt.name=Metallurgist's Mark item.ebwizardry\:charm_auto_smelt.desc=Pocket furnace triggers automatically when bound to a wand on your hotbar item.ebwizardry\:charm_lava_walking.name=Nether Ice Core @@ -1692,6 +1693,10 @@ config.ebwizardry.replace_vanilla_fall_damage=Replace Vanilla Fall Damage config.ebwizardry.replace_vanilla_fall_damage.tooltip=Whether to replace Minecraft's distance-based fall damage calculation with an equivalent, velocity-based one. This is done such that mobs in freefall will take exactly the same damage as normal, so it will not break falling-based mob farms. Disable this if you experience falling-related weirdness! If this is disabled, some spells revert to a more simplistic method of resetting the player's fall damage in certain cases. config.ebwizardry.replace_vanilla_fall_damage.true=Yes - it's parkour time config.ebwizardry.replace_vanilla_fall_damage.false=No - break my legs normally +config.ebwizardry.spell_book_colors_require_charm=Spell Book Colors Require Archivist's Eyeglass +config.ebwizardry.spell_book_colors_require_charm.tooltip=Whether to require the Archivist's Eyeglass charm artifact to see colored spell book bookmarks. +config.ebwizardry.spell_book_colors_require_charm.true=Yes - I want to see the colours only if the charm is worn +config.ebwizardry.spell_book_colors_require_charm.false=No - I want to see the colours all the time config.ebwizardry.blindness_tweak=Blindness Tweak config.ebwizardry.blindness_tweak.tooltip=Whether to tweak the blindness effect to reduce follow distance when used on non-players. This automatically disables itself in favour of Potion Core's implementation if installed. config.ebwizardry.mob_loot_table_whitelist=Mob Loot Table Whitelist diff --git a/src/main/resources/assets/ebwizardry/models/item/spell_book.json b/src/main/resources/assets/ebwizardry/models/item/spell_book.json index b5941b77..7ad16e32 100644 --- a/src/main/resources/assets/ebwizardry/models/item/spell_book.json +++ b/src/main/resources/assets/ebwizardry/models/item/spell_book.json @@ -1,14 +1,17 @@ { - "parent": "item/generated", - "textures": { - "layer0": "ebwizardry:items/spell_book" - }, + "parent": "ebwizardry:item/spell_book_undiscovered", "overrides": [ { "predicate": { "festive": 1 }, "model": "ebwizardry:item/festive_spell_book" + }, + { + "predicate": { + "ebwizardry:discovered": 1 + }, + "model": "ebwizardry:item/spell_book_discovered" } ] } \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/item/spell_book_discovered.json b/src/main/resources/assets/ebwizardry/models/item/spell_book_discovered.json new file mode 100644 index 00000000..065ae4d8 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spell_book_discovered.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/spell_book", + "layer1": "ebwizardry:items/spell_book_overlay" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spell_book_undiscovered.json b/src/main/resources/assets/ebwizardry/models/item/spell_book_undiscovered.json new file mode 100644 index 00000000..834e5195 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spell_book_undiscovered.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "ebwizardry:items/spell_book" + } +} diff --git a/src/main/resources/assets/ebwizardry/textures/items/spell_book_overlay.png b/src/main/resources/assets/ebwizardry/textures/items/spell_book_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..54b4e48c54bf2b5be3817bb94044feb2d1c92293 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYz7>k44ofvPP)Tw7+VBjq9 zh%9Dc;1&j9Muu5)BtU`zJ|V6Q3=Ahvp1gYX>g|GD2L=WP=8_=4V21zyT>`EtGB7a6 zdAc};RLn_EVPJAg;+$sh;PlyQLWB^r3X5HW1|vh}O%_2_wN@4e1_lOCS3j3^P6