Skip to content

Commit ef1b369

Browse files
committed
TextSubstitutor now can perform dynamic substitutions (replace tile/object/item names with their id's, evaluate lua expressions + ability to hook a String supplier to substitute specified string)
* Item names can now be used in craft recipes instead of id's, using the substitutor syntax ( e.g: @(item: stick)/3:@(item: rock)/5 ) * rollDungeonEntrance() now actually decides whether to generate a dungeon trapdoor tile or not based on "dungeonProbability" WorldGenPreset field for current biome * Enumerable now has name() method to unify fuzzysearch by name
1 parent ec3fe67 commit ef1b369

30 files changed

+249
-135
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ gradle.startParameter.showStacktrace = org.gradle.api.logging.configuration.Show
22
allprojects {
33
apply plugin: "eclipse"
44

5-
version = 'v0.49.18a'
5+
version = 'v0.49.18.1a'
66

77
ext {
88
appName = "MadSand"

core/assets/textures/textures9.png

-2.21 KB
Loading

core/assets/tiles.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@
404404
end
405405
",
406406
"altItems" : null,
407-
"name" : "Trapdoor",
407+
"name" : "Dungeon Trapdoor",
408408
"foreground" : false
409409
},
410410

core/assets/worldgen.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
"defaultTile" : 0,
88
"tiles" : [
99
{ "rollCount" : 350, "idList" : [ 1, 2 ] },
10-
{ "rollCount" : 100, "idList" : [ 3 ] },
11-
{ "scalable" : false, "rollCount" : 1, "idList" : [ 45 ] }
10+
{ "rollCount" : 100, "idList" : [ 3 ] }
1211
],
1312

1413
"objects" : [
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
11
package hitonoriol.madsand;
22

3+
import java.util.Map;
4+
35
import com.fasterxml.jackson.annotation.JsonGetter;
46

7+
import me.xdrop.fuzzywuzzy.FuzzySearch;
8+
59
public interface Enumerable {
610
void setId(int id);
711
@JsonGetter("id")
812
int id();
13+
String name();
914

1015
default boolean idEquals(Enumerable enumerableObj) {
1116
return id() == enumerableObj.id();
1217
}
18+
19+
static <T extends Enumerable> T find(Map<Integer, T> items, String partialName) {
20+
return FuzzySearch.extractOne(partialName,
21+
items.values(), item -> item.name() == null ? "" : item.name(),
22+
(str1, str2) -> FuzzySearch.tokenSortRatio(str1, str2))
23+
.getReferent();
24+
}
25+
26+
static <T extends Enumerable> int findId(Map<Integer, T> items, String partialName) {
27+
return find(items, partialName).id();
28+
}
1329
}

core/src/hitonoriol/madsand/MadSand.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import com.badlogic.gdx.utils.Timer;
1212

1313
import hitonoriol.madsand.containers.Storage;
14-
import hitonoriol.madsand.dialog.GameTextSubstitutor;
1514
import hitonoriol.madsand.entities.Player;
1615
import hitonoriol.madsand.input.Keyboard;
1716
import hitonoriol.madsand.input.Mouse;
@@ -61,7 +60,6 @@ public void create() {
6160
Timer.instance().start();
6261
Resources.loadAll();
6362
Gui.init();
64-
GameTextSubstitutor.init();
6563
initScreens();
6664
Keyboard.initListener();
6765
Mouse.initListener();

core/src/hitonoriol/madsand/dialog/GameDialog.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public GameDialog newLine() {
100100
}
101101

102102
public void setText(String text) {
103-
textLbl.setText(GameTextSubstitutor.replace(text));
103+
textLbl.setText(TextSubstitutor.replace(text));
104104
}
105105

106106
public GameDialog setTitle(String text) {

core/src/hitonoriol/madsand/dialog/GameTextSubstitutor.java

Lines changed: 0 additions & 68 deletions
This file was deleted.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package hitonoriol.madsand.dialog;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
import java.util.function.Supplier;
6+
import java.util.regex.Pattern;
7+
8+
import org.apache.commons.text.StringSubstitutor;
9+
10+
import hitonoriol.madsand.Enumerable;
11+
import hitonoriol.madsand.MadSand;
12+
import hitonoriol.madsand.lua.Lua;
13+
import hitonoriol.madsand.properties.ItemProp;
14+
import hitonoriol.madsand.properties.ObjectProp;
15+
import hitonoriol.madsand.properties.TileProp;
16+
import hitonoriol.madsand.resources.Resources;
17+
import hitonoriol.madsand.util.Strings;
18+
import hitonoriol.madsand.util.Utils;
19+
import me.xdrop.jrand.JRand;
20+
import me.xdrop.jrand.model.person.Gender;
21+
22+
public class TextSubstitutor {
23+
public static final String L = "{", R = "}";
24+
25+
static final String RAND_NAME = "RANDOM_NAME";
26+
static final String RAND_NAME_M = "RANDOM_NAME_M", RAND_NAME_F = "RANDOM_NAME_F";
27+
28+
public static final String QUEST_ITEM_REWARD = "ITEM_REWARD", QUEST_EXP_REWARD = "EXP_REWARD";
29+
public static final String QUEST_ITEM_OBJECTIVE = "ITEM_OBJECTIVE", QUEST_KILL_OBJECTIVE = "KILL_OBJECTIVE";
30+
public static final String LINEBREAK = "br";
31+
private static Pattern luaPattern = Pattern.compile("\\$\\((.*)\\)"); // $(lua_expression)
32+
private static Pattern idPattern = Pattern.compile("\\@\\((item|object|tile)\\:(.*?)\\)"); // @(<item/object/tile>:partial_name_str)
33+
34+
private Map<String, String> values = new HashMap<>();
35+
private Map<String, Supplier<String>> dynamicMap = new HashMap<>();
36+
private StringSubstitutor substitutor = new StringSubstitutor(values, L, R);
37+
38+
private static TextSubstitutor instance = new TextSubstitutor();
39+
static {
40+
add(LINEBREAK, Resources.LINEBREAK);
41+
add("PLAYER", () -> MadSand.player().getName());
42+
add(RAND_NAME, () -> JRand.firstname().gen());
43+
add(RAND_NAME_M, () -> JRand.firstname().gender(Gender.MALE).gen());
44+
add(RAND_NAME_F, () -> JRand.firstname().gender(Gender.FEMALE).gen());
45+
}
46+
47+
private TextSubstitutor() {}
48+
49+
public static void add(String var, String subText) {
50+
Utils.dbg("Substitutor: Setting " + L + var + R + " to \"" + subText + "\"");
51+
instance.values.put(var, subText);
52+
}
53+
54+
public static void add(String var, Supplier<String> subSupplier) {
55+
instance.dynamicMap.put(L + var + R, subSupplier);
56+
}
57+
58+
public static String replace(String str) {
59+
StringBuilder sb = new StringBuilder(str);
60+
replaceDynamic(sb);
61+
parsePatterns(sb);
62+
return instance.substitutor.replace(sb);
63+
}
64+
65+
private static void replaceDynamic(StringBuilder sb) {
66+
instance.dynamicMap.forEach((var, supplier) -> {
67+
int start;
68+
while ((start = sb.indexOf(var)) != -1) {
69+
sb.replace(start, start + var.length(), supplier.get());
70+
}
71+
});
72+
}
73+
74+
private static void parsePatterns(StringBuilder sb) {
75+
/* Replace lua expressions with their evaluation result */
76+
Strings.parseRegex(sb, luaPattern, matcher -> {
77+
String exprResult = Lua.execute("return " + matcher.group(1) + ";").tojstring();
78+
sb.replace(matcher.start(), matcher.end(), exprResult);
79+
});
80+
81+
/* Replace Item / MapObject / Tile names with their id's */
82+
Strings.parseRegex(sb, idPattern, matcher -> {
83+
Map<Integer, ? extends Enumerable> map;
84+
String type = matcher.group(1);
85+
if (type.equals("item"))
86+
map = ItemProp.items;
87+
else if (type.equals("object"))
88+
map = ObjectProp.objects;
89+
else
90+
map = TileProp.tiles;
91+
92+
sb.replace(matcher.start(), matcher.end(), Utils.str(Enumerable.findId(map, matcher.group(2))));
93+
});
94+
}
95+
}

core/src/hitonoriol/madsand/entities/Player.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import java.util.function.Supplier;
1515
import java.util.stream.Collectors;
1616

17+
import org.apache.commons.lang3.mutable.MutableInt;
18+
1719
import com.badlogic.gdx.Gdx;
1820
import com.badlogic.gdx.graphics.g2d.Sprite;
1921
import com.badlogic.gdx.graphics.g2d.TextureRegion;
@@ -31,7 +33,6 @@
3133
import hitonoriol.madsand.containers.Pair;
3234
import hitonoriol.madsand.dialog.DialogChainGenerator;
3335
import hitonoriol.madsand.dialog.GameDialog;
34-
import hitonoriol.madsand.dialog.GameTextSubstitutor;
3536
import hitonoriol.madsand.entities.ability.Ability;
3637
import hitonoriol.madsand.entities.ability.ActiveAbility;
3738
import hitonoriol.madsand.entities.equipment.EquipSlot;
@@ -105,6 +106,7 @@ public class Player extends Entity {
105106
private List<Ability> abilities = new ArrayList<>();
106107
private LinkedHashMap<Integer, Integer> abilityKeyBinds = new LinkedHashMap<>();
107108
private int settlementsEstablished = 0;
109+
private MutableInt dungeonsCompleted = new MutableInt();
108110
@JsonIgnore
109111
private List<Pair> visibleArea = new ArrayList<>();
110112

@@ -275,12 +277,6 @@ public void refreshEquipment() {
275277
Gui.overlay.equipmentSidebar.refresh();
276278
}
277279

278-
@JsonIgnore
279-
public void setName(String name) {
280-
super.setName(name);
281-
GameTextSubstitutor.add(GameTextSubstitutor.PLAYER_NAME, name);
282-
}
283-
284280
public void unTarget() {
285281
--targetedByNpcs;
286282
}
@@ -1474,4 +1470,8 @@ public void setStats(PlayerStats stats) {
14741470
public PlayerStats getStats() {
14751471
return stats;
14761472
}
1473+
1474+
public MutableInt dungeonsCompleted() {
1475+
return dungeonsCompleted;
1476+
}
14771477
}

core/src/hitonoriol/madsand/entities/inventory/item/Item.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import hitonoriol.madsand.Enumerable;
3030
import hitonoriol.madsand.HotbarAssignable;
3131
import hitonoriol.madsand.MadSand;
32+
import hitonoriol.madsand.dialog.TextSubstitutor;
3233
import hitonoriol.madsand.entities.Player;
3334
import hitonoriol.madsand.entities.equipment.EquipSlot;
3435
import hitonoriol.madsand.entities.inventory.item.category.ItemCategories;
@@ -39,7 +40,6 @@
3940
import hitonoriol.madsand.properties.ItemProp;
4041
import hitonoriol.madsand.resources.Resources;
4142
import hitonoriol.madsand.util.Utils;
42-
import me.xdrop.fuzzywuzzy.FuzzySearch;
4343

4444
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
4545
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@@ -107,6 +107,11 @@ public void setId(int id) {
107107
lastId = Math.max(id, lastId);
108108
}
109109

110+
@Override
111+
public String name() {
112+
return name;
113+
}
114+
110115
public static int getLastId() {
111116
return lastId;
112117
}
@@ -207,6 +212,7 @@ public void initRecipe() {
207212
if (recipe == null)
208213
return;
209214

215+
recipe = TextSubstitutor.replace(recipe);
210216
/* If only craftable at a crafting station */
211217
if (recipe.contains(CRAFTSTATION_DELIM)) {
212218
String[] craftStationRecipe = recipe.split("\\" + Item.CRAFTSTATION_DELIM);
@@ -408,6 +414,7 @@ public static void parseListString(String listString, BiConsumer<Integer, Intege
408414
if (!listString.contains(BLOCK_DELIM))
409415
listString += BLOCK_DELIM;
410416

417+
listString = TextSubstitutor.replace(listString);
411418
String listItems[] = listString.split(BLOCK_DELIM);
412419
String itemAttrs[];
413420
for (String itemStr : listItems) {
@@ -481,12 +488,7 @@ public static Item create(int id) {
481488
}
482489

483490
public static Item create(String partialName, int quantity) {
484-
return create(
485-
FuzzySearch.extractOne(partialName,
486-
ItemProp.items.values(), item -> item.name == null ? "" : item.name,
487-
(str1, str2) -> FuzzySearch.tokenSortRatio(str1, str2))
488-
.getReferent(),
489-
quantity);
491+
return create(Enumerable.find(ItemProp.items, partialName), quantity);
490492
}
491493

492494
public static Item create(String partialName) {

core/src/hitonoriol/madsand/entities/npc/AbstractNpc.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import hitonoriol.madsand.MadSand;
1717
import hitonoriol.madsand.containers.Pair;
18-
import hitonoriol.madsand.dialog.GameTextSubstitutor;
18+
import hitonoriol.madsand.dialog.TextSubstitutor;
1919
import hitonoriol.madsand.entities.Entity;
2020
import hitonoriol.madsand.entities.Faction;
2121
import hitonoriol.madsand.entities.Player;
@@ -153,7 +153,7 @@ void loadProperties(NpcContainer properties) {
153153
stats.calcStats();
154154
stats.restore();
155155

156-
stats.name = GameTextSubstitutor.replace(properties.name);
156+
stats.name = TextSubstitutor.replace(properties.name);
157157
stats.hp = (int) (properties.hp + lvl * HP_PER_LVL);
158158
stats.mhp = stats.hp;
159159
stats.set(Stat.Strength, (int) (properties.strength + lvl * STR_PER_LVL));

core/src/hitonoriol/madsand/entities/npc/FarmAnimal.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import hitonoriol.madsand.gui.textgenerator.CellInfoGenerator;
77
import hitonoriol.madsand.map.ItemProducer;
88
import hitonoriol.madsand.properties.NpcContainer;
9-
import hitonoriol.madsand.util.Utils;
9+
import hitonoriol.madsand.util.Strings;
1010
import me.xdrop.jrand.JRand;
1111
import me.xdrop.jrand.generators.basics.NaturalGenerator;
1212

@@ -65,7 +65,7 @@ public String getInfoString() {
6565
CellInfoGenerator.getItemProducerInfo(sb, animalProduct);
6666

6767
if (isStarving()) {
68-
Utils.newLine(sb);
68+
Strings.newLine(sb);
6969
sb.append("* Starving");
7070
}
7171

0 commit comments

Comments
 (0)