Twemoji Svelte
This commit is contained in:
parent
5497253e38
commit
bb3b58d8bf
@ -26,6 +26,7 @@
|
|||||||
import {soundPlayingStore} from "../Stores/SoundPlayingStore";
|
import {soundPlayingStore} from "../Stores/SoundPlayingStore";
|
||||||
import ErrorDialog from "./UI/ErrorDialog.svelte";
|
import ErrorDialog from "./UI/ErrorDialog.svelte";
|
||||||
import Menu from "./Menu/Menu.svelte";
|
import Menu from "./Menu/Menu.svelte";
|
||||||
|
import EmoteMenu from "./EmoteMenu/EmoteMenu.svelte";
|
||||||
import VideoOverlay from "./Video/VideoOverlay.svelte";
|
import VideoOverlay from "./Video/VideoOverlay.svelte";
|
||||||
import {gameOverlayVisibilityStore} from "../Stores/GameOverlayStoreVisibility";
|
import {gameOverlayVisibilityStore} from "../Stores/GameOverlayStoreVisibility";
|
||||||
import AdminMessage from "./TypeMessage/BanMessage.svelte";
|
import AdminMessage from "./TypeMessage/BanMessage.svelte";
|
||||||
@ -111,6 +112,9 @@
|
|||||||
<Menu></Menu>
|
<Menu></Menu>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if $gameOverlayVisibilityStore}
|
||||||
|
<EmoteMenu></EmoteMenu>
|
||||||
|
{/if}
|
||||||
{#if $gameOverlayVisibilityStore}
|
{#if $gameOverlayVisibilityStore}
|
||||||
<div>
|
<div>
|
||||||
<VideoOverlay></VideoOverlay>
|
<VideoOverlay></VideoOverlay>
|
||||||
|
65
front/src/Components/EmoteMenu/EmoteMenu.svelte
Normal file
65
front/src/Components/EmoteMenu/EmoteMenu.svelte
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<script lang="typescript">
|
||||||
|
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
import type { Unsubscriber } from "svelte/store";
|
||||||
|
import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore";
|
||||||
|
import { onDestroy, onMount } from "svelte";
|
||||||
|
import { EmojiButton } from '@joeattardi/emoji-button';
|
||||||
|
|
||||||
|
let emojiContainer: HTMLElement;
|
||||||
|
let picker: EmojiButton;
|
||||||
|
|
||||||
|
let unsubscriber: Unsubscriber | null = null;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
picker = new EmojiButton({
|
||||||
|
rootElement: emojiContainer,
|
||||||
|
style : 'twemoji',
|
||||||
|
styleProperties: {
|
||||||
|
'--font': 'Press Start 2P'
|
||||||
|
},
|
||||||
|
showSearch : false
|
||||||
|
});
|
||||||
|
|
||||||
|
picker.on("emoji", (selection) => {
|
||||||
|
emoteStore.set(selection.emoji);
|
||||||
|
});
|
||||||
|
|
||||||
|
picker.on("hidden", () => {
|
||||||
|
emoteMenuStore.set(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
unsubscriber = emoteMenuStore.subscribe(() => {
|
||||||
|
if (get(emoteMenuStore)) {
|
||||||
|
picker.showPicker(emojiContainer);
|
||||||
|
} else {
|
||||||
|
picker.hidePicker();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
if (unsubscriber) {
|
||||||
|
unsubscriber();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="emote-menu-container">
|
||||||
|
<div class="emote-menu" bind:this={emojiContainer}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.emote-menu-container {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emote-menu {
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,68 +0,0 @@
|
|||||||
import DOMElement = Phaser.GameObjects.DOMElement;
|
|
||||||
import { DEPTH_UI_INDEX } from "../Game/DepthIndexes";
|
|
||||||
import { waScaleManager } from "../Services/WaScaleManager";
|
|
||||||
import type { UserInputManager } from "../UserInput/UserInputManager";
|
|
||||||
import { EmojiButton } from '@joeattardi/emoji-button';
|
|
||||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
|
||||||
|
|
||||||
export const EmoteMenuClickEvent = "emoteClick";
|
|
||||||
|
|
||||||
export class EmoteMenu extends Phaser.GameObjects.Container {
|
|
||||||
private resizeCallback: OmitThisParameter<() => void>;
|
|
||||||
private container: DOMElement;
|
|
||||||
private picker: EmojiButton;
|
|
||||||
|
|
||||||
constructor(scene: Phaser.Scene, x: number, y: number, private userInputManager: UserInputManager) {
|
|
||||||
super(scene, x, y);
|
|
||||||
this.setDepth(DEPTH_UI_INDEX);
|
|
||||||
this.scene.add.existing(this);
|
|
||||||
this.container = new DOMElement(this.scene, 0, 0, "div", "", "");
|
|
||||||
this.container.setClassName("emoji-container");
|
|
||||||
const scalingFactor = waScaleManager.uiScalingFactor * 0.5;
|
|
||||||
this.container.setScale(scalingFactor);
|
|
||||||
this.add(this.container);
|
|
||||||
const emojiContainer = HtmlUtils.querySelectorOrFail(".emoji-container");
|
|
||||||
|
|
||||||
this.picker = new EmojiButton({
|
|
||||||
rootElement: emojiContainer,
|
|
||||||
styleProperties: {
|
|
||||||
'--font': 'Press Start 2P'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.picker.on("emoji", (selection) => {
|
|
||||||
this.emit(EmoteMenuClickEvent, selection.emoji);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.picker.on("hidden", () => {
|
|
||||||
this.userInputManager.restoreControls();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.resize();
|
|
||||||
this.resizeCallback = this.resize.bind(this);
|
|
||||||
this.scene.scale.on(Phaser.Scale.Events.RESIZE, this.resizeCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public isOpen(): boolean {
|
|
||||||
return this.picker.isPickerVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
public openPicker() {
|
|
||||||
this.userInputManager.disableControls();
|
|
||||||
const emojiContainer = HtmlUtils.querySelectorOrFail(".emoji-container");
|
|
||||||
this.picker.showPicker(emojiContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public closePicker() {
|
|
||||||
this.picker.hidePicker();
|
|
||||||
}
|
|
||||||
|
|
||||||
private resize() {
|
|
||||||
this.setScale(waScaleManager.uiScalingFactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public destroy() {
|
|
||||||
this.scene.scale.removeListener(Phaser.Scale.Events.RESIZE, this.resizeCallback);
|
|
||||||
super.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
@ -291,48 +291,48 @@ export abstract class Character extends Container {
|
|||||||
|
|
||||||
playEmote(emote: string) {
|
playEmote(emote: string) {
|
||||||
this.cancelPreviousEmote();
|
this.cancelPreviousEmote();
|
||||||
|
const emoteY = -45;
|
||||||
const scalingFactor = waScaleManager.uiScalingFactor;
|
|
||||||
const emoteY = -60;
|
|
||||||
|
|
||||||
this.playerName.setVisible(false);
|
this.playerName.setVisible(false);
|
||||||
this.emote = new Text(this.scene, -12, 0, emote, { fontFamily: '"twemoji"', fontSize: '24px' });
|
this.emote = new Text(this.scene, -10, 0, emote, { fontFamily: '"twemoji"', fontSize: '20px' });
|
||||||
this.emote.setAlpha(0);
|
this.emote.setAlpha(0);
|
||||||
this.add(this.emote);
|
this.add(this.emote);
|
||||||
this.createStartTransition(scalingFactor, emoteY);
|
this.createStartTransition(emoteY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createStartTransition(scalingFactor: number, emoteY: number) {
|
private createStartTransition(emoteY: number) {
|
||||||
this.emoteTween = this.scene?.tweens.add({
|
if (this.emote) {
|
||||||
targets: this.emote,
|
this.emoteTween = this.scene?.tweens.add({
|
||||||
props: {
|
targets: this.emote,
|
||||||
scale: scalingFactor,
|
props: {
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
y: emoteY,
|
y: emoteY,
|
||||||
},
|
},
|
||||||
ease: "Power2",
|
ease: "Power2",
|
||||||
duration: 500,
|
duration: 500,
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
this.startPulseTransition(emoteY, scalingFactor);
|
this.startPulseTransition(emoteY);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private startPulseTransition(emoteY: number, scalingFactor: number) {
|
private startPulseTransition(emoteY: number) {
|
||||||
this.emoteTween = this.scene?.tweens.add({
|
if (this.emote) {
|
||||||
targets: this.emote,
|
this.emoteTween = this.scene?.tweens.add({
|
||||||
props: {
|
targets: this.emote,
|
||||||
y: emoteY * 1.3,
|
props: {
|
||||||
scale: scalingFactor * 1.1,
|
y: emoteY * 1.3,
|
||||||
},
|
scale: this.emote.scale * 1.1,
|
||||||
duration: 250,
|
},
|
||||||
yoyo: true,
|
duration: 250,
|
||||||
repeat: 1,
|
yoyo: true,
|
||||||
completeDelay: 200,
|
repeat: 1,
|
||||||
onComplete: () => {
|
completeDelay: 200,
|
||||||
this.startExitTransition(emoteY);
|
onComplete: () => {
|
||||||
},
|
this.startExitTransition(emoteY);
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private startExitTransition(emoteY: number) {
|
private startExitTransition(emoteY: number) {
|
||||||
|
@ -82,6 +82,7 @@ import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStor
|
|||||||
import { SharedVariablesManager } from "./SharedVariablesManager";
|
import { SharedVariablesManager } from "./SharedVariablesManager";
|
||||||
import { playersStore } from "../../Stores/PlayersStore";
|
import { playersStore } from "../../Stores/PlayersStore";
|
||||||
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
||||||
|
import { emoteStore } from "../../Stores/EmoteStore";
|
||||||
import {
|
import {
|
||||||
audioManagerFileStore,
|
audioManagerFileStore,
|
||||||
audioManagerVisibilityStore,
|
audioManagerVisibilityStore,
|
||||||
@ -94,6 +95,7 @@ import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
|||||||
import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager";
|
import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager";
|
||||||
import { GameMapPropertiesListener } from "./GameMapPropertiesListener";
|
import { GameMapPropertiesListener } from "./GameMapPropertiesListener";
|
||||||
import type { RadialMenuItem } from "../Components/RadialMenu";
|
import type { RadialMenuItem } from "../Components/RadialMenu";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface | null;
|
initPosition: PointInterface | null;
|
||||||
@ -171,6 +173,7 @@ export class GameScene extends DirtyScene {
|
|||||||
private iframeSubscriptionList!: Array<Subscription>;
|
private iframeSubscriptionList!: Array<Subscription>;
|
||||||
private peerStoreUnsubscribe!: () => void;
|
private peerStoreUnsubscribe!: () => void;
|
||||||
private chatVisibilityUnsubscribe!: () => void;
|
private chatVisibilityUnsubscribe!: () => void;
|
||||||
|
private emoteUnsubscribe!: () => void;
|
||||||
private biggestAvailableAreaStoreUnsubscribe!: () => void;
|
private biggestAvailableAreaStoreUnsubscribe!: () => void;
|
||||||
MapUrlFile: string;
|
MapUrlFile: string;
|
||||||
roomUrl: string;
|
roomUrl: string;
|
||||||
@ -272,7 +275,7 @@ export class GameScene extends DirtyScene {
|
|||||||
// So if we are in https, we can still try to load a HTTP local resource (can be useful for testing purposes)
|
// So if we are in https, we can still try to load a HTTP local resource (can be useful for testing purposes)
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#when_is_a_context_considered_secure
|
// See https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#when_is_a_context_considered_secure
|
||||||
const url = new URL(file.src);
|
const url = new URL(file.src);
|
||||||
const host = url.host.split(":")[0];
|
const host = url.host.split(":")[ 0 ];
|
||||||
if (
|
if (
|
||||||
window.location.protocol === "https:" &&
|
window.location.protocol === "https:" &&
|
||||||
file.src === this.MapUrlFile &&
|
file.src === this.MapUrlFile &&
|
||||||
@ -321,8 +324,8 @@ export class GameScene extends DirtyScene {
|
|||||||
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
(this.load as any).rexWebFont({
|
(this.load as any).rexWebFont({
|
||||||
custom: {
|
custom: {
|
||||||
families: ["Press Start 2P"],
|
families: [ "Press Start 2P" ],
|
||||||
urls: ["/resources/fonts/fonts.css"],
|
urls: [ "/resources/fonts/fonts.css" ],
|
||||||
testString: "abcdefg",
|
testString: "abcdefg",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -368,7 +371,7 @@ export class GameScene extends DirtyScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [itemType, objectsOfType] of this.objectsByType) {
|
for (const [ itemType, objectsOfType ] of this.objectsByType) {
|
||||||
// FIXME: we would ideally need for the loader to WAIT for the import to be performed, which means writing our own loader plugin.
|
// FIXME: we would ideally need for the loader to WAIT for the import to be performed, which means writing our own loader plugin.
|
||||||
|
|
||||||
let itemFactory: ItemFactoryInterface;
|
let itemFactory: ItemFactoryInterface;
|
||||||
@ -399,7 +402,7 @@ export class GameScene extends DirtyScene {
|
|||||||
// TODO: we should pass here a factory to create sprites (maybe?)
|
// TODO: we should pass here a factory to create sprites (maybe?)
|
||||||
|
|
||||||
// Do we have a state for this object?
|
// Do we have a state for this object?
|
||||||
const state = roomJoinedAnswer.items[object.id];
|
const state = roomJoinedAnswer.items[ object.id ];
|
||||||
|
|
||||||
const actionableItem = itemFactory.factory(this, object, state);
|
const actionableItem = itemFactory.factory(this, object, state);
|
||||||
this.actionableItems.set(actionableItem.getId(), actionableItem);
|
this.actionableItems.set(actionableItem.getId(), actionableItem);
|
||||||
@ -614,7 +617,16 @@ export class GameScene extends DirtyScene {
|
|||||||
this.openChatIcon.setVisible(!v);
|
this.openChatIcon.setVisible(!v);
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.all([this.connectionAnswerPromise as Promise<unknown>, ...scriptPromises]).then(() => {
|
this.emoteUnsubscribe = emoteStore.subscribe(() => {
|
||||||
|
const emoteKey = get(emoteStore);
|
||||||
|
if (emoteKey) {
|
||||||
|
this.CurrentPlayer?.playEmote(emoteKey)
|
||||||
|
this.connection?.emitEmoteEvent(emoteKey);
|
||||||
|
emoteStore.set(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all([ this.connectionAnswerPromise as Promise<unknown>, ...scriptPromises ]).then(() => {
|
||||||
this.scene.wake();
|
this.scene.wake();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -702,8 +714,8 @@ export class GameScene extends DirtyScene {
|
|||||||
if (item === undefined) {
|
if (item === undefined) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'Received an event about object "' +
|
'Received an event about object "' +
|
||||||
message.itemId +
|
message.itemId +
|
||||||
'" but cannot find this item on the map.'
|
'" but cannot find this item on the map.'
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -897,15 +909,15 @@ export class GameScene extends DirtyScene {
|
|||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
"Error while opening a popup. Cannot find an object on the map with name '" +
|
"Error while opening a popup. Cannot find an object on the map with name '" +
|
||||||
openPopupEvent.targetObject +
|
openPopupEvent.targetObject +
|
||||||
"'. The first parameter of WA.openPopup() must be the name of a rectangle object in your map."
|
"'. The first parameter of WA.openPopup() must be the name of a rectangle object in your map."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const escapedMessage = HtmlUtils.escapeHtml(openPopupEvent.message);
|
const escapedMessage = HtmlUtils.escapeHtml(openPopupEvent.message);
|
||||||
let html = `<div id="container" hidden><div class="nes-container with-title is-centered">`;
|
let html = `<div id="container" hidden><div class="nes-container with-title is-centered">`;
|
||||||
html += escapedMessage;
|
html += escapedMessage;
|
||||||
if(openPopupEvent.input) {
|
if (openPopupEvent.input) {
|
||||||
html += `<input id="popupinput-${openPopupEvent.popupId}" class="nes-input" />`
|
html += `<input id="popupinput-${openPopupEvent.popupId}" class="nes-input" />`
|
||||||
}
|
}
|
||||||
html += `</div>`;
|
html += `</div>`;
|
||||||
@ -938,7 +950,7 @@ export class GameScene extends DirtyScene {
|
|||||||
const btnId = id;
|
const btnId = id;
|
||||||
button.onclick = () => {
|
button.onclick = () => {
|
||||||
let inputValue = '';
|
let inputValue = '';
|
||||||
if(openPopupEvent.input) {
|
if (openPopupEvent.input) {
|
||||||
inputValue = HtmlUtils.getElementByIdOrFail<HTMLInputElement>(`popupinput-${openPopupEvent.popupId}`).value;
|
inputValue = HtmlUtils.getElementByIdOrFail<HTMLInputElement>(`popupinput-${openPopupEvent.popupId}`).value;
|
||||||
}
|
}
|
||||||
iframeListener.sendButtonClickedEvent(openPopupEvent.popupId, btnId, openPopupEvent.input, inputValue);
|
iframeListener.sendButtonClickedEvent(openPopupEvent.popupId, btnId, openPopupEvent.input, inputValue);
|
||||||
@ -1095,17 +1107,17 @@ export class GameScene extends DirtyScene {
|
|||||||
|
|
||||||
this.iframeSubscriptionList.push(iframeListener.unregisterIFrameStream.subscribe(() => {
|
this.iframeSubscriptionList.push(iframeListener.unregisterIFrameStream.subscribe(() => {
|
||||||
const allProps = this.gameMap.getCurrentProperties();
|
const allProps = this.gameMap.getCurrentProperties();
|
||||||
if(allProps.get("openWebsite") == null) {
|
if (allProps.get("openWebsite") == null) {
|
||||||
layoutManagerActionStore.removeAction("openWebsite");
|
layoutManagerActionStore.removeAction("openWebsite");
|
||||||
} else {
|
} else {
|
||||||
const openWebsiteFunction = () => {
|
const openWebsiteFunction = () => {
|
||||||
coWebsiteManager.loadCoWebsite(allProps.get("openWebsite") as string, this.MapUrlFile, allProps.get('openWebsiteAllowApi') as boolean | undefined, allProps.get('openWebsitePolicy') as string | undefined);
|
coWebsiteManager.loadCoWebsite(allProps.get("openWebsite") as string, this.MapUrlFile, allProps.get('openWebsiteAllowApi') as boolean | undefined, allProps.get('openWebsitePolicy') as string | undefined);
|
||||||
layoutManagerActionStore.removeAction("openWebsite");
|
layoutManagerActionStore.removeAction("openWebsite");
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let message = allProps.get(WEBSITE_MESSAGE_PROPERTIES);
|
let message = allProps.get(WEBSITE_MESSAGE_PROPERTIES);
|
||||||
if(message === undefined) {
|
if (message === undefined) {
|
||||||
message = 'Press SPACE or touch here to open web site';
|
message = 'Press SPACE or touch here to open web site';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,7 +1130,7 @@ export class GameScene extends DirtyScene {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.iframeSubscriptionList.push(iframeListener.setTilesStream.subscribe((eventTiles) => {
|
this.iframeSubscriptionList.push(iframeListener.setTilesStream.subscribe((eventTiles) => {
|
||||||
for (const eventTile of eventTiles) {
|
for (const eventTile of eventTiles) {
|
||||||
this.gameMap.putTile(eventTile.tile, eventTile.x, eventTile.y, eventTile.layer);
|
this.gameMap.putTile(eventTile.tile, eventTile.x, eventTile.y, eventTile.layer);
|
||||||
@ -1130,7 +1142,7 @@ export class GameScene extends DirtyScene {
|
|||||||
const jsonTilesetDir = eventTileset.url.substr(0, eventTileset.url.lastIndexOf("/"));
|
const jsonTilesetDir = eventTileset.url.substr(0, eventTileset.url.lastIndexOf("/"));
|
||||||
//Initialise the firstgid to 1 because if there is no tileset in the tilemap, the firstgid will be 1
|
//Initialise the firstgid to 1 because if there is no tileset in the tilemap, the firstgid will be 1
|
||||||
let newFirstgid = 1;
|
let newFirstgid = 1;
|
||||||
const lastTileset = this.mapFile.tilesets[this.mapFile.tilesets.length - 1];
|
const lastTileset = this.mapFile.tilesets[ this.mapFile.tilesets.length - 1 ];
|
||||||
if (lastTileset) {
|
if (lastTileset) {
|
||||||
//If there is at least one tileset in the tilemap then calculate the firstgid of the new tileset
|
//If there is at least one tileset in the tilemap then calculate the firstgid of the new tileset
|
||||||
newFirstgid = lastTileset.firstgid + lastTileset.tilecount;
|
newFirstgid = lastTileset.firstgid + lastTileset.tilecount;
|
||||||
@ -1251,14 +1263,14 @@ export class GameScene extends DirtyScene {
|
|||||||
if (phaserLayers === []) {
|
if (phaserLayers === []) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'Could not find layer with name that contains "' +
|
'Could not find layer with name that contains "' +
|
||||||
layerName +
|
layerName +
|
||||||
'" when calling WA.hideLayer / WA.showLayer'
|
'" when calling WA.hideLayer / WA.showLayer'
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < phaserLayers.length; i++) {
|
for (let i = 0; i < phaserLayers.length; i++) {
|
||||||
phaserLayers[i].setVisible(visible);
|
phaserLayers[ i ].setVisible(visible);
|
||||||
phaserLayers[i].setCollisionByProperty({ collides: true }, visible);
|
phaserLayers[ i ].setCollisionByProperty({ collides: true }, visible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.markDirty();
|
this.markDirty();
|
||||||
@ -1338,6 +1350,7 @@ export class GameScene extends DirtyScene {
|
|||||||
this.emoteManager.destroy();
|
this.emoteManager.destroy();
|
||||||
this.peerStoreUnsubscribe();
|
this.peerStoreUnsubscribe();
|
||||||
this.chatVisibilityUnsubscribe();
|
this.chatVisibilityUnsubscribe();
|
||||||
|
this.emoteUnsubscribe();
|
||||||
this.biggestAvailableAreaStoreUnsubscribe();
|
this.biggestAvailableAreaStoreUnsubscribe();
|
||||||
iframeListener.unregisterAnswerer("getState");
|
iframeListener.unregisterAnswerer("getState");
|
||||||
iframeListener.unregisterAnswerer("loadTileset");
|
iframeListener.unregisterAnswerer("loadTileset");
|
||||||
@ -1468,7 +1481,7 @@ export class GameScene extends DirtyScene {
|
|||||||
if (pointer.wasTouch && (pointer.event as TouchEvent).touches.length > 1) {
|
if (pointer.wasTouch && (pointer.event as TouchEvent).touches.length > 1) {
|
||||||
return; //we don't want the menu to open when pinching on a touch screen.
|
return; //we don't want the menu to open when pinching on a touch screen.
|
||||||
}
|
}
|
||||||
|
|
||||||
this.CurrentPlayer.openOrCloseEmoteMenu();
|
this.CurrentPlayer.openOrCloseEmoteMenu();
|
||||||
})
|
})
|
||||||
this.CurrentPlayer.on(requestEmoteEventName, (emoteKey: string) => {
|
this.CurrentPlayer.on(requestEmoteEventName, (emoteKey: string) => {
|
||||||
@ -1856,13 +1869,13 @@ export class GameScene extends DirtyScene {
|
|||||||
|
|
||||||
const allProps = this.gameMap.getCurrentProperties();
|
const allProps = this.gameMap.getCurrentProperties();
|
||||||
|
|
||||||
if(allProps.get("jitsiRoom") === undefined) {
|
if (allProps.get("jitsiRoom") === undefined) {
|
||||||
layoutManagerActionStore.removeAction("jitsi");
|
layoutManagerActionStore.removeAction("jitsi");
|
||||||
} else {
|
} else {
|
||||||
const openJitsiRoomFunction = () => {
|
const openJitsiRoomFunction = () => {
|
||||||
const roomName = jitsiFactory.getRoomName(allProps.get("jitsiRoom") as string, this.instance);
|
const roomName = jitsiFactory.getRoomName(allProps.get("jitsiRoom") as string, this.instance);
|
||||||
const jitsiUrl = allProps.get("jitsiUrl") as string | undefined;
|
const jitsiUrl = allProps.get("jitsiUrl") as string | undefined;
|
||||||
if(JITSI_PRIVATE_MODE && !jitsiUrl) {
|
if (JITSI_PRIVATE_MODE && !jitsiUrl) {
|
||||||
const adminTag = allProps.get("jitsiRoomAdminTag") as string | undefined;
|
const adminTag = allProps.get("jitsiRoomAdminTag") as string | undefined;
|
||||||
|
|
||||||
this.connection && this.connection.emitQueryJitsiJwtMessage(roomName, adminTag);
|
this.connection && this.connection.emitQueryJitsiJwtMessage(roomName, adminTag);
|
||||||
@ -1873,7 +1886,7 @@ export class GameScene extends DirtyScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let message = allProps.get(JITSI_MESSAGE_PROPERTIES);
|
let message = allProps.get(JITSI_MESSAGE_PROPERTIES);
|
||||||
if(message === undefined) {
|
if (message === undefined) {
|
||||||
message = 'Press SPACE or touch here to enter Jitsi Meet room';
|
message = 'Press SPACE or touch here to enter Jitsi Meet room';
|
||||||
}
|
}
|
||||||
layoutManagerActionStore.addAction({
|
layoutManagerActionStore.addAction({
|
||||||
|
@ -3,7 +3,8 @@ import type { GameScene } from "../Game/GameScene";
|
|||||||
import { UserInputEvent, UserInputManager } from "../UserInput/UserInputManager";
|
import { UserInputEvent, UserInputManager } from "../UserInput/UserInputManager";
|
||||||
import { Character } from "../Entity/Character";
|
import { Character } from "../Entity/Character";
|
||||||
import { userMovingStore } from "../../Stores/GameStore";
|
import { userMovingStore } from "../../Stores/GameStore";
|
||||||
import { EmoteMenu, EmoteMenuClickEvent } from "../Components/EmoteMenu";
|
import { get } from "svelte/store";
|
||||||
|
import { emoteMenuStore } from "../../Stores/EmoteStore";
|
||||||
|
|
||||||
export const hasMovedEventName = "hasMoved";
|
export const hasMovedEventName = "hasMoved";
|
||||||
export const requestEmoteEventName = "requestEmote";
|
export const requestEmoteEventName = "requestEmote";
|
||||||
@ -11,8 +12,6 @@ export const requestEmoteEventName = "requestEmote";
|
|||||||
export class Player extends Character {
|
export class Player extends Character {
|
||||||
private previousDirection: string = PlayerAnimationDirections.Down;
|
private previousDirection: string = PlayerAnimationDirections.Down;
|
||||||
private wasMoving: boolean = false;
|
private wasMoving: boolean = false;
|
||||||
private emoteMenu: EmoteMenu | null = null;
|
|
||||||
private updateListener: () => void;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
Scene: GameScene,
|
Scene: GameScene,
|
||||||
@ -30,14 +29,6 @@ export class Player extends Character {
|
|||||||
|
|
||||||
//the current player model should be push away by other players to prevent conflict
|
//the current player model should be push away by other players to prevent conflict
|
||||||
this.getBody().setImmovable(false);
|
this.getBody().setImmovable(false);
|
||||||
|
|
||||||
this.updateListener = () => {
|
|
||||||
if (this.emoteMenu) {
|
|
||||||
this.emoteMenu.x = this.x;
|
|
||||||
this.emoteMenu.y = this.y;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.scene.events.addListener("postupdate", this.updateListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
moveUser(delta: number): void {
|
moveUser(delta: number): void {
|
||||||
@ -94,43 +85,16 @@ export class Player extends Character {
|
|||||||
return this.wasMoving;
|
return this.wasMoving;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playEmote(emote: string) {
|
||||||
|
super.playEmote(emote);
|
||||||
|
emoteMenuStore.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
openOrCloseEmoteMenu() {
|
openOrCloseEmoteMenu() {
|
||||||
if (!this.emoteMenu) {
|
if (get(emoteMenuStore)) {
|
||||||
this.emoteMenu = new EmoteMenu(this.scene, this.x, this.y, this.userInputManager)
|
emoteMenuStore.set(false);
|
||||||
}
|
|
||||||
|
|
||||||
if (this.emoteMenu.isOpen()) {
|
|
||||||
this.closeEmoteMenu();
|
|
||||||
} else {
|
} else {
|
||||||
this.openEmoteMenu();
|
emoteMenuStore.set(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openEmoteMenu(): void {
|
|
||||||
this.cancelPreviousEmote();
|
|
||||||
if (!this.emoteMenu) return;
|
|
||||||
this.emoteMenu.openPicker();
|
|
||||||
this.emoteMenu.on(EmoteMenuClickEvent, (emote: string) => {
|
|
||||||
this.closeEmoteMenu();
|
|
||||||
this.emit(requestEmoteEventName, emote);
|
|
||||||
this.playEmote(emote);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
isSilent() {
|
|
||||||
super.isSilent();
|
|
||||||
}
|
|
||||||
noSilent() {
|
|
||||||
super.noSilent();
|
|
||||||
}
|
|
||||||
|
|
||||||
closeEmoteMenu(): void {
|
|
||||||
if (!this.emoteMenu) return;
|
|
||||||
this.emoteMenu.closePicker();
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {
|
|
||||||
this.scene.events.removeListener("postupdate", this.updateListener);
|
|
||||||
super.destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
4
front/src/Stores/EmoteStore.ts
Normal file
4
front/src/Stores/EmoteStore.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
export const emoteStore = writable<string | null>(null);
|
||||||
|
export const emoteMenuStore = writable(false);
|
Loading…
Reference in New Issue
Block a user