Merge pull request #1647 from thecodingmachine/feature-picture-of-user-merge
User's WOKA used in UI (2)
This commit is contained in:
commit
08eab8dedb
39
front/src/Components/Companion/Companion.svelte
Normal file
39
front/src/Components/Companion/Companion.svelte
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<script lang="typescript">
|
||||||
|
import { onDestroy } from "svelte";
|
||||||
|
|
||||||
|
import { gameManager } from "../../Phaser/Game/GameManager";
|
||||||
|
|
||||||
|
export let userId: number;
|
||||||
|
export let placeholderSrc: string;
|
||||||
|
export let width: string = "62px";
|
||||||
|
export let height: string = "62px";
|
||||||
|
|
||||||
|
const gameScene = gameManager.getCurrentGameScene();
|
||||||
|
const playerWokaPictureStore = gameScene.getUserCompanionPictureStore(userId);
|
||||||
|
|
||||||
|
let src = placeholderSrc;
|
||||||
|
const unsubscribe = playerWokaPictureStore.picture.subscribe((source) => {
|
||||||
|
src = source ?? placeholderSrc;
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(unsubscribe);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<img {src} alt="" class="nes-pointer" style="--theme-width: {width}; --theme-height: {height}" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
img {
|
||||||
|
display: inline-block;
|
||||||
|
pointer-events: auto;
|
||||||
|
width: var(--theme-width);
|
||||||
|
height: var(--theme-height);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: static;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import logoWA from "../images/logo-WA-pixel.png";
|
|
||||||
import logoTalk from "../images/logo-message-pixel.png";
|
import logoTalk from "../images/logo-message-pixel.png";
|
||||||
|
import logoWA from "../images/logo-WA-pixel.png";
|
||||||
import { menuVisiblilityStore } from "../../Stores/MenuStore";
|
import { menuVisiblilityStore } from "../../Stores/MenuStore";
|
||||||
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
@ -31,6 +31,7 @@
|
|||||||
width: 60px;
|
width: 60px;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
margin: 3px;
|
margin: 3px;
|
||||||
|
image-rendering: pixelated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.menuIcon img:hover {
|
.menuIcon img:hover {
|
||||||
@ -38,9 +39,26 @@
|
|||||||
}
|
}
|
||||||
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
||||||
.menuIcon {
|
.menuIcon {
|
||||||
margin: 3px;
|
display: inline-grid;
|
||||||
|
z-index: 90;
|
||||||
|
position: relative;
|
||||||
|
margin: 25px;
|
||||||
img {
|
img {
|
||||||
width: 50px;
|
pointer-events: auto;
|
||||||
|
width: 60px;
|
||||||
|
padding-top: 0;
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.menuIcon img:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
||||||
|
.menuIcon {
|
||||||
|
margin: 3px;
|
||||||
|
img {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
import btnProfileSubMenuCamera from "../images/btn-menu-profile-camera.svg";
|
import btnProfileSubMenuCamera from "../images/btn-menu-profile-camera.svg";
|
||||||
import btnProfileSubMenuIdentity from "../images/btn-menu-profile-identity.svg";
|
import btnProfileSubMenuIdentity from "../images/btn-menu-profile-identity.svg";
|
||||||
import btnProfileSubMenuCompanion from "../images/btn-menu-profile-companion.svg";
|
import btnProfileSubMenuCompanion from "../images/btn-menu-profile-companion.svg";
|
||||||
import btnProfileSubMenuWoka from "../images/btn-menu-profile-woka.svg";
|
import Woka from "../Woka/Woka.svelte";
|
||||||
|
import Companion from "../Companion/Companion.svelte";
|
||||||
|
|
||||||
function disableMenuStores() {
|
function disableMenuStores() {
|
||||||
menuVisiblilityStore.set(false);
|
menuVisiblilityStore.set(false);
|
||||||
@ -65,11 +66,11 @@
|
|||||||
<span class="btn-hover">Edit your name</span>
|
<span class="btn-hover">Edit your name</span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="nes-btn" on:click|preventDefault={openEditSkinScene}>
|
<button type="button" class="nes-btn" on:click|preventDefault={openEditSkinScene}>
|
||||||
<img src={btnProfileSubMenuWoka} alt="Edit your WOKA" />
|
<Woka userId={-1} placeholderSrc="" width="26px" height="26px" />
|
||||||
<span class="btn-hover">Edit your WOKA</span>
|
<span class="btn-hover">Edit your WOKA</span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="nes-btn" on:click|preventDefault={openEditCompanionScene}>
|
<button type="button" class="nes-btn" on:click|preventDefault={openEditCompanionScene}>
|
||||||
<img src={btnProfileSubMenuCompanion} alt="Edit your companion" />
|
<Companion userId={-1} placeholderSrc={btnProfileSubMenuCompanion} width="26px" height="26px" />
|
||||||
<span class="btn-hover">Edit your companion</span>
|
<span class="btn-hover">Edit your companion</span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="nes-btn" on:click|preventDefault={openEnableCameraScene}>
|
<button type="button" class="nes-btn" on:click|preventDefault={openEnableCameraScene}>
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
import { showReportScreenStore } from "../../Stores/ShowReportScreenStore";
|
import { showReportScreenStore } from "../../Stores/ShowReportScreenStore";
|
||||||
import { getColorByString, srcObject } from "./utils";
|
import { getColorByString, srcObject } from "./utils";
|
||||||
|
|
||||||
|
import Woka from "../Woka/Woka.svelte";
|
||||||
|
|
||||||
export let peer: VideoPeer;
|
export let peer: VideoPeer;
|
||||||
let streamStore = peer.streamStore;
|
let streamStore = peer.streamStore;
|
||||||
let name = peer.userName;
|
let name = peer.userName;
|
||||||
@ -26,9 +28,15 @@
|
|||||||
{#if $statusStore === "error"}
|
{#if $statusStore === "error"}
|
||||||
<div class="rtc-error" />
|
<div class="rtc-error" />
|
||||||
{/if}
|
{/if}
|
||||||
{#if !$constraintStore || $constraintStore.video === false}
|
<!-- {#if !$constraintStore || $constraintStore.video === false} -->
|
||||||
<i style="background-color: {getColorByString(name)};">{name}</i>
|
<i
|
||||||
{/if}
|
class="container {!$constraintStore || $constraintStore.video === false ? '' : 'minimized'}"
|
||||||
|
style="background-color: {getColorByString(name)};"
|
||||||
|
>
|
||||||
|
<span>{peer.userName}</span>
|
||||||
|
<div class="woka-icon"><Woka userId={peer.userId} placeholderSrc={""} /></div>
|
||||||
|
</i>
|
||||||
|
<!-- {/if} -->
|
||||||
{#if $constraintStore && $constraintStore.audio === false}
|
{#if $constraintStore && $constraintStore.audio === false}
|
||||||
<img src={microphoneCloseImg} class="active" alt="Muted" />
|
<img src={microphoneCloseImg} class="active" alt="Muted" />
|
||||||
{/if}
|
{/if}
|
||||||
@ -43,3 +51,21 @@
|
|||||||
<SoundMeterWidget stream={$streamStore} />
|
<SoundMeterWidget stream={$streamStore} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.minimized {
|
||||||
|
left: auto;
|
||||||
|
transform: scale(0.5);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.woka-icon {
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
39
front/src/Components/Woka/Woka.svelte
Normal file
39
front/src/Components/Woka/Woka.svelte
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<script lang="typescript">
|
||||||
|
import { onDestroy } from "svelte";
|
||||||
|
|
||||||
|
import { gameManager } from "../../Phaser/Game/GameManager";
|
||||||
|
|
||||||
|
export let userId: number;
|
||||||
|
export let placeholderSrc: string;
|
||||||
|
export let width: string = "62px";
|
||||||
|
export let height: string = "62px";
|
||||||
|
|
||||||
|
const gameScene = gameManager.getCurrentGameScene();
|
||||||
|
const playerWokaPictureStore = gameScene.getUserWokaPictureStore(userId);
|
||||||
|
|
||||||
|
let src = placeholderSrc;
|
||||||
|
const unsubscribe = playerWokaPictureStore.picture.subscribe((source) => {
|
||||||
|
src = source ?? placeholderSrc;
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(unsubscribe);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<img {src} alt="" class="nes-pointer" style="--theme-width: {width}; --theme-height: {height}" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
img {
|
||||||
|
display: inline-block;
|
||||||
|
pointer-events: auto;
|
||||||
|
width: var(--theme-width);
|
||||||
|
height: var(--theme-height);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: static;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,6 +1,7 @@
|
|||||||
import Sprite = Phaser.GameObjects.Sprite;
|
import Sprite = Phaser.GameObjects.Sprite;
|
||||||
import Container = Phaser.GameObjects.Container;
|
import Container = Phaser.GameObjects.Container;
|
||||||
import { PlayerAnimationDirections, PlayerAnimationTypes } from "../Player/Animation";
|
import { PlayerAnimationDirections, PlayerAnimationTypes } from "../Player/Animation";
|
||||||
|
import { TexturesHelper } from "../Helpers/TexturesHelper";
|
||||||
|
|
||||||
export interface CompanionStatus {
|
export interface CompanionStatus {
|
||||||
x: number;
|
x: number;
|
||||||
@ -39,6 +40,7 @@ export class Companion extends Container {
|
|||||||
texturePromise.then((resource) => {
|
texturePromise.then((resource) => {
|
||||||
this.addResource(resource);
|
this.addResource(resource);
|
||||||
this.invisible = false;
|
this.invisible = false;
|
||||||
|
this.emit("texture-loaded");
|
||||||
});
|
});
|
||||||
|
|
||||||
this.scene.physics.world.enableBody(this);
|
this.scene.physics.world.enableBody(this);
|
||||||
@ -123,6 +125,22 @@ export class Companion extends Container {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getSnapshot(): Promise<string> {
|
||||||
|
const sprites = Array.from(this.sprites.values()).map((sprite) => {
|
||||||
|
return { sprite, frame: 1 };
|
||||||
|
});
|
||||||
|
return TexturesHelper.getSnapshot(this.scene, ...sprites).catch((reason) => {
|
||||||
|
console.warn(reason);
|
||||||
|
for (const sprite of this.sprites.values()) {
|
||||||
|
// it can be either cat or dog prefix
|
||||||
|
if (sprite.texture.key.includes("cat") || sprite.texture.key.includes("dog")) {
|
||||||
|
return this.scene.textures.getBase64(sprite.texture.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "cat1";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private playAnimation(direction: PlayerAnimationDirections, type: PlayerAnimationTypes): void {
|
private playAnimation(direction: PlayerAnimationDirections, type: PlayerAnimationTypes): void {
|
||||||
if (this.invisible) return;
|
if (this.invisible) return;
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@ import { TextureError } from "../../Exception/TextureError";
|
|||||||
import { Companion } from "../Companion/Companion";
|
import { Companion } from "../Companion/Companion";
|
||||||
import type { GameScene } from "../Game/GameScene";
|
import type { GameScene } from "../Game/GameScene";
|
||||||
import { DEPTH_INGAME_TEXT_INDEX } from "../Game/DepthIndexes";
|
import { DEPTH_INGAME_TEXT_INDEX } from "../Game/DepthIndexes";
|
||||||
import { waScaleManager } from "../Services/WaScaleManager";
|
|
||||||
import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js";
|
import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js";
|
||||||
import { isSilentStore } from "../../Stores/MediaStore";
|
import { isSilentStore } from "../../Stores/MediaStore";
|
||||||
import { lazyLoadPlayerCharacterTextures } from "./PlayerTexturesLoadingManager";
|
import { lazyLoadPlayerCharacterTextures, loadAllDefaultModels } from "./PlayerTexturesLoadingManager";
|
||||||
|
import { TexturesHelper } from "../Helpers/TexturesHelper";
|
||||||
|
|
||||||
const playerNameY = -25;
|
const playerNameY = -25;
|
||||||
|
|
||||||
@ -64,6 +64,7 @@ export abstract class Character extends Container {
|
|||||||
this.addTextures(textures, frame);
|
this.addTextures(textures, frame);
|
||||||
this.invisible = false;
|
this.invisible = false;
|
||||||
this.playAnimation(direction, moving);
|
this.playAnimation(direction, moving);
|
||||||
|
this.emit("woka-textures-loaded");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
return lazyLoadPlayerCharacterTextures(scene.load, ["color_22", "eyes_23"]).then((textures) => {
|
return lazyLoadPlayerCharacterTextures(scene.load, ["color_22", "eyes_23"]).then((textures) => {
|
||||||
@ -117,13 +118,28 @@ export abstract class Character extends Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getOutlinePlugin(): OutlinePipelinePlugin | undefined {
|
public async getSnapshot(): Promise<string> {
|
||||||
return this.scene.plugins.get("rexOutlinePipeline") as unknown as OutlinePipelinePlugin | undefined;
|
const sprites = Array.from(this.sprites.values()).map((sprite) => {
|
||||||
|
return { sprite, frame: 1 };
|
||||||
|
});
|
||||||
|
return TexturesHelper.getSnapshot(this.scene, ...sprites).catch((reason) => {
|
||||||
|
console.warn(reason);
|
||||||
|
for (const sprite of this.sprites.values()) {
|
||||||
|
// we can be sure that either predefined woka or body texture is at this point loaded
|
||||||
|
if (sprite.texture.key.includes("color") || sprite.texture.key.includes("male")) {
|
||||||
|
return this.scene.textures.getBase64(sprite.texture.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "male1";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public addCompanion(name: string, texturePromise?: Promise<string>): void {
|
public addCompanion(name: string, texturePromise?: Promise<string>): void {
|
||||||
if (typeof texturePromise !== "undefined") {
|
if (typeof texturePromise !== "undefined") {
|
||||||
this.companion = new Companion(this.scene, this.x, this.y, name, texturePromise);
|
this.companion = new Companion(this.scene, this.x, this.y, name, texturePromise);
|
||||||
|
this.companion.once("texture-loaded", () => {
|
||||||
|
this.emit("companion-texture-loaded", this.companion?.getSnapshot());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +170,10 @@ export abstract class Character extends Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getOutlinePlugin(): OutlinePipelinePlugin | undefined {
|
||||||
|
return this.scene.plugins.get("rexOutlinePipeline") as unknown as OutlinePipelinePlugin | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
private getPlayerAnimations(name: string): AnimationData[] {
|
private getPlayerAnimations(name: string): AnimationData[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,54 @@
|
|||||||
import type { Subscription } from "rxjs";
|
import type { Subscription } from "rxjs";
|
||||||
|
import AnimatedTiles from "phaser-animated-tiles";
|
||||||
|
import { Queue } from "queue-typescript";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
import { userMessageManager } from "../../Administration/UserMessageManager";
|
import { userMessageManager } from "../../Administration/UserMessageManager";
|
||||||
import { iframeListener } from "../../Api/IframeListener";
|
|
||||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||||
|
import { CoWebsite, coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
|
||||||
|
import { urlManager } from "../../Url/UrlManager";
|
||||||
|
import { mediaManager } from "../../WebRtc/MediaManager";
|
||||||
|
import { UserInputManager } from "../UserInput/UserInputManager";
|
||||||
|
import { gameManager } from "./GameManager";
|
||||||
|
import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
||||||
|
import { PinchManager } from "../UserInput/PinchManager";
|
||||||
|
import { waScaleManager } from "../Services/WaScaleManager";
|
||||||
|
import { EmoteManager } from "./EmoteManager";
|
||||||
|
import { soundManager } from "./SoundManager";
|
||||||
|
import { SharedVariablesManager } from "./SharedVariablesManager";
|
||||||
|
import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager";
|
||||||
|
|
||||||
|
import { lazyLoadPlayerCharacterTextures, loadCustomTexture } from "../Entity/PlayerTexturesLoadingManager";
|
||||||
|
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
||||||
|
import { ON_ACTION_TRIGGER_BUTTON } from "../../WebRtc/LayoutManager";
|
||||||
|
import { iframeListener } from "../../Api/IframeListener";
|
||||||
|
import { DEBUG_MODE, JITSI_PRIVATE_MODE, MAX_PER_GROUP, POSITION_DELAY } from "../../Enum/EnvironmentVariable";
|
||||||
|
import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils";
|
||||||
|
import { Room } from "../../Connexion/Room";
|
||||||
|
import { jitsiFactory } from "../../WebRtc/JitsiFactory";
|
||||||
|
import { TextureError } from "../../Exception/TextureError";
|
||||||
|
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||||
|
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||||
|
import { SimplePeer } from "../../WebRtc/SimplePeer";
|
||||||
|
import { Loader } from "../Components/Loader";
|
||||||
|
import { RemotePlayer } from "../Entity/RemotePlayer";
|
||||||
|
import { SelectCharacterScene, SelectCharacterSceneName } from "../Login/SelectCharacterScene";
|
||||||
|
import { PlayerAnimationDirections } from "../Player/Animation";
|
||||||
|
import { hasMovedEventName, Player, requestEmoteEventName } from "../Player/Player";
|
||||||
|
import { ErrorSceneName } from "../Reconnecting/ErrorScene";
|
||||||
|
import { ReconnectingSceneName } from "../Reconnecting/ReconnectingScene";
|
||||||
|
import { GameMap } from "./GameMap";
|
||||||
|
import { PlayerMovement } from "./PlayerMovement";
|
||||||
|
import { PlayersPositionInterpolator } from "./PlayersPositionInterpolator";
|
||||||
|
import { worldFullMessageStream } from "../../Connexion/WorldFullMessageStream";
|
||||||
|
import { DirtyScene } from "./DirtyScene";
|
||||||
|
import { TextUtils } from "../Components/TextUtils";
|
||||||
|
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
||||||
|
import { StartPositionCalculator } from "./StartPositionCalculator";
|
||||||
|
import { PropertyUtils } from "../Map/PropertyUtils";
|
||||||
|
import { GameMapPropertiesListener } from "./GameMapPropertiesListener";
|
||||||
|
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
||||||
|
import { GameMapProperties } from "./GameMapProperties";
|
||||||
import type {
|
import type {
|
||||||
GroupCreatedUpdatedMessageInterface,
|
GroupCreatedUpdatedMessageInterface,
|
||||||
MessageUserJoined,
|
MessageUserJoined,
|
||||||
@ -12,85 +59,36 @@ import type {
|
|||||||
PositionInterface,
|
PositionInterface,
|
||||||
RoomJoinedMessageInterface,
|
RoomJoinedMessageInterface,
|
||||||
} from "../../Connexion/ConnexionModels";
|
} from "../../Connexion/ConnexionModels";
|
||||||
import { DEBUG_MODE, JITSI_PRIVATE_MODE, MAX_PER_GROUP, POSITION_DELAY } from "../../Enum/EnvironmentVariable";
|
|
||||||
|
|
||||||
import { Queue } from "queue-typescript";
|
|
||||||
import { Box, ON_ACTION_TRIGGER_BUTTON } from "../../WebRtc/LayoutManager";
|
|
||||||
import { CoWebsite, coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
|
|
||||||
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
||||||
import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils";
|
|
||||||
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
||||||
import { Room } from "../../Connexion/Room";
|
|
||||||
import { jitsiFactory } from "../../WebRtc/JitsiFactory";
|
|
||||||
import { urlManager } from "../../Url/UrlManager";
|
|
||||||
import { TextureError } from "../../Exception/TextureError";
|
|
||||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
|
||||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
|
||||||
import { mediaManager } from "../../WebRtc/MediaManager";
|
|
||||||
import { SimplePeer } from "../../WebRtc/SimplePeer";
|
|
||||||
import { Loader } from "../Components/Loader";
|
|
||||||
import { lazyLoadPlayerCharacterTextures, loadCustomTexture } from "../Entity/PlayerTexturesLoadingManager";
|
|
||||||
import { RemotePlayer } from "../Entity/RemotePlayer";
|
|
||||||
import type { ActionableItem } from "../Items/ActionableItem";
|
import type { ActionableItem } from "../Items/ActionableItem";
|
||||||
import type { ItemFactoryInterface } from "../Items/ItemFactoryInterface";
|
import type { ItemFactoryInterface } from "../Items/ItemFactoryInterface";
|
||||||
import { SelectCharacterScene, SelectCharacterSceneName } from "../Login/SelectCharacterScene";
|
|
||||||
import type { ITiledMap, ITiledMapLayer, ITiledMapProperty, ITiledMapObject, ITiledTileSet } from "../Map/ITiledMap";
|
import type { ITiledMap, ITiledMapLayer, ITiledMapProperty, ITiledMapObject, ITiledTileSet } from "../Map/ITiledMap";
|
||||||
import { PlayerAnimationDirections } from "../Player/Animation";
|
|
||||||
import { hasMovedEventName, Player, requestEmoteEventName } from "../Player/Player";
|
|
||||||
import { ErrorSceneName } from "../Reconnecting/ErrorScene";
|
|
||||||
import { ReconnectingSceneName } from "../Reconnecting/ReconnectingScene";
|
|
||||||
import { UserInputManager } from "../UserInput/UserInputManager";
|
|
||||||
import type { AddPlayerInterface } from "./AddPlayerInterface";
|
import type { AddPlayerInterface } from "./AddPlayerInterface";
|
||||||
import { gameManager } from "./GameManager";
|
import { CameraManager } from "./CameraManager";
|
||||||
import { GameMap } from "./GameMap";
|
import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent";
|
||||||
import { PlayerMovement } from "./PlayerMovement";
|
import type { Character } from "../Entity/Character";
|
||||||
import { PlayersPositionInterpolator } from "./PlayersPositionInterpolator";
|
|
||||||
|
import { peerStore } from "../../Stores/PeerStore";
|
||||||
|
import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStore";
|
||||||
|
import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
||||||
|
import { playersStore } from "../../Stores/PlayersStore";
|
||||||
|
import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore";
|
||||||
|
import { userIsAdminStore } from "../../Stores/GameStore";
|
||||||
|
import { contactPageStore } from "../../Stores/MenuStore";
|
||||||
|
import { audioManagerFileStore, audioManagerVisibilityStore } from "../../Stores/AudioManagerStore";
|
||||||
|
import { UserWokaPictureStore } from "../../Stores/UserWokaPictureStore";
|
||||||
|
import { UserCompanionPictureStore } from "../../Stores/UserCompanionPictureStore";
|
||||||
|
|
||||||
|
import EVENT_TYPE = Phaser.Scenes.Events;
|
||||||
import Texture = Phaser.Textures.Texture;
|
import Texture = Phaser.Textures.Texture;
|
||||||
import Sprite = Phaser.GameObjects.Sprite;
|
import Sprite = Phaser.GameObjects.Sprite;
|
||||||
import CanvasTexture = Phaser.Textures.CanvasTexture;
|
import CanvasTexture = Phaser.Textures.CanvasTexture;
|
||||||
import GameObject = Phaser.GameObjects.GameObject;
|
import GameObject = Phaser.GameObjects.GameObject;
|
||||||
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
|
||||||
import DOMElement = Phaser.GameObjects.DOMElement;
|
import DOMElement = Phaser.GameObjects.DOMElement;
|
||||||
import { worldFullMessageStream } from "../../Connexion/WorldFullMessageStream";
|
|
||||||
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
|
||||||
import { DirtyScene } from "./DirtyScene";
|
|
||||||
import { TextUtils } from "../Components/TextUtils";
|
|
||||||
import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
|
||||||
import { PinchManager } from "../UserInput/PinchManager";
|
|
||||||
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
|
||||||
import { waScaleManager } from "../Services/WaScaleManager";
|
|
||||||
import { EmoteManager } from "./EmoteManager";
|
|
||||||
import { CameraManager } from "./CameraManager";
|
|
||||||
import EVENT_TYPE = Phaser.Scenes.Events;
|
|
||||||
import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent";
|
|
||||||
|
|
||||||
import AnimatedTiles from "phaser-animated-tiles";
|
|
||||||
import { StartPositionCalculator } from "./StartPositionCalculator";
|
|
||||||
import { soundManager } from "./SoundManager";
|
|
||||||
import { peerStore, screenSharingPeerStore } from "../../Stores/PeerStore";
|
|
||||||
import { videoFocusStore } from "../../Stores/VideoFocusStore";
|
|
||||||
import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStore";
|
|
||||||
import { SharedVariablesManager } from "./SharedVariablesManager";
|
|
||||||
import { playersStore } from "../../Stores/PlayersStore";
|
|
||||||
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
|
||||||
import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore";
|
|
||||||
import {
|
|
||||||
audioManagerFileStore,
|
|
||||||
audioManagerVisibilityStore,
|
|
||||||
audioManagerVolumeStore,
|
|
||||||
} from "../../Stores/AudioManagerStore";
|
|
||||||
import { PropertyUtils } from "../Map/PropertyUtils";
|
|
||||||
import Tileset = Phaser.Tilemaps.Tileset;
|
import Tileset = Phaser.Tilemaps.Tileset;
|
||||||
import { userIsAdminStore } from "../../Stores/GameStore";
|
|
||||||
import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
|
||||||
import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager";
|
|
||||||
import { GameMapPropertiesListener } from "./GameMapPropertiesListener";
|
|
||||||
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
|
||||||
import { get } from "svelte/store";
|
|
||||||
import { contactPageStore } from "../../Stores/MenuStore";
|
|
||||||
import { GameMapProperties } from "./GameMapProperties";
|
|
||||||
import SpriteSheetFile = Phaser.Loader.FileTypes.SpriteSheetFile;
|
import SpriteSheetFile = Phaser.Loader.FileTypes.SpriteSheetFile;
|
||||||
|
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface | null;
|
initPosition: PointInterface | null;
|
||||||
reconnecting: boolean;
|
reconnecting: boolean;
|
||||||
@ -206,6 +204,11 @@ export class GameScene extends DirtyScene {
|
|||||||
private objectsByType = new Map<string, ITiledMapObject[]>();
|
private objectsByType = new Map<string, ITiledMapObject[]>();
|
||||||
private embeddedWebsiteManager!: EmbeddedWebsiteManager;
|
private embeddedWebsiteManager!: EmbeddedWebsiteManager;
|
||||||
private loader: Loader;
|
private loader: Loader;
|
||||||
|
private userWokaPictureStores: Map<number, UserWokaPictureStore> = new Map<number, UserWokaPictureStore>();
|
||||||
|
private userCompanionPictureStores: Map<number, UserCompanionPictureStore> = new Map<
|
||||||
|
number,
|
||||||
|
UserCompanionPictureStore
|
||||||
|
>();
|
||||||
|
|
||||||
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
|
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
|
||||||
super({
|
super({
|
||||||
@ -339,6 +342,24 @@ export class GameScene extends DirtyScene {
|
|||||||
this.loader.addLoader();
|
this.loader.addLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getUserWokaPictureStore(userId: number) {
|
||||||
|
let store = this.userWokaPictureStores.get(userId);
|
||||||
|
if (!store) {
|
||||||
|
store = new UserWokaPictureStore();
|
||||||
|
this.userWokaPictureStores.set(userId, store);
|
||||||
|
}
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getUserCompanionPictureStore(userId: number) {
|
||||||
|
let store = this.userCompanionPictureStores.get(userId);
|
||||||
|
if (!store) {
|
||||||
|
store = new UserCompanionPictureStore();
|
||||||
|
this.userCompanionPictureStores.set(userId, store);
|
||||||
|
}
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: we need to put a "unknown" instead of a "any" and validate the structure of the JSON we are receiving.
|
// FIXME: we need to put a "unknown" instead of a "any" and validate the structure of the JSON we are receiving.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
private async onMapLoad(data: any): Promise<void> {
|
private async onMapLoad(data: any): Promise<void> {
|
||||||
@ -674,7 +695,6 @@ export class GameScene extends DirtyScene {
|
|||||||
this.connection = onConnect.connection;
|
this.connection = onConnect.connection;
|
||||||
|
|
||||||
playersStore.connectToRoomConnection(this.connection);
|
playersStore.connectToRoomConnection(this.connection);
|
||||||
|
|
||||||
userIsAdminStore.set(this.connection.hasTag("admin"));
|
userIsAdminStore.set(this.connection.hasTag("admin"));
|
||||||
|
|
||||||
this.connection.onUserJoins((message: MessageUserJoined) => {
|
this.connection.onUserJoins((message: MessageUserJoined) => {
|
||||||
@ -1539,6 +1559,14 @@ ${escapedMessage}
|
|||||||
this.companion,
|
this.companion,
|
||||||
this.companion !== null ? lazyLoadCompanionResource(this.load, this.companion) : undefined
|
this.companion !== null ? lazyLoadCompanionResource(this.load, this.companion) : undefined
|
||||||
);
|
);
|
||||||
|
this.CurrentPlayer.once("woka-textures-loaded", () => {
|
||||||
|
this.savePlayerWokaPicture(this.CurrentPlayer, -1);
|
||||||
|
});
|
||||||
|
this.CurrentPlayer.once("companion-texture-loaded", (snapshotPromise: Promise<string>) => {
|
||||||
|
snapshotPromise.then((snapshot: string) => {
|
||||||
|
this.savePlayerCompanionPicture(-1, snapshot);
|
||||||
|
});
|
||||||
|
});
|
||||||
this.CurrentPlayer.on("pointerdown", (pointer: Phaser.Input.Pointer) => {
|
this.CurrentPlayer.on("pointerdown", (pointer: Phaser.Input.Pointer) => {
|
||||||
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.
|
||||||
@ -1566,6 +1594,15 @@ ${escapedMessage}
|
|||||||
this.createCollisionWithPlayer();
|
this.createCollisionWithPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async savePlayerWokaPicture(character: Character, userId: number): Promise<void> {
|
||||||
|
const htmlImageElementSrc = await character.getSnapshot();
|
||||||
|
this.getUserWokaPictureStore(userId).picture.set(htmlImageElementSrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private savePlayerCompanionPicture(userId: number, snapshot: string): void {
|
||||||
|
this.getUserCompanionPictureStore(userId).picture.set(snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
pushPlayerPosition(event: HasPlayerMovedEvent) {
|
pushPlayerPosition(event: HasPlayerMovedEvent) {
|
||||||
if (this.lastMoveEventSent === event) {
|
if (this.lastMoveEventSent === event) {
|
||||||
return;
|
return;
|
||||||
@ -1753,6 +1790,9 @@ ${escapedMessage}
|
|||||||
addPlayerData.companion,
|
addPlayerData.companion,
|
||||||
addPlayerData.companion !== null ? lazyLoadCompanionResource(this.load, addPlayerData.companion) : undefined
|
addPlayerData.companion !== null ? lazyLoadCompanionResource(this.load, addPlayerData.companion) : undefined
|
||||||
);
|
);
|
||||||
|
player.once("woka-textures-loaded", () => {
|
||||||
|
this.savePlayerWokaPicture(player, addPlayerData.userId);
|
||||||
|
});
|
||||||
this.MapPlayers.add(player);
|
this.MapPlayers.add(player);
|
||||||
this.MapPlayersByKey.set(player.userId, player);
|
this.MapPlayersByKey.set(player.userId, player);
|
||||||
player.updatePosition(addPlayerData.position);
|
player.updatePosition(addPlayerData.position);
|
||||||
|
34
front/src/Phaser/Helpers/TexturesHelper.ts
Normal file
34
front/src/Phaser/Helpers/TexturesHelper.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
export class TexturesHelper {
|
||||||
|
public static async getSnapshot(
|
||||||
|
scene: Phaser.Scene,
|
||||||
|
...sprites: { sprite: Phaser.GameObjects.Sprite; frame?: string | number }[]
|
||||||
|
): Promise<string> {
|
||||||
|
const rt = scene.make.renderTexture({}, false);
|
||||||
|
try {
|
||||||
|
for (const { sprite, frame } of sprites) {
|
||||||
|
if (frame) {
|
||||||
|
sprite.setFrame(frame);
|
||||||
|
}
|
||||||
|
rt.draw(sprite, sprite.displayWidth * 0.5, sprite.displayHeight * 0.5);
|
||||||
|
}
|
||||||
|
return new Promise<string>((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
rt.snapshot(
|
||||||
|
(url) => {
|
||||||
|
resolve((url as HTMLImageElement).src);
|
||||||
|
rt.destroy();
|
||||||
|
},
|
||||||
|
"image/png",
|
||||||
|
1
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
rt.destroy();
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
rt.destroy();
|
||||||
|
throw new Error("Could not get the snapshot");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
front/src/Stores/UserCompanionPictureStore.ts
Normal file
8
front/src/Stores/UserCompanionPictureStore.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { writable, Writable } from "svelte/store";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A store that contains the player companion picture
|
||||||
|
*/
|
||||||
|
export class UserCompanionPictureStore {
|
||||||
|
constructor(public picture: Writable<string | undefined> = writable(undefined)) {}
|
||||||
|
}
|
8
front/src/Stores/UserWokaPictureStore.ts
Normal file
8
front/src/Stores/UserWokaPictureStore.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { writable, Writable } from "svelte/store";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A store that contains the player avatar picture
|
||||||
|
*/
|
||||||
|
export class UserWokaPictureStore {
|
||||||
|
constructor(public picture: Writable<string | undefined> = writable(undefined)) {}
|
||||||
|
}
|
@ -62,8 +62,7 @@ body .message-info.warning{
|
|||||||
background-color: black;
|
background-color: black;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 32px;
|
font-size: 14px;
|
||||||
font-size: 28px;
|
|
||||||
color: white;
|
color: white;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user