Merge branch 'develop' of github.com:thecodingmachine/workadventure into develop
This commit is contained in:
+1
-1
@@ -36,7 +36,7 @@ module.exports = {
|
||||
"eol-last": ["error", "always"],
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"no-throw-literal": "error",
|
||||
"@typescript-eslint/no-unused-vars": ["error"],
|
||||
"@typescript-eslint/no-unused-vars": ["error", { "args": "none", "caughtErrors": "all", "varsIgnorePattern": "_exhaustiveCheck" }],
|
||||
// TODO: remove those ignored rules and write a stronger code!
|
||||
"@typescript-eslint/no-unsafe-call": "off",
|
||||
"@typescript-eslint/restrict-plus-operands": "off",
|
||||
|
||||
+1
-1
@@ -42,8 +42,8 @@
|
||||
"buffer": "^6.0.3",
|
||||
"cancelable-promise": "^4.2.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"deep-copy-ts": "^0.5.0",
|
||||
"dompurify" : "^2.3.6",
|
||||
"deep-copy-ts": "^0.5.4",
|
||||
"easystarjs": "^0.4.4",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"google-protobuf": "^3.13.0",
|
||||
|
||||
@@ -297,7 +297,6 @@ class IframeListener {
|
||||
handleMenuUnregisterEvent(iframeEvent.data.name);
|
||||
} else {
|
||||
// Keep the line below. It will throw an error if we forget to handle one of the possible values.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const _exhaustiveCheck: never = iframeEvent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { WorkAdventureDesktopApi } from "@wa-preload-app";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
WAD: WorkAdventureDesktopApi;
|
||||
WAD?: WorkAdventureDesktopApi;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,6 @@ export function createState(target: "global" | "player"): WorkadventureStateComm
|
||||
}
|
||||
return target.loadVariable(p.toString());
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
set(target: WorkadventureStateCommands, p: PropertyKey, value: unknown, receiver: unknown): boolean {
|
||||
// Note: when using "set", there is no way to wait, so we ignore the return of the promise.
|
||||
// User must use WA.state.saveVariable to have error message.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import type { Game } from "../Phaser/Game/Game";
|
||||
import { chatVisibilityStore } from "../Stores/ChatStore";
|
||||
import { errorStore } from "../Stores/ErrorStore";
|
||||
import { errorScreenStore } from "../Stores/ErrorScreenStore";
|
||||
import { loginSceneVisibleStore } from "../Stores/LoginSceneStore";
|
||||
import { enableCameraSceneVisibilityStore } from "../Stores/MediaStore";
|
||||
import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore";
|
||||
@@ -13,11 +14,16 @@
|
||||
import SelectCharacterScene from "./selectCharacter/SelectCharacterScene.svelte";
|
||||
import SelectCompanionScene from "./SelectCompanion/SelectCompanionScene.svelte";
|
||||
import ErrorDialog from "./UI/ErrorDialog.svelte";
|
||||
import ErrorScreen from "./UI/ErrorScreen.svelte";
|
||||
|
||||
export let game: Game;
|
||||
</script>
|
||||
|
||||
{#if $errorStore.length > 0}
|
||||
{#if $errorScreenStore !== undefined}
|
||||
<div>
|
||||
<ErrorScreen />
|
||||
</div>
|
||||
{:else if $errorStore.length > 0}
|
||||
<div>
|
||||
<ErrorDialog />
|
||||
</div>
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
import { actionsMenuStore } from "../Stores/ActionsMenuStore";
|
||||
import ActionsMenu from "./ActionsMenu/ActionsMenu.svelte";
|
||||
import Lazy from "./Lazy.svelte";
|
||||
import { showDesktopCapturerSourcePicker } from "../Stores/ScreenSharingStore";
|
||||
|
||||
let mainLayout: HTMLDivElement;
|
||||
|
||||
@@ -119,6 +120,11 @@
|
||||
|
||||
<Lazy when={$emoteMenuStore} component={() => import("./EmoteMenu/EmoteMenu.svelte")} />
|
||||
|
||||
<Lazy
|
||||
when={$showDesktopCapturerSourcePicker}
|
||||
component={() => import("./Video/DesktopCapturerSourcePicker.svelte")}
|
||||
/>
|
||||
|
||||
{#if hasEmbedScreen}
|
||||
<EmbedScreensContainer />
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
<script lang="ts">
|
||||
import { fly } from "svelte/transition";
|
||||
import { errorScreenStore } from "../../Stores/ErrorScreenStore";
|
||||
import { gameManager } from "../../Phaser/Game/GameManager";
|
||||
import { get } from "svelte/store";
|
||||
import { onDestroy } from "svelte";
|
||||
|
||||
import logoImg from "../images/logo-min-white.png";
|
||||
let logo = gameManager?.currentStartedRoom?.loginSceneLogo ?? logoImg;
|
||||
import reload from "../images/reload.png";
|
||||
let errorScreen = get(errorScreenStore);
|
||||
|
||||
function click() {
|
||||
window.location.reload();
|
||||
}
|
||||
let details = errorScreen.details;
|
||||
let timeVar = errorScreen.timeToRetry ?? 0;
|
||||
|
||||
if (errorScreen.type === "retry") {
|
||||
let interval = setInterval(() => {
|
||||
if (timeVar <= 1000) click();
|
||||
timeVar -= 1000;
|
||||
}, 1000);
|
||||
onDestroy(() => clearInterval(interval));
|
||||
}
|
||||
|
||||
$: detailsStylized = (details ?? "").replace("{time}", `${timeVar / 1000}`);
|
||||
</script>
|
||||
|
||||
<main class="errorScreen" transition:fly={{ y: -200, duration: 500 }}>
|
||||
<div style="width: 90%;">
|
||||
<img src={logo} alt="WorkAdventure" class="logo" />
|
||||
<div><img src={$errorScreenStore.image} alt="" class="icon" /></div>
|
||||
{#if $errorScreenStore.type !== "retry"}<h2>{$errorScreenStore.title}</h2>{/if}
|
||||
<p>{$errorScreenStore.subtitle}</p>
|
||||
{#if $errorScreenStore.type !== "retry"}<p class="code">Code : {$errorScreenStore.code}</p>{/if}
|
||||
<p class="details">
|
||||
{detailsStylized}{#if $errorScreenStore.type === "retry"}<div class="loading" />{/if}
|
||||
</p>
|
||||
{#if $errorScreenStore.type === "retry" && $errorScreenStore.canRetryManual}
|
||||
<button type="button" class="nes-btn is-primary button" on:click={click}>
|
||||
<img src={reload} alt="" class="reload" />
|
||||
{$errorScreenStore.buttonTitle}
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style lang="scss">
|
||||
main.errorScreen {
|
||||
pointer-events: auto;
|
||||
width: 100%;
|
||||
background-color: #000000;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
min-width: 300px;
|
||||
z-index: 700;
|
||||
overflow-y: scroll;
|
||||
padding: 20px 0;
|
||||
.logo {
|
||||
width: 50%;
|
||||
margin-bottom: 50px;
|
||||
max-height: 25vh;
|
||||
max-width: 50vw;
|
||||
}
|
||||
.icon {
|
||||
height: 125px;
|
||||
margin-bottom: 25px;
|
||||
max-height: 25vh;
|
||||
max-width: 50vw;
|
||||
}
|
||||
h2 {
|
||||
font-family: "Press Start 2P";
|
||||
padding: 5px;
|
||||
font-size: 30px;
|
||||
}
|
||||
p {
|
||||
font-family: "Press Start 2P";
|
||||
}
|
||||
p.code {
|
||||
font-size: 12px;
|
||||
opacity: 0.6;
|
||||
user-select: text;
|
||||
}
|
||||
p.details {
|
||||
font-size: 12px;
|
||||
max-width: 80%;
|
||||
margin: 0 auto 35px auto;
|
||||
}
|
||||
.loading {
|
||||
display: inline-block;
|
||||
min-width: 20px;
|
||||
position: relative;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.loading:after {
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
-webkit-animation: ellipsis steps(4, end) 900ms infinite;
|
||||
animation: ellipsis steps(4, end) 900ms infinite;
|
||||
content: "\2026";
|
||||
width: 0;
|
||||
font-family: "Press Start 2P";
|
||||
font-size: 16px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -19px;
|
||||
}
|
||||
|
||||
@keyframes ellipsis {
|
||||
to {
|
||||
width: 1.25em;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes ellipsis {
|
||||
to {
|
||||
width: 1.25em;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
cursor: pointer;
|
||||
font-family: "Press Start 2P";
|
||||
font-size: 14px;
|
||||
.reload {
|
||||
margin-top: -4px;
|
||||
width: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,171 @@
|
||||
<script lang="ts">
|
||||
import { fly } from "svelte/transition";
|
||||
import {
|
||||
desktopCapturerSourcePromiseResolve,
|
||||
showDesktopCapturerSourcePicker,
|
||||
} from "../../Stores/ScreenSharingStore";
|
||||
import { onDestroy, onMount } from "svelte";
|
||||
import type { DesktopCapturerSource } from "@wa-preload-app";
|
||||
|
||||
let desktopCapturerSources: DesktopCapturerSource[] = [];
|
||||
let interval: ReturnType<typeof setInterval>;
|
||||
|
||||
async function getDesktopCapturerSources() {
|
||||
if (!window.WAD) {
|
||||
throw new Error("This component can only be used in the desktop app");
|
||||
}
|
||||
desktopCapturerSources = await window.WAD.getDesktopCapturerSources({
|
||||
thumbnailSize: {
|
||||
height: 144,
|
||||
width: 256,
|
||||
},
|
||||
types: ["screen", "window"],
|
||||
});
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
await getDesktopCapturerSources();
|
||||
interval = setInterval(() => {
|
||||
void getDesktopCapturerSources();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
|
||||
function selectDesktopCapturerSource(source: DesktopCapturerSource) {
|
||||
if (!desktopCapturerSourcePromiseResolve) {
|
||||
throw new Error("desktopCapturerSourcePromiseResolve is not defined");
|
||||
}
|
||||
desktopCapturerSourcePromiseResolve(source);
|
||||
close();
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
if (!desktopCapturerSourcePromiseResolve) {
|
||||
throw new Error("desktopCapturerSourcePromiseResolve is not defined");
|
||||
}
|
||||
desktopCapturerSourcePromiseResolve(null);
|
||||
close();
|
||||
}
|
||||
|
||||
function close() {
|
||||
$showDesktopCapturerSourcePicker = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="source-picker nes-container is-rounded" transition:fly={{ y: -50, duration: 500 }}>
|
||||
<button type="button" class="nes-btn is-error close" on:click={cancel}>×</button>
|
||||
<h2>Select a Screen or Window to share!</h2>
|
||||
<section class="streams">
|
||||
{#each desktopCapturerSources as source}
|
||||
<div
|
||||
class="media-box nes-container is-rounded clickable"
|
||||
on:click|preventDefault={() => selectDesktopCapturerSource(source)}
|
||||
>
|
||||
<img src={source.thumbnailURL} alt={source.name} />
|
||||
<div class="container">
|
||||
{source.name}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.source-picker {
|
||||
position: absolute;
|
||||
pointer-events: auto;
|
||||
background: #eceeee;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-top: 4%;
|
||||
height: 80vh;
|
||||
width: 80vw;
|
||||
max-width: 1024px;
|
||||
z-index: 900;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #333333;
|
||||
color: whitesmoke;
|
||||
|
||||
.nes-btn.is-error.close {
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
right: -20px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-family: "Press Start 2P";
|
||||
}
|
||||
|
||||
section.streams {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
overflow-y: auto;
|
||||
justify-content: center;
|
||||
align-content: flex-start;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.media-box {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
width: calc(100% / 3 - 20px);
|
||||
max-width: 256px;
|
||||
padding-bottom: calc(min((100% / 3 - 20px), 256px) * (144px / 256px));
|
||||
max-height: 144px;
|
||||
justify-content: center;
|
||||
background-color: #000;
|
||||
background-clip: padding-box;
|
||||
|
||||
&.clickable * {
|
||||
cursor: url("../../../style/images/cursor_pointer.png"), pointer;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
&.nes-container.is-rounded {
|
||||
border-image-outset: 1;
|
||||
}
|
||||
|
||||
div.container {
|
||||
position: absolute;
|
||||
width: 90%;
|
||||
height: auto;
|
||||
left: 5%;
|
||||
top: calc(100% - 28px);
|
||||
text-align: center;
|
||||
padding: 2px 36px;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 14px;
|
||||
margin: 2px;
|
||||
background-color: white;
|
||||
color: #333333;
|
||||
border: solid 3px black;
|
||||
border-radius: 8px;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
@@ -2,18 +2,19 @@
|
||||
import type { Game } from "../../Phaser/Game/Game";
|
||||
import { SelectCharacterScene, SelectCharacterSceneName } from "../../Phaser/Login/SelectCharacterScene";
|
||||
import LL from "../../i18n/i18n-svelte";
|
||||
import { customizeAvailableStore } from "../../Stores/SelectCharacterSceneStore";
|
||||
import { customizeAvailableStore, selectedCollection } from "../../Stores/SelectCharacterSceneStore";
|
||||
|
||||
export let game: Game;
|
||||
|
||||
const selectCharacterScene = game.scene.getScene(SelectCharacterSceneName) as SelectCharacterScene;
|
||||
const showArrows = selectCharacterScene.getCollectionKeysSize() > 1;
|
||||
|
||||
function selectLeft() {
|
||||
selectCharacterScene.moveToLeft();
|
||||
selectCharacterScene.selectPreviousCollection();
|
||||
}
|
||||
|
||||
function selectRight() {
|
||||
selectCharacterScene.moveToRight();
|
||||
selectCharacterScene.selectNextCollection();
|
||||
}
|
||||
|
||||
function cameraScene() {
|
||||
@@ -25,83 +26,72 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<form class="selectCharacterScene">
|
||||
<section class="text-center">
|
||||
<h2>{$LL.woka.selectWoka.title()}</h2>
|
||||
<button class="selectCharacterButton selectCharacterButtonLeft nes-btn" on:click|preventDefault={selectLeft}>
|
||||
<
|
||||
</button>
|
||||
<button class="selectCharacterButton selectCharacterButtonRight nes-btn" on:click|preventDefault={selectRight}>
|
||||
>
|
||||
</button>
|
||||
</section>
|
||||
<section class="action">
|
||||
<section class="text-center">
|
||||
<h2>{$LL.woka.selectWoka.title()}</h2>
|
||||
</section>
|
||||
<section class="category">
|
||||
{#if showArrows}
|
||||
<button class="selectCharacterButton nes-btn" on:click|preventDefault={selectLeft}> < </button>
|
||||
<strong class="category-text">{$selectedCollection}</strong>
|
||||
<button class="selectCharacterButton nes-btn" on:click|preventDefault={selectRight}> > </button>
|
||||
{/if}
|
||||
</section>
|
||||
<section class="action">
|
||||
<button
|
||||
type="submit"
|
||||
class="selectCharacterSceneFormSubmit nes-btn is-primary"
|
||||
on:click|preventDefault={cameraScene}>{$LL.woka.selectWoka.continue()}</button
|
||||
>
|
||||
{#if $customizeAvailableStore}
|
||||
<button
|
||||
type="submit"
|
||||
class="selectCharacterSceneFormSubmit nes-btn is-primary"
|
||||
on:click|preventDefault={cameraScene}>{$LL.woka.selectWoka.continue()}</button
|
||||
class="selectCharacterSceneFormCustomYourOwnSubmit nes-btn"
|
||||
on:click|preventDefault={customizeScene}>{$LL.woka.selectWoka.customize()}</button
|
||||
>
|
||||
{#if $customizeAvailableStore}
|
||||
<button
|
||||
type="submit"
|
||||
class="selectCharacterSceneFormCustomYourOwnSubmit nes-btn"
|
||||
on:click|preventDefault={customizeScene}>{$LL.woka.selectWoka.customize()}</button
|
||||
>
|
||||
{/if}
|
||||
</section>
|
||||
</form>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../../../style/breakpoints.scss";
|
||||
|
||||
form.selectCharacterScene {
|
||||
section {
|
||||
font-family: "Press Start 2P";
|
||||
color: #ebeeee;
|
||||
margin: 5px;
|
||||
|
||||
&.category {
|
||||
text-align: center;
|
||||
margin-top: 8vh;
|
||||
.category-text {
|
||||
font-family: "Press Start 2P";
|
||||
display: inline-block;
|
||||
width: 65%;
|
||||
}
|
||||
}
|
||||
|
||||
&.action {
|
||||
position: absolute;
|
||||
bottom: 2vh;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-family: "Press Start 2P";
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
&.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button.selectCharacterButton {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: "Press Start 2P";
|
||||
pointer-events: auto;
|
||||
color: #ebeeee;
|
||||
|
||||
section {
|
||||
margin: 10px;
|
||||
|
||||
&.action {
|
||||
text-align: center;
|
||||
margin-top: 55vh;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-family: "Press Start 2P";
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
&.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button.selectCharacterButton {
|
||||
position: absolute;
|
||||
top: 33vh;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: "Press Start 2P";
|
||||
|
||||
&.selectCharacterButtonLeft {
|
||||
left: 33vw;
|
||||
}
|
||||
|
||||
&.selectCharacterButtonRight {
|
||||
right: 33vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
form.selectCharacterScene button.selectCharacterButtonLeft {
|
||||
left: 5vw;
|
||||
}
|
||||
form.selectCharacterScene button.selectCharacterButtonRight {
|
||||
right: 5vw;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
TokenExpiredMessage,
|
||||
WorldConnexionMessage,
|
||||
ErrorMessage as ErrorMessageTsProto,
|
||||
ErrorScreenMessage as ErrorScreenMessageTsProto,
|
||||
UserMovedMessage as UserMovedMessageTsProto,
|
||||
GroupUpdateMessage as GroupUpdateMessageTsProto,
|
||||
GroupDeleteMessage as GroupDeleteMessageTsProto,
|
||||
@@ -47,6 +48,7 @@ import { Subject } from "rxjs";
|
||||
import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore";
|
||||
import { gameManager } from "../Phaser/Game/GameManager";
|
||||
import { SelectCharacterScene, SelectCharacterSceneName } from "../Phaser/Login/SelectCharacterScene";
|
||||
import { errorScreenStore } from "../Stores/ErrorScreenStore";
|
||||
|
||||
const manualPingDelay = 20000;
|
||||
|
||||
@@ -62,6 +64,9 @@ export class RoomConnection implements RoomConnection {
|
||||
private readonly _errorMessageStream = new Subject<ErrorMessageTsProto>();
|
||||
public readonly errorMessageStream = this._errorMessageStream.asObservable();
|
||||
|
||||
private readonly _errorScreenMessageStream = new Subject<ErrorScreenMessageTsProto>();
|
||||
public readonly errorScreenMessageStream = this._errorScreenMessageStream.asObservable();
|
||||
|
||||
private readonly _roomJoinedMessageStream = new Subject<{
|
||||
connection: RoomConnection;
|
||||
room: RoomJoinedMessageInterface;
|
||||
@@ -298,8 +303,7 @@ export class RoomConnection implements RoomConnection {
|
||||
}
|
||||
default: {
|
||||
// Security check: if we forget a "case", the line below will catch the error at compile-time.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const tmp: never = subMessage;
|
||||
const _exhaustiveCheck: never = subMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -477,10 +481,16 @@ export class RoomConnection implements RoomConnection {
|
||||
console.error("An error occurred server side: " + message.errorMessage.message);
|
||||
break;
|
||||
}
|
||||
case "errorScreenMessage": {
|
||||
this._errorScreenMessageStream.next(message.errorScreenMessage);
|
||||
if (message.errorScreenMessage.code !== "retry") this.closed = true;
|
||||
console.error("An error occurred server side: " + message.errorScreenMessage.code);
|
||||
errorScreenStore.setError(message.errorScreenMessage);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Security check: if we forget a "case", the line below will catch the error at compile-time.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const tmp: never = message;
|
||||
const _exhaustiveCheck: never = message;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { GridItem } from "@home-based-studio/phaser3-utils";
|
||||
|
||||
export class WokaSlot extends GridItem {
|
||||
private sprite: Phaser.GameObjects.Sprite;
|
||||
private selection: Phaser.GameObjects.Rectangle;
|
||||
|
||||
private readonly SIZE: number = 50;
|
||||
|
||||
constructor(scene: Phaser.Scene, spriteKey: string, id?: string) {
|
||||
super(scene, id);
|
||||
|
||||
this.sprite = this.scene.add.sprite(0, 0, spriteKey);
|
||||
this.selection = this.scene.add
|
||||
.rectangle(0, 0, this.SIZE, this.SIZE)
|
||||
.setStrokeStyle(1, 0xffffff)
|
||||
.setVisible(false);
|
||||
|
||||
this.add([this.selection, this.sprite]);
|
||||
this.setSize(this.SIZE, this.SIZE);
|
||||
this.setInteractive({ cursor: "pointer" });
|
||||
this.scene.input.setDraggable(this);
|
||||
|
||||
this.bindEventHandlers();
|
||||
|
||||
this.scene.add.existing(this);
|
||||
}
|
||||
|
||||
public getSprite(): Phaser.GameObjects.Sprite {
|
||||
return this.sprite;
|
||||
}
|
||||
|
||||
public select(select: boolean = true): void {
|
||||
this.selection.setVisible(select);
|
||||
}
|
||||
}
|
||||
@@ -36,14 +36,16 @@ export enum PlayerTexturesKey {
|
||||
}
|
||||
|
||||
export class PlayerTextures {
|
||||
private PLAYER_RESOURCES: BodyResourceDescriptionListInterface = {};
|
||||
private COLOR_RESOURCES: BodyResourceDescriptionListInterface = {};
|
||||
private EYES_RESOURCES: BodyResourceDescriptionListInterface = {};
|
||||
private HAIR_RESOURCES: BodyResourceDescriptionListInterface = {};
|
||||
private CLOTHES_RESOURCES: BodyResourceDescriptionListInterface = {};
|
||||
private HATS_RESOURCES: BodyResourceDescriptionListInterface = {};
|
||||
private ACCESSORIES_RESOURCES: BodyResourceDescriptionListInterface = {};
|
||||
private LAYERS: BodyResourceDescriptionListInterface[] = [];
|
||||
private wokaResources: BodyResourceDescriptionListInterface = {};
|
||||
private colorResources: BodyResourceDescriptionListInterface = {};
|
||||
private eyesResources: BodyResourceDescriptionListInterface = {};
|
||||
private hairResources: BodyResourceDescriptionListInterface = {};
|
||||
private clothesResources: BodyResourceDescriptionListInterface = {};
|
||||
private hatsResources: BodyResourceDescriptionListInterface = {};
|
||||
private accessoriesResources: BodyResourceDescriptionListInterface = {};
|
||||
private layers: BodyResourceDescriptionListInterface[] = [];
|
||||
|
||||
private wokaCollections = new Map<string, BodyResourceDescriptionInterface[]>();
|
||||
|
||||
public loadPlayerTexturesMetadata(metadata: WokaList): void {
|
||||
this.mapTexturesMetadataIntoResources(metadata);
|
||||
@@ -52,43 +54,53 @@ export class PlayerTextures {
|
||||
public getTexturesResources(key: PlayerTexturesKey): BodyResourceDescriptionListInterface {
|
||||
switch (key) {
|
||||
case PlayerTexturesKey.Accessory:
|
||||
return this.ACCESSORIES_RESOURCES;
|
||||
return this.accessoriesResources;
|
||||
case PlayerTexturesKey.Body:
|
||||
return this.COLOR_RESOURCES;
|
||||
return this.colorResources;
|
||||
case PlayerTexturesKey.Clothes:
|
||||
return this.CLOTHES_RESOURCES;
|
||||
return this.clothesResources;
|
||||
case PlayerTexturesKey.Eyes:
|
||||
return this.EYES_RESOURCES;
|
||||
return this.eyesResources;
|
||||
case PlayerTexturesKey.Hair:
|
||||
return this.HAIR_RESOURCES;
|
||||
return this.hairResources;
|
||||
case PlayerTexturesKey.Hat:
|
||||
return this.HATS_RESOURCES;
|
||||
return this.hatsResources;
|
||||
case PlayerTexturesKey.Woka:
|
||||
return this.PLAYER_RESOURCES;
|
||||
return this.wokaResources;
|
||||
}
|
||||
}
|
||||
|
||||
public getLayers(): BodyResourceDescriptionListInterface[] {
|
||||
return this.LAYERS;
|
||||
return this.layers;
|
||||
}
|
||||
|
||||
public getCollectionsKeys(): string[] {
|
||||
return Array.from(this.wokaCollections.keys());
|
||||
}
|
||||
|
||||
public getWokaCollectionTextures(key: string): BodyResourceDescriptionInterface[] {
|
||||
return this.wokaCollections.get(key) ?? [];
|
||||
}
|
||||
|
||||
private mapTexturesMetadataIntoResources(metadata: WokaList): void {
|
||||
this.PLAYER_RESOURCES = this.getMappedResources(metadata.woka);
|
||||
this.COLOR_RESOURCES = this.getMappedResources(metadata.body);
|
||||
this.EYES_RESOURCES = this.getMappedResources(metadata.eyes);
|
||||
this.HAIR_RESOURCES = this.getMappedResources(metadata.hair);
|
||||
this.CLOTHES_RESOURCES = this.getMappedResources(metadata.clothes);
|
||||
this.HATS_RESOURCES = this.getMappedResources(metadata.hat);
|
||||
this.ACCESSORIES_RESOURCES = this.getMappedResources(metadata.accessory);
|
||||
this.wokaResources = this.getMappedResources(metadata.woka);
|
||||
this.colorResources = this.getMappedResources(metadata.body);
|
||||
this.eyesResources = this.getMappedResources(metadata.eyes);
|
||||
this.hairResources = this.getMappedResources(metadata.hair);
|
||||
this.clothesResources = this.getMappedResources(metadata.clothes);
|
||||
this.hatsResources = this.getMappedResources(metadata.hat);
|
||||
this.accessoriesResources = this.getMappedResources(metadata.accessory);
|
||||
|
||||
this.LAYERS = [
|
||||
this.COLOR_RESOURCES,
|
||||
this.EYES_RESOURCES,
|
||||
this.HAIR_RESOURCES,
|
||||
this.CLOTHES_RESOURCES,
|
||||
this.HATS_RESOURCES,
|
||||
this.ACCESSORIES_RESOURCES,
|
||||
this.layers = [
|
||||
this.colorResources,
|
||||
this.eyesResources,
|
||||
this.hairResources,
|
||||
this.clothesResources,
|
||||
this.hatsResources,
|
||||
this.accessoriesResources,
|
||||
];
|
||||
|
||||
this.mapWokaCollections(metadata.woka);
|
||||
}
|
||||
|
||||
private getMappedResources(category: WokaPartType): BodyResourceDescriptionListInterface {
|
||||
@@ -103,6 +115,19 @@ export class PlayerTextures {
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
|
||||
private mapWokaCollections(category: WokaPartType): void {
|
||||
if (!category) {
|
||||
return;
|
||||
}
|
||||
for (const collection of category.collections) {
|
||||
const textures: BodyResourceDescriptionInterface[] = [];
|
||||
for (const texture of collection.textures) {
|
||||
textures.push({ id: texture.id, img: texture.url });
|
||||
}
|
||||
this.wokaCollections.set(collection.name, textures);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const OBJECTS: BodyResourceDescriptionInterface[] = [
|
||||
|
||||
@@ -97,7 +97,6 @@ export class CameraManager extends Phaser.Events.EventEmitter {
|
||||
});
|
||||
return;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
this.camera.pan(setTo.x, setTo.y, duration, Easing.SineEaseOut, true, (camera, progress, x, y) => {
|
||||
if (this.cameraMode === CameraMode.Positioned) {
|
||||
this.waScaleManager.zoomModifier = currentZoomModifier + progress * zoomModifierChange;
|
||||
@@ -139,7 +138,6 @@ export class CameraManager extends Phaser.Events.EventEmitter {
|
||||
this.emit(CameraManagerEvent.CameraUpdate, this.getCameraUpdateEventData());
|
||||
return;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
this.camera.pan(focusOn.x, focusOn.y, duration, Easing.SineEaseOut, true, (camera, progress, x, y) => {
|
||||
this.waScaleManager.zoomModifier = currentZoomModifier + progress * zoomModifierChange;
|
||||
if (progress === 1) {
|
||||
|
||||
@@ -177,8 +177,6 @@ export class GameScene extends DirtyScene {
|
||||
|
||||
private localVolumeStoreUnsubscriber: Unsubscriber | undefined;
|
||||
private followUsersColorStoreUnsubscribe!: Unsubscriber;
|
||||
private currentPlayerGroupIdStoreUnsubscribe!: Unsubscriber;
|
||||
private privacyShutdownStoreUnsubscribe!: Unsubscriber;
|
||||
private userIsJitsiDominantSpeakerStoreUnsubscriber!: Unsubscriber;
|
||||
private jitsiParticipantsCountStoreUnsubscriber!: Unsubscriber;
|
||||
|
||||
@@ -1593,7 +1591,6 @@ export class GameScene extends DirtyScene {
|
||||
this.emoteUnsubscribe();
|
||||
this.emoteMenuUnsubscribe();
|
||||
this.followUsersColorStoreUnsubscribe();
|
||||
this.privacyShutdownStoreUnsubscribe();
|
||||
this.biggestAvailableAreaStoreUnsubscribe();
|
||||
this.userIsJitsiDominantSpeakerStoreUnsubscriber();
|
||||
this.jitsiParticipantsCountStoreUnsubscriber();
|
||||
@@ -1733,7 +1730,6 @@ export class GameScene extends DirtyScene {
|
||||
private createCollisionWithPlayer() {
|
||||
//add collision layer
|
||||
for (const phaserLayer of this.gameMap.phaserLayers) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
this.physics.add.collider(this.CurrentPlayer, phaserLayer, (object1: GameObject, object2: GameObject) => {
|
||||
//this.CurrentPlayer.say("Collision with layer : "+ (object2 as Tile).layer.name)
|
||||
});
|
||||
@@ -1784,11 +1780,9 @@ export class GameScene extends DirtyScene {
|
||||
emoteMenuStore.openEmoteMenu();
|
||||
}
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
this.CurrentPlayer.on(Phaser.Input.Events.POINTER_OVER, (pointer: Phaser.Input.Pointer) => {
|
||||
this.CurrentPlayer.pointerOverOutline(0x365dff);
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
this.CurrentPlayer.on(Phaser.Input.Events.POINTER_OUT, (pointer: Phaser.Input.Pointer) => {
|
||||
this.CurrentPlayer.pointerOutOutline();
|
||||
});
|
||||
@@ -1890,8 +1884,7 @@ export class GameScene extends DirtyScene {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const tmp: never = event;
|
||||
const _exhaustiveCheck: never = event;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ export class TexturesHelper {
|
||||
});
|
||||
} catch (error) {
|
||||
rt.destroy();
|
||||
throw new Error("Could not get the snapshot");
|
||||
throw new Error("Could not get the snapshot: " + error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,4 +11,8 @@ export abstract class AbstractCharacterScene extends ResizableScene {
|
||||
this.playerTextures = new PlayerTextures();
|
||||
this.superLoad = new SuperLoaderPlugin(this);
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.input.dragDistanceThreshold = 10;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
||||
}
|
||||
|
||||
public preload(): void {
|
||||
this.input.dragDistanceThreshold = 10;
|
||||
super.preload();
|
||||
|
||||
this.load.image("iconClothes", "/resources/icons/icon_clothes.png");
|
||||
this.load.image("iconAccessory", "/resources/icons/icon_accessory.png");
|
||||
@@ -112,7 +112,6 @@ export class CustomizeScene extends AbstractCharacterScene {
|
||||
this.onResize();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public update(time: number, dt: number): void {
|
||||
this.customWokaPreviewer.update();
|
||||
}
|
||||
|
||||
@@ -13,6 +13,5 @@ export class EmptyScene extends Scene {
|
||||
|
||||
create() {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
update(time: number, delta: number): void {}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ export class EnableCameraScene extends ResizableScene {
|
||||
|
||||
public onResize(): void {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
update(time: number, delta: number): void {}
|
||||
|
||||
public login(): void {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { gameManager } from "../Game/GameManager";
|
||||
import { Scene } from "phaser";
|
||||
import { ErrorScene } from "../Reconnecting/ErrorScene";
|
||||
import { WAError } from "../Reconnecting/WAError";
|
||||
import { waScaleManager } from "../Services/WaScaleManager";
|
||||
import { ReconnectingTextures } from "../Reconnecting/ReconnectingScene";
|
||||
import LL from "../../i18n/i18n-svelte";
|
||||
import { get } from "svelte/store";
|
||||
import { localeDetector } from "../../i18n/locales";
|
||||
import { errorScreenStore } from "../../Stores/ErrorScreenStore";
|
||||
import { isErrorApiData } from "../../Messages/JsonMessages/ErrorApiData";
|
||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||
|
||||
export const EntrySceneName = "EntryScene";
|
||||
|
||||
@@ -47,27 +47,13 @@ export class EntryScene extends Scene {
|
||||
this.scene.start(nextSceneName);
|
||||
})
|
||||
.catch((err) => {
|
||||
const $LL = get(LL);
|
||||
if (err.response && err.response.status == 404) {
|
||||
ErrorScene.showError(
|
||||
new WAError(
|
||||
$LL.error.accessLink.title(),
|
||||
$LL.error.accessLink.subTitle(),
|
||||
$LL.error.accessLink.details()
|
||||
),
|
||||
this.scene
|
||||
);
|
||||
} else if (err.response && err.response.status == 403) {
|
||||
ErrorScene.showError(
|
||||
new WAError(
|
||||
$LL.error.connectionRejected.title(),
|
||||
$LL.error.connectionRejected.subTitle({
|
||||
error: err.response.data ? ". \n\r \n\r" + `${err.response.data}` : "",
|
||||
}),
|
||||
$LL.error.connectionRejected.details()
|
||||
),
|
||||
this.scene
|
||||
);
|
||||
const errorType = isErrorApiData.safeParse(err?.response?.data);
|
||||
if (errorType.success) {
|
||||
if (errorType.data.type === "unauthorized") {
|
||||
void connectionManager.logout();
|
||||
} else if (errorType.data.type === "redirect") {
|
||||
window.location.assign(errorType.data.urlToRedirect);
|
||||
} else errorScreenStore.setError(err?.response?.data);
|
||||
} else {
|
||||
ErrorScene.showError(err, this.scene);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ export class LoginScene extends ResizableScene {
|
||||
loginSceneVisibleStore.set(false);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
update(time: number, delta: number): void {}
|
||||
|
||||
public onResize(): void {}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import { SelectCharacterScene } from "./SelectCharacterScene";
|
||||
|
||||
export class SelectCharacterMobileScene extends SelectCharacterScene {
|
||||
create() {
|
||||
super.create();
|
||||
this.onResize();
|
||||
this.selectedRectangle.destroy();
|
||||
}
|
||||
|
||||
protected defineSetupPlayer(num: number) {
|
||||
const deltaX = 30;
|
||||
const deltaY = 2;
|
||||
let [playerX, playerY] = this.getCharacterPosition();
|
||||
let playerVisible = true;
|
||||
let playerScale = 1.5;
|
||||
let playerOpacity = 1;
|
||||
|
||||
if (this.currentSelectUser !== num) {
|
||||
playerVisible = false;
|
||||
}
|
||||
if (num === this.currentSelectUser + 1) {
|
||||
playerY -= deltaY;
|
||||
playerX += deltaX;
|
||||
playerScale = 0.8;
|
||||
playerOpacity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
if (num === this.currentSelectUser + 2) {
|
||||
playerY -= deltaY;
|
||||
playerX += deltaX * 2;
|
||||
playerScale = 0.8;
|
||||
playerOpacity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
if (num === this.currentSelectUser - 1) {
|
||||
playerY -= deltaY;
|
||||
playerX -= deltaX;
|
||||
playerScale = 0.8;
|
||||
playerOpacity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
if (num === this.currentSelectUser - 2) {
|
||||
playerY -= deltaY;
|
||||
playerX -= deltaX * 2;
|
||||
playerScale = 0.8;
|
||||
playerOpacity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
return { playerX, playerY, playerScale, playerOpacity, playerVisible };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel position by on column and row number
|
||||
*/
|
||||
protected getCharacterPosition(): [number, number] {
|
||||
return [this.game.renderer.width / 2, this.game.renderer.height / 3];
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import { gameManager } from "../Game/GameManager";
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import { EnableCameraSceneName } from "./EnableCameraScene";
|
||||
import { CustomizeSceneName } from "./CustomizeScene";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
@@ -13,25 +12,25 @@ import { PinchManager } from "../UserInput/PinchManager";
|
||||
import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore";
|
||||
import { waScaleManager } from "../Services/WaScaleManager";
|
||||
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
||||
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
|
||||
import { PUSHER_URL } from "../../Enum/EnvironmentVariable";
|
||||
import { customizeAvailableStore } from "../../Stores/SelectCharacterSceneStore";
|
||||
import { customizeAvailableStore, selectedCollection } from "../../Stores/SelectCharacterSceneStore";
|
||||
import { DraggableGrid } from "@home-based-studio/phaser3-utils";
|
||||
import { WokaSlot } from "../Components/SelectWoka/WokaSlot";
|
||||
import { DraggableGridEvent } from "@home-based-studio/phaser3-utils/lib/utils/gui/containers/grids/DraggableGrid";
|
||||
import { wokaList } from "../../Messages/JsonMessages/PlayerTextures";
|
||||
|
||||
//todo: put this constants in a dedicated file
|
||||
export const SelectCharacterSceneName = "SelectCharacterScene";
|
||||
|
||||
export class SelectCharacterScene extends AbstractCharacterScene {
|
||||
protected readonly nbCharactersPerRow = 6;
|
||||
protected selectedPlayer!: Phaser.Physics.Arcade.Sprite | null; // null if we are selecting the "customize" option
|
||||
protected players: Array<Phaser.Physics.Arcade.Sprite> = new Array<Phaser.Physics.Arcade.Sprite>();
|
||||
protected selectedWoka!: Phaser.GameObjects.Sprite | null; // null if we are selecting the "customize" option
|
||||
protected playerModels!: BodyResourceDescriptionInterface[];
|
||||
|
||||
protected selectedRectangle!: Rectangle;
|
||||
|
||||
protected currentSelectUser = 0;
|
||||
protected pointerClicked: boolean = false;
|
||||
protected pointerTimer: number = 0;
|
||||
private charactersDraggableGrid!: DraggableGrid;
|
||||
private collectionKeys!: string[];
|
||||
private selectedCollectionIndex!: number;
|
||||
private selectedGridItemIndex?: number;
|
||||
private gridRowsCount: number = 1;
|
||||
|
||||
protected lazyloadingAttempt = true; //permit to update texture loaded after renderer
|
||||
private loader: Loader;
|
||||
@@ -44,7 +43,8 @@ export class SelectCharacterScene extends AbstractCharacterScene {
|
||||
this.playerTextures = new PlayerTextures();
|
||||
}
|
||||
|
||||
preload() {
|
||||
public preload() {
|
||||
super.preload();
|
||||
const wokaMetadataKey = "woka-list" + gameManager.currentStartedRoom.href;
|
||||
this.cache.json.remove(wokaMetadataKey);
|
||||
|
||||
@@ -67,228 +67,236 @@ export class SelectCharacterScene extends AbstractCharacterScene {
|
||||
}
|
||||
)
|
||||
.catch((e) => console.error(e));
|
||||
this.playerModels = loadAllDefaultModels(this.load, this.playerTextures);
|
||||
this.lazyloadingAttempt = false;
|
||||
|
||||
//this function must stay at the end of preload function
|
||||
this.loader.addLoader();
|
||||
}
|
||||
|
||||
create() {
|
||||
public create() {
|
||||
waScaleManager.zoomModifier = 1;
|
||||
this.selectedWoka = null;
|
||||
this.selectedCollectionIndex = 0;
|
||||
this.collectionKeys = this.playerTextures.getCollectionsKeys();
|
||||
selectedCollection.set(this.getSelectedCollectionName());
|
||||
|
||||
customizeAvailableStore.set(this.isCustomizationAvailable());
|
||||
selectCharacterSceneVisibleStore.set(true);
|
||||
this.events.addListener("wake", () => {
|
||||
waScaleManager.saveZoom();
|
||||
waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 2 : 1;
|
||||
selectCharacterSceneVisibleStore.set(true);
|
||||
});
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
|
||||
waScaleManager.saveZoom();
|
||||
waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 2 : 1;
|
||||
|
||||
const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
|
||||
this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xffffff);
|
||||
this.selectedRectangle.setDepth(2);
|
||||
|
||||
/*create user*/
|
||||
this.createCurrentPlayer();
|
||||
|
||||
this.input.keyboard.on("keyup-ENTER", () => {
|
||||
return this.nextSceneToCameraScene();
|
||||
this.charactersDraggableGrid = new DraggableGrid(this, {
|
||||
position: { x: 0, y: 0 },
|
||||
maskPosition: { x: 0, y: 0 },
|
||||
dimension: { x: 485, y: 165 },
|
||||
horizontal: true,
|
||||
repositionToCenter: true,
|
||||
itemsInRow: 1,
|
||||
margin: {
|
||||
left: ((innerWidth - 200) / waScaleManager.getActualZoom()) * 0.5,
|
||||
right: ((innerWidth - 200) / waScaleManager.getActualZoom()) * 0.5,
|
||||
},
|
||||
spacing: 5,
|
||||
debug: {
|
||||
showDraggableSpace: false,
|
||||
},
|
||||
});
|
||||
|
||||
this.input.keyboard.on("keydown-RIGHT", () => {
|
||||
this.moveToRight();
|
||||
});
|
||||
this.input.keyboard.on("keydown-LEFT", () => {
|
||||
this.moveToLeft();
|
||||
});
|
||||
this.input.keyboard.on("keydown-UP", () => {
|
||||
this.moveToUp();
|
||||
});
|
||||
this.input.keyboard.on("keydown-DOWN", () => {
|
||||
this.moveToDown();
|
||||
});
|
||||
this.bindEventHandlers();
|
||||
|
||||
this.onResize();
|
||||
}
|
||||
|
||||
public nextSceneToCameraScene(): void {
|
||||
if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
|
||||
if (this.selectedWoka !== null && !areCharacterLayersValid([this.selectedWoka.texture.key])) {
|
||||
return;
|
||||
}
|
||||
if (!this.selectedPlayer) {
|
||||
if (!this.selectedWoka) {
|
||||
return;
|
||||
}
|
||||
|
||||
analyticsClient.validationWoka("SelectWoka");
|
||||
|
||||
gameManager.setCharacterLayers([this.selectedWoka.texture.key]);
|
||||
this.selectedWoka = null;
|
||||
this.scene.stop(SelectCharacterSceneName);
|
||||
waScaleManager.restoreZoom();
|
||||
gameManager.setCharacterLayers([this.selectedPlayer.texture.key]);
|
||||
gameManager.tryResumingGame(EnableCameraSceneName);
|
||||
this.players = [];
|
||||
selectCharacterSceneVisibleStore.set(false);
|
||||
this.events.removeListener("wake");
|
||||
}
|
||||
|
||||
public nextSceneToCustomizeScene(): void {
|
||||
if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
|
||||
if (this.selectedWoka !== null && !areCharacterLayersValid([this.selectedWoka.texture.key])) {
|
||||
return;
|
||||
}
|
||||
this.selectedWoka = null;
|
||||
this.scene.sleep(SelectCharacterSceneName);
|
||||
waScaleManager.restoreZoom();
|
||||
this.scene.run(CustomizeSceneName);
|
||||
selectCharacterSceneVisibleStore.set(false);
|
||||
}
|
||||
|
||||
createCurrentPlayer(): void {
|
||||
for (let i = 0; i < this.playerModels.length; i++) {
|
||||
const playerResource = this.playerModels[i];
|
||||
//check already exist texture
|
||||
if (this.players.find((c) => c.texture.key === playerResource.id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const [middleX, middleY] = this.getCharacterPosition();
|
||||
const player = this.physics.add.sprite(middleX, middleY, playerResource.id, 0);
|
||||
this.setUpPlayer(player, i);
|
||||
this.anims.create({
|
||||
key: playerResource.id,
|
||||
frames: this.anims.generateFrameNumbers(playerResource.id, { start: 0, end: 11 }),
|
||||
frameRate: 8,
|
||||
repeat: -1,
|
||||
});
|
||||
player.setInteractive().on("pointerdown", () => {
|
||||
if (this.pointerClicked) {
|
||||
return;
|
||||
}
|
||||
if (this.currentSelectUser === i) {
|
||||
return;
|
||||
}
|
||||
//To not trigger two time the pointerdown events :
|
||||
// We set a boolean to true so that pointerdown events does nothing when the boolean is true
|
||||
// We set a timer that we decrease in update function to not trigger the pointerdown events twice
|
||||
this.pointerClicked = true;
|
||||
this.pointerTimer = 250;
|
||||
this.currentSelectUser = i;
|
||||
this.moveUser();
|
||||
});
|
||||
this.players.push(player);
|
||||
}
|
||||
if (this.currentSelectUser >= this.players.length) {
|
||||
this.currentSelectUser = 0;
|
||||
}
|
||||
this.selectedPlayer = this.players[this.currentSelectUser];
|
||||
this.selectedPlayer.play(this.playerModels[this.currentSelectUser].id);
|
||||
}
|
||||
|
||||
protected moveUser() {
|
||||
for (let i = 0; i < this.players.length; i++) {
|
||||
const player = this.players[i];
|
||||
this.setUpPlayer(player, i);
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
}
|
||||
|
||||
public moveToLeft() {
|
||||
if (this.currentSelectUser === 0) {
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser -= 1;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
public moveToRight() {
|
||||
if (this.currentSelectUser === this.players.length - 1) {
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser += 1;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected moveToUp() {
|
||||
if (this.currentSelectUser < this.nbCharactersPerRow) {
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser -= this.nbCharactersPerRow;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected moveToDown() {
|
||||
if (this.currentSelectUser + this.nbCharactersPerRow > this.players.length - 1) {
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser += this.nbCharactersPerRow;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected defineSetupPlayer(num: number) {
|
||||
const deltaX = 32;
|
||||
const deltaY = 32;
|
||||
let [playerX, playerY] = this.getCharacterPosition(); // player X and player y are middle of the
|
||||
|
||||
playerX = playerX - deltaX * 2.5 + deltaX * (num % this.nbCharactersPerRow); // calcul position on line users
|
||||
playerY = playerY - deltaY * 2 + deltaY * Math.floor(num / this.nbCharactersPerRow); // calcul position on column users
|
||||
|
||||
const playerVisible = true;
|
||||
const playerScale = 1;
|
||||
const playerOpacity = 1;
|
||||
|
||||
// if selected
|
||||
if (num === this.currentSelectUser) {
|
||||
this.selectedRectangle.setX(playerX);
|
||||
this.selectedRectangle.setY(playerY);
|
||||
}
|
||||
|
||||
return { playerX, playerY, playerScale, playerOpacity, playerVisible };
|
||||
}
|
||||
|
||||
protected setUpPlayer(player: Phaser.Physics.Arcade.Sprite, num: number) {
|
||||
const { playerX, playerY, playerScale, playerOpacity, playerVisible } = this.defineSetupPlayer(num);
|
||||
player.setBounce(0.2);
|
||||
player.setCollideWorldBounds(false);
|
||||
player.setVisible(playerVisible);
|
||||
player.setScale(playerScale, playerScale);
|
||||
player.setAlpha(playerOpacity);
|
||||
player.setX(playerX);
|
||||
player.setY(playerY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel position by on column and row number
|
||||
*/
|
||||
protected getCharacterPosition(): [number, number] {
|
||||
return [this.game.renderer.width / 2, this.game.renderer.height / 2.5];
|
||||
}
|
||||
|
||||
protected updateSelectedPlayer(): void {
|
||||
this.selectedPlayer?.anims?.pause(this.selectedPlayer?.anims.currentAnim.frames[0]);
|
||||
const player = this.players[this.currentSelectUser];
|
||||
player?.play(this.playerModels[this.currentSelectUser].id);
|
||||
this.selectedPlayer = player;
|
||||
localUserStore.setPlayerCharacterIndex(this.currentSelectUser);
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
// pointerTimer is set to 250 when pointerdown events is trigger
|
||||
// After 250ms, pointerClicked is set to false and the pointerdown events can be trigger again
|
||||
this.pointerTimer -= delta;
|
||||
if (this.pointerTimer <= 0) {
|
||||
this.pointerClicked = false;
|
||||
}
|
||||
|
||||
public update(): void {
|
||||
if (this.lazyloadingAttempt) {
|
||||
//re-render players list
|
||||
this.createCurrentPlayer();
|
||||
this.moveUser();
|
||||
this.lazyloadingAttempt = false;
|
||||
}
|
||||
}
|
||||
|
||||
public onResize(): void {
|
||||
//move position of user
|
||||
this.moveUser();
|
||||
this.handleCharactersGridOnResize();
|
||||
}
|
||||
|
||||
public getSelectedCollectionName(): string {
|
||||
return this.collectionKeys[this.selectedCollectionIndex] ?? "";
|
||||
}
|
||||
|
||||
public getCollectionKeysSize(): number {
|
||||
return this.playerTextures.getCollectionsKeys().length;
|
||||
}
|
||||
|
||||
public selectPreviousCollection(): void {
|
||||
this.selectedCollectionIndex = (this.selectedCollectionIndex + 1) % this.collectionKeys.length;
|
||||
selectedCollection.set(this.getSelectedCollectionName());
|
||||
this.populateGrid();
|
||||
}
|
||||
|
||||
public selectNextCollection(): void {
|
||||
if (this.collectionKeys.length === 1) {
|
||||
return;
|
||||
}
|
||||
this.selectedCollectionIndex =
|
||||
this.selectedCollectionIndex - 1 < 0 ? this.collectionKeys.length - 1 : this.selectedCollectionIndex - 1;
|
||||
selectedCollection.set(this.getSelectedCollectionName());
|
||||
this.populateGrid();
|
||||
}
|
||||
|
||||
private handleCharactersGridOnResize(): void {
|
||||
const ratio = innerHeight / innerWidth;
|
||||
this.gridRowsCount = ratio > 1 || innerHeight > 900 ? 2 : 1;
|
||||
const gridHeight = this.gridRowsCount === 2 ? 210 : 105;
|
||||
const gridWidth = innerWidth / waScaleManager.getActualZoom();
|
||||
const gridPos = {
|
||||
x: this.cameras.main.worldView.x + this.cameras.main.width / 2,
|
||||
y: this.cameras.main.worldView.y + this.cameras.main.height * (ratio > 1 ? 0.5 : 0.575),
|
||||
};
|
||||
|
||||
try {
|
||||
this.charactersDraggableGrid.changeDraggableSpacePosAndSize(
|
||||
gridPos,
|
||||
{ x: gridWidth, y: gridHeight },
|
||||
gridPos
|
||||
);
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
this.charactersDraggableGrid.setItemsInRow(this.gridRowsCount);
|
||||
this.populateGrid();
|
||||
}
|
||||
|
||||
private populateGrid(): void {
|
||||
const wokaDimension = 100;
|
||||
|
||||
this.selectedWoka = null;
|
||||
this.charactersDraggableGrid.clearAllItems();
|
||||
const textures = this.playerTextures.getWokaCollectionTextures(this.getSelectedCollectionName());
|
||||
for (let i = 0; i < textures.length; i += 1) {
|
||||
const slot = new WokaSlot(this, textures[i].id).setDisplaySize(wokaDimension, wokaDimension);
|
||||
this.charactersDraggableGrid.addItem(slot);
|
||||
}
|
||||
this.charactersDraggableGrid.moveContentToBeginning();
|
||||
void this.charactersDraggableGrid.moveContentTo(0.5, textures.length * 50);
|
||||
}
|
||||
|
||||
private bindEventHandlers(): void {
|
||||
this.bindKeyboardEventHandlers();
|
||||
this.events.addListener("wake", () => {
|
||||
selectCharacterSceneVisibleStore.set(true);
|
||||
});
|
||||
|
||||
this.input.keyboard.on("keyup-ENTER", () => {
|
||||
return this.nextSceneToCameraScene();
|
||||
});
|
||||
|
||||
this.charactersDraggableGrid.on(DraggableGridEvent.ItemClicked, (item: WokaSlot) => {
|
||||
this.selectGridItem(item);
|
||||
});
|
||||
}
|
||||
|
||||
private selectGridItem(item: WokaSlot): void {
|
||||
this.selectedGridItemIndex = this.charactersDraggableGrid.getAllItems().indexOf(item);
|
||||
if (this.charactersDraggableGrid.getDraggableSpaceWidth() < this.charactersDraggableGrid.getGridSize().x) {
|
||||
void this.charactersDraggableGrid.centerOnItem(this.selectedGridItemIndex, 500);
|
||||
}
|
||||
this.charactersDraggableGrid.getAllItems().forEach((slot) => (slot as WokaSlot).select(false));
|
||||
this.selectedWoka?.stop()?.setFrame(0);
|
||||
this.selectedWoka = item.getSprite();
|
||||
const wokaKey = this.selectedWoka.texture.key;
|
||||
this.createWokaAnimation(wokaKey);
|
||||
this.selectedWoka.play(wokaKey);
|
||||
item.select(true);
|
||||
}
|
||||
|
||||
private bindKeyboardEventHandlers(): void {
|
||||
this.input.keyboard.on("keyup-SPACE", () => {
|
||||
this.selectNextCollection();
|
||||
});
|
||||
this.input.keyboard.on("keydown-LEFT", () => {
|
||||
this.selectNextGridItem(true, true);
|
||||
});
|
||||
this.input.keyboard.on("keydown-RIGHT", () => {
|
||||
this.selectNextGridItem(false, true);
|
||||
});
|
||||
this.input.keyboard.on("keydown-UP", () => {
|
||||
this.selectNextGridItem(true, false);
|
||||
});
|
||||
this.input.keyboard.on("keydown-DOWN", () => {
|
||||
this.selectNextGridItem(false, false);
|
||||
});
|
||||
this.input.keyboard.on("keydown-W", () => {
|
||||
this.selectNextGridItem(true, false);
|
||||
});
|
||||
this.input.keyboard.on("keydown-S", () => {
|
||||
this.selectNextGridItem(false, false);
|
||||
});
|
||||
this.input.keyboard.on("keydown-A", () => {
|
||||
this.selectNextGridItem(true, true);
|
||||
});
|
||||
this.input.keyboard.on("keydown-D", () => {
|
||||
this.selectNextGridItem(false, true);
|
||||
});
|
||||
}
|
||||
|
||||
private selectNextGridItem(previous: boolean = false, horizontally: boolean): void {
|
||||
if (this.selectedGridItemIndex === undefined) {
|
||||
this.selectedGridItemIndex = 0;
|
||||
}
|
||||
if (
|
||||
previous
|
||||
? this.selectedGridItemIndex > 0
|
||||
: this.selectedGridItemIndex < this.charactersDraggableGrid.getAllItems().length - 1
|
||||
) {
|
||||
// NOTE: getItemsInRowCount() not working properly. Fix on lib side needed
|
||||
const jump = horizontally ? this.gridRowsCount : 1;
|
||||
const item = this.charactersDraggableGrid.getAllItems()[
|
||||
this.selectedGridItemIndex + (previous ? -jump : jump)
|
||||
] as WokaSlot;
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
this.selectedGridItemIndex += previous ? -1 : 1;
|
||||
this.selectGridItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
private createWokaAnimation(key: string): void {
|
||||
this.anims.create({
|
||||
key,
|
||||
frames: this.anims.generateFrameNumbers(key, { start: 0, end: 11 }),
|
||||
frameRate: 8,
|
||||
repeat: -1,
|
||||
});
|
||||
}
|
||||
|
||||
private isCustomizationAvailable(): boolean {
|
||||
|
||||
@@ -3,7 +3,6 @@ import Image = Phaser.GameObjects.Image;
|
||||
import Sprite = Phaser.GameObjects.Sprite;
|
||||
import Text = Phaser.GameObjects.Text;
|
||||
import ScenePlugin = Phaser.Scenes.ScenePlugin;
|
||||
import { WAError } from "./WAError";
|
||||
import Axios from "axios";
|
||||
|
||||
export const ErrorSceneName = "ErrorScene";
|
||||
@@ -88,12 +87,6 @@ export class ErrorScene extends Phaser.Scene {
|
||||
title: "An error occurred",
|
||||
subTitle: error,
|
||||
});
|
||||
} else if (error instanceof WAError) {
|
||||
scene.start(ErrorSceneName, {
|
||||
title: error.title,
|
||||
subTitle: error.subTitle,
|
||||
message: error.details,
|
||||
});
|
||||
} else if (Axios.isAxiosError(error) && error.response) {
|
||||
// Axios HTTP error
|
||||
// client received an error response (5xx, 4xx)
|
||||
|
||||
@@ -1,26 +1,65 @@
|
||||
export class WAError extends Error {
|
||||
private _type: string;
|
||||
private _code: string;
|
||||
private _title: string;
|
||||
private _subTitle: string;
|
||||
private _subtitle: string;
|
||||
private _details: string;
|
||||
private _timeToRetry: number;
|
||||
private _canRetryManual: boolean;
|
||||
private _urlToRedirect: string;
|
||||
private _buttonTitle: string;
|
||||
|
||||
constructor(title: string, subTitle: string, details: string) {
|
||||
super(title + " - " + subTitle + " - " + details);
|
||||
constructor(
|
||||
type: string,
|
||||
code: string,
|
||||
title: string,
|
||||
subtitle: string,
|
||||
details: string,
|
||||
timeToRetry: number,
|
||||
canRetryManual: boolean,
|
||||
urlToRedirect: string,
|
||||
buttonTitle: string
|
||||
) {
|
||||
super(title + " - " + subtitle + " - " + details);
|
||||
|
||||
this._type = type;
|
||||
this._code = code;
|
||||
this._title = title;
|
||||
this._subTitle = subTitle;
|
||||
this._subtitle = subtitle;
|
||||
this._details = details;
|
||||
this._timeToRetry = timeToRetry;
|
||||
this._canRetryManual = canRetryManual;
|
||||
this._urlToRedirect = urlToRedirect;
|
||||
this._buttonTitle = buttonTitle;
|
||||
// Set the prototype explicitly.
|
||||
Object.setPrototypeOf(this, WAError.prototype);
|
||||
}
|
||||
|
||||
get type(): string {
|
||||
return this._type;
|
||||
}
|
||||
get code(): string {
|
||||
return this._code;
|
||||
}
|
||||
get title(): string {
|
||||
return this._title;
|
||||
}
|
||||
|
||||
get subTitle(): string {
|
||||
return this._subTitle;
|
||||
get subtitle(): string {
|
||||
return this._subtitle;
|
||||
}
|
||||
|
||||
get details(): string {
|
||||
return this._details;
|
||||
}
|
||||
get timeToRetry(): number {
|
||||
return this._timeToRetry;
|
||||
}
|
||||
get buttonTitle(): string {
|
||||
return this._buttonTitle;
|
||||
}
|
||||
get urlToRedirect(): string {
|
||||
return this._urlToRedirect;
|
||||
}
|
||||
get canRetryManual(): boolean {
|
||||
return this._canRetryManual;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ export class GameSceneUserInputHandler implements UserInputHandlerInterface {
|
||||
gameObjects: Phaser.GameObjects.GameObject[],
|
||||
deltaX: number,
|
||||
deltaY: number,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
deltaZ: number
|
||||
): void {
|
||||
this.gameScene.zoomByFactor(1 - (deltaY / 53) * 0.1);
|
||||
@@ -68,7 +67,7 @@ export class GameSceneUserInputHandler implements UserInputHandlerInterface {
|
||||
this.lastY = pointer.y;
|
||||
}
|
||||
|
||||
public handlePointerDownEvent(pointer: Phaser.Input.Pointer, gameObjects: Phaser.GameObjects.GameObject[]): void { }
|
||||
public handlePointerDownEvent(pointer: Phaser.Input.Pointer, gameObjects: Phaser.GameObjects.GameObject[]): void {}
|
||||
|
||||
public handleSpaceKeyUpEvent(event: Event): Event {
|
||||
const activatableManager = this.gameScene.getActivatablesManager();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { writable } from "svelte/store";
|
||||
import { ErrorScreenMessage } from "../Messages/ts-proto-generated/protos/messages";
|
||||
|
||||
/**
|
||||
* A store that contains one error of type WAError to be displayed.
|
||||
*/
|
||||
function createErrorScreenStore() {
|
||||
const { subscribe, set } = writable<ErrorScreenMessage>(undefined);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
setError: (e: ErrorScreenMessage): void => {
|
||||
set(e);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const errorScreenStore = createErrorScreenStore();
|
||||
@@ -2,6 +2,7 @@ import { derived, Readable, readable, writable } from "svelte/store";
|
||||
import { peerStore } from "./PeerStore";
|
||||
import type { LocalStreamStoreValue } from "./MediaStore";
|
||||
import { myCameraVisibilityStore } from "./MyCameraStoreVisibility";
|
||||
import type { DesktopCapturerSource } from "@wa-preload-app";
|
||||
|
||||
declare const navigator: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
@@ -91,6 +92,25 @@ export const screenSharingConstraintsStore = derived(
|
||||
} as MediaStreamConstraints
|
||||
);
|
||||
|
||||
async function getDesktopCapturerSources() {
|
||||
showDesktopCapturerSourcePicker.set(true);
|
||||
const source = await new Promise<DesktopCapturerSource | null>((resolve) => {
|
||||
desktopCapturerSourcePromiseResolve = resolve;
|
||||
});
|
||||
if (source === null) {
|
||||
return;
|
||||
}
|
||||
return navigator.mediaDevices.getUserMedia({
|
||||
audio: false,
|
||||
video: {
|
||||
mandatory: {
|
||||
chromeMediaSource: "desktop",
|
||||
chromeMediaSourceId: source.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A store containing the MediaStream object for ScreenSharing (or null if nothing requested, or Error if an error occurred)
|
||||
*/
|
||||
@@ -110,7 +130,9 @@ export const screenSharingLocalStreamStore = derived<Readable<MediaStreamConstra
|
||||
}
|
||||
|
||||
let currentStreamPromise: Promise<MediaStream>;
|
||||
if (navigator.getDisplayMedia) {
|
||||
if (window.WAD?.getDesktopCapturerSources) {
|
||||
currentStreamPromise = getDesktopCapturerSources();
|
||||
} else if (navigator.getDisplayMedia) {
|
||||
currentStreamPromise = navigator.getDisplayMedia({ constraints });
|
||||
} else if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {
|
||||
currentStreamPromise = navigator.mediaDevices.getDisplayMedia({ constraints });
|
||||
@@ -200,3 +222,7 @@ export const screenSharingLocalMedia = readable<ScreenSharingLocalMedia | null>(
|
||||
unsubscribe();
|
||||
};
|
||||
});
|
||||
|
||||
export const showDesktopCapturerSourcePicker = writable(false);
|
||||
|
||||
export let desktopCapturerSourcePromiseResolve: ((source: DesktopCapturerSource | null) => void) | undefined;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
export const customizeAvailableStore = writable(false);
|
||||
|
||||
export const selectedCollection = writable<string>();
|
||||
|
||||
@@ -14,15 +14,6 @@ export function getColorRgbFromHue(hue: number): { r: number; g: number; b: numb
|
||||
return hsv_to_rgb(hue, 0.5, 0.95);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function stringToDouble(string: string): number {
|
||||
let num = 1;
|
||||
for (const char of string.split("")) {
|
||||
num *= char.charCodeAt(0);
|
||||
}
|
||||
return (num % 255) / 255;
|
||||
}
|
||||
|
||||
//todo: test this.
|
||||
function hsv_to_rgb(hue: number, saturation: number, brightness: number): { r: number; g: number; b: number } {
|
||||
const h_i = Math.floor(hue * 6);
|
||||
|
||||
+1
-3
@@ -17,14 +17,12 @@ import { localUserStore } from "./Connexion/LocalUserStore";
|
||||
import { ErrorScene } from "./Phaser/Reconnecting/ErrorScene";
|
||||
import { iframeListener } from "./Api/IframeListener";
|
||||
import { desktopApi } from "./Api/desktop/index";
|
||||
import { SelectCharacterMobileScene } from "./Phaser/Login/SelectCharacterMobileScene";
|
||||
import { HdpiManager } from "./Phaser/Services/HdpiManager";
|
||||
import { waScaleManager } from "./Phaser/Services/WaScaleManager";
|
||||
import { Game } from "./Phaser/Game/Game";
|
||||
import App from "./Components/App.svelte";
|
||||
import { HtmlUtils } from "./WebRtc/HtmlUtils";
|
||||
import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer;
|
||||
import { isMediaBreakpointUp } from "./Utils/BreakpointsUtils";
|
||||
|
||||
const { width, height } = coWebsiteManager.getGameSize();
|
||||
const valueGameQuality = localUserStore.getGameQualityValue();
|
||||
@@ -91,7 +89,7 @@ const config: GameConfig = {
|
||||
scene: [
|
||||
EntryScene,
|
||||
LoginScene,
|
||||
isMediaBreakpointUp("md") ? SelectCharacterMobileScene : SelectCharacterScene,
|
||||
SelectCharacterScene,
|
||||
SelectCompanionScene,
|
||||
EnableCameraScene,
|
||||
ReconnectingScene,
|
||||
|
||||
+4
-4
@@ -806,10 +806,10 @@ debug@~3.1.0:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
deep-copy-ts@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-copy-ts/-/deep-copy-ts-0.5.0.tgz#b9493d8e2bae85ef7d659c16eb707c13efb84499"
|
||||
integrity sha512-/3cgBcMkznRf5BM8wu6YWz3SQUkHzgh/v1TZFjevztLj9sMjFvNFBtpN4uUtPzw/rA/TldyD6c6LRL1zno4+YA==
|
||||
deep-copy-ts@^0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/deep-copy-ts/-/deep-copy-ts-0.5.4.tgz#e81b15797e4075cb3a690a1a7ac30179f2d72562"
|
||||
integrity sha512-YJbPjw0YqdosorpCsa6copy1p/gJsFT9Q6Zq0tLi7D0nXh6Y/usjeIQZfkzV3HVuqY0Hl/5gM7TwgIbIWvEjlA==
|
||||
|
||||
deep-equal@^1.0.1:
|
||||
version "1.1.1"
|
||||
|
||||
Reference in New Issue
Block a user