Commit 22cbe748 authored by Magix's avatar Magix Committed by GitHub
Browse files

Merge pull request #802 from Grasscutters/better-config

Implement a better config structure
parents 54cf45a7 812f4b37
...@@ -31,6 +31,8 @@ import emu.grasscutter.scripts.data.ScriptArgs; ...@@ -31,6 +31,8 @@ import emu.grasscutter.scripts.data.ScriptArgs;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import static emu.grasscutter.Configuration.*;
public class SceneScriptManager { public class SceneScriptManager {
private final Scene scene; private final Scene scene;
private final ScriptLib scriptLib; private final ScriptLib scriptLib;
...@@ -164,7 +166,7 @@ public class SceneScriptManager { ...@@ -164,7 +166,7 @@ public class SceneScriptManager {
private void init() { private void init() {
// Get compiled script if cached // Get compiled script if cached
CompiledScript cs = ScriptLoader.getScriptByPath( CompiledScript cs = ScriptLoader.getScriptByPath(
Grasscutter.getConfig().SCRIPTS_FOLDER + "Scene/" + getScene().getId() + "/scene" + getScene().getId() + "." + ScriptLoader.getScriptType()); SCRIPT("Scene/" + getScene().getId() + "/scene" + getScene().getId() + "." + ScriptLoader.getScriptType()));
if (cs == null) { if (cs == null) {
Grasscutter.getLogger().warn("No script found for scene " + getScene().getId()); Grasscutter.getLogger().warn("No script found for scene " + getScene().getId());
...@@ -211,7 +213,7 @@ public class SceneScriptManager { ...@@ -211,7 +213,7 @@ public class SceneScriptManager {
private void loadBlockFromScript(SceneBlock block) { private void loadBlockFromScript(SceneBlock block) {
CompiledScript cs = ScriptLoader.getScriptByPath( CompiledScript cs = ScriptLoader.getScriptByPath(
Grasscutter.getConfig().SCRIPTS_FOLDER + "Scene/" + getScene().getId() + "/scene" + getScene().getId() + "_block" + block.id + "." + ScriptLoader.getScriptType()); SCRIPT("Scene/" + getScene().getId() + "/scene" + getScene().getId() + "_block" + block.id + "." + ScriptLoader.getScriptType()));
if (cs == null) { if (cs == null) {
return; return;
...@@ -234,7 +236,7 @@ public class SceneScriptManager { ...@@ -234,7 +236,7 @@ public class SceneScriptManager {
group.setLoaded(true); group.setLoaded(true);
CompiledScript cs = ScriptLoader.getScriptByPath( CompiledScript cs = ScriptLoader.getScriptByPath(
Grasscutter.getConfig().SCRIPTS_FOLDER + "Scene/" + getScene().getId() + "/scene" + getScene().getId() + "_group" + group.id + "." + ScriptLoader.getScriptType()); SCRIPTS_FOLDER + "Scene/" + getScene().getId() + "/scene" + getScene().getId() + "_group" + group.id + "." + ScriptLoader.getScriptType());
if (cs == null) { if (cs == null) {
return; return;
...@@ -281,9 +283,7 @@ public class SceneScriptManager { ...@@ -281,9 +283,7 @@ public class SceneScriptManager {
if (gadget != null) { if (gadget != null) {
suite.sceneGadgets.add(gadget); suite.sceneGadgets.add(gadget);
} }
} catch (Exception e) { } catch (Exception ignored) { }
continue;
}
} }
} }
this.sceneGroups.put(group.id, group); this.sceneGroups.put(group.id, group);
......
...@@ -10,26 +10,29 @@ import java.io.FileInputStream; ...@@ -10,26 +10,29 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
import static emu.grasscutter.Configuration.*;
public final class AnnouncementHandler implements HttpContextHandler { public final class AnnouncementHandler implements HttpContextHandler {
@Override @Override
public void handle(Request request, Response response) throws IOException {//event public void handle(Request request, Response response) throws IOException {//event
if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnContent")) { if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnContent")) {
response.send("{\"retcode\":0,\"message\":\"OK\",\"data\":" + readToString(new File(Grasscutter.getConfig().DATA_FOLDER + "GameAnnouncement.json")) +"}"); response.send("{\"retcode\":0,\"message\":\"OK\",\"data\":" + readToString(new File(DATA("GameAnnouncement.json"))) +"}");
} else if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnList")) { } else if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnList")) {
String data = readToString(new File(Grasscutter.getConfig().DATA_FOLDER + "GameAnnouncementList.json")).replace("System.currentTimeMillis()",String.valueOf(System.currentTimeMillis())); String data = readToString(new File(DATA("GameAnnouncementList.json"))).replace("System.currentTimeMillis()",String.valueOf(System.currentTimeMillis()));
response.send("{\"retcode\":0,\"message\":\"OK\",\"data\": "+data +"}"); response.send("{\"retcode\":0,\"message\":\"OK\",\"data\": "+data +"}");
} }
} }
@SuppressWarnings("ResultOfMethodCallIgnored")
private static String readToString(File file) { private static String readToString(File file) {
Long filelength = file.length(); long length = file.length();
byte[] filecontent = new byte[filelength.intValue()]; byte[] content = new byte[(int) length];
try { try {
FileInputStream in = new FileInputStream(file); FileInputStream in = new FileInputStream(file);
in.read(filecontent); in.read(content); in.close();
in.close(); } catch (IOException ignored) {
} catch (IOException fileNotFoundException) { Grasscutter.getLogger().warn("File not found: " + file.getAbsolutePath());
fileNotFoundException.printStackTrace();
} }
return new String(filecontent);
return new String(content);
} }
} }
\ No newline at end of file
...@@ -11,6 +11,7 @@ import express.http.Request; ...@@ -11,6 +11,7 @@ import express.http.Request;
import express.http.Response; import express.http.Response;
import static emu.grasscutter.utils.Language.translate; import static emu.grasscutter.utils.Language.translate;
import static emu.grasscutter.Configuration.*;
public final class DispatchHttpJsonHandler implements HttpContextHandler { public final class DispatchHttpJsonHandler implements HttpContextHandler {
private final String response; private final String response;
...@@ -34,8 +35,8 @@ public final class DispatchHttpJsonHandler implements HttpContextHandler { ...@@ -34,8 +35,8 @@ public final class DispatchHttpJsonHandler implements HttpContextHandler {
@Override @Override
public void handle(Request req, Response res) throws IOException { public void handle(Request req, Response res) throws IOException {
// Checking for ALL here isn't required as when ALL is enabled enableDevLogging() gets enabled // Checking for ALL here isn't required as when ALL is enabled enableDevLogging() gets enabled
if(Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING && Arrays.stream(missingRoutes).anyMatch(x -> Objects.equals(x, req.baseUrl()))) { if(SERVER.debugLevel == ServerDebugMode.MISSING && Arrays.stream(missingRoutes).anyMatch(x -> Objects.equals(x, req.baseUrl()))) {
Grasscutter.getLogger().info(translate("messages.dispatch.request", req.ip(), req.method(), req.baseUrl()) + (Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING ? "(MISSING)" : "")); Grasscutter.getLogger().info(translate("messages.dispatch.request", req.ip(), req.method(), req.baseUrl()) + (SERVER.debugLevel == ServerDebugMode.MISSING ? "(MISSING)" : ""));
} }
res.send(response); res.send(response);
} }
......
...@@ -4,7 +4,6 @@ import com.google.gson.Gson; ...@@ -4,7 +4,6 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import emu.grasscutter.Config;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.Grasscutter.ServerDebugMode; import emu.grasscutter.Grasscutter.ServerDebugMode;
import emu.grasscutter.Grasscutter.ServerRunMode; import emu.grasscutter.Grasscutter.ServerRunMode;
...@@ -33,9 +32,11 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; ...@@ -33,9 +32,11 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
import java.io.*; import java.io.*;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import static emu.grasscutter.utils.Language.translate; import static emu.grasscutter.utils.Language.translate;
import static emu.grasscutter.Configuration.*;
public final class DispatchServer { public final class DispatchServer {
public static String query_region_list = ""; public static String query_region_list = "";
...@@ -64,7 +65,7 @@ public final class DispatchServer { ...@@ -64,7 +65,7 @@ public final class DispatchServer {
public void setHttpServer(Express httpServer) { public void setHttpServer(Express httpServer) {
this.httpServer.stop(); this.httpServer.stop();
this.httpServer = httpServer; this.httpServer = httpServer;
this.httpServer.listen(Grasscutter.getConfig().getDispatchOptions().Port); this.httpServer.listen(DISPATCH_INFO.bindPort);
} }
public Gson getGsonFactory() { public Gson getGsonFactory() {
...@@ -73,7 +74,7 @@ public final class DispatchServer { ...@@ -73,7 +74,7 @@ public final class DispatchServer {
public QueryCurrRegionHttpRsp getCurrRegion() { public QueryCurrRegionHttpRsp getCurrRegion() {
// Needs to be fixed by having the game servers connect to the dispatch server. // Needs to be fixed by having the game servers connect to the dispatch server.
if (Grasscutter.getConfig().RunMode == ServerRunMode.HYBRID) { if (SERVER.runMode == ServerRunMode.HYBRID) {
return regions.get(defaultServerName).parsedRegionQuery; return regions.get(defaultServerName).parsedRegionQuery;
} }
...@@ -84,14 +85,14 @@ public final class DispatchServer { ...@@ -84,14 +85,14 @@ public final class DispatchServer {
public void loadQueries() { public void loadQueries() {
File file; File file;
file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_region_list.txt"); file = new File(DATA("query_region_list.txt"));
if (file.exists()) { if (file.exists()) {
query_region_list = new String(FileUtils.read(file)); query_region_list = new String(FileUtils.read(file));
} else { } else {
Grasscutter.getLogger().warn("[Dispatch] query_region_list not found! Using default region list."); Grasscutter.getLogger().warn("[Dispatch] query_region_list not found! Using default region list.");
} }
file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_cur_region.txt"); file = new File(DATA("query_cur_region.txt"));
if (file.exists()) { if (file.exists()) {
query_cur_region = new String(FileUtils.read(file)); query_cur_region = new String(FileUtils.read(file));
} else { } else {
...@@ -108,52 +109,37 @@ public final class DispatchServer { ...@@ -108,52 +109,37 @@ public final class DispatchServer {
QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRsp.parseFrom(decoded2); QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRsp.parseFrom(decoded2);
List<RegionSimpleInfo> servers = new ArrayList<>(); List<RegionSimpleInfo> servers = new ArrayList<>();
List<String> usedNames = new ArrayList<>(); // List to check for potential naming conflicts List<String> usedNames = new ArrayList<>(); // List to check for potential naming conflicts.
if (Grasscutter.getConfig().RunMode == ServerRunMode.HYBRID) { // Automatically add the game server if in if (SERVER.runMode == ServerRunMode.HYBRID) { // Automatically add the game server if in hybrid mode.
// hybrid mode
RegionSimpleInfo server = RegionSimpleInfo.newBuilder() RegionSimpleInfo server = RegionSimpleInfo.newBuilder()
.setName("os_usa") .setName("os_usa")
.setTitle(Grasscutter.getConfig().getGameServerOptions().Name) .setTitle(DISPATCH_INFO.defaultName)
.setType("DEV_PUBLIC") .setType("DEV_PUBLIC")
.setDispatchUrl( .setDispatchUrl(
"http" + (Grasscutter.getConfig().getDispatchOptions().FrontHTTPS ? "s" : "") + "://" "http" + (DISPATCH_ENCRYPTION.useEncryption ? "s" : "") + "://"
+ (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() + lr(DISPATCH_INFO.accessAddress, DISPATCH_INFO.bindAddress) + ":"
? Grasscutter.getConfig().getDispatchOptions().Ip + lr(DISPATCH_INFO.accessPort, DISPATCH_INFO.bindPort)
: Grasscutter.getConfig().getDispatchOptions().PublicIp)
+ ":"
+ (Grasscutter.getConfig().getDispatchOptions().PublicPort != 0
? Grasscutter.getConfig().getDispatchOptions().PublicPort
: Grasscutter.getConfig().getDispatchOptions().Port)
+ "/query_cur_region/" + defaultServerName) + "/query_cur_region/" + defaultServerName)
.build(); .build();
usedNames.add(defaultServerName); usedNames.add(defaultServerName);
servers.add(server); servers.add(server);
RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
.setGateserverIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() .setGateserverIp(lr(DISPATCH_INFO.accessAddress, DISPATCH_INFO.bindAddress))
? Grasscutter.getConfig().getGameServerOptions().Ip .setGateserverPort(lr(DISPATCH_INFO.accessPort, DISPATCH_INFO.bindPort))
: Grasscutter.getConfig().getGameServerOptions().PublicIp)) .setSecretKey(ByteString.copyFrom(FileUtils.read(KEYS_FOLDER + "/dispatchSeed.bin")))
.setGateserverPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0
? Grasscutter.getConfig().getGameServerOptions().PublicPort
: Grasscutter.getConfig().getGameServerOptions().Port)
.setSecretKey(ByteString
.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
.build(); .build();
QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(serverRegion).build(); QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(serverRegion).build();
regions.put(defaultServerName, new RegionData(parsedRegionQuery, regions.put(defaultServerName, new RegionData(parsedRegionQuery,
Base64.getEncoder().encodeToString(parsedRegionQuery.toByteString().toByteArray()))); Base64.getEncoder().encodeToString(parsedRegionQuery.toByteString().toByteArray())));
} else { } else if (DISPATCH_INFO.regions.length == 0) {
if (Grasscutter.getConfig().getDispatchOptions().getGameServers().length == 0) { Grasscutter.getLogger().error("[Dispatch] There are no game servers available. Exiting due to unplayable state.");
Grasscutter.getLogger()
.error("[Dispatch] There are no game servers available. Exiting due to unplayable state.");
System.exit(1); System.exit(1);
} }
}
for (Config.DispatchServerOptions.RegionInfo regionInfo : Grasscutter.getConfig().getDispatchOptions() for (var regionInfo : DISPATCH_INFO.regions) {
.getGameServers()) {
if (usedNames.contains(regionInfo.Name)) { if (usedNames.contains(regionInfo.Name)) {
Grasscutter.getLogger().error("Region name already in use."); Grasscutter.getLogger().error("Region name already in use.");
continue; continue;
...@@ -163,13 +149,10 @@ public final class DispatchServer { ...@@ -163,13 +149,10 @@ public final class DispatchServer {
.setTitle(regionInfo.Title) .setTitle(regionInfo.Title)
.setType("DEV_PUBLIC") .setType("DEV_PUBLIC")
.setDispatchUrl( .setDispatchUrl(
"http" + (Grasscutter.getConfig().getDispatchOptions().FrontHTTPS ? "s" : "") + "://" "http" + (DISPATCH_ENCRYPTION.useEncryption ? "s" : "") + "://"
+ (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() + lr(DISPATCH_INFO.accessAddress, DISPATCH_INFO.bindAddress) + ":"
? Grasscutter.getConfig().getDispatchOptions().Ip + lr(DISPATCH_INFO.accessPort, DISPATCH_INFO.bindPort)
: Grasscutter.getConfig().getDispatchOptions().PublicIp) + "/query_cur_region/" + regionInfo.Name)
+ ":" + (Grasscutter.getConfig().getDispatchOptions().PublicPort != 0
? Grasscutter.getConfig().getDispatchOptions().PublicPort
: Grasscutter.getConfig().getDispatchOptions().Port) + "/query_cur_region/" + regionInfo.Name)
.build(); .build();
usedNames.add(regionInfo.Name); usedNames.add(regionInfo.Name);
servers.add(server); servers.add(server);
...@@ -178,7 +161,7 @@ public final class DispatchServer { ...@@ -178,7 +161,7 @@ public final class DispatchServer {
.setGateserverIp(regionInfo.Ip) .setGateserverIp(regionInfo.Ip)
.setGateserverPort(regionInfo.Port) .setGateserverPort(regionInfo.Port)
.setSecretKey(ByteString .setSecretKey(ByteString
.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin"))) .copyFrom(FileUtils.read(KEYS_FOLDER + "/dispatchSeed.bin")))
.build(); .build();
QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(serverRegion).build(); QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(serverRegion).build();
...@@ -194,8 +177,8 @@ public final class DispatchServer { ...@@ -194,8 +177,8 @@ public final class DispatchServer {
.build(); .build();
this.regionListBase64 = Base64.getEncoder().encodeToString(regionList.toByteString().toByteArray()); this.regionListBase64 = Base64.getEncoder().encodeToString(regionList.toByteString().toByteArray());
} catch (Exception e) { } catch (Exception exception) {
Grasscutter.getLogger().error("[Dispatch] Error while initializing region info!", e); Grasscutter.getLogger().error("[Dispatch] Error while initializing region info!", exception);
} }
} }
...@@ -205,14 +188,14 @@ public final class DispatchServer { ...@@ -205,14 +188,14 @@ public final class DispatchServer {
Server server = new Server(); Server server = new Server();
ServerConnector serverConnector; ServerConnector serverConnector;
if(Grasscutter.getConfig().getDispatchOptions().UseSSL) { if(DISPATCH_ENCRYPTION.useEncryption) {
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
File keystoreFile = new File(Grasscutter.getConfig().getDispatchOptions().KeystorePath); File keystoreFile = new File(DISPATCH_ENCRYPTION.keystore);
if(keystoreFile.exists()) { if(keystoreFile.exists()) {
try { try {
sslContextFactory.setKeyStorePath(keystoreFile.getPath()); sslContextFactory.setKeyStorePath(keystoreFile.getPath());
sslContextFactory.setKeyStorePassword(Grasscutter.getConfig().getDispatchOptions().KeystorePassword); sslContextFactory.setKeyStorePassword(DISPATCH_ENCRYPTION.keystorePassword);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.password_error")); Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.password_error"));
...@@ -230,7 +213,7 @@ public final class DispatchServer { ...@@ -230,7 +213,7 @@ public final class DispatchServer {
serverConnector = new ServerConnector(server, sslContextFactory); serverConnector = new ServerConnector(server, sslContextFactory);
} else { } else {
Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.no_keystore_error")); Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.no_keystore_error"));
Grasscutter.getConfig().getDispatchOptions().UseSSL = false; DISPATCH_ENCRYPTION.useEncryption = false;
serverConnector = new ServerConnector(server); serverConnector = new ServerConnector(server);
} }
...@@ -238,24 +221,27 @@ public final class DispatchServer { ...@@ -238,24 +221,27 @@ public final class DispatchServer {
serverConnector = new ServerConnector(server); serverConnector = new ServerConnector(server);
} }
serverConnector.setPort(Grasscutter.getConfig().getDispatchOptions().Port); serverConnector.setPort(DISPATCH_INFO.bindPort);
server.setConnectors(new Connector[]{serverConnector}); server.setConnectors(new Connector[]{serverConnector});
return server; return server;
}); });
config.enforceSsl = Grasscutter.getConfig().getDispatchOptions().UseSSL; config.enforceSsl = DISPATCH_ENCRYPTION.useEncryption;
if(Grasscutter.getConfig().DebugMode == ServerDebugMode.ALL) { if(SERVER.debugLevel == ServerDebugMode.ALL) {
config.enableDevLogging(); config.enableDevLogging();
} }
if (Grasscutter.getConfig().getDispatchOptions().CORS){
if (Grasscutter.getConfig().getDispatchOptions().CORSAllowedOrigins.length > 0) config.enableCorsForOrigin(Grasscutter.getConfig().getDispatchOptions().CORSAllowedOrigins); if (DISPATCH_POLICIES.cors.enabled) {
var corsPolicy = DISPATCH_POLICIES.cors;
if (corsPolicy.allowedOrigins.length > 0)
config.enableCorsForOrigin(corsPolicy.allowedOrigins);
else config.enableCorsForAllOrigins(); else config.enableCorsForAllOrigins();
} }
}); });
httpServer.get("/", (req, res) -> res.send("<!doctype html><html><head><meta charset=\"utf8\"></head><body>" + translate("messages.status.welcome") + "</body></html>")); httpServer.get("/", (req, res) -> res.send("<!doctype html><html><head><meta charset=\"utf8\"></head><body>" + translate("messages.status.welcome") + "</body></html>"));
httpServer.raw().error(404, ctx -> { httpServer.raw().error(404, ctx -> {
if(Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING) { if(SERVER.debugLevel == ServerDebugMode.MISSING) {
Grasscutter.getLogger().info(translate("messages.dispatch.unhandled_request_error", ctx.method(), ctx.url())); Grasscutter.getLogger().info(translate("messages.dispatch.unhandled_request_error", ctx.method(), ctx.url()));
} }
ctx.contentType("text/html"); ctx.contentType("text/html");
...@@ -450,7 +436,7 @@ public final class DispatchServer { ...@@ -450,7 +436,7 @@ public final class DispatchServer {
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}"));
// gacha record. // gacha record.
String gachaMappingsPath = Utils.toFilePath(Grasscutter.getConfig().DATA_FOLDER + "/gacha_mappings.js"); String gachaMappingsPath = Utils.toFilePath(DATA("/gacha_mappings.js"));
// TODO: Only serve the html page and have a subsequent request to fetch the gacha data. // TODO: Only serve the html page and have a subsequent request to fetch the gacha data.
httpServer.get("/gacha", new GachaRecordHandler()); httpServer.get("/gacha", new GachaRecordHandler());
if(!(new File(gachaMappingsPath).exists())) { if(!(new File(gachaMappingsPath).exists())) {
...@@ -462,7 +448,7 @@ public final class DispatchServer { ...@@ -462,7 +448,7 @@ public final class DispatchServer {
// static file support for plugins // 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 httpServer.raw().config.precompressStaticFiles = false; // If this isn't set to false, files such as images may appear corrupted when serving static files
httpServer.listen(Grasscutter.getConfig().getDispatchOptions().Port); httpServer.listen(DISPATCH_INFO.bindPort);
Grasscutter.getLogger().info(translate("messages.dispatch.port_bind", Integer.toString(httpServer.raw().port()))); Grasscutter.getLogger().info(translate("messages.dispatch.port_bind", Integer.toString(httpServer.raw().port())));
} }
...@@ -481,15 +467,11 @@ public final class DispatchServer { ...@@ -481,15 +467,11 @@ public final class DispatchServer {
if (next > last) { if (next > last) {
int eqPos = qs.indexOf('=', last); int eqPos = qs.indexOf('=', last);
try {
if (eqPos < 0 || eqPos > next) { if (eqPos < 0 || eqPos > next) {
result.put(URLDecoder.decode(qs.substring(last, next), "utf-8"), ""); result.put(URLDecoder.decode(qs.substring(last, next), StandardCharsets.UTF_8), "");
} else { } else {
result.put(URLDecoder.decode(qs.substring(last, eqPos), "utf-8"), result.put(URLDecoder.decode(qs.substring(last, eqPos), StandardCharsets.UTF_8),
URLDecoder.decode(qs.substring(eqPos + 1, next), "utf-8")); URLDecoder.decode(qs.substring(eqPos + 1, next), StandardCharsets.UTF_8));
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e); // will never happen, utf-8 support is mandatory for java
} }
} }
last = next + 1; last = next + 1;
......
...@@ -9,6 +9,7 @@ import express.http.Request; ...@@ -9,6 +9,7 @@ import express.http.Request;
import express.http.Response; import express.http.Response;
import static emu.grasscutter.utils.Language.translate; import static emu.grasscutter.utils.Language.translate;
import static emu.grasscutter.Configuration.*;
public class DefaultAuthenticationHandler implements AuthenticationHandler { public class DefaultAuthenticationHandler implements AuthenticationHandler {
...@@ -37,11 +38,11 @@ public class DefaultAuthenticationHandler implements AuthenticationHandler { ...@@ -37,11 +38,11 @@ public class DefaultAuthenticationHandler implements AuthenticationHandler {
// Check if account exists, else create a new one. // Check if account exists, else create a new one.
if (account == null) { if (account == null) {
// Account doesn't exist, so we can either auto create it if the config value is set. // Account doesn't exist, so we can either auto create it if the config value is set.
if (Grasscutter.getConfig().getDispatchOptions().AutomaticallyCreateAccounts) { if (ACCOUNT.autoCreate) {
// This account has been created AUTOMATICALLY. There will be no permissions added. // This account has been created AUTOMATICALLY. There will be no permissions added.
account = DatabaseHelper.createAccountWithId(requestData.account, 0); account = DatabaseHelper.createAccountWithId(requestData.account, 0);
for (String permission : Grasscutter.getConfig().getDispatchOptions().defaultPermissions) { for (String permission : ACCOUNT.defaultPermissions) {
account.addPermission(permission); account.addPermission(permission);
} }
......
...@@ -3,7 +3,6 @@ package emu.grasscutter.server.dispatch.http; ...@@ -3,7 +3,6 @@ package emu.grasscutter.server.dispatch.http;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.Account; import emu.grasscutter.game.Account;
import emu.grasscutter.utils.FileUtils; import emu.grasscutter.utils.FileUtils;
...@@ -12,10 +11,12 @@ import express.http.HttpContextHandler; ...@@ -12,10 +11,12 @@ import express.http.HttpContextHandler;
import express.http.Request; import express.http.Request;
import express.http.Response; import express.http.Response;
import static emu.grasscutter.Configuration.*;
public final class GachaRecordHandler implements HttpContextHandler { public final class GachaRecordHandler implements HttpContextHandler {
String render_template; String render_template;
public GachaRecordHandler() { public GachaRecordHandler() {
File template = new File(Utils.toFilePath(Grasscutter.getConfig().DATA_FOLDER + "/gacha_records.html")); File template = new File(Utils.toFilePath(DATA("/gacha_records.html")));
if (template.exists()) { if (template.exists()) {
// Load from cache // Load from cache
render_template = new String(FileUtils.read(template)); render_template = new String(FileUtils.read(template));
...@@ -31,11 +32,11 @@ public final class GachaRecordHandler implements HttpContextHandler { ...@@ -31,11 +32,11 @@ public final class GachaRecordHandler implements HttpContextHandler {
int page = 0; int page = 0;
int gachaType = 0; int gachaType = 0;
if (req.query("p") != null) { if (req.query("p") != null) {
page = Integer.valueOf(req.query("p")); page = Integer.parseInt(req.query("p"));
} }
if (req.query("gachaType") != null) { if (req.query("gachaType") != null) {
gachaType = Integer.valueOf(req.query("gachaType")); gachaType = Integer.parseInt(req.query("gachaType"));
} }
Account account = DatabaseHelper.getAccountBySessionKey(sessionKey); Account account = DatabaseHelper.getAccountBySessionKey(sessionKey);
......
...@@ -30,11 +30,9 @@ import java.net.InetSocketAddress; ...@@ -30,11 +30,9 @@ import java.net.InetSocketAddress;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static emu.grasscutter.utils.Language.translate; import static emu.grasscutter.utils.Language.translate;
import static emu.grasscutter.Configuration.*;
public final class GameServer extends KcpServer { public final class GameServer extends KcpServer {
private final InetSocketAddress address; private final InetSocketAddress address;
...@@ -59,8 +57,8 @@ public final class GameServer extends KcpServer { ...@@ -59,8 +57,8 @@ public final class GameServer extends KcpServer {
public GameServer() { public GameServer() {
this(new InetSocketAddress( this(new InetSocketAddress(
Grasscutter.getConfig().getGameServerOptions().Ip, GAME_INFO.bindAddress,
Grasscutter.getConfig().getGameServerOptions().Port GAME_INFO.bindPort
)); ));
} }
......
...@@ -14,6 +14,8 @@ import emu.grasscutter.server.game.GameSession.SessionState; ...@@ -14,6 +14,8 @@ import emu.grasscutter.server.game.GameSession.SessionState;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import static emu.grasscutter.Configuration.*;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class GameServerPacketHandler { public class GameServerPacketHandler {
private final Int2ObjectMap<PacketHandler> handlers; private final Int2ObjectMap<PacketHandler> handlers;
...@@ -92,7 +94,7 @@ public class GameServerPacketHandler { ...@@ -92,7 +94,7 @@ public class GameServerPacketHandler {
} }
// Log unhandled packets // Log unhandled packets
if (Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING) { if (SERVER.debugLevel == ServerDebugMode.MISSING) {
Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtil.getOpcodeName(opcode)); Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtil.getOpcodeName(opcode));
} }
} }
......
...@@ -3,7 +3,6 @@ package emu.grasscutter.server.game; ...@@ -3,7 +3,6 @@ package emu.grasscutter.server.game;
import java.io.File; import java.io.File;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
...@@ -23,9 +22,10 @@ import io.netty.buffer.Unpooled; ...@@ -23,9 +22,10 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import static emu.grasscutter.utils.Language.translate; import static emu.grasscutter.utils.Language.translate;
import static emu.grasscutter.Configuration.*;
public class GameSession extends KcpChannel { public class GameSession extends KcpChannel {
private GameServer server; private final GameServer server;
private Account account; private Account account;
private Player player; private Player player;
...@@ -140,7 +140,7 @@ public class GameSession extends KcpChannel { ...@@ -140,7 +140,7 @@ public class GameSession extends KcpChannel {
} }
public void replayPacket(int opcode, String name) { public void replayPacket(int opcode, String name) {
String filePath = Grasscutter.getConfig().PACKETS_FOLDER + name; String filePath = PACKETS_FOLDER + name;
File p = new File(filePath); File p = new File(filePath);
if (!p.exists()) return; if (!p.exists()) return;
...@@ -172,7 +172,7 @@ public class GameSession extends KcpChannel { ...@@ -172,7 +172,7 @@ public class GameSession extends KcpChannel {
} }
// Log // Log
if (Grasscutter.getConfig().DebugMode == ServerDebugMode.ALL) { if (SERVER.debugLevel == ServerDebugMode.ALL) {
logPacket(packet); logPacket(packet);
} }
...@@ -239,7 +239,7 @@ public class GameSession extends KcpChannel { ...@@ -239,7 +239,7 @@ public class GameSession extends KcpChannel {
} }
// Log packet // Log packet
if (Grasscutter.getConfig().DebugMode == ServerDebugMode.ALL) { if (SERVER.debugLevel == ServerDebugMode.ALL) {
if (!loopPacket.contains(opcode)) { if (!loopPacket.contains(opcode)) {
Grasscutter.getLogger().info("RECV: " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")"); Grasscutter.getLogger().info("RECV: " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")");
System.out.println(Utils.bytesToHex(payload)); System.out.println(Utils.bytesToHex(payload));
......
...@@ -19,6 +19,8 @@ import emu.grasscutter.server.game.GameSession.SessionState; ...@@ -19,6 +19,8 @@ import emu.grasscutter.server.game.GameSession.SessionState;
import java.util.Arrays; import java.util.Arrays;
import static emu.grasscutter.Configuration.*;
@Opcodes(PacketOpcodes.SetPlayerBornDataReq) @Opcodes(PacketOpcodes.SetPlayerBornDataReq)
public class HandlerSetPlayerBornDataReq extends PacketHandler { public class HandlerSetPlayerBornDataReq extends PacketHandler {
...@@ -85,12 +87,13 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler { ...@@ -85,12 +87,13 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler {
session.send(new BasePacket(PacketOpcodes.SetPlayerBornDataRsp)); session.send(new BasePacket(PacketOpcodes.SetPlayerBornDataRsp));
// Default mail // Default mail
var welcomeMail = GAME_INFO.joinOptions.welcomeMail;
MailBuilder mailBuilder = new MailBuilder(player.getUid(), new Mail()); MailBuilder mailBuilder = new MailBuilder(player.getUid(), new Mail());
mailBuilder.mail.mailContent.title = Grasscutter.getConfig().GameServer.WelcomeMailTitle; mailBuilder.mail.mailContent.title = welcomeMail.title;
mailBuilder.mail.mailContent.sender = Grasscutter.getConfig().GameServer.WelcomeMailSender; mailBuilder.mail.mailContent.sender = welcomeMail.sender;
// Please credit Grasscutter if changing something here. We don't condone commercial use of the project. // Please credit Grasscutter if changing something here. We don't condone commercial use of the project.
mailBuilder.mail.mailContent.content = Grasscutter.getConfig().GameServer.WelcomeMailContent + "\n<type=\"browser\" text=\"GitHub\" href=\"https://github.com/Melledy/Grasscutter\"/>"; mailBuilder.mail.mailContent.content = welcomeMail.content + "\n<type=\"browser\" text=\"GitHub\" href=\"https://github.com/Melledy/Grasscutter\"/>";
mailBuilder.mail.itemList.addAll(Arrays.asList(Grasscutter.getConfig().GameServer.WelcomeMailItems)); mailBuilder.mail.itemList.addAll(Arrays.asList(welcomeMail.items));
mailBuilder.mail.importance = 1; mailBuilder.mail.importance = 1;
player.sendMail(mailBuilder.mail); player.sendMail(mailBuilder.mail);
} catch (Exception e) { } catch (Exception e) {
......
package emu.grasscutter.server.packet.send; package emu.grasscutter.server.packet.send;
import emu.grasscutter.GameConstants; import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.friends.Friendship; import emu.grasscutter.game.friends.Friendship;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
...@@ -12,20 +11,23 @@ import emu.grasscutter.net.proto.GetPlayerFriendListRspOuterClass.GetPlayerFrien ...@@ -12,20 +11,23 @@ import emu.grasscutter.net.proto.GetPlayerFriendListRspOuterClass.GetPlayerFrien
import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture;
import emu.grasscutter.net.proto.PlatformTypeOuterClass; import emu.grasscutter.net.proto.PlatformTypeOuterClass;
import static emu.grasscutter.Configuration.*;
public class PacketGetPlayerFriendListRsp extends BasePacket { public class PacketGetPlayerFriendListRsp extends BasePacket {
public PacketGetPlayerFriendListRsp(Player player) { public PacketGetPlayerFriendListRsp(Player player) {
super(PacketOpcodes.GetPlayerFriendListRsp); super(PacketOpcodes.GetPlayerFriendListRsp);
var serverAccount = GAME_INFO.serverAccount;
FriendBrief serverFriend = FriendBrief.newBuilder() FriendBrief serverFriend = FriendBrief.newBuilder()
.setUid(GameConstants.SERVER_CONSOLE_UID) .setUid(GameConstants.SERVER_CONSOLE_UID)
.setNickname(Grasscutter.getConfig().getGameServerOptions().ServerNickname) .setNickname(serverAccount.nickName)
.setLevel(Grasscutter.getConfig().getGameServerOptions().ServerLevel) .setLevel(serverAccount.adventureRank)
.setProfilePicture(ProfilePicture.newBuilder().setAvatarId(Grasscutter.getConfig().getGameServerOptions().ServerAvatarId)) .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(serverAccount.avatarId))
.setWorldLevel(Grasscutter.getConfig().getGameServerOptions().ServerWorldLevel) .setWorldLevel(serverAccount.worldLevel)
.setSignature(Grasscutter.getConfig().getGameServerOptions().ServerSignature) .setSignature(serverAccount.signature)
.setLastActiveTime((int) (System.currentTimeMillis() / 1000f)) .setLastActiveTime((int) (System.currentTimeMillis() / 1000f))
.setNameCardId(Grasscutter.getConfig().getGameServerOptions().ServerNameCardId) .setNameCardId(serverAccount.nameCardId)
.setOnlineState(FriendOnlineState.FRIEND_ONLINE) .setOnlineState(FriendOnlineState.FRIEND_ONLINE)
.setParam(1) .setParam(1)
.setIsGameSource(true) .setIsGameSource(true)
...@@ -37,10 +39,12 @@ public class PacketGetPlayerFriendListRsp extends BasePacket { ...@@ -37,10 +39,12 @@ public class PacketGetPlayerFriendListRsp extends BasePacket {
for (Friendship friendship : player.getFriendsList().getFriends().values()) { for (Friendship friendship : player.getFriendsList().getFriends().values()) {
proto.addFriendList(friendship.toProto()); proto.addFriendList(friendship.toProto());
} }
for (Friendship friendship : player.getFriendsList().getPendingFriends().values()) { for (Friendship friendship : player.getFriendsList().getPendingFriends().values()) {
if (friendship.getAskerId() == player.getUid()) { if (friendship.getAskerId() == player.getUid()) {
continue; continue;
} }
proto.addAskFriendList(friendship.toProto()); proto.addAskFriendList(friendship.toProto());
} }
......
...@@ -2,7 +2,6 @@ package emu.grasscutter.server.packet.send; ...@@ -2,7 +2,6 @@ package emu.grasscutter.server.packet.send;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.Grasscutter.ServerDebugMode;
import emu.grasscutter.Grasscutter.ServerRunMode; import emu.grasscutter.Grasscutter.ServerRunMode;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
...@@ -13,9 +12,10 @@ import emu.grasscutter.server.game.GameSession; ...@@ -13,9 +12,10 @@ import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.utils.FileUtils; import emu.grasscutter.utils.FileUtils;
import java.io.File; import java.io.File;
import java.net.URL;
import java.util.Base64; import java.util.Base64;
import static emu.grasscutter.Configuration.*;
public class PacketPlayerLoginRsp extends BasePacket { public class PacketPlayerLoginRsp extends BasePacket {
private static QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionCache; private static QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionCache;
...@@ -27,10 +27,10 @@ public class PacketPlayerLoginRsp extends BasePacket { ...@@ -27,10 +27,10 @@ public class PacketPlayerLoginRsp extends BasePacket {
RegionInfo info; RegionInfo info;
if (Grasscutter.getConfig().RunMode == ServerRunMode.GAME_ONLY) { if (SERVER.runMode == ServerRunMode.GAME_ONLY) {
if (regionCache == null) { if (regionCache == null) {
try { try {
File file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_cur_region.txt"); File file = new File(DATA("query_cur_region.txt"));
String query_cur_region = ""; String query_cur_region = "";
if (file.exists()) { if (file.exists()) {
query_cur_region = new String(FileUtils.read(file)); query_cur_region = new String(FileUtils.read(file));
...@@ -42,9 +42,9 @@ public class PacketPlayerLoginRsp extends BasePacket { ...@@ -42,9 +42,9 @@ public class PacketPlayerLoginRsp extends BasePacket {
QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp.parseFrom(decodedCurRegion); QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp.parseFrom(decodedCurRegion);
RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
.setGateserverIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getGameServerOptions().Ip : Grasscutter.getConfig().getGameServerOptions().PublicIp)) .setGateserverIp(lr(GAME_INFO.accessAddress, GAME_INFO.bindAddress))
.setGateserverPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0 ? Grasscutter.getConfig().getGameServerOptions().PublicPort : Grasscutter.getConfig().getGameServerOptions().Port) .setGateserverPort(lr(GAME_INFO.accessPort, GAME_INFO.bindPort))
.setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin"))) .setSecretKey(ByteString.copyFrom(FileUtils.read(KEYS_FOLDER + "/dispatchSeed.bin")))
.build(); .build();
regionCache = regionQuery.toBuilder().setRegionInfo(serverRegion).build(); regionCache = regionQuery.toBuilder().setRegionInfo(serverRegion).build();
......
package emu.grasscutter.server.packet.send; package emu.grasscutter.server.packet.send;
import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
...@@ -10,6 +8,8 @@ import emu.grasscutter.net.proto.ItemOuterClass.Item; ...@@ -10,6 +8,8 @@ import emu.grasscutter.net.proto.ItemOuterClass.Item;
import emu.grasscutter.net.proto.PlayerStoreNotifyOuterClass.PlayerStoreNotify; import emu.grasscutter.net.proto.PlayerStoreNotifyOuterClass.PlayerStoreNotify;
import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType;
import static emu.grasscutter.Configuration.*;
public class PacketPlayerStoreNotify extends BasePacket { public class PacketPlayerStoreNotify extends BasePacket {
public PacketPlayerStoreNotify(Player player) { public PacketPlayerStoreNotify(Player player) {
...@@ -19,7 +19,7 @@ public class PacketPlayerStoreNotify extends BasePacket { ...@@ -19,7 +19,7 @@ public class PacketPlayerStoreNotify extends BasePacket {
PlayerStoreNotify.Builder p = PlayerStoreNotify.newBuilder() PlayerStoreNotify.Builder p = PlayerStoreNotify.newBuilder()
.setStoreType(StoreType.STORE_PACK) .setStoreType(StoreType.STORE_PACK)
.setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll); .setWeightLimit(GAME_OPTIONS.inventoryLimits.all);
for (GameItem item : player.getInventory()) { for (GameItem item : player.getInventory()) {
Item itemProto = item.toProto(); Item itemProto = item.toProto();
......
package emu.grasscutter.server.packet.send; package emu.grasscutter.server.packet.send;
import emu.grasscutter.Config.GameServerOptions;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.GameConstants; import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo;
import emu.grasscutter.net.proto.PullRecentChatRspOuterClass.PullRecentChatRsp; import emu.grasscutter.net.proto.PullRecentChatRspOuterClass.PullRecentChatRsp;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import static emu.grasscutter.Configuration.*;
public class PacketPullRecentChatRsp extends BasePacket { public class PacketPullRecentChatRsp extends BasePacket {
public PacketPullRecentChatRsp(Player player) { public PacketPullRecentChatRsp(Player player) {
super(PacketOpcodes.PullRecentChatRsp); super(PacketOpcodes.PullRecentChatRsp);
GameServerOptions serverOptions = Grasscutter.getConfig().getGameServerOptions(); var joinOptions = GAME_INFO.joinOptions;
PullRecentChatRsp.Builder proto = PullRecentChatRsp.newBuilder(); PullRecentChatRsp.Builder proto = PullRecentChatRsp.newBuilder();
if (serverOptions.WelcomeEmotes != null && serverOptions.WelcomeEmotes.length > 0) { if (joinOptions.welcomeEmotes != null && joinOptions.welcomeEmotes.length > 0) {
ChatInfo welcomeEmote = ChatInfo.newBuilder() ChatInfo welcomeEmote = ChatInfo.newBuilder()
.setTime((int) (System.currentTimeMillis() / 1000)) .setTime((int) (System.currentTimeMillis() / 1000))
.setUid(GameConstants.SERVER_CONSOLE_UID) .setUid(GameConstants.SERVER_CONSOLE_UID)
.setToUid(player.getUid()) .setToUid(player.getUid())
.setIcon(serverOptions.WelcomeEmotes[Utils.randomRange(0, serverOptions.WelcomeEmotes.length - 1)]) .setIcon(joinOptions.welcomeEmotes[Utils.randomRange(0, joinOptions.welcomeEmotes.length - 1)])
.build(); .build();
proto.addChatInfo(welcomeEmote); proto.addChatInfo(welcomeEmote);
} }
if (serverOptions.WelcomeMotd != null && serverOptions.WelcomeMotd.length() > 0) { if (joinOptions.welcomeMessage != null && joinOptions.welcomeMessage.length() > 0) {
ChatInfo welcomeMotd = ChatInfo.newBuilder() ChatInfo welcomeMessage = ChatInfo.newBuilder()
.setTime((int) (System.currentTimeMillis() / 1000)) .setTime((int) (System.currentTimeMillis() / 1000))
.setUid(GameConstants.SERVER_CONSOLE_UID) .setUid(GameConstants.SERVER_CONSOLE_UID)
.setToUid(player.getUid()) .setToUid(player.getUid())
.setText(Grasscutter.getConfig().getGameServerOptions().WelcomeMotd) .setText(joinOptions.welcomeMessage)
.build(); .build();
proto.addChatInfo(welcomeMessage);
proto.addChatInfo(welcomeMotd);
} }
this.setData(proto); this.setData(proto);
......
package emu.grasscutter.server.packet.send; package emu.grasscutter.server.packet.send;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType;
import emu.grasscutter.net.proto.StoreWeightLimitNotifyOuterClass.StoreWeightLimitNotify; import emu.grasscutter.net.proto.StoreWeightLimitNotifyOuterClass.StoreWeightLimitNotify;
import static emu.grasscutter.Configuration.*;
public class PacketStoreWeightLimitNotify extends BasePacket { public class PacketStoreWeightLimitNotify extends BasePacket {
public PacketStoreWeightLimitNotify() { public PacketStoreWeightLimitNotify() {
...@@ -13,11 +14,11 @@ public class PacketStoreWeightLimitNotify extends BasePacket { ...@@ -13,11 +14,11 @@ public class PacketStoreWeightLimitNotify extends BasePacket {
StoreWeightLimitNotify p = StoreWeightLimitNotify.newBuilder() StoreWeightLimitNotify p = StoreWeightLimitNotify.newBuilder()
.setStoreType(StoreType.STORE_PACK) .setStoreType(StoreType.STORE_PACK)
.setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll) .setWeightLimit(INVENTORY_LIMITS.all)
.setWeaponCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitWeapon) .setWeaponCountLimit(INVENTORY_LIMITS.weapons)
.setReliquaryCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitRelic) .setReliquaryCountLimit(INVENTORY_LIMITS.relics)
.setMaterialCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitMaterial) .setMaterialCountLimit(INVENTORY_LIMITS.materials)
.setFurnitureCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitFurniture) .setFurnitureCountLimit(INVENTORY_LIMITS.furniture)
.build(); .build();
this.setData(p); this.setData(p);
......
package emu.grasscutter.tools; package emu.grasscutter.tools;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.PrintWriter; import java.io.PrintWriter;
...@@ -14,14 +10,12 @@ import java.nio.charset.StandardCharsets; ...@@ -14,14 +10,12 @@ import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import emu.grasscutter.GameConstants; import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command; import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.command.CommandMap; import emu.grasscutter.command.CommandMap;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.ResourceLoader; import emu.grasscutter.data.ResourceLoader;
...@@ -32,6 +26,7 @@ import emu.grasscutter.data.def.SceneData; ...@@ -32,6 +26,7 @@ import emu.grasscutter.data.def.SceneData;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import static emu.grasscutter.utils.Language.translate; import static emu.grasscutter.utils.Language.translate;
import static emu.grasscutter.Configuration.*;
public final class Tools { public final class Tools {
public static void createGmHandbook() throws Exception { public static void createGmHandbook() throws Exception {
...@@ -42,50 +37,45 @@ public final class Tools { ...@@ -42,50 +37,45 @@ public final class Tools {
ToolsWithLanguageOption.createGachaMapping(location, getLanguageOption()); ToolsWithLanguageOption.createGachaMapping(location, getLanguageOption());
} }
public static List<String> getAvailableLanguage() throws Exception { public static List<String> getAvailableLanguage() {
File textMapFolder = new File(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap"); File textMapFolder = new File(RESOURCE("TextMap"));
List<String> availableLangList = new ArrayList<String>(); List<String> availableLangList = new ArrayList<>();
for (String textMapFileName : textMapFolder.list(new FilenameFilter() { for (String textMapFileName : Objects.requireNonNull(textMapFolder.list((dir, name) -> name.startsWith("TextMap") && name.endsWith(".json")))) {
@Override availableLangList.add(textMapFileName.replace("TextMap", "").replace(".json", "").toLowerCase());
public boolean accept(File dir, String name) { } return availableLangList;
if (name.startsWith("TextMap") && name.endsWith(".json")){
return true;
}
return false;
}
})) {
availableLangList.add(textMapFileName.replace("TextMap","").replace(".json","").toLowerCase());
}
return availableLangList;
} }
public static String getLanguageOption() throws Exception { public static String getLanguageOption() {
List<String> availableLangList = getAvailableLanguage(); List<String> availableLangList = getAvailableLanguage();
// Use system out for better format // Use system out for better format
if (availableLangList.size() == 1) { if (availableLangList.size() == 1) {
return availableLangList.get(0).toUpperCase(); return availableLangList.get(0).toUpperCase();
} }
String stagedMessage = ""; StringBuilder stagedMessage = new StringBuilder();
stagedMessage += "The following languages mappings are available, please select one: [default: EN]\n"; stagedMessage.append("The following languages mappings are available, please select one: [default: EN] \n");
String groupedLangList = ">\t";
StringBuilder groupedLangList = new StringBuilder(">\t"); String input;
int groupedLangCount = 0; int groupedLangCount = 0;
String input = "";
for (String availableLanguage: availableLangList){ for (String availableLanguage: availableLangList){
groupedLangCount++; groupedLangCount++;
groupedLangList = groupedLangList + "" + availableLanguage + "\t"; groupedLangList.append(availableLanguage).append("\t");
if (groupedLangCount == 6) { if (groupedLangCount == 6) {
stagedMessage += groupedLangList + "\n"; stagedMessage.append(groupedLangList).append("\n");
groupedLangCount = 0; groupedLangCount = 0;
groupedLangList = ">\t"; groupedLangList = new StringBuilder(">\t");
} }
} }
if (groupedLangCount > 0) { if (groupedLangCount > 0) {
stagedMessage += groupedLangList + "\n"; stagedMessage.append(groupedLangList).append("\n");
} }
stagedMessage += "\nYour choice:[EN] ";
input = Grasscutter.getConsole().readLine(stagedMessage); stagedMessage.append("\nYour choice:[EN] ");
input = Grasscutter.getConsole().readLine(stagedMessage.toString());
if (availableLangList.contains(input.toLowerCase())) { if (availableLangList.contains(input.toLowerCase())) {
return input.toUpperCase(); return input.toUpperCase();
} }
...@@ -101,7 +91,7 @@ final class ToolsWithLanguageOption { ...@@ -101,7 +91,7 @@ final class ToolsWithLanguageOption {
ResourceLoader.loadResources(); ResourceLoader.loadResources();
Map<Long, String> map; Map<Long, String> map;
try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap/TextMap"+language+".json")), StandardCharsets.UTF_8)) { try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(RESOURCE("TextMap/TextMap"+language+".json"))), StandardCharsets.UTF_8)) {
map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken<Map<Long, String>>() {}.getType()); map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken<Map<Long, String>>() {}.getType());
} }
...@@ -119,9 +109,9 @@ final class ToolsWithLanguageOption { ...@@ -119,9 +109,9 @@ final class ToolsWithLanguageOption {
writer.println("// Commands"); writer.println("// Commands");
for (Command cmd : cmdList) { for (Command cmd : cmdList) {
String cmdName = cmd.label(); StringBuilder cmdName = new StringBuilder(cmd.label());
while (cmdName.length() <= 15) { while (cmdName.length() <= 15) {
cmdName = " " + cmdName; cmdName.insert(0, " ");
} }
writer.println(cmdName + " : " + translate(cmd.description())); writer.println(cmdName + " : " + translate(cmd.description()));
} }
...@@ -178,16 +168,13 @@ final class ToolsWithLanguageOption { ...@@ -178,16 +168,13 @@ final class ToolsWithLanguageOption {
ResourceLoader.loadResources(); ResourceLoader.loadResources();
Map<Long, String> map; Map<Long, String> map;
try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap/TextMap"+language+".json")), StandardCharsets.UTF_8)) { try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(RESOURCE("TextMap/TextMap" + language + ".json"))), StandardCharsets.UTF_8)) {
map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken<Map<Long, String>>() {}.getType()); map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken<Map<Long, String>>() {}.getType());
} }
List<Integer> list; List<Integer> list;
String fileName = location; try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(location), StandardCharsets.UTF_8), false)) {
try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8), false)) {
list = new ArrayList<>(GameData.getAvatarDataMap().keySet()); list = new ArrayList<>(GameData.getAvatarDataMap().keySet());
Collections.sort(list); Collections.sort(list);
...@@ -209,18 +196,11 @@ final class ToolsWithLanguageOption { ...@@ -209,18 +196,11 @@ final class ToolsWithLanguageOption {
} else { } else {
writer.print(","); writer.print(",");
} }
String color; String color = switch (data.getQualityType()) {
switch (data.getQualityType()){ case "QUALITY_PURPLE" -> "purple";
case "QUALITY_PURPLE": case "QUALITY_ORANGE" -> "yellow";
color = "purple"; default -> "blue";
break; };
case "QUALITY_ORANGE":
color = "yellow";
break;
case "QUALITY_BLUE":
default:
color = "blue";
}
// Got the magic number 4233146695 from manually search in the json file // Got the magic number 4233146695 from manually search in the json file
writer.println( writer.println(
"\"" + (avatarID % 1000 + 1000) + "\" : [\"" "\"" + (avatarID % 1000 + 1000) + "\" : [\""
......
package emu.grasscutter.utils;
import com.google.gson.JsonObject;
import emu.grasscutter.Grasscutter;
import java.io.FileReader;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Locale;
import static emu.grasscutter.Grasscutter.config;
/**
* *when your JVM fails*
*/
public class ConfigContainer {
private static int version() {
return 1;
}
/**
* Attempts to update the server's existing configuration to the latest
*/
public static void updateConfig() {
try { // Check if the server is using a legacy config.
JsonObject configObject = Grasscutter.getGsonFactory()
.fromJson(new FileReader(Grasscutter.configFile), JsonObject.class);
if(!configObject.has("version")) {
Grasscutter.getLogger().info("Updating legacy ..");
Grasscutter.saveConfig(null);
}
} catch (Exception ignored) { }
var existing = config.version;
var latest = version();
if(existing == latest)
return;
// Create a new configuration instance.
ConfigContainer updated = new ConfigContainer();
// Update all configuration fields.
Field[] fields = ConfigContainer.class.getDeclaredFields();
Arrays.stream(fields).forEach(field -> {
try {
field.set(updated, field.get(config));
} catch (Exception exception) {
Grasscutter.getLogger().error("Failed to update a configuration field.", exception);
}
}); updated.version = version();
try { // Save configuration & reload.
Grasscutter.saveConfig(updated);
Grasscutter.loadConfig();
} catch (Exception exception) {
Grasscutter.getLogger().warn("Failed to inject the updated ", exception);
}
}
public Structure folderStructure = new Structure();
public Database databaseInfo = new Database();
public Language language = new Language();
public Account account = new Account();
public Server server = new Server();
// DO NOT. TOUCH. THE VERSION NUMBER.
public int version = version();
/* Option containers. */
public static class Database {
public String connectionUri = "mongodb://localhost:27017";
public String collection = "grasscutter";
}
public static class Structure {
public String resources = "./resources/";
public String data = "./data/";
public String packets = "./packets/";
public String keys = "./keys/";
public String scripts = "./resources/scripts/";
public String plugins = "./plugins/";
// UNUSED (potentially added later?)
// public String dumps = "./dumps/";
}
public static class Server {
public Grasscutter.ServerDebugMode debugLevel = Grasscutter.ServerDebugMode.NONE;
public Grasscutter.ServerRunMode runMode = Grasscutter.ServerRunMode.HYBRID;
public Dispatch dispatch = new Dispatch();
public Game game = new Game();
}
public static class Language {
public Locale language = Locale.getDefault();
public Locale fallback = Locale.US;
}
public static class Account {
public boolean autoCreate = false;
public String[] defaultPermissions = {};
}
/* Server options. */
public static class Dispatch {
public String bindAddress = "0.0.0.0";
/* This is the address used in URLs. */
public String accessAddress = "127.0.0.1";
public int bindPort = 443;
/* This is the port used in URLs. */
public int accessPort = 443;
public Encryption encryption = new Encryption();
public Policies policies = new Policies();
public Region[] regions = {};
public String defaultName = "Grasscutter";
}
public static class Game {
public String bindAddress = "0.0.0.0";
/* This is the address used in the default region. */
public String accessAddress = "127.0.0.1";
public int bindPort = 443;
/* This is the port used in the default region. */
public int accessPort = 443;
public GameOptions gameOptions = new GameOptions();
public JoinOptions joinOptions = new JoinOptions();
public ConsoleAccount serverAccount = new ConsoleAccount();
}
/* Data containers. */
public static class Encryption {
public boolean useEncryption = true;
/* Should 'https' be appended to URLs? */
public boolean useInRouting = true;
public String keystore = "./keystore.p12";
public String keystorePassword = "123456";
}
public static class Policies {
public Policies.CORS cors = new Policies.CORS();
public static class CORS {
public boolean enabled = false;
public String[] allowedOrigins = new String[]{"*"};
}
}
public static class GameOptions {
public GameOptions.InventoryLimits inventoryLimits = new GameOptions.InventoryLimits();
public GameOptions.AvatarLimits avatarLimits = new GameOptions.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 static class InventoryLimits {
public int weapons = 2000;
public int relics = 2000;
public int materials = 2000;
public int furniture = 2000;
public int all = 30000;
}
public static class AvatarLimits {
public int singlePlayerTeam = 4;
public int multiplayerTeam = 4;
}
public static class Rates {
public float adventureExp = 1.0f;
public float mora = 1.0f;
public float leyLines = 1.0f;
}
}
public static class JoinOptions {
public int[] welcomeEmotes = {2007, 1002, 4010};
public String welcomeMessage = "Welcome to a Grasscutter server.";
public JoinOptions.Mail welcomeMail = new JoinOptions.Mail();
public static class Mail {
public String title = "Welcome to Grasscutter!";
public String content = """
Hi there!\r
First of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you! \r
\r
Check out our:\r
<type="browser" text="Discord" href="https://discord.gg/T5vZU6UyeG"/>
""";
public String sender = "Lawnmower";
public emu.grasscutter.game.mail.Mail.MailItem[] items = {
new emu.grasscutter.game.mail.Mail.MailItem(13509, 1, 1),
new emu.grasscutter.game.mail.Mail.MailItem(201, 99999, 1)
};
}
}
public static class ConsoleAccount {
public int avatarId = 10000007;
public int nameCardId = 210001;
public int adventureRank = 1;
public int worldLevel = 0;
public String nickName = "Server";
public String signature = "Welcome to Grasscutter!";
}
/* Objects. */
public static class Region {
public String Name = "os_usa";
public String Title = "Grasscutter";
public String Ip = "127.0.0.1";
public int Port = 22102;
}
}
...@@ -7,6 +7,8 @@ import emu.grasscutter.Grasscutter; ...@@ -7,6 +7,8 @@ import emu.grasscutter.Grasscutter;
import emu.grasscutter.net.proto.GetPlayerTokenRspOuterClass.GetPlayerTokenRsp; import emu.grasscutter.net.proto.GetPlayerTokenRspOuterClass.GetPlayerTokenRsp;
import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp; import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp;
import static emu.grasscutter.Configuration.*;
public final class Crypto { public final class Crypto {
private static final SecureRandom secureRandom = new SecureRandom(); private static final SecureRandom secureRandom = new SecureRandom();
public static final long ENCRYPT_SEED = Long.parseUnsignedLong("11468049314633205968"); public static final long ENCRYPT_SEED = Long.parseUnsignedLong("11468049314633205968");
...@@ -16,9 +18,9 @@ public final class Crypto { ...@@ -16,9 +18,9 @@ public final class Crypto {
public static byte[] ENCRYPT_KEY; public static byte[] ENCRYPT_KEY;
public static void loadKeys() { public static void loadKeys() {
DISPATCH_KEY = FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchKey.bin"); DISPATCH_KEY = FileUtils.read(KEYS_FOLDER + "/dispatchKey.bin");
ENCRYPT_KEY = FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "secretKey.bin"); ENCRYPT_KEY = FileUtils.read(KEYS_FOLDER + "/secretKey.bin");
ENCRYPT_SEED_BUFFER = FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "secretKeyBuffer.bin"); ENCRYPT_SEED_BUFFER = FileUtils.read(KEYS_FOLDER + "/secretKeyBuffer.bin");
} }
public static void xor(byte[] packet, byte[] key) { public static void xor(byte[] packet, byte[] key) {
...@@ -34,7 +36,7 @@ public final class Crypto { ...@@ -34,7 +36,7 @@ public final class Crypto {
public static void extractSecretKeyBuffer(byte[] data) { public static void extractSecretKeyBuffer(byte[] data) {
try { try {
GetPlayerTokenRsp p = GetPlayerTokenRsp.parseFrom(data); GetPlayerTokenRsp p = GetPlayerTokenRsp.parseFrom(data);
FileUtils.write(Grasscutter.getConfig().KEY_FOLDER + "secretKeyBuffer.bin", p.getSecretKeyBytes().toByteArray()); FileUtils.write(KEYS_FOLDER + "/secretKeyBuffer.bin", p.getSecretKeyBytes().toByteArray());
Grasscutter.getLogger().info("Secret Key: " + p.getSecretKey()); Grasscutter.getLogger().info("Secret Key: " + p.getSecretKey());
} catch (Exception e) { } catch (Exception e) {
Grasscutter.getLogger().error("Crypto error.", e); Grasscutter.getLogger().error("Crypto error.", e);
...@@ -44,7 +46,7 @@ public final class Crypto { ...@@ -44,7 +46,7 @@ public final class Crypto {
public static void extractDispatchSeed(String data) { public static void extractDispatchSeed(String data) {
try { try {
QueryCurrRegionHttpRsp p = QueryCurrRegionHttpRsp.parseFrom(Base64.getDecoder().decode(data)); QueryCurrRegionHttpRsp p = QueryCurrRegionHttpRsp.parseFrom(Base64.getDecoder().decode(data));
FileUtils.write(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin", p.getRegionInfo().getSecretKey().toByteArray()); FileUtils.write(KEYS_FOLDER + "/dispatchSeed.bin", p.getRegionInfo().getSecretKey().toByteArray());
} catch (Exception e) { } catch (Exception e) {
Grasscutter.getLogger().error("Crypto error.", e); Grasscutter.getLogger().error("Crypto error.", e);
} }
......
...@@ -10,6 +10,8 @@ import java.io.InputStream; ...@@ -10,6 +10,8 @@ import java.io.InputStream;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.Map; import java.util.Map;
import static emu.grasscutter.Configuration.*;
public final class Language { public final class Language {
private static final Map<String, Language> cachedLanguages = new ConcurrentHashMap<>(); private static final Map<String, Language> cachedLanguages = new ConcurrentHashMap<>();
...@@ -27,8 +29,8 @@ public final class Language { ...@@ -27,8 +29,8 @@ public final class Language {
return cachedLanguages.get(langCode); return cachedLanguages.get(langCode);
} }
var fallbackLanguageCode = Utils.getLanguageCode(Grasscutter.getConfig().DefaultLanguage); var fallbackLanguageCode = Utils.getLanguageCode(FALLBACK_LANGUAGE);
var description = getLanguageFileStreamDescripter(langCode, fallbackLanguageCode); var description = getLanguageFileDescription(langCode, fallbackLanguageCode);
var actualLanguageCode = description.getLanguageCode(); var actualLanguageCode = description.getLanguageCode();
Language languageInst; Language languageInst;
...@@ -111,7 +113,7 @@ public final class Language { ...@@ -111,7 +113,7 @@ public final class Language {
* @param languageCode The name of the language code. * @param languageCode The name of the language code.
* @param fallbackLanguageCode The name of the fallback language code. * @param fallbackLanguageCode The name of the fallback language code.
*/ */
private static LanguageStreamDescription getLanguageFileStreamDescripter(String languageCode, String fallbackLanguageCode) { private static LanguageStreamDescription getLanguageFileDescription(String languageCode, String fallbackLanguageCode) {
var fileName = languageCode + ".json"; var fileName = languageCode + ".json";
var fallback = fallbackLanguageCode + ".json"; var fallback = fallbackLanguageCode + ".json";
......
...@@ -11,7 +11,6 @@ import java.util.Map; ...@@ -11,7 +11,6 @@ import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Locale; import java.util.Locale;
import emu.grasscutter.Config;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
...@@ -175,12 +174,12 @@ public final class Utils { ...@@ -175,12 +174,12 @@ public final class Utils {
* Checks for required files and folders before startup. * Checks for required files and folders before startup.
*/ */
public static void startupCheck() { public static void startupCheck() {
Config config = Grasscutter.getConfig(); ConfigContainer config = Grasscutter.getConfig();
Logger logger = Grasscutter.getLogger(); Logger logger = Grasscutter.getLogger();
boolean exit = false; boolean exit = false;
String resourcesFolder = config.RESOURCE_FOLDER; String resourcesFolder = config.folderStructure.resources;
String dataFolder = config.DATA_FOLDER; String dataFolder = config.folderStructure.data;
// Check for resources folder. // Check for resources folder.
if(!fileExists(resourcesFolder)) { if(!fileExists(resourcesFolder)) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment