diff --git a/rpc/src/core/base.ts b/rpc/src/core/base.ts index 5024a05..8d15bcc 100644 --- a/rpc/src/core/base.ts +++ b/rpc/src/core/base.ts @@ -51,6 +51,7 @@ export class RPCInstanceBase { to: RPCEnvironment, args: unknown[], player: number | null, + type: 'event' | 'broadcast' = 'event', ): RPCState { return { event, @@ -60,7 +61,7 @@ export class RPCInstanceBase { error: null, data: args, player, - type: 'event', + type, } } diff --git a/rpc/src/core/client.ts b/rpc/src/core/client.ts index d718973..43543fe 100644 --- a/rpc/src/core/client.ts +++ b/rpc/src/core/client.ts @@ -54,11 +54,18 @@ export class RPCInstanceClient extends RPCInstanceBase { const payload = this.accept(payloadRaw) if (!payload) return - if (payload.type === 'event') { + if (payload.type === 'event' || payload.type === 'broadcast') { if (payload.calledTo === 'client') { const response = await this.dispatch(this._emitterServer, payload) - emitNet(RPCEvents.LISTENER_CLIENT, stringify(response)) + if (payload.type === 'event') { + emitNet(RPCEvents.LISTENER_CLIENT, stringify(response)) + } else if (response.error) { + // nobody waits for a broadcast, so its failures only show up here + this.log( + `broadcast ${payload.event} failed: ${response.error.message}`, + ) + } } if (payload.calledTo === 'webview') { this._sendWebMessage({ diff --git a/rpc/src/core/server.ts b/rpc/src/core/server.ts index 977f2bf..f1def5f 100644 --- a/rpc/src/core/server.ts +++ b/rpc/src/core/server.ts @@ -61,7 +61,7 @@ export class RPCInstanceServer extends RPCInstanceBase { if (payload.type === 'event') { const response = await this.dispatch(emitter, payload, player) emitNet(RPCEvents.LISTENER_SERVER, player, stringify(response)) - } else { + } else if (payload.type === 'response') { this.settle(payload, player) } } @@ -108,7 +108,7 @@ export class RPCInstanceServer extends RPCInstanceBase { EventName extends keyof s.RPCEvents_ServerClient, Arguments extends Parameters, >(eventName: EventName, ...args: Arguments): Promise { - const payload = this.request(eventName, 'client', args, -1) + const payload = this.request(eventName, 'client', args, -1, 'broadcast') emitNet(RPCEvents.LISTENER_SERVER, -1, stringify(payload)) } diff --git a/rpc/src/utils/funcs.ts b/rpc/src/utils/funcs.ts index e2425a3..daf5e67 100644 --- a/rpc/src/utils/funcs.ts +++ b/rpc/src/utils/funcs.ts @@ -24,7 +24,7 @@ export function isRPCState(value: unknown): value is RPCState { return ( typeof v.event === 'string' && typeof v.uuid === 'string' && - (v.type === 'event' || v.type === 'response') && + (v.type === 'event' || v.type === 'response' || v.type === 'broadcast') && ENVIRONMENTS.includes(v.calledFrom) && ENVIRONMENTS.includes(v.calledTo) && (v.data === null || Array.isArray(v.data)) diff --git a/rpc/src/utils/types.ts b/rpc/src/utils/types.ts index f022201..ca3ba44 100644 --- a/rpc/src/utils/types.ts +++ b/rpc/src/utils/types.ts @@ -33,8 +33,14 @@ export type RPCConfig = { timeout?: number } -/** **Internal** */ -export type RPCEventType = 'event' | 'response' +/** + * **Internal** + * + * - `event`: call that expects a `response` + * - `response`: answer to an `event` + * - `broadcast`: one-way event, receivers do not reply + */ +export type RPCEventType = 'event' | 'response' | 'broadcast' /** * **Internal**