Tools.java 8.87 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
import emu.grasscutter.command.Command;
24
import emu.grasscutter.command.CommandHandler;
25
import emu.grasscutter.command.CommandMap;
26
import emu.grasscutter.data.GameData;
Melledy's avatar
Melledy committed
27
28
29
30
import emu.grasscutter.data.ResourceLoader;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.data.def.MonsterData;
31
import emu.grasscutter.data.def.SceneData;
32
import emu.grasscutter.utils.Utils;
Melledy's avatar
Melledy committed
33

方块君's avatar
方块君 committed
34
35
import static emu.grasscutter.utils.Language.translate;

KingRainbow44's avatar
KingRainbow44 committed
36
public final class Tools {
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
	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
64
	
65
66
67
68
		// Use system out for better format
		if (availableLangList.size() == 1) {
			return availableLangList.get(0).toUpperCase();
		}
mingjun97's avatar
mingjun97 committed
69
70
71
		String stagedMessage = "";
		stagedMessage += "The following languages mappings are available, please select one: [default: EN]\n";
		String groupedLangList = ">\t";
72
73
74
75
76
77
		int groupedLangCount = 0;
		String input = "";
		for (String availableLanguage: availableLangList){
			groupedLangCount++;
			groupedLangList = groupedLangList + "" + availableLanguage + "\t";
			if (groupedLangCount == 6) {
mingjun97's avatar
mingjun97 committed
78
				stagedMessage += groupedLangList + "\n";
79
				groupedLangCount = 0;
mingjun97's avatar
mingjun97 committed
80
				groupedLangList = ">\t";
81
82
83
			}
		}
		if (groupedLangCount > 0) {
mingjun97's avatar
mingjun97 committed
84
			stagedMessage += groupedLangList + "\n";
85
		}
mingjun97's avatar
mingjun97 committed
86
87
88
		stagedMessage += "\nYour choice:[EN] ";
		
		input = Grasscutter.getConsole().readLine(stagedMessage);
89
90
91
92
93
94
95
96
97
98
		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
99
	@SuppressWarnings("deprecation")
100
	public static void createGmHandbook(String language) throws Exception {
Melledy's avatar
Melledy committed
101
102
103
		ResourceLoader.loadResources();
		
		Map<Long, String> map;
104
		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
105
106
107
108
109
			map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken<Map<Long, String>>() {}.getType());
		}
		
		List<Integer> list;
		String fileName = "./GM Handbook.txt";
110
		try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8), false)) {
Melledy's avatar
Melledy committed
111
112
113
			DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");  
			LocalDateTime now = LocalDateTime.now();
			   
114
			writer.println("// Grasscutter " + GameConstants.VERSION + " GM Handbook");
Melledy's avatar
Melledy committed
115
			writer.println("// Created " + dtf.format(now) + System.lineSeparator() + System.lineSeparator());
116
117

			CommandMap cmdMap = new CommandMap(true);
方块君's avatar
方块君 committed
118
			List<Command> cmdList = new ArrayList<>(cmdMap.getAnnotationsAsList());
119
120

			writer.println("// Commands");
方块君's avatar
方块君 committed
121
122
			for (Command cmd : cmdList) {
				String cmdName = cmd.label();
123
124
125
				while (cmdName.length() <= 15) {
					cmdName = " " + cmdName;
				}
方块君's avatar
方块君 committed
126
127
				writer.println(cmdName + " : " + translate(cmd.description()));
			}
128
129
			writer.println();

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

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

187
		String fileName = location;
188
189
190
191
192
193

		try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8), false)) {
			
			list = new ArrayList<>(GameData.getAvatarDataMap().keySet());
			Collections.sort(list); 
			 
194
195
196
			// 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.
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
222
223
			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";
				}
224
				// Got the magic number 4233146695 from manually search in the json file
225
226
				writer.println(
					"\"" + (avatarID % 1000 + 1000) + "\" : [\"" 
227
					+ map.get(data.getNameTextMapHash()) + "(" +  map.get(4233146695L)+ ")\", \"" 
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
255
256
					+ 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
				}
257
258
259
				
				// Got the magic number 4231343903 from manually search in the json file

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