added trigger message code
This commit is contained in:
parent
3cf0a9ee84
commit
5472d220ba
@ -87,3 +87,23 @@ WA.ui.registerMenuCommand("test", () => {
|
||||
<div class="col">
|
||||
<img src="https://workadventu.re/img/docs/menu-command.png" class="figure-img img-fluid rounded" alt="" />
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
### Awaiting User Confirmation (with space bar)
|
||||
|
||||
```typescript
|
||||
triggerMessage(message: string): TriggerMessage
|
||||
```
|
||||
|
||||
Displays a message at the bottom of the screen (that will disappear when space bar is pressed).
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
const triggerMessage = WA.ui.triggerMessage("press 'space' to confirm");
|
||||
setTimeout(()=>{
|
||||
// later
|
||||
triggerMessage.remove();
|
||||
},1000)
|
||||
```
|
@ -18,6 +18,7 @@ import type { PlaySoundEvent } from "./PlaySoundEvent";
|
||||
import type { MenuItemClickedEvent } from "./ui/MenuItemClickedEvent";
|
||||
import type { MenuItemRegisterEvent } from './ui/MenuItemRegisterEvent';
|
||||
import type { HasPlayerMovedEvent } from "./HasPlayerMovedEvent";
|
||||
import type { MessageReferenceEvent, TriggerMessageEvent } from '../iframe/TriggerMessageEvent';
|
||||
|
||||
|
||||
export interface TypedMessageEvent<T> extends MessageEvent {
|
||||
@ -49,6 +50,9 @@ export type IframeEventMap = {
|
||||
stopSound: null,
|
||||
getState: undefined,
|
||||
registerMenuCommand: MenuItemRegisterEvent
|
||||
|
||||
triggerMessage: TriggerMessageEvent
|
||||
removeTriggerMessage: MessageReferenceEvent
|
||||
}
|
||||
export interface IframeEvent<T extends keyof IframeEventMap> {
|
||||
type: T;
|
||||
@ -68,6 +72,7 @@ export interface IframeResponseEventMap {
|
||||
hasPlayerMoved: HasPlayerMovedEvent
|
||||
dataLayer: DataLayerEvent
|
||||
menuItemClicked: MenuItemClickedEvent
|
||||
messageTriggered: MessageReferenceEvent
|
||||
}
|
||||
export interface IframeResponseEvent<T extends keyof IframeResponseEventMap> {
|
||||
type: T;
|
||||
|
21
front/src/Api/Events/ui/TriggerMessageEvent.ts
Normal file
21
front/src/Api/Events/ui/TriggerMessageEvent.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import * as tg from "generic-type-guard";
|
||||
|
||||
export const triggerMessage = "triggerMessage"
|
||||
export const removeTriggerMessage = "removeTriggerMessage"
|
||||
|
||||
export const isTriggerMessageEvent = new tg.IsInterface().withProperties({
|
||||
message: tg.isString,
|
||||
uuid: tg.isString
|
||||
}).get()
|
||||
|
||||
|
||||
export type TriggerMessageEvent = tg.GuardedType<typeof isTriggerMessageEvent>;
|
||||
|
||||
|
||||
export const isMessageReferenceEvent =
|
||||
new tg.IsInterface().withProperties({
|
||||
uuid: tg.isString
|
||||
}).get();
|
||||
|
||||
|
||||
export type MessageReferenceEvent = tg.GuardedType<typeof isMessageReferenceEvent>;
|
42
front/src/Api/Events/ui/TriggerMessageEventHandler.ts
Normal file
42
front/src/Api/Events/ui/TriggerMessageEventHandler.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Subject } from 'rxjs';
|
||||
import { iframeListener } from '../../IframeListener';
|
||||
import { isMessageReferenceEvent, isTriggerMessageEvent, MessageReferenceEvent, removeTriggerMessage, triggerMessage, TriggerMessageEvent } from './TriggerMessageEvent';
|
||||
import * as tg from "generic-type-guard";
|
||||
export function sendMessageTriggeredEvent(uuid: string) {
|
||||
iframeListener.postMessage({
|
||||
'type': 'messageTriggered',
|
||||
'data': {
|
||||
uuid,
|
||||
} as MessageReferenceEvent
|
||||
});
|
||||
}
|
||||
|
||||
const _triggerMessageEvent: Subject<TriggerMessageEvent> = new Subject();
|
||||
const _removeTriggerMessageEvent: Subject<MessageReferenceEvent> = new Subject();
|
||||
|
||||
export const triggerMessageEvent = _triggerMessageEvent.asObservable();
|
||||
|
||||
export const removeTriggerMessageEvent = _removeTriggerMessageEvent.asObservable();
|
||||
|
||||
const isTriggerMessageEventObject = new tg.IsInterface().withProperties({
|
||||
type: tg.isSingletonString(triggerMessage),
|
||||
data: isTriggerMessageEvent
|
||||
}).get()
|
||||
const isTriggerMessageRemoveEventObject = new tg.IsInterface().withProperties({
|
||||
type: tg.isSingletonString(removeTriggerMessage),
|
||||
data: isMessageReferenceEvent
|
||||
}).get()
|
||||
|
||||
|
||||
export const isTriggerMessageHandlerEvent = tg.isUnion(isTriggerMessageEventObject, isTriggerMessageRemoveEventObject)
|
||||
|
||||
|
||||
|
||||
|
||||
export function triggerMessageEventHandler(event: tg.GuardedType<typeof isTriggerMessageHandlerEvent>) {
|
||||
if (isTriggerMessageEventObject(event)) {
|
||||
_triggerMessageEvent.next(event.data)
|
||||
} else if (isTriggerMessageRemoveEventObject(event)) {
|
||||
_removeTriggerMessageEvent.next(event.data)
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ import type {GameStateEvent} from "./Events/GameStateEvent";
|
||||
import type { HasPlayerMovedEvent } from "./Events/HasPlayerMovedEvent";
|
||||
import { isLoadPageEvent } from "./Events/LoadPageEvent";
|
||||
import { handleMenuItemRegistrationEvent, isMenuItemRegisterIframeEvent } from "./Events/ui/MenuItemRegisterEvent";
|
||||
import { isTriggerMessageHandlerEvent, triggerMessageEventHandler } from './Events/ui/TriggerMessageEventHandler';
|
||||
|
||||
/**
|
||||
* Listens to messages from iframes and turn those messages into easy to use observables.
|
||||
@ -190,6 +191,8 @@ class IframeListener {
|
||||
this._unregisterMenuCommandStream.next(data);
|
||||
})
|
||||
handleMenuItemRegistrationEvent(payload.data)
|
||||
} else if (isTriggerMessageHandlerEvent(payload)) {
|
||||
triggerMessageEventHandler(payload)
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
51
front/src/Api/iframe/Ui/TriggerMessage.ts
Normal file
51
front/src/Api/iframe/Ui/TriggerMessage.ts
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
import { removeTriggerMessage, triggerMessage, TriggerMessageEvent } from '../../Events/ui/TriggerMessageEvent';
|
||||
import { sendToWorkadventure } from '../IframeApiContribution';
|
||||
function uuidv4() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||
const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
export let triggerMessageInstance: TriggerMessage | undefined = undefined
|
||||
|
||||
|
||||
|
||||
export class TriggerMessage {
|
||||
uuid: string
|
||||
|
||||
constructor(private message: string, private callback: () => void) {
|
||||
this.uuid = uuidv4()
|
||||
if (triggerMessageInstance) {
|
||||
triggerMessageInstance.remove();
|
||||
}
|
||||
triggerMessageInstance = this;
|
||||
this.create();
|
||||
}
|
||||
|
||||
create(): this {
|
||||
sendToWorkadventure({
|
||||
type: triggerMessage,
|
||||
data: {
|
||||
message: this.message,
|
||||
uuid: this.uuid
|
||||
} as TriggerMessageEvent
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
remove() {
|
||||
sendToWorkadventure({
|
||||
type: removeTriggerMessage,
|
||||
data: {
|
||||
uuid: this.uuid
|
||||
} as TriggerMessageEvent
|
||||
})
|
||||
triggerMessageInstance = undefined
|
||||
}
|
||||
|
||||
trigger() {
|
||||
this.callback();
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
import { isButtonClickedEvent } from '../Events/ButtonClickedEvent';
|
||||
import { isMenuItemClickedEvent } from '../Events/ui/MenuItemClickedEvent';
|
||||
import type { MenuItemRegisterEvent } from '../Events/ui/MenuItemRegisterEvent';
|
||||
import { isMessageReferenceEvent } from '../Events/ui/TriggerMessageEvent';
|
||||
import { IframeApiContribution, sendToWorkadventure } from './IframeApiContribution';
|
||||
import { apiCallback } from "./registeredCallbacks";
|
||||
import type { ButtonClickedCallback, ButtonDescriptor } from "./Ui/ButtonDescriptor";
|
||||
import { Popup } from "./Ui/Popup";
|
||||
import { TriggerMessage, triggerMessageInstance } from './Ui/TriggerMessage';
|
||||
|
||||
let popupId = 0;
|
||||
const popups: Map<number, Popup> = new Map<number, Popup>();
|
||||
@ -12,18 +13,10 @@ const popupCallbacks: Map<number, Map<number, ButtonClickedCallback>> = new Map<
|
||||
|
||||
const menuCallbacks: Map<string, (command: string) => void> = new Map()
|
||||
|
||||
interface ZonedPopupOptions {
|
||||
zone: string
|
||||
objectLayerName?: string,
|
||||
popupText: string,
|
||||
delay?: number
|
||||
popupOptions: Array<ButtonDescriptor>
|
||||
}
|
||||
|
||||
|
||||
class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventureUiCommands> {
|
||||
|
||||
callbacks = [apiCallback({
|
||||
callbacks = [
|
||||
apiCallback({
|
||||
type: "buttonClickedEvent",
|
||||
typeChecker: isButtonClickedEvent,
|
||||
callback: (payloadData) => {
|
||||
@ -46,7 +39,15 @@ class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventureUiComma
|
||||
callback(event.menuItem)
|
||||
}
|
||||
}
|
||||
})];
|
||||
}),
|
||||
apiCallback({
|
||||
type: "messageTriggered",
|
||||
typeChecker: isMessageReferenceEvent,
|
||||
callback: event => {
|
||||
triggerMessageInstance?.trigger();
|
||||
}
|
||||
})
|
||||
];
|
||||
|
||||
|
||||
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup {
|
||||
@ -101,6 +102,9 @@ class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventureUiComma
|
||||
removeBubble(): void {
|
||||
sendToWorkadventure({ 'type': 'removeBubble', data: null });
|
||||
}
|
||||
triggerMessage(message: string, callback: () => void): TriggerMessage {
|
||||
return new TriggerMessage(message, callback);
|
||||
}
|
||||
}
|
||||
|
||||
export default new WorkAdventureUiCommands();
|
||||
|
@ -64,7 +64,8 @@ import type {
|
||||
ITiledMapLayerProperty,
|
||||
ITiledMapObject,
|
||||
ITiledMapTileLayer,
|
||||
ITiledTileSet } from "../Map/ITiledMap";
|
||||
ITiledTileSet
|
||||
} from "../Map/ITiledMap";
|
||||
import { MenuScene, MenuSceneName } from '../Menu/MenuScene';
|
||||
import { PlayerAnimationDirections } from "../Player/Animation";
|
||||
import { hasMovedEventName, Player, requestEmoteEventName } from "../Player/Player";
|
||||
@ -94,6 +95,7 @@ import type { HasPlayerMovedEvent } from '../../Api/Events/HasPlayerMovedEvent';
|
||||
|
||||
import AnimatedTiles from "phaser-animated-tiles";
|
||||
import { soundManager } from "./SoundManager";
|
||||
import { removeTriggerMessageEvent, sendMessageTriggeredEvent, triggerMessageEvent } from '../../Api/Events/ui/TriggerMessageEventHandler';
|
||||
|
||||
export interface GameSceneInitInterface {
|
||||
initPosition: PointInterface | null,
|
||||
@ -959,6 +961,18 @@ ${escapedMessage}
|
||||
})
|
||||
}));
|
||||
|
||||
|
||||
this.iframeSubscriptionList.push(triggerMessageEvent.subscribe(message => {
|
||||
layoutManager.addActionButton(message.uuid, message.message, () => {
|
||||
sendMessageTriggeredEvent(message.uuid)
|
||||
layoutManager.removeActionButton(message.uuid, this.userInputManager);
|
||||
}, this.userInputManager);
|
||||
}))
|
||||
|
||||
this.iframeSubscriptionList.push(removeTriggerMessageEvent.subscribe(message => {
|
||||
layoutManager.removeActionButton(message.uuid, this.userInputManager);
|
||||
}))
|
||||
|
||||
}
|
||||
|
||||
private setPropertyLayer(layerName: string, propertyName: string, propertyValue: string | number | boolean | undefined): void {
|
||||
|
@ -1,3 +1,4 @@
|
||||
///<reference path="../../front/src/iframe_api.ts" />
|
||||
console.log('SCRIPT LAUNCHED');
|
||||
//WA.sendChatMessage('Hi, my name is Poly and I repeat what you say!', 'Poly Parrot');
|
||||
var isFirstTimeTuto = false;
|
||||
@ -77,3 +78,10 @@ WA.room.onLeaveZone('popupZone', () => {
|
||||
if(popUpExplanation !== undefined) popUpExplanation.close();
|
||||
WA.ui.removeBubble();
|
||||
})
|
||||
|
||||
const message = WA.ui.triggerMessage("testMessage", () => {
|
||||
WA.chat.sendChatMessage("triggered", "triggerbot");
|
||||
})
|
||||
setTimeout(() => {
|
||||
message.remove();
|
||||
}, 5000)
|
Loading…
Reference in New Issue
Block a user