From 119caabb9ad43baac77e584fde3accac4867759b Mon Sep 17 00:00:00 2001 From: Zin <62830952+Zintixx@users.noreply.github.com> Date: Tue, 11 Mar 2025 09:33:20 -0700 Subject: [PATCH 1/3] Field Player Spawn Point Trigger --- .../Storage/Metadata/MapEntityStorage.cs | 2 - Maple2.File.Ingest/Mapper/MapEntityMapper.cs | 5 -- Maple2.Model/Metadata/MapEntity/MapEntity.cs | 1 - .../Metadata/MapEntity/Ms2RegionBoxSpawn.cs | 11 ----- Maple2.Model/Metadata/MapEntityMetadata.cs | 1 - Maple2.Server.Game/Commands/FieldCommand.cs | 46 ++++++++++++++++++- .../Field/FieldManager/FieldManager.State.cs | 7 +-- .../Field/FieldManager/FieldManager.cs | 8 ++++ .../Field/Entity/FieldPlayerSpawnPoint.cs | 14 ++++++ .../Trigger/TriggerContext.Field.cs | 3 +- .../Trigger/TriggerContext.Player.cs | 8 +++- 11 files changed, 80 insertions(+), 26 deletions(-) delete mode 100644 Maple2.Model/Metadata/MapEntity/Ms2RegionBoxSpawn.cs create mode 100644 Maple2.Server.Game/Model/Field/Entity/FieldPlayerSpawnPoint.cs diff --git a/Maple2.Database/Storage/Metadata/MapEntityStorage.cs b/Maple2.Database/Storage/Metadata/MapEntityStorage.cs index 83c74df96..589774679 100644 --- a/Maple2.Database/Storage/Metadata/MapEntityStorage.cs +++ b/Maple2.Database/Storage/Metadata/MapEntityStorage.cs @@ -38,7 +38,6 @@ public class MapEntityStorage(MetadataContext context) : MetadataStorage(); var npcSpawns = new List(); var regionSpawns = new Dictionary(); - var boxRegionSpawns = new Dictionary(); var regionSkills = new List(); var eventNpcSpawns = new Dictionary(); var eventItemSpawns = new Dictionary(); @@ -131,7 +130,6 @@ public class MapEntityStorage(MetadataContext context) : MetadataStorage ParseMap(string xblock, IEnumerable e continue; } continue; - case IMS2RegionBoxSpawn boxSpawn: - yield return new MapEntity(xblock, new Guid(entity.EntityId), entity.EntityName) { - Block = new Ms2RegionBoxSpawn(boxSpawn.SpawnPointID, (int) boxSpawn.SpawnTypeID, boxSpawn.Scale, boxSpawn.Position, boxSpawn.Rotation) - }; - continue; case IMS2RegionSpawnBase spawn: yield return new MapEntity(xblock, new Guid(entity.EntityId), entity.EntityName) { Block = new Ms2RegionSpawn(spawn.SpawnPointID, spawn.UseRotAsSpawnDir, spawn.Position, spawn.Rotation) diff --git a/Maple2.Model/Metadata/MapEntity/MapEntity.cs b/Maple2.Model/Metadata/MapEntity/MapEntity.cs index c0743d6e6..19a881ea8 100644 --- a/Maple2.Model/Metadata/MapEntity/MapEntity.cs +++ b/Maple2.Model/Metadata/MapEntity/MapEntity.cs @@ -57,5 +57,4 @@ public MapEntity(string xBlock, Guid guid, string name) { [JsonDerivedType(typeof(TriggerModel), 1436346081)] [JsonDerivedType(typeof(Ms2Bounding), 1539875768)] [JsonDerivedType(typeof(MS2PatrolData), 250722994)] -[JsonDerivedType(typeof(Ms2RegionBoxSpawn), 465193598)] public abstract record MapBlock; diff --git a/Maple2.Model/Metadata/MapEntity/Ms2RegionBoxSpawn.cs b/Maple2.Model/Metadata/MapEntity/Ms2RegionBoxSpawn.cs deleted file mode 100644 index 55d3c81cd..000000000 --- a/Maple2.Model/Metadata/MapEntity/Ms2RegionBoxSpawn.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Numerics; - -namespace Maple2.Model.Metadata; - -public record Ms2RegionBoxSpawn( - int Id, - int SpawnTypeId, - float Scale, - Vector3 Position, - Vector3 Rotation -) : MapBlock; diff --git a/Maple2.Model/Metadata/MapEntityMetadata.cs b/Maple2.Model/Metadata/MapEntityMetadata.cs index 5687df9e2..b32bf40d2 100644 --- a/Maple2.Model/Metadata/MapEntityMetadata.cs +++ b/Maple2.Model/Metadata/MapEntityMetadata.cs @@ -16,7 +16,6 @@ public class MapEntityMetadata { public required IReadOnlyDictionary PlayerSpawns { get; init; } public required IReadOnlyList NpcSpawns { get; init; } public required IReadOnlyDictionary RegionSpawns { get; init; } - public required IReadOnlyDictionary BoxRegionSpawns { get; init; } public required IReadOnlyList RegionSkills { get; init; } public required IReadOnlyDictionary EventNpcSpawns { get; init; } public required IReadOnlyDictionary EventItemSpawns { get; init; } diff --git a/Maple2.Server.Game/Commands/FieldCommand.cs b/Maple2.Server.Game/Commands/FieldCommand.cs index 7edf19b21..a38671d6d 100644 --- a/Maple2.Server.Game/Commands/FieldCommand.cs +++ b/Maple2.Server.Game/Commands/FieldCommand.cs @@ -2,6 +2,7 @@ using System.CommandLine.Invocation; using System.CommandLine.IO; using Maple2.Database.Storage; +using Maple2.Model.Metadata; using Maple2.Server.Game.Model; using Maple2.Server.Game.Session; @@ -13,12 +14,16 @@ public class FieldCommand : Command { private readonly GameSession session; private readonly MapMetadataStorage mapStorage; + private readonly MapEntityStorage mapEntities; - public FieldCommand(GameSession session, MapMetadataStorage mapStorage) : base(NAME, DESCRIPTION) { + public FieldCommand(GameSession session, MapMetadataStorage mapStorage, MapEntityStorage mapEntities) : base(NAME, DESCRIPTION) { this.session = session; this.mapStorage = mapStorage; + this.mapEntities = mapEntities; AddCommand(new EntityInfoCommand(session)); + AddCommand(new SpawnPointsCommand(session, mapStorage, mapEntities)); + this.SetHandler(Handle); } @@ -64,4 +69,43 @@ private void Handle(InvocationContext ctx, int objectId) { } } } + + private class SpawnPointsCommand : Command { + private readonly GameSession session; + private readonly MapMetadataStorage mapStorage; + private readonly MapEntityStorage mapEntities; + + public SpawnPointsCommand(GameSession session, MapMetadataStorage mapStorage, MapEntityStorage mapEntities) : base("spawnpoints", "Prints all spawn points in the map.") { + this.session = session; + this.mapStorage = mapStorage; + this.mapEntities = mapEntities; + + this.SetHandler(Handle); + } + + private void Handle(InvocationContext ctx) { + if (session.Field == null) { + ctx.Console.Error.WriteLine("No active field"); + ctx.ExitCode = 1; + return; + } + + if (!mapStorage.TryGet(session.Field.MapId, out MapMetadata? map)) { + ctx.Console.Out.WriteLine($"Unknown map: {session.Field.MapId}"); + return; + } + + MapEntityMetadata? mapEntityMetadata = mapEntities.Get(map.XBlock); + if (mapEntityMetadata == null) { + ctx.Console.Out.WriteLine($"No xblock data found for map: {session.Field.MapId}"); + return; + } + + foreach ((int id, SpawnPointPC spawnPoint) in mapEntityMetadata.PlayerSpawns) { + if (session.Field.TryGetPlayerSpawn(id, out FieldPlayerSpawnPoint? fieldPlayerSpawnPoint)) { + ctx.Console.Out.WriteLine($"Id: {id}, Position: {spawnPoint.Position}. Enabled: {fieldPlayerSpawnPoint.Enable}"); + } + } + } + } } diff --git a/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs b/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs index 8475c81d5..e56df0aae 100644 --- a/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs +++ b/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs @@ -38,6 +38,7 @@ public partial class FieldManager { private readonly ConcurrentDictionary fieldItems = new(); private readonly ConcurrentDictionary fieldMobSpawns = new(); private readonly ConcurrentDictionary fieldSpawnPointNpcs = new(); + private readonly ConcurrentDictionary fieldPlayerSpawnPoints = new(); private readonly ConcurrentDictionary fieldSpawnGroups = new(); private readonly ConcurrentDictionary fieldSkills = new(); private readonly ConcurrentDictionary fieldPortals = new(); @@ -81,7 +82,7 @@ public FieldPlayer SpawnPlayer(GameSession session, Player player, int portalId // Use SpawnPoint if needed. if (fieldPlayer.Position == default) { - SpawnPointPC? spawn = Entities.PlayerSpawns.Values.FirstOrDefault(spawn => spawn.Enable); + FieldPlayerSpawnPoint? spawn = fieldPlayerSpawnPoints.Values.FirstOrDefault(spawn => spawn.Enable); if (spawn != null) { fieldPlayer.Position = spawn.Position + new Vector3(0, 0, 25); fieldPlayer.Rotation = spawn.Rotation; @@ -380,7 +381,7 @@ public void ToggleNpcSpawnPoint(int spawnId) { } public void SpawnInteractObject(SpawnInteractObjectMetadata metadata) { - if (!Entities.BoxRegionSpawns.TryGetValue(metadata.RegionSpawnId, out Ms2RegionBoxSpawn? boxSpawn) || + if (!Entities.RegionSpawns.TryGetValue(metadata.RegionSpawnId, out Ms2RegionSpawn? boxSpawn) || !TableMetadata.InteractObjectTable.Entries.TryGetValue(metadata.InteractId, out InteractObjectMetadata? interactObjectMetadata)) { return; } @@ -743,7 +744,7 @@ public void OnAddPlayer(FieldPlayer added) { } } - added.Session.Send(FunctionCubePacket.SendCubes(fieldFunctionInteracts.Values.ToList())); + added.Session.Send(FunctionCubePacket.SendCubes(fieldFunctionInteracts.Values)); foreach (Plot plot in Plots.Values) { foreach (PlotCube plotCube in plot.Cubes.Values) { diff --git a/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs b/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs index 9b96c361f..663153375 100644 --- a/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs +++ b/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs @@ -152,6 +152,10 @@ public virtual void Init() { AddSpawnPointNpc(spawnPointNpc); } + foreach ((int id, SpawnPointPC spawnPoint) in Entities.PlayerSpawns) { + fieldPlayerSpawnPoints[id] = new FieldPlayerSpawnPoint(this, NextLocalId(), spawnPoint); + } + IList bonusMaps = MapMetadata.GetMapsByType(Metadata.Property.Continent, MapType.PocketRealm); foreach (MapMetadataSpawn spawn in Metadata.Spawns) { if (!Entities.RegionSpawns.TryGetValue(spawn.Id, out Ms2RegionSpawn? regionSpawn)) { @@ -347,6 +351,10 @@ public bool TryGetPortal(int portalId, [NotNullWhen(true)] out FieldPortal? port return portal != null; } + public bool TryGetPlayerSpawn(int id, [NotNullWhen(true)] out FieldPlayerSpawnPoint? playerSpawnPoint) { + return fieldPlayerSpawnPoints.TryGetValue(id, out playerSpawnPoint); + } + public bool TryGetItem(int objectId, [NotNullWhen(true)] out FieldItem? fieldItem) { return fieldItems.TryGetValue(objectId, out fieldItem); } diff --git a/Maple2.Server.Game/Model/Field/Entity/FieldPlayerSpawnPoint.cs b/Maple2.Server.Game/Model/Field/Entity/FieldPlayerSpawnPoint.cs new file mode 100644 index 000000000..a465799c7 --- /dev/null +++ b/Maple2.Server.Game/Model/Field/Entity/FieldPlayerSpawnPoint.cs @@ -0,0 +1,14 @@ +using Maple2.Model.Metadata; +using Maple2.Server.Game.Manager.Field; + +namespace Maple2.Server.Game.Model; + +public class FieldPlayerSpawnPoint : FieldEntity { + public bool Enable; + + public FieldPlayerSpawnPoint(FieldManager field, int objectId, SpawnPointPC metadata) : base(field, objectId, metadata) { + Enable = metadata.Enable; + Position = metadata.Position; + Rotation = metadata.Rotation; + } +} diff --git a/Maple2.Server.Game/Trigger/TriggerContext.Field.cs b/Maple2.Server.Game/Trigger/TriggerContext.Field.cs index 0e20f2ffd..7fe77e25d 100644 --- a/Maple2.Server.Game/Trigger/TriggerContext.Field.cs +++ b/Maple2.Server.Game/Trigger/TriggerContext.Field.cs @@ -85,7 +85,8 @@ public void SightRange(bool enabled, int range, int rangeZ, int border) { for (int i = 0; i < range; i++) { sightRange.Fades[i] = rangeZ; } - sightRange.Opacity = (byte) (100 - border); + + sightRange.Opacity = (byte) border; sightRange.Opaque = false; sightRange.Unknown = enabled; Broadcast(FieldPropertyPacket.Add(sightRange)); diff --git a/Maple2.Server.Game/Trigger/TriggerContext.Player.cs b/Maple2.Server.Game/Trigger/TriggerContext.Player.cs index 9937f81aa..4121c1b6e 100644 --- a/Maple2.Server.Game/Trigger/TriggerContext.Player.cs +++ b/Maple2.Server.Game/Trigger/TriggerContext.Player.cs @@ -11,7 +11,13 @@ namespace Maple2.Server.Game.Trigger; public partial class TriggerContext { public void EnableSpawnPointPc(int spawnPointId, bool enabled) { - ErrorLog("[EnableSpawnPointPc] spawnPointId:{Type}, enabled:{Enabled}", spawnPointId, enabled); + DebugLog("[EnableSpawnPointPc] spawnPointId:{Type}, enabled:{Enabled}", spawnPointId, enabled); + if (!Field.TryGetPlayerSpawn(spawnPointId, out FieldPlayerSpawnPoint? fieldPlayerSpawn)) { + logger.Error("[EnableSpawnPointPc] Invalid Player Spawn Point ID: {spawnPointId} in Map ID: {mapId}", spawnPointId, Field.MapId); + return; + } + + fieldPlayerSpawn.Enable = enabled; } public void GiveExp(int boxId, float expRate, bool arg3) { From 15a8af01089e8b981577ac923c7e22c883b41ff9 Mon Sep 17 00:00:00 2001 From: Zin <62830952+Zintixx@users.noreply.github.com> Date: Tue, 11 Mar 2025 09:40:49 -0700 Subject: [PATCH 2/3] fix --- Maple2.Database/Storage/Metadata/MapEntityStorage.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Maple2.Database/Storage/Metadata/MapEntityStorage.cs b/Maple2.Database/Storage/Metadata/MapEntityStorage.cs index 589774679..1730875ac 100644 --- a/Maple2.Database/Storage/Metadata/MapEntityStorage.cs +++ b/Maple2.Database/Storage/Metadata/MapEntityStorage.cs @@ -68,9 +68,6 @@ public class MapEntityStorage(MetadataContext context) : MetadataStorage Date: Tue, 11 Mar 2025 10:51:07 -0700 Subject: [PATCH 3/3] Revert back Timer changes --- Maple2.Server.Game/Trigger/TriggerContext.Field.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Maple2.Server.Game/Trigger/TriggerContext.Field.cs b/Maple2.Server.Game/Trigger/TriggerContext.Field.cs index 7fe77e25d..11f35887d 100644 --- a/Maple2.Server.Game/Trigger/TriggerContext.Field.cs +++ b/Maple2.Server.Game/Trigger/TriggerContext.Field.cs @@ -457,10 +457,10 @@ public void StartCombineSpawn(int[] groupIds, bool isStart) { } } - public void SetTimer(string timerId, int seconds, bool disableUi, bool autoRemove, int vOffset, string type, string desc) { + public void SetTimer(string timerId, int seconds, bool autoRemove, bool display, int vOffset, string type, string desc) { DebugLog("[SetTimer] timerId:{Id}, seconds:{Seconds}", timerId, seconds); - Field.Timers[timerId] = new TickTimer(seconds * 1000, autoRemove, vOffset, !disableUi, type); - if (!disableUi) { + Field.Timers[timerId] = new TickTimer(seconds * 1000, autoRemove, vOffset, display, type); + if (display) { Broadcast(TriggerPacket.TimerDialog(Field.Timers[timerId])); } }