Starsector API
Loading...
Searching...
No Matches
CodexTextEntryLoader.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.codex;
2
3import java.io.IOException;
4import java.util.ArrayList;
5import java.util.List;
6import java.util.regex.Matcher;
7import java.util.regex.Pattern;
8
9import java.awt.Color;
10
11import org.json.JSONArray;
12import org.json.JSONException;
13import org.json.JSONObject;
14
15import com.fs.starfarer.api.Global;
16import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
17import com.fs.starfarer.api.ui.CustomPanelAPI;
18import com.fs.starfarer.api.ui.LabelAPI;
19import com.fs.starfarer.api.ui.TooltipMakerAPI;
20import com.fs.starfarer.api.ui.UIPanelAPI;
21import com.fs.starfarer.api.util.ListMap;
22import com.fs.starfarer.api.util.Misc;
23
25
26 public static class ParaData {
27 public int fontSize = 0;
28 public int bulletMode = 0;
29 public Color color = Misc.getTextColor();
30 public String text;
31 public List<String> highlights = new ArrayList<>();
32 public List<Color> colors = new ArrayList<>();
33 public String image;
34 public float imageHeight;
35 }
36
37 public static class TextEntry extends CodexEntryV2 {
38 public List<Object> data = new ArrayList<>();
39 public String parentId;
40 public TextEntry(String id, String title, String icon) {
41 super(id, title, icon);
42 setParam(id);
43 }
44
45 @Override
46 public void createTitleForList(TooltipMakerAPI info, float width, ListMode mode) {
47 super.createTitleForList(info, width, mode);
48 }
49
50 @Override
51 public boolean hasCustomDetailPanel() {
52 return true;
53 }
54
55 @Override
56 public void createCustomDetail(CustomPanelAPI panel, UIPanelAPI relatedEntries, CodexDialogAPI codex) {
57 Color color = Misc.getBasePlayerColor();
58 Color dark = Misc.getDarkPlayerColor();
59 Color h = Misc.getHighlightColor();
60 Color g = Misc.getGrayColor();
61 float opad = 10f;
62 float pad = 3f;
63 float small = 5f;
64
65 float width = panel.getPosition().getWidth();
66
67 float initPad = 0f;
68
69 float horzBoxPad = 30f;
70
71 // the right width for a tooltip wrapped in a box to fit next to relatedEntries
72 // 290 is the width of the related entries widget, but it may be null
73 float tw = width - 290f - opad - horzBoxPad + 10f;
74
75 TooltipMakerAPI text = panel.createUIElement(tw, 0, false);
77
78 int prevBulletMode = 0;
79 for (Object o : data) {
80 if (o instanceof ParaData) {
81 ParaData para = (ParaData) o;
82
83 TooltipMakerAPI curr = text;
84 float outerPad = initPad;
85 if (para.image != null) {
86 float height = para.imageHeight;
87 if (height <= 0f) height = Global.getSettings().getSprite(para.image).getHeight();
88 curr = text.beginImageWithText(para.image, height);
89 initPad = 0f;
90 }
91
92 if (prevBulletMode != 0 && para.bulletMode != 0) {
93 initPad = 0f;
94 }
95 prevBulletMode = para.bulletMode;
96
97 if (para.fontSize == -1) {
98 curr.setParaFontDefault();
99 } else if (para.fontSize == 0) {
101 } else if (para.fontSize == 1) {
103 } else if (para.fontSize == 2) {
105 } else if (para.fontSize == 3) {
107 }
108
109 if (para.bulletMode == 0) {
110 curr.setBulletedListMode(null);
111 } else if (para.bulletMode == 1) {
113 } else if (para.bulletMode == 2) {
115 }
116
117 LabelAPI label = curr.addPara(para.text, initPad,
118 para.colors.toArray(new Color[0]), para.highlights.toArray(new String[0]));
119 label.setColor(para.color);
120 label.setHighlight(para.highlights.toArray(new String[0]));
121 label.setHighlightColors(para.colors.toArray(new Color[0]));
122 initPad = opad;
123
124 prevBulletMode = para.bulletMode;
125
126 if (para.image != null) {
127 text.addImageWithText(outerPad);
128 }
129
130 if (para.fontSize > 0) {
131 text.addSpacer(-opad + pad);
132 }
133 }
134 }
136
137 UIPanelAPI box = panel.wrapTooltipWithBox(text);
138 panel.addComponent(box).inTL(0f, 0f);
139 if (relatedEntries != null) {
140 panel.addComponent(relatedEntries).inTR(0f, 0f);
141 }
142
143 float height = box.getPosition().getHeight();
144 if (relatedEntries != null) {
145 height = Math.max(height, relatedEntries.getPosition().getHeight());
146 }
147 panel.getPosition().setSize(width, height);
148 }
149 }
150
151
152 public static ListMap<String> LINKS = new ListMap<>();
153 public static void linkRelated() {
154 for (String key : LINKS.keySet()) {
156 for (String key2 : LINKS.getList(key)) {
158 if (entry != null && other != null) {
159 CodexDataV2.makeRelated(entry, other);
160 }
161 }
162 }
163 LINKS.clear();
164 }
165
166 public static void loadTextEntries() {
167 try {
168 String csvName = "data/codex/text_codex_entries.csv";
169 Global.getLogger(CodexTextEntryLoader.class).info("Loading [" + csvName + "]");
170 JSONArray rows = Global.getSettings().loadCSV(csvName, true);
171
172 for (int i = 0; i < rows.length(); i++) {
173 JSONObject row = rows.getJSONObject(i);
174 String filename = row.getString("filename");
175 Global.getLogger(CodexTextEntryLoader.class).info("Loading [" + filename + "]");
176 String contents = Global.getSettings().loadText(filename);
177 Global.getLogger(CodexTextEntryLoader.class).info("Parsing [" + filename + "]");
178 parseContents(contents, filename);
179 }
180 } catch (IOException e) {
181 throw new RuntimeException(e);
182 } catch (JSONException e) {
183 throw new RuntimeException(e);
184 }
185 }
186
187
188 public static void parseContents(String contents, String filename) {
189 contents = contents.replaceAll("\\r", "").trim();
190 String [] lines = contents.split("\\n");
191
192 Color base = Misc.getBasePlayerColor();
193 Color dark = Misc.getDarkPlayerColor();
194
195 Color currColor = null;
196 int currFontSize = 0;
197 String currCategory = null;
198 String paraImage = null;
199 int paraImageHeight = 0;
200
201 TextEntry entry = null;
202 int lineNum = 0;
203 for (String line : lines) {
204 lineNum++;
205 if (line.startsWith("#")) continue;
206 if (line.isBlank()) continue;
207 line = line.trim();
208
209 if (line.startsWith("CATEGORY ")) {
210 line = line.replaceFirst("CATEGORY ", "").trim();
211 Global.getLogger(CodexTextEntryLoader.class).info("Parsing category [" + line + "]");
212 String [] arr = line.split("\\|");
213 TextEntry cat = new TextEntry(arr[0], arr[2], CodexDataV2.getIcon(arr[1]));
214 cat.parentId = arr[3];
215 cat.setParam(null);
216 CodexDataV2.ENTRIES.put(cat.getId(), cat);
217 CodexEntryPlugin parent = CodexDataV2.getEntry(cat.parentId);
218 if (parent != null) {
219 cat.setParent(parent);
220 parent.addChild(cat);
221 }
222 continue;
223 }
224
225 if (line.startsWith("COLOR ")) {
226 line = line.replaceFirst("COLOR ", "").trim();
227 currColor = getColor(line);
228 continue;
229 }
230 if (line.startsWith("FONT ")) {
231 line = line.replaceFirst("FONT ", "").trim();
232 currFontSize = line.toLowerCase().equals("small") ? -1 : 0;
233 continue;
234 }
235 if (line.startsWith("IMAGE ")) {
236 line = line.replaceFirst("IMAGE ", "").trim();
237 String [] arr = line.split("\\|");
238 paraImage = arr[0];
239 if (arr.length > 1) {
240 try {
241 paraImageHeight = Integer.parseInt(arr[1]);
242 } catch (Throwable t) {
243 paraImage = Global.getSettings().getSpriteName(arr[0], arr[1]);
244 if (arr.length > 2) {
245 paraImageHeight = Integer.parseInt(arr[2]);
246 }
247 }
248 } else {
249 paraImageHeight = 0;
250 }
251 continue;
252 }
253 if (line.startsWith("RESET")) {
254 currColor = getColor("text");
255 currFontSize = 0;
256 continue;
257 }
258 if (line.startsWith("CURRENT_CATEGORY ")) {
259 line = line.replaceFirst("CURRENT_CATEGORY ", "").trim();
260 currCategory = line;
261 continue;
262 }
263
264 if (line.startsWith("BEGIN ")) {
265 line = line.replaceFirst("BEGIN ", "").trim();
266 Global.getLogger(CodexTextEntryLoader.class).info("Parsing entry [" + line + "]");
267 String [] arr = line.split("\\|");
268 entry = new TextEntry(arr[0], arr[1], null);
269 entry.parentId = currCategory;
270 if (arr.length >= 3) entry.parentId = arr[2];
271 continue;
272 }
273
274 if (entry == null) {
275 throw new RuntimeException(String.format("Error parsing [%s] line %s, expected to be inside entry",
276 filename, "" + lineNum));
277 }
278
279 if (line.startsWith("END")) {
280 if (entry.getIcon() == null) {
281 String icon = CodexDataV2.getIcon("generic");
282 entry.setIcon(icon);
283 }
284 CodexEntryPlugin parent = CodexDataV2.getEntry(entry.parentId);
285 if (parent != null) {
286 entry.setParent(parent);
287 parent.addChild(entry);
288 }
289 entry = null;
290 currColor = null;
291 currFontSize = 0;
292 continue;
293 }
294
295 if (line.startsWith("ICON ")) {
296 line = line.replaceFirst("ICON ", "").trim();
297 String icon = CodexDataV2.getIcon(line);
298 entry.setIcon(icon);
299 continue;
300 }
301
302 if (line.startsWith("RELATED ")) {
303 line = line.replaceFirst("RELATED ", "").trim();
304 String [] ids = line.split("\\|");
305 for (String id : ids) {
306 //entry.addRelatedEntry(id);
307 LINKS.add(entry.getId(), id);
308 }
309 continue;
310 }
311
312
313 ParaData para = new ParaData();
314
315 Pattern p = Pattern.compile("(?is)^(=+)(.+?)=+$");
316 Matcher m = p.matcher(line);
317 if (m.find()) {
318 line = m.group(2);
319 para.fontSize = m.group(1).length();
320 para.color = base;
321 }
322
323 if (line.startsWith("_ ")) {
324 line = line.replaceFirst("_ ", "").trim();
325 para.bulletMode = 1;
326 } else if (line.startsWith("- ")) {
327 line = line.replaceFirst("- ", "").trim();
328 para.bulletMode = 2;
329 }
330
331 p = Pattern.compile("(?is)\\{\\{(.*?)\\}\\}");
332 m = p.matcher(line);
333
334 while (m.find()) {
335 String curr = m.group(1);
336 String replacement = "";
337 if (curr.startsWith("color:")) {
338 curr = curr.replaceFirst("color:", "").trim();
339 String [] arr = curr.split("\\|");
340 Color color = getColor(arr[0]);
341 para.colors.add(color);
342 para.highlights.add(arr[1]);
343 replacement = arr[1];
344 } else if (curr.startsWith("rel:")) {
345 curr = curr.replaceFirst("rel:", "").trim();
346 String [] arr = curr.split("\\|");
347 //entry.addRelatedEntry(arr[0]);
348 LINKS.add(entry.getId(), arr[0]);
349 para.colors.add(base);
350 para.highlights.add(arr[1]);
351 replacement = arr[1];
352 } else {
353 Color color = Misc.getHighlightColor();
354 para.colors.add(color);
355 para.highlights.add(curr);
356 replacement = curr;
357 }
358 line = line.replaceFirst(Pattern.quote(m.group(0)), replacement);
359 }
360
361 para.text = line.replaceAll("%", "%%");
362 if (currColor != null) {
363 para.color = currColor;
364 }
365 if (para.fontSize == 0) {
366 para.fontSize = currFontSize;
367 }
368
369 para.image = paraImage;
370 para.imageHeight = paraImageHeight;
371 paraImage = null;
372 paraImageHeight = 0;
373
374 entry.data.add(para);
375 }
376
377 if (entry != null) {
378 throw new RuntimeException(String.format("Error parsing [%s] file ended while still parsing entry", filename));
379 }
380 }
381
382 public static Color getColor(String str) {
385 }
386
387 Color dark = Misc.getDarkPlayerColor();
388 Color h = Misc.getHighlightColor();
389 Color bad = Misc.getNegativeHighlightColor();
390 Color good = Misc.getPositiveHighlightColor();
391 Color gray = Misc.getGrayColor();
392 Color textColor = Misc.getTextColor();
393 Color player = Misc.getBasePlayerColor();
394
395 Color color = null;
396 if (str.equals("h")) color = h;
397 else if (str.equals("good")) color = good;
398 else if (str.equals("bad")) color = bad;
399 else if (str.equals("gray")) color = gray;
400 else if (str.equals("grey")) color = gray;
401 else if (str.equals("text")) color = textColor;
402 else if (str.equals("player")) color = player;
403 else if (str.equals("blue")) color = player;
404 else if (str.equals("base")) color = player;
405 else if (str.equals("dark")) color = dark;
406 else color = Global.getSettings().getColor(str);
407 if (color == null) {
408 throw new RuntimeException(String.format("Parsing error: color [%s] not found", str));
409 }
410 return color;
411 }
412
413
414 public static void main(String[] args) {
415 String test = "Testing 100% in text";
416 test = test.replaceAll("%", "%%");
417 System.out.println(String.format(test));
418
419// String line = "Flux generated by taking damage on shields is {{color:h|hard}} flux, meaning that it can not dissipate while shields are up. Flux generated by firing weapons is {{color:h|soft}} flux and can dissipate while shields are up.";
420// Pattern p = Pattern.compile("(?is)\\{\\{(.*?)\\}\\}");
421// Matcher m = p.matcher(line);
422
423// String line = "===A heading===\n";
424// line = line.trim();
425// Pattern p = Pattern.compile("(?is)^(=+)(.+?)=+$");
426// Matcher m = p.matcher(line);
427//
428// while (m.find()) {
429// String curr = m.group(2);
430// System.out.println("Found: " + curr);
431// }
432 }
433}
434
435
436
437
438
439
440
441
442
443
444
445
446
447
static SettingsAPI getSettings()
Definition Global.java:57
static Logger getLogger(Class c)
Definition Global.java:32
static void makeRelated(CodexEntryPlugin ... plugins)
static Map< String, CodexEntryPlugin > ENTRIES
static CodexEntryPlugin getEntry(String id)
void setParent(CodexEntryPlugin parent)
static void parseContents(String contents, String filename)
static Color getTextColor()
Definition Misc.java:839
static Color getNegativeHighlightColor()
Definition Misc.java:802
static Color getBasePlayerColor()
Definition Misc.java:833
static Color getGrayColor()
Definition Misc.java:826
static Color getHighlightColor()
Definition Misc.java:792
static Color getDarkPlayerColor()
Definition Misc.java:836
static Color getPositiveHighlightColor()
Definition Misc.java:822
boolean hasDesignTypeColor(String designType)
JSONArray loadCSV(String filename)
String loadText(String filename)
String getSpriteName(String category, String id)
SpriteAPI getSprite(String filename)
Color getDesignTypeColor(String designType)
TooltipMakerAPI createUIElement(float width, float height, boolean withScroller)
void updateUIElementSizeAndMakeItProcessInput(TooltipMakerAPI element)
UIPanelAPI wrapTooltipWithBox(TooltipMakerAPI tooltip)
void setHighlight(int start, int end)
void setHighlightColors(Color ... colors)
PositionAPI inTL(float xPad, float yPad)
PositionAPI setSize(float width, float height)
PositionAPI inTR(float xPad, float yPad)
LabelAPI addPara(String format, float pad, Color hl, String... highlights)
UIComponentAPI addSpacer(float height)
TooltipMakerAPI beginImageWithText(String spriteName, float imageHeight)
UIPanelAPI addImageWithText(float pad)
void setBulletedListMode(String itemPrefix)
PositionAPI addComponent(UIComponentAPI custom)