From 98fbc4e512cb69c016cff545bedd68e10e4034f6 Mon Sep 17 00:00:00 2001 From: Nazrin Date: Sat, 29 Jul 2023 08:38:34 -0700 Subject: [PATCH] Improve Platforms (#2275) * Improve Platforms * add this. --- .../emu/grasscutter/data/ResourceLoader.java | 26 ++++++++++++ .../grasscutter/game/entity/EntityGadget.java | 40 +++++++++++++++++++ .../entity/gadget/platform/ConfigRoute.java | 11 ++++- .../emu/grasscutter/game/world/Scene.java | 7 ++++ .../emu/grasscutter/scripts/ScriptLib.java | 7 ++++ .../server/scheduler/ServerTask.java | 2 +- 6 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index 2e763d405..6d03ff8b2 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -9,6 +9,7 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.data.binout.*; import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; import emu.grasscutter.data.binout.config.*; +import emu.grasscutter.data.binout.routes.*; import emu.grasscutter.data.common.PointData; import emu.grasscutter.data.custom.*; import emu.grasscutter.data.excels.trial.TrialAvatarActivityDataData; @@ -107,6 +108,7 @@ public final class ResourceLoader { // Load default home layout loadHomeworldDefaultSaveData(); loadNpcBornData(); + loadRoutes(); loadBlossomResources(); cacheTalentLevelSets(); // Load activities. @@ -264,6 +266,30 @@ public final class ResourceLoader { } } + private static void loadRoutes() { + try { + Files.newDirectoryStream(getResourcePath("BinOutput/LevelDesign/Routes/"),"*.json") + .forEach( + path -> { + try { + val data = JsonUtils.loadToClass(path, SceneRoutes.class); + val routesArray = data.getRoutes(); + if (routesArray == null) return; + val routesMap = GameData.getSceneRouteData().getOrDefault(data.getSceneId(), new Int2ObjectOpenHashMap<>()); + for (Route route : routesArray) { + routesMap.put(route.getLocalId(), route); + } + GameData.getSceneRouteData().put(data.getSceneId(), routesMap); + } catch (IOException ignored) { + } + }); + Grasscutter.getLogger() + .debug("Loaded " + GameData.getSceneNpcBornData().size() + " SceneRouteDatas."); + } catch (IOException e) { + Grasscutter.getLogger().error("Failed to load SceneRouteData folder."); + } + } + private static void cacheTalentLevelSets() { // All known levels, keyed by proudSkillGroupId GameData.getProudSkillDataMap() diff --git a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java index b8d5a58c9..d1cf59824 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java @@ -7,6 +7,7 @@ import emu.grasscutter.data.binout.config.fields.ConfigAbilityData; import emu.grasscutter.data.excels.GadgetData; import emu.grasscutter.game.entity.gadget.*; import emu.grasscutter.game.entity.gadget.platform.BaseRoute; +import emu.grasscutter.game.entity.gadget.platform.ConfigRoute; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.*; import emu.grasscutter.game.world.*; @@ -246,6 +247,37 @@ public class EntityGadget extends EntityBaseGadget { if (routeConfig.isStarted()) { return true; } + + if(routeConfig instanceof ConfigRoute configRoute) { + var route = this.getScene().getSceneRouteById(configRoute.getRouteId()); + if(route != null) { + var points = route.getPoints(); + val currIndex = configRoute.getStartIndex(); + + Position prevpos; + if(currIndex == 0) { + prevpos = getPosition(); + this.getScene().getScriptManager().callEvent(new ScriptArgs(this.getGroupId(), EventType.EVENT_PLATFORM_REACH_POINT, this.getConfigId(), configRoute.getRouteId()).setParam3(0).setEventSource(this.getConfigId())); + }else { + prevpos = points[currIndex].getPos(); + } + + double time = 0; + for(var i = currIndex; i < points.length;++i) { + time += points[i].getPos().computeDistance(prevpos) / points[i].getTargetVelocity(); + prevpos = points[i].getPos(); + val I = i; + configRoute.getScheduledIndexes().add(this.getScene().getScheduler().scheduleDelayedTask(() -> { + if(points[I].isHasReachEvent() && I > currIndex) { + this.getScene().getScriptManager().callEvent(new ScriptArgs(this.getGroupId(), EventType.EVENT_PLATFORM_REACH_POINT, this.getConfigId(), configRoute.getRouteId()).setParam3(I).setEventSource(this.getConfigId())); + } + configRoute.setStartIndex(I); + this.position.set(points[I].getPos()); + },(int)time)); + } + } + } + getScene().broadcastPacket(new PacketSceneTimeNotify(getScene())); routeConfig.startRoute(getScene()); getScene().broadcastPacket(new PacketPlatformStartRouteNotify(this)); @@ -261,6 +293,14 @@ public class EntityGadget extends EntityBaseGadget { if (!routeConfig.isStarted()) { return true; } + + if(routeConfig instanceof ConfigRoute configRoute) { + for(var task : configRoute.getScheduledIndexes()) { + this.getScene().getScheduler().cancelTask(task); + } + configRoute.getScheduledIndexes().clear(); + } + routeConfig.stopRoute(getScene()); getScene().broadcastPacket(new PacketPlatformStopRouteNotify(this)); diff --git a/src/main/java/emu/grasscutter/game/entity/gadget/platform/ConfigRoute.java b/src/main/java/emu/grasscutter/game/entity/gadget/platform/ConfigRoute.java index 4a4f3d838..14f6730bb 100644 --- a/src/main/java/emu/grasscutter/game/entity/gadget/platform/ConfigRoute.java +++ b/src/main/java/emu/grasscutter/game/entity/gadget/platform/ConfigRoute.java @@ -6,25 +6,34 @@ import emu.grasscutter.net.proto.PlatformInfoOuterClass; import emu.grasscutter.scripts.data.SceneGadget; import lombok.Getter; import lombok.Setter; +import java.util.ArrayList; +import java.util.List; public class ConfigRoute extends BaseRoute { @Getter @Setter private int routeId; + @Getter @Setter private int startIndex; + @Getter @Setter private List scheduledIndexes; public ConfigRoute(SceneGadget gadget) { super(gadget); this.routeId = gadget.route_id; + this.startIndex = 0; + this.scheduledIndexes = new ArrayList<>(); } public ConfigRoute(Position startRot, boolean startRoute, boolean isActive, int routeId) { super(startRot, startRoute, isActive); this.routeId = routeId; + this.startIndex = 0; + this.scheduledIndexes = new ArrayList<>(); } @Override public PlatformInfoOuterClass.PlatformInfo.Builder toProto() { return super.toProto() - .setRouteId(routeId) + .setRouteId(this.routeId) + .setStartIndex(this.startIndex) .setMovingPlatformType( MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_USE_CONFIG); } diff --git a/src/main/java/emu/grasscutter/game/world/Scene.java b/src/main/java/emu/grasscutter/game/world/Scene.java index 103a6d53c..c3adb0f05 100644 --- a/src/main/java/emu/grasscutter/game/world/Scene.java +++ b/src/main/java/emu/grasscutter/game/world/Scene.java @@ -31,6 +31,7 @@ import emu.grasscutter.scripts.data.*; import emu.grasscutter.server.event.entity.EntityCreationEvent; import emu.grasscutter.server.event.player.PlayerTeleportEvent; import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.server.scheduler.ServerTaskScheduler; import emu.grasscutter.utils.objects.KahnsSort; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import java.util.*; @@ -71,6 +72,7 @@ public final class Scene { private final List afterHostInitCallbacks = new ArrayList<>(); @Getter private GameEntity sceneEntity; + @Getter private final ServerTaskScheduler scheduler; public Scene(World world, SceneData sceneData) { this.world = world; @@ -94,6 +96,7 @@ public final class Scene { this.blossomManager = new BlossomManager(this); this.unlockedForces = new HashSet<>(); this.sceneEntity = new EntityScene(this); + this.scheduler = new ServerTaskScheduler(); } public int getId() { @@ -533,6 +536,10 @@ public final class Scene { return; } + if(!isPaused) { + this.getScheduler().runTasks(); + } + if (this.getScriptManager().isInit()) { // this.checkBlocks(); this.checkGroups(); diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index ba185b86a..c881f95dc 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -1319,6 +1319,13 @@ public class ScriptLib { } configRoute.setRouteId(routeId); + configRoute.setStartIndex(0); + configRoute.setStarted(false); + for(var task : configRoute.getScheduledIndexes()) { + sceneScriptManager.get().getScene().getScheduler().cancelTask(task); + } + configRoute.getScheduledIndexes().clear(); + sceneScriptManager.get().getScene().broadcastPacket(new PacketPlatformChangeRouteNotify(entityGadget)); return 0; } diff --git a/src/main/java/emu/grasscutter/server/scheduler/ServerTask.java b/src/main/java/emu/grasscutter/server/scheduler/ServerTask.java index 44a6ed04e..2c0ed7040 100644 --- a/src/main/java/emu/grasscutter/server/scheduler/ServerTask.java +++ b/src/main/java/emu/grasscutter/server/scheduler/ServerTask.java @@ -36,7 +36,7 @@ public final class ServerTask implements Runnable { */ public boolean shouldRun() { // Increase tick count. - var ticks = this.ticks++; + ++this.ticks; if (this.delay != -1 && this.considerDelay) { // Check if the task should run. var shouldRun = ticks >= this.delay;