First version with variables that actually work

This commit is contained in:
David Négrier 2021-07-07 17:17:28 +02:00
parent 5116b82e77
commit e65e8b2097
11 changed files with 250 additions and 50 deletions

View file

@ -34,6 +34,8 @@ import { handleMenuItemRegistrationEvent, isMenuItemRegisterIframeEvent } from "
import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent";
import { isSetVariableIframeEvent, SetVariableEvent } from "./Events/SetVariableEvent";
type AnswererCallback<T extends keyof IframeQueryMap> = (query: IframeQueryMap[T]['query']) => IframeQueryMap[T]['answer']|PromiseLike<IframeQueryMap[T]['answer']>;
/**
* Listens to messages from iframes and turn those messages into easy to use observables.
* Also allows to send messages to those iframes.
@ -111,12 +113,10 @@ class IframeListener {
private sendPlayerMove: boolean = false;
// Note: we are forced to type this in "any" because of https://github.com/microsoft/TypeScript/issues/31904
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private answerers: any = {};
/*private answerers: {
[key in keyof IframeQueryMap]?: (query: IframeQueryMap[key]['query']) => IframeQueryMap[key]['answer']|PromiseLike<IframeQueryMap[key]['answer']>
} = {};*/
// Note: we are forced to type this in unknown and later cast with "as" because of https://github.com/microsoft/TypeScript/issues/31904
private answerers: {
[str in keyof IframeQueryMap]?: unknown
} = {};
init() {
@ -156,7 +156,7 @@ class IframeListener {
const queryId = payload.id;
const query = payload.query;
const answerer = this.answerers[query.type];
const answerer = this.answerers[query.type] as AnswererCallback<keyof IframeQueryMap> | undefined;
if (answerer === undefined) {
const errorMsg = 'The iFrame sent a message of type "'+query.type+'" but there is no service configured to answer these messages.';
console.error(errorMsg);
@ -432,7 +432,7 @@ class IframeListener {
* @param key The "type" of the query we are answering
* @param callback
*/
public registerAnswerer<T extends keyof IframeQueryMap>(key: T, callback: (query: IframeQueryMap[T]['query']) => IframeQueryMap[T]['answer']|PromiseLike<IframeQueryMap[T]['answer']> ): void {
public registerAnswerer<T extends keyof IframeQueryMap>(key: T, callback: AnswererCallback<T> ): void {
this.answerers[key] = callback;
}

View file

@ -31,6 +31,7 @@ export enum EventMessage {
TELEPORT = "teleport",
USER_MESSAGE = "user-message",
START_JITSI_ROOM = "start-jitsi-room",
SET_VARIABLE = "set-variable",
}
export interface PointInterface {
@ -105,6 +106,7 @@ export interface RoomJoinedMessageInterface {
//users: MessageUserPositionInterface[],
//groups: GroupCreatedUpdatedMessageInterface[],
items: { [itemId: number]: unknown };
variables: Map<string, unknown>;
}
export interface PlayGlobalMessageInterface {

View file

@ -165,6 +165,9 @@ export class RoomConnection implements RoomConnection {
} else if (subMessage.hasEmoteeventmessage()) {
const emoteMessage = subMessage.getEmoteeventmessage() as EmoteEventMessage;
emoteEventStream.fire(emoteMessage.getActoruserid(), emoteMessage.getEmote());
} else if (subMessage.hasVariablemessage()) {
event = EventMessage.SET_VARIABLE;
payload = subMessage.getVariablemessage();
} else {
throw new Error("Unexpected batch message type");
}
@ -174,6 +177,7 @@ export class RoomConnection implements RoomConnection {
}
}
} else if (message.hasRoomjoinedmessage()) {
console.error('COUCOU')
const roomJoinedMessage = message.getRoomjoinedmessage() as RoomJoinedMessage;
const items: { [itemId: number]: unknown } = {};
@ -181,6 +185,11 @@ export class RoomConnection implements RoomConnection {
items[item.getItemid()] = JSON.parse(item.getStatejson());
}
const variables = new Map<string, unknown>();
for (const variable of roomJoinedMessage.getVariableList()) {
variables.set(variable.getName(), JSON.parse(variable.getValue()));
}
this.userId = roomJoinedMessage.getCurrentuserid();
this.tags = roomJoinedMessage.getTagList();
@ -188,6 +197,7 @@ export class RoomConnection implements RoomConnection {
connection: this,
room: {
items,
variables,
} as RoomJoinedMessageInterface,
});
} else if (message.hasWorldfullmessage()) {
@ -634,6 +644,18 @@ export class RoomConnection implements RoomConnection {
});
}
public onSetVariable(callback: (name: string, value: unknown) => void): void {
this.onMessage(EventMessage.SET_VARIABLE, (message: VariableMessage) => {
const name = message.getName();
const serializedValue = message.getValue();
let value: unknown = undefined;
if (serializedValue) {
value = JSON.parse(serializedValue);
}
callback(name, value);
});
}
public hasTag(tag: string): boolean {
return this.tags.includes(tag);
}

View file

@ -707,7 +707,7 @@ export class GameScene extends DirtyScene {
});
// Set up variables manager
this.sharedVariablesManager = new SharedVariablesManager(this.connection, this.gameMap);
this.sharedVariablesManager = new SharedVariablesManager(this.connection, this.gameMap, onConnect.room.variables);
//this.initUsersPosition(roomJoinedMessage.users);
this.connectionAnswerPromiseResolve(onConnect.room);

View file

@ -7,6 +7,7 @@ import type {Subscription} from "rxjs";
import type {GameMap} from "./GameMap";
import type {ITile, ITiledMapObject} from "../Map/ITiledMap";
import type {Var} from "svelte/types/compiler/interfaces";
import {init} from "svelte/internal";
interface Variable {
defaultValue: unknown,
@ -18,7 +19,7 @@ export class SharedVariablesManager {
private _variables = new Map<string, unknown>();
private variableObjects: Map<string, Variable>;
constructor(private roomConnection: RoomConnection, private gameMap: GameMap) {
constructor(private roomConnection: RoomConnection, private gameMap: GameMap, serverVariables: Map<string, unknown>) {
// We initialize the list of variable object at room start. The objects cannot be edited later
// (otherwise, this would cause a security issue if the scripting API can edit this list of objects)
this.variableObjects = SharedVariablesManager.findVariablesInMap(gameMap);
@ -28,6 +29,22 @@ export class SharedVariablesManager {
this._variables.set(name, variableObject.defaultValue);
}
// Override default values with the variables from the server:
for (const [name, value] of serverVariables) {
this._variables.set(name, value);
}
roomConnection.onSetVariable((name, value) => {
console.log('Set Variable received from server');
this._variables.set(name, value);
// On server change, let's notify the iframes
iframeListener.setVariable({
key: name,
value: value,
})
});
// When a variable is modified from an iFrame
iframeListener.registerAnswerer('setVariable', (event) => {
const key = event.key;
@ -48,7 +65,8 @@ export class SharedVariablesManager {
}
this._variables.set(key, event.value);
// TODO: dispatch to the room connection.
// Dispatch to the room connection.
this.roomConnection.emitSetVariableEvent(key, event.value);
});
}