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