Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 49 additions & 12 deletions src/main/java/net/tfminecraft/magic/artifact/ArtifactLore.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import net.tfminecraft.magic.artifact.sacrifice.SacrificeImprintStore;
import net.tfminecraft.magic.artifact.sacrifice.SacrificeRegistry;
import net.tfminecraft.magic.model.ElementDef;
import net.tfminecraft.magic.model.ElementVisibility;
import net.tfminecraft.magic.registry.ElementRegistry;
import net.tfminecraft.magic.util.MagicNumbers;
import net.tfminecraft.magic.util.MagicText;
Expand Down Expand Up @@ -54,13 +55,12 @@ public static void apply(ItemStack stack) {
double cap = artifact.getCap(element.getId());
double fill = artifact.getFill(element.getId());
double shown = ArtifactCareStore.usableFill(fill, cap, muffle);
block.add(MagicText.format(
element.getColor()
+ element.getName()
+ " {color:label_muted}"
+ formatAmount(shown)
+ " / "
+ formatAmount(cap)));
block.add(MagicText.elementName(element)
+ MagicText.format(
" {color:label_muted}"
+ formatAmount(shown)
+ " / "
+ formatAmount(cap)));
}
int attuneOffset = block.size();
List<String> attuneLines = buildAttuneLines(stack, artifact);
Expand Down Expand Up @@ -270,8 +270,8 @@ private static ElementDef matchElement(String before) {
ElementDef best = null;
int bestLen = 0;
for (ElementDef element : ElementRegistry.getAll()) {
String name = plain(element.getName()).toLowerCase(Locale.ROOT);
if (name.isEmpty() || !lower.startsWith(name)) {
String name = loreName(element);
if (!auraLabel(lower, name)) {
continue;
}
if (name.length() > bestLen) {
Expand Down Expand Up @@ -424,14 +424,50 @@ private static boolean isFillLine(String line) {
}
String before = p.substring(0, slash).trim().toLowerCase(Locale.ROOT);
for (ElementDef element : ElementRegistry.getAll()) {
String name = plain(element.getName()).toLowerCase(Locale.ROOT);
if (!name.isEmpty() && before.startsWith(name)) {
String name = loreName(element);
if (auraLabel(before, name)) {
return true;
}
}
return false;
}

/**
* True when {@code before} is the element label followed only by its amount.
* A short id such as {@code fire} must not match {@code fire resistance 5}.
*/
private static boolean auraLabel(String before, String name) {
if (before == null || name == null || name.isEmpty() || !before.startsWith(name)) {
return false;
}
String rest = before.substring(name.length()).trim();
if (rest.isEmpty()) {
return false;
}
boolean digit = false;
for (int i = 0; i < rest.length(); i++) {
char c = rest.charAt(i);
if (Character.isDigit(c)) {
digit = true;
continue;
}
if (c == '.' && digit) {
continue;
}
return false;
}
return digit;
}

/** Same label {@link MagicText#elementName} writes, so a blank name still matches its id. */
private static String loreName(ElementDef element) {
String name = plain(element.getName()).toLowerCase(Locale.ROOT);
if (!name.isEmpty()) {
return name;
}
return element.getId() == null ? "" : element.getId().toLowerCase(Locale.ROOT);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

// Keep the existing legacy text representation, formatting, and exact-string comparisons.
@SuppressWarnings("deprecation")
private static String plain(String line) {
Expand All @@ -455,7 +491,8 @@ private static List<ElementDef> orderedAuraElements(ItemStack stack, Artifact ar
String primary = primaryId(stack, artifact);
List<ElementDef> listed = new ArrayList<>();
for (ElementDef element : ElementRegistry.getAll()) {
if (artifact.getCap(element.getId()) > 0) {
if (artifact.getCap(element.getId()) > 0
&& ElementVisibility.shownOnArtifact(element.getId(), primary)) {
listed.add(element);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import net.tfminecraft.magic.artifact.generate.ArtifactAuraSlot;
import net.tfminecraft.magic.artifact.generate.ArtifactItemBuilder;
import net.tfminecraft.magic.artifact.generate.ArtifactRoll;
import net.tfminecraft.magic.model.ElementVisibility;
import net.tfminecraft.magic.util.MagicNumbers;

public final class ArtifactCreateSession {
Expand Down Expand Up @@ -121,6 +122,10 @@ public boolean cycleElement(String elementId) {
}
ElementRole role = roleOf(elementId);
if (role == ElementRole.OFF) {
if (primaryId != null && !primaryId.isBlank()
&& !ElementVisibility.shownOnArtifact(elementId, primaryId)) {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return false;
}
if (!ArtifactAffinityRegistry.compatibleWith(caps.keySet(), elementId)) {
return false;
}
Expand Down Expand Up @@ -181,6 +186,9 @@ public ArtifactRoll toRoll() {
if (primaryId.equals(entry.getKey()) || entry.getValue() == null || entry.getValue() <= 0) {
continue;
}
if (!ElementVisibility.shownOnArtifact(entry.getKey(), primaryId)) {
continue;
}
slots.add(new ArtifactAuraSlot(entry.getKey(), entry.getValue()));
}
return ArtifactRoll.ok(primaryId, rarityId, slots);
Expand Down Expand Up @@ -240,6 +248,14 @@ private void assignPrimary(String next) {
primaryId = next;
if (next != null) {
clampCapsToRarity();
if (next.equals(primaryId)) {
for (String elementId : new ArrayList<>(caps.keySet())) {
if (!elementId.equals(next)
&& !ElementVisibility.shownOnArtifact(elementId, next)) {
setCap(elementId, 0);
}
}
}
}
clearPreviewLock();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import net.tfminecraft.magic.artifact.config.ArtifactTypeRegistry;
import net.tfminecraft.magic.artifact.config.CapRange;
import net.tfminecraft.magic.artifact.path.ArtifactPathSpec;
import net.tfminecraft.magic.model.ElementVisibility;
import net.tfminecraft.magic.util.MagicNumbers;

public final class ArtifactRoller {
Expand Down Expand Up @@ -68,6 +69,9 @@ public ArtifactRoll roll(String primaryId, String rarityId) {
if (companion == null || !companion.isEnabled() || !companion.hasRarity(rarity.getId())) {
continue;
}
if (!ElementVisibility.shownOnArtifact(companion.getElementId(), type.getElementId())) {
continue;
}
pool.add(companion);
}

Expand Down Expand Up @@ -139,6 +143,9 @@ private ArtifactRoll rollLockedPrimary(ArtifactPathSpec spec) {
if (companion == null || !companion.isEnabled() || !companion.hasRarity(rarity.getId())) {
continue;
}
if (!ElementVisibility.shownOnArtifact(companion.getElementId(), type.getElementId())) {
continue;
}
if (!ArtifactAffinityRegistry.compatibleWith(slotIds(slots), companion.getElementId())) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,8 @@ public static AdminStart startAdmin(Player player, String elementId, double amou
continue;
}
sawArtifact = true;
// Admin fill names the element outright, so a charge can take on one the
// shrine would never score. This is the only way to reach the elements
// that have scenery charging disabled.
// Admin fill names the element outright. Schools players cannot charge
// are refused here, the same as a shrine imprint.
if (artifact instanceof Charge charge && charge.getCap(id) <= 0
&& charge.imprintElement(item, id)) {
charge.write(item);
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/net/tfminecraft/magic/charge/Charge.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import net.tfminecraft.magic.artifact.aura.VesselKind;
import net.tfminecraft.magic.artifact.shrine.ShrineScore;
import net.tfminecraft.magic.artifact.shrine.ShrineElementScore;
import net.tfminecraft.magic.model.ElementVisibility;

/**
* Crafting consumable that gathers aura at a shrine and is spent at the mage station.
Expand Down Expand Up @@ -87,7 +88,7 @@ public boolean isBlank() {
}

/**
* Takes on every element the shrine scores, capped at this charge's tier.
* Takes on every playable element the shrine scores, capped at this charge's tier.
*
* @return true when at least one element was imprinted
*/
Expand All @@ -107,6 +108,9 @@ public boolean imprint(ItemStack stack, ShrineScore score) {
if (elementScore == null || elementScore.getMaxAura() <= 0) {
continue;
}
if (!ElementVisibility.shownOnCharge(entry.getKey())) {
continue;
}
setCap(entry.getKey(), cap);
any = true;
if (elementScore.getMaxAura() > bestScore) {
Expand All @@ -130,6 +134,9 @@ public boolean imprintElement(ItemStack stack, String elementId) {
if (stack == null || elementId == null || elementId.isBlank() || cap <= 0) {
return false;
}
if (!ElementVisibility.shownOnCharge(elementId)) {
return false;
}
setCap(elementId, cap);
stampTier(stack);
if (primary.isBlank()) {
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/net/tfminecraft/magic/charge/ChargeLore.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import net.tfminecraft.magic.Cache;
import net.tfminecraft.magic.model.ElementDef;
import net.tfminecraft.magic.model.ElementVisibility;
import net.tfminecraft.magic.registry.ElementRegistry;
import net.tfminecraft.magic.util.MagicText;

Expand Down Expand Up @@ -54,8 +55,8 @@ public static void apply(ItemStack stack) {
String numeral = TierBands.numeralFor(element.getId(), charge.getFill(element.getId()));
// An imprinted element below the first band still lists, so the player can
// see which elements the charge took on before it has gathered anything.
block.add(MagicText.format(element.getColor() + element.getName()
+ " {color:label_muted}" + (numeral.isEmpty() ? "-" : numeral)));
block.add(MagicText.elementName(element)
+ MagicText.format(" {color:label_muted}" + (numeral.isEmpty() ? "-" : numeral)));
}
}
block.set(0, BEGIN + block.get(0));
Expand All @@ -71,7 +72,7 @@ private static List<ElementDef> orderedElements(Charge charge) {
String primary = charge.primaryElementId();
List<ElementDef> listed = new ArrayList<>();
for (ElementDef element : ElementRegistry.getAll()) {
if (charge.getCap(element.getId()) > 0) {
if (charge.getCap(element.getId()) > 0 && ElementVisibility.shownOnCharge(element.getId())) {
listed.add(element);
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/net/tfminecraft/magic/gear/WeaponLore.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import net.tfminecraft.magic.charge.TierBands;
import net.tfminecraft.magic.model.ElementDef;
import net.tfminecraft.magic.model.ElementVisibility;
import net.tfminecraft.magic.registry.ElementRegistry;
import net.tfminecraft.magic.util.MagicText;

Expand Down Expand Up @@ -44,13 +45,16 @@ public static void apply(ItemStack stack) {
} else {
block.add(MagicText.format("{color:label_muted}Resonance"));
for (ElementDef element : ElementRegistry.getAll()) {
if (!ElementVisibility.shownOnCharge(element.getId())) {
continue;
}
double fill = requirement.aura().getFill(element.getId());
if (requirement.aura().getCap(element.getId()) <= 0 && fill <= 0) {
continue;
}
String numeral = TierBands.numeralFor(element.getId(), fill);
block.add(MagicText.format(element.getColor() + element.getName()
+ " {color:label_muted}" + (numeral.isEmpty() ? "-" : numeral)));
block.add(MagicText.elementName(element)
+ MagicText.format(" {color:label_muted}" + (numeral.isEmpty() ? "-" : numeral)));
}
}
int rift = WeaponRift.get(stack);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import net.tfminecraft.magic.artifact.aura.AuraData;
import net.tfminecraft.magic.charge.Charge;
import net.tfminecraft.magic.charge.TierBands;
import net.tfminecraft.magic.model.ElementVisibility;

public final class WeaponRequirement {

Expand Down Expand Up @@ -64,6 +65,9 @@ public void mergeAmounts(Map<String, Double> amounts) {
continue;
}
String elementId = entry.getKey();
if (!ElementVisibility.shownOnCharge(elementId)) {
continue;
}
double next = Math.max(aura.getFill(elementId), incoming);
if (aura.getCap(elementId) < next) {
aura.setCap(elementId, next);
Expand Down
53 changes: 50 additions & 3 deletions src/main/java/net/tfminecraft/magic/model/ElementDef.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package net.tfminecraft.magic.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

import org.bukkit.configuration.ConfigurationSection;

import net.tfminecraft.magic.Cache;
import net.tfminecraft.magic.modifier.KeyframeCurve;

public final class ElementDef {

private static final Pattern HEX = Pattern.compile("#?[0-9a-fA-F]{6}");

private final String id;
private final String name;
private final String icon;
private final String color;
private final List<String> colors;
private final int slot;
private final double maxResonance;
private final Double decayPerHourOverride;
Expand All @@ -21,7 +29,7 @@ public ElementDef(String id, ConfigurationSection config) {
this.id = id;
this.name = config.getString("name", id);
this.icon = config.getString("icon", "v.BARRIER");
this.color = config.getString("color", "#ffffff");
this.colors = readColors(config);
this.slot = config.getInt("slot", -1);
this.maxResonance = Math.max(1.0, config.getDouble("max_resonance", 100.0));
this.decayPerHourOverride = config.contains("decay_per_hour")
Expand All @@ -47,8 +55,14 @@ public String getIcon() {
return icon;
}

/** First colour stop, {@code #rrggbb}. Used for particles and single-colour text. */
public String getColor() {
return color;
return colors.get(0);
}

/** Colour stops in config order. One stop is a solid colour. Several form a gradient. */
public List<String> getColors() {
return colors;
}

public double getMaxResonance() {
Expand All @@ -70,4 +84,37 @@ public int getSlot() {
public KeyframeCurve getResonanceCurve() {
return resonance;
}

/**
* {@code color} is either one {@code #rrggbb} or a list of stops. Reading the list
* with {@code getString} would stringify it to {@code [#rrggbb]} and print the brackets.
*/
private static List<String> readColors(ConfigurationSection config) {
List<String> parsed = new ArrayList<>();
if (config.isList("color")) {
for (String entry : config.getStringList("color")) {
addColor(parsed, entry);
}
} else {
addColor(parsed, config.getString("color"));
}
if (parsed.isEmpty()) {
parsed.add("#ffffff");
}
return Collections.unmodifiableList(parsed);
}

private static void addColor(List<String> parsed, String raw) {
if (raw == null) {
return;
}
String token = raw.trim();
if (!HEX.matcher(token).matches()) {
return;
}
if (!token.startsWith("#")) {
token = "#" + token;
}
parsed.add(token.toLowerCase(Locale.ROOT));
}
}
Loading