Skip to content

Field Spawn Groups - #357

Merged
AngeloTadeucci merged 2 commits into
MS2Community:masterfrom
Zintixx:spawns
Mar 10, 2025
Merged

Field Spawn Groups#357
AngeloTadeucci merged 2 commits into
MS2Community:masterfrom
Zintixx:spawns

Conversation

@Zintixx

@Zintixx Zintixx commented Mar 10, 2025

Copy link
Copy Markdown
Collaborator
  • This implements spawn groups needed for Mushking Royale and Kritias Invasion
  • Implements looting items and applying buff if applicable
  • Fixed a few triggers (setting visible ui, npc side talk cut in, movies, etc)
  • Fixed timer showing up only when applicable

Summary by CodeRabbit

  • New Features

    • Introduced an advanced spawn system that supports region-specific and combined spawn groups for NPCs and interactive objects.
    • Added survival event functionality with a dedicated widget to enhance gameplay events.
    • Enabled a new defensive item action that temporarily summons protective NPCs.
  • Enhancements

    • Improved item pickup behavior to apply special effects as buffs before adding items.
    • Refined field visuals with dynamic sight range adjustments for better environmental clarity.
    • Upgraded UI interactions and NPC dialogue triggers for smoother in-game communication.
    • Expanded metadata structures to include new spawn types and effects for enhanced gameplay mechanics.

@coderabbitai

coderabbitai Bot commented Mar 10, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This pull request enhances the game’s systems by integrating new spawn types and interactive elements. The changes update metadata storage by adding dictionaries and lazy-loaded combine spawn tables, and they extend mapper logic to process additional parameters and new spawn cases. New enums and record types are introduced for proper categorization and polymorphic behavior, while FieldManager gains methods for spawning NPCs, interactable objects, and toggling spawn states. Packet handlers and trigger contexts are also revised to support defense guard actions, UI visibility controls, and refined broadcast and logging mechanisms.

Changes

File(s) Change Summary
Maple2.Database/Storage/Metadata/...MapEntityStorage.cs, ServerTableMetadataStorage.cs Added region box spawn dictionary in MapEntityStorage and introduced a Lazy<CombineSpawnTable> field with a corresponding property in ServerTableMetadataStorage.
Maple2.File.Ingest/Mapper/...ItemMapper.cs, MapEntityMapper.cs, ServerTableMapper.cs Updated mappers to include an extra parameter for additional effects, added a new case for IMS2RegionBoxSpawn, and implemented a ParseCombineSpawn method for combine spawn data.
Maple2.Model/Enum/...CombineSpawnGroupType.cs, Interact.cs; Maple2.Model/Metadata/...IFieldProperty.cs, ItemMetadata.cs, MapEntity.cs, Ms2RegionBoxSpawn.cs, MapEntityMetadata.cs, CombineSpawnTable.cs, ServerTableMetadata.cs Introduced new enums, updated the item metadata record with a PickUpEffect, added the Ms2RegionBoxSpawn record, and extended metadata classes to integrate combine spawn tables via polymorphic JSON types.
Maple2.Server.DebugGame/...csproj Upgraded the SixLabors.ImageSharp package version from 3.1.5 to 3.1.7.
Maple2.Server.Game/Manager/Field/...FieldManager.State.cs, FieldManager.cs; Maple2.Server.Game/Model/Field/Entity/...FieldInteract.cs, FieldNpcSpawnPoint.cs, FieldSpawnGroup.cs Enhanced FieldManager with new public methods for NPC spawn, interact object creation, and combinatorial spawn toggling; added classes for spawn point NPCs and spawn groups; updated NPC spawn handling and interact object removal with delay and broadcast functionality.
Maple2.Server.Game/Model/Widget/...SurvivalContentsWidget.cs; Maple2.Server.Game/PacketHandlers/...ItemPickupHandler.cs, ItemUseHandler.cs, UserChatHandler.cs Added the SurvivalContentsWidget with serialization and dynamic action invocation; updated item handlers to check for pickup effects and to process DefenseGuard items; modified chat handler using directives to include additional namespaces.
Maple2.Server.Game/Packets/...SurvivalEventPacket.cs, TriggerPacket.cs; Maple2.Server.Game/Scripting/Trigger/...TriggerEnums.cs; Maple2.Server.Game/Trigger/...TriggerContext.Field.cs, TriggerContext.Interface.cs Modified packet commands (e.g., replacing Unknown19 with SetVisibleUi) and added new methods for UI visibility and side NPC talk; introduced the SideNpcTalkType enum; updated trigger context methods for timer setting, UI adjustments, and broadcast logic with debug logging.

Sequence Diagram(s)

sequenceDiagram
    participant P as Player
    participant IU as ItemUseHandler
    participant NS as NpcMetadataService
    participant FM as FieldManager
    participant SCH as Scheduler

    P->>IU: Use DefenseGuard item
    IU->>IU: Validate parameters
    IU->>NS: Retrieve NPC metadata (npcId)
    NS-->>IU: Return NPC metadata
    IU->>FM: Calculate spawn position & request NPC spawn
    FM->>FM: Spawn NPC and broadcast addition
    FM->>SCH: Schedule NPC removal (lifeSpanSeconds)
    SCH-->>FM: Removal confirmed
    IU->>P: Consume item
Loading
sequenceDiagram
    participant FM as FieldManager
    participant IO as InteractObject
    participant BC as Broadcast System

    FM->>FM: Call SpawnInteractObject(metadata)
    FM->>IO: Create interact object instance
    FM->>FM: Add interact object to fieldChests
    FM->>BC: Broadcast interact object addition
Loading

Poem

Hop, hop, I scurry with delight,
New spawns and toggles shine so bright.
Records and enums in a playful dance,
Code carrots bloom as features advance.
With each refined broadcast and spawn so true,
This bunny cheers for changes fresh and new!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (22)
Maple2.Server.Game/PacketHandlers/UserChatHandler.cs (1)

1-2: Imports added without corresponding implementation changes.

Only import statements have been added to the file without any changes to the implementation code. The new imports suggest preparation for future functionality that will integrate chat with:

  • Vector mathematics (System.Numerics)
  • Game model classes (Maple2.Server.Game.Model)
  • Scripting triggers (Maple2.Server.Game.Scripting.Trigger)

Consider adding a code comment explaining the purpose of these imports if they're being added proactively for future development. If they're not currently used, it would be helpful to understand their intended purpose.

Also applies to: 13-13, 15-15

Maple2.Model/Enum/CombineSpawnGroupType.cs (2)

1-2: Confirm Using Directives
The file imports System.ComponentModel. Please verify if this using directive is required in this file; if it’s not used now, it may be removed in a future cleanup for better maintainability.


3-10: Enum Naming Conventions
The enumeration members are defined in lowercase (e.g., none, npc, interactObject), which deviates from standard C# naming conventions that prefer PascalCase (e.g., None, Npc, InteractObject). Adopting the conventional casing would improve code readability and consistency across the codebase.

Maple2.Server.Game/PacketHandlers/ItemUseHandler.cs (1)

488-512: Defense Guard implementation is well structured.

The implementation correctly:

  1. Parses parameters from the item metadata
  2. Calculates spawn position relative to player
  3. Spawns the NPC and sets up its lifecycle
  4. Consumes the item upon successful spawning

Some minor suggestions:

  • The TODO comment on line 503 should be addressed or clarified
  • Consider adding validation for the NPC spawning position (e.g., checking for collisions or invalid terrain)
- Vector3 position = session.Player.Transform.Position + session.Player.Transform.FrontAxis * distance;
- // TODO: Do we check Z?
+ Vector3 position = session.Player.Transform.Position + session.Player.Transform.FrontAxis * distance;
+ // Ensure the NPC is spawned on valid terrain
+ if (session.Field.TryGetValidPosition(position, out Vector3 validPosition)) {
+     position = validPosition;
+ }
Maple2.Server.Game/Model/Field/Entity/FieldNpcSpawnPoint.cs (3)

8-21: Consider adding XML documentation for public types and members.

The class structure looks good, but adding XML documentation would improve code maintainability and make it easier for other developers to understand the purpose of this class and its properties.

Also, I noticed that the active field is set in the constructor but not used elsewhere in this file. Ensure this is intentional or consider how it will be used in future implementations.


38-40: Consider adding logging when NPC spawn fails.

When Field.SpawnNpc returns null, the code simply continues to the next iteration. Consider adding a log entry similar to the one on line 32 to help with debugging when NPC spawning fails.

if (npc == null) {
+    Log.Logger.Warning("Failed to spawn Npc {NpcId} at spawn point {SpawnId} in map {MapId}", spawn.NpcId, SpawnId, Field.MapId);
    continue;
}

43-45: Consider error handling for broadcast operations.

While the Field.Broadcast methods might handle exceptions internally, it's good practice to ensure these operations won't cause issues if they fail. Consider wrapping these in a try-catch block to prevent any potential exceptions from stopping the spawn process.

Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs (1)

25-49: Implication of fallback behavior.

The Init() method adds entries to either npcs or interactObjects based on the group type. If the group type is invalid, an error log is written. Consider throwing or handling that scenario more robustly if an invalid type should halt further processing in some contexts.

Maple2.Model/Metadata/ServerTable/CombineSpawnTable.cs (3)

10-15: Good use of record for spawn group metadata.

The record provides an immutable data structure with clear property names. Consider adding XML documentation comments to explain the purpose of each property, especially ResetTick which might not be self-explanatory.


17-21: Properly defined NPC metadata record.

The record captures the essential properties needed for NPC spawning. Consider adding documentation for the Weight property to clarify its meaning and how it affects spawn behavior.


23-34: Comprehensive interact object metadata.

This record contains all necessary properties for interactive objects, but some property names could be more self-explanatory:

  • What does Reactable represent? Is it a path to a reactable asset or a boolean flag?
  • What does KeepAnimate control in the spawn behavior?

Consider adding XML documentation to clarify these properties.

Maple2.Server.Game/Packets/TriggerPacket.cs (1)

111-120: Enhanced SidePopupTalk method with additional parameters.

The method now supports different talk types and includes a usm parameter. The default parameter values help maintain backward compatibility. The packet writing order has been adjusted to match the client's expectations.

For future reference, consider adding a comment explaining what the usm parameter represents, as its purpose is not immediately clear from the name.

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (1)

459-465: Remove or utilize unused parameters.
The parameter desc is not used, which might indicate dead code or an incomplete feature. Consider either removing it or implementing its usage to avoid confusion.

Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (2)

316-334: Handle concurrent iteration for improved stability.
Enumerating the Npcs, Mobs, and Pets dictionaries while they are potentially modified in parallel may produce partial or inconsistent results. To avoid concurrency issues, consider capturing a snapshot or employing additional synchronization if strict consistency is required.


372-376: Validate concurrent enumeration in multi-dictionary queries.
Similar to the GetActorsBySpawnId method, constructing the IEnumerable from multiple dictionaries may yield inconsistent data if these collections change at runtime. For stricter consistency, consider copying to a local list inside a locked section or employing thread-safe iteration patterns.

Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)

374-380: Use consistent naming for clarity.
The local variable fieldSpawnGroup is confusingly named when retrieving a spawn point NPC. Renaming it to spawnPointNpc or similar could improve readability.


382-406: Align naming to match object usage.
Objects created in SpawnInteractObject are stored in fieldChests, which can be misleading if they are not exclusively chests. You might consider a different collection name (e.g., fieldInteractibles) or clarifying comments.

Maple2.Server.Game/Trigger/TriggerContext.Interface.cs (2)

162-166: Fix the incorrect log message label

The debug log message uses "[SideNpcTalkBottom]" when it should be "[SideNpcTalk]" to match the actual method name.

-        DebugLog("[SideNpcTalkBottom] npcId:{NpcId}, illust:{Illustration}, duration:{Duration}, script:{Script}, voice:{Voice}",
+        DebugLog("[SideNpcTalk] npcId:{NpcId}, illust:{Illustration}, duration:{Duration}, script:{Script}, voice:{Voice}",
            npcId, illust, duration, script, voice);

178-181: Fix incorrect log message label

The debug log message uses "[SideNpcMovie]" when it should be "[SideNpcCutin]" to match the actual method name.

-        DebugLog("[SideNpcMovie] illust:{Illustration}, duration:{Duration}", illust, duration);
+        DebugLog("[SideNpcCutin] illust:{Illustration}, duration:{Duration}", illust, duration);
Maple2.Server.Game/Packets/SurvivalEventPacket.cs (2)

9-12: Add documentation and consider removing empty enum

The SurvivalEventPacket class lacks documentation explaining its purpose and usage. Additionally, the Command enum is currently empty, which suggests it might be intended for future use but doesn't serve any purpose now.

Consider either:

  1. Adding enum values if they're already known
  2. Removing the empty enum until needed
  3. Adding a TODO comment explaining planned values

13-19: Improve method naming and documentation

The method name Test suggests this might be temporary or experimental code. Consider renaming it to better reflect its purpose (e.g., SendSurvivalContentsWidget or BroadcastSurvivalEvent).

Also, the comment on line 15 "bool to enable?" is unclear. If this is a boolean flag to enable something, it should be properly documented what exactly is being enabled.

-    public static ByteWriter Test(SurvivalContentsWidget widget) {
+    /// <summary>
+    /// Creates a packet for broadcasting survival content widget information to clients.
+    /// </summary>
+    /// <param name="widget">The survival contents widget containing storm and safe zone data</param>
+    /// <returns>A ByteWriter containing the packet data</returns>
+    public static ByteWriter BroadcastSurvivalWidget(SurvivalContentsWidget widget) {
         var pWriter = Packet.Of(SendOp.SurvivalEvent);
-        pWriter.WriteByte(0); // bool lto enable?
+        pWriter.WriteByte(0); // 0 = Enable survival content display
         pWriter.WriteClass<SurvivalContentsWidget>(widget);

         return pWriter;
     }
Maple2.Server.Game/Model/Field/Widget/SurvivalContentsWidget.cs (1)

36-43: Document hardcoded values and add property accessors

The WriteTo method contains several hardcoded values with minimal comments. These should be properly documented or extracted as constants with meaningful names.

Also, consider adding public properties for StormCenter and SafeZoneCenter to allow setting these values from outside the class.

+// Constants for survival content configuration
+private const short STORM_DAMAGE = 500;
+private const short STORM_RADIUS = 3000;
+private const short STORM_INTERVAL = 1000;
+private const short SAFE_ZONE_RADIUS = 1000;

+// Properties to allow setting center positions
+public Vector3 StormCenterPosition {
+    get => StormCenter;
+    set => StormCenter = value;
+}
+
+public Vector3 SafeZoneCenterPosition {
+    get => SafeZoneCenter;
+    set => SafeZoneCenter = value;
+}

 public void WriteTo(IByteWriter writer) {
-    writer.WriteShort(500);
-    writer.WriteShort(3000); // radius
-    writer.WriteShort(1000);
+    writer.WriteShort(STORM_DAMAGE);  // Damage per tick inside storm
+    writer.WriteShort(STORM_RADIUS);  // Storm radius
+    writer.WriteShort(STORM_INTERVAL); // Time interval between damage ticks
     writer.Write<Vector3>(StormCenter);
-    writer.WriteShort(1000); // radius of center
+    writer.WriteShort(SAFE_ZONE_RADIUS); // Safe zone radius
     writer.Write<Vector3>(SafeZoneCenter);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 127e21e and 1a7ff8e.

📒 Files selected for processing (29)
  • Maple2.Database/Storage/Metadata/MapEntityStorage.cs (3 hunks)
  • Maple2.Database/Storage/Metadata/ServerTableMetadataStorage.cs (3 hunks)
  • Maple2.File.Ingest/Mapper/ItemMapper.cs (1 hunks)
  • Maple2.File.Ingest/Mapper/MapEntityMapper.cs (1 hunks)
  • Maple2.File.Ingest/Mapper/ServerTableMapper.cs (2 hunks)
  • Maple2.Model/Enum/CombineSpawnGroupType.cs (1 hunks)
  • Maple2.Model/Enum/Interact.cs (1 hunks)
  • Maple2.Model/Game/IFieldProperty.cs (1 hunks)
  • Maple2.Model/Metadata/ItemMetadata.cs (1 hunks)
  • Maple2.Model/Metadata/MapEntity/MapEntity.cs (1 hunks)
  • Maple2.Model/Metadata/MapEntity/Ms2RegionBoxSpawn.cs (1 hunks)
  • Maple2.Model/Metadata/MapEntityMetadata.cs (1 hunks)
  • Maple2.Model/Metadata/ServerTable/CombineSpawnTable.cs (1 hunks)
  • Maple2.Model/Metadata/ServerTableMetadata.cs (1 hunks)
  • Maple2.Server.DebugGame/Maple2.Server.DebugGame.csproj (1 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (9 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (3 hunks)
  • Maple2.Server.Game/Model/Field/Entity/FieldInteract.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Entity/FieldNpcSpawnPoint.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Widget/SurvivalContentsWidget.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemPickupHandler.cs (2 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemUseHandler.cs (3 hunks)
  • Maple2.Server.Game/PacketHandlers/UserChatHandler.cs (2 hunks)
  • Maple2.Server.Game/Packets/SurvivalEventPacket.cs (1 hunks)
  • Maple2.Server.Game/Packets/TriggerPacket.cs (3 hunks)
  • Maple2.Server.Game/Scripting/Trigger/TriggerEnums.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Interface.cs (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (40)
Maple2.Server.Game/PacketHandlers/ItemPickupHandler.cs (1)

56-62: Good implementation of pickup effect handling.

This new block correctly handles items with pickup effects by applying their buffs to the player without adding them to inventory. The approach ensures that items with these effects are processed correctly and consistently.

Maple2.Model/Metadata/ItemMetadata.cs (1)

86-89: Record property addition looks good.

The new PickUpEffect boolean property in the ItemMetadataAdditionalEffect record is a clean addition that maintains the model's structure while enabling the new functionality.

Maple2.File.Ingest/Mapper/ItemMapper.cs (1)

218-220: Properly updated to accommodate the model change.

The mapper now correctly includes the dropEffect value when creating ItemMetadataAdditionalEffect instances, ensuring data consistency between the parsed file data and the model objects.

Maple2.Server.Game/PacketHandlers/ItemUseHandler.cs (2)

1-2: Added required namespace for Vector3.

The addition of the System.Numerics namespace is appropriate for the Vector3 usage in the new method.


104-106: New case properly integrated.

The implementation of the DefenseGuard case in the switch statement correctly calls the new handler method.

Maple2.Model/Enum/Interact.cs (1)

68-72:

Details

❓ Verification inconclusive

Appropriate enum extensions for spawn group functionality.

The new enum values (Notice, InstallNPC, Portal, SpawnPoint, PVP) appropriately support the PR objectives of implementing spawn groups for Mushking Royale and Kritias Invasion features. The additions are correctly placed at the end of the enum without explicit values, maintaining backward compatibility.

If there are any switch statements that check all cases of InteractCubeControlType, they might need updating to handle these new values. Consider running:


🏁 Script executed:

#!/bin/bash
# Search for switch statements on InteractCubeControlType
rg "switch.*InteractCubeControlType" -A 10 -B 2

Length of output: 49


Action required: Confirm switch statement handling for new enum values

The new enum values in Maple2.Model/Enum/Interact.cs (lines 68–72) correctly extend support for spawn group functionality while preserving backward compatibility. The enum values are appended without explicit assignments, so they function as intended.

However, our automated search for switch statements referencing InteractCubeControlType did not yield any results. This result is inconclusive, and there’s a possibility that switch cases elsewhere in the codebase might not yet account for the new enum values.

  • Review location: Maple2.Model/Enum/Interact.cs (lines 68–72)
  • Action: Please manually verify if there are any switch statements on InteractCubeControlType that need updates to gracefully handle the new enum values.
Maple2.Server.Game/Model/Field/Entity/FieldNpcSpawnPoint.cs (1)

36-42: Setting SpawnPointId to 0 seems counterintuitive.

On line 41, npc.SpawnPointId = 0 is set despite the NPC being spawned from a spawn point. This might be intentional, but it seems contradictory. Consider if this should instead reference the current spawn point's ID or document why it's explicitly set to 0.

Maple2.Server.DebugGame/Maple2.Server.DebugGame.csproj (1)

27-27: Package upgrade looks good

The SixLabors.ImageSharp package has been updated to version 3.1.7, which is appropriate. This package is used for image processing in the debug game.

Maple2.Model/Metadata/MapEntity/Ms2RegionBoxSpawn.cs (1)

5-11: New record type for box region spawns looks well-structured

This new record type Ms2RegionBoxSpawn provides a clear data structure for box-shaped region spawns with appropriate spatial properties (position, rotation, scale) and identifying properties (Id, SpawnTypeId).

The inheritance from MapBlock is appropriate as this is a type of map entity block.

Maple2.Model/Metadata/MapEntity/MapEntity.cs (1)

60-60: JsonDerivedType attribute correctly added for Ms2RegionBoxSpawn

The JsonDerivedType attribute has been properly added for the new Ms2RegionBoxSpawn type with a unique discriminator value. This ensures proper JSON serialization/deserialization capabilities for this new map entity type.

Maple2.File.Ingest/Mapper/MapEntityMapper.cs (1)

122-126: Looks good!

This new case for IMS2RegionBoxSpawn integrates seamlessly into the existing switch statement and properly populates the Block property with Ms2RegionBoxSpawn. The usage of (int) boxSpawn.SpawnTypeID appears appropriate, aligning with the typical pattern throughout the mapper.

Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs (5)

9-17: Validate potential concurrency and data structures usage.

This class declaration and its private fields look well structured, with separate WeightedSet<SpawnNpcMetadata> and WeightedSet<SpawnInteractObjectMetadata> for NPCs and interactable objects. However, confirm that the field manager does not call these methods concurrently. If concurrency is possible, ensure thread-safety for the shared collections (spawnIds, npcs, etc.).

Would you like a script to check for concurrency usages or potential multi-threaded calls to this class?


18-23: Constructor logic is clear.

Initializing resetTick and calling Init() right after setting up the weighted sets is a straightforward approach, ensuring the spawn data is populated early. No issues spotted here.


51-59: ToggleActive flipping spawn states.

The ToggleActive method correctly clears or re-initializes spawns based on the bool toggle. Very straightforward logic.


61-74: Initialization method is consistent.

InitializeSpawns() checks if TotalCount > 0 and dispatches to either SpawnNpcs() or SpawnInteractObjects() depending on the group type. This is consistent with the approach in Init().


120-132: Re-initializing spawns upon reset tick.

Overriding Update to reset the spawns works well for timed re-initialization. Ensure ToggleActive(false) cleans up states properly when a field is unloaded or no longer active, to avoid unbounded growth of spawnIds.

Maple2.File.Ingest/Mapper/ServerTableMapper.cs (1)

1645-1705: Implementation is coherent and well-organized.

The new ParseCombineSpawn() method consistently partitions spawn data into dictionaries for spawn groups, NPCs, and interactable objects. Returning a CombineSpawnTable with these structures is a clean approach. This looks properly aligned with how other parse methods in ServerTableMapper handle grouped data.

Maple2.Model/Metadata/ServerTable/CombineSpawnTable.cs (1)

6-8: Well-structured dictionary usage with clear key definitions.

The dictionaries are appropriately defined as read-only with nested structure, and the comments clearly document the meaning of each key (MapId, groupId, combineId). This enables type-safe access while maintaining good organization of the spawn metadata.

Maple2.Server.Game/Packets/TriggerPacket.cs (3)

8-8: Appropriate namespace import.

Adding the Trigger namespace import enables the use of the SideNpcTalkType enum.


26-26: Good renaming of enum value.

Replacing the generic Unknown19 with the descriptive SetVisibleUi improves code readability and self-documentation.


125-132: Well-implemented UI visibility control.

This new method allows toggling UI elements visibility through a simple interface. The implementation writes the command and parameters in the correct order.

Maple2.Model/Game/IFieldProperty.cs (2)

77-81: Improved FieldPropertySightRange with better property access.

The changes enhance flexibility by:

  1. Changing init to set accessors for runtime modification
  2. Consolidating fade values into a single array
  3. Setting sensible defaults

This is a good refactoring that simplifies the code while maintaining functionality.


86-88: Efficient fade values writing using array iteration.

Using a loop to write fade values from the array is cleaner than writing each fade value individually. This approach is more maintainable and accommodates potential future changes to the number of fade values.

Maple2.Model/Metadata/MapEntityMetadata.cs (1)

19-19:

Details

✅ Verification successful

Good addition of BoxRegionSpawns property.

The new property follows the same pattern as existing properties, using a required read-only dictionary for type safety and immutability. This addition logically extends the metadata to support box-shaped spawn regions alongside the existing region spawns.

Consider ensuring that the corresponding mapper and storage implementations initialize this dictionary correctly, even if empty, to prevent null reference exceptions.


🏁 Script executed:

#!/bin/bash
# Check if BoxRegionSpawns is properly initialized in the mapper code
# Look for initialization pattern similar to other region spawns

echo "Searching for MapEntityStorage implementation..."
rg -A 5 "boxRegionSpawns.*=.*new" --type cs

Length of output: 833


Code Initialization Verified – No Changes Required

The new BoxRegionSpawns property is well implemented. The mapper and storage code (see Maple2.Database/Storage/Metadata/MapEntityStorage.cs) correctly initializes the dictionary, ensuring it won’t be null. The property follows the established pattern for type safety and immutability.

Maple2.Model/Metadata/ServerTableMetadata.cs (1)

46-46: Well-implemented JSON polymorphism support for CombineSpawnTable

The addition of CombineSpawnTable as a derived type follows the established pattern in the codebase for polymorphic JSON serialization/deserialization. This change properly integrates the new table type into the existing framework.

Maple2.Server.Game/Scripting/Trigger/TriggerEnums.cs (1)

16-16: Good implementation of NPC dialog presentation types

This new enum provides well-defined types for different NPC dialog presentation styles, supporting the UI trigger fixes mentioned in the PR description. The byte-based enum pattern is consistent with other enumerations in this file.

Maple2.Database/Storage/Metadata/ServerTableMetadataStorage.cs (1)

28-28: Clean integration of CombineSpawnTable

The implementation follows the established pattern of lazy-loaded metadata tables. The field declaration, property accessor, and initialization in the constructor are consistent with the existing code structure, making this a seamless integration.

Also applies to: 48-48, 69-69

Maple2.Database/Storage/Metadata/MapEntityStorage.cs (1)

41-42: Proper implementation of boxRegionSpawns

The addition of Ms2RegionBoxSpawn handling is well-integrated into the existing entity processing system:

  1. The dictionary declaration follows the same pattern as other entity collections
  2. The switch case correctly processes and stores the new entity type
  3. The dictionary is properly included in the returned MapEntityMetadata

This implementation provides the foundation needed for the spawn groups feature mentioned in the PR objectives.

Also applies to: 72-74, 134-134

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2)

84-92: Check for potential out-of-bounds access and clarify usage of Unknown.
The loop writing to sightRange.Fades[i] may risk an out-of-bounds error if range exceeds Fades.Length. Consider validating that range does not exceed the array length. Additionally, Unknown = enabled; lacks clarity, which could lead to confusion. Using a more descriptive property name or documentation would be helpful.


444-456: Iterate safely and consider logging toggled groups.
These lines properly handle missing group metadata. However, you might consider also logging successful toggles for better traceability when diagnosing spawn issues. Other than that, the flow looks good.

Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)

369-370: Combined dictionary check appears correct.
Merging the checks for fieldInteracts, fieldAdBalloons, and fieldChests into a single return statement is concise and understandable. No immediate concerns.

Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (5)

6-6: Added imports look correct.
The new using directives for Maple2.Model.Common and Maple2.Tools.VectorMath appear legitimate.

Also applies to: 18-18


36-36: New fieldChests dictionary introduced.
Creating this concurrent dictionary is aligned with the other concurrency patterns. No concerns here.


40-41: Additional dictionaries for NPCs and groups.
Using concurrent dictionaries for fieldSpawnPointNpcs and fieldSpawnGroups provides consistent parallel access. Implementation aligns with existing concurrency usage.


126-128: Overload to spawn NPC from SpawnPointNPC looks fine.
This overload delegates to the existing SpawnNpc method, minimizing duplicated logic.


354-363: Confirm potential ID collisions.
AddSpawnPointNpc directly indexes fieldSpawnPointNpcs by metadata.Id without checking if a conflicting entry exists. You might consider verifying the ID's uniqueness or gracefully handling duplicates.

Maple2.Server.Game/Trigger/TriggerContext.Interface.cs (4)

137-140: Nice implementation of UI visibility broadcast!

The changes correctly implement broadcasting UI visibility settings to clients and appropriately downgrade logging from error to debug level. This change aligns with the PR objectives of addressing UI triggers.


168-171: Well-implemented NPC talk broadcast functionality

Good job implementing the broadcast functionality for bottom NPC talks with the appropriate talk type and downgrading the log level from error to debug.


173-176: Proper implementation of movie side popup broadcast

The change appropriately implements broadcasting for movie popups and uses the correct debug log level.


183-185: Appropriate log level change for widget actions

The change from error to debug level logging is appropriate since widget actions are normal operations rather than error conditions.

Comment thread Maple2.Server.Game/Model/Field/Entity/FieldNpcSpawnPoint.cs Outdated
Comment thread Maple2.Server.Game/Model/Field/Entity/FieldNpcSpawnPoint.cs
Comment thread Maple2.Server.Game/Model/Field/Entity/FieldInteract.cs
Comment thread Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs
Comment thread Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs Outdated
Comment thread Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Comment thread Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Comment thread Maple2.Server.Game/Model/Field/Widget/SurvivalContentsWidget.cs
Comment thread Maple2.Server.Game/Model/Field/Widget/SurvivalContentsWidget.cs
Comment thread Maple2.Server.Game/Model/Field/Widget/SurvivalContentsWidget.cs
Comment thread Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs Outdated
Comment thread Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs Outdated
Comment thread Maple2.Server.Game/Packets/SurvivalEventPacket.cs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs (2)

90-97: ⚠️ Potential issue

Prevent potential infinite loop in NPC spawning.

When WeightedSet keeps returning duplicates already in spawnIds, the loop can run indefinitely. This mirrors a previously noted concern.

Consider imposing a retry limit, for instance:

-do {
+int retryCount = 0;
 do {
     SpawnNpcMetadata npc = npcs.Get();
     if (spawnIds.Contains(npc.SpawnId)) {
         continue;
     }
     Field.ToggleNpcSpawnPoint(npc.SpawnId);
     spawnIds.Add(npc.SpawnId);
-} while (totalCount > spawnIds.Count);
+} while (totalCount > spawnIds.Count && retryCount++ < 50);

113-120: ⚠️ Potential issue

Similar infinite loop risk for interact objects.

This loop is virtually the same as the NPC loop; WeightedSet duplicates can cause indefinite repetition. Introduce a safety mechanism, similar to the NPC loop fix.

-do {
+int retryCount = 0;
 do {
     SpawnInteractObjectMetadata interactObject = interactObjects.Get();
     if (spawnIds.Contains(interactObject.RegionSpawnId)) {
         continue;
     }
     Field.SpawnInteractObject(interactObject);
     spawnIds.Add(interactObject.RegionSpawnId);
-} while (totalCount > spawnIds.Count);
+} while (totalCount > spawnIds.Count && retryCount++ < 50);
🧹 Nitpick comments (5)
Maple2.Server.Game/Packets/SurvivalEventPacket.cs (3)

9-17: The class looks well-structured but could benefit from documentation.

The implementation follows the packet builder pattern used elsewhere in the codebase. Consider adding XML documentation to explain the purpose of this class and its role in handling survival events (Mushking Royale and Kritias Invasion).

+ /// <summary>
+ /// Handles packet operations for survival events such as Mushking Royale and Kritias Invasion.
+ /// </summary>
 public static class SurvivalEventPacket {
+    /// <summary>
+    /// Creates a packet to update the survival contents widget with current state.
+    /// </summary>
+    /// <param name="widget">The widget containing survival content state to be updated</param>
+    /// <returns>A ByteWriter containing the serialized packet data</returns>
     public static ByteWriter Update(SurvivalContentsWidget widget) {

12-12: Fix the unclear comment.

The comment "bool lto enable?" seems to have a typo or is unclear. Consider clarifying the purpose of this byte value.

- pWriter.WriteByte(0); // bool lto enable?
+ pWriter.WriteByte(0); // Boolean flag to enable the survival event

13-13: Consider adding null check for widget parameter.

If the widget parameter is null, the WriteClass method might throw an exception. Consider adding a null check or using null-conditional operators if appropriate.

- pWriter.WriteClass<SurvivalContentsWidget>(widget);
+ pWriter.WriteClass<SurvivalContentsWidget>(widget ?? throw new ArgumentNullException(nameof(widget)));

Also ensure you add the corresponding using System; directive at the top of the file.

Maple2.Server.Game/Model/Field/Widget/SurvivalContentsWidget.cs (1)

50-57: Use constants for magic numbers

The WriteTo method contains several magic numbers that would benefit from being defined as constants with meaningful names to improve code readability and maintainability.

+    // Constants for survival content parameters
+    private const short DEFAULT_STORM_DECAY_RATE = 500;
+    private const short DEFAULT_STORM_RADIUS = 3000;
+    private const short DEFAULT_STORM_DAMAGE = 1000;
+    private const short DEFAULT_SAFE_ZONE_RADIUS = 1000;
+
     public void WriteTo(IByteWriter writer) {
-        writer.WriteShort(500);
-        writer.WriteShort(3000); // radius
-        writer.WriteShort(1000);
+        writer.WriteShort(DEFAULT_STORM_DECAY_RATE);
+        writer.WriteShort(DEFAULT_STORM_RADIUS);
+        writer.WriteShort(DEFAULT_STORM_DAMAGE);
         writer.Write<Vector3>(StormCenter);
-        writer.WriteShort(1000); // radius of center
+        writer.WriteShort(DEFAULT_SAFE_ZONE_RADIUS);
         writer.Write<Vector3>(SafeZoneCenter);
     }
Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs (1)

77-121: Refactor repetitive spawning logic.

The methods SpawnNpcs() and SpawnInteractObjects() share similar structures (removal of invalid IDs, do-while logic, etc.). Consolidate into a single method with parameters to reduce duplication and enhance maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a7ff8e and 81ff2dd.

📒 Files selected for processing (5)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (10 hunks)
  • Maple2.Server.Game/Model/Field/Entity/FieldNpcSpawnPoint.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Widget/SurvivalContentsWidget.cs (1 hunks)
  • Maple2.Server.Game/Packets/SurvivalEventPacket.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Maple2.Server.Game/Model/Field/Entity/FieldNpcSpawnPoint.cs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (16)
Maple2.Server.Game/Model/Field/Widget/SurvivalContentsWidget.cs (3)

18-19: Proper initialization of Vector3 fields

Good job initializing the Vector3 fields to prevent serializing uninitialized values. This addresses a previously identified issue.


22-36: Well-structured action handling

The switch-based approach for function dispatch is more efficient and type-safe than reflection-based method invocation. This is a good implementation that properly handles unknown functions with appropriate logging.


39-48: Document empty method implementations

The empty methods still lack documentation explaining their intended behavior or implementation plan.

 private void StormData(string step) {
-
+    // TODO: Implement storm data processing when step changes
+    // This should update StormCenter based on the current step
 }

 private void EnterStep(string step) {
+    // TODO: Implement actions when entering a new step
+    // This should handle any state changes needed when a player enters a step
 }

 private void ExitStep(string step) {
-
+    // TODO: Implement actions when exiting a step
+    // This should handle any cleanup or state changes when a player exits a step
 }
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (13)

36-36: New field for storing chest interactions.

This field adds storage for chest-type interactions, which is a necessary extension to keep field objects organized by their category.


40-41: Added storage for spawn point NPCs and spawn groups.

These concurrent dictionaries provide thread-safe storage for tracking spawn points and groups, which appears to be part of the field spawn groups feature implementation.


114-114: Modified SpawnPointId assignment logic.

Changed to use 0 as a default value when owner is null, which appears to be more appropriate than the previous implementation that likely used a global ID.


126-128: Made SpawnNpc method public.

The method's access modifier change from private to public enables external classes to create NPCs with SpawnPointNPC data, supporting the new spawn functionality.


354-363: New method to add and initialize spawn point NPCs.

This method properly follows the established pattern of other "Add" methods in the class and correctly initializes the spawn on creation.


365-372: Use atomic operations or locks to avoid race conditions.

If multiple threads call ToggleCombineSpawn with the same GroupId at roughly the same time, the code could create multiple FieldSpawnGroup instances. Consider using GetOrAdd or locks for a clean concurrency solution.


374-380: Added method to toggle NPC spawn points.

The method correctly checks if the spawn point exists before attempting to trigger it, following a defensive programming approach.


382-407: New method to spawn interact objects.

This method handles the creation of interactive objects based on metadata and adds them to the field. The implementation correctly:

  1. Validates input data before proceeding
  2. Creates appropriate objects with necessary properties
  3. Broadcasts the addition to all relevant clients

509-516: Create default properties based on requested type.

Currently, any missing field property is replaced with FieldPropertySightRange even if a different property was requested. This can lead to incorrect property usage. Consider properly instantiating the requested property type or throwing a descriptive error if unavailable.


657-676: Consider removing objects from fieldChests as well.

Your method removes the interact object only from fieldAdBalloons or fieldInteracts, ignoring the case in which an object resides in fieldChests. This discrepancy may lead to stale data. Update the removal logic to handle all dictionaries consistently.


678-693: Improved NPC removal logic.

The updated implementation:

  1. First checks if the NPC exists before scheduling removal
  2. Added a safety check to prevent double-removal
  3. Maintains the existing delayed removal functionality

This is a good improvement that prevents potential errors and race conditions.


737-739: Added chest objects loading for new players.

This change ensures that when new players enter the field, they correctly receive all chest interact objects, maintaining consistent state across all clients.


805-807: Added display of relevant timers.

This addition ensures that timers marked as displayable are properly shown to players, fixing the issue mentioned in the PR description where timers would only display when relevant.

Comment thread Maple2.Server.Game/Model/Field/Entity/FieldSpawnGroup.cs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants