mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-17 01:15:52 +01:00
Merge branch 'development' into dev-quests
This commit is contained in:
@@ -29,6 +29,7 @@ import emu.grasscutter.server.dispatch.DispatchServer;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import emu.grasscutter.tools.Tools;
|
||||
import emu.grasscutter.utils.Crypto;
|
||||
import emu.grasscutter.BuildConfig;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -82,6 +83,9 @@ public final class Grasscutter {
|
||||
case "-gachamap" -> {
|
||||
Tools.createGachaMapping(DATA("gacha_mappings.js")); exitEarly = true;
|
||||
}
|
||||
case "-version" -> {
|
||||
System.out.println("Grasscutter version: " + BuildConfig.VERSION + "-" + BuildConfig.GIT_HASH); exitEarly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +190,7 @@ public final class Grasscutter {
|
||||
}
|
||||
|
||||
getLogger().info(translate("messages.status.done"));
|
||||
getLogger().info(translate("messages.status.version", BuildConfig.VERSION, BuildConfig.GIT_HASH));
|
||||
String input = null;
|
||||
boolean isLastInterrupted = false;
|
||||
while (true) {
|
||||
|
||||
@@ -78,25 +78,25 @@ public final class DatabaseHelper {
|
||||
}
|
||||
|
||||
public static Account getAccountByName(String username) {
|
||||
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("username", username)).first();
|
||||
return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("username", username)).first();
|
||||
}
|
||||
|
||||
public static Account getAccountByToken(String token) {
|
||||
if(token == null) return null;
|
||||
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("token", token)).first();
|
||||
return DatabaseManager.getGameDatastore().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();
|
||||
return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("sessionKey", sessionKey)).first();
|
||||
}
|
||||
|
||||
public static Account getAccountById(String uid) {
|
||||
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("_id", uid)).first();
|
||||
return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("_id", uid)).first();
|
||||
}
|
||||
|
||||
public static Account getAccountByPlayerId(int playerId) {
|
||||
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("playerId", playerId)).first();
|
||||
return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("playerId", playerId)).first();
|
||||
}
|
||||
|
||||
public static void deleteAccount(Account target) {
|
||||
@@ -105,39 +105,39 @@ public final class DatabaseHelper {
|
||||
// database in an inconsistent state, but unfortunately Mongo only supports that when we have a replica set ...
|
||||
|
||||
// Delete Mail.class data
|
||||
DatabaseManager.getDatabase().getCollection("mail").deleteMany(eq("ownerUid", target.getPlayerUid()));
|
||||
DatabaseManager.getGameDatabase().getCollection("mail").deleteMany(eq("ownerUid", target.getPlayerUid()));
|
||||
// Delete Avatar.class data
|
||||
DatabaseManager.getDatabase().getCollection("avatars").deleteMany(eq("ownerId", target.getPlayerUid()));
|
||||
DatabaseManager.getGameDatabase().getCollection("avatars").deleteMany(eq("ownerId", target.getPlayerUid()));
|
||||
// Delete GachaRecord.class data
|
||||
DatabaseManager.getDatabase().getCollection("gachas").deleteMany(eq("ownerId", target.getPlayerUid()));
|
||||
DatabaseManager.getGameDatabase().getCollection("gachas").deleteMany(eq("ownerId", target.getPlayerUid()));
|
||||
// Delete GameItem.class data
|
||||
DatabaseManager.getDatabase().getCollection("items").deleteMany(eq("ownerId", target.getPlayerUid()));
|
||||
DatabaseManager.getGameDatabase().getCollection("items").deleteMany(eq("ownerId", target.getPlayerUid()));
|
||||
// Delete GameMainQuest.class data
|
||||
DatabaseManager.getDatabase().getCollection("quests").deleteMany(eq("ownerUid", target.getPlayerUid()));
|
||||
DatabaseManager.getGameDatabase().getCollection("quests").deleteMany(eq("ownerUid", target.getPlayerUid()));
|
||||
|
||||
// Delete friendships.
|
||||
// Here, we need to make sure to not only delete the deleted account's friendships,
|
||||
// but also all friendship entries for that account's friends.
|
||||
DatabaseManager.getDatabase().getCollection("friendships").deleteMany(eq("ownerId", target.getPlayerUid()));
|
||||
DatabaseManager.getDatabase().getCollection("friendships").deleteMany(eq("friendId", target.getPlayerUid()));
|
||||
DatabaseManager.getGameDatabase().getCollection("friendships").deleteMany(eq("ownerId", target.getPlayerUid()));
|
||||
DatabaseManager.getGameDatabase().getCollection("friendships").deleteMany(eq("friendId", target.getPlayerUid()));
|
||||
|
||||
// Delete the player.
|
||||
DatabaseManager.getDatastore().find(Player.class).filter(Filters.eq("id", target.getPlayerUid())).delete();
|
||||
DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("id", target.getPlayerUid())).delete();
|
||||
|
||||
// Finally, delete the account itself.
|
||||
DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("id", target.getId())).delete();
|
||||
DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("id", target.getId())).delete();
|
||||
}
|
||||
|
||||
public static List<Player> getAllPlayers() {
|
||||
return DatabaseManager.getDatastore().find(Player.class).stream().toList();
|
||||
return DatabaseManager.getGameDatastore().find(Player.class).stream().toList();
|
||||
}
|
||||
|
||||
public static Player getPlayerById(int id) {
|
||||
return DatabaseManager.getDatastore().find(Player.class).filter(Filters.eq("_id", id)).first();
|
||||
return DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("_id", id)).first();
|
||||
}
|
||||
|
||||
public static boolean checkPlayerExists(int id) {
|
||||
return DatabaseManager.getDatastore().find(Player.class).filter(Filters.eq("_id", id)).first() != null;
|
||||
return DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("_id", id)).first() != null;
|
||||
}
|
||||
|
||||
public static synchronized Player createPlayer(Player character, int reservedId) {
|
||||
@@ -154,7 +154,7 @@ public final class DatabaseHelper {
|
||||
character.setUid(id);
|
||||
}
|
||||
// Save to database
|
||||
DatabaseManager.getDatastore().save(character);
|
||||
DatabaseManager.getGameDatastore().save(character);
|
||||
return character;
|
||||
}
|
||||
|
||||
@@ -173,48 +173,48 @@ public final class DatabaseHelper {
|
||||
}
|
||||
|
||||
public static void savePlayer(Player character) {
|
||||
DatabaseManager.getDatastore().save(character);
|
||||
DatabaseManager.getGameDatastore().save(character);
|
||||
}
|
||||
|
||||
public static void saveAvatar(Avatar avatar) {
|
||||
DatabaseManager.getDatastore().save(avatar);
|
||||
DatabaseManager.getGameDatastore().save(avatar);
|
||||
}
|
||||
|
||||
public static List<Avatar> getAvatars(Player player) {
|
||||
return DatabaseManager.getDatastore().find(Avatar.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList();
|
||||
return DatabaseManager.getGameDatastore().find(Avatar.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList();
|
||||
}
|
||||
|
||||
public static void saveItem(GameItem item) {
|
||||
DatabaseManager.getDatastore().save(item);
|
||||
DatabaseManager.getGameDatastore().save(item);
|
||||
}
|
||||
|
||||
public static boolean deleteItem(GameItem item) {
|
||||
DeleteResult result = DatabaseManager.getDatastore().delete(item);
|
||||
DeleteResult result = DatabaseManager.getGameDatastore().delete(item);
|
||||
return result.wasAcknowledged();
|
||||
}
|
||||
|
||||
public static List<GameItem> getInventoryItems(Player player) {
|
||||
return DatabaseManager.getDatastore().find(GameItem.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList();
|
||||
return DatabaseManager.getGameDatastore().find(GameItem.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList();
|
||||
}
|
||||
|
||||
public static List<Friendship> getFriends(Player player) {
|
||||
return DatabaseManager.getDatastore().find(Friendship.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList();
|
||||
return DatabaseManager.getGameDatastore().find(Friendship.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList();
|
||||
}
|
||||
|
||||
public static List<Friendship> getReverseFriends(Player player) {
|
||||
return DatabaseManager.getDatastore().find(Friendship.class).filter(Filters.eq("friendId", player.getUid())).stream().toList();
|
||||
return DatabaseManager.getGameDatastore().find(Friendship.class).filter(Filters.eq("friendId", player.getUid())).stream().toList();
|
||||
}
|
||||
|
||||
public static void saveFriendship(Friendship friendship) {
|
||||
DatabaseManager.getDatastore().save(friendship);
|
||||
DatabaseManager.getGameDatastore().save(friendship);
|
||||
}
|
||||
|
||||
public static void deleteFriendship(Friendship friendship) {
|
||||
DatabaseManager.getDatastore().delete(friendship);
|
||||
DatabaseManager.getGameDatastore().delete(friendship);
|
||||
}
|
||||
|
||||
public static Friendship getReverseFriendship(Friendship friendship) {
|
||||
return DatabaseManager.getDatastore().find(Friendship.class).filter(Filters.and(
|
||||
return DatabaseManager.getGameDatastore().find(Friendship.class).filter(Filters.and(
|
||||
Filters.eq("ownerId", friendship.getFriendId()),
|
||||
Filters.eq("friendId", friendship.getOwnerId())
|
||||
)).first();
|
||||
@@ -225,7 +225,7 @@ public final class DatabaseHelper {
|
||||
}
|
||||
|
||||
public static List<GachaRecord> getGachaRecords(int ownerId, int page, int gachaType, int pageSize){
|
||||
return DatabaseManager.getDatastore().find(GachaRecord.class).filter(
|
||||
return DatabaseManager.getGameDatastore().find(GachaRecord.class).filter(
|
||||
Filters.eq("ownerId", ownerId),
|
||||
Filters.eq("gachaType", gachaType)
|
||||
).iterator(new FindOptions()
|
||||
@@ -240,7 +240,7 @@ public final class DatabaseHelper {
|
||||
}
|
||||
|
||||
public static long getGachaRecordsMaxPage(int ownerId, int page, int gachaType, int pageSize){
|
||||
long count = DatabaseManager.getDatastore().find(GachaRecord.class).filter(
|
||||
long count = DatabaseManager.getGameDatastore().find(GachaRecord.class).filter(
|
||||
Filters.eq("ownerId", ownerId),
|
||||
Filters.eq("gachaType", gachaType)
|
||||
).count();
|
||||
@@ -248,31 +248,31 @@ public final class DatabaseHelper {
|
||||
}
|
||||
|
||||
public static void saveGachaRecord(GachaRecord gachaRecord){
|
||||
DatabaseManager.getDatastore().save(gachaRecord);
|
||||
DatabaseManager.getGameDatastore().save(gachaRecord);
|
||||
}
|
||||
|
||||
public static List<Mail> getAllMail(Player player) {
|
||||
return DatabaseManager.getDatastore().find(Mail.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList();
|
||||
return DatabaseManager.getGameDatastore().find(Mail.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList();
|
||||
}
|
||||
|
||||
public static void saveMail(Mail mail) {
|
||||
DatabaseManager.getDatastore().save(mail);
|
||||
DatabaseManager.getGameDatastore().save(mail);
|
||||
}
|
||||
|
||||
public static boolean deleteMail(Mail mail) {
|
||||
DeleteResult result = DatabaseManager.getDatastore().delete(mail);
|
||||
DeleteResult result = DatabaseManager.getGameDatastore().delete(mail);
|
||||
return result.wasAcknowledged();
|
||||
}
|
||||
|
||||
public static List<GameMainQuest> getAllQuests(Player player) {
|
||||
return DatabaseManager.getDatastore().find(GameMainQuest.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList();
|
||||
return DatabaseManager.getGameDatastore().find(GameMainQuest.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList();
|
||||
}
|
||||
|
||||
public static void saveQuest(GameMainQuest quest) {
|
||||
DatabaseManager.getDatastore().save(quest);
|
||||
DatabaseManager.getGameDatastore().save(quest);
|
||||
}
|
||||
|
||||
public static boolean deleteQuest(GameMainQuest quest) {
|
||||
return DatabaseManager.getDatastore().delete(quest).wasAcknowledged();
|
||||
return DatabaseManager.getGameDatastore().delete(quest).wasAcknowledged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import emu.grasscutter.game.quest.GameQuest;
|
||||
import static emu.grasscutter.Configuration.*;
|
||||
|
||||
public final class DatabaseManager {
|
||||
private static Datastore datastore;
|
||||
private static Datastore gameDatastore;
|
||||
private static Datastore dispatchDatastore;
|
||||
|
||||
private static final Class<?>[] mappedClasses = new Class<?>[] {
|
||||
@@ -33,12 +33,12 @@ public final class DatabaseManager {
|
||||
GachaRecord.class, Mail.class, GameMainQuest.class
|
||||
};
|
||||
|
||||
public static Datastore getDatastore() {
|
||||
return datastore;
|
||||
public static Datastore getGameDatastore() {
|
||||
return gameDatastore;
|
||||
}
|
||||
|
||||
public static MongoDatabase getDatabase() {
|
||||
return getDatastore().getDatabase();
|
||||
public static MongoDatabase getGameDatabase() {
|
||||
return getGameDatastore().getDatabase();
|
||||
}
|
||||
|
||||
// Yes. I very dislike this method. However, this will be good for now.
|
||||
@@ -47,42 +47,42 @@ public final class DatabaseManager {
|
||||
if(SERVER.runMode == ServerRunMode.GAME_ONLY) {
|
||||
return dispatchDatastore;
|
||||
} else {
|
||||
return datastore;
|
||||
return gameDatastore;
|
||||
}
|
||||
}
|
||||
|
||||
public static void initialize() {
|
||||
// Initialize
|
||||
MongoClient mongoClient = MongoClients.create(DATABASE.connectionUri);
|
||||
MongoClient gameMongoClient = MongoClients.create(DATABASE.game.connectionUri);
|
||||
|
||||
// Set mapper options.
|
||||
MapperOptions mapperOptions = MapperOptions.builder()
|
||||
.storeEmpties(true).storeNulls(false).build();
|
||||
// Create data store.
|
||||
datastore = Morphia.createDatastore(mongoClient, DATABASE.collection, mapperOptions);
|
||||
gameDatastore = Morphia.createDatastore(gameMongoClient, DATABASE.game.collection, mapperOptions);
|
||||
// Map classes.
|
||||
datastore.getMapper().map(mappedClasses);
|
||||
gameDatastore.getMapper().map(mappedClasses);
|
||||
|
||||
// Ensure indexes
|
||||
try {
|
||||
datastore.ensureIndexes();
|
||||
gameDatastore.ensureIndexes();
|
||||
} catch (MongoCommandException exception) {
|
||||
Grasscutter.getLogger().info("Mongo index error: ", exception);
|
||||
// Duplicate index error
|
||||
if (exception.getCode() == 85) {
|
||||
// Drop all indexes and re add them
|
||||
MongoIterable<String> collections = datastore.getDatabase().listCollectionNames();
|
||||
MongoIterable<String> collections = gameDatastore.getDatabase().listCollectionNames();
|
||||
for (String name : collections) {
|
||||
datastore.getDatabase().getCollection(name).dropIndexes();
|
||||
gameDatastore.getDatabase().getCollection(name).dropIndexes();
|
||||
}
|
||||
// Add back indexes
|
||||
datastore.ensureIndexes();
|
||||
gameDatastore.ensureIndexes();
|
||||
}
|
||||
}
|
||||
|
||||
if(SERVER.runMode == ServerRunMode.GAME_ONLY) {
|
||||
MongoClient dispatchMongoClient = MongoClients.create(GAME_OPTIONS.databaseInfo.connectionUri);
|
||||
dispatchDatastore = Morphia.createDatastore(dispatchMongoClient, GAME_OPTIONS.databaseInfo.collection);
|
||||
MongoClient dispatchMongoClient = MongoClients.create(DATABASE.server.connectionUri);
|
||||
dispatchDatastore = Morphia.createDatastore(dispatchMongoClient, DATABASE.server.collection);
|
||||
|
||||
// Ensure indexes for dispatch server
|
||||
try {
|
||||
@@ -104,14 +104,14 @@ public final class DatabaseManager {
|
||||
}
|
||||
|
||||
public static synchronized int getNextId(Class<?> c) {
|
||||
DatabaseCounter counter = getDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getSimpleName())).first();
|
||||
DatabaseCounter counter = getGameDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getSimpleName())).first();
|
||||
if (counter == null) {
|
||||
counter = new DatabaseCounter(c.getSimpleName());
|
||||
}
|
||||
try {
|
||||
return counter.getNextId();
|
||||
} finally {
|
||||
getDatastore().save(counter);
|
||||
getGameDatastore().save(counter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import emu.grasscutter.server.event.HandlerPriority;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
@@ -90,6 +91,8 @@ public final class PluginManager {
|
||||
fileReader.close(); // Close the file reader.
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
Grasscutter.getLogger().warn("Plugin " + plugin.getName() + " has an invalid main class.");
|
||||
} catch (FileNotFoundException ignored) {
|
||||
Grasscutter.getLogger().warn("Plugin " + plugin.getName() + " lacks a valid config file.");
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
Grasscutter.getLogger().error("Failed to load plugin: " + plugin.getName(), exception);
|
||||
|
||||
@@ -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;
|
||||
@@ -117,7 +118,7 @@ public final class DispatchServer {
|
||||
.setTitle(DISPATCH_INFO.defaultName)
|
||||
.setType("DEV_PUBLIC")
|
||||
.setDispatchUrl(
|
||||
"http" + (DISPATCH_ENCRYPTION.useEncryption ? "s" : "") + "://"
|
||||
"http" + (DISPATCH_ENCRYPTION.useInRouting ? "s" : "") + "://"
|
||||
+ lr(DISPATCH_INFO.accessAddress, DISPATCH_INFO.bindAddress) + ":"
|
||||
+ lr(DISPATCH_INFO.accessPort, DISPATCH_INFO.bindPort)
|
||||
+ "/query_cur_region/" + defaultServerName)
|
||||
@@ -150,7 +151,7 @@ public final class DispatchServer {
|
||||
.setTitle(regionInfo.Title)
|
||||
.setType("DEV_PUBLIC")
|
||||
.setDispatchUrl(
|
||||
"http" + (DISPATCH_ENCRYPTION.useEncryption ? "s" : "") + "://"
|
||||
"http" + (DISPATCH_ENCRYPTION.useInRouting ? "s" : "") + "://"
|
||||
+ lr(DISPATCH_INFO.accessAddress, DISPATCH_INFO.bindAddress) + ":"
|
||||
+ lr(DISPATCH_INFO.accessPort, DISPATCH_INFO.bindPort)
|
||||
+ "/query_cur_region/" + regionInfo.Name)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -12,5 +12,12 @@ public interface AuthenticationHandler {
|
||||
void handleRegister(Request req, Response res);
|
||||
void handleChangePassword(Request req, Response res);
|
||||
|
||||
/**
|
||||
* Other plugins may need to verify a user's identity using details from handleLogin()
|
||||
* @param details The user's unique one-time token that needs to be verified
|
||||
* @return If the verification was successful
|
||||
*/
|
||||
boolean verifyUser(String details);
|
||||
|
||||
LoginResultJson handleGameLogin(Request req, LoginAccountRequestJson requestData);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,12 @@ public class DefaultAuthenticationHandler implements AuthenticationHandler {
|
||||
res.send("Authentication is not available with the default authentication method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyUser(String details) {
|
||||
Grasscutter.getLogger().info(translate("dispatch.authentication.default_unable_to_verify"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginResultJson handleGameLogin(Request req, LoginAccountRequestJson requestData) {
|
||||
LoginResultJson responseData = new LoginResultJson();
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
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"));
|
||||
|
||||
response = response.replace("{{LANGUAGE}}", Utils.getLanguageCode(account.getLocale()));
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package emu.grasscutter.utils;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.Grasscutter.ServerDebugMode;
|
||||
import emu.grasscutter.Grasscutter.ServerRunMode;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -15,7 +17,7 @@ import static emu.grasscutter.Grasscutter.config;
|
||||
*/
|
||||
public class ConfigContainer {
|
||||
private static int version() {
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,8 +71,13 @@ public class ConfigContainer {
|
||||
/* Option containers. */
|
||||
|
||||
public static class Database {
|
||||
public String connectionUri = "mongodb://localhost:27017";
|
||||
public String collection = "grasscutter";
|
||||
public DataStore server = new DataStore();
|
||||
public DataStore game = new DataStore();
|
||||
|
||||
public static class DataStore {
|
||||
public String connectionUri = "mongodb://localhost:27017";
|
||||
public String collection = "grasscutter";
|
||||
}
|
||||
}
|
||||
|
||||
public static class Structure {
|
||||
@@ -86,8 +93,8 @@ public class ConfigContainer {
|
||||
}
|
||||
|
||||
public static class Server {
|
||||
public Grasscutter.ServerDebugMode debugLevel = Grasscutter.ServerDebugMode.NONE;
|
||||
public Grasscutter.ServerRunMode runMode = Grasscutter.ServerRunMode.HYBRID;
|
||||
public ServerDebugMode debugLevel = ServerDebugMode.NONE;
|
||||
public ServerRunMode runMode = ServerRunMode.HYBRID;
|
||||
|
||||
public Dispatch dispatch = new Dispatch();
|
||||
public Game game = new Game();
|
||||
@@ -112,7 +119,7 @@ public class ConfigContainer {
|
||||
|
||||
public int bindPort = 443;
|
||||
/* This is the port used in URLs. */
|
||||
public int accessPort = 443;
|
||||
public int accessPort = 0;
|
||||
|
||||
public Encryption encryption = new Encryption();
|
||||
public Policies policies = new Policies();
|
||||
@@ -128,7 +135,7 @@ public class ConfigContainer {
|
||||
|
||||
public int bindPort = 22102;
|
||||
/* This is the port used in the default region. */
|
||||
public int accessPort = 22102;
|
||||
public int accessPort = 0;
|
||||
|
||||
public GameOptions gameOptions = new GameOptions();
|
||||
public JoinOptions joinOptions = new JoinOptions();
|
||||
@@ -155,16 +162,14 @@ public class ConfigContainer {
|
||||
}
|
||||
|
||||
public static class GameOptions {
|
||||
public GameOptions.InventoryLimits inventoryLimits = new GameOptions.InventoryLimits();
|
||||
public GameOptions.AvatarLimits avatarLimits = new GameOptions.AvatarLimits();
|
||||
public InventoryLimits inventoryLimits = new InventoryLimits();
|
||||
public AvatarLimits avatarLimits = new AvatarLimits();
|
||||
public int worldEntityLimit = 1000; // Unenforced. TODO: Implement.
|
||||
|
||||
public boolean watchGachaConfig = false;
|
||||
public boolean enableShopItems = true;
|
||||
public boolean staminaUsage = true;
|
||||
public GameOptions.Rates rates = new GameOptions.Rates();
|
||||
|
||||
public Database databaseInfo = new Database();
|
||||
public Rates rates = new Rates();
|
||||
|
||||
public static class InventoryLimits {
|
||||
public int weapons = 2000;
|
||||
|
||||
@@ -160,7 +160,9 @@ public final class Language {
|
||||
JsonObject object = this.languageData;
|
||||
|
||||
int index = 0;
|
||||
String result = "This value does not exist. Please report this to the Discord: " + key;
|
||||
String valueNotFoundPattern = "This value does not exist. Please report this to the Discord: ";
|
||||
String result = valueNotFoundPattern + key;
|
||||
boolean isValueFound = false;
|
||||
|
||||
while (true) {
|
||||
if(index == keys.length) break;
|
||||
@@ -171,10 +173,18 @@ public final class Language {
|
||||
if(element.isJsonObject())
|
||||
object = element.getAsJsonObject();
|
||||
else {
|
||||
isValueFound = true;
|
||||
result = element.getAsString(); break;
|
||||
}
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (!isValueFound && !languageCode.equals("en-US")) {
|
||||
var englishValue = Grasscutter.getLanguage("en-US").get(key);
|
||||
if (!englishValue.contains(valueNotFoundPattern)) {
|
||||
result += "\nhere is english version:\n" + englishValue;
|
||||
}
|
||||
}
|
||||
|
||||
this.cachedTranslations.put(key, result); return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user