Merge branch 'develop' of github.com:thecodingmachine/workadventure

This commit is contained in:
_Bastler 2021-09-06 18:49:47 +02:00
commit 64613b076e
66 changed files with 953 additions and 822 deletions

View File

@ -61,6 +61,10 @@ jobs:
run: yarn run lint run: yarn run lint
working-directory: "front" working-directory: "front"
- name: "Pretty"
run: yarn run pretty
working-directory: "front"
- name: "Jasmine" - name: "Jasmine"
run: yarn test run: yarn test
working-directory: "front" working-directory: "front"

View File

@ -14,7 +14,7 @@ WA.state.onVariableChange(key : string).subscribe((data: unknown) => {}) : Subsc
WA.state.[any property]: unknown WA.state.[any property]: unknown
``` ```
These methods and properties can be used to save, load and track changes in variables related to the current room. These methods and properties can be used to save, load and track changes in [variables related to the current room](variables.md).
Variables stored in `WA.state` can be any value that is serializable in JSON. Variables stored in `WA.state` can be any value that is serializable in JSON.
@ -63,44 +63,11 @@ that you get the expected type).
For security reasons, the list of variables you are allowed to access and modify is **restricted** (otherwise, anyone on your map could set any data). For security reasons, the list of variables you are allowed to access and modify is **restricted** (otherwise, anyone on your map could set any data).
Variables storage is subject to an authorization process. Read below to learn more. Variables storage is subject to an authorization process. Read below to learn more.
### Declaring allowed keys ## Defining a variable
In order to declare allowed keys related to a room, you need to add **objects** in an "object layer" of the map. Out of the box, you cannot edit *any* variable. Variables MUST be declared in the map.
Each object will represent a variable.
<div class="row">
<div class="col">
<img src="images/object_variable.png" class="figure-img img-fluid rounded" alt="" />
</div>
</div>
The name of the variable is the name of the object.
The object **type** MUST be **variable**.
You can set a default value for the object in the `default` property.
### Persisting variables state
Use the `persist` property to save the state of the variable in database. If `persist` is false, the variable will stay
in the memory of the WorkAdventure servers but will be wiped out of the memory as soon as the room is empty (or if the
server restarts).
{.alert.alert-info}
Do not use `persist` for highly dynamic values that have a short life spawn.
### Managing access rights to variables
With `readableBy` and `writableBy`, you control who can read of write in this variable. The property accepts a string
representing a "tag". Anyone having this "tag" can read/write in the variable.
{.alert.alert-warning}
`readableBy` and `writableBy` are specific to the "online" version of WorkAdventure because the notion of tags
is not available unless you have an "admin" server (that is not part of the self-hosted version of WorkAdventure).
Finally, the `jsonSchema` property can contain [a complete JSON schema](https://json-schema.org/) to validate the content of the variable.
Trying to set a variable to a value that is not compatible with the schema will fail.
Check the [dedicated variables page](variables.md) to learn how to declare a variable in a map.
## Tracking variables changes ## Tracking variables changes

59
docs/maps/variables.md Normal file
View File

@ -0,0 +1,59 @@
{.section-title.accent.text-primary}
# Variables
Maps can contain **variables**. Variables are piece of information that store some data. In computer science, we like
to say variables are storing the "state" of the room.
- Variables are shared amongst all players in a given room. When the value of a variable changes for one player, it changes
for everyone.
- Variables are **invisible**. There are plenty of ways they can act on the room, but by default, you don't see them.
## Declaring a variable
In order to declare allowed variables in a room, you need to add **objects** in an "object layer" of the map.
Each object will represent a variable.
<div class="row">
<div class="col">
<img src="images/object_variable.png" class="figure-img img-fluid rounded" alt="" />
</div>
</div>
The name of the variable is the name of the object.
The object **type** MUST be **variable**.
You can set a default value for the object in the `default` property.
## Persisting variables state
Use the `persist` property to save the state of the variable in database. If `persist` is false, the variable will stay
in the memory of the WorkAdventure servers but will be wiped out of the memory as soon as the room is empty (or if the
server restarts).
{.alert.alert-info}
Do not use `persist` for highly dynamic values that have a short life spawn.
## Managing access rights to variables
With `readableBy` and `writableBy`, you control who can read of write in this variable. The property accepts a string
representing a "tag". Anyone having this "tag" can read/write in the variable.
{.alert.alert-warning}
`readableBy` and `writableBy` are specific to the "online" version of WorkAdventure because the notion of tags
is not available unless you have an "admin" server (that is not part of the self-hosted version of WorkAdventure).
In a future release, the `jsonSchema` property will contain [a complete JSON schema](https://json-schema.org/) to validate the content of the variable.
Trying to set a variable to a value that is not compatible with the schema will fail.
## Using variables
There are plenty of ways to use variables in WorkAdventure:
- Using the [scripting API](api-state.md), you can read, edit or track the content of variables.
- Using the [Action zones](https://workadventu.re/map-building-extra/generic-action-zones.md), you can set the value of a variable when someone is entering or leaving a zone
- By [binding variable values to properties in the map](https://workadventu.re/map-building-extra/variable-to-property-binding.md)
- By [using automatically generated configuration screens](https://workadventu.re/map-building-extra/automatic-configuration.md) to create forms to edit the value of variables
In general, variables can be used by third party libraries that you can embed in your map to add extra features.
A good example of such a library is the ["Scripting API Extra" library](https://workadventu.re/map-building-extra/about.md)

View File

View File

@ -1,11 +1,11 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isButtonClickedEvent = export const isButtonClickedEvent = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
popupId: tg.isNumber, popupId: tg.isNumber,
buttonId: tg.isNumber, buttonId: tg.isNumber,
input : tg.isBoolean, input: tg.isBoolean,
inputValue : tg.isString, inputValue: tg.isString,
}).get(); }).get();
/** /**
* A message sent from the game to the iFrame when a user enters or leaves a zone marked with the "zone" property. * A message sent from the game to the iFrame when a user enters or leaves a zone marked with the "zone" property.

View File

@ -1,10 +1,11 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isChatEvent = export const isChatEvent = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
message: tg.isString, message: tg.isString,
author: tg.isString, author: tg.isString,
}).get(); })
.get();
/** /**
* A message sent from the iFrame to the game to add a message in the chat. * A message sent from the iFrame to the game to add a message in the chat.
*/ */

View File

@ -1,9 +1,9 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isClosePopupEvent = export const isClosePopupEvent = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
popupId: tg.isNumber, popupId: tg.isNumber,
inputValue : tg.isString, inputValue: tg.isString,
}).get(); }).get();
/** /**

View File

@ -1,9 +1,10 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isEnterLeaveEvent = export const isEnterLeaveEvent = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
name: tg.isString, name: tg.isString,
}).get(); })
.get();
/** /**
* A message sent from the game to the iFrame when a user enters or leaves a zone marked with the "zone" property. * A message sent from the game to the iFrame when a user enters or leaves a zone marked with the "zone" property.
*/ */

View File

@ -1,11 +1,10 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isGoToPageEvent = new tg.IsInterface()
.withProperties({
export const isGoToPageEvent =
new tg.IsInterface().withProperties({
url: tg.isString, url: tg.isString,
}).get(); })
.get();
/** /**
* A message sent from the iFrame to the game to add a message in the chat. * A message sent from the iFrame to the game to add a message in the chat.

View File

@ -1,9 +1,10 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isLoadSoundEvent = export const isLoadSoundEvent = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
url: tg.isString, url: tg.isString,
}).get(); })
.get();
/** /**
* A message sent from the iFrame to the game to add a message in the chat. * A message sent from the iFrame to the game to add a message in the chat.

View File

@ -1,13 +1,14 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
const isButtonDescriptor = const isButtonDescriptor = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
label: tg.isString, label: tg.isString,
className: tg.isOptional(tg.isString) className: tg.isOptional(tg.isString),
}).get(); })
.get();
export const isOpenPopupEvent = export const isOpenPopupEvent = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
popupId: tg.isNumber, popupId: tg.isNumber,
targetObject: tg.isString, targetObject: tg.isString,
message: tg.isString, message: tg.isString,

View File

@ -1,11 +1,10 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isOpenTabEvent = new tg.IsInterface()
.withProperties({
export const isOpenTabEvent =
new tg.IsInterface().withProperties({
url: tg.isString, url: tg.isString,
}).get(); })
.get();
/** /**
* A message sent from the iFrame to the game to add a message in the chat. * A message sent from the iFrame to the game to add a message in the chat.

View File

@ -1,22 +1,23 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
const isSoundConfig = new tg.IsInterface()
const isSoundConfig = .withProperties({
new tg.IsInterface().withProperties({
volume: tg.isOptional(tg.isNumber), volume: tg.isOptional(tg.isNumber),
loop: tg.isOptional(tg.isBoolean), loop: tg.isOptional(tg.isBoolean),
mute: tg.isOptional(tg.isBoolean), mute: tg.isOptional(tg.isBoolean),
rate: tg.isOptional(tg.isNumber), rate: tg.isOptional(tg.isNumber),
detune: tg.isOptional(tg.isNumber), detune: tg.isOptional(tg.isNumber),
seek: tg.isOptional(tg.isNumber), seek: tg.isOptional(tg.isNumber),
delay: tg.isOptional(tg.isNumber) delay: tg.isOptional(tg.isNumber),
}).get(); })
.get();
export const isPlaySoundEvent = export const isPlaySoundEvent = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
url: tg.isString, url: tg.isString,
config : tg.isOptional(isSoundConfig), config: tg.isOptional(isSoundConfig),
}).get(); })
.get();
/** /**
* A message sent from the iFrame to the game to add a message in the chat. * A message sent from the iFrame to the game to add a message in the chat.

View File

@ -1,9 +1,10 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isStopSoundEvent = export const isStopSoundEvent = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
url: tg.isString, url: tg.isString,
}).get(); })
.get();
/** /**
* A message sent from the iFrame to the game to add a message in the chat. * A message sent from the iFrame to the game to add a message in the chat.

View File

@ -1,9 +1,10 @@
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
export const isUserInputChatEvent = export const isUserInputChatEvent = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
message: tg.isString, message: tg.isString,
}).get(); })
.get();
/** /**
* A message sent from the game to the iFrame when a user types a message in the chat. * A message sent from the game to the iFrame when a user types a message in the chat.
*/ */

View File

@ -1,4 +1,4 @@
import type {Popup} from "./Popup"; import type { Popup } from "./Popup";
export type ButtonClickedCallback = (popup: Popup) => void; export type ButtonClickedCallback = (popup: Popup) => void;
@ -6,13 +6,13 @@ export interface ButtonDescriptor {
/** /**
* The label of the button * The label of the button
*/ */
label: string, label: string;
/** /**
* The type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled" * The type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled"
*/ */
className?: "normal" | "primary" | "success" | "warning" | "error" | "disabled", className?: "normal" | "primary" | "success" | "warning" | "error" | "disabled";
/** /**
* Callback called if the button is pressed * Callback called if the button is pressed
*/ */
callback: ButtonClickedCallback, callback: ButtonClickedCallback;
} }

View File

@ -1,5 +1,5 @@
import {sendToWorkadventure} from "../IframeApiContribution"; import { sendToWorkadventure } from "../IframeApiContribution";
import type {ClosePopupEvent} from "../../Events/ClosePopupEvent"; import type { ClosePopupEvent } from "../../Events/ClosePopupEvent";
export class Popup { export class Popup {

View File

@ -1,16 +1,18 @@
import type {IframeResponseEventMap} from "../../Api/Events/IframeEvent"; import type { IframeResponseEventMap } from "../../Api/Events/IframeEvent";
import type {IframeCallback} from "../../Api/iframe/IframeApiContribution"; import type { IframeCallback } from "../../Api/iframe/IframeApiContribution";
import type {IframeCallbackContribution} from "../../Api/iframe/IframeApiContribution"; import type { IframeCallbackContribution } from "../../Api/iframe/IframeApiContribution";
export const registeredCallbacks: { [K in keyof IframeResponseEventMap]?: IframeCallback<K> } = {} export const registeredCallbacks: { [K in keyof IframeResponseEventMap]?: IframeCallback<K> } = {};
export function apiCallback<T extends keyof IframeResponseEventMap>(callbackData: IframeCallbackContribution<T>): IframeCallbackContribution<keyof IframeResponseEventMap> { export function apiCallback<T extends keyof IframeResponseEventMap>(
callbackData: IframeCallbackContribution<T>
): IframeCallbackContribution<keyof IframeResponseEventMap> {
const iframeCallback = { const iframeCallback = {
typeChecker: callbackData.typeChecker, typeChecker: callbackData.typeChecker,
callback: callbackData.callback callback: callbackData.callback,
} as IframeCallback<T>; } as IframeCallback<T>;
const newCallback = { [callbackData.type]: iframeCallback }; const newCallback = { [callbackData.type]: iframeCallback };
Object.assign(registeredCallbacks, newCallback) Object.assign(registeredCallbacks, newCallback);
return callbackData as unknown as IframeCallbackContribution<keyof IframeResponseEventMap>; return callbackData as unknown as IframeCallbackContribution<keyof IframeResponseEventMap>;
} }

View File

@ -1,10 +1,5 @@
<script lang="ts"> <script lang="ts">
function goToGettingStarted() {
const sparkHost = "https://workadventu.re/getting-started";
window.open(sparkHost, "_blank");
}
function goToBuildingMap() { function goToBuildingMap() {
const sparkHost = "https://wiki.bstly.de/services/partey/map"; const sparkHost = "https://wiki.bstly.de/services/partey/map";
window.open(sparkHost, "_blank"); window.open(sparkHost, "_blank");

View File

@ -1,56 +1,49 @@
<script lang="typescript"> <script lang="typescript">
import {gameManager} from "../../Phaser/Game/GameManager"; import { gameManager } from "../../Phaser/Game/GameManager";
import {SelectCompanionScene, SelectCompanionSceneName} from "../../Phaser/Login/SelectCompanionScene"; import { SelectCompanionScene, SelectCompanionSceneName } from "../../Phaser/Login/SelectCompanionScene";
import {menuIconVisiblilityStore, menuVisiblilityStore, userIsConnected} from "../../Stores/MenuStore"; import { menuIconVisiblilityStore, menuVisiblilityStore, userIsConnected } from "../../Stores/MenuStore";
import {selectCompanionSceneVisibleStore} from "../../Stores/SelectCompanionStore"; import { selectCompanionSceneVisibleStore } from "../../Stores/SelectCompanionStore";
import {LoginScene, LoginSceneName} from "../../Phaser/Login/LoginScene"; import { loginSceneVisibleStore } from "../../Stores/LoginSceneStore";
import {loginSceneVisibleStore} from "../../Stores/LoginSceneStore"; import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore";
import {selectCharacterSceneVisibleStore} from "../../Stores/SelectCharacterStore"; import { SelectCharacterScene, SelectCharacterSceneName } from "../../Phaser/Login/SelectCharacterScene";
import {SelectCharacterScene, SelectCharacterSceneName} from "../../Phaser/Login/SelectCharacterScene"; import { connectionManager } from "../../Connexion/ConnectionManager";
import {connectionManager} from "../../Connexion/ConnectionManager"; import { PROFILE_URL } from "../../Enum/EnvironmentVariable";
import {PROFILE_URL} from "../../Enum/EnvironmentVariable"; import { localUserStore } from "../../Connexion/LocalUserStore";
import {localUserStore} from "../../Connexion/LocalUserStore"; import { EnableCameraScene, EnableCameraSceneName } from "../../Phaser/Login/EnableCameraScene";
import {EnableCameraScene, EnableCameraSceneName} from "../../Phaser/Login/EnableCameraScene"; import { enableCameraSceneVisibilityStore } from "../../Stores/MediaStore";
import {enableCameraSceneVisibilityStore} from "../../Stores/MediaStore";
function disableMenuStores(){ function disableMenuStores() {
menuVisiblilityStore.set(false); menuVisiblilityStore.set(false);
menuIconVisiblilityStore.set(false); menuIconVisiblilityStore.set(false);
} }
function openEditCompanionScene(){ function openEditCompanionScene() {
disableMenuStores(); disableMenuStores();
selectCompanionSceneVisibleStore.set(true); selectCompanionSceneVisibleStore.set(true);
gameManager.leaveGame(SelectCompanionSceneName,new SelectCompanionScene()); gameManager.leaveGame(SelectCompanionSceneName, new SelectCompanionScene());
} }
function openEditNameScene(){ function openEditSkinScene() {
disableMenuStores();
loginSceneVisibleStore.set(true);
gameManager.leaveGame(LoginSceneName,new LoginScene());
}
function openEditSkinScene(){
disableMenuStores(); disableMenuStores();
selectCharacterSceneVisibleStore.set(true); selectCharacterSceneVisibleStore.set(true);
gameManager.leaveGame(SelectCharacterSceneName,new SelectCharacterScene()); gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene());
} }
function logOut(){ function logOut() {
disableMenuStores(); disableMenuStores();
loginSceneVisibleStore.set(true); loginSceneVisibleStore.set(true);
connectionManager.logout(); connectionManager.logout();
} }
function getProfileUrl(){ function getProfileUrl() {
return PROFILE_URL + `?token=${localUserStore.getAuthToken()}`; return PROFILE_URL + `?token=${localUserStore.getAuthToken()}`;
} }
function openEnableCameraScene(){ function openEnableCameraScene() {
disableMenuStores(); disableMenuStores();
enableCameraSceneVisibilityStore.showEnableCameraScene(); enableCameraSceneVisibilityStore.showEnableCameraScene();
gameManager.leaveGame(EnableCameraSceneName,new EnableCameraScene()); gameManager.leaveGame(EnableCameraSceneName, new EnableCameraScene());
} }
//TODO: Uncomment when login will be completely developed //TODO: Uncomment when login will be completely developed
@ -61,56 +54,55 @@
<div class="customize-main"> <div class="customize-main">
{#if $userIsConnected} {#if $userIsConnected}
<section> <section>
{#if PROFILE_URL != undefined} {#if PROFILE_URL != undefined}
<iframe title="profile" src="{getProfileUrl()}"></iframe> <iframe title="profile" src="{getProfileUrl()}"></iframe>
{/if} {/if}
</section> </section>
<section> <section>
<button type="button" class="nes-btn" on:click|preventDefault={logOut}>Log out</button> <button type="button" class="nes-btn" on:click|preventDefault={logOut}>Log out</button>
</section> </section>
{:else} {:else}
<section> <section>
<a type="button" class="nes-btn" href="/login">Sing in</a> <a type="button" class="nes-btn" href="/login">Sing in</a>
</section> </section>
{/if} {/if}
<section> <section>
<!-- <button type="button" class="nes-btn" on:click|preventDefault={openEditNameScene}>Edit Name</button> -->
<button type="button" class="nes-btn is-rounded" on:click|preventDefault={openEditSkinScene}>Edit Skin</button> <button type="button" class="nes-btn is-rounded" on:click|preventDefault={openEditSkinScene}>Edit Skin</button>
<button type="button" class="nes-btn" on:click|preventDefault={openEditCompanionScene}>Edit Companion</button> <button type="button" class="nes-btn" on:click|preventDefault={openEditCompanionScene}>Edit Companion</button>
</section> </section>
<section> <section>
<button type="button" class="nes-btn" on:click|preventDefault={openEnableCameraScene}>Setup camera</button> <button type="button" class="nes-btn" on:click|preventDefault={openEnableCameraScene}>Setup camera</button>
</section> </section>
<!-- <section> <!-- <section>
<button type="button" class="nes-btn is-primary" on:click|preventDefault={clickLogin}>Login</button> <button type="button" class="nes-btn is-primary" on:click|preventDefault={clickLogin}>Login</button>
</section>--> </section>-->
</div> </div>
<style lang="scss"> <style lang="scss">
div.customize-main{ div.customize-main {
section { section {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-bottom: 20px; margin-bottom: 20px;
iframe{ iframe {
width: 100%; width: 100%;
height: 50vh; height: 50vh;
border: none; border: none;
} }
button { button {
height: 50px; height: 50px;
width: 250px; width: 250px;
}
} }
}
} }
@media only screen and (max-width: 800px) { @media only screen and (max-width: 800px) {
div.customize-main section button { div.customize-main section button {
width: 130px; width: 130px;
} }
} }
</style> </style>

View File

@ -1,11 +1,11 @@
<script lang="typescript"> <script lang="typescript">
import {obtainedMediaConstraintStore} from "../Stores/MediaStore"; import { obtainedMediaConstraintStore } from "../Stores/MediaStore";
import {localStreamStore, isSilentStore} from "../Stores/MediaStore"; import { localStreamStore, isSilentStore } from "../Stores/MediaStore";
import SoundMeterWidget from "./SoundMeterWidget.svelte"; import SoundMeterWidget from "./SoundMeterWidget.svelte";
import {onDestroy} from "svelte"; import { onDestroy } from "svelte";
import {srcObject} from "./Video/utils"; import { srcObject } from "./Video/utils";
let stream : MediaStream|null; let stream: MediaStream | null;
const unsubscribe = localStreamStore.subscribe(value => { const unsubscribe = localStreamStore.subscribe(value => {
if (value.type === 'success') { if (value.type === 'success') {
@ -29,7 +29,8 @@
<div> <div>
<div class="video-container nes-container is-rounded is-dark div-myCamVideo" class:hide={!$obtainedMediaConstraintStore.video || isSilent}> <div class="video-container nes-container is-rounded is-dark div-myCamVideo"
class:hide={!$obtainedMediaConstraintStore.video || isSilent}>
{#if $localStreamStore.type === "success" && $localStreamStore.stream} {#if $localStreamStore.type === "success" && $localStreamStore.stream}
<video class="myCamVideo" use:srcObject={stream} autoplay muted playsinline></video> <video class="myCamVideo" use:srcObject={stream} autoplay muted playsinline></video>
<SoundMeterWidget stream={stream}></SoundMeterWidget> <SoundMeterWidget stream={stream}></SoundMeterWidget>
@ -38,4 +39,4 @@
<div class="is-silent" class:hide={isSilent}> <div class="is-silent" class:hide={isSilent}>
Silent zone Silent zone
</div> </div>
</div> </div>

View File

@ -1,15 +1,15 @@
import {Subject} from "rxjs"; import { Subject } from "rxjs";
import type {BanUserMessage, SendUserMessage} from "../Messages/generated/messages_pb"; import type { BanUserMessage, SendUserMessage } from "../Messages/generated/messages_pb";
export enum AdminMessageEventTypes { export enum AdminMessageEventTypes {
admin = 'message', admin = "message",
audio = 'audio', audio = "audio",
ban = 'ban', ban = "ban",
banned = 'banned', banned = "banned",
} }
interface AdminMessageEvent { interface AdminMessageEvent {
type: AdminMessageEventTypes, type: AdminMessageEventTypes;
text: string; text: string;
//todo add optional properties for other event types //todo add optional properties for other event types
} }
@ -21,14 +21,14 @@ class AdminMessagesService {
public messageStream = this._messageStream.asObservable(); public messageStream = this._messageStream.asObservable();
constructor() { constructor() {
this.messageStream.subscribe((event) => console.log('message', event)) this.messageStream.subscribe((event) => console.log("message", event));
} }
onSendusermessage(message: SendUserMessage|BanUserMessage) { onSendusermessage(message: SendUserMessage | BanUserMessage) {
this._messageStream.next({ this._messageStream.next({
type: message.getType() as unknown as AdminMessageEventTypes, type: message.getType() as unknown as AdminMessageEventTypes,
text: message.getMessage(), text: message.getMessage(),
}) });
} }
} }

View File

@ -1,19 +1,18 @@
import {Subject} from "rxjs"; import { Subject } from "rxjs";
interface EmoteEvent { interface EmoteEvent {
userId: number, userId: number;
emote: string, emote: string;
} }
class EmoteEventStream { class EmoteEventStream {
private _stream: Subject<EmoteEvent> = new Subject();
private _stream:Subject<EmoteEvent> = new Subject();
public stream = this._stream.asObservable(); public stream = this._stream.asObservable();
fire(userId: number, emote:string) { fire(userId: number, emote: string) {
this._stream.next({userId, emote}); this._stream.next({ userId, emote });
} }
} }
export const emoteEventStream = new EmoteEventStream(); export const emoteEventStream = new EmoteEventStream();

View File

@ -1,14 +1,12 @@
import {Subject} from "rxjs"; import { Subject } from "rxjs";
class WorldFullMessageStream { class WorldFullMessageStream {
private _stream: Subject<string | null> = new Subject<string | null>();
private _stream:Subject<string|null> = new Subject<string|null>();
public stream = this._stream.asObservable(); public stream = this._stream.asObservable();
onMessage(message?: string) {
onMessage(message? :string) {
this._stream.next(message); this._stream.next(message);
} }
} }
export const worldFullMessageStream = new WorldFullMessageStream(); export const worldFullMessageStream = new WorldFullMessageStream();

View File

@ -1 +1 @@
export class TextureError extends Error{} export class TextureError extends Error {}

View File

@ -1,19 +1,21 @@
export class MessageUI { export class MessageUI {
static warningMessage(text: string) {
static warningMessage(text: string){
this.removeMessage(); this.removeMessage();
const body = document.getElementById("body"); const body = document.getElementById("body");
body?.insertAdjacentHTML('afterbegin', ` body?.insertAdjacentHTML(
"afterbegin",
`
<div id="message-reconnect" class="message-info warning"> <div id="message-reconnect" class="message-info warning">
${text} ${text}
</div> </div>
`); `
);
} }
static removeMessage(id : string|null = null) { static removeMessage(id: string | null = null) {
if(!id){ if (!id) {
const messages = document.getElementsByClassName("message-info"); const messages = document.getElementsByClassName("message-info");
for (let i = 0; i < messages.length; i++){ for (let i = 0; i < messages.length; i++) {
messages.item(i)?.remove(); messages.item(i)?.remove();
} }
return; return;

View File

@ -1,23 +1,22 @@
import {PositionMessage} from "../Messages/generated/messages_pb"; import { PositionMessage } from "../Messages/generated/messages_pb";
import Direction = PositionMessage.Direction; import Direction = PositionMessage.Direction;
import type {PointInterface} from "../Connexion/ConnexionModels"; import type { PointInterface } from "../Connexion/ConnexionModels";
export class ProtobufClientUtils { export class ProtobufClientUtils {
public static toPointInterface(position: PositionMessage): PointInterface { public static toPointInterface(position: PositionMessage): PointInterface {
let direction: string; let direction: string;
switch (position.getDirection()) { switch (position.getDirection()) {
case Direction.UP: case Direction.UP:
direction = 'up'; direction = "up";
break; break;
case Direction.DOWN: case Direction.DOWN:
direction = 'down'; direction = "down";
break; break;
case Direction.LEFT: case Direction.LEFT:
direction = 'left'; direction = "left";
break; break;
case Direction.RIGHT: case Direction.RIGHT:
direction = 'right'; direction = "right";
break; break;
default: default:
throw new Error("Unexpected direction"); throw new Error("Unexpected direction");

View File

@ -16,7 +16,7 @@ export class Companion extends Container {
private delta: number; private delta: number;
private invisible: boolean; private invisible: boolean;
private updateListener: Function; private updateListener: Function;
private target: { x: number, y: number, direction: PlayerAnimationDirections }; private target: { x: number; y: number; direction: PlayerAnimationDirections };
private companionName: string; private companionName: string;
private direction: PlayerAnimationDirections; private direction: PlayerAnimationDirections;
@ -36,10 +36,10 @@ export class Companion extends Container {
this.companionName = name; this.companionName = name;
texturePromise.then(resource => { texturePromise.then((resource) => {
this.addResource(resource); this.addResource(resource);
this.invisible = false; this.invisible = false;
}) });
this.scene.physics.world.enableBody(this); this.scene.physics.world.enableBody(this);
@ -52,7 +52,7 @@ export class Companion extends Container {
this.setDepth(-1); this.setDepth(-1);
this.updateListener = this.step.bind(this); this.updateListener = this.step.bind(this);
this.scene.events.addListener('update', this.updateListener); this.scene.events.addListener("update", this.updateListener);
this.scene.add.existing(this); this.scene.add.existing(this);
} }
@ -62,7 +62,7 @@ export class Companion extends Container {
} }
public step(time: number, delta: number) { public step(time: number, delta: number) {
if (typeof this.target === 'undefined') return; if (typeof this.target === "undefined") return;
this.delta += delta; this.delta += delta;
if (this.delta < 128) { if (this.delta < 128) {
@ -87,7 +87,10 @@ export class Companion extends Container {
const yDir = yDist / Math.max(Math.abs(yDist), 1); const yDir = yDist / Math.max(Math.abs(yDist), 1);
const speed = 256; const speed = 256;
this.getBody().setVelocity(Math.min(Math.abs(xDist * 2.5), speed) * xDir, Math.min(Math.abs(yDist * 2.5), speed) * yDir); this.getBody().setVelocity(
Math.min(Math.abs(xDist * 2.5), speed) * xDir,
Math.min(Math.abs(yDist * 2.5), speed) * yDir
);
if (Math.abs(xDist) > Math.abs(yDist)) { if (Math.abs(xDist) > Math.abs(yDist)) {
if (xDist < 0) { if (xDist < 0) {
@ -116,8 +119,8 @@ export class Companion extends Container {
y, y,
direction, direction,
moving: animationType === PlayerAnimationTypes.Walk, moving: animationType === PlayerAnimationTypes.Walk,
name: companionName name: companionName,
} };
} }
private playAnimation(direction: PlayerAnimationDirections, type: PlayerAnimationTypes): void { private playAnimation(direction: PlayerAnimationDirections, type: PlayerAnimationTypes): void {
@ -133,7 +136,7 @@ export class Companion extends Container {
this.add(sprite); this.add(sprite);
this.getAnimations(resource).forEach(animation => { this.getAnimations(resource).forEach((animation) => {
this.scene.anims.create(animation); this.scene.anims.create(animation);
}); });
@ -145,60 +148,60 @@ export class Companion extends Container {
return [ return [
{ {
key: `${resource}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Idle}`, key: `${resource}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Idle}`,
frames: this.scene.anims.generateFrameNumbers(resource, {frames: [1]}), frames: this.scene.anims.generateFrameNumbers(resource, { frames: [1] }),
frameRate: 10, frameRate: 10,
repeat: 1 repeat: 1,
}, },
{ {
key: `${resource}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Idle}`, key: `${resource}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Idle}`,
frames: this.scene.anims.generateFrameNumbers(resource, {frames: [4]}), frames: this.scene.anims.generateFrameNumbers(resource, { frames: [4] }),
frameRate: 10, frameRate: 10,
repeat: 1 repeat: 1,
}, },
{ {
key: `${resource}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Idle}`, key: `${resource}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Idle}`,
frames: this.scene.anims.generateFrameNumbers(resource, {frames: [7]}), frames: this.scene.anims.generateFrameNumbers(resource, { frames: [7] }),
frameRate: 10, frameRate: 10,
repeat: 1 repeat: 1,
}, },
{ {
key: `${resource}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Idle}`, key: `${resource}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Idle}`,
frames: this.scene.anims.generateFrameNumbers(resource, {frames: [10]}), frames: this.scene.anims.generateFrameNumbers(resource, { frames: [10] }),
frameRate: 10, frameRate: 10,
repeat: 1 repeat: 1,
}, },
{ {
key: `${resource}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Walk}`, key: `${resource}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Walk}`,
frames: this.scene.anims.generateFrameNumbers(resource, {frames: [0, 1, 2]}), frames: this.scene.anims.generateFrameNumbers(resource, { frames: [0, 1, 2] }),
frameRate: 15, frameRate: 15,
repeat: -1 repeat: -1,
}, },
{ {
key: `${resource}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Walk}`, key: `${resource}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Walk}`,
frames: this.scene.anims.generateFrameNumbers(resource, {frames: [3, 4, 5]}), frames: this.scene.anims.generateFrameNumbers(resource, { frames: [3, 4, 5] }),
frameRate: 15, frameRate: 15,
repeat: -1 repeat: -1,
}, },
{ {
key: `${resource}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Walk}`, key: `${resource}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Walk}`,
frames: this.scene.anims.generateFrameNumbers(resource, {frames: [6, 7, 8]}), frames: this.scene.anims.generateFrameNumbers(resource, { frames: [6, 7, 8] }),
frameRate: 15, frameRate: 15,
repeat: -1 repeat: -1,
}, },
{ {
key: `${resource}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Walk}`, key: `${resource}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Walk}`,
frames: this.scene.anims.generateFrameNumbers(resource, {frames: [9, 10, 11]}), frames: this.scene.anims.generateFrameNumbers(resource, { frames: [9, 10, 11] }),
frameRate: 15, frameRate: 15,
repeat: -1 repeat: -1,
} },
] ];
} }
private getBody(): Phaser.Physics.Arcade.Body { private getBody(): Phaser.Physics.Arcade.Body {
const body = this.body; const body = this.body;
if (!(body instanceof Phaser.Physics.Arcade.Body)) { if (!(body instanceof Phaser.Physics.Arcade.Body)) {
throw new Error('Container does not have arcade body'); throw new Error("Container does not have arcade body");
} }
return body; return body;
@ -212,7 +215,7 @@ export class Companion extends Container {
} }
if (this.scene) { if (this.scene) {
this.scene.events.removeListener('update', this.updateListener); this.scene.events.removeListener("update", this.updateListener);
} }
super.destroy(); super.destroy();

View File

@ -1,7 +1,7 @@
export interface CompanionResourceDescriptionInterface { export interface CompanionResourceDescriptionInterface {
name: string, name: string;
img: string, img: string;
behaviour: "dog" | "cat" behaviour: "dog" | "cat";
} }
export const COMPANION_RESOURCES: CompanionResourceDescriptionInterface[] = [ export const COMPANION_RESOURCES: CompanionResourceDescriptionInterface[] = [
@ -11,4 +11,4 @@ export const COMPANION_RESOURCES: CompanionResourceDescriptionInterface[] = [
{ name: "cat1", img: "resources/characters/pipoya/Cat 01-1.png", behaviour: "cat" }, { name: "cat1", img: "resources/characters/pipoya/Cat 01-1.png", behaviour: "cat" },
{ name: "cat2", img: "resources/characters/pipoya/Cat 01-2.png", behaviour: "cat" }, { name: "cat2", img: "resources/characters/pipoya/Cat 01-2.png", behaviour: "cat" },
{ name: "cat3", img: "resources/characters/pipoya/Cat 01-3.png", behaviour: "cat" }, { name: "cat3", img: "resources/characters/pipoya/Cat 01-3.png", behaviour: "cat" },
] ];

View File

@ -7,23 +7,23 @@ export const getAllCompanionResources = (loader: LoaderPlugin): CompanionResourc
}); });
return COMPANION_RESOURCES; return COMPANION_RESOURCES;
} };
export const lazyLoadCompanionResource = (loader: LoaderPlugin, name: string): Promise<string> => { export const lazyLoadCompanionResource = (loader: LoaderPlugin, name: string): Promise<string> => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const resource = COMPANION_RESOURCES.find(item => item.name === name); const resource = COMPANION_RESOURCES.find((item) => item.name === name);
if (typeof resource === 'undefined') { if (typeof resource === "undefined") {
return reject(`Texture '${name}' not found!`); return reject(`Texture '${name}' not found!`);
} }
if (loader.textureManager.exists(resource.name)) { if (loader.textureManager.exists(resource.name)) {
return resolve(resource.name); return resolve(resource.name);
} }
loader.spritesheet(resource.name, resource.img, { frameWidth: 32, frameHeight: 32, endFrame: 12 }); loader.spritesheet(resource.name, resource.img, { frameWidth: 32, frameHeight: 32, endFrame: 12 });
loader.once(`filecomplete-spritesheet-${resource.name}`, () => resolve(resource.name)); loader.once(`filecomplete-spritesheet-${resource.name}`, () => resolve(resource.name));
loader.start(); // It's only automatically started during the Scene preload. loader.start(); // It's only automatically started during the Scene preload.
}); });
} };

View File

@ -2,7 +2,7 @@ import { DEPTH_INGAME_TEXT_INDEX } from "../Game/DepthIndexes";
export class ChatModeIcon extends Phaser.GameObjects.Sprite { export class ChatModeIcon extends Phaser.GameObjects.Sprite {
constructor(scene: Phaser.Scene, x: number, y: number) { constructor(scene: Phaser.Scene, x: number, y: number) {
super(scene, x, y, 'layout_modes', 3); super(scene, x, y, "layout_modes", 3);
scene.add.existing(this); scene.add.existing(this);
this.setScrollFactor(0, 0); this.setScrollFactor(0, 0);
this.setOrigin(0, 1); this.setOrigin(0, 1);
@ -10,4 +10,4 @@ export class ChatModeIcon extends Phaser.GameObjects.Sprite {
this.setVisible(false); this.setVisible(false);
this.setDepth(DEPTH_INGAME_TEXT_INDEX); this.setDepth(DEPTH_INGAME_TEXT_INDEX);
} }
} }

View File

@ -1,11 +1,8 @@
export class ClickButton extends Phaser.GameObjects.Image {
export class ClickButton extends Phaser.GameObjects.Image{
constructor(scene: Phaser.Scene, x: number, y: number, textureName: string, callback: Function) { constructor(scene: Phaser.Scene, x: number, y: number, textureName: string, callback: Function) {
super(scene, x, y, textureName); super(scene, x, y, textureName);
this.scene.add.existing(this); this.scene.add.existing(this);
this.setInteractive(); this.setInteractive();
this.on("pointerup", callback); this.on("pointerup", callback);
} }
}
}

View File

@ -1,8 +1,8 @@
import {DEPTH_INGAME_TEXT_INDEX} from "../Game/DepthIndexes"; import { DEPTH_INGAME_TEXT_INDEX } from "../Game/DepthIndexes";
export class PresentationModeIcon extends Phaser.GameObjects.Sprite { export class PresentationModeIcon extends Phaser.GameObjects.Sprite {
constructor(scene: Phaser.Scene, x: number, y: number) { constructor(scene: Phaser.Scene, x: number, y: number) {
super(scene, x, y, 'layout_modes', 0); super(scene, x, y, "layout_modes", 0);
scene.add.existing(this); scene.add.existing(this);
this.setScrollFactor(0, 0); this.setScrollFactor(0, 0);
this.setOrigin(0, 1); this.setOrigin(0, 1);
@ -10,4 +10,4 @@ export class PresentationModeIcon extends Phaser.GameObjects.Sprite {
this.setVisible(false); this.setVisible(false);
this.setDepth(DEPTH_INGAME_TEXT_INDEX); this.setDepth(DEPTH_INGAME_TEXT_INDEX);
} }
} }

View File

@ -1,20 +1,20 @@
import Sprite = Phaser.GameObjects.Sprite; import Sprite = Phaser.GameObjects.Sprite;
import {DEPTH_UI_INDEX} from "../Game/DepthIndexes"; import { DEPTH_UI_INDEX } from "../Game/DepthIndexes";
import {waScaleManager} from "../Services/WaScaleManager"; import { waScaleManager } from "../Services/WaScaleManager";
export interface RadialMenuItem { export interface RadialMenuItem {
image: string, image: string;
name: string, name: string;
} }
export const RadialMenuClickEvent = 'radialClick'; export const RadialMenuClickEvent = "radialClick";
export class RadialMenu extends Phaser.GameObjects.Container { export class RadialMenu extends Phaser.GameObjects.Container {
private resizeCallback: OmitThisParameter<() => void>; private resizeCallback: OmitThisParameter<() => void>;
constructor(scene: Phaser.Scene, x: number, y: number, private items: RadialMenuItem[]) { constructor(scene: Phaser.Scene, x: number, y: number, private items: RadialMenuItem[]) {
super(scene, x, y); super(scene, x, y);
this.setDepth(DEPTH_UI_INDEX) this.setDepth(DEPTH_UI_INDEX);
this.scene.add.existing(this); this.scene.add.existing(this);
this.initItems(); this.initItems();
@ -22,45 +22,45 @@ export class RadialMenu extends Phaser.GameObjects.Container {
this.resizeCallback = this.resize.bind(this); this.resizeCallback = this.resize.bind(this);
this.scene.scale.on(Phaser.Scale.Events.RESIZE, this.resizeCallback); this.scene.scale.on(Phaser.Scale.Events.RESIZE, this.resizeCallback);
} }
private initItems() { private initItems() {
const itemsNumber = this.items.length; const itemsNumber = this.items.length;
const menuRadius = 70 + (waScaleManager.uiScalingFactor - 1) * 20; const menuRadius = 70 + (waScaleManager.uiScalingFactor - 1) * 20;
this.items.forEach((item, index) => this.createRadialElement(item, index, itemsNumber, menuRadius)) this.items.forEach((item, index) => this.createRadialElement(item, index, itemsNumber, menuRadius));
} }
private createRadialElement(item: RadialMenuItem, index: number, itemsNumber: number, menuRadius: number) { private createRadialElement(item: RadialMenuItem, index: number, itemsNumber: number, menuRadius: number) {
const image = new Sprite(this.scene, 0, menuRadius, item.image); const image = new Sprite(this.scene, 0, menuRadius, item.image);
this.add(image); this.add(image);
this.scene.sys.updateList.add(image); this.scene.sys.updateList.add(image);
const scalingFactor = waScaleManager.uiScalingFactor * 0.075; const scalingFactor = waScaleManager.uiScalingFactor * 0.075;
image.setScale(scalingFactor) image.setScale(scalingFactor);
image.setInteractive({ image.setInteractive({
useHandCursor: true, useHandCursor: true,
}); });
image.on('pointerdown', () => this.emit(RadialMenuClickEvent, item)); image.on("pointerdown", () => this.emit(RadialMenuClickEvent, item));
image.on('pointerover', () => { image.on("pointerover", () => {
this.scene.tweens.add({ this.scene.tweens.add({
targets: image, targets: image,
props: { props: {
scale: 2 * scalingFactor, scale: 2 * scalingFactor,
}, },
duration: 500, duration: 500,
ease: 'Power3', ease: "Power3",
}) });
}); });
image.on('pointerout', () => { image.on("pointerout", () => {
this.scene.tweens.add({ this.scene.tweens.add({
targets: image, targets: image,
props: { props: {
scale: scalingFactor, scale: scalingFactor,
}, },
duration: 500, duration: 500,
ease: 'Power3', ease: "Power3",
}) });
}); });
const angle = 2 * Math.PI * index / itemsNumber; const angle = (2 * Math.PI * index) / itemsNumber;
Phaser.Actions.RotateAroundDistance([image], {x: 0, y: 0}, angle, menuRadius); Phaser.Actions.RotateAroundDistance([image], { x: 0, y: 0 }, angle, menuRadius);
} }
private resize() { private resize() {
@ -71,4 +71,4 @@ export class RadialMenu extends Phaser.GameObjects.Container {
this.scene.scale.removeListener(Phaser.Scale.Events.RESIZE, this.resizeCallback); this.scene.scale.removeListener(Phaser.Scale.Events.RESIZE, this.resizeCallback);
super.destroy(); super.destroy();
} }
} }

View File

@ -1,4 +1,4 @@
import type {IAnalyserNode, IAudioContext, IMediaStreamAudioSourceNode} from 'standardized-audio-context'; import type { IAnalyserNode, IAudioContext, IMediaStreamAudioSourceNode } from "standardized-audio-context";
/** /**
* Class to measure the sound volume of a media stream * Class to measure the sound volume of a media stream
@ -7,10 +7,10 @@ export class SoundMeter {
private instant: number; private instant: number;
private clip: number; private clip: number;
//private script: ScriptProcessorNode; //private script: ScriptProcessorNode;
private analyser: IAnalyserNode<IAudioContext>|undefined; private analyser: IAnalyserNode<IAudioContext> | undefined;
private dataArray: Uint8Array|undefined; private dataArray: Uint8Array | undefined;
private context: IAudioContext|undefined; private context: IAudioContext | undefined;
private source: IMediaStreamAudioSourceNode<IAudioContext>|undefined; private source: IMediaStreamAudioSourceNode<IAudioContext> | undefined;
constructor() { constructor() {
this.instant = 0.0; this.instant = 0.0;
@ -27,8 +27,7 @@ export class SoundMeter {
this.dataArray = new Uint8Array(bufferLength); this.dataArray = new Uint8Array(bufferLength);
} }
public connectToSource(stream: MediaStream, context: IAudioContext): void public connectToSource(stream: MediaStream, context: IAudioContext): void {
{
if (this.source !== undefined) { if (this.source !== undefined) {
this.stop(); this.stop();
} }
@ -42,8 +41,6 @@ export class SoundMeter {
//analyser.connect(distortion); //analyser.connect(distortion);
//distortion.connect(this.context.destination); //distortion.connect(this.context.destination);
//this.analyser.connect(this.context.destination); //this.analyser.connect(this.context.destination);
} }
public getVolume(): number { public getVolume(): number {
@ -52,16 +49,15 @@ export class SoundMeter {
} }
this.analyser.getByteFrequencyData(this.dataArray); this.analyser.getByteFrequencyData(this.dataArray);
const input = this.dataArray; const input = this.dataArray;
let i; let i;
let sum = 0.0; let sum = 0.0;
//let clipcount = 0; //let clipcount = 0;
for (i = 0; i < input.length; ++i) { for (i = 0; i < input.length; ++i) {
sum += input[i] * input[i]; sum += input[i] * input[i];
// if (Math.abs(input[i]) > 0.99) { // if (Math.abs(input[i]) > 0.99) {
// clipcount += 1; // clipcount += 1;
// } // }
} }
this.instant = Math.sqrt(sum / input.length); this.instant = Math.sqrt(sum / input.length);
//this.slow = 0.95 * that.slow + 0.05 * that.instant; //this.slow = 0.95 * that.slow + 0.05 * that.instant;
@ -84,6 +80,4 @@ export class SoundMeter {
this.dataArray = undefined; this.dataArray = undefined;
this.source = undefined; this.source = undefined;
} }
} }

View File

@ -1,10 +1,9 @@
export class TextField extends Phaser.GameObjects.BitmapText { export class TextField extends Phaser.GameObjects.BitmapText {
constructor(scene: Phaser.Scene, x: number, y: number, text: string | string[], center: boolean = true) { constructor(scene: Phaser.Scene, x: number, y: number, text: string | string[], center: boolean = true) {
super(scene, x, y, 'main_font', text, 8); super(scene, x, y, "main_font", text, 8);
this.scene.add.existing(this); this.scene.add.existing(this);
if (center) { if (center) {
this.setOrigin(0.5).setCenterAlign() this.setOrigin(0.5).setCenterAlign();
} }
} }
} }

View File

@ -33,7 +33,7 @@ export abstract class Character extends Container {
private invisible: boolean; private invisible: boolean;
public companion?: Companion; public companion?: Companion;
private emote: Phaser.GameObjects.Text | null = null; private emote: Phaser.GameObjects.Text | null = null;
private emoteTween: Phaser.Tweens.Tween|null = null; private emoteTween: Phaser.Tweens.Tween | null = null;
scene: GameScene; scene: GameScene;
constructor( constructor(
@ -146,56 +146,56 @@ export abstract class Character extends Container {
{ {
key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Walk}`, key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Walk}`,
frameModel: name, frameModel: name,
frames: [0, 1, 2, 1], frames: [ 0, 1, 2, 1 ],
frameRate: 10, frameRate: 10,
repeat: -1, repeat: -1,
}, },
{ {
key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Walk}`, key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Walk}`,
frameModel: name, frameModel: name,
frames: [3, 4, 5, 4], frames: [ 3, 4, 5, 4 ],
frameRate: 10, frameRate: 10,
repeat: -1, repeat: -1,
}, },
{ {
key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Walk}`, key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Walk}`,
frameModel: name, frameModel: name,
frames: [6, 7, 8, 7], frames: [ 6, 7, 8, 7 ],
frameRate: 10, frameRate: 10,
repeat: -1, repeat: -1,
}, },
{ {
key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Walk}`, key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Walk}`,
frameModel: name, frameModel: name,
frames: [9, 10, 11, 10], frames: [ 9, 10, 11, 10 ],
frameRate: 10, frameRate: 10,
repeat: -1, repeat: -1,
}, },
{ {
key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Idle}`, key: `${name}-${PlayerAnimationDirections.Down}-${PlayerAnimationTypes.Idle}`,
frameModel: name, frameModel: name,
frames: [1], frames: [ 1 ],
frameRate: 10, frameRate: 10,
repeat: 1, repeat: 1,
}, },
{ {
key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Idle}`, key: `${name}-${PlayerAnimationDirections.Left}-${PlayerAnimationTypes.Idle}`,
frameModel: name, frameModel: name,
frames: [4], frames: [ 4 ],
frameRate: 10, frameRate: 10,
repeat: 1, repeat: 1,
}, },
{ {
key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Idle}`, key: `${name}-${PlayerAnimationDirections.Right}-${PlayerAnimationTypes.Idle}`,
frameModel: name, frameModel: name,
frames: [7], frames: [ 7 ],
frameRate: 10, frameRate: 10,
repeat: 1, repeat: 1,
}, },
{ {
key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Idle}`, key: `${name}-${PlayerAnimationDirections.Up}-${PlayerAnimationTypes.Idle}`,
frameModel: name, frameModel: name,
frames: [10], frames: [ 10 ],
frameRate: 10, frameRate: 10,
repeat: 1, repeat: 1,
}, },
@ -204,7 +204,7 @@ export abstract class Character extends Container {
protected playAnimation(direction: PlayerAnimationDirections, moving: boolean): void { protected playAnimation(direction: PlayerAnimationDirections, moving: boolean): void {
if (this.invisible) return; if (this.invisible) return;
for (const [texture, sprite] of this.sprites.entries()) { for (const [ texture, sprite ] of this.sprites.entries()) {
if (!sprite.anims) { if (!sprite.anims) {
console.error("ANIMS IS NOT DEFINED!!!"); console.error("ANIMS IS NOT DEFINED!!!");
return; return;
@ -296,7 +296,7 @@ export abstract class Character extends Container {
const emoteY = -60; const emoteY = -60;
this.playerName.setVisible(false); this.playerName.setVisible(false);
this.emote = new Text(this.scene, -12, 0, emote, {fontFamily: '"twemoji"', fontSize:'24px'}); this.emote = new Text(this.scene, -12, 0, emote, { fontFamily: '"twemoji"', fontSize: '24px' });
this.emote.setAlpha(0); this.emote.setAlpha(0);
this.add(this.emote); this.add(this.emote);
this.createStartTransition(scalingFactor, emoteY); this.createStartTransition(scalingFactor, emoteY);

View File

@ -1,5 +1,5 @@
import Container = Phaser.GameObjects.Container; import Container = Phaser.GameObjects.Container;
import type {Scene} from "phaser"; import type { Scene } from "phaser";
import Sprite = Phaser.GameObjects.Sprite; import Sprite = Phaser.GameObjects.Sprite;
/** /**

View File

@ -1,334 +1,440 @@
//The list of all the player textures, both the default models and the partial textures used for customization //The list of all the player textures, both the default models and the partial textures used for customization
export interface BodyResourceDescriptionListInterface { export interface BodyResourceDescriptionListInterface {
[key: string]: BodyResourceDescriptionInterface [ key: string ]: BodyResourceDescriptionInterface;
} }
export interface BodyResourceDescriptionInterface { export interface BodyResourceDescriptionInterface {
name: string, name: string;
img: string, img: string;
level?: number level?: number;
} }
export const PLAYER_RESOURCES: BodyResourceDescriptionListInterface = { export const PLAYER_RESOURCES: BodyResourceDescriptionListInterface = {
"male1": {name: "male1", img: "resources/characters/pipoya/Male 01-1.png"}, male1: { name: "male1", img: "resources/characters/pipoya/Male 01-1.png" },
"male2": {name: "male2", img: "resources/characters/pipoya/Male 02-2.png"}, male2: { name: "male2", img: "resources/characters/pipoya/Male 02-2.png" },
"male3": {name: "male3", img: "resources/characters/pipoya/Male 03-4.png"}, male3: { name: "male3", img: "resources/characters/pipoya/Male 03-4.png" },
"male4": {name: "male4", img: "resources/characters/pipoya/Male 09-1.png"}, male4: { name: "male4", img: "resources/characters/pipoya/Male 09-1.png" },
"male5": {name: "male5", img: "resources/characters/pipoya/Male 10-3.png"}, male5: { name: "male5", img: "resources/characters/pipoya/Male 10-3.png" },
"male6": {name: "male6", img: "resources/characters/pipoya/Male 17-2.png"}, male6: { name: "male6", img: "resources/characters/pipoya/Male 17-2.png" },
"male7": {name: "male7", img: "resources/characters/pipoya/Male 18-1.png"}, male7: { name: "male7", img: "resources/characters/pipoya/Male 18-1.png" },
"male8": {name: "male8", img: "resources/characters/pipoya/Male 16-4.png"}, male8: { name: "male8", img: "resources/characters/pipoya/Male 16-4.png" },
"male9": {name: "male9", img: "resources/characters/pipoya/Male 07-2.png"}, male9: { name: "male9", img: "resources/characters/pipoya/Male 07-2.png" },
"male10": {name: "male10", img: "resources/characters/pipoya/Male 05-3.png"}, male10: { name: "male10", img: "resources/characters/pipoya/Male 05-3.png" },
"male11": {name: "male11", img: "resources/characters/pipoya/Teacher male 02.png"}, male11: { name: "male11", img: "resources/characters/pipoya/Teacher male 02.png" },
"male12": {name: "male12", img: "resources/characters/pipoya/su4 Student male 12.png"}, male12: { name: "male12", img: "resources/characters/pipoya/su4 Student male 12.png" },
"Female1": {name: "Female1", img: "resources/characters/pipoya/Female 01-1.png"}, Female1: { name: "Female1", img: "resources/characters/pipoya/Female 01-1.png" },
"Female2": {name: "Female2", img: "resources/characters/pipoya/Female 02-2.png"}, Female2: { name: "Female2", img: "resources/characters/pipoya/Female 02-2.png" },
"Female3": {name: "Female3", img: "resources/characters/pipoya/Female 03-4.png"}, Female3: { name: "Female3", img: "resources/characters/pipoya/Female 03-4.png" },
"Female4": {name: "Female4", img: "resources/characters/pipoya/Female 09-1.png"}, Female4: { name: "Female4", img: "resources/characters/pipoya/Female 09-1.png" },
"Female5": {name: "Female5", img: "resources/characters/pipoya/Female 10-3.png"}, Female5: { name: "Female5", img: "resources/characters/pipoya/Female 10-3.png" },
"Female6": {name: "Female6", img: "resources/characters/pipoya/Female 17-2.png"}, Female6: { name: "Female6", img: "resources/characters/pipoya/Female 17-2.png" },
"Female7": {name: "Female7", img: "resources/characters/pipoya/Female 18-1.png"}, Female7: { name: "Female7", img: "resources/characters/pipoya/Female 18-1.png" },
"Female8": {name: "Female8", img: "resources/characters/pipoya/Female 16-4.png"}, Female8: { name: "Female8", img: "resources/characters/pipoya/Female 16-4.png" },
"Female9": {name: "Female9", img: "resources/characters/pipoya/Female 07-2.png"}, Female9: { name: "Female9", img: "resources/characters/pipoya/Female 07-2.png" },
"Female10": {name: "Female10", img: "resources/characters/pipoya/Female 05-3.png"}, Female10: { name: "Female10", img: "resources/characters/pipoya/Female 05-3.png" },
"Female11": {name: "Female11", img: "resources/characters/pipoya/Teacher fmale 02.png"}, Female11: { name: "Female11", img: "resources/characters/pipoya/Teacher fmale 02.png" },
"Female12": {name: "Female12", img: "resources/characters/pipoya/su4 Student fmale 12.png"}, Female12: { name: "Female12", img: "resources/characters/pipoya/su4 Student fmale 12.png" },
}; };
export const COLOR_RESOURCES: BodyResourceDescriptionListInterface = { export const COLOR_RESOURCES: BodyResourceDescriptionListInterface = {
"color_1": {name: "color_1", img: "resources/customisation/character_color/character_color0.png"}, color_1: { name: "color_1", img: "resources/customisation/character_color/character_color0.png" },
"color_2": {name: "color_2", img: "resources/customisation/character_color/character_color1.png"}, color_2: { name: "color_2", img: "resources/customisation/character_color/character_color1.png" },
"color_3": {name: "color_3", img: "resources/customisation/character_color/character_color2.png"}, color_3: { name: "color_3", img: "resources/customisation/character_color/character_color2.png" },
"color_4": {name: "color_4", img: "resources/customisation/character_color/character_color3.png"}, color_4: { name: "color_4", img: "resources/customisation/character_color/character_color3.png" },
"color_5": {name: "color_5", img: "resources/customisation/character_color/character_color4.png"}, color_5: { name: "color_5", img: "resources/customisation/character_color/character_color4.png" },
"color_6": {name: "color_6", img: "resources/customisation/character_color/character_color5.png"}, color_6: { name: "color_6", img: "resources/customisation/character_color/character_color5.png" },
"color_7": {name: "color_7", img: "resources/customisation/character_color/character_color6.png"}, color_7: { name: "color_7", img: "resources/customisation/character_color/character_color6.png" },
"color_8": {name: "color_8", img: "resources/customisation/character_color/character_color7.png"}, color_8: { name: "color_8", img: "resources/customisation/character_color/character_color7.png" },
"color_9": {name: "color_9", img: "resources/customisation/character_color/character_color8.png"}, color_9: { name: "color_9", img: "resources/customisation/character_color/character_color8.png" },
"color_10": {name: "color_10", img: "resources/customisation/character_color/character_color9.png"}, color_10: { name: "color_10", img: "resources/customisation/character_color/character_color9.png" },
"color_11": {name: "color_11", img: "resources/customisation/character_color/character_color10.png"}, color_11: { name: "color_11", img: "resources/customisation/character_color/character_color10.png" },
"color_12": {name: "color_12", img: "resources/customisation/character_color/character_color11.png"}, color_12: { name: "color_12", img: "resources/customisation/character_color/character_color11.png" },
"color_13": {name: "color_13", img: "resources/customisation/character_color/character_color12.png"}, color_13: { name: "color_13", img: "resources/customisation/character_color/character_color12.png" },
"color_14": {name: "color_14", img: "resources/customisation/character_color/character_color13.png"}, color_14: { name: "color_14", img: "resources/customisation/character_color/character_color13.png" },
"color_15": {name: "color_15", img: "resources/customisation/character_color/character_color14.png"}, color_15: { name: "color_15", img: "resources/customisation/character_color/character_color14.png" },
"color_16": {name: "color_16", img: "resources/customisation/character_color/character_color15.png"}, color_16: { name: "color_16", img: "resources/customisation/character_color/character_color15.png" },
"color_17": {name: "color_17", img: "resources/customisation/character_color/character_color16.png"}, color_17: { name: "color_17", img: "resources/customisation/character_color/character_color16.png" },
"color_18": {name: "color_18", img: "resources/customisation/character_color/character_color17.png"}, color_18: { name: "color_18", img: "resources/customisation/character_color/character_color17.png" },
"color_19": {name: "color_19", img: "resources/customisation/character_color/character_color18.png"}, color_19: { name: "color_19", img: "resources/customisation/character_color/character_color18.png" },
"color_20": {name: "color_20", img: "resources/customisation/character_color/character_color19.png"}, color_20: { name: "color_20", img: "resources/customisation/character_color/character_color19.png" },
"color_21": {name: "color_21", img: "resources/customisation/character_color/character_color20.png"}, color_21: { name: "color_21", img: "resources/customisation/character_color/character_color20.png" },
"color_22": {name: "color_22", img: "resources/customisation/character_color/character_color21.png"}, color_22: { name: "color_22", img: "resources/customisation/character_color/character_color21.png" },
"color_23": {name: "color_23", img: "resources/customisation/character_color/character_color22.png"}, color_23: { name: "color_23", img: "resources/customisation/character_color/character_color22.png" },
"color_24": {name: "color_24", img: "resources/customisation/character_color/character_color23.png"}, color_24: { name: "color_24", img: "resources/customisation/character_color/character_color23.png" },
"color_25": {name: "color_25", img: "resources/customisation/character_color/character_color24.png"}, color_25: { name: "color_25", img: "resources/customisation/character_color/character_color24.png" },
"color_26": {name: "color_26", img: "resources/customisation/character_color/character_color25.png"}, color_26: { name: "color_26", img: "resources/customisation/character_color/character_color25.png" },
"color_27": {name: "color_27", img: "resources/customisation/character_color/character_color26.png"}, color_27: { name: "color_27", img: "resources/customisation/character_color/character_color26.png" },
"color_28": {name: "color_28", img: "resources/customisation/character_color/character_color27.png"}, color_28: { name: "color_28", img: "resources/customisation/character_color/character_color27.png" },
"color_29": {name: "color_29", img: "resources/customisation/character_color/character_color28.png"}, color_29: { name: "color_29", img: "resources/customisation/character_color/character_color28.png" },
"color_30": {name: "color_30", img: "resources/customisation/character_color/character_color29.png"}, color_30: { name: "color_30", img: "resources/customisation/character_color/character_color29.png" },
"color_31": {name: "color_31", img: "resources/customisation/character_color/character_color30.png"}, color_31: { name: "color_31", img: "resources/customisation/character_color/character_color30.png" },
"color_32": {name: "color_32", img: "resources/customisation/character_color/character_color31.png"}, color_32: { name: "color_32", img: "resources/customisation/character_color/character_color31.png" },
"color_33": {name: "color_33", img: "resources/customisation/character_color/character_color32.png"} color_33: { name: "color_33", img: "resources/customisation/character_color/character_color32.png" },
}; };
export const EYES_RESOURCES: BodyResourceDescriptionListInterface = { export const EYES_RESOURCES: BodyResourceDescriptionListInterface = {
"eyes_1": {name: "eyes_1", img: "resources/customisation/character_eyes/character_eyes1.png"}, eyes_1: { name: "eyes_1", img: "resources/customisation/character_eyes/character_eyes1.png" },
"eyes_2": {name: "eyes_2", img: "resources/customisation/character_eyes/character_eyes2.png"}, eyes_2: { name: "eyes_2", img: "resources/customisation/character_eyes/character_eyes2.png" },
"eyes_3": {name: "eyes_3", img: "resources/customisation/character_eyes/character_eyes3.png"}, eyes_3: { name: "eyes_3", img: "resources/customisation/character_eyes/character_eyes3.png" },
"eyes_4": {name: "eyes_4", img: "resources/customisation/character_eyes/character_eyes4.png"}, eyes_4: { name: "eyes_4", img: "resources/customisation/character_eyes/character_eyes4.png" },
"eyes_5": {name: "eyes_5", img: "resources/customisation/character_eyes/character_eyes5.png"}, eyes_5: { name: "eyes_5", img: "resources/customisation/character_eyes/character_eyes5.png" },
"eyes_6": {name: "eyes_6", img: "resources/customisation/character_eyes/character_eyes6.png"}, eyes_6: { name: "eyes_6", img: "resources/customisation/character_eyes/character_eyes6.png" },
"eyes_7": {name: "eyes_7", img: "resources/customisation/character_eyes/character_eyes7.png"}, eyes_7: { name: "eyes_7", img: "resources/customisation/character_eyes/character_eyes7.png" },
"eyes_8": {name: "eyes_8", img: "resources/customisation/character_eyes/character_eyes8.png"}, eyes_8: { name: "eyes_8", img: "resources/customisation/character_eyes/character_eyes8.png" },
"eyes_9": {name: "eyes_9", img: "resources/customisation/character_eyes/character_eyes9.png"}, eyes_9: { name: "eyes_9", img: "resources/customisation/character_eyes/character_eyes9.png" },
"eyes_10": {name: "eyes_10", img: "resources/customisation/character_eyes/character_eyes10.png"}, eyes_10: { name: "eyes_10", img: "resources/customisation/character_eyes/character_eyes10.png" },
"eyes_11": {name: "eyes_11", img: "resources/customisation/character_eyes/character_eyes11.png"}, eyes_11: { name: "eyes_11", img: "resources/customisation/character_eyes/character_eyes11.png" },
"eyes_12": {name: "eyes_12", img: "resources/customisation/character_eyes/character_eyes12.png"}, eyes_12: { name: "eyes_12", img: "resources/customisation/character_eyes/character_eyes12.png" },
"eyes_13": {name: "eyes_13", img: "resources/customisation/character_eyes/character_eyes13.png"}, eyes_13: { name: "eyes_13", img: "resources/customisation/character_eyes/character_eyes13.png" },
"eyes_14": {name: "eyes_14", img: "resources/customisation/character_eyes/character_eyes14.png"}, eyes_14: { name: "eyes_14", img: "resources/customisation/character_eyes/character_eyes14.png" },
"eyes_15": {name: "eyes_15", img: "resources/customisation/character_eyes/character_eyes15.png"}, eyes_15: { name: "eyes_15", img: "resources/customisation/character_eyes/character_eyes15.png" },
"eyes_16": {name: "eyes_16", img: "resources/customisation/character_eyes/character_eyes16.png"}, eyes_16: { name: "eyes_16", img: "resources/customisation/character_eyes/character_eyes16.png" },
"eyes_17": {name: "eyes_17", img: "resources/customisation/character_eyes/character_eyes17.png"}, eyes_17: { name: "eyes_17", img: "resources/customisation/character_eyes/character_eyes17.png" },
"eyes_18": {name: "eyes_18", img: "resources/customisation/character_eyes/character_eyes18.png"}, eyes_18: { name: "eyes_18", img: "resources/customisation/character_eyes/character_eyes18.png" },
"eyes_19": {name: "eyes_19", img: "resources/customisation/character_eyes/character_eyes19.png"}, eyes_19: { name: "eyes_19", img: "resources/customisation/character_eyes/character_eyes19.png" },
"eyes_20": {name: "eyes_20", img: "resources/customisation/character_eyes/character_eyes20.png"}, eyes_20: { name: "eyes_20", img: "resources/customisation/character_eyes/character_eyes20.png" },
"eyes_21": {name: "eyes_21", img: "resources/customisation/character_eyes/character_eyes21.png"}, eyes_21: { name: "eyes_21", img: "resources/customisation/character_eyes/character_eyes21.png" },
"eyes_22": {name: "eyes_22", img: "resources/customisation/character_eyes/character_eyes22.png"}, eyes_22: { name: "eyes_22", img: "resources/customisation/character_eyes/character_eyes22.png" },
"eyes_23": {name: "eyes_23", img: "resources/customisation/character_eyes/character_eyes23.png"}, eyes_23: { name: "eyes_23", img: "resources/customisation/character_eyes/character_eyes23.png" },
"eyes_24": {name: "eyes_24", img: "resources/customisation/character_eyes/character_eyes24.png"}, eyes_24: { name: "eyes_24", img: "resources/customisation/character_eyes/character_eyes24.png" },
"eyes_25": {name: "eyes_25", img: "resources/customisation/character_eyes/character_eyes25.png"}, eyes_25: { name: "eyes_25", img: "resources/customisation/character_eyes/character_eyes25.png" },
"eyes_26": {name: "eyes_26", img: "resources/customisation/character_eyes/character_eyes26.png"}, eyes_26: { name: "eyes_26", img: "resources/customisation/character_eyes/character_eyes26.png" },
"eyes_27": {name: "eyes_27", img: "resources/customisation/character_eyes/character_eyes27.png"}, eyes_27: { name: "eyes_27", img: "resources/customisation/character_eyes/character_eyes27.png" },
"eyes_28": {name: "eyes_28", img: "resources/customisation/character_eyes/character_eyes28.png"}, eyes_28: { name: "eyes_28", img: "resources/customisation/character_eyes/character_eyes28.png" },
"eyes_29": {name: "eyes_29", img: "resources/customisation/character_eyes/character_eyes29.png"}, eyes_29: { name: "eyes_29", img: "resources/customisation/character_eyes/character_eyes29.png" },
"eyes_30": {name: "eyes_30", img: "resources/customisation/character_eyes/character_eyes30.png"} eyes_30: { name: "eyes_30", img: "resources/customisation/character_eyes/character_eyes30.png" },
}; };
export const HAIR_RESOURCES: BodyResourceDescriptionListInterface = { export const HAIR_RESOURCES: BodyResourceDescriptionListInterface = {
"hair_1": {name:"hair_1", img: "resources/customisation/character_hairs/character_hairs0.png"}, hair_1: { name: "hair_1", img: "resources/customisation/character_hairs/character_hairs0.png" },
"hair_2": {name:"hair_2", img: "resources/customisation/character_hairs/character_hairs1.png"}, hair_2: { name: "hair_2", img: "resources/customisation/character_hairs/character_hairs1.png" },
"hair_3": {name:"hair_3", img: "resources/customisation/character_hairs/character_hairs2.png"}, hair_3: { name: "hair_3", img: "resources/customisation/character_hairs/character_hairs2.png" },
"hair_4": {name:"hair_4", img: "resources/customisation/character_hairs/character_hairs3.png"}, hair_4: { name: "hair_4", img: "resources/customisation/character_hairs/character_hairs3.png" },
"hair_5": {name:"hair_5", img: "resources/customisation/character_hairs/character_hairs4.png"}, hair_5: { name: "hair_5", img: "resources/customisation/character_hairs/character_hairs4.png" },
"hair_6": {name:"hair_6", img: "resources/customisation/character_hairs/character_hairs5.png"}, hair_6: { name: "hair_6", img: "resources/customisation/character_hairs/character_hairs5.png" },
"hair_7": {name:"hair_7", img: "resources/customisation/character_hairs/character_hairs6.png"}, hair_7: { name: "hair_7", img: "resources/customisation/character_hairs/character_hairs6.png" },
"hair_8": {name:"hair_8", img: "resources/customisation/character_hairs/character_hairs7.png"}, hair_8: { name: "hair_8", img: "resources/customisation/character_hairs/character_hairs7.png" },
"hair_9": {name:"hair_9", img: "resources/customisation/character_hairs/character_hairs8.png"}, hair_9: { name: "hair_9", img: "resources/customisation/character_hairs/character_hairs8.png" },
"hair_10": {name:"hair_10",img: "resources/customisation/character_hairs/character_hairs9.png"}, hair_10: { name: "hair_10", img: "resources/customisation/character_hairs/character_hairs9.png" },
"hair_11": {name:"hair_11",img: "resources/customisation/character_hairs/character_hairs10.png"}, hair_11: { name: "hair_11", img: "resources/customisation/character_hairs/character_hairs10.png" },
"hair_12": {name:"hair_12",img: "resources/customisation/character_hairs/character_hairs11.png"}, hair_12: { name: "hair_12", img: "resources/customisation/character_hairs/character_hairs11.png" },
"hair_13": {name:"hair_13",img: "resources/customisation/character_hairs/character_hairs12.png"}, hair_13: { name: "hair_13", img: "resources/customisation/character_hairs/character_hairs12.png" },
"hair_14": {name:"hair_14",img: "resources/customisation/character_hairs/character_hairs13.png"}, hair_14: { name: "hair_14", img: "resources/customisation/character_hairs/character_hairs13.png" },
"hair_15": {name:"hair_15",img: "resources/customisation/character_hairs/character_hairs14.png"}, hair_15: { name: "hair_15", img: "resources/customisation/character_hairs/character_hairs14.png" },
"hair_16": {name:"hair_16",img: "resources/customisation/character_hairs/character_hairs15.png"}, hair_16: { name: "hair_16", img: "resources/customisation/character_hairs/character_hairs15.png" },
"hair_17": {name:"hair_17",img: "resources/customisation/character_hairs/character_hairs16.png"}, hair_17: { name: "hair_17", img: "resources/customisation/character_hairs/character_hairs16.png" },
"hair_18": {name:"hair_18",img: "resources/customisation/character_hairs/character_hairs17.png"}, hair_18: { name: "hair_18", img: "resources/customisation/character_hairs/character_hairs17.png" },
"hair_19": {name:"hair_19",img: "resources/customisation/character_hairs/character_hairs18.png"}, hair_19: { name: "hair_19", img: "resources/customisation/character_hairs/character_hairs18.png" },
"hair_20": {name:"hair_20",img: "resources/customisation/character_hairs/character_hairs19.png"}, hair_20: { name: "hair_20", img: "resources/customisation/character_hairs/character_hairs19.png" },
"hair_21": {name:"hair_21",img: "resources/customisation/character_hairs/character_hairs20.png"}, hair_21: { name: "hair_21", img: "resources/customisation/character_hairs/character_hairs20.png" },
"hair_22": {name:"hair_22",img: "resources/customisation/character_hairs/character_hairs21.png"}, hair_22: { name: "hair_22", img: "resources/customisation/character_hairs/character_hairs21.png" },
"hair_23": {name:"hair_23",img: "resources/customisation/character_hairs/character_hairs22.png"}, hair_23: { name: "hair_23", img: "resources/customisation/character_hairs/character_hairs22.png" },
"hair_24": {name:"hair_24",img: "resources/customisation/character_hairs/character_hairs23.png"}, hair_24: { name: "hair_24", img: "resources/customisation/character_hairs/character_hairs23.png" },
"hair_25": {name:"hair_25",img: "resources/customisation/character_hairs/character_hairs24.png"}, hair_25: { name: "hair_25", img: "resources/customisation/character_hairs/character_hairs24.png" },
"hair_26": {name:"hair_26",img: "resources/customisation/character_hairs/character_hairs25.png"}, hair_26: { name: "hair_26", img: "resources/customisation/character_hairs/character_hairs25.png" },
"hair_27": {name:"hair_27",img: "resources/customisation/character_hairs/character_hairs26.png"}, hair_27: { name: "hair_27", img: "resources/customisation/character_hairs/character_hairs26.png" },
"hair_28": {name:"hair_28",img: "resources/customisation/character_hairs/character_hairs27.png"}, hair_28: { name: "hair_28", img: "resources/customisation/character_hairs/character_hairs27.png" },
"hair_29": {name:"hair_29",img: "resources/customisation/character_hairs/character_hairs28.png"}, hair_29: { name: "hair_29", img: "resources/customisation/character_hairs/character_hairs28.png" },
"hair_30": {name:"hair_30",img: "resources/customisation/character_hairs/character_hairs29.png"}, hair_30: { name: "hair_30", img: "resources/customisation/character_hairs/character_hairs29.png" },
"hair_31": {name:"hair_31",img: "resources/customisation/character_hairs/character_hairs30.png"}, hair_31: { name: "hair_31", img: "resources/customisation/character_hairs/character_hairs30.png" },
"hair_32": {name:"hair_32",img: "resources/customisation/character_hairs/character_hairs31.png"}, hair_32: { name: "hair_32", img: "resources/customisation/character_hairs/character_hairs31.png" },
"hair_33": {name:"hair_33",img: "resources/customisation/character_hairs/character_hairs32.png"}, hair_33: { name: "hair_33", img: "resources/customisation/character_hairs/character_hairs32.png" },
"hair_34": {name:"hair_34",img: "resources/customisation/character_hairs/character_hairs33.png"}, hair_34: { name: "hair_34", img: "resources/customisation/character_hairs/character_hairs33.png" },
"hair_35": {name:"hair_35",img: "resources/customisation/character_hairs/character_hairs34.png"}, hair_35: { name: "hair_35", img: "resources/customisation/character_hairs/character_hairs34.png" },
"hair_36": {name:"hair_36",img: "resources/customisation/character_hairs/character_hairs35.png"}, hair_36: { name: "hair_36", img: "resources/customisation/character_hairs/character_hairs35.png" },
"hair_37": {name:"hair_37",img: "resources/customisation/character_hairs/character_hairs36.png"}, hair_37: { name: "hair_37", img: "resources/customisation/character_hairs/character_hairs36.png" },
"hair_38": {name:"hair_38",img: "resources/customisation/character_hairs/character_hairs37.png"}, hair_38: { name: "hair_38", img: "resources/customisation/character_hairs/character_hairs37.png" },
"hair_39": {name:"hair_39",img: "resources/customisation/character_hairs/character_hairs38.png"}, hair_39: { name: "hair_39", img: "resources/customisation/character_hairs/character_hairs38.png" },
"hair_40": {name:"hair_40",img: "resources/customisation/character_hairs/character_hairs39.png"}, hair_40: { name: "hair_40", img: "resources/customisation/character_hairs/character_hairs39.png" },
"hair_41": {name:"hair_41",img: "resources/customisation/character_hairs/character_hairs40.png"}, hair_41: { name: "hair_41", img: "resources/customisation/character_hairs/character_hairs40.png" },
"hair_42": {name:"hair_42",img: "resources/customisation/character_hairs/character_hairs41.png"}, hair_42: { name: "hair_42", img: "resources/customisation/character_hairs/character_hairs41.png" },
"hair_43": {name:"hair_43",img: "resources/customisation/character_hairs/character_hairs42.png"}, hair_43: { name: "hair_43", img: "resources/customisation/character_hairs/character_hairs42.png" },
"hair_44": {name:"hair_44",img: "resources/customisation/character_hairs/character_hairs43.png"}, hair_44: { name: "hair_44", img: "resources/customisation/character_hairs/character_hairs43.png" },
"hair_45": {name:"hair_45",img: "resources/customisation/character_hairs/character_hairs44.png"}, hair_45: { name: "hair_45", img: "resources/customisation/character_hairs/character_hairs44.png" },
"hair_46": {name:"hair_46",img: "resources/customisation/character_hairs/character_hairs45.png"}, hair_46: { name: "hair_46", img: "resources/customisation/character_hairs/character_hairs45.png" },
"hair_47": {name:"hair_47",img: "resources/customisation/character_hairs/character_hairs46.png"}, hair_47: { name: "hair_47", img: "resources/customisation/character_hairs/character_hairs46.png" },
"hair_48": {name:"hair_48",img: "resources/customisation/character_hairs/character_hairs47.png"}, hair_48: { name: "hair_48", img: "resources/customisation/character_hairs/character_hairs47.png" },
"hair_49": {name:"hair_49",img: "resources/customisation/character_hairs/character_hairs48.png"}, hair_49: { name: "hair_49", img: "resources/customisation/character_hairs/character_hairs48.png" },
"hair_50": {name:"hair_50",img: "resources/customisation/character_hairs/character_hairs49.png"}, hair_50: { name: "hair_50", img: "resources/customisation/character_hairs/character_hairs49.png" },
"hair_51": {name:"hair_51",img: "resources/customisation/character_hairs/character_hairs50.png"}, hair_51: { name: "hair_51", img: "resources/customisation/character_hairs/character_hairs50.png" },
"hair_52": {name:"hair_52",img: "resources/customisation/character_hairs/character_hairs51.png"}, hair_52: { name: "hair_52", img: "resources/customisation/character_hairs/character_hairs51.png" },
"hair_53": {name:"hair_53",img: "resources/customisation/character_hairs/character_hairs52.png"}, hair_53: { name: "hair_53", img: "resources/customisation/character_hairs/character_hairs52.png" },
"hair_54": {name:"hair_54",img: "resources/customisation/character_hairs/character_hairs53.png"}, hair_54: { name: "hair_54", img: "resources/customisation/character_hairs/character_hairs53.png" },
"hair_55": {name:"hair_55",img: "resources/customisation/character_hairs/character_hairs54.png"}, hair_55: { name: "hair_55", img: "resources/customisation/character_hairs/character_hairs54.png" },
"hair_56": {name:"hair_56",img: "resources/customisation/character_hairs/character_hairs55.png"}, hair_56: { name: "hair_56", img: "resources/customisation/character_hairs/character_hairs55.png" },
"hair_57": {name:"hair_57",img: "resources/customisation/character_hairs/character_hairs56.png"}, hair_57: { name: "hair_57", img: "resources/customisation/character_hairs/character_hairs56.png" },
"hair_58": {name:"hair_58",img: "resources/customisation/character_hairs/character_hairs57.png"}, hair_58: { name: "hair_58", img: "resources/customisation/character_hairs/character_hairs57.png" },
"hair_59": {name:"hair_59",img: "resources/customisation/character_hairs/character_hairs58.png"}, hair_59: { name: "hair_59", img: "resources/customisation/character_hairs/character_hairs58.png" },
"hair_60": {name:"hair_60",img: "resources/customisation/character_hairs/character_hairs59.png"}, hair_60: { name: "hair_60", img: "resources/customisation/character_hairs/character_hairs59.png" },
"hair_61": {name:"hair_61",img: "resources/customisation/character_hairs/character_hairs60.png"}, hair_61: { name: "hair_61", img: "resources/customisation/character_hairs/character_hairs60.png" },
"hair_62": {name:"hair_62",img: "resources/customisation/character_hairs/character_hairs61.png"}, hair_62: { name: "hair_62", img: "resources/customisation/character_hairs/character_hairs61.png" },
"hair_63": {name:"hair_63",img: "resources/customisation/character_hairs/character_hairs62.png"}, hair_63: { name: "hair_63", img: "resources/customisation/character_hairs/character_hairs62.png" },
"hair_64": {name:"hair_64",img: "resources/customisation/character_hairs/character_hairs63.png"}, hair_64: { name: "hair_64", img: "resources/customisation/character_hairs/character_hairs63.png" },
"hair_65": {name:"hair_65",img: "resources/customisation/character_hairs/character_hairs64.png"}, hair_65: { name: "hair_65", img: "resources/customisation/character_hairs/character_hairs64.png" },
"hair_66": {name:"hair_66",img: "resources/customisation/character_hairs/character_hairs65.png"}, hair_66: { name: "hair_66", img: "resources/customisation/character_hairs/character_hairs65.png" },
"hair_67": {name:"hair_67",img: "resources/customisation/character_hairs/character_hairs66.png"}, hair_67: { name: "hair_67", img: "resources/customisation/character_hairs/character_hairs66.png" },
"hair_68": {name:"hair_68",img: "resources/customisation/character_hairs/character_hairs67.png"}, hair_68: { name: "hair_68", img: "resources/customisation/character_hairs/character_hairs67.png" },
"hair_69": {name:"hair_69",img: "resources/customisation/character_hairs/character_hairs68.png"}, hair_69: { name: "hair_69", img: "resources/customisation/character_hairs/character_hairs68.png" },
"hair_70": {name:"hair_70",img: "resources/customisation/character_hairs/character_hairs69.png"}, hair_70: { name: "hair_70", img: "resources/customisation/character_hairs/character_hairs69.png" },
"hair_71": {name:"hair_71",img: "resources/customisation/character_hairs/character_hairs70.png"}, hair_71: { name: "hair_71", img: "resources/customisation/character_hairs/character_hairs70.png" },
"hair_72": {name:"hair_72",img: "resources/customisation/character_hairs/character_hairs71.png"}, hair_72: { name: "hair_72", img: "resources/customisation/character_hairs/character_hairs71.png" },
"hair_73": {name:"hair_73",img: "resources/customisation/character_hairs/character_hairs72.png"}, hair_73: { name: "hair_73", img: "resources/customisation/character_hairs/character_hairs72.png" },
"hair_74": {name:"hair_74",img: "resources/customisation/character_hairs/character_hairs73.png"}, hair_74: { name: "hair_74", img: "resources/customisation/character_hairs/character_hairs73.png" },
"hair_75": {name:"hair_75",img: "resources/customisation/character_hairs/character_hairs74.png"} hair_75: { name: "hair_75", img: "resources/customisation/character_hairs/character_hairs74.png" }
}; };
export const CLOTHES_RESOURCES: BodyResourceDescriptionListInterface = { export const CLOTHES_RESOURCES: BodyResourceDescriptionListInterface = {
"clothes_1": {name:"clothes_1", img: "resources/customisation/character_clothes/character_clothes0.png"}, clothes_1: { name: "clothes_1", img: "resources/customisation/character_clothes/character_clothes0.png" },
"clothes_2": {name:"clothes_2", img: "resources/customisation/character_clothes/character_clothes1.png"}, clothes_2: { name: "clothes_2", img: "resources/customisation/character_clothes/character_clothes1.png" },
"clothes_3": {name:"clothes_3", img: "resources/customisation/character_clothes/character_clothes2.png"}, clothes_3: { name: "clothes_3", img: "resources/customisation/character_clothes/character_clothes2.png" },
"clothes_4": {name:"clothes_4", img: "resources/customisation/character_clothes/character_clothes3.png"}, clothes_4: { name: "clothes_4", img: "resources/customisation/character_clothes/character_clothes3.png" },
"clothes_5": {name:"clothes_5", img: "resources/customisation/character_clothes/character_clothes4.png"}, clothes_5: { name: "clothes_5", img: "resources/customisation/character_clothes/character_clothes4.png" },
"clothes_6": {name:"clothes_6", img: "resources/customisation/character_clothes/character_clothes5.png"}, clothes_6: { name: "clothes_6", img: "resources/customisation/character_clothes/character_clothes5.png" },
"clothes_7": {name:"clothes_7", img: "resources/customisation/character_clothes/character_clothes6.png"}, clothes_7: { name: "clothes_7", img: "resources/customisation/character_clothes/character_clothes6.png" },
"clothes_8": {name:"clothes_8", img: "resources/customisation/character_clothes/character_clothes7.png"}, clothes_8: { name: "clothes_8", img: "resources/customisation/character_clothes/character_clothes7.png" },
"clothes_9": {name:"clothes_9", img: "resources/customisation/character_clothes/character_clothes8.png"}, clothes_9: { name: "clothes_9", img: "resources/customisation/character_clothes/character_clothes8.png" },
"clothes_10": {name:"clothes_10",img: "resources/customisation/character_clothes/character_clothes9.png"}, clothes_10: { name: "clothes_10", img: "resources/customisation/character_clothes/character_clothes9.png" },
"clothes_11": {name:"clothes_11",img: "resources/customisation/character_clothes/character_clothes10.png"}, clothes_11: { name: "clothes_11", img: "resources/customisation/character_clothes/character_clothes10.png" },
"clothes_12": {name:"clothes_12",img: "resources/customisation/character_clothes/character_clothes11.png"}, clothes_12: { name: "clothes_12", img: "resources/customisation/character_clothes/character_clothes11.png" },
"clothes_13": {name:"clothes_13",img: "resources/customisation/character_clothes/character_clothes12.png"}, clothes_13: { name: "clothes_13", img: "resources/customisation/character_clothes/character_clothes12.png" },
"clothes_14": {name:"clothes_14",img: "resources/customisation/character_clothes/character_clothes13.png"}, clothes_14: { name: "clothes_14", img: "resources/customisation/character_clothes/character_clothes13.png" },
"clothes_15": {name:"clothes_15",img: "resources/customisation/character_clothes/character_clothes14.png"}, clothes_15: { name: "clothes_15", img: "resources/customisation/character_clothes/character_clothes14.png" },
"clothes_16": {name:"clothes_16",img: "resources/customisation/character_clothes/character_clothes15.png"}, clothes_16: { name: "clothes_16", img: "resources/customisation/character_clothes/character_clothes15.png" },
"clothes_17": {name:"clothes_17",img: "resources/customisation/character_clothes/character_clothes16.png"}, clothes_17: { name: "clothes_17", img: "resources/customisation/character_clothes/character_clothes16.png" },
"clothes_18": {name:"clothes_18",img: "resources/customisation/character_clothes/character_clothes17.png"}, clothes_18: { name: "clothes_18", img: "resources/customisation/character_clothes/character_clothes17.png" },
"clothes_19": {name:"clothes_19",img: "resources/customisation/character_clothes/character_clothes18.png"}, clothes_19: { name: "clothes_19", img: "resources/customisation/character_clothes/character_clothes18.png" },
"clothes_20": {name:"clothes_20",img: "resources/customisation/character_clothes/character_clothes19.png"}, clothes_20: { name: "clothes_20", img: "resources/customisation/character_clothes/character_clothes19.png" },
"clothes_21": {name:"clothes_21",img: "resources/customisation/character_clothes/character_clothes20.png"}, clothes_21: { name: "clothes_21", img: "resources/customisation/character_clothes/character_clothes20.png" },
"clothes_22": {name:"clothes_22",img: "resources/customisation/character_clothes/character_clothes21.png"}, clothes_22: { name: "clothes_22", img: "resources/customisation/character_clothes/character_clothes21.png" },
"clothes_23": {name:"clothes_23",img: "resources/customisation/character_clothes/character_clothes22.png"}, clothes_23: { name: "clothes_23", img: "resources/customisation/character_clothes/character_clothes22.png" },
"clothes_24": {name:"clothes_24",img: "resources/customisation/character_clothes/character_clothes23.png"}, clothes_24: { name: "clothes_24", img: "resources/customisation/character_clothes/character_clothes23.png" },
"clothes_25": {name:"clothes_25",img: "resources/customisation/character_clothes/character_clothes24.png"}, clothes_25: { name: "clothes_25", img: "resources/customisation/character_clothes/character_clothes24.png" },
"clothes_26": {name:"clothes_26",img: "resources/customisation/character_clothes/character_clothes25.png"}, clothes_26: { name: "clothes_26", img: "resources/customisation/character_clothes/character_clothes25.png" },
"clothes_27": {name:"clothes_27",img: "resources/customisation/character_clothes/character_clothes26.png"}, clothes_27: { name: "clothes_27", img: "resources/customisation/character_clothes/character_clothes26.png" },
"clothes_28": {name:"clothes_28",img: "resources/customisation/character_clothes/character_clothes27.png"}, clothes_28: { name: "clothes_28", img: "resources/customisation/character_clothes/character_clothes27.png" },
"clothes_29": {name:"clothes_29",img: "resources/customisation/character_clothes/character_clothes28.png"}, clothes_29: { name: "clothes_29", img: "resources/customisation/character_clothes/character_clothes28.png" },
"clothes_30": {name:"clothes_30",img: "resources/customisation/character_clothes/character_clothes29.png"}, clothes_30: { name: "clothes_30", img: "resources/customisation/character_clothes/character_clothes29.png" },
"clothes_31": {name:"clothes_31",img: "resources/customisation/character_clothes/character_clothes30.png"}, clothes_31: { name: "clothes_31", img: "resources/customisation/character_clothes/character_clothes30.png" },
"clothes_32": {name:"clothes_32",img: "resources/customisation/character_clothes/character_clothes31.png"}, clothes_32: { name: "clothes_32", img: "resources/customisation/character_clothes/character_clothes31.png" },
"clothes_33": {name:"clothes_33",img: "resources/customisation/character_clothes/character_clothes32.png"}, clothes_33: { name: "clothes_33", img: "resources/customisation/character_clothes/character_clothes32.png" },
"clothes_34": {name:"clothes_34",img: "resources/customisation/character_clothes/character_clothes33.png"}, clothes_34: { name: "clothes_34", img: "resources/customisation/character_clothes/character_clothes33.png" },
"clothes_35": {name:"clothes_35",img: "resources/customisation/character_clothes/character_clothes34.png"}, clothes_35: { name: "clothes_35", img: "resources/customisation/character_clothes/character_clothes34.png" },
"clothes_36": {name:"clothes_36",img: "resources/customisation/character_clothes/character_clothes35.png"}, clothes_36: { name: "clothes_36", img: "resources/customisation/character_clothes/character_clothes35.png" },
"clothes_37": {name:"clothes_37",img: "resources/customisation/character_clothes/character_clothes36.png"}, clothes_37: { name: "clothes_37", img: "resources/customisation/character_clothes/character_clothes36.png" },
"clothes_38": {name:"clothes_38",img: "resources/customisation/character_clothes/character_clothes37.png"}, clothes_38: { name: "clothes_38", img: "resources/customisation/character_clothes/character_clothes37.png" },
"clothes_39": {name:"clothes_39",img: "resources/customisation/character_clothes/character_clothes38.png"}, clothes_39: { name: "clothes_39", img: "resources/customisation/character_clothes/character_clothes38.png" },
"clothes_40": {name:"clothes_40",img: "resources/customisation/character_clothes/character_clothes39.png"}, clothes_40: { name: "clothes_40", img: "resources/customisation/character_clothes/character_clothes39.png" },
"clothes_41": {name:"clothes_41",img: "resources/customisation/character_clothes/character_clothes40.png"}, clothes_41: { name: "clothes_41", img: "resources/customisation/character_clothes/character_clothes40.png" },
"clothes_42": {name:"clothes_42",img: "resources/customisation/character_clothes/character_clothes41.png"}, clothes_42: { name: "clothes_42", img: "resources/customisation/character_clothes/character_clothes41.png" },
"clothes_43": {name:"clothes_43",img: "resources/customisation/character_clothes/character_clothes42.png"}, clothes_43: { name: "clothes_43", img: "resources/customisation/character_clothes/character_clothes42.png" },
"clothes_44": {name:"clothes_44",img: "resources/customisation/character_clothes/character_clothes43.png"}, clothes_44: { name: "clothes_44", img: "resources/customisation/character_clothes/character_clothes43.png" },
"clothes_45": {name:"clothes_45",img: "resources/customisation/character_clothes/character_clothes44.png"}, clothes_45: { name: "clothes_45", img: "resources/customisation/character_clothes/character_clothes44.png" },
"clothes_46": {name:"clothes_46",img: "resources/customisation/character_clothes/character_clothes45.png"}, clothes_46: { name: "clothes_46", img: "resources/customisation/character_clothes/character_clothes45.png" },
"clothes_47": {name:"clothes_47",img: "resources/customisation/character_clothes/character_clothes46.png"}, clothes_47: { name: "clothes_47", img: "resources/customisation/character_clothes/character_clothes46.png" },
"clothes_48": {name:"clothes_48",img: "resources/customisation/character_clothes/character_clothes47.png"}, clothes_48: { name: "clothes_48", img: "resources/customisation/character_clothes/character_clothes47.png" },
"clothes_49": {name:"clothes_49",img: "resources/customisation/character_clothes/character_clothes48.png"}, clothes_49: { name: "clothes_49", img: "resources/customisation/character_clothes/character_clothes48.png" },
"clothes_50": {name:"clothes_50",img: "resources/customisation/character_clothes/character_clothes49.png"}, clothes_50: { name: "clothes_50", img: "resources/customisation/character_clothes/character_clothes49.png" },
"clothes_51": {name:"clothes_51",img: "resources/customisation/character_clothes/character_clothes50.png"}, clothes_51: { name: "clothes_51", img: "resources/customisation/character_clothes/character_clothes50.png" },
"clothes_52": {name:"clothes_52",img: "resources/customisation/character_clothes/character_clothes51.png"}, clothes_52: { name: "clothes_52", img: "resources/customisation/character_clothes/character_clothes51.png" },
"clothes_53": {name:"clothes_53",img: "resources/customisation/character_clothes/character_clothes52.png"}, clothes_53: { name: "clothes_53", img: "resources/customisation/character_clothes/character_clothes52.png" },
"clothes_54": {name:"clothes_54",img: "resources/customisation/character_clothes/character_clothes53.png"}, clothes_54: { name: "clothes_54", img: "resources/customisation/character_clothes/character_clothes53.png" },
"clothes_55": {name:"clothes_55",img: "resources/customisation/character_clothes/character_clothes54.png"}, clothes_55: { name: "clothes_55", img: "resources/customisation/character_clothes/character_clothes54.png" },
"clothes_56": {name:"clothes_56",img: "resources/customisation/character_clothes/character_clothes55.png"}, clothes_56: { name: "clothes_56", img: "resources/customisation/character_clothes/character_clothes55.png" },
"clothes_57": {name:"clothes_57",img: "resources/customisation/character_clothes/character_clothes56.png"}, clothes_57: { name: "clothes_57", img: "resources/customisation/character_clothes/character_clothes56.png" },
"clothes_58": {name:"clothes_58",img: "resources/customisation/character_clothes/character_clothes57.png"}, clothes_58: { name: "clothes_58", img: "resources/customisation/character_clothes/character_clothes57.png" },
"clothes_59": {name:"clothes_59",img: "resources/customisation/character_clothes/character_clothes58.png"}, clothes_59: { name: "clothes_59", img: "resources/customisation/character_clothes/character_clothes58.png" },
"clothes_60": {name:"clothes_60",img: "resources/customisation/character_clothes/character_clothes59.png"}, clothes_60: { name: "clothes_60", img: "resources/customisation/character_clothes/character_clothes59.png" },
"clothes_61": {name:"clothes_61",img: "resources/customisation/character_clothes/character_clothes60.png"}, clothes_61: { name: "clothes_61", img: "resources/customisation/character_clothes/character_clothes60.png" },
"clothes_62": {name:"clothes_62",img: "resources/customisation/character_clothes/character_clothes61.png"}, clothes_62: { name: "clothes_62", img: "resources/customisation/character_clothes/character_clothes61.png" },
"clothes_63": {name:"clothes_63",img: "resources/customisation/character_clothes/character_clothes62.png"}, clothes_63: { name: "clothes_63", img: "resources/customisation/character_clothes/character_clothes62.png" },
"clothes_64": {name:"clothes_64",img: "resources/customisation/character_clothes/character_clothes63.png"}, clothes_64: { name: "clothes_64", img: "resources/customisation/character_clothes/character_clothes63.png" },
"clothes_65": {name:"clothes_65",img: "resources/customisation/character_clothes/character_clothes64.png"}, clothes_65: { name: "clothes_65", img: "resources/customisation/character_clothes/character_clothes64.png" },
"clothes_66": {name:"clothes_66",img: "resources/customisation/character_clothes/character_clothes65.png"}, clothes_66: { name: "clothes_66", img: "resources/customisation/character_clothes/character_clothes65.png" },
"clothes_67": {name:"clothes_67",img: "resources/customisation/character_clothes/character_clothes66.png"}, clothes_67: { name: "clothes_67", img: "resources/customisation/character_clothes/character_clothes66.png" },
"clothes_68": {name:"clothes_68",img: "resources/customisation/character_clothes/character_clothes67.png"}, clothes_68: { name: "clothes_68", img: "resources/customisation/character_clothes/character_clothes67.png" },
"clothes_69": {name:"clothes_69",img: "resources/customisation/character_clothes/character_clothes68.png"}, clothes_69: { name: "clothes_69", img: "resources/customisation/character_clothes/character_clothes68.png" },
"clothes_70": {name:"clothes_70",img: "resources/customisation/character_clothes/character_clothes69.png"}, clothes_70: { name: "clothes_70", img: "resources/customisation/character_clothes/character_clothes69.png" },
"clothes_pride_shirt": {name:"clothes_pride_shirt",img: "resources/customisation/character_clothes/pride_shirt.png"}, clothes_pride_shirt: {
"clothes_black_hoodie": {name:"clothes_black_hoodie",img: "resources/customisation/character_clothes/black_hoodie.png"}, name: "clothes_pride_shirt",
"clothes_white_hoodie": {name:"clothes_white_hoodie",img: "resources/customisation/character_clothes/white_hoodie.png"}, img: "resources/customisation/character_clothes/pride_shirt.png",
"clothes_engelbert": {name:"clothes_engelbert",img: "resources/customisation/character_clothes/engelbert.png"} },
clothes_black_hoodie: {
name: "clothes_black_hoodie",
img: "resources/customisation/character_clothes/black_hoodie.png",
},
clothes_white_hoodie: {
name: "clothes_white_hoodie",
img: "resources/customisation/character_clothes/white_hoodie.png",
},
clothes_engelbert: { name: "clothes_engelbert", img: "resources/customisation/character_clothes/engelbert.png" },
}; };
export const HATS_RESOURCES: BodyResourceDescriptionListInterface = { export const HATS_RESOURCES: BodyResourceDescriptionListInterface = {
"hats_1": {name: "hats_1", img: "resources/customisation/character_hats/character_hats1.png"}, hats_1: { name: "hats_1", img: "resources/customisation/character_hats/character_hats1.png" },
"hats_2": {name: "hats_2", img: "resources/customisation/character_hats/character_hats2.png"}, hats_2: { name: "hats_2", img: "resources/customisation/character_hats/character_hats2.png" },
"hats_3": {name: "hats_3", img: "resources/customisation/character_hats/character_hats3.png"}, hats_3: { name: "hats_3", img: "resources/customisation/character_hats/character_hats3.png" },
"hats_4": {name: "hats_4", img: "resources/customisation/character_hats/character_hats4.png"}, hats_4: { name: "hats_4", img: "resources/customisation/character_hats/character_hats4.png" },
"hats_5": {name: "hats_5", img: "resources/customisation/character_hats/character_hats5.png"}, hats_5: { name: "hats_5", img: "resources/customisation/character_hats/character_hats5.png" },
"hats_6": {name: "hats_6", img: "resources/customisation/character_hats/character_hats6.png"}, hats_6: { name: "hats_6", img: "resources/customisation/character_hats/character_hats6.png" },
"hats_7": {name: "hats_7", img: "resources/customisation/character_hats/character_hats7.png"}, hats_7: { name: "hats_7", img: "resources/customisation/character_hats/character_hats7.png" },
"hats_8": {name: "hats_8", img: "resources/customisation/character_hats/character_hats8.png"}, hats_8: { name: "hats_8", img: "resources/customisation/character_hats/character_hats8.png" },
"hats_9": {name: "hats_9", img: "resources/customisation/character_hats/character_hats9.png"}, hats_9: { name: "hats_9", img: "resources/customisation/character_hats/character_hats9.png" },
"hats_10": {name: "hats_10", img: "resources/customisation/character_hats/character_hats10.png"}, hats_10: { name: "hats_10", img: "resources/customisation/character_hats/character_hats10.png" },
"hats_11": {name: "hats_11", img: "resources/customisation/character_hats/character_hats11.png"}, hats_11: { name: "hats_11", img: "resources/customisation/character_hats/character_hats11.png" },
"hats_12": {name: "hats_12", img: "resources/customisation/character_hats/character_hats12.png"}, hats_12: { name: "hats_12", img: "resources/customisation/character_hats/character_hats12.png" },
"hats_13": {name: "hats_13", img: "resources/customisation/character_hats/character_hats13.png"}, hats_13: { name: "hats_13", img: "resources/customisation/character_hats/character_hats13.png" },
"hats_14": {name: "hats_14", img: "resources/customisation/character_hats/character_hats14.png"}, hats_14: { name: "hats_14", img: "resources/customisation/character_hats/character_hats14.png" },
"hats_15": {name: "hats_15", img: "resources/customisation/character_hats/character_hats15.png"}, hats_15: { name: "hats_15", img: "resources/customisation/character_hats/character_hats15.png" },
"hats_16": {name: "hats_16", img: "resources/customisation/character_hats/character_hats16.png"}, hats_16: { name: "hats_16", img: "resources/customisation/character_hats/character_hats16.png" },
"hats_17": {name: "hats_17", img: "resources/customisation/character_hats/character_hats17.png"}, hats_17: { name: "hats_17", img: "resources/customisation/character_hats/character_hats17.png" },
"hats_18": {name: "hats_18", img: "resources/customisation/character_hats/character_hats18.png"}, hats_18: { name: "hats_18", img: "resources/customisation/character_hats/character_hats18.png" },
"hats_19": {name: "hats_19", img: "resources/customisation/character_hats/character_hats19.png"}, hats_19: { name: "hats_19", img: "resources/customisation/character_hats/character_hats19.png" },
"hats_20": {name: "hats_20", img: "resources/customisation/character_hats/character_hats20.png"}, hats_20: { name: "hats_20", img: "resources/customisation/character_hats/character_hats20.png" },
"hats_21": {name: "hats_21", img: "resources/customisation/character_hats/character_hats21.png"}, hats_21: { name: "hats_21", img: "resources/customisation/character_hats/character_hats21.png" },
"hats_22": {name: "hats_22", img: "resources/customisation/character_hats/character_hats22.png"}, hats_22: { name: "hats_22", img: "resources/customisation/character_hats/character_hats22.png" },
"hats_23": {name: "hats_23", img: "resources/customisation/character_hats/character_hats23.png"}, hats_23: { name: "hats_23", img: "resources/customisation/character_hats/character_hats23.png" },
"hats_24": {name: "hats_24", img: "resources/customisation/character_hats/character_hats24.png"}, hats_24: { name: "hats_24", img: "resources/customisation/character_hats/character_hats24.png" },
"hats_25": {name: "hats_25", img: "resources/customisation/character_hats/character_hats25.png"}, hats_25: { name: "hats_25", img: "resources/customisation/character_hats/character_hats25.png" },
"hats_26": {name: "hats_26", img: "resources/customisation/character_hats/character_hats26.png"}, hats_26: { name: "hats_26", img: "resources/customisation/character_hats/character_hats26.png" },
"tinfoil_hat1": {name: "tinfoil_hat1", img: "resources/customisation/character_hats/tinfoil_hat1.png"} tinfoil_hat1: { name: "tinfoil_hat1", img: "resources/customisation/character_hats/tinfoil_hat1.png" },
}; };
export const ACCESSORIES_RESOURCES: BodyResourceDescriptionListInterface = { export const ACCESSORIES_RESOURCES: BodyResourceDescriptionListInterface = {
"accessory_1": {name: "accessory_1", img: "resources/customisation/character_accessories/character_accessories1.png"}, accessory_1: {
"accessory_2": {name: "accessory_2", img: "resources/customisation/character_accessories/character_accessories2.png"}, name: "accessory_1",
"accessory_3": {name: "accessory_3", img: "resources/customisation/character_accessories/character_accessories3.png"}, img: "resources/customisation/character_accessories/character_accessories1.png",
"accessory_4": {name: "accessory_4", img: "resources/customisation/character_accessories/character_accessories4.png"}, },
"accessory_5": {name: "accessory_5", img: "resources/customisation/character_accessories/character_accessories5.png"}, accessory_2: {
"accessory_6": {name: "accessory_6", img: "resources/customisation/character_accessories/character_accessories6.png"}, name: "accessory_2",
"accessory_7": {name: "accessory_7", img: "resources/customisation/character_accessories/character_accessories7.png"}, img: "resources/customisation/character_accessories/character_accessories2.png",
"accessory_8": {name: "accessory_8", img: "resources/customisation/character_accessories/character_accessories8.png"}, },
"accessory_9": {name: "accessory_9", img: "resources/customisation/character_accessories/character_accessories9.png"}, accessory_3: {
"accessory_10": {name: "accessory_10", img: "resources/customisation/character_accessories/character_accessories10.png"}, name: "accessory_3",
"accessory_11": {name: "accessory_11", img: "resources/customisation/character_accessories/character_accessories11.png"}, img: "resources/customisation/character_accessories/character_accessories3.png",
"accessory_12": {name: "accessory_12", img: "resources/customisation/character_accessories/character_accessories12.png"}, },
"accessory_13": {name: "accessory_13", img: "resources/customisation/character_accessories/character_accessories13.png"}, accessory_4: {
"accessory_14": {name: "accessory_14", img: "resources/customisation/character_accessories/character_accessories14.png"}, name: "accessory_4",
"accessory_15": {name: "accessory_15", img: "resources/customisation/character_accessories/character_accessories15.png"}, img: "resources/customisation/character_accessories/character_accessories4.png",
"accessory_16": {name: "accessory_16", img: "resources/customisation/character_accessories/character_accessories16.png"}, },
"accessory_17": {name: "accessory_17", img: "resources/customisation/character_accessories/character_accessories17.png"}, accessory_5: {
"accessory_18": {name: "accessory_18", img: "resources/customisation/character_accessories/character_accessories18.png"}, name: "accessory_5",
"accessory_19": {name: "accessory_19", img: "resources/customisation/character_accessories/character_accessories19.png"}, img: "resources/customisation/character_accessories/character_accessories5.png",
"accessory_20": {name: "accessory_20", img: "resources/customisation/character_accessories/character_accessories20.png"}, },
"accessory_21": {name: "accessory_21", img: "resources/customisation/character_accessories/character_accessories21.png"}, accessory_6: {
"accessory_22": {name: "accessory_22", img: "resources/customisation/character_accessories/character_accessories22.png"}, name: "accessory_6",
"accessory_23": {name: "accessory_23", img: "resources/customisation/character_accessories/character_accessories23.png"}, img: "resources/customisation/character_accessories/character_accessories6.png",
"accessory_24": {name: "accessory_24", img: "resources/customisation/character_accessories/character_accessories24.png"}, },
"accessory_25": {name: "accessory_25", img: "resources/customisation/character_accessories/character_accessories25.png"}, accessory_7: {
"accessory_26": {name: "accessory_26", img: "resources/customisation/character_accessories/character_accessories26.png"}, name: "accessory_7",
"accessory_27": {name: "accessory_27", img: "resources/customisation/character_accessories/character_accessories27.png"}, img: "resources/customisation/character_accessories/character_accessories7.png",
"accessory_28": {name: "accessory_28", img: "resources/customisation/character_accessories/character_accessories28.png"}, },
"accessory_29": {name: "accessory_29", img: "resources/customisation/character_accessories/character_accessories29.png"}, accessory_8: {
"accessory_30": {name: "accessory_30", img: "resources/customisation/character_accessories/character_accessories30.png"}, name: "accessory_8",
"accessory_31": {name: "accessory_31", img: "resources/customisation/character_accessories/character_accessories31.png"}, img: "resources/customisation/character_accessories/character_accessories8.png",
"accessory_32": {name: "accessory_32", img: "resources/customisation/character_accessories/character_accessories32.png"}, },
"accessory_mate_bottle": {name: "accessory_mate_bottle", img: "resources/customisation/character_accessories/mate_bottle1.png"}, accessory_9: {
"accessory_mask": {name: "accessory_mask", img: "resources/customisation/character_accessories/mask.png"} name: "accessory_9",
img: "resources/customisation/character_accessories/character_accessories9.png",
},
accessory_10: {
name: "accessory_10",
img: "resources/customisation/character_accessories/character_accessories10.png",
},
accessory_11: {
name: "accessory_11",
img: "resources/customisation/character_accessories/character_accessories11.png",
},
accessory_12: {
name: "accessory_12",
img: "resources/customisation/character_accessories/character_accessories12.png",
},
accessory_13: {
name: "accessory_13",
img: "resources/customisation/character_accessories/character_accessories13.png",
},
accessory_14: {
name: "accessory_14",
img: "resources/customisation/character_accessories/character_accessories14.png",
},
accessory_15: {
name: "accessory_15",
img: "resources/customisation/character_accessories/character_accessories15.png",
},
accessory_16: {
name: "accessory_16",
img: "resources/customisation/character_accessories/character_accessories16.png",
},
accessory_17: {
name: "accessory_17",
img: "resources/customisation/character_accessories/character_accessories17.png",
},
accessory_18: {
name: "accessory_18",
img: "resources/customisation/character_accessories/character_accessories18.png",
},
accessory_19: {
name: "accessory_19",
img: "resources/customisation/character_accessories/character_accessories19.png",
},
accessory_20: {
name: "accessory_20",
img: "resources/customisation/character_accessories/character_accessories20.png",
},
accessory_21: {
name: "accessory_21",
img: "resources/customisation/character_accessories/character_accessories21.png",
},
accessory_22: {
name: "accessory_22",
img: "resources/customisation/character_accessories/character_accessories22.png",
},
accessory_23: {
name: "accessory_23",
img: "resources/customisation/character_accessories/character_accessories23.png",
},
accessory_24: {
name: "accessory_24",
img: "resources/customisation/character_accessories/character_accessories24.png",
},
accessory_25: {
name: "accessory_25",
img: "resources/customisation/character_accessories/character_accessories25.png",
},
accessory_26: {
name: "accessory_26",
img: "resources/customisation/character_accessories/character_accessories26.png",
},
accessory_27: {
name: "accessory_27",
img: "resources/customisation/character_accessories/character_accessories27.png",
},
accessory_28: {
name: "accessory_28",
img: "resources/customisation/character_accessories/character_accessories28.png",
},
accessory_29: {
name: "accessory_29",
img: "resources/customisation/character_accessories/character_accessories29.png",
},
accessory_30: {
name: "accessory_30",
img: "resources/customisation/character_accessories/character_accessories30.png",
},
accessory_31: {
name: "accessory_31",
img: "resources/customisation/character_accessories/character_accessories31.png",
},
accessory_32: {
name: "accessory_32",
img: "resources/customisation/character_accessories/character_accessories32.png",
},
accessory_mate_bottle: {
name: "accessory_mate_bottle",
img: "resources/customisation/character_accessories/mate_bottle1.png",
},
accessory_mask: { name: "accessory_mask", img: "resources/customisation/character_accessories/mask.png" },
}; };
export const LAYERS: BodyResourceDescriptionListInterface[] = [ export const LAYERS: BodyResourceDescriptionListInterface[] = [
@ -337,9 +443,9 @@ export const LAYERS: BodyResourceDescriptionListInterface[] = [
HAIR_RESOURCES, HAIR_RESOURCES,
CLOTHES_RESOURCES, CLOTHES_RESOURCES,
HATS_RESOURCES, HATS_RESOURCES,
ACCESSORIES_RESOURCES ACCESSORIES_RESOURCES,
]; ];
export const OBJECTS: BodyResourceDescriptionInterface[] = [ export const OBJECTS: BodyResourceDescriptionInterface[] = [
{name:'teleportation', img:'resources/objects/teleportation.png'}, { name: "teleportation", img: "resources/objects/teleportation.png" },
]; ];

View File

@ -1,14 +1,12 @@
import Scene = Phaser.Scene; import Scene = Phaser.Scene;
import type {Character} from "./Character"; import type { Character } from "./Character";
//todo: improve this WIP //todo: improve this WIP
export class SpeechBubble { export class SpeechBubble {
private bubble: Phaser.GameObjects.Graphics; private bubble: Phaser.GameObjects.Graphics;
private content: Phaser.GameObjects.Text; private content: Phaser.GameObjects.Text;
constructor(scene: Scene, player: Character, text: string = "") { constructor(scene: Scene, player: Character, text: string = "") {
const bubbleHeight = 50; const bubbleHeight = 50;
const bubblePadding = 10; const bubblePadding = 10;
const bubbleWidth = bubblePadding * 2 + text.length * 10; const bubbleWidth = bubblePadding * 2 + text.length * 10;
@ -49,15 +47,24 @@ export class SpeechBubble {
this.bubble.lineBetween(point2X, point2Y, point3X, point3Y); this.bubble.lineBetween(point2X, point2Y, point3X, point3Y);
this.bubble.lineBetween(point1X, point1Y, point3X, point3Y); this.bubble.lineBetween(point1X, point1Y, point3X, point3Y);
this.content = scene.add.text(0, 0, text, { fontFamily: 'Arial', fontSize: '20', color: '#000000', align: 'center', wordWrap: { width: bubbleWidth - (bubblePadding * 2) } }); this.content = scene.add.text(0, 0, text, {
fontFamily: "Arial",
fontSize: "20",
color: "#000000",
align: "center",
wordWrap: { width: bubbleWidth - bubblePadding * 2 },
});
player.add(this.content); player.add(this.content);
const bounds = this.content.getBounds(); const bounds = this.content.getBounds();
this.content.setPosition(this.bubble.x + (bubbleWidth / 2) - (bounds.width / 2), this.bubble.y + (bubbleHeight / 2) - (bounds.height / 2)); this.content.setPosition(
this.bubble.x + bubbleWidth / 2 - bounds.width / 2,
this.bubble.y + bubbleHeight / 2 - bounds.height / 2
);
} }
destroy(): void { destroy(): void {
this.bubble.setVisible(false) //todo find a better way this.bubble.setVisible(false); //todo find a better way
this.bubble.destroy(); this.bubble.destroy();
this.content.destroy(); this.content.destroy();
} }

View File

@ -1,8 +1,7 @@
export class Sprite extends Phaser.GameObjects.Sprite { export class Sprite extends Phaser.GameObjects.Sprite {
constructor(scene: Phaser.Scene, x: number, y: number, texture: string, frame?: number | string) { constructor(scene: Phaser.Scene, x: number, y: number, texture: string, frame?: number | string) {
super(scene, x, y, texture, frame); super(scene, x, y, texture, frame);
scene.sys.updateList.add(this); scene.sys.updateList.add(this);
scene.sys.displayList.add(this); scene.sys.displayList.add(this);
} }
} }

View File

@ -1,6 +1,6 @@
import {emoteEventStream} from "../../Connexion/EmoteEventStream"; import { emoteEventStream } from "../../Connexion/EmoteEventStream";
import type {GameScene} from "./GameScene"; import type { GameScene } from "./GameScene";
import type {Subscription} from "rxjs"; import type { Subscription } from "rxjs";
export class EmoteManager { export class EmoteManager {
private subscription: Subscription; private subscription: Subscription;
@ -8,7 +8,7 @@ export class EmoteManager {
constructor(private scene: GameScene) { constructor(private scene: GameScene) {
this.subscription = emoteEventStream.stream.subscribe((event) => { this.subscription = emoteEventStream.stream.subscribe((event) => {
const actor = this.scene.MapPlayersByKey.get(event.userId); const actor = this.scene.MapPlayersByKey.get(event.userId);
if(actor) { if (actor) {
actor.playEmote(event.emote); actor.playEmote(event.emote);
} }
}); });

View File

@ -36,11 +36,11 @@ export class GameManager {
this.startRoom = await connectionManager.initGameConnexion(); this.startRoom = await connectionManager.initGameConnexion();
this.loadMap(this.startRoom); this.loadMap(this.startRoom);
if(!this.playerName) { if (!this.playerName) {
const res = await Axios.get("/"); const res = await Axios.get("/");
this.playerName = res.headers['bstlyusername']; this.playerName = res.headers[ 'bstlyusername' ];
} }
//If player name was not set show login scene with player name //If player name was not set show login scene with player name
//If Room si not public and Auth was not set, show login scene to authenticate user (OpenID - SSO - Anonymous) //If Room si not public and Auth was not set, show login scene to authenticate user (OpenID - SSO - Anonymous)
if (!this.playerName || (this.startRoom.authenticationMandatory && !localUserStore.getAuthToken())) { if (!this.playerName || (this.startRoom.authenticationMandatory && !localUserStore.getAuthToken())) {

View File

@ -4,35 +4,39 @@ import BaseSound = Phaser.Sound.BaseSound;
import SoundConfig = Phaser.Types.Sound.SoundConfig; import SoundConfig = Phaser.Types.Sound.SoundConfig;
class SoundManager { class SoundManager {
private soundPromises : Map<string,Promise<BaseSound>> = new Map<string, Promise<Phaser.Sound.BaseSound>>(); private soundPromises: Map<string, Promise<BaseSound>> = new Map<string, Promise<Phaser.Sound.BaseSound>>();
public loadSound (loadPlugin: LoaderPlugin, soundManager : BaseSoundManager, soundUrl: string) : Promise<BaseSound> { public loadSound(loadPlugin: LoaderPlugin, soundManager: BaseSoundManager, soundUrl: string): Promise<BaseSound> {
let soundPromise = this.soundPromises.get(soundUrl); let soundPromise = this.soundPromises.get(soundUrl);
if (soundPromise !== undefined) { if (soundPromise !== undefined) {
return soundPromise; return soundPromise;
} }
soundPromise = new Promise<BaseSound>((res) => { soundPromise = new Promise<BaseSound>((res) => {
const sound = soundManager.get(soundUrl); const sound = soundManager.get(soundUrl);
if (sound !== null) { if (sound !== null) {
return res(sound); return res(sound);
} }
loadPlugin.audio(soundUrl, soundUrl); loadPlugin.audio(soundUrl, soundUrl);
loadPlugin.once('filecomplete-audio-' + soundUrl, () => { loadPlugin.once("filecomplete-audio-" + soundUrl, () => {
res(soundManager.add(soundUrl)); res(soundManager.add(soundUrl));
}); });
loadPlugin.start(); loadPlugin.start();
}); });
this.soundPromises.set(soundUrl,soundPromise); this.soundPromises.set(soundUrl, soundPromise);
return soundPromise; return soundPromise;
} }
public async playSound(loadPlugin: LoaderPlugin, soundManager : BaseSoundManager, soundUrl: string, config: SoundConfig|undefined) : Promise<void> { public async playSound(
const sound = await this.loadSound(loadPlugin,soundManager,soundUrl); loadPlugin: LoaderPlugin,
soundManager: BaseSoundManager,
soundUrl: string,
config: SoundConfig | undefined
): Promise<void> {
const sound = await this.loadSound(loadPlugin, soundManager, soundUrl);
if (config === undefined) sound.play(); if (config === undefined) sound.play();
else sound.play(config); else sound.play(config);
} }
public stopSound(soundManager : BaseSoundManager,soundUrl : string){ public stopSound(soundManager: BaseSoundManager, soundUrl: string) {
soundManager.get(soundUrl).stop(); soundManager.get(soundUrl).stop();
} }
} }

View File

@ -3,17 +3,23 @@
* It has coordinates and an "activation radius" * It has coordinates and an "activation radius"
*/ */
import Sprite = Phaser.GameObjects.Sprite; import Sprite = Phaser.GameObjects.Sprite;
import type {GameScene} from "../Game/GameScene"; import type { GameScene } from "../Game/GameScene";
import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js"; import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js";
type EventCallback = (state: unknown, parameters: unknown) => void; type EventCallback = (state: unknown, parameters: unknown) => void;
export class ActionableItem { export class ActionableItem {
private readonly activationRadiusSquared : number; private readonly activationRadiusSquared: number;
private isSelectable: boolean = false; private isSelectable: boolean = false;
private callbacks: Map<string, Array<EventCallback>> = new Map<string, Array<EventCallback>>(); private callbacks: Map<string, Array<EventCallback>> = new Map<string, Array<EventCallback>>();
public constructor(private id: number, private sprite: Sprite, private eventHandler: GameScene, private activationRadius: number, private onActivateCallback: (item: ActionableItem) => void) { public constructor(
private id: number,
private sprite: Sprite,
private eventHandler: GameScene,
private activationRadius: number,
private onActivateCallback: (item: ActionableItem) => void
) {
this.activationRadiusSquared = activationRadius * activationRadius; this.activationRadiusSquared = activationRadius * activationRadius;
} }
@ -25,8 +31,8 @@ export class ActionableItem {
* Returns the square of the distance to the object center IF we are in item action range * Returns the square of the distance to the object center IF we are in item action range
* OR null if we are out of range. * OR null if we are out of range.
*/ */
public actionableDistance(x: number, y: number): number|null { public actionableDistance(x: number, y: number): number | null {
const distanceSquared = (x - this.sprite.x)*(x - this.sprite.x) + (y - this.sprite.y)*(y - this.sprite.y); const distanceSquared = (x - this.sprite.x) * (x - this.sprite.x) + (y - this.sprite.y) * (y - this.sprite.y);
if (distanceSquared < this.activationRadiusSquared) { if (distanceSquared < this.activationRadiusSquared) {
return distanceSquared; return distanceSquared;
} else { } else {
@ -45,7 +51,7 @@ export class ActionableItem {
this.getOutlinePlugin()?.add(this.sprite, { this.getOutlinePlugin()?.add(this.sprite, {
thickness: 2, thickness: 2,
outlineColor: 0xffff00 outlineColor: 0xffff00,
}); });
} }
@ -60,8 +66,8 @@ export class ActionableItem {
this.getOutlinePlugin()?.remove(this.sprite); this.getOutlinePlugin()?.remove(this.sprite);
} }
private getOutlinePlugin(): OutlinePipelinePlugin|undefined { private getOutlinePlugin(): OutlinePipelinePlugin | undefined {
return this.sprite.scene.plugins.get('rexOutlinePipeline') as unknown as OutlinePipelinePlugin|undefined; return this.sprite.scene.plugins.get("rexOutlinePipeline") as unknown as OutlinePipelinePlugin | undefined;
} }
/** /**
@ -78,7 +84,7 @@ export class ActionableItem {
} }
public on(eventName: string, callback: EventCallback): void { public on(eventName: string, callback: EventCallback): void {
let callbacksArray: Array<EventCallback>|undefined = this.callbacks.get(eventName); let callbacksArray: Array<EventCallback> | undefined = this.callbacks.get(eventName);
if (callbacksArray === undefined) { if (callbacksArray === undefined) {
callbacksArray = new Array<EventCallback>(); callbacksArray = new Array<EventCallback>();
this.callbacks.set(eventName, callbacksArray); this.callbacks.set(eventName, callbacksArray);

View File

@ -1,86 +1,91 @@
import * as Phaser from 'phaser'; import * as Phaser from "phaser";
import {Scene} from "phaser"; import { Scene } from "phaser";
import Sprite = Phaser.GameObjects.Sprite; import Sprite = Phaser.GameObjects.Sprite;
import type {ITiledMapObject} from "../../Map/ITiledMap"; import type { ITiledMapObject } from "../../Map/ITiledMap";
import type {ItemFactoryInterface} from "../ItemFactoryInterface"; import type { ItemFactoryInterface } from "../ItemFactoryInterface";
import type {GameScene} from "../../Game/GameScene"; import type { GameScene } from "../../Game/GameScene";
import {ActionableItem} from "../ActionableItem"; import { ActionableItem } from "../ActionableItem";
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
const isComputerState = const isComputerState = new tg.IsInterface()
new tg.IsInterface().withProperties({ .withProperties({
status: tg.isString, status: tg.isString,
}).get(); })
.get();
type ComputerState = tg.GuardedType<typeof isComputerState>; type ComputerState = tg.GuardedType<typeof isComputerState>;
let state: ComputerState = { let state: ComputerState = {
'status': 'off' status: "off",
}; };
export default { export default {
preload: (loader: Phaser.Loader.LoaderPlugin): void => { preload: (loader: Phaser.Loader.LoaderPlugin): void => {
loader.atlas('computer', '/resources/items/computer/computer.png', '/resources/items/computer/computer_atlas.json'); loader.atlas(
"computer",
"/resources/items/computer/computer.png",
"/resources/items/computer/computer_atlas.json"
);
}, },
create: (scene: GameScene): void => { create: (scene: GameScene): void => {
scene.anims.create({ scene.anims.create({
key: 'computer_off', key: "computer_off",
frames: [ frames: [
{ {
key: 'computer', key: "computer",
frame: 'computer_off' frame: "computer_off",
} },
], ],
frameRate: 10, frameRate: 10,
repeat: -1 repeat: -1,
}); });
scene.anims.create({ scene.anims.create({
key: 'computer_run', key: "computer_run",
frames: [ frames: [
{ {
key: 'computer', key: "computer",
frame: 'computer_on1' frame: "computer_on1",
}, },
{ {
key: 'computer', key: "computer",
frame: 'computer_on2' frame: "computer_on2",
} },
], ],
frameRate: 5, frameRate: 5,
repeat: -1 repeat: -1,
}); });
}, },
factory: (scene: GameScene, object: ITiledMapObject, initState: unknown): ActionableItem => { factory: (scene: GameScene, object: ITiledMapObject, initState: unknown): ActionableItem => {
if (initState !== undefined) { if (initState !== undefined) {
if (!isComputerState(initState)) { if (!isComputerState(initState)) {
throw new Error('Invalid state received for computer object'); throw new Error("Invalid state received for computer object");
} }
state = initState; state = initState;
} }
// Idée: ESSAYER WebPack? https://paultavares.wordpress.com/2018/07/02/webpack-how-to-generate-an-es-module-bundle/ // Idée: ESSAYER WebPack? https://paultavares.wordpress.com/2018/07/02/webpack-how-to-generate-an-es-module-bundle/
const computer = new Sprite(scene, object.x, object.y, 'computer'); const computer = new Sprite(scene, object.x, object.y, "computer");
scene.add.existing(computer); scene.add.existing(computer);
if (state.status === 'on') { if (state.status === "on") {
computer.anims.play('computer_run'); computer.anims.play("computer_run");
} }
const item = new ActionableItem(object.id, computer, scene, 32, (item: ActionableItem) => { const item = new ActionableItem(object.id, computer, scene, 32, (item: ActionableItem) => {
if (state.status === 'off') { if (state.status === "off") {
state.status = 'on'; state.status = "on";
item.emit('TURN_ON', state); item.emit("TURN_ON", state);
} else { } else {
state.status = 'off'; state.status = "off";
item.emit('TURN_OFF', state); item.emit("TURN_OFF", state);
} }
}); });
item.on('TURN_ON', () => { item.on("TURN_ON", () => {
computer.anims.play('computer_run'); computer.anims.play("computer_run");
}); });
item.on('TURN_OFF', () => { item.on("TURN_OFF", () => {
computer.anims.play('computer_off'); computer.anims.play("computer_off");
}); });
return item; return item;
//scene.add.sprite(object.x, object.y, 'computer'); //scene.add.sprite(object.x, object.y, 'computer');
} },
} as ItemFactoryInterface; } as ItemFactoryInterface;

View File

@ -1,6 +1,6 @@
import type {GameScene} from "../Game/GameScene"; import type { GameScene } from "../Game/GameScene";
import type {ITiledMapObject} from "../Map/ITiledMap"; import type { ITiledMapObject } from "../Map/ITiledMap";
import type {ActionableItem} from "./ActionableItem"; import type { ActionableItem } from "./ActionableItem";
import LoaderPlugin = Phaser.Loader.LoaderPlugin; import LoaderPlugin = Phaser.Loader.LoaderPlugin;
export interface ItemFactoryInterface { export interface ItemFactoryInterface {

View File

@ -1,14 +1,13 @@
import {ResizableScene} from "./ResizableScene"; import { ResizableScene } from "./ResizableScene";
import {localUserStore} from "../../Connexion/LocalUserStore"; import { localUserStore } from "../../Connexion/LocalUserStore";
import type {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures"; import type { BodyResourceDescriptionInterface } from "../Entity/PlayerTextures";
import {loadCustomTexture} from "../Entity/PlayerTexturesLoadingManager"; import { loadCustomTexture } from "../Entity/PlayerTexturesLoadingManager";
import type {CharacterTexture} from "../../Connexion/LocalUser"; import type { CharacterTexture } from "../../Connexion/LocalUser";
export abstract class AbstractCharacterScene extends ResizableScene { export abstract class AbstractCharacterScene extends ResizableScene {
loadCustomSceneSelectCharacters(): Promise<BodyResourceDescriptionInterface[]> {
loadCustomSceneSelectCharacters() : Promise<BodyResourceDescriptionInterface[]> {
const textures = this.getTextures(); const textures = this.getTextures();
const promises : Promise<BodyResourceDescriptionInterface>[] = []; const promises: Promise<BodyResourceDescriptionInterface>[] = [];
if (textures) { if (textures) {
for (const texture of textures) { for (const texture of textures) {
if (texture.level === -1) { if (texture.level === -1) {
@ -17,10 +16,10 @@ export abstract class AbstractCharacterScene extends ResizableScene {
promises.push(loadCustomTexture(this.load, texture)); promises.push(loadCustomTexture(this.load, texture));
} }
} }
return Promise.all(promises) return Promise.all(promises);
} }
loadSelectSceneCharacters() : Promise<BodyResourceDescriptionInterface[]> { loadSelectSceneCharacters(): Promise<BodyResourceDescriptionInterface[]> {
const textures = this.getTextures(); const textures = this.getTextures();
const promises: Promise<BodyResourceDescriptionInterface>[] = []; const promises: Promise<BodyResourceDescriptionInterface>[] = [];
if (textures) { if (textures) {
@ -31,10 +30,10 @@ export abstract class AbstractCharacterScene extends ResizableScene {
promises.push(loadCustomTexture(this.load, texture)); promises.push(loadCustomTexture(this.load, texture));
} }
} }
return Promise.all(promises) return Promise.all(promises);
} }
private getTextures() : CharacterTexture[]|undefined{ private getTextures(): CharacterTexture[] | undefined {
const localUser = localUserStore.getLocalUser(); const localUser = localUserStore.getLocalUser();
return localUser?.textures; return localUser?.textures;
} }

View File

@ -1,4 +1,4 @@
import {Scene} from "phaser"; import { Scene } from "phaser";
import DOMElement = Phaser.GameObjects.DOMElement; import DOMElement = Phaser.GameObjects.DOMElement;
export abstract class ResizableScene extends Scene { export abstract class ResizableScene extends Scene {
@ -11,13 +11,10 @@ export abstract class ResizableScene extends Scene {
* @param defaultWidth The width of the DOM element. We try to compute it but it may not be available if called from "create". * @param defaultWidth The width of the DOM element. We try to compute it but it may not be available if called from "create".
*/ */
public centerXDomElement(object: DOMElement, defaultWidth: number): void { public centerXDomElement(object: DOMElement, defaultWidth: number): void {
object.x = (this.scale.width / 2) - object.x =
( this.scale.width / 2 -
object (object && object.node && object.node.getBoundingClientRect().width > 0
&& object.node ? object.node.getBoundingClientRect().width / 2 / this.scale.zoom
&& object.node.getBoundingClientRect().width > 0 : defaultWidth / this.scale.zoom);
? (object.node.getBoundingClientRect().width / 2 / this.scale.zoom)
: (defaultWidth / this.scale.zoom)
);
} }
} }

View File

@ -1,14 +1,13 @@
import { SelectCharacterScene } from "./SelectCharacterScene"; import { SelectCharacterScene } from "./SelectCharacterScene";
export class SelectCharacterMobileScene extends SelectCharacterScene { export class SelectCharacterMobileScene extends SelectCharacterScene {
create() {
create(){
super.create(); super.create();
this.onResize(); this.onResize();
this.selectedRectangle.destroy(); this.selectedRectangle.destroy();
} }
protected defineSetupPlayer(num: number){ protected defineSetupPlayer(num: number) {
const deltaX = 30; const deltaX = 30;
const deltaY = 2; const deltaY = 2;
let [playerX, playerY] = this.getCharacterPosition(); let [playerX, playerY] = this.getCharacterPosition();
@ -16,48 +15,44 @@ export class SelectCharacterMobileScene extends SelectCharacterScene {
let playerScale = 1.5; let playerScale = 1.5;
let playerOpacity = 1; let playerOpacity = 1;
if( this.currentSelectUser !== num ){ if (this.currentSelectUser !== num) {
playerVisible = false; playerVisible = false;
} }
if( num === (this.currentSelectUser + 1) ){ if (num === this.currentSelectUser + 1) {
playerY -= deltaY; playerY -= deltaY;
playerX += deltaX; playerX += deltaX;
playerScale = 0.8; playerScale = 0.8;
playerOpacity = 0.6; playerOpacity = 0.6;
playerVisible = true; playerVisible = true;
} }
if( num === (this.currentSelectUser + 2) ){ if (num === this.currentSelectUser + 2) {
playerY -= deltaY; playerY -= deltaY;
playerX += (deltaX * 2); playerX += deltaX * 2;
playerScale = 0.8; playerScale = 0.8;
playerOpacity = 0.6; playerOpacity = 0.6;
playerVisible = true; playerVisible = true;
} }
if( num === (this.currentSelectUser - 1) ){ if (num === this.currentSelectUser - 1) {
playerY -= deltaY; playerY -= deltaY;
playerX -= deltaX; playerX -= deltaX;
playerScale = 0.8; playerScale = 0.8;
playerOpacity = 0.6; playerOpacity = 0.6;
playerVisible = true; playerVisible = true;
} }
if( num === (this.currentSelectUser - 2) ){ if (num === this.currentSelectUser - 2) {
playerY -= deltaY; playerY -= deltaY;
playerX -= (deltaX * 2); playerX -= deltaX * 2;
playerScale = 0.8; playerScale = 0.8;
playerOpacity = 0.6; playerOpacity = 0.6;
playerVisible = true; playerVisible = true;
} }
return {playerX, playerY, playerScale, playerOpacity, playerVisible} return { playerX, playerY, playerScale, playerOpacity, playerVisible };
} }
/** /**
* Returns pixel position by on column and row number * Returns pixel position by on column and row number
*/ */
protected getCharacterPosition(): [number, number] { protected getCharacterPosition(): [number, number] {
return [ return [this.game.renderer.width / 2, this.game.renderer.height / 3];
this.game.renderer.width / 2, }
this.game.renderer.height / 3
];
}
} }

View File

@ -1,13 +1,10 @@
export enum PlayerAnimationDirections { export enum PlayerAnimationDirections {
Down = 'down', Down = "down",
Left = 'left', Left = "left",
Up = 'up', Up = "up",
Right = 'right', Right = "right",
} }
export enum PlayerAnimationTypes { export enum PlayerAnimationTypes {
Walk = 'walk', Walk = "walk",
Idle = 'idle', Idle = "idle",
} }

View File

@ -1,9 +1,9 @@
import {PlayerAnimationDirections} from "./Animation"; import { PlayerAnimationDirections } from "./Animation";
import type {GameScene} from "../Game/GameScene"; import type { GameScene } from "../Game/GameScene";
import {UserInputEvent, UserInputManager} from "../UserInput/UserInputManager"; import { UserInputEvent, UserInputManager } from "../UserInput/UserInputManager";
import {Character} from "../Entity/Character"; import { Character } from "../Entity/Character";
import {userMovingStore} from "../../Stores/GameStore"; import { userMovingStore } from "../../Stores/GameStore";
import {EmoteMenu, EmoteMenuClickEvent} from "../Components/EmoteMenu"; import { EmoteMenu, EmoteMenuClickEvent } from "../Components/EmoteMenu";
export const hasMovedEventName = "hasMoved"; export const hasMovedEventName = "hasMoved";
export const requestEmoteEventName = "requestEmote"; export const requestEmoteEventName = "requestEmote";
@ -11,7 +11,7 @@ export const requestEmoteEventName = "requestEmote";
export class Player extends Character { export class Player extends Character {
private previousDirection: string = PlayerAnimationDirections.Down; private previousDirection: string = PlayerAnimationDirections.Down;
private wasMoving: boolean = false; private wasMoving: boolean = false;
private emoteMenu: EmoteMenu|null = null; private emoteMenu: EmoteMenu | null = null;
private updateListener: () => void; private updateListener: () => void;
constructor( constructor(
@ -99,7 +99,7 @@ export class Player extends Character {
this.emoteMenu = new EmoteMenu(this.scene, this.x, this.y, this.userInputManager) this.emoteMenu = new EmoteMenu(this.scene, this.x, this.y, this.userInputManager)
} }
if(this.emoteMenu.isOpen()) { if (this.emoteMenu.isOpen()) {
this.closeEmoteMenu(); this.closeEmoteMenu();
} else { } else {
this.openEmoteMenu(); this.openEmoteMenu();

View File

@ -3,13 +3,13 @@ export class WAError extends Error {
private _subTitle: string; private _subTitle: string;
private _details: string; private _details: string;
constructor (title: string, subTitle: string, details: string) { constructor(title: string, subTitle: string, details: string) {
super(title+' - '+subTitle+' - '+details); super(title + " - " + subTitle + " - " + details);
this._title = title; this._title = title;
this._subTitle = subTitle; this._subTitle = subTitle;
this._details = details; this._details = details;
// Set the prototype explicitly. // Set the prototype explicitly.
Object.setPrototypeOf (this, WAError.prototype); Object.setPrototypeOf(this, WAError.prototype);
} }
get title(): string { get title(): string {

View File

@ -1,4 +1,3 @@
interface Size { interface Size {
width: number; width: number;
height: number; height: number;
@ -23,14 +22,14 @@ export class HdpiManager {
* *
* @param realPixelScreenSize * @param realPixelScreenSize
*/ */
public getOptimalGameSize(realPixelScreenSize: Size): { game: Size, real: Size } { public getOptimalGameSize(realPixelScreenSize: Size): { game: Size; real: Size } {
const realPixelNumber = realPixelScreenSize.width * realPixelScreenSize.height; const realPixelNumber = realPixelScreenSize.width * realPixelScreenSize.height;
// If the screen has not a definition small enough to match the minimum number of pixels we want to display, // If the screen has not a definition small enough to match the minimum number of pixels we want to display,
// let's make the canvas the size of the screen (in real pixels) // let's make the canvas the size of the screen (in real pixels)
if (realPixelNumber <= this.minRecommendedGamePixelsNumber) { if (realPixelNumber <= this.minRecommendedGamePixelsNumber) {
return { return {
game: realPixelScreenSize, game: realPixelScreenSize,
real: realPixelScreenSize real: realPixelScreenSize,
}; };
} }
@ -49,8 +48,8 @@ export class HdpiManager {
real: { real: {
width: realPixelScreenSize.width, width: realPixelScreenSize.width,
height: realPixelScreenSize.height, height: realPixelScreenSize.height,
} },
} };
} }
const gameWidth = Math.ceil(realPixelScreenSize.width / optimalZoomLevel / this._zoomModifier); const gameWidth = Math.ceil(realPixelScreenSize.width / optimalZoomLevel / this._zoomModifier);
@ -58,8 +57,12 @@ export class HdpiManager {
// Let's ensure we display a minimum of pixels, even if crazily zoomed in. // Let's ensure we display a minimum of pixels, even if crazily zoomed in.
if (gameWidth * gameHeight < this.absoluteMinPixelNumber) { if (gameWidth * gameHeight < this.absoluteMinPixelNumber) {
const minGameHeight = Math.sqrt(this.absoluteMinPixelNumber * realPixelScreenSize.height / realPixelScreenSize.width); const minGameHeight = Math.sqrt(
const minGameWidth = Math.sqrt(this.absoluteMinPixelNumber * realPixelScreenSize.width / realPixelScreenSize.height); (this.absoluteMinPixelNumber * realPixelScreenSize.height) / realPixelScreenSize.width
);
const minGameWidth = Math.sqrt(
(this.absoluteMinPixelNumber * realPixelScreenSize.width) / realPixelScreenSize.height
);
// Let's reset the zoom modifier (WARNING this is a SIDE EFFECT in a getter) // Let's reset the zoom modifier (WARNING this is a SIDE EFFECT in a getter)
this._zoomModifier = realPixelScreenSize.width / minGameWidth / optimalZoomLevel; this._zoomModifier = realPixelScreenSize.width / minGameWidth / optimalZoomLevel;
@ -72,9 +75,8 @@ export class HdpiManager {
real: { real: {
width: realPixelScreenSize.width, width: realPixelScreenSize.width,
height: realPixelScreenSize.height, height: realPixelScreenSize.height,
} },
} };
} }
return { return {
@ -85,8 +87,8 @@ export class HdpiManager {
real: { real: {
width: Math.ceil(realPixelScreenSize.width / optimalZoomLevel) * optimalZoomLevel, width: Math.ceil(realPixelScreenSize.width / optimalZoomLevel) * optimalZoomLevel,
height: Math.ceil(realPixelScreenSize.height / optimalZoomLevel) * optimalZoomLevel, height: Math.ceil(realPixelScreenSize.height / optimalZoomLevel) * optimalZoomLevel,
} },
} };
} }
/** /**
@ -95,7 +97,7 @@ export class HdpiManager {
private getOptimalZoomLevel(realPixelNumber: number): number { private getOptimalZoomLevel(realPixelNumber: number): number {
const result = Math.sqrt(realPixelNumber / this.minRecommendedGamePixelsNumber); const result = Math.sqrt(realPixelNumber / this.minRecommendedGamePixelsNumber);
if (1.5 <= result && result < 2) { if (1.5 <= result && result < 2) {
return 1.5 return 1.5;
} else { } else {
return Math.floor(result); return Math.floor(result);
} }

View File

@ -1,10 +1,9 @@
import {HdpiManager} from "./HdpiManager"; import { HdpiManager } from "./HdpiManager";
import ScaleManager = Phaser.Scale.ScaleManager; import ScaleManager = Phaser.Scale.ScaleManager;
import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager"; import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
import type {Game} from "../Game/Game"; import type { Game } from "../Game/Game";
import {ResizableScene} from "../Login/ResizableScene"; import { ResizableScene } from "../Login/ResizableScene";
import {HtmlUtils} from "../../WebRtc/HtmlUtils"; import { HtmlUtils } from "../../WebRtc/HtmlUtils";
class WaScaleManager { class WaScaleManager {
private hdpiManager: HdpiManager; private hdpiManager: HdpiManager;
@ -23,26 +22,29 @@ class WaScaleManager {
} }
public applyNewSize() { public applyNewSize() {
const {width, height} = coWebsiteManager.getGameSize(); const { width, height } = coWebsiteManager.getGameSize();
let devicePixelRatio = 1; let devicePixelRatio = 1;
if (window.devicePixelRatio) { if (window.devicePixelRatio) {
devicePixelRatio = window.devicePixelRatio; devicePixelRatio = window.devicePixelRatio;
} }
const { game: gameSize, real: realSize } = this.hdpiManager.getOptimalGameSize({width: width * devicePixelRatio, height: height * devicePixelRatio}); const { game: gameSize, real: realSize } = this.hdpiManager.getOptimalGameSize({
width: width * devicePixelRatio,
height: height * devicePixelRatio,
});
this.actualZoom = realSize.width / gameSize.width / devicePixelRatio; this.actualZoom = realSize.width / gameSize.width / devicePixelRatio;
this.scaleManager.setZoom(realSize.width / gameSize.width / devicePixelRatio) this.scaleManager.setZoom(realSize.width / gameSize.width / devicePixelRatio);
this.scaleManager.resize(gameSize.width, gameSize.height); this.scaleManager.resize(gameSize.width, gameSize.height);
// Override bug in canvas resizing in Phaser. Let's resize the canvas ourselves // Override bug in canvas resizing in Phaser. Let's resize the canvas ourselves
const style = this.scaleManager.canvas.style; const style = this.scaleManager.canvas.style;
style.width = Math.ceil(realSize.width / devicePixelRatio) + 'px'; style.width = Math.ceil(realSize.width / devicePixelRatio) + "px";
style.height = Math.ceil(realSize.height / devicePixelRatio) + 'px'; style.height = Math.ceil(realSize.height / devicePixelRatio) + "px";
// Resize the game element at the same size at the canvas // Resize the game element at the same size at the canvas
const gameStyle = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('game').style; const gameStyle = HtmlUtils.getElementByIdOrFail<HTMLDivElement>("game").style;
gameStyle.width = style.width; gameStyle.width = style.width;
gameStyle.height = style.height; gameStyle.height = style.height;
@ -70,7 +72,7 @@ class WaScaleManager {
this._saveZoom = this.hdpiManager.zoomModifier; this._saveZoom = this.hdpiManager.zoomModifier;
} }
public restoreZoom(): void{ public restoreZoom(): void {
this.hdpiManager.zoomModifier = this._saveZoom; this.hdpiManager.zoomModifier = this._saveZoom;
this.applyNewSize(); this.applyNewSize();
} }
@ -81,7 +83,6 @@ class WaScaleManager {
public get uiScalingFactor(): number { public get uiScalingFactor(): number {
return this.actualZoom > 1 ? 1 : 1.2; return this.actualZoom > 1 ? 1 : 1.2;
} }
} }
export const waScaleManager = new WaScaleManager(640*480, 196*196); export const waScaleManager = new WaScaleManager(640 * 480, 196 * 196);

View File

@ -1,6 +1,6 @@
import {Pinch} from "phaser3-rex-plugins/plugins/gestures.js"; import { Pinch } from "phaser3-rex-plugins/plugins/gestures.js";
import {waScaleManager} from "../Services/WaScaleManager"; import { waScaleManager } from "../Services/WaScaleManager";
import {GameScene} from "../Game/GameScene"; import { GameScene } from "../Game/GameScene";
export class PinchManager { export class PinchManager {
private scene: Phaser.Scene; private scene: Phaser.Scene;
@ -15,18 +15,18 @@ export class PinchManager {
// We are smoothing its value with previous values to prevent the flicking. // We are smoothing its value with previous values to prevent the flicking.
let smoothPinch = 1; let smoothPinch = 1;
this.pinch.on('pinchstart', () => { this.pinch.on("pinchstart", () => {
smoothPinch = 1; smoothPinch = 1;
}); });
// eslint-disable-next-line
this.pinch.on('pinch', (pinch:any) => { // eslint-disable-line this.pinch.on("pinch", (pinch: any) => {
if (pinch.scaleFactor > 1.2 || pinch.scaleFactor < 0.8) { if (pinch.scaleFactor > 1.2 || pinch.scaleFactor < 0.8) {
// Pinch too fast! Probably a bad measure. // Pinch too fast! Probably a bad measure.
return; return;
} }
smoothPinch = 3/5*smoothPinch + 2/5*pinch.scaleFactor; smoothPinch = (3 / 5) * smoothPinch + (2 / 5) * pinch.scaleFactor;
if (this.scene instanceof GameScene) { if (this.scene instanceof GameScene) {
this.scene.zoomByFactor(smoothPinch); this.scene.zoomByFactor(smoothPinch);
} else { } else {

View File

@ -2,4 +2,4 @@ import { writable } from "svelte/store";
export const consoleGlobalMessageManagerVisibleStore = writable(false); export const consoleGlobalMessageManagerVisibleStore = writable(false);
export const consoleGlobalMessageManagerFocusStore = writable(false); export const consoleGlobalMessageManagerFocusStore = writable(false);

View File

@ -1,4 +1,4 @@
import {writable} from "svelte/store"; import { writable } from "svelte/store";
/** /**
* A store that contains a list of error messages to be displayed. * A store that contains a list of error messages to be displayed.
@ -8,7 +8,7 @@ function createErrorStore() {
return { return {
subscribe, subscribe,
addErrorMessage: (e: string|Error): void => { addErrorMessage: (e: string | Error): void => {
update((messages: string[]) => { update((messages: string[]) => {
let message: string; let message: string;
if (e instanceof Error) { if (e instanceof Error) {
@ -26,7 +26,7 @@ function createErrorStore() {
}, },
clearMessages: (): void => { clearMessages: (): void => {
set([]); set([]);
} },
}; };
} }

View File

@ -1,8 +1,10 @@
export class BrowserTooOldError extends Error { export class BrowserTooOldError extends Error {
static NAME = 'BrowserTooOldError'; static NAME = "BrowserTooOldError";
constructor() { constructor() {
super('Unable to access your camera or microphone. Your browser is too old. Please consider upgrading your browser or try using a recent version of Chrome.'); super(
"Unable to access your camera or microphone. Your browser is too old. Please consider upgrading your browser or try using a recent version of Chrome."
);
this.name = BrowserTooOldError.NAME; this.name = BrowserTooOldError.NAME;
} }
} }

View File

@ -1,8 +1,10 @@
export class WebviewOnOldIOS extends Error { export class WebviewOnOldIOS extends Error {
static NAME = 'WebviewOnOldIOS'; static NAME = "WebviewOnOldIOS";
constructor() { constructor() {
super('Your iOS version cannot use video/audio in the browser unless you are using Safari. Please switch to Safari or upgrade iOS to 14.3 or above.'); super(
"Your iOS version cannot use video/audio in the browser unless you are using Safari. Please switch to Safari or upgrade iOS to 14.3 or above."
);
this.name = WebviewOnOldIOS.NAME; this.name = WebviewOnOldIOS.NAME;
} }
} }

View File

@ -1,3 +1,3 @@
import { derived, writable, Writable } from "svelte/store"; import { derived, writable, Writable } from "svelte/store";
export const selectCharacterSceneVisibleStore = writable(false); export const selectCharacterSceneVisibleStore = writable(false);

View File

@ -4,7 +4,7 @@ import { writable } from "svelte/store";
* A store that contains the URL of the sound currently playing * A store that contains the URL of the sound currently playing
*/ */
function createSoundPlayingStore() { function createSoundPlayingStore() {
const { subscribe, set, update } = writable<string|null>(null); const { subscribe, set, update } = writable<string | null>(null);
return { return {
subscribe, subscribe,
@ -13,9 +13,7 @@ function createSoundPlayingStore() {
}, },
soundEnded: () => { soundEnded: () => {
set(null); set(null);
} },
}; };
} }

View File

@ -1,16 +1,14 @@
class TouchScreenManager { class TouchScreenManager {
readonly supportTouchScreen: boolean;
readonly supportTouchScreen:boolean;
constructor() { constructor() {
this.supportTouchScreen = this.detectTouchscreen(); this.supportTouchScreen = this.detectTouchscreen();
} }
//found here: https://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript#4819886 //found here: https://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript#4819886
detectTouchscreen(): boolean { detectTouchscreen(): boolean {
return (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)); return "ontouchstart" in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
} }
} }
export const touchScreenManager = new TouchScreenManager(); export const touchScreenManager = new TouchScreenManager();

View File

@ -1,12 +1,9 @@
export function isIOS(): boolean { export function isIOS(): boolean {
return [ return (
'iPad Simulator', ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(
'iPhone Simulator', navigator.platform
'iPod Simulator', ) ||
'iPad',
'iPhone',
'iPod'
].includes(navigator.platform)
// iPad on iOS 13 detection // iPad on iOS 13 detection
|| (navigator.userAgent.includes("Mac") && "ontouchend" in document) (navigator.userAgent.includes("Mac") && "ontouchend" in document)
);
} }

View File

@ -1,16 +1,16 @@
declare module 'phaser3-rex-plugins/plugins/virtualjoystick.js' { declare module "phaser3-rex-plugins/plugins/virtualjoystick.js" {
const content: any; // eslint-disable-line const content: any; // eslint-disable-line
export default content; export default content;
} }
declare module 'phaser3-rex-plugins/plugins/gestures-plugin.js' { declare module "phaser3-rex-plugins/plugins/gestures-plugin.js" {
const content: any; // eslint-disable-line const content: any; // eslint-disable-line
export default content; export default content;
} }
declare module 'phaser3-rex-plugins/plugins/webfontloader-plugin.js' { declare module "phaser3-rex-plugins/plugins/webfontloader-plugin.js" {
const content: any; // eslint-disable-line const content: any; // eslint-disable-line
export default content; export default content;
} }
declare module 'phaser3-rex-plugins/plugins/outlinepipeline-plugin.js' { declare module "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js" {
import GameObject = Phaser.GameObjects.GameObject; import GameObject = Phaser.GameObjects.GameObject;
class OutlinePipelinePlugin { class OutlinePipelinePlugin {
@ -21,6 +21,6 @@ declare module 'phaser3-rex-plugins/plugins/outlinepipeline-plugin.js' {
export default OutlinePipelinePlugin; export default OutlinePipelinePlugin;
} }
declare module 'phaser3-rex-plugins/plugins/gestures.js' { declare module "phaser3-rex-plugins/plugins/gestures.js" {
export const Pinch: any; // eslint-disable-line export const Pinch: any; // eslint-disable-line
} }

View File

@ -9,7 +9,7 @@ const JITSI_URL: string | undefined = process.env.JITSI_URL === "" ? undefined :
const JITSI_ISS = process.env.JITSI_ISS || ""; const JITSI_ISS = process.env.JITSI_ISS || "";
const SECRET_JITSI_KEY = process.env.SECRET_JITSI_KEY || ""; const SECRET_JITSI_KEY = process.env.SECRET_JITSI_KEY || "";
const PUSHER_HTTP_PORT = parseInt(process.env.PUSHER_HTTP_PORT || "8080") || 8080; const PUSHER_HTTP_PORT = parseInt(process.env.PUSHER_HTTP_PORT || "8080") || 8080;
export const SOCKET_IDLE_TIMER = parseInt(process.env.SOCKET_IDLE_TIMER as string) || 30; // maximum time (in second) without activity before a socket is closed export const SOCKET_IDLE_TIMER = parseInt(process.env.SOCKET_IDLE_TIMER as string) || 32; // maximum time (in second) without activity before a socket is closed
export const FRONT_URL = process.env.FRONT_URL || "http://localhost"; export const FRONT_URL = process.env.FRONT_URL || "http://localhost";
export const OPID_CLIENT_ID = process.env.OPID_CLIENT_ID || ""; export const OPID_CLIENT_ID = process.env.OPID_CLIENT_ID || "";