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 @@
+
+
+
+
+
+
+
+
+ Banner Details
+
+
+
+
+
+
{{TITLE}}
+
+
{{AVAILABLE_FIVE_STARS}}
+
+
+
+
{{AVAILABLE_FOUR_STARS}}
+
+
+
+
{{AVAILABLE_THREE_STARS}}
+
+
+
+
+
+
+
+
+
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 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 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 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 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."
+ }
}
}