mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
doc: inline code documentation.
This commit is contained in:
@@ -7,27 +7,62 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Stage holds stage-specific information
|
||||
// Semaphore is a multiplayer coordination mechanism for quests and events.
|
||||
//
|
||||
// Despite the name, Semaphore is NOT an OS synchronization primitive (like sync.Semaphore).
|
||||
// Instead, it's a game-specific resource lock that coordinates multiplayer activities where:
|
||||
// - Players must acquire a semaphore before participating
|
||||
// - A limited number of participants are allowed (maxPlayers)
|
||||
// - The semaphore tracks both active and reserved participants
|
||||
//
|
||||
// Use Cases:
|
||||
// - Quest coordination: Ensures quest party size limits are enforced
|
||||
// - Event coordination: Raviente, VS Tournament, Diva Defense
|
||||
// - Global resources: Prevents multiple groups from starting conflicting events
|
||||
//
|
||||
// Semaphore vs Stage:
|
||||
// - Stages are spatial (game rooms, areas). Players in a stage can see each other.
|
||||
// - Semaphores are logical (coordination locks). Players in a semaphore are
|
||||
// participating in the same activity but may be in different stages.
|
||||
//
|
||||
// Example: Raviente Event
|
||||
// - Players acquire the Raviente semaphore to register for the event
|
||||
// - Multiple quest stages exist (preparation, phase 1, phase 2, carving)
|
||||
// - All participants share the same semaphore across different stages
|
||||
// - The semaphore enforces the 32-player limit across all stages
|
||||
//
|
||||
// Thread Safety:
|
||||
// Semaphore embeds sync.RWMutex. Use RLock for reads and Lock for writes.
|
||||
type Semaphore struct {
|
||||
sync.RWMutex
|
||||
sync.RWMutex // Protects semaphore state during concurrent access
|
||||
|
||||
// Stage ID string
|
||||
id_semaphore string
|
||||
// Semaphore identity
|
||||
id_semaphore string // Semaphore ID string (identifies the resource/activity)
|
||||
id uint32 // Numeric ID for client communication (auto-generated, starts at 7)
|
||||
|
||||
id uint32
|
||||
// Active participants
|
||||
clients map[*Session]uint32 // Sessions actively using this semaphore -> character ID
|
||||
|
||||
// Map of session -> charID.
|
||||
// These are clients that are CURRENTLY in the stage
|
||||
clients map[*Session]uint32
|
||||
// Reserved slots
|
||||
// Players who have acquired the semaphore but may not be actively in the stage yet.
|
||||
// The value is always nil; only the key (charID) matters. This is a set implementation.
|
||||
reservedClientSlots map[uint32]interface{} // Character ID -> nil (set of reserved IDs)
|
||||
|
||||
// Map of charID -> interface{}, only the key is used, value is always nil.
|
||||
reservedClientSlots map[uint32]interface{}
|
||||
|
||||
// Max Players for Semaphore
|
||||
maxPlayers uint16
|
||||
// Capacity
|
||||
maxPlayers uint16 // Maximum concurrent participants (e.g., 4 for quests, 32 for Raviente)
|
||||
}
|
||||
|
||||
// NewStage creates a new stage with intialized values.
|
||||
// NewSemaphore creates and initializes a new Semaphore for coordinating an activity.
|
||||
//
|
||||
// The semaphore is assigned an auto-incrementing ID from the server's semaphoreIndex.
|
||||
// IDs 0-6 are reserved, so the first semaphore gets ID 7.
|
||||
//
|
||||
// Parameters:
|
||||
// - s: The server (used to generate unique semaphore ID)
|
||||
// - ID: Semaphore ID string (identifies the activity/resource)
|
||||
// - MaxPlayers: Maximum participants allowed
|
||||
//
|
||||
// Returns a new Semaphore ready for client acquisition.
|
||||
func NewSemaphore(s *Server, ID string, MaxPlayers uint16) *Semaphore {
|
||||
sema := &Semaphore{
|
||||
id_semaphore: ID,
|
||||
@@ -55,7 +90,22 @@ func (s *Semaphore) BroadcastRavi(pkt mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
|
||||
// BroadcastMHF queues a MHFPacket to be sent to all sessions in the stage.
|
||||
// BroadcastMHF sends a packet to all active participants in the semaphore.
|
||||
//
|
||||
// This is used for event-wide announcements that all participants need to see,
|
||||
// regardless of which stage they're currently in. Examples:
|
||||
// - Raviente phase changes
|
||||
// - Tournament updates
|
||||
// - Event completion notifications
|
||||
//
|
||||
// Only active clients (in the clients map) receive broadcasts. Reserved clients
|
||||
// who haven't fully joined yet are excluded.
|
||||
//
|
||||
// Parameters:
|
||||
// - pkt: The MHFPacket to broadcast to all participants
|
||||
// - ignoredSession: Optional session to exclude from broadcast
|
||||
//
|
||||
// Thread Safety: Caller should hold semaphore lock when iterating clients.
|
||||
func (s *Semaphore) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
||||
// Broadcast the data.
|
||||
for session := range s.clients {
|
||||
|
||||
Reference in New Issue
Block a user