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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions src/main/java/toniarts/openkeeper/utils/TextParameter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright (C) 2014-2026 OpenKeeper
*
* OpenKeeper is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/
package toniarts.openkeeper.utils;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
* Parameters embedded in Dungeon Keeper text resources.
* <p>
* The numeric IDs are part of the original text-resource format and must not
* be replaced with enum ordinals.
*/
public enum TextParameter {

NAME(1),
COST(2),
SPELL_LEVEL(3),
CLAIMED_LAND_MANA(4),
MANA_SOURCES(5),
TEMPLE_PRAYERS(6),
IMP_UPKEEP(7),
TRAP_UPKEEP(8),
SPELL_MANA_USAGE(9),
DUNGEON_HEART_HEALTH(10),
PAYDAY_COST(11),
IDLE_CREATURE_COUNT(12),
CLAIMED_LAND_MANA_GAIN(13),
MANA_SOURCE_GAIN(14),
TEMPLE_PRAYER_GAIN(15),
IMP_UPKEEP_LOSS(16),
TRAP_OR_DOOR_COST(17),
SPELL_MANA_COST(18),
CURRENT_DUNGEON_HEART_HEALTH(19),
CURRENT_PAYDAY_COST(20),
ROOM_COST(21),
ROOM_SIZE_HINT(22),
HORNY_TALISMAN_MANA_COST(23),
SPECIAL_COUNT(24),
MANA_USAGE(25),
MANA_COST_TO_FIRE(26),
CREATURE_DESCRIPTION(27),
CREATURE_FIGHT_STYLE(28),
CREATURE_INSTANCE_NAME(29),
CREATURE_NAME(30),
CREATURE_ACTIVITY(31),
CREATURE_STATUS(32),
CREATURE_MOOD(33),
CREATURE_BLOOD_TYPE(34),
CREATURE_PAY(35),
CREATURE_GOLD(36),
HEALTH_PERCENTAGE(37),
ROOM_USED_CAPACITY(38),
ROOM_MAX_CAPACITY(39),
DUNGEON_HEART_MANA(40),
DUNGEON_HEART_MAX_MANA(41),
ATTRACTED_CREATURE_COUNT(42),
PORTAL_CREATURE_CAPACITY(43),
PORTAL_COUNT(44),
LAIR_COUNT(45),
HATCHERY_COUNT(46),
TREASURY_COUNT(47),
LIBRARY_COUNT(48),
TRAINING_ROOM_COUNT(49),
WORKSHOP_COUNT(50),
GUARD_ROOM_COUNT(51),
PATROL_ROUTE_COUNT(52),
COMBAT_PIT_COUNT(53),
TORTURE_CHAMBER_COUNT(54),
SKELETON_COUNT(55),
MAX_SKELETON_COUNT(56),
PRISON_STATUS(57),
PRISON_COUNT(58),
VAMPIRE_COUNT(59),
MAX_VAMPIRE_COUNT(60),
GRAVEYARD_COUNT(61),
TEMPLE_COUNT(62),
CASINO_COUNT(63),
ROOM_NAME(64),
ROOM_USER_COUNT(65),
MANA_GAIN(66),
GOLD(67),
ENTITY_NAME(68),
WORKSHOP_ITEM_NUMBER(69),
WORKSHOP_QUEUE_SIZE(70),
TRAP_TRIGGER_STATE(71),
STATE(72),
ENTITY_GOLD(73),
CREATURE_EFFICIENCY(74),
TREASURY_GOLD(75),
TREASURY_MAX_GOLD(76),
LIBRARY_RESEARCHER_COUNT(77),
LIBRARY_MAX_RESEARCHER_COUNT(78),
WORKSHOP_USED_CAPACITY(79),
WORKSHOP_MAX_CAPACITY(80),
GUARD_ROOM_GUARD_COUNT(81),
GUARD_ROOM_MAX_GUARD_COUNT(82),
PRISONER_COUNT(83),
MAX_PRISONER_COUNT(84),
PRISON_COUNT_ALTERNATIVE(85),
GRAVEYARD_MAX_VAMPIRE_COUNT(86),
CASINO_PAYOUT(87),
CREATURE_LEVEL(88),
BONUS_PACK_NUMBER(89),
CRYPT_STATUS(90);

private static final Map<Integer, TextParameter> BY_ID;

static {
Map<Integer, TextParameter> parameters = new HashMap<>();
for (TextParameter parameter : values()) {
TextParameter previous = parameters.put(parameter.id, parameter);
if (previous != null) {
throw new IllegalStateException("Duplicate text parameter ID " + parameter.id);
}
}
BY_ID = Collections.unmodifiableMap(parameters);
}

private final int id;

TextParameter(int id) {
this.id = id;
}

public int getId() {
return id;
}

public static Optional<TextParameter> fromId(int id) {
return Optional.ofNullable(BY_ID.get(id));
}
}
4 changes: 2 additions & 2 deletions src/main/java/toniarts/openkeeper/utils/TextReplacer.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public interface TextReplacer {
/**
* Get replacement for a parameter
*
* @param index parameter index
* @param parameter text parameter
* @return the actual parameter replacement
*/
String getReplacement(int index);
String getReplacement(TextParameter parameter);

}
23 changes: 21 additions & 2 deletions src/main/java/toniarts/openkeeper/utils/TextUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
*/
package toniarts.openkeeper.utils;

import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -32,6 +35,7 @@
*/
public final class TextUtils {

private static final Logger logger = System.getLogger(TextUtils.class.getName());
private final static Pattern PATTERN = Pattern.compile("%(\\d+|%)");

private TextUtils() {
Expand All @@ -43,14 +47,29 @@ public static String parseText(String text, TextReplacer replacer) {
StringBuilder sb = new StringBuilder();
while (matcher.find()) {
String param = matcher.group(1);
String replacement;
if ("%".equals(param)) {
matcher.appendReplacement(sb, "%");
replacement = "%";
} else {
matcher.appendReplacement(sb, replacer.getReplacement(Integer.parseInt(param)));
int id = Integer.parseInt(param);
Optional<TextParameter> parameter = TextParameter.fromId(id);
if (parameter.isEmpty()) {
logger.log(Level.WARNING, "Unknown text parameter ID {0}", id);
replacement = matcher.group();
} else {
replacement = replacer.getReplacement(parameter.get());
}
}
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);

return sb.toString();
}

public static String getUnsupportedParameterMessage(TextParameter parameter, Class<?> parserType) {
logger.log(Level.WARNING, "Text parameter {0} is not supported by {1}",
new Object[]{parameter.getId(), parserType.getSimpleName()});
return "Parameter " + parameter.getId() + " not implemented!";
}
}
21 changes: 11 additions & 10 deletions src/main/java/toniarts/openkeeper/view/text/CreatureTextParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.simsilica.es.Entity;
import com.simsilica.es.EntityComponent;
import java.util.Collection;
import toniarts.openkeeper.utils.TextParameter;
import toniarts.openkeeper.game.component.CreatureAi;
import toniarts.openkeeper.game.component.CreatureComponent;
import toniarts.openkeeper.game.component.CreatureEfficiency;
Expand All @@ -45,40 +46,40 @@ public CreatureTextParser(IMapInformation mapInformation) {
}

@Override
protected String getReplacement(int index, Entity entity, Creature creature) {
switch (index) {
case 29:
protected String getReplacement(TextParameter parameter, Entity entity, Creature creature) {
switch (parameter) {
case CREATURE_INSTANCE_NAME:
CreatureComponent creatureComponent = entity.get(CreatureComponent.class);
if (creatureComponent != null) {
return creatureComponent.name;
}
return "";
case 30:
case CREATURE_NAME:
return Utils.getMainTextResourceBundle().getString(Integer.toString(creature.getNameStringId()));
case 31:
case CREATURE_ACTIVITY:
CreatureAi creatureAi = entity.get(CreatureAi.class);
if (creatureAi != null) {
return getStatusText(entity, creatureAi, mapInformation);
}
return "";
case 32:
case CREATURE_STATUS:
// FIXME
return "";
case 33:
case CREATURE_MOOD:
CreatureMood creatureMood = entity.get(CreatureMood.class);
if (creatureMood != null) {
return Integer.toString(creatureMood.moodValue);
}
return "";
case 74:
case CREATURE_EFFICIENCY:
CreatureEfficiency creatureEfficiency = entity.get(CreatureEfficiency.class);
if (creatureEfficiency != null) {
return Integer.toString(creatureEfficiency.efficiencyPercentage);
}
return "";
default:
return super.getReplacement(parameter, entity, creature);
}

return super.getReplacement(index, entity, creature);
}

private static String getStatusText(Entity entity, CreatureAi creatureAi,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import toniarts.openkeeper.tools.convert.map.Door;
import toniarts.openkeeper.tools.convert.map.Trap;
import toniarts.openkeeper.utils.TextParameter;
import toniarts.openkeeper.utils.TextUtils;
import toniarts.openkeeper.utils.Utils;

/**
Expand All @@ -28,19 +30,19 @@
public final class DoorIconTextParser extends IconTextParser<Door, Trap> {

@Override
protected String getReplacement(int index, Door door, Trap trap) {
switch (index) {
case 1:
protected String getReplacement(TextParameter parameter, Door door, Trap trap) {
switch (parameter) {
case NAME:
return Utils.getMainTextResourceBundle().getString(Integer.toString(door.getNameStringId()));
case 2:
case COST:
return Integer.toString(door.getGoldCost());
case 25:
case MANA_USAGE:
return Integer.toString(trap.getManaUsage());
case 26:
case MANA_COST_TO_FIRE:
return Integer.toString(trap.getManaCostToFire());
default:
return TextUtils.getUnsupportedParameterMessage(parameter, getClass());
}

return "Parameter " + index + " not implemented!";
}

}
13 changes: 7 additions & 6 deletions src/main/java/toniarts/openkeeper/view/text/DoorTextParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.simsilica.es.Entity;
import com.simsilica.es.EntityComponent;
import java.util.Collection;
import toniarts.openkeeper.utils.TextParameter;
import toniarts.openkeeper.game.component.DoorComponent;
import toniarts.openkeeper.tools.convert.map.Door;
import toniarts.openkeeper.utils.Utils;
Expand All @@ -35,19 +36,19 @@ public DoorTextParser() {
}

@Override
protected String getReplacement(int index, Entity entity, Door door) {
switch (index) {
case 68:
protected String getReplacement(TextParameter parameter, Entity entity, Door door) {
switch (parameter) {
case ENTITY_NAME:
return Utils.getMainTextResourceBundle().getString(Integer.toString(door.getNameStringId()));
case 72:
case STATE:
DoorComponent doorComponent = entity.get(DoorComponent.class);
if (doorComponent != null) {
return doorComponent.locked ? Utils.getMainTextResourceBundle().getString("2516") : Utils.getMainTextResourceBundle().getString("2515");
}
return "";
default:
return super.getReplacement(parameter, entity, door);
}

return super.getReplacement(index, entity, door);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import toniarts.openkeeper.utils.TextParameter;
import toniarts.openkeeper.game.component.Gold;
import toniarts.openkeeper.game.component.Health;
import toniarts.openkeeper.utils.TextUtils;
Expand All @@ -37,28 +38,28 @@ public EntityTextParser() {
}

public String parseText(String text, Entity entity, T dataObject) {
return TextUtils.parseText(text, (index) -> {
return getReplacement(index, entity, dataObject);
return TextUtils.parseText(text, (parameter) -> {
return getReplacement(parameter, entity, dataObject);
});
}

protected String getReplacement(int index, Entity entity, T dataObject) {
switch (index) {
case 37:
protected String getReplacement(TextParameter parameter, Entity entity, T dataObject) {
switch (parameter) {
case HEALTH_PERCENTAGE:
Health health = entity.get(Health.class);
if (health != null) {
return Integer.toString((int) (health.health / health.maxHealth * 100f));
}
return "";
case 73:
case ENTITY_GOLD:
Gold gold = entity.get(Gold.class);
if (gold != null) {
return Integer.toString(gold.gold);
}
return "";
default:
return TextUtils.getUnsupportedParameterMessage(parameter, getClass());
}

return "Parameter " + index + " not implemented!";
}

public Collection<Class<? extends EntityComponent>> getWatchedComponents() {
Expand Down
Loading
Loading