From 1d4e0e09d04f2e7427af35af355ac2dbe86a6fbe Mon Sep 17 00:00:00 2001 From: ImmuState <kyoko12@gmx.at> Date: Wed, 11 May 2022 11:19:25 -0700 Subject: [PATCH] Add gacha details page. --- data/gacha_details.html | 121 ++++++++++++++++++ .../grasscutter/game/gacha/GachaBanner.java | 9 +- .../grasscutter/game/gacha/GachaManager.java | 18 ++- .../server/dispatch/DispatchServer.java | 4 + .../dispatch/http/GachaDetailsHandler.java | 90 +++++++++++++ src/main/resources/languages/en-US.json | 9 ++ src/main/resources/languages/pl-PL.json | 9 ++ src/main/resources/languages/zh-CN.json | 9 ++ src/main/resources/languages/zh-TW.json | 9 ++ 9 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 data/gacha_details.html create mode 100644 src/main/java/emu/grasscutter/server/dispatch/http/GachaDetailsHandler.java diff --git a/data/gacha_details.html b/data/gacha_details.html new file mode 100644 index 000000000..16cf7313a --- /dev/null +++ b/data/gacha_details.html @@ -0,0 +1,121 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400&display=swap"> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"> + <style> + body { + background-color: #f0f0f0; + } + p { + font-weight:300; + } + a,a:hover { + text-decoration:none !important; + color:#626976; + } + .content { + padding:3rem 0; + } + .container { + color:#626976; + position: relative; + } + + h2 { + font-size:20px; + } + h3 { + font-size:16px; + } + </style> + <title>Banner Details</title> + <script type="text/javascript" src="/gacha/mappings"></script> + </head> + <body> + <div class="content"> + <div class="container"> + <h2 class="mb-5">{{TITLE}}</h2> + + <h3 class="">{{AVAILABLE_FIVE_STARS}}</h3> + <hr /> + <ul id="5-star-list"> + </ul> + + <h3 class="">{{AVAILABLE_FOUR_STARS}}</h3> + <hr /> + <ul id="4-star-list"> + </ul> + + <h3 class="">{{AVAILABLE_THREE_STARS}}</h3> + <hr /> + <ul id="3-star-list"> + </ul> + </div> + </div> + <footer> + <div class="copyright"> + <div class="container"> + <div class="row"> + <div class="col-md-6"> + <span> + Template by BecodReyes. All rights reserved. + </span> + </div> + <div class="col-md-6"> + <ul style="float:right"> + <li class="list-inline-item"> + <a href="https://github.com/Grasscutters/Grasscutter">Github</a> + </li> + <li class="list-inline-item">·</li> + <li class="list-inline-item"> + <a href="https://github.com/Grasscutters/Grasscutter/blob/stable/LICENSE">License</a> + </li> + </ul> + </div> + </div> + </div> + </div> + </footer> + + <script> + fiveStarItems = {{FIVE_STARS}}; + fourStarItems = {{FOUR_STARS}}; + threeStarItems = {{THREE_STARS}}; + + var lang = new window.URLSearchParams(window.location.search).get("lang"); + function getNameForId(itemId) { + if (mappings[lang] != null && mappings[lang][itemId] != null) { + return mappings[lang][itemId][0]; + } + else if (mappings["en-us"] != null && mappings["en-us"][itemId] != null) { + return mappings["en-us"][itemId][0]; + } + + return itemId.toString(); + } + + fiveStarList = document.getElementById("5-star-list"); + fourStarList = document.getElementById("4-star-list"); + threeStarList = document.getElementById("3-star-list"); + + fiveStarItems.forEach(element => { + var entry = document.createElement("li"); + entry.innerHTML = getNameForId(element); + fiveStarList.appendChild(entry); + }); + fourStarItems.forEach(element => { + var entry = document.createElement("li"); + entry.innerHTML = getNameForId(element); + fourStarList.appendChild(entry); + }); + threeStarItems.forEach(element => { + var entry = document.createElement("li"); + entry.innerHTML = getNameForId(element); + threeStarList.appendChild(entry); + }); + </script> + </body> +</html> diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java index dce433fcf..7a2646a4f 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java @@ -102,6 +102,11 @@ public class GachaBanner { + lr(DISPATCH_INFO.accessAddress, DISPATCH_INFO.bindAddress) + ":" + lr(DISPATCH_INFO.accessPort, DISPATCH_INFO.bindPort) + "/gacha?s=" + sessionKey + "&gachaType=" + gachaType; + String details = "http" + (DISPATCH_INFO.encryption.useInRouting ? "s" : "") + "://" + + lr(DISPATCH_INFO.accessAddress, DISPATCH_INFO.bindAddress) + ":" + + lr(DISPATCH_INFO.accessPort, DISPATCH_INFO.bindPort) + + "/gacha/details?s=" + sessionKey + "&gachaType=" + gachaType; + // Grasscutter.getLogger().info("record = " + record); GachaInfo.Builder info = GachaInfo.newBuilder() .setGachaType(this.getGachaType()) @@ -112,8 +117,8 @@ public class GachaBanner { .setCostItemNum(1) .setGachaPrefabPath(this.getPrefabPath()) .setGachaPreviewPrefabPath(this.getPreviewPrefabPath()) - .setGachaProbUrl(record) - .setGachaProbUrlOversea(record) + .setGachaProbUrl(details) + .setGachaProbUrlOversea(details) .setGachaRecordUrl(record) .setGachaRecordUrlOversea(record) .setTenCostItemId(this.getCostItem()) diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java index 03edca09a..f0baf65a9 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java @@ -65,7 +65,23 @@ public class GachaManager { public Int2ObjectMap<GachaBanner> getGachaBanners() { return gachaBanners; } - + + public int[] getYellowAvatars() { + return this.yellowAvatars; + } + public int[] getYellowWeapons() { + return this.yellowWeapons; + } + public int[] getPurpleAvatars() { + return this.purpleAvatars; + } + public int[] getPurpleWeapons() { + return this.purpleWeapons; + } + public int[] getBlueWeapons() { + return this.blueWeapons; + } + public int randomRange(int min, int max) { return ThreadLocalRandom.current().nextInt(max - min + 1) + min; } diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java index 4e09f8881..c78aff7c6 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java +++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java @@ -16,6 +16,7 @@ import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo; import emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo; import emu.grasscutter.server.dispatch.authentication.AuthenticationHandler; import emu.grasscutter.server.dispatch.authentication.DefaultAuthenticationHandler; +import emu.grasscutter.server.dispatch.http.GachaDetailsHandler; import emu.grasscutter.server.dispatch.http.GachaRecordHandler; import emu.grasscutter.server.dispatch.json.*; import emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData; @@ -455,6 +456,9 @@ public final class DispatchServer { httpServer.raw().config.addSinglePageRoot("/gacha/mappings", gachaMappingsPath, Location.EXTERNAL); + // gacha details + httpServer.get("/gacha/details", new GachaDetailsHandler()); + // static file support for plugins httpServer.raw().config.precompressStaticFiles = false; // If this isn't set to false, files such as images may appear corrupted when serving static files diff --git a/src/main/java/emu/grasscutter/server/dispatch/http/GachaDetailsHandler.java b/src/main/java/emu/grasscutter/server/dispatch/http/GachaDetailsHandler.java new file mode 100644 index 000000000..d46cead40 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/dispatch/http/GachaDetailsHandler.java @@ -0,0 +1,90 @@ +package emu.grasscutter.server.dispatch.http; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.gacha.GachaBanner; +import emu.grasscutter.game.gacha.GachaManager; +import emu.grasscutter.game.gacha.GachaBanner.BannerType; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import express.http.HttpContextHandler; +import express.http.Request; +import express.http.Response; + +import static emu.grasscutter.utils.Language.translate; + +import static emu.grasscutter.Configuration.*; + +public final class GachaDetailsHandler implements HttpContextHandler { + private final String render_template; + + public GachaDetailsHandler() { + File template = new File(Utils.toFilePath(DATA("/gacha_details.html"))); + this.render_template = template.exists() ? new String(FileUtils.read(template)) : null; + } + + @Override + public void handle(Request req, Response res) throws IOException { + String response = this.render_template; + + // Get player info (for langauge). + String sessionKey = req.query("s"); + Account account = DatabaseHelper.getAccountBySessionKey(sessionKey); + Player player = Grasscutter.getGameServer().getPlayerByUid(account.getPlayerUid()); + + // If the template was not loaded, return an error. + if (this.render_template == null) { + res.send(translate(player, "gacha.details.template_missing")); + return; + } + + // Add translated title etc. to the page. + response = response.replace("{{TITLE}}", translate(player, "gacha.details.title")); + response = response.replace("{{AVAILABLE_FIVE_STARS}}", translate(player, "gacha.details.available_five_stars")); + response = response.replace("{{AVAILABLE_FOUR_STARS}}", translate(player, "gacha.details.available_four_stars")); + response = response.replace("{{AVAILABLE_THREE_STARS}}", translate(player, "gacha.details.available_three_stars")); + + // Get the banner info for the banner we want. + int gachaType = Integer.parseInt(req.query("gachaType")); + GachaManager manager = Grasscutter.getGameServer().getGachaManager(); + GachaBanner banner = manager.getGachaBanners().get(gachaType); + + // Add 5-star items. + Set<String> fiveStarItems = new LinkedHashSet<>(); + + Arrays.stream(banner.getRateUpItems1()).forEach(i -> fiveStarItems.add(Integer.toString(i))); + if (banner.getBannerType() == BannerType.STANDARD || banner.getBannerType() == BannerType.EVENT) { + Arrays.stream(manager.getYellowAvatars()).forEach(i -> fiveStarItems.add(Integer.toString(i))); + } + if (banner.getBannerType() == BannerType.STANDARD || banner.getBannerType() == BannerType.WEAPON) { + Arrays.stream(manager.getYellowWeapons()).forEach(i -> fiveStarItems.add(Integer.toString(i))); + } + + response = response.replace("{{FIVE_STARS}}", "[" + String.join(",", fiveStarItems) + "]"); + + // Add 4-star items. + Set<String> fourStarItems = new LinkedHashSet<>(); + + Arrays.stream(banner.getRateUpItems2()).forEach(i -> fourStarItems.add(Integer.toString(i))); + Arrays.stream(manager.getPurpleAvatars()).forEach(i -> fourStarItems.add(Integer.toString(i))); + Arrays.stream(manager.getPurpleWeapons()).forEach(i -> fourStarItems.add(Integer.toString(i))); + + response = response.replace("{{FOUR_STARS}}", "[" + String.join(",", fourStarItems) + "]"); + + // Add 3-star items. + Set<String> threeStarItems = new LinkedHashSet<>(); + Arrays.stream(manager.getBlueWeapons()).forEach(i -> threeStarItems.add(Integer.toString(i))); + response = response.replace("{{THREE_STARS}}", "[" + String.join(",", threeStarItems) + "]"); + + // Done. + res.send(response); + } +} diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index 81e97eed7..42b52d7f5 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -352,5 +352,14 @@ "resetshop": { "description": "reset shop" } + }, + "gacha": { + "details": { + "title": "Banner Details", + "available_five_stars": "Available 5-star Items", + "available_four_stars": "Available 4-star Items", + "available_three_stars": "Available 3-star Items", + "template_missing": "data/gacha_details.html is missing." + } } } diff --git a/src/main/resources/languages/pl-PL.json b/src/main/resources/languages/pl-PL.json index aa06723d8..e5eff2d84 100644 --- a/src/main/resources/languages/pl-PL.json +++ b/src/main/resources/languages/pl-PL.json @@ -302,5 +302,14 @@ "resetshop": { "description": "zresetuj sklep" } + }, + "gacha": { + "details": { + "title": "Banner Details", + "available_five_stars": "Available 5-star Items", + "available_four_stars": "Available 4-star Items", + "available_three_stars": "Available 3-star Items", + "template_missing": "data/gacha_details.html is missing." + } } } \ No newline at end of file diff --git a/src/main/resources/languages/zh-CN.json b/src/main/resources/languages/zh-CN.json index 84d4a8c94..ac46370d5 100644 --- a/src/main/resources/languages/zh-CN.json +++ b/src/main/resources/languages/zh-CN.json @@ -349,5 +349,14 @@ "resetshop": { "description": "重置商店刷新时间" } + }, + "gacha": { + "details": { + "title": "Banner Details", + "available_five_stars": "Available 5-star Items", + "available_four_stars": "Available 4-star Items", + "available_three_stars": "Available 3-star Items", + "template_missing": "data/gacha_details.html is missing." + } } } diff --git a/src/main/resources/languages/zh-TW.json b/src/main/resources/languages/zh-TW.json index 8e7a75949..f6ae52c9d 100644 --- a/src/main/resources/languages/zh-TW.json +++ b/src/main/resources/languages/zh-TW.json @@ -302,5 +302,14 @@ "resetshop": { "description": "重置商店時間" } + }, + "gacha": { + "details": { + "title": "Banner Details", + "available_five_stars": "Available 5-star Items", + "available_four_stars": "Available 4-star Items", + "available_three_stars": "Available 3-star Items", + "template_missing": "data/gacha_details.html is missing." + } } }