RuneHive-Tarnish
Neural OSRS Enhancement Framework
Loading...
Searching...
No Matches
DialogueScriptParser.java
1package com.osroyale.content.dialogue.script;
2
3import com.osroyale.content.dialogue.Expression;
4import com.osroyale.util.MessageColor;
5import org.apache.logging.log4j.LogManager;
6import org.apache.logging.log4j.Logger;
7
8import java.io.BufferedReader;
9import java.io.File;
10import java.io.FileReader;
11import java.io.IOException;
12import java.nio.file.Files;
13import java.nio.file.Path;
14import java.nio.file.Paths;
15import java.util.*;
16import java.util.regex.Matcher;
17import java.util.regex.Pattern;
18import java.util.stream.Stream;
19
45
47
48 private static final Logger logger = LogManager.getLogger(DialogueScriptParser.class);
49 private static final Map<Integer, DialogueScript> scripts = new HashMap<>();
50
51 private static final Pattern DIALOGUE_PATTERN = Pattern.compile("@dialogue\\s+npc:(.+)");
52 private static final Pattern NPC_PATTERN = Pattern.compile("npc\\(\"(.+?)\"(?:,\\s*\"(.+?)\")?\\)");
53 private static final Pattern PLAYER_PATTERN = Pattern.compile("player\\(\"(.+?)\"(?:,\\s*\"(.+?)\")?\\)");
54 private static final Pattern MESSAGE_PATTERN = Pattern.compile("message\\(\"(.+?)\"\\)");
55 private static final Pattern OPTION_PATTERN = Pattern.compile("option\\((.+)\\)");
56
57 public static void loadAll() {
58 scripts.clear();
59
60 try {
61 Path scriptDir = Paths.get("./data/dialogue/scripts");
62 if (!Files.exists(scriptDir)) {
63 Files.createDirectories(scriptDir);
64 logger.info("Created dialogue scripts directory");
65 return;
66 }
67
68 try (Stream<Path> paths = Files.walk(scriptDir)) {
69 paths.filter(Files::isRegularFile)
70 .filter(path -> path.toString().endsWith(".asc"))
71 .forEach(DialogueScriptParser::loadScript);
72 }
73
74 logger.info("Loaded {} dialogue scripts", MessageColor.DARK_GREEN, scripts.size());
75 } catch (IOException e) {
76 logger.error("Error loading dialogue scripts", e);
77 }
78 }
79
80 private static void loadScript(Path path) {
81 try (BufferedReader reader = new BufferedReader(new FileReader(path.toFile()))) {
82 String line;
83 DialogueScript currentScript = null;
84 List<String> currentMessages = new ArrayList<>();
85
86 while ((line = reader.readLine()) != null) {
87 line = line.trim();
88
89 if (line.isEmpty() || line.startsWith("#") || line.startsWith("//")) {
90 continue;
91 }
92
93 Matcher dialogueMatcher = DIALOGUE_PATTERN.matcher(line);
94 if (dialogueMatcher.matches()) {
95 if (currentScript != null) {
96 registerScript(currentScript);
97 }
98
99 String npcIdString = dialogueMatcher.group(1).trim();
100 int[] npcIds = parseNpcIds(npcIdString);
101 currentScript = new DialogueScript(npcIds);
102 continue;
103 }
104
105 if (currentScript == null) {
106 continue;
107 }
108
109 Matcher npcMatcher = NPC_PATTERN.matcher(line);
110 if (npcMatcher.matches()) {
111 String message1 = npcMatcher.group(1);
112 String message2 = npcMatcher.group(2);
113
114 String[] messages = message2 != null ?
115 new String[] { message1, message2 } :
116 new String[] { message1 };
117
118 currentScript.addAction(new DialogueScript.NpcDialogueAction(messages, Expression.DEFAULT));
119 continue;
120 }
121
122 Matcher playerMatcher = PLAYER_PATTERN.matcher(line);
123 if (playerMatcher.matches()) {
124 String message1 = playerMatcher.group(1);
125 String message2 = playerMatcher.group(2);
126
127 String[] messages = message2 != null ?
128 new String[] { message1, message2 } :
129 new String[] { message1 };
130
131 currentScript.addAction(new DialogueScript.PlayerDialogueAction(messages, Expression.DEFAULT));
132 continue;
133 }
134
135 Matcher messageMatcher = MESSAGE_PATTERN.matcher(line);
136 if (messageMatcher.matches()) {
137 String message = messageMatcher.group(1);
138 currentScript.addAction(new DialogueScript.StatementAction(new String[] { message }));
139 continue;
140 }
141
142 Matcher optionMatcher = OPTION_PATTERN.matcher(line);
143 if (optionMatcher.matches()) {
144 String optionsString = optionMatcher.group(1);
145 String[] options = parseOptions(optionsString);
146
147 currentScript.addAction(new DialogueScript.OptionAction("Select an option", options, new Runnable[options.length]));
148 continue;
149 }
150 }
151
152 if (currentScript != null) {
153 registerScript(currentScript);
154 }
155
156 } catch (IOException e) {
157 logger.error("Error loading script: " + path, e);
158 }
159 }
160
161 private static int[] parseNpcIds(String npcIdString) {
162 String[] parts = npcIdString.split(",");
163 int[] ids = new int[parts.length];
164
165 for (int i = 0; i < parts.length; i++) {
166 try {
167 ids[i] = Integer.parseInt(parts[i].trim());
168 } catch (NumberFormatException e) {
169 logger.error("Invalid NPC ID: " + parts[i]);
170 }
171 }
172
173 return ids;
174 }
175
176 private static String[] parseOptions(String optionsString) {
177 List<String> options = new ArrayList<>();
178 Pattern quotedPattern = Pattern.compile("\"([^\"]+)\"");
179 Matcher matcher = quotedPattern.matcher(optionsString);
180
181 while (matcher.find()) {
182 options.add(matcher.group(1));
183 }
184
185 return options.toArray(new String[0]);
186 }
187
188 private static void registerScript(DialogueScript script) {
189 for (int npcId : script.getNpcIds()) {
190 scripts.put(npcId, script);
191 }
192 }
193
194 public static Optional<DialogueScript> getScript(int npcId) {
195 return Optional.ofNullable(scripts.get(npcId));
196 }
197
198 public static Map<Integer, DialogueScript> getScripts() {
199 return Collections.unmodifiableMap(scripts);
200 }
201}