Merge branch 'develop' of github.com:thecodingmachine/workadventure into GlobalMessageToWorld

This commit is contained in:
GRL 2021-07-23 14:10:43 +02:00
commit ba6e6235d6
6 changed files with 77 additions and 29 deletions

View file

@ -327,6 +327,11 @@ export class GameRoom {
const readableBy = variableManager.setVariable(name, value, user); const readableBy = variableManager.setVariable(name, value, user);
// If the variable was not changed, let's not dispatch anything.
if (readableBy === false) {
return;
}
// TODO: should we batch those every 100ms? // TODO: should we batch those every 100ms?
const variableMessage = new VariableWithTagMessage(); const variableMessage = new VariableWithTagMessage();
variableMessage.setName(name); variableMessage.setName(name);

View file

@ -51,6 +51,17 @@ export class VariablesManager {
} }
const variables = await variablesRepository.loadVariables(this.roomUrl); const variables = await variablesRepository.loadVariables(this.roomUrl);
for (const key in variables) { for (const key in variables) {
// Let's only set variables if they are in the map (if the map has changed, maybe stored variables do not exist anymore)
if (this.variableObjects) {
const variableObject = this.variableObjects.get(key);
if (variableObject === undefined) {
continue;
}
if (!variableObject.persist) {
continue;
}
}
this._variables.set(key, variables[key]); this._variables.set(key, variables[key]);
} }
return this; return this;
@ -134,10 +145,21 @@ export class VariablesManager {
return variable; return variable;
} }
setVariable(name: string, value: string, user: User): string | undefined { /**
* Sets the variable.
*
* Returns who is allowed to read the variable (the readableby property) or "undefined" if anyone can read it.
* Also, returns "false" if the variable was not modified (because we set it to the value it already has)
*
* @param name
* @param value
* @param user
*/
setVariable(name: string, value: string, user: User): string | undefined | false {
let readableBy: string | undefined; let readableBy: string | undefined;
let variableObject: Variable | undefined;
if (this.variableObjects) { if (this.variableObjects) {
const variableObject = this.variableObjects.get(name); variableObject = this.variableObjects.get(name);
if (variableObject === undefined) { if (variableObject === undefined) {
throw new Error('Trying to set a variable "' + name + '" that is not defined as an object in the map.'); throw new Error('Trying to set a variable "' + name + '" that is not defined as an object in the map.');
} }
@ -159,10 +181,19 @@ export class VariablesManager {
readableBy = variableObject.readableBy; readableBy = variableObject.readableBy;
} }
// If the value is not modified, return false
if (this._variables.get(name) === value) {
return false;
}
this._variables.set(name, value); this._variables.set(name, value);
variablesRepository
.saveVariable(this.roomUrl, name, value) if (variableObject !== undefined && variableObject.persist) {
.catch((e) => console.error("Error while saving variable in Redis:", e)); variablesRepository
.saveVariable(this.roomUrl, name, value)
.catch((e) => console.error("Error while saving variable in Redis:", e));
}
return readableBy; return readableBy;
} }

View file

@ -55,10 +55,10 @@ Start by testing this with a simple message sent to the chat.
**script.js** **script.js**
```javascript ```javascript
WA.sendChatMessage('Hello world', 'Mr Robot'); WA.chat.sendChatMessage('Hello world', 'Mr Robot');
``` ```
The `WA` objects contains a number of useful methods enabling you to interact with the WorkAdventure game. For instance, `WA.sendChatMessage` opens the chat and adds a message in it. The `WA` objects contains a number of useful methods enabling you to interact with the WorkAdventure game. For instance, `WA.chat.sendChatMessage` opens the chat and adds a message in it.
In your browser console, when you open the map, the chat message should be displayed right away. In your browser console, when you open the map, the chat message should be displayed right away.

View file

@ -33,10 +33,11 @@ import type { HasPlayerMovedEvent } from "./Events/HasPlayerMovedEvent";
import { isLoadPageEvent } from "./Events/LoadPageEvent"; import { isLoadPageEvent } from "./Events/LoadPageEvent";
import { handleMenuItemRegistrationEvent, isMenuItemRegisterIframeEvent } from "./Events/ui/MenuItemRegisterEvent"; import { handleMenuItemRegistrationEvent, isMenuItemRegisterIframeEvent } from "./Events/ui/MenuItemRegisterEvent";
import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent"; import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent";
import { isSetVariableIframeEvent, SetVariableEvent } from "./Events/SetVariableEvent"; import type { SetVariableEvent } from "./Events/SetVariableEvent";
type AnswererCallback<T extends keyof IframeQueryMap> = ( type AnswererCallback<T extends keyof IframeQueryMap> = (
query: IframeQueryMap[T]["query"] query: IframeQueryMap[T]["query"],
source: MessageEventSource | null
) => IframeQueryMap[T]["answer"] | PromiseLike<IframeQueryMap[T]["answer"]>; ) => IframeQueryMap[T]["answer"] | PromiseLike<IframeQueryMap[T]["answer"]>;
/** /**
@ -197,7 +198,7 @@ class IframeListener {
}; };
try { try {
Promise.resolve(answerer(query.data)) Promise.resolve(answerer(query.data, message.source))
.then((value) => { .then((value) => {
iframe?.contentWindow?.postMessage( iframe?.contentWindow?.postMessage(
{ {
@ -212,21 +213,6 @@ class IframeListener {
} catch (reason) { } catch (reason) {
errorHandler(reason); errorHandler(reason);
} }
if (isSetVariableIframeEvent(payload.query)) {
// Let's dispatch the message to the other iframes
for (iframe of this.iframes) {
if (iframe.contentWindow !== message.source) {
iframe.contentWindow?.postMessage(
{
type: "setVariable",
data: payload.query.data,
},
"*"
);
}
}
}
} else if (isIframeEventWrapper(payload)) { } else if (isIframeEventWrapper(payload)) {
if (payload.type === "showLayer" && isLayerEvent(payload.data)) { if (payload.type === "showLayer" && isLayerEvent(payload.data)) {
this._showLayerStream.next(payload.data); this._showLayerStream.next(payload.data);
@ -457,6 +443,24 @@ class IframeListener {
public unregisterAnswerer(key: keyof IframeQueryMap): void { public unregisterAnswerer(key: keyof IframeQueryMap): void {
delete this.answerers[key]; delete this.answerers[key];
} }
dispatchVariableToOtherIframes(key: string, value: unknown, source: MessageEventSource | null) {
// Let's dispatch the message to the other iframes
for (const iframe of this.iframes) {
if (iframe.contentWindow !== source) {
iframe.contentWindow?.postMessage(
{
type: "setVariable",
data: {
key,
value,
},
},
"*"
);
}
}
}
} }
export const iframeListener = new IframeListener(); export const iframeListener = new IframeListener();

View file

@ -23,11 +23,11 @@ export const initVariables = (_variables: Map<string, unknown>): void => {
setVariableResolvers.subscribe((event) => { setVariableResolvers.subscribe((event) => {
const oldValue = variables.get(event.key); const oldValue = variables.get(event.key);
// If we are setting the same value, no need to do anything. // If we are setting the same value, no need to do anything.
if (oldValue === event.value) { // No need to do this check since it is already performed in SharedVariablesManager
/*if (JSON.stringify(oldValue) === JSON.stringify(event.value)) {
return; return;
} }*/
variables.set(event.key, event.value); variables.set(event.key, event.value);
const subject = variableSubscribers.get(event.key); const subject = variableSubscribers.get(event.key);

View file

@ -54,7 +54,7 @@ export class SharedVariablesManager {
}); });
// When a variable is modified from an iFrame // When a variable is modified from an iFrame
iframeListener.registerAnswerer("setVariable", (event) => { iframeListener.registerAnswerer("setVariable", (event, source) => {
const key = event.key; const key = event.key;
const object = this.variableObjects.get(key); const object = this.variableObjects.get(key);
@ -82,10 +82,18 @@ export class SharedVariablesManager {
throw new Error(errMsg); throw new Error(errMsg);
} }
// Let's stop any propagation of the value we set is the same as the existing value.
if (JSON.stringify(event.value) === JSON.stringify(this._variables.get(key))) {
return;
}
this._variables.set(key, event.value); this._variables.set(key, event.value);
// Dispatch to the room connection. // Dispatch to the room connection.
this.roomConnection.emitSetVariableEvent(key, event.value); this.roomConnection.emitSetVariableEvent(key, event.value);
// Dispatch to other iframes
iframeListener.dispatchVariableToOtherIframes(key, event.value, source);
}); });
} }