mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-01-08 08:12:57 +08:00
Reflections change & Start HTTP before game server
This commit is contained in:
parent
58b3570f27
commit
9295d79bc2
@ -1,10 +1,10 @@
|
||||
package emu.grasscutter;
|
||||
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.utils.objects.SparseSet;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import emu.grasscutter.utils.objects.SparseSet;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class GameConstants {
|
||||
public static String VERSION = "4.0.0";
|
||||
|
@ -1,8 +1,5 @@
|
||||
package emu.grasscutter;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.SERVER;
|
||||
import static emu.grasscutter.utils.lang.Language.translate;
|
||||
|
||||
import ch.qos.logback.classic.*;
|
||||
import emu.grasscutter.auth.*;
|
||||
import emu.grasscutter.command.*;
|
||||
@ -21,16 +18,20 @@ import emu.grasscutter.tools.Tools;
|
||||
import emu.grasscutter.utils.*;
|
||||
import emu.grasscutter.utils.lang.Language;
|
||||
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||
import java.io.*;
|
||||
import java.util.Calendar;
|
||||
import java.util.concurrent.*;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.*;
|
||||
import org.jline.reader.*;
|
||||
import org.jline.terminal.*;
|
||||
import org.reflections.Reflections;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.*;
|
||||
import java.util.Calendar;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.SERVER;
|
||||
import static emu.grasscutter.utils.lang.Language.translate;
|
||||
|
||||
public final class Grasscutter {
|
||||
public static final File configFile = new File("./config.json");
|
||||
public static final Reflections reflector = new Reflections("emu.grasscutter");
|
||||
@ -108,15 +109,6 @@ public final class Grasscutter {
|
||||
logger.info(translate("messages.status.game_version", GameConstants.VERSION));
|
||||
logger.info(translate("messages.status.version", BuildConfig.VERSION, BuildConfig.GIT_HASH));
|
||||
|
||||
if (runMode != ServerRunMode.DISPATCH_ONLY) {
|
||||
// Load all resources.
|
||||
Grasscutter.updateDayOfWeek();
|
||||
ResourceLoader.loadAll();
|
||||
|
||||
// Generate handbooks.
|
||||
Tools.createGmHandbooks(false);
|
||||
}
|
||||
|
||||
// Initialize database.
|
||||
DatabaseManager.initialize();
|
||||
|
||||
@ -150,16 +142,31 @@ public final class Grasscutter {
|
||||
httpServer.addRouter(HandbookHandler.class);
|
||||
}
|
||||
|
||||
// Check if the HTTP server should start.
|
||||
var started = config.server.http.startImmediately;
|
||||
if (started) {
|
||||
Grasscutter.getLogger().info("HTTP server is starting...");
|
||||
Grasscutter.startDispatch();
|
||||
|
||||
Grasscutter.getLogger().info("Game server is starting...");
|
||||
}
|
||||
|
||||
// Load resources.
|
||||
if (runMode != ServerRunMode.DISPATCH_ONLY) {
|
||||
// Load all resources.
|
||||
Grasscutter.updateDayOfWeek();
|
||||
ResourceLoader.loadAll();
|
||||
|
||||
// Generate handbooks.
|
||||
Tools.createGmHandbooks(false);
|
||||
}
|
||||
|
||||
// Start servers.
|
||||
if (runMode == ServerRunMode.HYBRID) {
|
||||
httpServer.start();
|
||||
if (!started) Grasscutter.startDispatch();
|
||||
gameServer.start();
|
||||
} else if (runMode == ServerRunMode.DISPATCH_ONLY) {
|
||||
httpServer.start();
|
||||
|
||||
// Start dispatch server.
|
||||
dispatchServer = new DispatchServer("0.0.0.0", 1111);
|
||||
dispatchServer.start();
|
||||
if (!started) Grasscutter.startDispatch();
|
||||
} else if (runMode == ServerRunMode.GAME_ONLY) {
|
||||
gameServer.start();
|
||||
} else {
|
||||
@ -204,6 +211,20 @@ public final class Grasscutter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for starting the:
|
||||
* - SDK server
|
||||
* - Dispatch server
|
||||
*/
|
||||
public static void startDispatch() throws Exception {
|
||||
httpServer.start(); // Start the SDK/HTTP server.
|
||||
|
||||
if (Grasscutter.getRunMode() == ServerRunMode.DISPATCH_ONLY) {
|
||||
dispatchServer = new DispatchServer("0.0.0.0", 1111); // Create the dispatch server.
|
||||
dispatchServer.start(); // Start the dispatch server.
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Methods for the language system component.
|
||||
*/
|
||||
|
@ -1,15 +1,16 @@
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.SERVER;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.event.game.ExecuteCommandEvent;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
import java.util.*;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.SERVER;
|
||||
|
||||
@SuppressWarnings({"UnusedReturnValue", "unused"})
|
||||
public final class CommandMap {
|
||||
private static final int INVALID_UID = Integer.MIN_VALUE;
|
||||
@ -53,7 +54,7 @@ public final class CommandMap {
|
||||
* @return Instance chaining.
|
||||
*/
|
||||
public CommandMap registerCommand(String label, CommandHandler command) {
|
||||
Grasscutter.getLogger().debug("Registered command: " + label);
|
||||
Grasscutter.getLogger().trace("Registered command: " + label);
|
||||
label = label.toLowerCase();
|
||||
|
||||
// Get command data.
|
||||
@ -76,7 +77,7 @@ public final class CommandMap {
|
||||
* @return Instance chaining.
|
||||
*/
|
||||
public CommandMap unregisterCommand(String label) {
|
||||
Grasscutter.getLogger().debug("Unregistered command: " + label);
|
||||
Grasscutter.getLogger().trace("Un-registered command: " + label);
|
||||
|
||||
CommandHandler handler = this.commands.get(label);
|
||||
if (handler == null) return this;
|
||||
|
@ -31,9 +31,11 @@ public class ConfigContainer {
|
||||
* on trial avatars.
|
||||
* Version 11 - 'server.fastRequire' was added for disabling the new
|
||||
* Lua script require system if performance is a concern.
|
||||
* Version 12 - 'http.startImmediately' was added to control whether the
|
||||
* HTTP server should start immediately.
|
||||
*/
|
||||
private static int version() {
|
||||
return 11;
|
||||
return 12;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,7 +45,7 @@ public class ConfigContainer {
|
||||
try { // Check if the server is using a legacy config.
|
||||
var configObject = JsonUtils.loadToClass(Grasscutter.configFile.toPath(), JsonObject.class);
|
||||
if (!configObject.has("version")) {
|
||||
Grasscutter.getLogger().info("Updating legacy ..");
|
||||
Grasscutter.getLogger().info("Updating legacy config...");
|
||||
Grasscutter.saveConfig(null);
|
||||
}
|
||||
} catch (Exception ignored) { }
|
||||
@ -142,6 +144,9 @@ public class ConfigContainer {
|
||||
/* Server options. */
|
||||
|
||||
public static class HTTP {
|
||||
/* This starts the HTTP server before the game server. */
|
||||
public boolean startImmediately = false;
|
||||
|
||||
public String bindAddress = "0.0.0.0";
|
||||
public int bindPort = 443;
|
||||
|
||||
|
@ -3,19 +3,13 @@ package emu.grasscutter.data;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.server.http.handlers.GachaHandler;
|
||||
import emu.grasscutter.tools.Tools;
|
||||
import emu.grasscutter.utils.FileUtils;
|
||||
import emu.grasscutter.utils.JsonUtils;
|
||||
import emu.grasscutter.utils.TsvUtils;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import emu.grasscutter.utils.*;
|
||||
import lombok.val;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
|
||||
public class DataLoader {
|
||||
|
||||
/**
|
||||
@ -98,7 +92,7 @@ public class DataLoader {
|
||||
public static <T> List<T> loadTableToList(String resourcePath, Class<T> classType)
|
||||
throws IOException {
|
||||
val path = FileUtils.getDataPathTsjJsonTsv(resourcePath);
|
||||
Grasscutter.getLogger().debug("Loading data table from: " + path);
|
||||
Grasscutter.getLogger().trace("Loading data table from: " + path);
|
||||
return switch (FileUtils.getFileExtension(path)) {
|
||||
case "json" -> JsonUtils.loadToList(path, classType);
|
||||
case "tsj" -> TsvUtils.loadTsjToListSetField(path, classType);
|
||||
|
@ -1,8 +1,5 @@
|
||||
package emu.grasscutter.data;
|
||||
|
||||
import static emu.grasscutter.utils.FileUtils.*;
|
||||
import static emu.grasscutter.utils.lang.Language.translate;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
@ -23,6 +20,9 @@ import emu.grasscutter.scripts.*;
|
||||
import emu.grasscutter.utils.*;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import lombok.*;
|
||||
|
||||
import javax.script.*;
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
@ -30,9 +30,9 @@ import java.util.Map.Entry;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.*;
|
||||
import javax.script.*;
|
||||
import lombok.*;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import static emu.grasscutter.utils.FileUtils.*;
|
||||
import static emu.grasscutter.utils.lang.Language.translate;
|
||||
|
||||
public final class ResourceLoader {
|
||||
|
||||
@ -41,8 +41,7 @@ public final class ResourceLoader {
|
||||
|
||||
// Get a list of all resource classes, sorted by loadPriority
|
||||
public static List<Class<?>> getResourceDefClasses() {
|
||||
Reflections reflections = new Reflections(ResourceLoader.class.getPackage().getName());
|
||||
Set<?> classes = reflections.getSubTypesOf(GameResource.class);
|
||||
Set<?> classes = Grasscutter.reflector.getSubTypesOf(GameResource.class);
|
||||
|
||||
List<Class<?>> classList = new ArrayList<>(classes.size());
|
||||
classes.forEach(
|
||||
@ -62,9 +61,8 @@ public final class ResourceLoader {
|
||||
}
|
||||
|
||||
// Get a list containing sets of all resource classes, sorted by loadPriority
|
||||
protected static List<Set<Class<?>>> getResourceDefClassesPrioritySets() {
|
||||
val reflections = new Reflections(ResourceLoader.class.getPackage().getName());
|
||||
val classes = reflections.getSubTypesOf(GameResource.class);
|
||||
private static List<Set<Class<?>>> getResourceDefClassesPrioritySets() {
|
||||
val classes = Grasscutter.reflector.getSubTypesOf(GameResource.class);
|
||||
val priorities = ResourceType.LoadPriority.getInOrder();
|
||||
Grasscutter.getLogger().debug("Priorities are " + priorities);
|
||||
val map = new LinkedHashMap<ResourceType.LoadPriority, Set<Class<?>>>(priorities.size());
|
||||
|
@ -1,22 +1,16 @@
|
||||
package emu.grasscutter.database;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.DATABASE;
|
||||
|
||||
import com.mongodb.MongoCommandException;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.MongoIterable;
|
||||
import dev.morphia.Datastore;
|
||||
import dev.morphia.Morphia;
|
||||
import com.mongodb.client.*;
|
||||
import dev.morphia.*;
|
||||
import dev.morphia.annotations.Entity;
|
||||
import dev.morphia.mapping.Mapper;
|
||||
import dev.morphia.mapping.MapperOptions;
|
||||
import dev.morphia.mapping.*;
|
||||
import dev.morphia.query.experimental.filters.Filters;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.Grasscutter.ServerRunMode;
|
||||
import emu.grasscutter.game.Account;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.DATABASE;
|
||||
|
||||
public final class DatabaseManager {
|
||||
private static Datastore gameDatastore;
|
||||
@ -48,8 +42,8 @@ public final class DatabaseManager {
|
||||
Morphia.createDatastore(gameMongoClient, DATABASE.game.collection, mapperOptions);
|
||||
|
||||
// Map classes.
|
||||
Class<?>[] entities =
|
||||
new Reflections(Grasscutter.class.getPackageName())
|
||||
var entities =
|
||||
Grasscutter.reflector
|
||||
.getTypesAnnotatedWith(Entity.class).stream()
|
||||
.filter(
|
||||
cls -> {
|
||||
|
@ -20,10 +20,10 @@ import emu.grasscutter.net.proto.AbilityScalarValueEntryOuterClass.AbilityScalar
|
||||
import emu.grasscutter.net.proto.ModifierActionOuterClass.ModifierAction;
|
||||
import emu.grasscutter.server.event.player.PlayerUseSkillEvent;
|
||||
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.*;
|
||||
import lombok.Getter;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
public final class AbilityManager extends BasePlayerManager {
|
||||
private static final HashMap<AbilityModifierAction.Type, AbilityActionHandler> actionHandlers =
|
||||
@ -54,8 +54,8 @@ public final class AbilityManager extends BasePlayerManager {
|
||||
}
|
||||
|
||||
public static void registerHandlers() {
|
||||
Reflections reflections = new Reflections("emu.grasscutter.game.ability.actions");
|
||||
var handlerClassesAction = reflections.getSubTypesOf(AbilityActionHandler.class);
|
||||
var handlerClassesAction = Grasscutter.reflector
|
||||
.getSubTypesOf(AbilityActionHandler.class);
|
||||
|
||||
for (var obj : handlerClassesAction) {
|
||||
try {
|
||||
@ -70,9 +70,8 @@ public final class AbilityManager extends BasePlayerManager {
|
||||
}
|
||||
}
|
||||
|
||||
reflections = new Reflections("emu.grasscutter.game.ability.mixins");
|
||||
var handlerClassesMixin = reflections.getSubTypesOf(AbilityMixinHandler.class);
|
||||
|
||||
var handlerClassesMixin = Grasscutter.reflector
|
||||
.getSubTypesOf(AbilityMixinHandler.class);
|
||||
for (var obj : handlerClassesMixin) {
|
||||
try {
|
||||
if (obj.isAnnotationPresent(AbilityAction.class)) {
|
||||
@ -413,11 +412,9 @@ public final class AbilityManager extends BasePlayerManager {
|
||||
|
||||
if (instancedAbilityData == null) {
|
||||
// search on entity base id
|
||||
if (entity != null) {
|
||||
if ((head.getInstancedAbilityId() - 1) < entity.getInstancedAbilities().size()) {
|
||||
instancedAbility = entity.getInstancedAbilities().get(head.getInstancedAbilityId() - 1);
|
||||
if (instancedAbility != null) instancedAbilityData = instancedAbility.getData();
|
||||
}
|
||||
if ((head.getInstancedAbilityId() - 1) < entity.getInstancedAbilities().size()) {
|
||||
instancedAbility = entity.getInstancedAbilities().get(head.getInstancedAbilityId() - 1);
|
||||
if (instancedAbility != null) instancedAbilityData = instancedAbility.getData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,6 +578,6 @@ public final class AbilityManager extends BasePlayerManager {
|
||||
|
||||
public void addAbilityToEntity(GameEntity entity, AbilityData abilityData) {
|
||||
var ability = new Ability(abilityData, entity, this.player);
|
||||
entity.getInstancedAbilities().add(ability); // This are in order
|
||||
entity.getInstancedAbilities().add(ability); // This is in order
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,12 @@ import emu.grasscutter.game.player.*;
|
||||
import emu.grasscutter.game.props.*;
|
||||
import emu.grasscutter.net.proto.ActivityInfoOuterClass;
|
||||
import emu.grasscutter.server.packet.send.PacketActivityScheduleInfoNotify;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import lombok.Getter;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Getter
|
||||
public class ActivityManager extends BasePlayerManager {
|
||||
private static final Map<Integer, ActivityConfigItem> activityConfigItemMap;
|
||||
@ -29,16 +30,14 @@ public class ActivityManager extends BasePlayerManager {
|
||||
// scan activity type handler & watcher type
|
||||
var activityHandlerTypeMap = new HashMap<ActivityType, ConstructorAccess<?>>();
|
||||
var activityWatcherTypeMap = new HashMap<WatcherTriggerType, ConstructorAccess<?>>();
|
||||
var reflections = new Reflections(ActivityManager.class.getPackage().getName());
|
||||
|
||||
reflections
|
||||
Grasscutter.reflector
|
||||
.getSubTypesOf(ActivityHandler.class)
|
||||
.forEach(
|
||||
item -> {
|
||||
var typeName = item.getAnnotation(GameActivity.class);
|
||||
activityHandlerTypeMap.put(typeName.value(), ConstructorAccess.get(item));
|
||||
});
|
||||
reflections
|
||||
Grasscutter.reflector
|
||||
.getSubTypesOf(ActivityWatcher.class)
|
||||
.forEach(
|
||||
item -> {
|
||||
|
@ -1,49 +1,41 @@
|
||||
package emu.grasscutter.game.dungeons;
|
||||
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.*;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.ScenePointEntry;
|
||||
import emu.grasscutter.data.excels.dungeon.DungeonData;
|
||||
import emu.grasscutter.data.excels.dungeon.DungeonPassConfigData;
|
||||
import emu.grasscutter.data.excels.dungeon.*;
|
||||
import emu.grasscutter.game.dungeons.handlers.DungeonBaseHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.SceneType;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.server.game.BaseGameSystem;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import emu.grasscutter.game.world.*;
|
||||
import emu.grasscutter.net.packet.*;
|
||||
import emu.grasscutter.server.game.*;
|
||||
import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.util.List;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import lombok.val;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
public class DungeonSystem extends BaseGameSystem {
|
||||
import java.util.List;
|
||||
|
||||
public final class DungeonSystem extends BaseGameSystem {
|
||||
private static final BasicDungeonSettleListener basicDungeonSettleObserver =
|
||||
new BasicDungeonSettleListener();
|
||||
private final Int2ObjectMap<DungeonBaseHandler> passCondHandlers;
|
||||
|
||||
public DungeonSystem(GameServer server) {
|
||||
super(server);
|
||||
|
||||
this.passCondHandlers = new Int2ObjectOpenHashMap<>();
|
||||
registerHandlers();
|
||||
this.registerHandlers();
|
||||
}
|
||||
|
||||
public void registerHandlers() {
|
||||
this.registerHandlers(
|
||||
this.passCondHandlers,
|
||||
"emu.grasscutter.game.dungeons.pass_condition",
|
||||
DungeonBaseHandler.class);
|
||||
}
|
||||
|
||||
public <T> void registerHandlers(Int2ObjectMap<T> map, String packageName, Class<T> clazz) {
|
||||
Reflections reflections = new Reflections(packageName);
|
||||
var handlerClasses = reflections.getSubTypesOf(clazz);
|
||||
|
||||
public <T> void registerHandlers(Int2ObjectMap<T> map, Class<T> clazz) {
|
||||
var handlerClasses = Grasscutter.reflector.getSubTypesOf(clazz);
|
||||
for (var obj : handlerClasses) {
|
||||
this.registerHandler(map, obj);
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package emu.grasscutter.game.gacha;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||
|
||||
import com.sun.nio.file.SensitivityWatchEventModifier;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.*;
|
||||
@ -23,10 +21,13 @@ import emu.grasscutter.server.game.*;
|
||||
import emu.grasscutter.server.packet.send.PacketDoGachaRsp;
|
||||
import emu.grasscutter.utils.*;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||
|
||||
public class GachaSystem extends BaseGameSystem {
|
||||
private static final int starglitterId = 221;
|
||||
@ -58,9 +59,9 @@ public class GachaSystem extends BaseGameSystem {
|
||||
int autoScheduleId = 1000;
|
||||
int autoSortId = 9000;
|
||||
try {
|
||||
List<GachaBanner> banners = DataLoader.loadTableToList("Banners", GachaBanner.class);
|
||||
if (banners.size() > 0) {
|
||||
for (GachaBanner banner : banners) {
|
||||
var banners = DataLoader.loadTableToList("Banners", GachaBanner.class);
|
||||
if (!banners.isEmpty()) {
|
||||
for (var banner : banners) {
|
||||
banner.onLoad();
|
||||
if (banner.isDeprecated()) {
|
||||
Grasscutter.getLogger()
|
||||
|
@ -2,21 +2,15 @@ package emu.grasscutter.game.quest;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.data.excels.quest.QuestData.QuestAcceptCondition;
|
||||
import emu.grasscutter.data.excels.quest.QuestData.QuestContentCondition;
|
||||
import emu.grasscutter.data.excels.quest.QuestData.QuestExecParam;
|
||||
import emu.grasscutter.data.excels.quest.QuestData.*;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.quest.conditions.BaseCondition;
|
||||
import emu.grasscutter.game.quest.content.BaseContent;
|
||||
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
|
||||
import emu.grasscutter.server.game.BaseGameSystem;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.reflections.Reflections;
|
||||
import emu.grasscutter.server.game.*;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class QuestSystem extends BaseGameSystem {
|
||||
public final class QuestSystem extends BaseGameSystem {
|
||||
private final Int2ObjectMap<BaseCondition> condHandlers;
|
||||
private final Int2ObjectMap<BaseContent> contHandlers;
|
||||
private final Int2ObjectMap<QuestExecHandler> execHandlers;
|
||||
@ -33,17 +27,15 @@ public class QuestSystem extends BaseGameSystem {
|
||||
|
||||
public void registerHandlers() {
|
||||
this.registerHandlers(
|
||||
this.condHandlers, "emu.grasscutter.game.quest.conditions", BaseCondition.class);
|
||||
this.condHandlers, BaseCondition.class);
|
||||
this.registerHandlers(
|
||||
this.contHandlers, "emu.grasscutter.game.quest.content", BaseContent.class);
|
||||
this.contHandlers, BaseContent.class);
|
||||
this.registerHandlers(
|
||||
this.execHandlers, "emu.grasscutter.game.quest.exec", QuestExecHandler.class);
|
||||
this.execHandlers, QuestExecHandler.class);
|
||||
}
|
||||
|
||||
public <T> void registerHandlers(Int2ObjectMap<T> map, String packageName, Class<T> clazz) {
|
||||
Reflections reflections = new Reflections(packageName);
|
||||
var handlerClasses = reflections.getSubTypesOf(clazz);
|
||||
|
||||
public <T> void registerHandlers(Int2ObjectMap<T> map, Class<T> clazz) {
|
||||
var handlerClasses = Grasscutter.reflector.getSubTypesOf(clazz);
|
||||
for (var obj : handlerClasses) {
|
||||
this.registerHandler(map, obj);
|
||||
}
|
||||
@ -51,8 +43,7 @@ public class QuestSystem extends BaseGameSystem {
|
||||
|
||||
public <T> void registerHandler(Int2ObjectMap<T> map, Class<? extends T> handlerClass) {
|
||||
try {
|
||||
int value = 0;
|
||||
if (handlerClass.isAnnotationPresent(QuestValueExec.class)) {
|
||||
int value; if (handlerClass.isAnnotationPresent(QuestValueExec.class)) {
|
||||
QuestValueExec opcode = handlerClass.getAnnotation(QuestValueExec.class);
|
||||
value = opcode.value().getValue();
|
||||
} else if (handlerClass.isAnnotationPresent(QuestValueContent.class)) {
|
||||
@ -71,7 +62,7 @@ public class QuestSystem extends BaseGameSystem {
|
||||
|
||||
map.put(value, handlerClass.getDeclaredConstructor().newInstance());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Grasscutter.getLogger().warn("Unable to register handler {}.", handlerClass.getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,11 +4,8 @@ import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.excels.TalkConfigData;
|
||||
import emu.grasscutter.data.excels.TalkConfigData.TalkExecParam;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.game.BaseGameSystem;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.reflections.Reflections;
|
||||
import emu.grasscutter.server.game.*;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
|
||||
public final class TalkSystem extends BaseGameSystem {
|
||||
private final Int2ObjectMap<TalkExecHandler> execHandlers = new Int2ObjectOpenHashMap<>();
|
||||
@ -16,21 +13,17 @@ public final class TalkSystem extends BaseGameSystem {
|
||||
public TalkSystem(GameServer server) {
|
||||
super(server);
|
||||
|
||||
this.registerHandlers(
|
||||
this.execHandlers, "emu.grasscutter.game.talk.exec", TalkExecHandler.class);
|
||||
this.registerHandlers(this.execHandlers, TalkExecHandler.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all handlers with the required conditions.
|
||||
*
|
||||
* @param map The map to save handlers to.
|
||||
* @param packageName The full package domain.
|
||||
* @param clazz The class which handlers should derive from.
|
||||
*/
|
||||
public <T> void registerHandlers(Int2ObjectMap<T> map, String packageName, Class<T> clazz) {
|
||||
var reflections = new Reflections(packageName);
|
||||
var handlerClasses = reflections.getSubTypesOf(clazz);
|
||||
|
||||
public <T> void registerHandlers(Int2ObjectMap<T> map, Class<T> clazz) {
|
||||
var handlerClasses = Grasscutter.reflector.getSubTypesOf(clazz);
|
||||
for (var obj : handlerClasses) {
|
||||
this.registerTalkHandler(map, obj);
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package emu.grasscutter.plugin;
|
||||
|
||||
import static emu.grasscutter.utils.lang.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.*;
|
||||
import emu.grasscutter.server.event.*;
|
||||
import emu.grasscutter.utils.*;
|
||||
import lombok.*;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.jar.*;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.*;
|
||||
|
||||
import static emu.grasscutter.utils.lang.Language.translate;
|
||||
|
||||
/** Manages the server's plugins and the event system. */
|
||||
public final class PluginManager {
|
||||
@ -20,7 +21,7 @@ public final class PluginManager {
|
||||
* A 'breaking change' is something which changes the existing logic of the API.
|
||||
*/
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static int API_VERSION = 2;
|
||||
public static int API_VERSION = 3;
|
||||
|
||||
/* All loaded plugins. */
|
||||
private final Map<String, Plugin> plugins = new LinkedHashMap<>();
|
||||
|
@ -1,18 +1,15 @@
|
||||
package emu.grasscutter.server.game;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.GAME_INFO;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.Grasscutter.ServerDebugMode;
|
||||
import emu.grasscutter.net.packet.*;
|
||||
import emu.grasscutter.server.event.game.ReceivePacketEvent;
|
||||
import emu.grasscutter.server.game.GameSession.SessionState;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import java.util.Set;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class GameServerPacketHandler {
|
||||
import static emu.grasscutter.config.Configuration.GAME_INFO;
|
||||
|
||||
public final class GameServerPacketHandler {
|
||||
private final Int2ObjectMap<PacketHandler> handlers;
|
||||
|
||||
public GameServerPacketHandler(Class<? extends PacketHandler> handlerClass) {
|
||||
@ -23,26 +20,22 @@ public class GameServerPacketHandler {
|
||||
|
||||
public void registerPacketHandler(Class<? extends PacketHandler> handlerClass) {
|
||||
try {
|
||||
Opcodes opcode = handlerClass.getAnnotation(Opcodes.class);
|
||||
|
||||
var opcode = handlerClass.getAnnotation(Opcodes.class);
|
||||
if (opcode == null || opcode.disabled() || opcode.value() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
PacketHandler packetHandler = handlerClass.getDeclaredConstructor().newInstance();
|
||||
|
||||
var packetHandler = handlerClass.getDeclaredConstructor().newInstance();
|
||||
this.handlers.put(opcode.value(), packetHandler);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Grasscutter.getLogger().warn("Unable to register handler {}.", handlerClass.getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerHandlers(Class<? extends PacketHandler> handlerClass) {
|
||||
Reflections reflections = new Reflections("emu.grasscutter.server.packet");
|
||||
Set<?> handlerClasses = reflections.getSubTypesOf(handlerClass);
|
||||
|
||||
for (Object obj : handlerClasses) {
|
||||
this.registerPacketHandler((Class<? extends PacketHandler>) obj);
|
||||
var handlerClasses = Grasscutter.reflector.getSubTypesOf(handlerClass);
|
||||
for (var obj : handlerClasses) {
|
||||
this.registerPacketHandler(obj);
|
||||
}
|
||||
|
||||
// Debug
|
||||
|
@ -1,6 +1,5 @@
|
||||
package emu.grasscutter.server.http.documentation;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.server.http.Router;
|
||||
import io.javalin.Javalin;
|
||||
|
||||
@ -11,13 +10,7 @@ public final class DocumentationServerHandler implements Router {
|
||||
final var root = new RootRequestHandler();
|
||||
final var gachaMapping = new GachaMappingRequestHandler();
|
||||
|
||||
// TODO: Removal
|
||||
// TODO: Forward /documentation requests to https://grasscutter.io/wiki
|
||||
if (Grasscutter.getRunMode() != Grasscutter.ServerRunMode.DISPATCH_ONLY) {
|
||||
final var handbook = new HandbookRequestHandler();
|
||||
javalin.get("/documentation/handbook", handbook::handle);
|
||||
}
|
||||
|
||||
javalin.get("/documentation/handbook", ctx -> ctx.redirect("https://grasscutter.io/handbook"));
|
||||
javalin.get("/documentation/gachamapping", gachaMapping::handle);
|
||||
javalin.get("/documentation", root::handle);
|
||||
}
|
||||
|
@ -1,204 +0,0 @@
|
||||
package emu.grasscutter.server.http.documentation;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.CommandMap;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.ItemData;
|
||||
import emu.grasscutter.data.excels.avatar.AvatarData;
|
||||
import emu.grasscutter.data.excels.monster.MonsterData;
|
||||
import emu.grasscutter.data.excels.scene.SceneData;
|
||||
import emu.grasscutter.utils.FileUtils;
|
||||
import emu.grasscutter.utils.lang.Language;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
final class HandbookRequestHandler implements DocumentationHandler {
|
||||
private List<String> handbookHtmls;
|
||||
|
||||
public HandbookRequestHandler() {
|
||||
var templatePath = FileUtils.getDataPath("documentation/handbook.html");
|
||||
try {
|
||||
this.handbookHtmls = generateHandbookHtmls(Files.readString(templatePath));
|
||||
} catch (IOException ignored) {
|
||||
Grasscutter.getLogger().warn("File does not exist: " + templatePath);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Context ctx) {
|
||||
int langIdx = 0;
|
||||
String acceptLanguage = ctx.header("Accept-Language");
|
||||
if (acceptLanguage != null) {
|
||||
Pattern localePattern = Pattern.compile("[a-z]+-[A-Z]+");
|
||||
Matcher matcher = localePattern.matcher(acceptLanguage);
|
||||
if (matcher.find()) {
|
||||
String lang = matcher.group(0);
|
||||
langIdx = Language.TextStrings.MAP_GC_LANGUAGES.getOrDefault(lang, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.handbookHtmls == null) {
|
||||
ctx.status(500);
|
||||
} else {
|
||||
if (langIdx <= this.handbookHtmls.size() - 1) {
|
||||
ctx.contentType(ContentType.TEXT_HTML);
|
||||
ctx.result(this.handbookHtmls.get(langIdx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> generateHandbookHtmls(String template) {
|
||||
final int NUM_LANGUAGES = Language.TextStrings.NUM_LANGUAGES;
|
||||
final List<String> output = new ArrayList<>(NUM_LANGUAGES);
|
||||
final List<Language> languages = Language.TextStrings.getLanguages();
|
||||
final List<StringBuilder> sbs = new ArrayList<>(NUM_LANGUAGES);
|
||||
for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) sbs.add(new StringBuilder());
|
||||
|
||||
// Commands table
|
||||
CommandMap.getInstance()
|
||||
.getHandlersAsList()
|
||||
.forEach(
|
||||
cmd -> {
|
||||
String label = cmd.getLabel();
|
||||
String descKey = cmd.getDescriptionKey();
|
||||
for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++)
|
||||
sbs.get(langIdx)
|
||||
.append(
|
||||
"<tr><td><code>"
|
||||
+ label
|
||||
+ "</code></td><td>"
|
||||
+ languages.get(langIdx).get(descKey)
|
||||
+ "</td></tr>\n");
|
||||
});
|
||||
sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n
|
||||
final List<String> cmdsTable = sbs.stream().map(StringBuilder::toString).toList();
|
||||
|
||||
// Avatars table
|
||||
final Int2ObjectMap<AvatarData> avatarMap = GameData.getAvatarDataMap();
|
||||
sbs.forEach(sb -> sb.setLength(0));
|
||||
avatarMap
|
||||
.keySet()
|
||||
.intStream()
|
||||
.sorted()
|
||||
.mapToObj(avatarMap::get)
|
||||
.forEach(
|
||||
data -> {
|
||||
int id = data.getId();
|
||||
Language.TextStrings name = Language.getTextMapKey(data.getNameTextMapHash());
|
||||
for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++)
|
||||
sbs.get(langIdx)
|
||||
.append(
|
||||
"<tr><td><code>"
|
||||
+ id
|
||||
+ "</code></td><td>"
|
||||
+ name.get(langIdx)
|
||||
+ "</td></tr>\n");
|
||||
});
|
||||
sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n
|
||||
final List<String> avatarsTable = sbs.stream().map(StringBuilder::toString).toList();
|
||||
|
||||
// Items table
|
||||
final Int2ObjectMap<ItemData> itemMap = GameData.getItemDataMap();
|
||||
sbs.forEach(sb -> sb.setLength(0));
|
||||
itemMap
|
||||
.keySet()
|
||||
.intStream()
|
||||
.sorted()
|
||||
.mapToObj(itemMap::get)
|
||||
.forEach(
|
||||
data -> {
|
||||
int id = data.getId();
|
||||
Language.TextStrings name = Language.getTextMapKey(data.getNameTextMapHash());
|
||||
for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++)
|
||||
sbs.get(langIdx)
|
||||
.append(
|
||||
"<tr><td><code>"
|
||||
+ id
|
||||
+ "</code></td><td>"
|
||||
+ name.get(langIdx)
|
||||
+ "</td></tr>\n");
|
||||
});
|
||||
sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n
|
||||
final List<String> itemsTable = sbs.stream().map(StringBuilder::toString).toList();
|
||||
|
||||
// Scenes table
|
||||
final Int2ObjectMap<SceneData> sceneMap = GameData.getSceneDataMap();
|
||||
sceneMap
|
||||
.keySet()
|
||||
.intStream()
|
||||
.sorted()
|
||||
.mapToObj(sceneMap::get)
|
||||
.forEach(
|
||||
data -> {
|
||||
int id = data.getId();
|
||||
for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++)
|
||||
sbs.get(langIdx)
|
||||
.append(
|
||||
"<tr><td><code>"
|
||||
+ id
|
||||
+ "</code></td><td>"
|
||||
+ data.getScriptData()
|
||||
+ "</td></tr>\n");
|
||||
});
|
||||
sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n
|
||||
final List<String> scenesTable = sbs.stream().map(StringBuilder::toString).toList();
|
||||
|
||||
// Monsters table
|
||||
final Int2ObjectMap<MonsterData> monsterMap = GameData.getMonsterDataMap();
|
||||
monsterMap
|
||||
.keySet()
|
||||
.intStream()
|
||||
.sorted()
|
||||
.mapToObj(monsterMap::get)
|
||||
.forEach(
|
||||
data -> {
|
||||
int id = data.getId();
|
||||
Language.TextStrings name = Language.getTextMapKey(data.getNameTextMapHash());
|
||||
for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++)
|
||||
sbs.get(langIdx)
|
||||
.append(
|
||||
"<tr><td><code>"
|
||||
+ id
|
||||
+ "</code></td><td>"
|
||||
+ name.get(langIdx)
|
||||
+ "</td></tr>\n");
|
||||
});
|
||||
sbs.forEach(sb -> sb.setLength(sb.length() - 1)); // Remove trailing \n
|
||||
final List<String> monstersTable = sbs.stream().map(StringBuilder::toString).toList();
|
||||
|
||||
// Add translated title etc. to the page.
|
||||
for (int langIdx = 0; langIdx < NUM_LANGUAGES; langIdx++) {
|
||||
Language lang = languages.get(langIdx);
|
||||
output.add(
|
||||
template
|
||||
.replace("{{TITLE}}", lang.get("documentation.handbook.title"))
|
||||
.replace("{{TITLE_COMMANDS}}", lang.get("documentation.handbook.title_commands"))
|
||||
.replace("{{TITLE_AVATARS}}", lang.get("documentation.handbook.title_avatars"))
|
||||
.replace("{{TITLE_ITEMS}}", lang.get("documentation.handbook.title_items"))
|
||||
.replace("{{TITLE_SCENES}}", lang.get("documentation.handbook.title_scenes"))
|
||||
.replace("{{TITLE_MONSTERS}}", lang.get("documentation.handbook.title_monsters"))
|
||||
.replace("{{HEADER_ID}}", lang.get("documentation.handbook.header_id"))
|
||||
.replace("{{HEADER_COMMAND}}", lang.get("documentation.handbook.header_command"))
|
||||
.replace(
|
||||
"{{HEADER_DESCRIPTION}}", lang.get("documentation.handbook.header_description"))
|
||||
.replace("{{HEADER_AVATAR}}", lang.get("documentation.handbook.header_avatar"))
|
||||
.replace("{{HEADER_ITEM}}", lang.get("documentation.handbook.header_item"))
|
||||
.replace("{{HEADER_SCENE}}", lang.get("documentation.handbook.header_scene"))
|
||||
.replace("{{HEADER_MONSTER}}", lang.get("documentation.handbook.header_monster"))
|
||||
// Commands table
|
||||
.replace("{{COMMANDS_TABLE}}", cmdsTable.get(langIdx))
|
||||
.replace("{{AVATARS_TABLE}}", avatarsTable.get(langIdx))
|
||||
.replace("{{ITEMS_TABLE}}", itemsTable.get(langIdx))
|
||||
.replace("{{SCENES_TABLE}}", scenesTable.get(langIdx))
|
||||
.replace("{{MONSTERS_TABLE}}", monstersTable.get(langIdx)));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user