Commit 9125bacf authored by ButterCookies's avatar ButterCookies Committed by GitHub
Browse files

Set the maximum number of player on the server through the config.json (#1001)

* Show server status to three-party game launcher

* Set the maximum number of player on the server through the config.json

* modify the logical order and show the number of maxplayer to API /status/server

* Now even players who have token already cannot bypass the maxPlayer check
parent 2a467a48
...@@ -23,14 +23,16 @@ public final class DefaultAuthenticators { ...@@ -23,14 +23,16 @@ public final class DefaultAuthenticators {
var requestData = request.getPasswordRequest(); var requestData = request.getPasswordRequest();
assert requestData != null; // This should never be null. assert requestData != null; // This should never be null.
int playerCount = Grasscutter.getGameServer().getPlayers().size();
boolean successfulLogin = false; boolean successfulLogin = false;
String address = request.getRequest().ip(); String address = request.getRequest().ip();
String responseMessage = translate("messages.dispatch.account.username_error"); String responseMessage = translate("messages.dispatch.account.username_error");
String loggerMessage = "";
// Get account from database. // Get account from database.
Account account = DatabaseHelper.getAccountByName(requestData.account); Account account = DatabaseHelper.getAccountByName(requestData.account);
if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) {
// Check if account exists. // Check if account exists.
if(account == null && ACCOUNT.autoCreate) { if(account == null && 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.
...@@ -49,6 +51,14 @@ public final class DefaultAuthenticators { ...@@ -49,6 +51,14 @@ public final class DefaultAuthenticators {
} }
} else if(account != null) } else if(account != null)
successfulLogin = true; successfulLogin = true;
else
loggerMessage = translate("messages.dispatch.account.account_login_exist_error", address);
} else {
responseMessage = translate("messages.dispatch.account.server_max_player_limit");
loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address);
}
// Set response data. // Set response data.
if(successfulLogin) { if(successfulLogin) {
...@@ -57,15 +67,13 @@ public final class DefaultAuthenticators { ...@@ -57,15 +67,13 @@ public final class DefaultAuthenticators {
response.data.account.token = account.generateSessionKey(); response.data.account.token = account.generateSessionKey();
response.data.account.email = account.getEmail(); response.data.account.email = account.getEmail();
// Log the login. loggerMessage = translate("messages.dispatch.account.login_success", address, account.getId());
Grasscutter.getLogger().info(translate("messages.dispatch.account.login_success", address, account.getId()));
} else { } else {
response.retcode = -201; response.retcode = -201;
response.message = responseMessage; response.message = responseMessage;
// Log the failure.
Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_exist_error", address));
} }
Grasscutter.getLogger().info(loggerMessage);
return response; return response;
} }
...@@ -83,10 +91,14 @@ public final class DefaultAuthenticators { ...@@ -83,10 +91,14 @@ public final class DefaultAuthenticators {
boolean successfulLogin; boolean successfulLogin;
String address = request.getRequest().ip(); String address = request.getRequest().ip();
String loggerMessage;
int playerCount = Grasscutter.getGameServer().getPlayers().size();
// Log the attempt. // Log the attempt.
Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_attempt", address)); Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_attempt", address));
if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) {
// Get account from database. // Get account from database.
Account account = DatabaseHelper.getAccountById(requestData.uid); Account account = DatabaseHelper.getAccountById(requestData.uid);
...@@ -101,15 +113,23 @@ public final class DefaultAuthenticators { ...@@ -101,15 +113,23 @@ public final class DefaultAuthenticators {
response.data.account.email = account.getEmail(); response.data.account.email = account.getEmail();
// Log the login. // Log the login.
Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_success", address, requestData.uid)); loggerMessage = translate("messages.dispatch.account.login_token_success", address, requestData.uid);
} else { } else {
response.retcode = -201; response.retcode = -201;
response.message = translate("messages.dispatch.account.account_cache_error"); response.message = translate("messages.dispatch.account.account_cache_error");
// Log the failure. // Log the failure.
Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_error", address)); loggerMessage = translate("messages.dispatch.account.login_token_error", address);
}
} else {
response.retcode = -201;
response.message = translate("messages.dispatch.account.server_max_player_limit");
loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address);
} }
Grasscutter.getLogger().info(loggerMessage);
return response; return response;
} }
} }
...@@ -127,7 +147,10 @@ public final class DefaultAuthenticators { ...@@ -127,7 +147,10 @@ public final class DefaultAuthenticators {
boolean successfulLogin; boolean successfulLogin;
String address = request.getRequest().ip(); String address = request.getRequest().ip();
String loggerMessage;
int playerCount = Grasscutter.getGameServer().getPlayers().size();
if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) {
// Get account from database. // Get account from database.
Account account = DatabaseHelper.getAccountById(loginData.uid); Account account = DatabaseHelper.getAccountById(loginData.uid);
...@@ -142,15 +165,23 @@ public final class DefaultAuthenticators { ...@@ -142,15 +165,23 @@ public final class DefaultAuthenticators {
response.data.combo_token = account.generateLoginToken(); response.data.combo_token = account.generateLoginToken();
// Log the login. // Log the login.
Grasscutter.getLogger().info(translate("messages.dispatch.account.combo_token_success", address)); loggerMessage = translate("messages.dispatch.account.combo_token_success", address);
} else { } else {
response.retcode = -201; response.retcode = -201;
response.message = translate("messages.dispatch.account.session_key_error"); response.message = translate("messages.dispatch.account.session_key_error");
// Log the failure. // Log the failure.
Grasscutter.getLogger().info(translate("messages.dispatch.account.combo_token_error", address)); loggerMessage = translate("messages.dispatch.account.combo_token_error", address);
}
} else {
response.retcode = -201;
response.message = translate("messages.dispatch.account.server_max_player_limit");
loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address);
} }
Grasscutter.getLogger().info(loggerMessage);
return response; return response;
} }
} }
......
...@@ -9,6 +9,8 @@ import express.http.Request; ...@@ -9,6 +9,8 @@ import express.http.Request;
import express.http.Response; import express.http.Response;
import io.javalin.Javalin; import io.javalin.Javalin;
import static emu.grasscutter.Configuration.ACCOUNT;
/** /**
* Handles all generic, hard-coded responses. * Handles all generic, hard-coded responses.
*/ */
...@@ -48,8 +50,9 @@ public final class GenericHandler implements Router { ...@@ -48,8 +50,9 @@ public final class GenericHandler implements Router {
private static void serverStatus(Request request, Response response) { private static void serverStatus(Request request, Response response) {
int playerCount = Grasscutter.getGameServer().getPlayers().size(); int playerCount = Grasscutter.getGameServer().getPlayers().size();
int maxPlayer = ACCOUNT.maxPlayer;
String version = GameConstants.VERSION; String version = GameConstants.VERSION;
response.send("{\"retcode\":0,\"status\":{\"playerCount\":" + playerCount + ",\"version\":\"" + version + "\"}}"); response.send("{\"retcode\":0,\"status\":{\"playerCount\":" + playerCount + ",\"maxPlayer\":" + maxPlayer + ",\"version\":\"" + version + "\"}}");
} }
} }
package emu.grasscutter.server.packet.recv; package emu.grasscutter.server.packet.recv;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.database.DatabaseHelper;
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,6 +13,8 @@ import emu.grasscutter.server.game.GameSession.SessionState; ...@@ -12,6 +13,8 @@ import emu.grasscutter.server.game.GameSession.SessionState;
import emu.grasscutter.server.packet.send.PacketPlayerLoginRsp; import emu.grasscutter.server.packet.send.PacketPlayerLoginRsp;
import emu.grasscutter.server.packet.send.PacketTakeAchievementRewardReq; import emu.grasscutter.server.packet.send.PacketTakeAchievementRewardReq;
import static emu.grasscutter.Configuration.ACCOUNT;
@Opcodes(PacketOpcodes.PlayerLoginReq) // Sends initial data packets @Opcodes(PacketOpcodes.PlayerLoginReq) // Sends initial data packets
public class HandlerPlayerLoginReq extends PacketHandler { public class HandlerPlayerLoginReq extends PacketHandler {
...@@ -22,6 +25,11 @@ public class HandlerPlayerLoginReq extends PacketHandler { ...@@ -22,6 +25,11 @@ public class HandlerPlayerLoginReq extends PacketHandler {
return; return;
} }
// Max players limit
if (ACCOUNT.maxPlayer > -1 && Grasscutter.getGameServer().getPlayers().size() >= ACCOUNT.maxPlayer) {
return;
}
// Parse request // Parse request
PlayerLoginReq req = PlayerLoginReq.parseFrom(payload); PlayerLoginReq req = PlayerLoginReq.parseFrom(payload);
......
...@@ -110,6 +110,7 @@ public class ConfigContainer { ...@@ -110,6 +110,7 @@ public class ConfigContainer {
public static class Account { public static class Account {
public boolean autoCreate = false; public boolean autoCreate = false;
public String[] defaultPermissions = {}; public String[] defaultPermissions = {};
public int maxPlayer = -1;
} }
/* Server options. */ /* Server options. */
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
"account": { "account": {
"login_attempt": "[Dispatch] Client %s is trying to log in.", "login_attempt": "[Dispatch] Client %s is trying to log in.",
"login_success": "[Dispatch] Client %s logged in as %s.", "login_success": "[Dispatch] Client %s logged in as %s.",
"login_max_player_limit": "[Dispatch] Client %s failed to log in: The number of online players has reached the limit",
"login_token_attempt": "[Dispatch] Client %s is trying to log in via token.", "login_token_attempt": "[Dispatch] Client %s is trying to log in via token.",
"login_token_error": "[Dispatch] Client %s failed to log in via token.", "login_token_error": "[Dispatch] Client %s failed to log in via token.",
"login_token_success": "[Dispatch] Client %s logged in via token as %s.", "login_token_success": "[Dispatch] Client %s logged in via token as %s.",
...@@ -35,7 +36,8 @@ ...@@ -35,7 +36,8 @@
"account_cache_error": "Game account cache information error.", "account_cache_error": "Game account cache information error.",
"session_key_error": "Wrong session key.", "session_key_error": "Wrong session key.",
"username_error": "Username not found.", "username_error": "Username not found.",
"username_create_error": "Username not found, create failed." "username_create_error": "Username not found, create failed.",
"server_max_player_limit": "The number of online players has reached the limit"
}, },
"router_error": "[Dispatch] Unable to attach router." "router_error": "[Dispatch] Unable to attach router."
}, },
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
"account": { "account": {
"login_attempt": "[Dispatch] Klient %s próbuje się zalogować", "login_attempt": "[Dispatch] Klient %s próbuje się zalogować",
"login_success": "[Dispatch] Klient %s zalogował się jako %s", "login_success": "[Dispatch] Klient %s zalogował się jako %s",
"login_max_player_limit": "[Dispatch] Klient %s nie powiodło się: Liczba graczy online osiągnęła limit",
"login_token_attempt": "[Dispatch] Klient %s próbuje się zalogować poprzez token", "login_token_attempt": "[Dispatch] Klient %s próbuje się zalogować poprzez token",
"login_token_error": "[Dispatch] Klient %s nie mógł się zalogować poprzez token", "login_token_error": "[Dispatch] Klient %s nie mógł się zalogować poprzez token",
"login_token_success": "[Dispatch] Klient %s zalogował się poprzez token jako %s", "login_token_success": "[Dispatch] Klient %s zalogował się poprzez token jako %s",
...@@ -32,7 +33,8 @@ ...@@ -32,7 +33,8 @@
"account_cache_error": "Błąd pamięci cache konta gry", "account_cache_error": "Błąd pamięci cache konta gry",
"session_key_error": "Błędny klucz sesji.", "session_key_error": "Błędny klucz sesji.",
"username_error": "Nazwa użytkownika nie znaleziona.", "username_error": "Nazwa użytkownika nie znaleziona.",
"username_create_error": "Nazwa użytkownika nie znaleziona, tworzenie nie powiodło się." "username_create_error": "Nazwa użytkownika nie znaleziona, tworzenie nie powiodło się.",
"server_max_player_limit": "Liczba graczy online osiągnęła limit"
} }
}, },
"status": { "status": {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
"account": { "account": {
"login_attempt": "[Dispatch] 客户端 %s 正在尝试登录", "login_attempt": "[Dispatch] 客户端 %s 正在尝试登录",
"login_success": "[Dispatch] 客户端 %s 已登录,UID 为 %s", "login_success": "[Dispatch] 客户端 %s 已登录,UID 为 %s",
"login_max_player_limit": "[Dispatch] 客户端 %s 登录失败:在线人数已满",
"login_token_attempt": "[Dispatch] 客户端 %s 正在尝试使用 token 登录", "login_token_attempt": "[Dispatch] 客户端 %s 正在尝试使用 token 登录",
"login_token_error": "[Dispatch] 客户端 %s 使用 token 登录失败", "login_token_error": "[Dispatch] 客户端 %s 使用 token 登录失败",
"login_token_success": "[Dispatch] 客户端 %s 已通过 token 登录,UID 为 %s", "login_token_success": "[Dispatch] 客户端 %s 已通过 token 登录,UID 为 %s",
...@@ -35,7 +36,8 @@ ...@@ -35,7 +36,8 @@
"account_cache_error": "游戏账号缓存信息错误", "account_cache_error": "游戏账号缓存信息错误",
"session_key_error": "会话密钥错误", "session_key_error": "会话密钥错误",
"username_error": "未找到此用户名", "username_error": "未找到此用户名",
"username_create_error": "未找到用户名,建立连接失败" "username_create_error": "未找到用户名,建立连接失败",
"server_max_player_limit": "服务器在线人数已满"
}, },
"router_error": "[Dispatch] 无法连接路由" "router_error": "[Dispatch] 无法连接路由"
}, },
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
"account": { "account": {
"login_attempt": "[Dispatch] 客戶端 %s 正在嘗試登入", "login_attempt": "[Dispatch] 客戶端 %s 正在嘗試登入",
"login_success": "[Dispatch] 客戶端 %s 已登入,UID為 %s", "login_success": "[Dispatch] 客戶端 %s 已登入,UID為 %s",
"login_max_player_limit": "[Dispatch] 客戶端 %s 登入失敗:在綫人數已滿",
"login_token_attempt": "[Dispatch] 客戶端 %s 正在嘗試用憑證登入", "login_token_attempt": "[Dispatch] 客戶端 %s 正在嘗試用憑證登入",
"login_token_error": "[Dispatch] 客戶端 %s 使用憑證登入失敗", "login_token_error": "[Dispatch] 客戶端 %s 使用憑證登入失敗",
"login_token_success": "[Dispatch] 客戶端 %s 已透過憑證登入,UID為 %s", "login_token_success": "[Dispatch] 客戶端 %s 已透過憑證登入,UID為 %s",
...@@ -35,7 +36,8 @@ ...@@ -35,7 +36,8 @@
"account_cache_error": "遊戲帳號緩存資訊錯誤", "account_cache_error": "遊戲帳號緩存資訊錯誤",
"session_key_error": "對話密鑰不符。", "session_key_error": "對話密鑰不符。",
"username_error": "未找到此用戶名。", "username_error": "未找到此用戶名。",
"username_create_error": "未找到用戶名,建立失敗。" "username_create_error": "未找到用戶名,建立失敗。",
"server_max_player_limit": "服務器在綫人數已滿"
} }
}, },
"status": { "status": {
......
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