239 lines
7.9 KiB
Java
239 lines
7.9 KiB
Java
package uulm.teamname.marvelous.server;
|
|
|
|
import com.beust.jcommander.JCommander;
|
|
import com.beust.jcommander.ParameterException;
|
|
import org.tinylog.Logger;
|
|
import org.tinylog.configuration.Configuration;
|
|
import uulm.teamname.marvelous.gamelibrary.config.CharacterConfig;
|
|
import uulm.teamname.marvelous.gamelibrary.config.FieldType;
|
|
import uulm.teamname.marvelous.gamelibrary.config.PartyConfig;
|
|
import uulm.teamname.marvelous.gamelibrary.config.ScenarioConfig;
|
|
import uulm.teamname.marvelous.gamelibrary.json.JSON;
|
|
import uulm.teamname.marvelous.gamelibrary.json.ValidationUtility;
|
|
import uulm.teamname.marvelous.server.args.ServerArgs;
|
|
import uulm.teamname.marvelous.server.netconnector.MarvelousServer;
|
|
|
|
import java.io.*;
|
|
import java.net.InetSocketAddress;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* The MainClass of the Server application. The main responsibility of this class is to parse command line arguments,
|
|
* set the log level, load the configuration files, and create and manage the threads that make up the server itself.
|
|
* To run the server edit your IntelliJ run config, and enter
|
|
* {@code -c .\configs\marvelheros.character.json -m .\configs\matchconfig_1.game.json
|
|
* -s .\configs\asgard.scenario.json -v} into the arguments field.
|
|
*/
|
|
public class Server {
|
|
private static PartyConfig partyConfig;
|
|
private static ScenarioConfig scenarioConfig;
|
|
private static CharacterConfig characterConfig;
|
|
|
|
private static Integer maxLobbies;
|
|
|
|
public static void main(String[] args) {
|
|
ServerArgs serverArgs = new ServerArgs();
|
|
JCommander jc = JCommander.newBuilder().addObject(serverArgs).build();
|
|
|
|
try {
|
|
jc.parse(args);
|
|
} catch (ParameterException e) {
|
|
Logger.error("Invalid parameters: {}", e.getMessage());
|
|
System.exit(1);
|
|
return;
|
|
}
|
|
|
|
if(serverArgs.isHelp()) {
|
|
jc.usage();
|
|
System.exit(0);
|
|
return;
|
|
}
|
|
|
|
maxLobbies = serverArgs.getMaxLobbies();
|
|
|
|
if (serverArgs.isVerbose() || serverArgs.isCheckConfig()) {
|
|
// If checkConfig, the LogLevel is also set to max, because more information
|
|
// is exactly what checking the requirements means
|
|
setLogLevel(5);
|
|
} else {
|
|
setLogLevel(serverArgs.getLogLevel());
|
|
}
|
|
|
|
ScenarioConfig scenarioConfig = readScenarioConfig(serverArgs.getScenarioConfigFile());
|
|
CharacterConfig characterConfig = readCharacterConfig(serverArgs.getCharacterConfigFile());
|
|
PartyConfig partyConfig = readPartyConfig(serverArgs.getMatchConfigFile());
|
|
|
|
// If only configurations should be checked, the server exits here
|
|
if (serverArgs.isCheckConfig()) {
|
|
Logger.info("Exiting as configuration file check is done");
|
|
System.exit(0);
|
|
return;
|
|
}
|
|
|
|
Logger.info("populating static Server variables with config objects");
|
|
Server.scenarioConfig = scenarioConfig;
|
|
Server.characterConfig = characterConfig;
|
|
Server.partyConfig = partyConfig;
|
|
|
|
InetSocketAddress address = new InetSocketAddress(serverArgs.getPort());
|
|
Logger.trace("Inet address {} created", address);
|
|
|
|
Logger.trace("Instantiating MarvelousServer...");
|
|
MarvelousServer netConnector = new MarvelousServer(address);
|
|
|
|
Logger.trace("Starting MarvelousServer...");
|
|
netConnector.start();
|
|
|
|
Logger.trace("End of Main reached. Exiting main thread.");
|
|
}
|
|
|
|
/** Function that sets the log level for {@link Logger Tinylog}.
|
|
* It has to be executed <b>BEFORE ANY LOGGING OPERATIONS</b> .
|
|
*/
|
|
private static void setLogLevel(int logLevel) {
|
|
Map<String, String> map = new HashMap<>();
|
|
|
|
Configuration.replace(map);
|
|
|
|
String logLevelDescriptor = switch (logLevel) {
|
|
case 0 -> "off";
|
|
case 1 -> "error";
|
|
case 2 -> "warn";
|
|
case 3 -> "info";
|
|
case 4 -> "debug";
|
|
case 5 -> "trace";
|
|
default -> "info";
|
|
};
|
|
|
|
// Add log writer 1, a console writer (which logs to the console)
|
|
map.put("writer1", "console");
|
|
map.put("writer1.level", logLevelDescriptor);
|
|
map.put("writer1.format", "[{thread}] {level}: {message}");
|
|
|
|
// Add log writer 2, a file writer logging to the file server.log
|
|
map.put("writer2", "file");
|
|
map.put("writer2.level", logLevelDescriptor);
|
|
map.put("writer2.file", "./logs/server.log");
|
|
|
|
Configuration.replace(map);
|
|
|
|
Logger.info("Log level set to '{}'", logLevelDescriptor);
|
|
}
|
|
|
|
|
|
private static ScenarioConfig readScenarioConfig(File source) {
|
|
|
|
if (!source.exists()) {
|
|
Logger.error("Scenario Configuration file not found. Exiting...");
|
|
System.exit(1);
|
|
}
|
|
var config = JSON.parseScenarioConfig(source);
|
|
if (config.isEmpty()) {
|
|
Logger.error("Scenario Configuration couldn't be parsed. Exiting...");
|
|
System.exit(1);
|
|
}
|
|
|
|
Logger.trace("Validating configuration file...");
|
|
|
|
var violations = ValidationUtility.validate(config.get());
|
|
|
|
if (violations.isPresent()) {
|
|
Logger.error("Scenario Configuration vas invalid: {}", violations.get());
|
|
System.exit(1);
|
|
}
|
|
|
|
int grassFields = 0;
|
|
|
|
for (FieldType[] row: config.get().scenario) {
|
|
for (FieldType type: row) {
|
|
if (type == FieldType.GRASS) grassFields++;
|
|
}
|
|
if (grassFields > 18) break;
|
|
}
|
|
|
|
if (grassFields <= 18) {
|
|
Logger.error(
|
|
"Scenario Configuration vas invalid: Only {} grass fields found, which is less than 18"
|
|
, grassFields);
|
|
System.exit(1);
|
|
}
|
|
|
|
Logger.info("Scenario Config file loaded");
|
|
|
|
return config.get();
|
|
}
|
|
|
|
|
|
private static CharacterConfig readCharacterConfig(File source) {
|
|
|
|
if (!source.exists()) {
|
|
Logger.error("Character Configuration file not found. Exiting...");
|
|
System.exit(1);
|
|
}
|
|
var config = JSON.parseCharacterConfig(source);
|
|
if (config.isEmpty()) {
|
|
Logger.error("Character Configuration couldn't be parsed. Exiting...");
|
|
System.exit(1);
|
|
}
|
|
|
|
var violations = ValidationUtility.validate(config.get());
|
|
|
|
if (violations.isPresent()) {
|
|
Logger.error("Scenario Configuration vas invalid: {}", violations.get());
|
|
System.exit(1);
|
|
}
|
|
|
|
Logger.info("Character Config file loaded");
|
|
|
|
return config.get();
|
|
}
|
|
|
|
|
|
private static PartyConfig readPartyConfig(File source) {
|
|
|
|
if (!source.exists()) {
|
|
Logger.error("Party Configuration file not found. Exiting...");
|
|
System.exit(1);
|
|
}
|
|
var config = JSON.parsePartyConfig(source);
|
|
if (config.isEmpty()) {
|
|
Logger.error("Party Configuration couldn't be parsed. Exiting...");
|
|
System.exit(1);
|
|
}
|
|
|
|
|
|
var violations = ValidationUtility.validate(config.get());
|
|
|
|
if (violations.isPresent()) {
|
|
Logger.error("Party Configuration vas invalid: {}", violations.get());
|
|
System.exit(1);
|
|
}
|
|
|
|
Logger.info("Party Config file loaded");
|
|
|
|
return config.get();
|
|
}
|
|
|
|
|
|
/** Returns the party configuration the server was initialized with */
|
|
public static PartyConfig getPartyConfig() {
|
|
return partyConfig;
|
|
}
|
|
|
|
/** Returns the scenario configuration the server was initialized with */
|
|
public static ScenarioConfig getScenarioConfig() {
|
|
return scenarioConfig;
|
|
}
|
|
|
|
/** Returns the character configuration the server was initialized with */
|
|
public static CharacterConfig getCharacterConfig() {
|
|
return characterConfig;
|
|
}
|
|
|
|
/** Returns the maximum amount of lobbies the server should create */
|
|
public static Integer getMaxLobbies() {
|
|
return maxLobbies;
|
|
}
|
|
}
|