mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-30 17:28:50 +00:00
Implement gacha history record subsystem
* Frontend is not very beautiful yet * Didn't include too much `some anime game` data in the page to avoid being DMCA'd
This commit is contained in:
parent
22a651b4aa
commit
8cf4ef59ec
176
data/gacha_records.html
Normal file
176
data/gacha_records.html
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
// Debug entry
|
||||||
|
// record = [
|
||||||
|
// {"time": 10000341, "item": 1001},
|
||||||
|
// {"time": 10000342, "item": 1002},
|
||||||
|
// {"time": 10000343, "item": 1003},
|
||||||
|
// ];
|
||||||
|
// maxPage = 5;
|
||||||
|
|
||||||
|
// in production environment
|
||||||
|
record = {{REPLACE_RECORD}};
|
||||||
|
maxPage = {{REPLACE_MAXPAGE}};
|
||||||
|
|
||||||
|
// TODO: implement this mapper by yourself
|
||||||
|
// I don't want to put real items' name here to avoid being DMCA'd
|
||||||
|
mappings = {
|
||||||
|
'en-us': {
|
||||||
|
200: "Standard",
|
||||||
|
301: "Event Avatar",
|
||||||
|
302: "Event Weapon",
|
||||||
|
1041 : ["M0n4", "yellow"],
|
||||||
|
1032 : ["B4nn477", "purple"],
|
||||||
|
1035 : ["77", "yellow"]
|
||||||
|
},
|
||||||
|
'zh-cn': {
|
||||||
|
// encoding issues here, maybe we should consider load mappings remotely
|
||||||
|
// will display as "锟斤铐锟斤铐锟斤铐", lmao
|
||||||
|
// 200: "常驻",
|
||||||
|
// 301: "角色UP-1",
|
||||||
|
// 302: "武器UP"
|
||||||
|
200: "Standard",
|
||||||
|
301: "Event Avatar",
|
||||||
|
302: "Event Weapon",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mappings['default'] = mappings['en-us'];
|
||||||
|
</script>
|
||||||
|
<!-- TODO: Refine the CSS -->
|
||||||
|
<style>
|
||||||
|
a {
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
width: 400px;
|
||||||
|
margin: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .navbar {
|
||||||
|
margin: auto;
|
||||||
|
width: fit-content;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.yellow {
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blue {
|
||||||
|
color: rgb(75, 107, 251);
|
||||||
|
}
|
||||||
|
|
||||||
|
.purple {
|
||||||
|
color: rgb(242, 40, 242);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="background: skyblue;">
|
||||||
|
<div class="content">
|
||||||
|
<h1>Gacha Records</h1>
|
||||||
|
<h2 id="gacha-type"></h2>
|
||||||
|
<br/>
|
||||||
|
<div style="width: fit-content">
|
||||||
|
<table border="1">
|
||||||
|
<tbody id="container">
|
||||||
|
<tr>
|
||||||
|
<th>Time</th>
|
||||||
|
<th>Item</th>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="navbar">
|
||||||
|
<a href="" id="prev"> < </a>
|
||||||
|
<span id="curpage">1</span>
|
||||||
|
<a href="" id="next"> > </a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var lang = new window.URLSearchParams(window.location.search).get("lang");
|
||||||
|
function itemMapper(itemID) {
|
||||||
|
if (mappings[lang] != null && mappings[lang][itemID] != null) {
|
||||||
|
var entry = mappings[lang][itemID];
|
||||||
|
if (entry){
|
||||||
|
return "<span class='" + entry[1] + "'>" + entry[0] + "</span>";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mappings['default'][itemID] != null) {
|
||||||
|
var entry = mappings['default'][itemID];
|
||||||
|
if (entry){
|
||||||
|
return "<span class='" + entry[1] + "'>" + entry[0] + "</span>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "<span class='blue'>" + itemID + "</span>";
|
||||||
|
}
|
||||||
|
function dateFormatter(timeStamp) {
|
||||||
|
var date = new Date(timeStamp);
|
||||||
|
if (lang == "en-us" || lang == null) { // MM/DD/YYYY hh:mm:ss.SSS
|
||||||
|
return String(date.getMonth()+1).padStart(2, "0") +
|
||||||
|
"/"+String(date.getDate()).padStart(2, "0")+
|
||||||
|
"/"+date.getFullYear()+
|
||||||
|
" "+String(date.getHours()).padStart(2, "0")+
|
||||||
|
":"+String(date.getMinutes()).padStart(2, "0")+
|
||||||
|
":"+String(date.getSeconds()).padStart(2, "0")+
|
||||||
|
"."+date.getMilliseconds();
|
||||||
|
} else if (lang == "zh-cn") { // YYYY/MM/DD hh:mm:ss.SSS
|
||||||
|
return date.getFullYear()+
|
||||||
|
"/" + String(date.getMonth()+1).padStart(2, "0") +
|
||||||
|
"/"+String(date.getDate()).padStart(2, "0")+
|
||||||
|
" "+String(date.getHours()).padStart(2, "0")+
|
||||||
|
":"+String(date.getMinutes()).padStart(2, "0")+
|
||||||
|
":"+String(date.getSeconds()).padStart(2, "0")+
|
||||||
|
"."+date.getMilliseconds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(function (){
|
||||||
|
var container = document.getElementById("container");
|
||||||
|
record.forEach(element => {
|
||||||
|
var e = document.createElement("tr");
|
||||||
|
|
||||||
|
e.innerHTML= "<td>" + dateFormatter(element.time) + "</td><td>" + itemMapper(element.item) + "</td>";
|
||||||
|
container.appendChild(e);
|
||||||
|
});
|
||||||
|
// setup pagenation buttons
|
||||||
|
var page = parseInt(new window.URLSearchParams(window.location.search).get("p"));
|
||||||
|
if (!page){
|
||||||
|
page = 0;
|
||||||
|
}
|
||||||
|
document.getElementById("curpage").innerText = page + 1;
|
||||||
|
var href = new URL(window.location);
|
||||||
|
href.searchParams.set("p", page - 1);
|
||||||
|
document.getElementById("prev").href = href.toString();
|
||||||
|
href.searchParams.set("p", page + 1);
|
||||||
|
document.getElementById("next").href = href.toString();
|
||||||
|
|
||||||
|
if (page <= 0) {
|
||||||
|
document.getElementById("prev").style.display = "none";
|
||||||
|
}
|
||||||
|
if (page >= maxPage - 1) {
|
||||||
|
document.getElementById("next").style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup gacha type info
|
||||||
|
var gachaType = new window.URLSearchParams(window.location.search).get("gachaType");
|
||||||
|
var gachaString;
|
||||||
|
if (mappings[lang] != null && mappings[lang][gachaType] != null) {
|
||||||
|
gachaString = mappings[lang][gachaType];
|
||||||
|
}else{
|
||||||
|
gachaString = mappings['default'][gachaType];
|
||||||
|
if (gachaString == null) {
|
||||||
|
gachaString = gachaType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.getElementById("gacha-type").innerText = gachaString;
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -3,11 +3,14 @@ package emu.grasscutter.database;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.mongodb.client.result.DeleteResult;
|
import com.mongodb.client.result.DeleteResult;
|
||||||
|
import dev.morphia.query.FindOptions;
|
||||||
|
import dev.morphia.query.Sort;
|
||||||
import dev.morphia.query.experimental.filters.Filters;
|
import dev.morphia.query.experimental.filters.Filters;
|
||||||
import emu.grasscutter.GameConstants;
|
import emu.grasscutter.GameConstants;
|
||||||
import emu.grasscutter.game.Account;
|
import emu.grasscutter.game.Account;
|
||||||
import emu.grasscutter.game.avatar.Avatar;
|
import emu.grasscutter.game.avatar.Avatar;
|
||||||
import emu.grasscutter.game.friends.Friendship;
|
import emu.grasscutter.game.friends.Friendship;
|
||||||
|
import emu.grasscutter.game.gacha.GachaRecord;
|
||||||
import emu.grasscutter.game.inventory.GameItem;
|
import emu.grasscutter.game.inventory.GameItem;
|
||||||
import emu.grasscutter.game.player.Player;
|
import emu.grasscutter.game.player.Player;
|
||||||
|
|
||||||
@ -78,6 +81,11 @@ public final class DatabaseHelper {
|
|||||||
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("token", token)).first();
|
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("token", token)).first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Account getAccountBySessionKey(String sessionKey) {
|
||||||
|
if(sessionKey == null) return null;
|
||||||
|
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("sessionKey", sessionKey)).first();
|
||||||
|
}
|
||||||
|
|
||||||
public static Account getAccountById(String uid) {
|
public static Account getAccountById(String uid) {
|
||||||
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("_id", uid)).first();
|
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("_id", uid)).first();
|
||||||
}
|
}
|
||||||
@ -181,5 +189,36 @@ public final class DatabaseHelper {
|
|||||||
)).first();
|
)).first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<GachaRecord> getGachaRecords(int ownerId, int page, int gachaType){
|
||||||
|
return getGachaRecords(ownerId, page, gachaType, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<GachaRecord> getGachaRecords(int ownerId, int page, int gachaType, int pageSize){
|
||||||
|
return DatabaseManager.getDatastore().find(GachaRecord.class).filter(
|
||||||
|
Filters.eq("ownerId", ownerId),
|
||||||
|
Filters.eq("gachaType", gachaType)
|
||||||
|
).iterator(new FindOptions()
|
||||||
|
.sort(Sort.descending("transactionDate"))
|
||||||
|
.skip(pageSize * page)
|
||||||
|
.limit(pageSize)
|
||||||
|
).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getGachaRecordsMaxPage(int ownerId, int page, int gachaType){
|
||||||
|
return getGachaRecordsMaxPage(ownerId, page, gachaType, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getGachaRecordsMaxPage(int ownerId, int page, int gachaType, int pageSize){
|
||||||
|
long count = DatabaseManager.getDatastore().find(GachaRecord.class).filter(
|
||||||
|
Filters.eq("ownerId", ownerId),
|
||||||
|
Filters.eq("gachaType", gachaType)
|
||||||
|
).count();
|
||||||
|
return count / 10 + (count % 10 > 0 ? 1 : 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveGachaRecord(GachaRecord gachaRecord){
|
||||||
|
DatabaseManager.getDatastore().save(gachaRecord);
|
||||||
|
}
|
||||||
|
|
||||||
public static char AWJVN = 'e';
|
public static char AWJVN = 'e';
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import emu.grasscutter.Grasscutter.ServerRunMode;
|
|||||||
import emu.grasscutter.game.Account;
|
import emu.grasscutter.game.Account;
|
||||||
import emu.grasscutter.game.avatar.Avatar;
|
import emu.grasscutter.game.avatar.Avatar;
|
||||||
import emu.grasscutter.game.friends.Friendship;
|
import emu.grasscutter.game.friends.Friendship;
|
||||||
|
import emu.grasscutter.game.gacha.GachaRecord;
|
||||||
import emu.grasscutter.game.inventory.GameItem;
|
import emu.grasscutter.game.inventory.GameItem;
|
||||||
import emu.grasscutter.game.player.Player;
|
import emu.grasscutter.game.player.Player;
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ public final class DatabaseManager {
|
|||||||
private static Datastore dispatchDatastore;
|
private static Datastore dispatchDatastore;
|
||||||
|
|
||||||
private static final Class<?>[] mappedClasses = new Class<?>[] {
|
private static final Class<?>[] mappedClasses = new Class<?>[] {
|
||||||
DatabaseCounter.class, Account.class, Player.class, Avatar.class, GameItem.class, Friendship.class
|
DatabaseCounter.class, Account.class, Player.class, Avatar.class, GameItem.class, Friendship.class, GachaRecord.class
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Datastore getDatastore() {
|
public static Datastore getDatastore() {
|
||||||
|
@ -91,9 +91,21 @@ public class GachaBanner {
|
|||||||
return eventChance;
|
return eventChance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public GachaInfo toProto() {
|
public GachaInfo toProto() {
|
||||||
String record = "http://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + "/gacha";
|
return toProto("");
|
||||||
|
}
|
||||||
|
public GachaInfo toProto(String sessionKey) {
|
||||||
|
String record = "https://"
|
||||||
|
+ (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ?
|
||||||
|
Grasscutter.getConfig().getDispatchOptions().Ip :
|
||||||
|
Grasscutter.getConfig().getDispatchOptions().PublicIp)
|
||||||
|
+ ":"
|
||||||
|
+ Integer.toString(Grasscutter.getConfig().getDispatchOptions().PublicPort == 0 ?
|
||||||
|
Grasscutter.getConfig().getDispatchOptions().Port :
|
||||||
|
Grasscutter.getConfig().getDispatchOptions().PublicPort)
|
||||||
|
+ "/gacha?s=" + sessionKey + "&gachaType=" + gachaType;
|
||||||
|
// Grasscutter.getLogger().info("record = " + record);
|
||||||
GachaInfo.Builder info = GachaInfo.newBuilder()
|
GachaInfo.Builder info = GachaInfo.newBuilder()
|
||||||
.setGachaType(this.getGachaType())
|
.setGachaType(this.getGachaType())
|
||||||
.setScheduleId(this.getScheduleId())
|
.setScheduleId(this.getScheduleId())
|
||||||
|
@ -14,6 +14,7 @@ import com.sun.nio.file.SensitivityWatchEventModifier;
|
|||||||
import emu.grasscutter.Grasscutter;
|
import emu.grasscutter.Grasscutter;
|
||||||
import emu.grasscutter.data.GameData;
|
import emu.grasscutter.data.GameData;
|
||||||
import emu.grasscutter.data.def.ItemData;
|
import emu.grasscutter.data.def.ItemData;
|
||||||
|
import emu.grasscutter.database.DatabaseHelper;
|
||||||
import emu.grasscutter.game.avatar.Avatar;
|
import emu.grasscutter.game.avatar.Avatar;
|
||||||
import emu.grasscutter.game.gacha.GachaBanner.BannerType;
|
import emu.grasscutter.game.gacha.GachaBanner.BannerType;
|
||||||
import emu.grasscutter.game.inventory.GameItem;
|
import emu.grasscutter.game.inventory.GameItem;
|
||||||
@ -197,6 +198,10 @@ public class GachaManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write gacha record
|
||||||
|
GachaRecord gachaRecord = new GachaRecord(itemId, player.getUid(), gachaType);
|
||||||
|
DatabaseHelper.saveGachaRecord(gachaRecord);
|
||||||
|
|
||||||
// Create gacha item
|
// Create gacha item
|
||||||
GachaItem.Builder gachaItem = GachaItem.newBuilder();
|
GachaItem.Builder gachaItem = GachaItem.newBuilder();
|
||||||
int addStardust = 0, addStarglitter = 0;
|
int addStardust = 0, addStarglitter = 0;
|
||||||
@ -321,6 +326,7 @@ public class GachaManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
private synchronized GetGachaInfoRsp createProto() {
|
private synchronized GetGachaInfoRsp createProto() {
|
||||||
GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345);
|
GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345);
|
||||||
|
|
||||||
@ -331,11 +337,25 @@ public class GachaManager {
|
|||||||
return proto.build();
|
return proto.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized GetGachaInfoRsp createProto(String sessionKey) {
|
||||||
|
GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345);
|
||||||
|
|
||||||
|
for (GachaBanner banner : getGachaBanners().values()) {
|
||||||
|
proto.addGachaInfoList(banner.toProto(sessionKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
return proto.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public GetGachaInfoRsp toProto() {
|
public GetGachaInfoRsp toProto() {
|
||||||
if (this.cachedProto == null) {
|
if (this.cachedProto == null) {
|
||||||
this.cachedProto = createProto();
|
this.cachedProto = createProto();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.cachedProto;
|
return this.cachedProto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GetGachaInfoRsp toProto(String sessionKey) {
|
||||||
|
return createProto(sessionKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
75
src/main/java/emu/grasscutter/game/gacha/GachaRecord.java
Normal file
75
src/main/java/emu/grasscutter/game/gacha/GachaRecord.java
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package emu.grasscutter.game.gacha;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
|
import dev.morphia.annotations.*;
|
||||||
|
|
||||||
|
@Entity(value = "gachas", useDiscriminator = false)
|
||||||
|
public class GachaRecord {
|
||||||
|
@Id private ObjectId id;
|
||||||
|
|
||||||
|
@Indexed private int ownerId;
|
||||||
|
|
||||||
|
private Date transactionDate;
|
||||||
|
private int itemID;
|
||||||
|
@Indexed private int gachaType;
|
||||||
|
|
||||||
|
public GachaRecord() {}
|
||||||
|
|
||||||
|
public GachaRecord(int itemId ,int ownerId, int gachaType){
|
||||||
|
this.transactionDate = new Date();
|
||||||
|
this.itemID = itemId;
|
||||||
|
this.ownerId = ownerId;
|
||||||
|
this.gachaType = gachaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOwnerId() {
|
||||||
|
return ownerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwnerId(int ownerId) {
|
||||||
|
this.ownerId = ownerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGachaType() {
|
||||||
|
return gachaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGachaType(int type) {
|
||||||
|
this.gachaType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getTransactionDate() {
|
||||||
|
return transactionDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransactionDate(Date transactionDate) {
|
||||||
|
this.transactionDate = transactionDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemID() {
|
||||||
|
return itemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemID(int itemID) {
|
||||||
|
this.itemID = itemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectId getId(){
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(ObjectId id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return toJsonString();
|
||||||
|
}
|
||||||
|
public String toJsonString() {
|
||||||
|
return "{\"time\": " + this.transactionDate.getTime() + ",\"item\":" + this.itemID + "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -18,6 +18,7 @@ import emu.grasscutter.server.dispatch.json.*;
|
|||||||
import emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData;
|
import emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData;
|
||||||
import emu.grasscutter.server.event.dispatch.QueryAllRegionsEvent;
|
import emu.grasscutter.server.event.dispatch.QueryAllRegionsEvent;
|
||||||
import emu.grasscutter.server.event.dispatch.QueryCurrentRegionEvent;
|
import emu.grasscutter.server.event.dispatch.QueryCurrentRegionEvent;
|
||||||
|
import emu.grasscutter.server.http.gacha.GachaRecordHandler;
|
||||||
import emu.grasscutter.utils.FileUtils;
|
import emu.grasscutter.utils.FileUtils;
|
||||||
import express.Express;
|
import express.Express;
|
||||||
import org.eclipse.jetty.server.Connector;
|
import org.eclipse.jetty.server.Connector;
|
||||||
@ -485,7 +486,7 @@ public final class DispatchServer {
|
|||||||
// webstatic-sea.hoyoverse.com
|
// webstatic-sea.hoyoverse.com
|
||||||
httpServer.get("/admin/mi18n/plat_oversea/m202003048/m202003048-version.json", new DispatchHttpJsonHandler("{\"version\":51}"));
|
httpServer.get("/admin/mi18n/plat_oversea/m202003048/m202003048-version.json", new DispatchHttpJsonHandler("{\"version\":51}"));
|
||||||
|
|
||||||
httpServer.get("/gacha", (req, res) -> res.send("<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"));
|
httpServer.get("/gacha", new GachaRecordHandler());
|
||||||
|
|
||||||
httpServer.listen(Grasscutter.getConfig().getDispatchOptions().Port);
|
httpServer.listen(Grasscutter.getConfig().getDispatchOptions().Port);
|
||||||
Grasscutter.getLogger().info("[Dispatch] Dispatch server started on port " + httpServer.raw().port());
|
Grasscutter.getLogger().info("[Dispatch] Dispatch server started on port " + httpServer.raw().port());
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package emu.grasscutter.server.http.gacha;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import emu.grasscutter.Grasscutter;
|
||||||
|
import emu.grasscutter.database.DatabaseHelper;
|
||||||
|
import emu.grasscutter.game.Account;
|
||||||
|
import emu.grasscutter.utils.FileUtils;
|
||||||
|
import express.http.HttpContextHandler;
|
||||||
|
import express.http.Request;
|
||||||
|
import express.http.Response;
|
||||||
|
|
||||||
|
public final class GachaRecordHandler implements HttpContextHandler {
|
||||||
|
String render_template;
|
||||||
|
public GachaRecordHandler() {
|
||||||
|
File template = new File(Grasscutter.getConfig().DATA_FOLDER + "gacha_records.html");
|
||||||
|
if (template.exists()) {
|
||||||
|
// Load from cache
|
||||||
|
render_template = new String(FileUtils.read(template));
|
||||||
|
} else {
|
||||||
|
render_template = "{{REPLACE_RECORD}}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(Request req, Response res) throws IOException {
|
||||||
|
// Grasscutter.getLogger().info( req.query().toString() );
|
||||||
|
String sessionKey = req.query("s");
|
||||||
|
int page = 0;
|
||||||
|
int gachaType = 0;
|
||||||
|
if (req.query("p") != null) {
|
||||||
|
page = Integer.valueOf(req.query("p"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.query("gachaType") != null) {
|
||||||
|
gachaType = Integer.valueOf(req.query("gachaType"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Account account = DatabaseHelper.getAccountBySessionKey(sessionKey);
|
||||||
|
if (account != null) {
|
||||||
|
String records = DatabaseHelper.getGachaRecords(account.getPlayerUid(), page, gachaType).toString();
|
||||||
|
// Grasscutter.getLogger().info(records);
|
||||||
|
String response = render_template.replace("{{REPLACE_RECORD}}", records)
|
||||||
|
.replace("{{REPLACE_MAXPAGE}}", String.valueOf(DatabaseHelper.getGachaRecordsMaxPage(account.getPlayerUid(), page, gachaType)));
|
||||||
|
|
||||||
|
res.send(response);
|
||||||
|
} else {
|
||||||
|
res.send("404");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,10 @@ public class HandlerGetGachaInfoReq extends PacketHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||||
session.send(new PacketGetGachaInfoRsp(session.getServer().getGachaManager()));
|
session.send(new PacketGetGachaInfoRsp(session.getServer().getGachaManager(),
|
||||||
|
// TODO: use other Nonce/key insteadof session key to ensure the overall security for the player
|
||||||
|
session.getPlayer().getAccount().getSessionKey())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,17 @@ import emu.grasscutter.net.packet.PacketOpcodes;
|
|||||||
|
|
||||||
public class PacketGetGachaInfoRsp extends BasePacket {
|
public class PacketGetGachaInfoRsp extends BasePacket {
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public PacketGetGachaInfoRsp(GachaManager manager) {
|
public PacketGetGachaInfoRsp(GachaManager manager) {
|
||||||
super(PacketOpcodes.GetGachaInfoRsp);
|
super(PacketOpcodes.GetGachaInfoRsp);
|
||||||
|
|
||||||
this.setData(manager.toProto());
|
this.setData(manager.toProto());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PacketGetGachaInfoRsp(GachaManager manager, String sessionKey) {
|
||||||
|
super(PacketOpcodes.GetGachaInfoRsp);
|
||||||
|
|
||||||
|
this.setData(manager.toProto(sessionKey));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user