Tools.java 8.76 KB
Newer Older
Melledy's avatar
Melledy committed
1
2
package emu.grasscutter.tools;

3
import java.io.BufferedReader;
4
import java.io.File;
5
import java.io.FileInputStream;
6
import java.io.FileOutputStream;
Melledy's avatar
Melledy committed
7
8
import java.io.FileReader;
import java.io.FileWriter;
9
import java.io.FilenameFilter;
10
import java.io.InputStreamReader;
11
import java.io.OutputStreamWriter;
Melledy's avatar
Melledy committed
12
import java.io.PrintWriter;
13
import java.nio.charset.StandardCharsets;
Melledy's avatar
Melledy committed
14
15
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
16
import java.util.*;
Melledy's avatar
Melledy committed
17
18
19
20
import java.util.stream.Collectors;

import com.google.gson.reflect.TypeToken;

21
import emu.grasscutter.GameConstants;
Melledy's avatar
Melledy committed
22
import emu.grasscutter.Grasscutter;
23
24
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandMap;
25
import emu.grasscutter.data.GameData;
Melledy's avatar
Melledy committed
26
27
28
29
import emu.grasscutter.data.ResourceLoader;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.data.def.MonsterData;
30
import emu.grasscutter.data.def.SceneData;
31
import emu.grasscutter.utils.Utils;
Melledy's avatar
Melledy committed
32

KingRainbow44's avatar
KingRainbow44 committed
33
public final class Tools {
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
	public static void createGmHandbook() throws Exception {
		ToolsWithLanguageOption.createGmHandbook(getLanguageOption());
	}

	public static void createGachaMapping(String location) throws Exception {
		ToolsWithLanguageOption.createGachaMapping(location, getLanguageOption());
	}

	public static List<String> getAvailableLanguage() throws Exception {
		File textMapFolder = new File(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap");
		List<String> availableLangList = new ArrayList<String>();
		for (String textMapFileName : textMapFolder.list(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				if (name.startsWith("TextMap") && name.endsWith(".json")){
					return true;
				}
				return false;
			}
		})) {
			availableLangList.add(textMapFileName.replace("TextMap","").replace(".json","").toLowerCase());
		}
		return availableLangList;
	}

	public static String getLanguageOption() throws Exception {
		List<String> availableLangList = getAvailableLanguage();
Melledy's avatar
Melledy committed
61
	
62
63
64
65
		// Use system out for better format
		if (availableLangList.size() == 1) {
			return availableLangList.get(0).toUpperCase();
		}
mingjun97's avatar
mingjun97 committed
66
67
68
		String stagedMessage = "";
		stagedMessage += "The following languages mappings are available, please select one: [default: EN]\n";
		String groupedLangList = ">\t";
69
70
71
72
73
74
		int groupedLangCount = 0;
		String input = "";
		for (String availableLanguage: availableLangList){
			groupedLangCount++;
			groupedLangList = groupedLangList + "" + availableLanguage + "\t";
			if (groupedLangCount == 6) {
mingjun97's avatar
mingjun97 committed
75
				stagedMessage += groupedLangList + "\n";
76
				groupedLangCount = 0;
mingjun97's avatar
mingjun97 committed
77
				groupedLangList = ">\t";
78
79
80
			}
		}
		if (groupedLangCount > 0) {
mingjun97's avatar
mingjun97 committed
81
			stagedMessage += groupedLangList + "\n";
82
		}
mingjun97's avatar
mingjun97 committed
83
84
85
		stagedMessage += "\nYour choice:[EN] ";
		
		input = Grasscutter.getConsole().readLine(stagedMessage);
86
87
88
89
90
91
92
93
94
95
		if (availableLangList.contains(input.toLowerCase())) {
			return input.toUpperCase();
		}
		Grasscutter.getLogger().info("Invalid option. Will use EN(English) as fallback");

		return "EN";
	}
}

final class ToolsWithLanguageOption {
Melledy's avatar
Melledy committed
96
	@SuppressWarnings("deprecation")
97
	public static void createGmHandbook(String language) throws Exception {
Melledy's avatar
Melledy committed
98
99
100
		ResourceLoader.loadResources();
		
		Map<Long, String> map;
101
		try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap/TextMap"+language+".json")), StandardCharsets.UTF_8)) {
Melledy's avatar
Melledy committed
102
103
104
105
106
			map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken<Map<Long, String>>() {}.getType());
		}
		
		List<Integer> list;
		String fileName = "./GM Handbook.txt";
107
		try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8), false)) {
Melledy's avatar
Melledy committed
108
109
110
			DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");  
			LocalDateTime now = LocalDateTime.now();
			   
111
			writer.println("// Grasscutter " + GameConstants.VERSION + " GM Handbook");
Melledy's avatar
Melledy committed
112
			writer.println("// Created " + dtf.format(now) + System.lineSeparator() + System.lineSeparator());
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

			CommandMap cmdMap = new CommandMap(true);
			List<Command> cmdList = new ArrayList<>(cmdMap.getAnnotationsAsList());

			writer.println("// Commands");
			for (Command cmd : cmdList) {
				String cmdName = cmd.label();
				while (cmdName.length() <= 15) {
					cmdName = " " + cmdName;
				}
				writer.println(cmdName + " : " + cmd.description());
			}

			writer.println();

128
			list = new ArrayList<>(GameData.getAvatarDataMap().keySet());
Melledy's avatar
Melledy committed
129
130
131
132
			Collections.sort(list); 
			 
			writer.println("// Avatars");
			for (Integer id : list) {
133
				AvatarData data = GameData.getAvatarDataMap().get(id);
Melledy's avatar
Melledy committed
134
135
136
137
138
				writer.println(data.getId() + " : " + map.get(data.getNameTextMapHash()));
			}
			
			writer.println();
			
139
			list = new ArrayList<>(GameData.getItemDataMap().keySet());
Melledy's avatar
Melledy committed
140
141
142
143
			Collections.sort(list); 
			
			writer.println("// Items");
			for (Integer id : list) {
144
				ItemData data = GameData.getItemDataMap().get(id);
Melledy's avatar
Melledy committed
145
146
147
148
149
				writer.println(data.getId() + " : " + map.get(data.getNameTextMapHash()));
			}
			
			writer.println();
			
150
			writer.println("// Scenes");
151
			list = new ArrayList<>(GameData.getSceneDataMap().keySet());
152
153
154
			Collections.sort(list); 
			
			for (Integer id : list) {
155
				SceneData data = GameData.getSceneDataMap().get(id);
156
157
158
159
160
				writer.println(data.getId() + " : " + data.getScriptData());
			}
			
			writer.println();
			
Melledy's avatar
Melledy committed
161
			writer.println("// Monsters");
162
			list = new ArrayList<>(GameData.getMonsterDataMap().keySet());
Melledy's avatar
Melledy committed
163
164
165
			Collections.sort(list); 
			
			for (Integer id : list) {
166
				MonsterData data = GameData.getMonsterDataMap().get(id);
Melledy's avatar
Melledy committed
167
168
169
170
171
172
				writer.println(data.getId() + " : " + map.get(data.getNameTextMapHash()));
			}
		}
		
		Grasscutter.getLogger().info("GM Handbook generated!");
	}
173
174

	@SuppressWarnings("deprecation")
175
	public static void createGachaMapping(String location, String language) throws Exception {
176
177
178
		ResourceLoader.loadResources();
		
		Map<Long, String> map;
179
		try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap/TextMap"+language+".json")), StandardCharsets.UTF_8)) {
180
181
182
183
184
			map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken<Map<Long, String>>() {}.getType());
		}
		
		List<Integer> list;

185
		String fileName = location;
186
187
188
189
190
191

		try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8), false)) {
			
			list = new ArrayList<>(GameData.getAvatarDataMap().keySet());
			Collections.sort(list); 
			 
192
193
194
			// if the user made choices for language, I assume it's okay to assign his/her selected language to "en-us"
			// since it's the fallback language and there will be no difference in the gacha record page. 
			// The enduser can still modify the `gacha_mappings.js` directly to enable multilingual for the gacha record system.
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
			writer.println("mappings = {\"en-us\": {"); 

			// Avatars
			boolean first = true;
			for (Integer id : list) {
				AvatarData data = GameData.getAvatarDataMap().get(id);
				int avatarID = data.getId();
				if (avatarID >= 11000000) { // skip test avatar
					continue;
				}
				if (first) { // skip adding comma for the first element
					first = false;
				} else {
					writer.print(",");
				}
				String color;
				switch (data.getQualityType()){
					case "QUALITY_PURPLE":
						color = "purple";
						break;
					case "QUALITY_ORANGE":
						color = "yellow";
						break;
					case "QUALITY_BLUE":
					default:
						color = "blue";
				}
222
				// Got the magic number 4233146695 from manually search in the json file
223
224
				writer.println(
					"\"" + (avatarID % 1000 + 1000) + "\" : [\"" 
225
					+ map.get(data.getNameTextMapHash()) + "(" +  map.get(4233146695L)+ ")\", \"" 
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
					+ color + "\"]");
			}
			
			writer.println();
			
			list = new ArrayList<>(GameData.getItemDataMap().keySet());
			Collections.sort(list); 
			
			// Weapons
			for (Integer id : list) {
				ItemData data = GameData.getItemDataMap().get(id);
				if (data.getId() <= 11101 || data.getId() >= 20000) {
					continue; //skip non weapon items
				}
				String color;

				switch (data.getRankLevel()){
					case 3: 
						color = "blue";
						break;
					case 4:
						color = "purple";
						break;
					case 5:
						color = "yellow";
						break;
					default:
						continue; // skip unnecessary entries
				}
255
256
257
				
				// Got the magic number 4231343903 from manually search in the json file

258
259
				writer.println(",\"" + data.getId() +
						 "\" : [\"" + map.get(data.getNameTextMapHash()).replaceAll("\"", "")
260
						 + "("+ map.get(4231343903L)+")\",\""+ color + "\"]");
261
			}
262
			writer.println(",\"200\": \""+map.get(332935371L)+"\", \"301\": \""+ map.get(2272170627L) + "\", \"302\": \""+map.get(2864268523L)+"\"");
263
264
			writer.println("}\n}");
		}
265
		
mingjun97's avatar
mingjun97 committed
266
		Grasscutter.getLogger().info("Mappings generated to " + location + " !");
267
	}
Melledy's avatar
Melledy committed
268
}