mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-25 11:57:35 +00:00
Utils for gacha history record subsystem
* Auto generate mapping files with command `java -jar grasscutter.jar -gachamap` * Static file provider * For gacha record webpage * All static files should be stored at `GRASSCUTTER_RESOURCE/gcstatic/` * Can benefit other subsystem in future when webpages involved
This commit is contained in:
parent
6a20e383f7
commit
a102613313
@ -102,6 +102,8 @@ You can find the output jar in the root of the project folder.
|
||||
|
||||
You might want to use this command (`java -jar grasscutter.jar -handbook`) in a cmd that is in the grasscutter folder. It will create a handbook file (GM Handbook.txt) where you can find the item IDs for stuff you want
|
||||
|
||||
You may want to use this command (`java -jar grasscutter.jar -gachamap`) to generate a mapping file for the gacha record subsystem. The file will be generated to `GRASSCUTTER_RESOURCE/gcstatic` folder. Otherwise you may only see number IDs in the gacha record page.
|
||||
|
||||
There is a dummy user named "Server" in every player's friends list that you can message to use commands. Commands also work in other chat rooms, such as private/team chats. to run commands ingame, you need to add prefix `/` or `!` such as `/pos`
|
||||
|
||||
| Commands | Usage | Permission node | Availability | description | Alias |
|
||||
|
@ -102,6 +102,8 @@ chmod +x gradlew
|
||||
|
||||
你可能需要在终端中运行 `java -jar grasscutter.jar -handbook` 它将会创建一个 `GM Handbook.txt` 以方便您查阅物品ID等
|
||||
|
||||
你可能需要在终端中运行 `java -jar grasscutter.jar -gachamap` 来使得祈愿历史记录系统正常显示物品信息。 这个命令生成一个配置文件到如下文件夹:`GRASSCUTTER_RESOURCE/gcstatic`。 不执行此命令,您的祈愿历史记录中将只会显示数字ID而非物品名称。(目前仅支持自动生成英文记录信息)
|
||||
|
||||
在每个玩家的朋友列表中都有一个名为“Server”的虚拟用户,你可以通过发送消息来使用命令。命令也适用于其他聊天室,例如私人/团队聊天。
|
||||
要在游戏中使用命令,需要添加 `/` 或 `!` 前缀,如 `/pos`
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<!--Not sure the page is provided in UTF-8 acutally, just put meta here-->
|
||||
<meta charset="utf-8" />
|
||||
<script>
|
||||
// Debug entry
|
||||
// record = [
|
||||
@ -35,7 +37,13 @@
|
||||
302: "Event Weapon",
|
||||
}
|
||||
};
|
||||
mappings['default'] = mappings['en-us'];
|
||||
</script>
|
||||
<!-- This file could be generated automatically using `java -jar grasscutter.jar -gachamap` -->
|
||||
<!-- You can also modify the file manually to customize it -->
|
||||
<!-- Otherwise you may onle see number IDs in the gacha record -->
|
||||
<script type="text/javascript" src="/gcstatic/mappings.js"></script>
|
||||
<script>
|
||||
mappings['default'] = mappings['en-us']; // make en-us as default/fallback option
|
||||
</script>
|
||||
<!-- TODO: Refine the CSS -->
|
||||
<style>
|
||||
@ -43,7 +51,7 @@
|
||||
text-decoration: none !important;
|
||||
}
|
||||
.content {
|
||||
width: 400px;
|
||||
width: 600px;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -119,7 +127,7 @@
|
||||
" "+String(date.getHours()).padStart(2, "0")+
|
||||
":"+String(date.getMinutes()).padStart(2, "0")+
|
||||
":"+String(date.getSeconds()).padStart(2, "0")+
|
||||
"."+date.getMilliseconds();
|
||||
"."+String(date.getMilliseconds()).padStart(3, "0");
|
||||
} else if (lang == "zh-cn") { // YYYY/MM/DD hh:mm:ss.SSS
|
||||
return date.getFullYear()+
|
||||
"/" + String(date.getMonth()+1).padStart(2, "0") +
|
||||
@ -127,7 +135,7 @@
|
||||
" "+String(date.getHours()).padStart(2, "0")+
|
||||
":"+String(date.getMinutes()).padStart(2, "0")+
|
||||
":"+String(date.getSeconds()).padStart(2, "0")+
|
||||
"."+date.getMilliseconds();
|
||||
"."+String(date.getMilliseconds()).padStart(3, "0");
|
||||
}
|
||||
}
|
||||
(function (){
|
||||
|
@ -60,6 +60,9 @@ public final class Grasscutter {
|
||||
case "-handbook" -> {
|
||||
Tools.createGmHandbook(); return;
|
||||
}
|
||||
case "-gachamap" -> {
|
||||
Tools.createGachaMapping(); return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ import emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData;
|
||||
import emu.grasscutter.server.event.dispatch.QueryAllRegionsEvent;
|
||||
import emu.grasscutter.server.event.dispatch.QueryCurrentRegionEvent;
|
||||
import emu.grasscutter.server.http.gacha.GachaRecordHandler;
|
||||
import emu.grasscutter.server.http.gcstatic.StaticFileHandler;
|
||||
import emu.grasscutter.utils.FileUtils;
|
||||
import express.Express;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
@ -445,8 +446,12 @@ public final class DispatchServer {
|
||||
// webstatic-sea.hoyoverse.com
|
||||
httpServer.get("/admin/mi18n/plat_oversea/m202003048/m202003048-version.json", new DispatchHttpJsonHandler("{\"version\":51}"));
|
||||
|
||||
// gacha record
|
||||
httpServer.get("/gacha", new GachaRecordHandler());
|
||||
|
||||
// static file provider
|
||||
httpServer.get("/gcstatic/*", new StaticFileHandler());
|
||||
|
||||
httpServer.listen(Grasscutter.getConfig().getDispatchOptions().Port);
|
||||
Grasscutter.getLogger().info("[Dispatch] Dispatch server started on port " + httpServer.raw().port());
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package emu.grasscutter.server.http.gcstatic;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import express.http.HttpContextHandler;
|
||||
import express.http.Request;
|
||||
import express.http.Response;
|
||||
|
||||
public final class StaticFileHandler implements HttpContextHandler {
|
||||
String static_folder;
|
||||
public StaticFileHandler() {
|
||||
static_folder = Grasscutter.getConfig().RESOURCE_FOLDER + "/gcstatic";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Request req, Response res) throws IOException {
|
||||
// Grasscutter.getLogger().info( req.path());
|
||||
|
||||
String reqFilename = req.path().replace("/gcstatic", ""); // remove the leading path
|
||||
reqFilename = reqFilename.replace("/../", "/./"); // security guard to prevent arbitrary read
|
||||
File resFile = new File(static_folder + reqFilename);
|
||||
if (resFile.exists()) {
|
||||
res.sendFile(resFile.toPath());
|
||||
} else {
|
||||
res.status(404);
|
||||
res.send("404");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package emu.grasscutter.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
@ -93,4 +94,96 @@ public final class Tools {
|
||||
|
||||
Grasscutter.getLogger().info("GM Handbook generated!");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void createGachaMapping() throws Exception {
|
||||
ResourceLoader.loadResources();
|
||||
|
||||
Map<Long, String> map;
|
||||
try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap/TextMapEN.json")), StandardCharsets.UTF_8)) {
|
||||
map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken<Map<Long, String>>() {}.getType());
|
||||
}
|
||||
|
||||
List<Integer> list;
|
||||
|
||||
|
||||
String fileName = Grasscutter.getConfig().RESOURCE_FOLDER + "/gcstatic";
|
||||
File folder = new File(fileName);
|
||||
if (!folder.exists()) { folder.mkdirs(); } // create folder if it doesn't exist
|
||||
fileName = fileName + "/mappings.js";
|
||||
|
||||
try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8), false)) {
|
||||
|
||||
list = new ArrayList<>(GameData.getAvatarDataMap().keySet());
|
||||
Collections.sort(list);
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
writer.println(
|
||||
"\"" + (avatarID % 1000 + 1000) + "\" : [\""
|
||||
+ map.get(data.getNameTextMapHash()) + "(Avatar)\", \""
|
||||
+ 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
|
||||
}
|
||||
writer.println(",\"" + data.getId() +
|
||||
"\" : [\"" + map.get(data.getNameTextMapHash()).replaceAll("\"", "")
|
||||
+ "(Weapon)\",\""+ color + "\"]");
|
||||
}
|
||||
writer.println(",\"200\": \"Standard\", \"301\": \"Avatar Event\", \"302\": \"Weapon event\"");
|
||||
writer.println("}\n}");
|
||||
}
|
||||
Grasscutter.getLogger().info("Mappings generated!");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user