diff --git a/front/package.json b/front/package.json index 4e4d66c9..12b47ee9 100644 --- a/front/package.json +++ b/front/package.json @@ -39,6 +39,7 @@ }, "dependencies": { "@fontsource/press-start-2p": "^4.3.0", + "@joeattardi/emoji-button": "^4.6.0", "@types/simple-peer": "^9.11.1", "@types/socket.io-client": "^1.4.32", "axios": "^0.21.1", diff --git a/front/src/Phaser/Components/EmoteMenu.ts b/front/src/Phaser/Components/EmoteMenu.ts index 3415dfbf..ef0a3f10 100644 --- a/front/src/Phaser/Components/EmoteMenu.ts +++ b/front/src/Phaser/Components/EmoteMenu.ts @@ -1,63 +1,50 @@ import Sprite = Phaser.GameObjects.Sprite; import Text = Phaser.GameObjects.Text; -import {DEPTH_UI_INDEX} from "../Game/DepthIndexes"; -import {waScaleManager} from "../Services/WaScaleManager"; +import DOMElement = Phaser.GameObjects.DOMElement; +import { DEPTH_UI_INDEX } from "../Game/DepthIndexes"; +import { waScaleManager } from "../Services/WaScaleManager"; +import { EmojiButton } from "@joeattardi/emoji-button"; +import { HtmlUtils } from "../../WebRtc/HtmlUtils"; -export const EmoteMenuClickEvent = 'emoteClick'; +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 items: string[]) { + constructor(scene: Phaser.Scene, x: number, y: number) { super(scene, x, y); - this.setDepth(DEPTH_UI_INDEX) + this.setDepth(DEPTH_UI_INDEX); this.scene.add.existing(this); - this.initItems(); + 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 }); + + this.picker.on("emoji", (selection) => { + this.emit(EmoteMenuClickEvent, selection.emoji); + }); this.resize(); this.resizeCallback = this.resize.bind(this); this.scene.scale.on(Phaser.Scale.Events.RESIZE, this.resizeCallback); } - private initItems() { - const itemsNumber = this.items.length; - const menuRadius = 70 + (waScaleManager.uiScalingFactor - 1) * 20; - this.items.forEach((item, index) => this.createEmoteElement(item, index, itemsNumber, menuRadius)) + public isOpen(): boolean { + return this.picker.isPickerVisible(); } - private createEmoteElement(item: string, index: number, itemsNumber: number, menuRadius: number) { - // const image = new Sprite(this.scene, 0, menuRadius, item.image); - const image = new Text(this.scene, -12, menuRadius, item, {fontFamily: '"twemoji"', fontSize:'75px'}); - this.add(image); - // this.scene.sys.updateList.add(image); - const scalingFactor = waScaleManager.uiScalingFactor * 0.3; - image.setScale(scalingFactor) - image.setInteractive({ - useHandCursor: true, - }); - image.on('pointerdown', () => this.emit(EmoteMenuClickEvent, item)); - image.on('pointerover', () => { - this.scene.tweens.add({ - targets: image, - props: { - scale: 1.5 * scalingFactor, - }, - duration: 500, - ease: 'Power3', - }) - }); - image.on('pointerout', () => { - this.scene.tweens.add({ - targets: image, - props: { - scale: scalingFactor, - }, - duration: 500, - ease: 'Power3', - }) - }); - const angle = 2 * Math.PI * index / itemsNumber; - Phaser.Actions.RotateAroundDistance([image], {x: -12, y: -12}, angle, menuRadius); + public openPicker() { + const emojiContainer = HtmlUtils.querySelectorOrFail(".emoji-container"); + this.picker.showPicker(emojiContainer); + } + + public closePicker() { + this.picker.hidePicker(); } private resize() { @@ -68,4 +55,4 @@ export class EmoteMenu extends Phaser.GameObjects.Container { this.scene.scale.removeListener(Phaser.Scale.Events.RESIZE, this.resizeCallback); super.destroy(); } -} \ No newline at end of file +} diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts index 275110c8..19a158b2 100644 --- a/front/src/Phaser/Entity/Character.ts +++ b/front/src/Phaser/Entity/Character.ts @@ -1,29 +1,29 @@ -import {PlayerAnimationDirections, PlayerAnimationTypes} from "../Player/Animation"; -import {SpeechBubble} from "./SpeechBubble"; +import { PlayerAnimationDirections, PlayerAnimationTypes } from "../Player/Animation"; +import { SpeechBubble } from "./SpeechBubble"; import Text = Phaser.GameObjects.Text; import Container = Phaser.GameObjects.Container; import Sprite = Phaser.GameObjects.Sprite; -import {TextureError} from "../../Exception/TextureError"; -import {Companion} from "../Companion/Companion"; -import type {GameScene} from "../Game/GameScene"; -import {DEPTH_INGAME_TEXT_INDEX} from "../Game/DepthIndexes"; -import {waScaleManager} from "../Services/WaScaleManager"; +import { TextureError } from "../../Exception/TextureError"; +import { Companion } from "../Companion/Companion"; +import type { GameScene } from "../Game/GameScene"; +import { DEPTH_INGAME_TEXT_INDEX } from "../Game/DepthIndexes"; +import { waScaleManager } from "../Services/WaScaleManager"; import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js"; -const playerNameY = - 25; +const playerNameY = -25; interface AnimationData { key: string; frameRate: number; repeat: number; frameModel: string; //todo use an enum - frames : number[] + frames: number[]; } const interactiveRadius = 35; export abstract class Character extends Container { - private bubble: SpeechBubble|null = null; + private bubble: SpeechBubble | null = null; private readonly playerName: Text; public PlayerValue: string; public sprites: Map; @@ -32,35 +32,41 @@ export abstract class Character extends Container { private invisible: boolean; public companion?: Companion; private emote: Phaser.GameObjects.Text | null = null; - private emoteTween: Phaser.Tweens.Tween|null = null; + private emoteTween: Phaser.Tweens.Tween | null = null; scene: GameScene; - constructor(scene: GameScene, - x: number, - y: number, - texturesPromise: Promise, - name: string, - direction: PlayerAnimationDirections, - moving: boolean, - frame: string | number, - isClickable: boolean, - companion: string|null, - companionTexturePromise?: Promise + constructor( + scene: GameScene, + x: number, + y: number, + texturesPromise: Promise, + name: string, + direction: PlayerAnimationDirections, + moving: boolean, + frame: string | number, + isClickable: boolean, + companion: string | null, + companionTexturePromise?: Promise ) { - super(scene, x, y/*, texture, frame*/); + super(scene, x, y /*, texture, frame*/); this.scene = scene; this.PlayerValue = name; - this.invisible = true + this.invisible = true; this.sprites = new Map(); //textures are inside a Promise in case they need to be lazyloaded before use. texturesPromise.then((textures) => { this.addTextures(textures, frame); - this.invisible = false - }) + this.invisible = false; + }); - this.playerName = new Text(scene, 0, playerNameY, name, {fontFamily: '"Press Start 2P"', fontSize: '8px', strokeThickness: 2, stroke: "gray"}); + this.playerName = new Text(scene, 0, playerNameY, name, { + fontFamily: '"Press Start 2P"', + fontSize: "8px", + strokeThickness: 2, + stroke: "gray", + }); this.playerName.setOrigin(0.5).setDepth(DEPTH_INGAME_TEXT_INDEX); this.add(this.playerName); @@ -71,18 +77,17 @@ export abstract class Character extends Container { useHandCursor: true, }); - this.on('pointerover',() => { + this.on("pointerover", () => { this.getOutlinePlugin()?.add(this.playerName, { thickness: 2, - outlineColor: 0xffff00 + outlineColor: 0xffff00, }); this.scene.markDirty(); }); - this.on('pointerout',() => { + this.on("pointerout", () => { this.getOutlinePlugin()?.remove(this.playerName); this.scene.markDirty(); - }) - + }); } scene.add.existing(this); @@ -97,38 +102,38 @@ export abstract class Character extends Container { this.playAnimation(direction, moving); - if (typeof companion === 'string') { + if (typeof companion === "string") { this.addCompanion(companion, companionTexturePromise); } } - private getOutlinePlugin(): OutlinePipelinePlugin|undefined { - return this.scene.plugins.get('rexOutlinePipeline') as unknown as OutlinePipelinePlugin|undefined; + private getOutlinePlugin(): OutlinePipelinePlugin | undefined { + return this.scene.plugins.get("rexOutlinePipeline") as unknown as OutlinePipelinePlugin | undefined; } public addCompanion(name: string, texturePromise?: Promise): void { - if (typeof texturePromise !== 'undefined') { + if (typeof texturePromise !== "undefined") { this.companion = new Companion(this.scene, this.x, this.y, name, texturePromise); } } public addTextures(textures: string[], frame?: string | number): void { for (const texture of textures) { - if(this.scene && !this.scene.textures.exists(texture)){ - throw new TextureError('texture not found'); + if (this.scene && !this.scene.textures.exists(texture)) { + throw new TextureError("texture not found"); } const sprite = new Sprite(this.scene, 0, 0, texture, frame); this.add(sprite); - this.getPlayerAnimations(texture).forEach(d => { + this.getPlayerAnimations(texture).forEach((d) => { this.scene.anims.create({ key: d.key, - frames: this.scene.anims.generateFrameNumbers(d.frameModel, {frames: d.frames}), + frames: this.scene.anims.generateFrameNumbers(d.frameModel, { frames: d.frames }), frameRate: d.frameRate, - repeat: d.repeat + repeat: d.repeat, }); - }) + }); // Needed, otherwise, animations are not handled correctly. - if(this.scene) { + if (this.scene) { this.scene.sys.updateList.add(sprite); } this.sprites.set(texture, sprite); @@ -136,68 +141,77 @@ export abstract class Character extends Container { } private getPlayerAnimations(name: string): AnimationData[] { - return [{ - key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Walk}`, - frameModel: name, - frames: [0, 1, 2, 1], - frameRate: 10, - repeat: -1 - }, { - key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Walk}`, - frameModel: name, - frames: [3, 4, 5, 4], - frameRate: 10, - repeat: -1 - }, { - key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Walk}`, - frameModel: name, - frames: [6, 7, 8, 7], - frameRate: 10, - repeat: -1 - }, { - key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Walk}`, - frameModel: name, - frames: [9, 10, 11, 10], - frameRate: 10, - repeat: -1 - },{ - key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Idle}`, - frameModel: name, - frames: [1], - frameRate: 10, - repeat: 1 - }, { - key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Idle}`, - frameModel: name, - frames: [4], - frameRate: 10, - repeat: 1 - }, { - key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Idle}`, - frameModel: name, - frames: [7], - frameRate: 10, - repeat: 1 - }, { - key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Idle}`, - frameModel: name, - frames: [10], - frameRate: 10, - repeat: 1 - }]; + return [ + { + key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Walk}`, + frameModel: name, + frames: [0, 1, 2, 1], + frameRate: 10, + repeat: -1, + }, + { + key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Walk}`, + frameModel: name, + frames: [3, 4, 5, 4], + frameRate: 10, + repeat: -1, + }, + { + key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Walk}`, + frameModel: name, + frames: [6, 7, 8, 7], + frameRate: 10, + repeat: -1, + }, + { + key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Walk}`, + frameModel: name, + frames: [9, 10, 11, 10], + frameRate: 10, + repeat: -1, + }, + { + key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Idle}`, + frameModel: name, + frames: [1], + frameRate: 10, + repeat: 1, + }, + { + key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Idle}`, + frameModel: name, + frames: [4], + frameRate: 10, + repeat: 1, + }, + { + key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Idle}`, + frameModel: name, + frames: [7], + frameRate: 10, + repeat: 1, + }, + { + key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Idle}`, + frameModel: name, + frames: [10], + frameRate: 10, + repeat: 1, + }, + ]; } - protected playAnimation(direction : PlayerAnimationDirections, moving: boolean): void { + protected playAnimation(direction: PlayerAnimationDirections, moving: boolean): void { if (this.invisible) return; for (const [texture, sprite] of this.sprites.entries()) { if (!sprite.anims) { - console.error('ANIMS IS NOT DEFINED!!!'); + console.error("ANIMS IS NOT DEFINED!!!"); return; } if (moving && (!sprite.anims.currentAnim || sprite.anims.currentAnim.key !== direction)) { - sprite.play(texture+'-'+direction+'-'+PlayerAnimationTypes.Walk, true); + sprite.play(texture + "-" + direction + "-" + PlayerAnimationTypes.Walk, true); } else if (!moving) { - sprite.anims.play(texture + '-' + direction + '-'+PlayerAnimationTypes.Idle, true); + sprite.anims.play(texture + "-" + direction + "-" + PlayerAnimationTypes.Idle, true); } } } @@ -205,7 +219,7 @@ export abstract class Character extends Container { protected getBody(): Phaser.Physics.Arcade.Body { const body = this.body; if (!(body instanceof Phaser.Physics.Arcade.Body)) { - throw new Error('Container does not have arcade body'); + throw new Error("Container does not have arcade body"); } return body; } @@ -216,16 +230,20 @@ export abstract class Character extends Container { body.setVelocity(x, y); // up or down animations are prioritized over left and right - if (body.velocity.y < 0) { //moving up + if (body.velocity.y < 0) { + //moving up this.lastDirection = PlayerAnimationDirections.Up; this.playAnimation(PlayerAnimationDirections.Up, true); - } else if (body.velocity.y > 0) { //moving down + } else if (body.velocity.y > 0) { + //moving down this.lastDirection = PlayerAnimationDirections.Down; this.playAnimation(PlayerAnimationDirections.Down, true); - } else if (body.velocity.x > 0) { //moving right + } else if (body.velocity.x > 0) { + //moving right this.lastDirection = PlayerAnimationDirections.Right; this.playAnimation(PlayerAnimationDirections.Right, true); - } else if (body.velocity.x < 0) { //moving left + } else if (body.velocity.x < 0) { + //moving left this.lastDirection = PlayerAnimationDirections.Left; this.playAnimation(PlayerAnimationDirections.Left, true); } @@ -237,45 +255,42 @@ export abstract class Character extends Container { } } - stop(){ + stop() { this.getBody().setVelocity(0, 0); this.playAnimation(this.lastDirection, false); } say(text: string) { if (this.bubble) return; - this.bubble = new SpeechBubble(this.scene, this, text) + this.bubble = new SpeechBubble(this.scene, this, text); setTimeout(() => { if (this.bubble !== null) { this.bubble.destroy(); this.bubble = null; } - }, 3000) + }, 3000); } destroy(): void { for (const sprite of this.sprites.values()) { - if(this.scene) { + if (this.scene) { this.scene.sys.updateList.remove(sprite); } } - this.list.forEach(objectContaining => objectContaining.destroy()) + this.list.forEach((objectContaining) => objectContaining.destroy()); super.destroy(); } playEmote(emote: string) { this.cancelPreviousEmote(); - const scalingFactor = waScaleManager.uiScalingFactor * 0.5; - const emoteY = -60 - scalingFactor * 10; + const scalingFactor = waScaleManager.uiScalingFactor; + const emoteY = -60; this.playerName.setVisible(false); - this.emote = new Text(this.scene, -12, 0, emote, {fontFamily: '"twemoji"', fontSize:'55px'}); + this.emote = new Text(this.scene, -12, 0, emote, { fontFamily: '"Twemoji Mozilla"', fontSize: "24px" }); this.emote.setAlpha(0); - this.emote.setScale(0.1 * scalingFactor); this.add(this.emote); - // this.scene.sys.updateList.add(this.emote); - this.createStartTransition(scalingFactor, emoteY); } @@ -287,11 +302,11 @@ export abstract class Character extends Container { alpha: 1, y: emoteY, }, - ease: 'Power2', + ease: "Power2", duration: 500, onComplete: () => { this.startPulseTransition(emoteY, scalingFactor); - } + }, }); } @@ -300,7 +315,7 @@ export abstract class Character extends Container { targets: this.emote, props: { y: emoteY * 1.3, - scale: scalingFactor * 1.1 + scale: scalingFactor * 1.1, }, duration: 250, yoyo: true, @@ -308,7 +323,7 @@ export abstract class Character extends Container { completeDelay: 200, onComplete: () => { this.startExitTransition(emoteY); - } + }, }); } @@ -319,11 +334,11 @@ export abstract class Character extends Container { alpha: 0, y: 2 * emoteY, }, - ease: 'Power2', + ease: "Power2", duration: 500, onComplete: () => { this.destroyEmote(); - } + }, }); } @@ -331,7 +346,7 @@ export abstract class Character extends Container { if (!this.emote) return; this.emoteTween?.remove(); - this.destroyEmote() + this.destroyEmote(); } private destroyEmote() { diff --git a/front/src/Phaser/Game/EmoteManager.ts b/front/src/Phaser/Game/EmoteManager.ts index 8316240c..06e8b099 100644 --- a/front/src/Phaser/Game/EmoteManager.ts +++ b/front/src/Phaser/Game/EmoteManager.ts @@ -1,8 +1,6 @@ -import {emoteEventStream} from "../../Connexion/EmoteEventStream"; -import type {GameScene} from "./GameScene"; -import type {Subscription} from "rxjs"; - -export const emotes: string[] = ['❤️', '👏', '✋', '🙏', '👍', '👎']; +import { emoteEventStream } from "../../Connexion/EmoteEventStream"; +import type { GameScene } from "./GameScene"; +import type { Subscription } from "rxjs"; export class EmoteManager { private subscription: Subscription; @@ -10,18 +8,13 @@ export class EmoteManager { constructor(private scene: GameScene) { this.subscription = emoteEventStream.stream.subscribe((event) => { const actor = this.scene.MapPlayersByKey.get(event.userId); - if(actor) { + if (actor) { actor.playEmote(event.emote); } - }) - } - - getEmotes(): string[] { - // TODO: localstorage + management - return emotes; + }); } destroy() { this.subscription.unsubscribe(); } -} \ No newline at end of file +} diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 096bd91f..aa840caf 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1319,9 +1319,9 @@ ${escapedMessage} 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. } - - this.CurrentPlayer.openOrCloseEmoteMenu( this.emoteManager.getEmotes()); - }) + + this.CurrentPlayer.openOrCloseEmoteMenu(); + }); this.CurrentPlayer.on(requestEmoteEventName, (emoteKey: string) => { this.connection?.emitEmoteEvent(emoteKey); }); diff --git a/front/src/Phaser/Player/Player.ts b/front/src/Phaser/Player/Player.ts index cd6f3fed..2dfae398 100644 --- a/front/src/Phaser/Player/Player.ts +++ b/front/src/Phaser/Player/Player.ts @@ -1,9 +1,9 @@ -import {PlayerAnimationDirections} from "./Animation"; -import type {GameScene} from "../Game/GameScene"; -import {UserInputEvent, UserInputManager} from "../UserInput/UserInputManager"; -import {Character} from "../Entity/Character"; -import {userMovingStore} from "../../Stores/GameStore"; -import {EmoteMenu, EmoteMenuClickEvent} from "../Components/EmoteMenu"; +import { PlayerAnimationDirections } from "./Animation"; +import type { GameScene } from "../Game/GameScene"; +import { UserInputEvent, UserInputManager } from "../UserInput/UserInputManager"; +import { Character } from "../Entity/Character"; +import { userMovingStore } from "../../Stores/GameStore"; +import { EmoteMenu, EmoteMenuClickEvent } from "../Components/EmoteMenu"; export const hasMovedEventName = "hasMoved"; export const requestEmoteEventName = "requestEmote"; @@ -11,7 +11,7 @@ export const requestEmoteEventName = "requestEmote"; export class Player extends Character { private previousDirection: string = PlayerAnimationDirections.Down; private wasMoving: boolean = false; - private emoteMenu: EmoteMenu|null = null; + private emoteMenu: EmoteMenu | null = null; private updateListener: () => void; constructor( @@ -23,7 +23,7 @@ export class Player extends Character { direction: PlayerAnimationDirections, moving: boolean, private userInputManager: UserInputManager, - companion: string|null, + companion: string | null, companionTexturePromise?: Promise ) { super(Scene, x, y, texturesPromise, name, direction, moving, 1, true, companion, companionTexturePromise); @@ -37,7 +37,7 @@ export class Player extends Character { this.emoteMenu.y = this.y; } }; - this.scene.events.addListener('postupdate', this.updateListener); + this.scene.events.addListener("postupdate", this.updateListener); } moveUser(delta: number): void { @@ -73,14 +73,14 @@ export class Player extends Character { if (x !== 0 || y !== 0) { this.move(x, y); - this.emit(hasMovedEventName, {moving, direction, x: this.x, y: this.y}); + this.emit(hasMovedEventName, { moving, direction, x: this.x, y: this.y }); } else if (this.wasMoving && moving) { // slow joystick movement this.move(0, 0); - this.emit(hasMovedEventName, {moving, direction: this.previousDirection, x: this.x, y: this.y}); + this.emit(hasMovedEventName, { moving, direction: this.previousDirection, x: this.x, y: this.y }); } else if (this.wasMoving && !moving) { this.stop(); - this.emit(hasMovedEventName, {moving, direction: this.previousDirection, x: this.x, y: this.y}); + this.emit(hasMovedEventName, { moving, direction: this.previousDirection, x: this.x, y: this.y }); } if (direction !== null) { @@ -94,17 +94,23 @@ export class Player extends Character { return this.wasMoving; } - openOrCloseEmoteMenu(emotes:string[]) { - if(this.emoteMenu) { + openOrCloseEmoteMenu() { + if (!this.emoteMenu) { + this.emoteMenu = new EmoteMenu(this.scene, this.x, this.y); + } + + if (this.emoteMenu.isOpen()) { this.closeEmoteMenu(); } else { - this.openEmoteMenu(emotes); + this.openEmoteMenu(); } } - openEmoteMenu(emotes:string[]): void { + openEmoteMenu(): void { this.cancelPreviousEmote(); - this.emoteMenu = new EmoteMenu(this.scene, this.x, this.y, emotes) + if (!this.emoteMenu) return; + this.userInputManager.disableControls(); + this.emoteMenu.openPicker(); this.emoteMenu.on(EmoteMenuClickEvent, (emote: string) => { this.closeEmoteMenu(); this.emit(requestEmoteEventName, emote); @@ -113,13 +119,13 @@ export class Player extends Character { } closeEmoteMenu(): void { + this.userInputManager.restoreControls(); if (!this.emoteMenu) return; - this.emoteMenu.destroy(); - this.emoteMenu = null; + this.emoteMenu.closePicker(); } destroy() { - this.scene.events.removeListener('postupdate', this.updateListener); + this.scene.events.removeListener("postupdate", this.updateListener); super.destroy(); } } diff --git a/front/style/fonts.scss b/front/style/fonts.scss index 7c3501d3..018dfa0d 100644 --- a/front/style/fonts.scss +++ b/front/style/fonts.scss @@ -6,7 +6,7 @@ } *{ - font-family: "Twemoji Mozilla",PixelFont-7,monospace; + font-family: PixelFont-7,monospace; } .nes-btn { diff --git a/front/webpack.config.ts b/front/webpack.config.ts index 37362baf..62fee59b 100644 --- a/front/webpack.config.ts +++ b/front/webpack.config.ts @@ -26,7 +26,7 @@ module.exports = { devServer: { contentBase: "./dist", host: "0.0.0.0", - sockPort: 80, + sockPort: 443, disableHostCheck: true, historyApiFallback: { rewrites: [{ from: /^_\/.*$/, to: "/index.html" }], diff --git a/front/yarn.lock b/front/yarn.lock index 6ee607d3..e8dc1166 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -62,6 +62,48 @@ resolved "https://registry.yarnpkg.com/@fontsource/press-start-2p/-/press-start-2p-4.3.0.tgz#37124387f7fbfe7792b5fc9a1906b80d9aeda4c6" integrity sha512-gmS4070EoZp5/6NUJ+tBnvtDiSmFcR+S+ClAOJ8NGFXDWOkO12yMnyGJEJaDCNCAMX0s2TQCcmr6qWKx5ad3RQ== +"@fortawesome/fontawesome-common-types@^0.2.35": + version "0.2.35" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.35.tgz#01dd3d054da07a00b764d78748df20daf2b317e9" + integrity sha512-IHUfxSEDS9dDGqYwIW7wTN6tn/O8E0n5PcAHz9cAaBoZw6UpG20IG/YM3NNLaGPwPqgjBAFjIURzqoQs3rrtuw== + +"@fortawesome/fontawesome-svg-core@^1.2.28": + version "1.2.35" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.35.tgz#85aea8c25645fcec88d35f2eb1045c38d3e65cff" + integrity sha512-uLEXifXIL7hnh2sNZQrIJWNol7cTVIzwI+4qcBIq9QWaZqUblm0IDrtSqbNg+3SQf8SMGHkiSigD++rHmCHjBg== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.2.35" + +"@fortawesome/free-regular-svg-icons@^5.13.0": + version "5.15.3" + resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.3.tgz#1ec4f2410ff638db549c5c5484fc60b66407dbe6" + integrity sha512-q4/p8Xehy9qiVTdDWHL4Z+o5PCLRChePGZRTXkl+/Z7erDVL8VcZUuqzJjs6gUz6czss4VIPBRdCz6wP37/zMQ== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.2.35" + +"@fortawesome/free-solid-svg-icons@^5.13.0": + version "5.15.3" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz#52eebe354f60dc77e0bde934ffc5c75ffd04f9d8" + integrity sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.2.35" + +"@joeattardi/emoji-button@^4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@joeattardi/emoji-button/-/emoji-button-4.6.0.tgz#93a78abb19c61ce9dcc464d15f373743b15cd2a2" + integrity sha512-KwOE1j+YxX47JmT0pXNCa+9Ai4Wf2fmABtvuxy6JBJ5QV0HdoThRKjL6CxAreVwwLbNQ/PDoR36xpc5QJjLXPA== + dependencies: + "@fortawesome/fontawesome-svg-core" "^1.2.28" + "@fortawesome/free-regular-svg-icons" "^5.13.0" + "@fortawesome/free-solid-svg-icons" "^5.13.0" + "@popperjs/core" "^2.4.0" + "@types/twemoji" "^12.1.1" + focus-trap "^5.1.0" + fuzzysort "^1.1.4" + tiny-emitter "^2.1.0" + tslib "^2.0.0" + twemoji "^13.0.0" + "@nodelib/fs.scandir@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" @@ -83,6 +125,11 @@ "@nodelib/fs.scandir" "2.1.4" fastq "^1.6.0" +"@popperjs/core@^2.4.0": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353" + integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q== + "@tsconfig/svelte@^1.0.10": version "1.0.10" resolved "https://registry.yarnpkg.com/@tsconfig/svelte/-/svelte-1.0.10.tgz#30ec7feeee0bdf38b12a50f0686f8a2e7b6b9dc0" @@ -284,6 +331,11 @@ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.7.tgz#545158342f949e8fd3bfd813224971ecddc3fac4" integrity sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ== +"@types/twemoji@^12.1.1": + version "12.1.2" + resolved "https://registry.yarnpkg.com/@types/twemoji/-/twemoji-12.1.2.tgz#52578fd22665311e6a78d04f800275449d51c97e" + integrity sha512-3eMyKenMi0R1CeKzBYtk/Z2JIHsTMQrIrTah0q54o45pHTpWVNofU2oHx0jS8tqsDRhis2TbB6238WP9oh2l2w== + "@types/uglify-js@*": version "3.13.0" resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.13.0.tgz#1cad8df1fb0b143c5aba08de5712ea9d1ff71124" @@ -2359,6 +2411,14 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== +focus-trap@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-5.1.0.tgz#64a0bfabd95c382103397dbc96bfef3a3cf8e5ad" + integrity sha512-CkB/nrO55069QAUjWFBpX6oc+9V90Qhgpe6fBWApzruMq5gnlh90Oo7iSSDK7pKiV5ugG6OY2AXM5mxcmL3lwQ== + dependencies: + tabbable "^4.0.0" + xtend "^4.0.1" + follow-redirects@^1.0.0, follow-redirects@^1.10.0: version "1.14.1" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" @@ -2410,6 +2470,15 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fs-extra@^8.0.1: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-extra@^9.0.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -2453,6 +2522,11 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +fuzzysort@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/fuzzysort/-/fuzzysort-1.1.4.tgz#a0510206ed44532cbb52cf797bf5a3cb12acd4ba" + integrity sha512-JzK/lHjVZ6joAg3OnCjylwYXYVjRiwTY6Yb25LvfpJHK8bjisfnZJ5bY8aVWwTwCXgxPNgLAtmHL+Hs5q1ddLQ== + generic-type-guard@^3.2.0: version "3.4.1" resolved "https://registry.yarnpkg.com/generic-type-guard/-/generic-type-guard-3.4.1.tgz#0896dc018de915c890562a34763858076e4676da" @@ -3324,6 +3398,22 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-5.0.0.tgz#e6b718f73da420d612823996fdf14a03f6ff6922" + integrity sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w== + dependencies: + universalify "^0.1.2" + optionalDependencies: + graceful-fs "^4.1.6" + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -5455,6 +5545,11 @@ svelte@^3.38.2: resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.38.2.tgz#55e5c681f793ae349b5cc2fe58e5782af4275ef5" integrity sha512-q5Dq0/QHh4BLJyEVWGe7Cej5NWs040LWjMbicBGZ+3qpFWJ1YObRmUDZKbbovddLC9WW7THTj3kYbTOFmU9fbg== +tabbable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261" + integrity sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ== + table@^6.0.4: version "6.7.1" resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" @@ -5529,6 +5624,11 @@ timers-browserify@^2.0.12: dependencies: setimmediate "^1.0.4" +tiny-emitter@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + to-array@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" @@ -5608,6 +5708,11 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + tslib@^2.0.3, tslib@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" @@ -5625,6 +5730,21 @@ tty-browserify@^0.0.1: resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== +twemoji-parser@13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-13.1.0.tgz#65e7e449c59258791b22ac0b37077349127e3ea4" + integrity sha512-AQOzLJpYlpWMy8n+0ATyKKZzWlZBJN+G0C+5lhX7Ftc2PeEVdUU/7ns2Pn2vVje26AIZ/OHwFoUbdv6YYD/wGg== + +twemoji@^13.0.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/twemoji/-/twemoji-13.1.0.tgz#65bb71e966dae56f0d42c30176f04cbdae109913" + integrity sha512-e3fZRl2S9UQQdBFLYXtTBT6o4vidJMnpWUAhJA+yLGR+kaUTZAt3PixC0cGvvxWSuq2MSz/o0rJraOXrWw/4Ew== + dependencies: + fs-extra "^8.0.1" + jsonfile "^5.0.0" + twemoji-parser "13.1.0" + universalify "^0.1.2" + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -5685,6 +5805,11 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" +universalify@^0.1.0, universalify@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" @@ -6069,7 +6194,7 @@ xmlhttprequest-ssl@~1.6.2: resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz#03b713873b01659dfa2c1c5d056065b27ddc2de6" integrity sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q== -xtend@^4.0.2: +xtend@^4.0.1, xtend@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==