import MessagingEvent , { isSubscriptionMessage , ISubscriptionMessage } from "../messaging/MessagingEvent" ; import { getGlobalRemote , IS_CLIENT , isLuaTable } from "../internal" ; import ServerEvent from "./ServerEvent" ; const Players = game . GetService ( "Players" ) ; export interface IMessage < TArgs > { InnerData : TArgs ; TargetId ? : number ; TargetIds ? : Array < number > ; } export interface ISubscriptionTargetedMessage extends ISubscriptionMessage { Data : IMessage < any > ; } function isTargetedSubscriptionMessage ( value ) { if ( isSubscriptionMessage ( value ) ) { if ( isLuaTable ( value . Data ) ) { return value . Data . has ( "InnerData" ) ; } } return false ; } /**
 * Similar to a ServerEvent, but works across all servers.
 */ export default class ServerMessagingEvent < TArgs extends unknown [ ] = unknown [ ] > { private readonly instance : ServerEvent < [ ] , TArgs > ; private readonly event : MessagingEvent ; private readonly eventHandler : RBXScriptConnection ; constructor ( name ) { this . instance = new ServerEvent ( getGlobalRemote ( name ) ) ; this . event = new MessagingEvent ( name ) ; assert ( ! IS_CLIENT , "Cannot create a Net.GlobalServerEvent on the Client!" ) ; this . eventHandler = this . event . Connect ( ( message ) => { if ( isTargetedSubscriptionMessage ( message ) ) { this . recievedMessage ( message . Data ) ; } else { warn ( `[rbx-net] Recieved malformed message for ServerGameEvent: ${ name }` ) ; } } ) ; } private getPlayersMatchingId ( matching ) { if ( typeIs ( matching , "number" ) ) { return Players . GetPlayerByUserId ( matching ) ; } else { const players = new Array < Player > ( ) ; for ( const id of matching ) { const player = Players . GetPlayerByUserId ( id ) ; if ( player ) { players . push ( player ) ; } } return players ; } } private recievedMessage ( message ) { if ( message . TargetIds ) { const players = this . getPlayersMatchingId ( message . TargetIds ) ; if ( players ) { this . instance . SendToPlayers ( players as Array < Player > , ... message . InnerData ) ; } } else if ( message . TargetId !== undefined ) { const player = this . getPlayersMatchingId ( message . TargetId ) ; if ( player ) { this . instance . SendToPlayer ( player as Player , ... message . InnerData ) ; } } else { this . instance . SendToAllPlayers ( ... message . InnerData ) ; } } /**
     * Disconnects this event handler
     *
     * **NOTE**: Once disconnected, you will have to re-create this object to recieve the messages again.
     */ public Disconnect ( ) { this . eventHandler . Disconnect ( ) ; } param args public SendToAllServers ( ... args ) { this . event . SendToAllServers ( { data : [ ... args ] } ) ; } param jobId param args public SendToServer ( jobId , ... args ) { this . event . SendToServer ( jobId , { data : [ ... args ] } ) ; } param userId param args public SendToPlayer ( userId , ... args ) { const player = Players . GetPlayerByUserId ( userId ) ; if ( player ) { this . instance . SendToPlayer ( player , ... args ) ; } else { this . event . SendToAllServers ( { data : [ ... args ] , targetId : userId } ) ; } } param userIds param args public SendToPlayers ( userIds , ... args ) { for ( const targetId of userIds ) { const player = Players . GetPlayerByUserId ( targetId ) ; if ( player ) { this . instance . SendToPlayer ( player , ... args ) ; userIds . remove ( targetId ) ; } } if ( userIds . size ( ) > 0 ) { this . event . SendToAllServers ( { data : [ ... args ] , targetIds : userIds } ) ; } } }