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

This commit is contained in:
David Négrier
2022-03-11 11:55:30 +01:00
101 changed files with 7448 additions and 191 deletions
+27 -25
View File
@@ -1,31 +1,33 @@
# The building of ProtoBuf "messages" must be done out of Docker because grpc-node does not ship with ARM64 binaries.
# See: https://github.com/grpc/grpc-node/issues/1405
# When the issue above is closed, we can move back messages building inside Dockerfile
# protobuf build
#FROM node:14.18.2-buster-slim@sha256:20bedf0c09de887379e59a41c04284974f5fb529cf0e13aab613473ce298da3d as proto-builder
#WORKDIR /usr/src
#COPY messages/yarn.lock messages/package.json ./
#RUN yarn install
#COPY messages .
#RUN yarn ts-proto
# typescript build
FROM node:14.18.2-buster-slim@sha256:20bedf0c09de887379e59a41c04284974f5fb529cf0e13aab613473ce298da3d as builder
WORKDIR /usr/src/messages
COPY messages .
RUN yarn install && yarn ts-proto
WORKDIR /usr/src/front
WORKDIR /usr/src
COPY front/yarn.lock front/package.json ./
RUN yarn install --network-timeout 1000000
COPY front .
#COPY --from=proto-builder /usr/src/ts-proto-generated/protos src/Messages/ts-proto-generated
#RUN sed -i 's/import { Observable } from "rxjs";/import type { Observable } from "rxjs";/g' src/Messages/ts-proto-generated/messages.ts
#COPY --from=proto-builder /usr/src/JsonMessages src/Messages/JsonMessages
RUN yarn run typesafe-i18n && yarn run build-iframe-api && yarn build
# move messages to front
RUN cp -r ../messages/ts-proto-generated/protos/* src/Messages/ts-proto-generated
RUN sed -i 's/import { Observable } from "rxjs";/import type { Observable } from "rxjs";/g' src/Messages/ts-proto-generated/messages.ts
RUN cp -r ../messages/JsonMessages/* src/Messages/JsonMessages
# final production image
FROM nginx:1.21.6-alpine
RUN yarn install && yarn run typesafe-i18n && yarn run build-iframe-api && yarn build
COPY front/nginx.conf /etc/nginx/conf.d/default.conf
COPY front/templater.sh /
FROM thecodingmachine/nodejs:14-apache
COPY --from=builder /usr/src/dist /usr/share/nginx/html
COPY --from=builder --chown=docker:docker /usr/src/front/dist dist
COPY front/templater.sh .
USER root
RUN DEBIAN_FRONTEND=noninteractive apt-get update \
&& apt-get install -y \
gettext-base \
&& rm -rf /var/lib/apt/lists/*
USER docker
ENV STARTUP_COMMAND_0="./templater.sh"
ENV STARTUP_COMMAND_1="envsubst < dist/env-config.template.js > dist/env-config.js"
ENV APACHE_DOCUMENT_ROOT=dist/
EXPOSE 80
CMD ["/bin/sh", "-c", "/templater.sh && envsubst < /usr/share/nginx/html/env-config.template.js > /usr/share/nginx/html/env-config.js && exec nginx -g 'daemon off;'"]
+51
View File
@@ -0,0 +1,51 @@
server {
listen 80;
listen [::]:80;
server_name localhost;
access_log off;
gzip on;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_proxied any;
gzip_disable "msie6";
gzip_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/svg+xml
text/css
text/javascript
text/plain
text/xml;
# serve static assets (that have a cache busting hash) with an efficient cache policy
location /assets {
root /usr/share/nginx/html;
expires 1y;
add_header Cache-Control "public";
}
location / {
root /usr/share/nginx/html;
index index.html;
rewrite ^/register/ /index.html break;
rewrite ^/login /index.html break;
rewrite ^/jwt /index.html break;
}
location ~ ^/[@_]/ {
try_files $uri $uri/ /index.html;
}
}
+38
View File
@@ -0,0 +1,38 @@
import { isSilentStore, requestedCameraState, requestedMicrophoneState } from "../../Stores/MediaStore";
import { get } from "svelte/store";
class DesktopApi {
isSilent: boolean = false;
init() {
if (!window?.WAD?.desktop) {
return;
}
console.log("Yipee you are using the desktop app ;)");
window.WAD.onMuteToggle(() => {
if (this.isSilent) return;
if (get(requestedMicrophoneState) === true) {
requestedMicrophoneState.disableMicrophone();
} else {
requestedMicrophoneState.enableMicrophone();
}
});
window.WAD.onCameraToggle(() => {
if (this.isSilent) return;
if (get(requestedCameraState) === true) {
requestedCameraState.disableWebcam();
} else {
requestedCameraState.enableWebcam();
}
});
isSilentStore.subscribe((value) => {
this.isSilent = value;
});
}
}
export const desktopApi = new DesktopApi();
+21
View File
@@ -0,0 +1,21 @@
<!-- https://lihautan.com/notes/svelte-lazy-load/ -->
<script>
export let when = false;
export let component;
let loading;
$: if (when) {
load();
}
function load() {
loading = component();
}
</script>
{#if when}
{#await loading then { default: Component }}
<Component />
{/await}
{/if}
+2 -4
View File
@@ -12,7 +12,6 @@
import AudioManager from "./AudioManager/AudioManager.svelte";
import CameraControls from "./CameraControls.svelte";
import EmbedScreensContainer from "./EmbedScreens/EmbedScreensContainer.svelte";
import EmoteMenu from "./EmoteMenu/EmoteMenu.svelte";
import HelpCameraSettingsPopup from "./HelpCameraSettings/HelpCameraSettingsPopup.svelte";
import LayoutActionManager from "./LayoutActionManager/LayoutActionManager.svelte";
import Menu from "./Menu/Menu.svelte";
@@ -38,6 +37,7 @@
import { LayoutMode } from "../WebRtc/LayoutManager";
import { actionsMenuStore } from "../Stores/ActionsMenuStore";
import ActionsMenu from "./ActionsMenu/ActionsMenu.svelte";
import Lazy from "./Lazy.svelte";
let mainLayout: HTMLDivElement;
@@ -116,9 +116,7 @@
<VisitCard visitCardUrl={$requestVisitCardsStore} />
{/if}
{#if $emoteMenuStore}
<EmoteMenu />
{/if}
<Lazy when={$emoteMenuStore} component={() => import("./EmoteMenu/EmoteMenu.svelte")} />
{#if hasEmbedScreen}
<EmbedScreensContainer />
+26 -1
View File
@@ -16,6 +16,10 @@ import { isRegisterData } from "../Messages/JsonMessages/RegisterData";
import { isAdminApiData } from "../Messages/JsonMessages/AdminApiData";
import { limitMapStore } from "../Stores/GameStore";
import { showLimitRoomModalStore } from "../Stores/ModalStore";
import { gameManager } from "../Phaser/Game/GameManager";
import { locales } from "../i18n/i18n-util";
import type { Locales } from "../i18n/i18n-types";
import { setCurrentLocale } from "../i18n/locales";
class ConnectionManager {
private localUser!: LocalUser;
@@ -326,7 +330,7 @@ class ConnectionManager {
throw new Error("No Auth code provided");
}
}
const { authToken, userUuid, email } = await Axios.get(`${PUSHER_URL}/login-callback`, {
const { authToken, userUuid, email, username, locale } = await Axios.get(`${PUSHER_URL}/login-callback`, {
params: { code, nonce, token, playUri: this.currentRoom?.key },
}).then((res) => {
return res.data;
@@ -336,6 +340,27 @@ class ConnectionManager {
localUserStore.saveUser(this.localUser);
this.authToken = authToken;
if (username) {
gameManager.setPlayerName(username);
}
if (locale) {
try {
if (locales.indexOf(locale) == -1) {
locales.forEach((l) => {
if (l.startsWith(locale.split("-")[0])) {
setCurrentLocale(l);
return;
}
});
} else {
setCurrentLocale(locale as Locales);
}
} catch (err) {
console.warn("Could not set locale", err);
}
}
//user connected, set connected store for menu at true
userIsConnected.set(true);
}
+5 -18
View File
@@ -126,19 +126,7 @@ export class GameMap {
for (let y = 0; y < this.map.height; y += 1) {
const row: number[] = [];
for (let x = 0; x < this.map.width; x += 1) {
row.push(this.isCollidingAt(x, y) ? 1 : 0);
}
grid.push(row);
}
return grid;
}
public getWalkingCostGrid(): number[][] {
const grid: number[][] = [];
for (let y = 0; y < this.map.height; y += 1) {
const row: number[] = [];
for (let x = 0; x < this.map.width; x += 1) {
row.push(this.getWalkingCostAt(x, y));
row.push(this.isCollidingAt(x, y) ? 1 : this.isExitTile(x, y) ? 2 : 0);
}
grid.push(row);
}
@@ -355,8 +343,7 @@ export class GameMap {
return false;
}
private getWalkingCostAt(x: number, y: number): number {
const bigCost = 100;
private isExitTile(x: number, y: number): boolean {
for (const layer of this.phaserLayers) {
if (!layer.visible) {
continue;
@@ -369,16 +356,16 @@ export class GameMap {
tile &&
(tile.properties[GameMapProperties.EXIT_URL] || tile.properties[GameMapProperties.EXIT_SCENE_URL])
) {
return bigCost;
return true;
}
for (const property of layer.layer.properties) {
//@ts-ignore
if (property.name && property.name === "exitUrl") {
return bigCost;
return true;
}
}
}
return 0;
return false;
}
private triggerAllProperties(): void {
+3 -2
View File
@@ -566,7 +566,6 @@ export class GameScene extends DirtyScene {
this.pathfindingManager = new PathfindingManager(
this,
this.gameMap.getCollisionGrid(),
this.gameMap.getWalkingCostGrid(),
this.gameMap.getTileDimensions()
);
@@ -1453,7 +1452,7 @@ ${escapedMessage}
phaserLayers[i].setCollisionByProperty({ collides: true }, visible);
}
}
this.pathfindingManager.setCollisionGrid(this.gameMap.getCollisionGrid(), this.gameMap.getWalkingCostGrid());
this.pathfindingManager.setCollisionGrid(this.gameMap.getCollisionGrid());
this.markDirty();
}
@@ -1601,6 +1600,8 @@ ${escapedMessage}
}
})
.catch((reason) => console.warn(reason));
urlManager.clearHashParameter();
} catch (err) {
console.warn(`Cannot proceed with moveTo command:\n\t-> ${err}`);
}
+4
View File
@@ -58,6 +58,10 @@ class UrlManager {
return this.getHashParameters()[name];
}
public clearHashParameter(): void {
window.location.hash = "";
}
private getHashParameters(): Record<string, string> {
return window.location.hash
.substring(1)
+4 -18
View File
@@ -8,27 +8,21 @@ export class PathfindingManager {
private grid: number[][];
private tileDimensions: { width: number; height: number };
constructor(
scene: Phaser.Scene,
collisionsGrid: number[][],
walkingCostGrid: number[][],
tileDimensions: { width: number; height: number }
) {
constructor(scene: Phaser.Scene, collisionsGrid: number[][], tileDimensions: { width: number; height: number }) {
this.scene = scene;
this.easyStar = new EasyStar.js();
this.easyStar.enableDiagonals();
this.easyStar.disableCornerCutting();
this.easyStar.setTileCost(2, 100);
this.grid = collisionsGrid;
this.tileDimensions = tileDimensions;
this.setEasyStarGrid(collisionsGrid);
this.setWalkingCostGrid(walkingCostGrid);
}
public setCollisionGrid(collisionGrid: number[][], walkingCostGrid: number[][]): void {
public setCollisionGrid(collisionGrid: number[][]): void {
this.setEasyStarGrid(collisionGrid);
this.setWalkingCostGrid(walkingCostGrid);
}
public async findPath(
@@ -120,15 +114,7 @@ export class PathfindingManager {
private setEasyStarGrid(grid: number[][]): void {
this.easyStar.setGrid(grid);
this.easyStar.setAcceptableTiles([0]); // zeroes are walkable
}
private setWalkingCostGrid(grid: number[][]): void {
for (let y = 0; y < grid.length; y += 1) {
for (let x = 0; x < grid[y].length; x += 1) {
this.easyStar.setAdditionalPointCost(x, y, grid[y][x]);
}
}
this.easyStar.setAcceptableTiles([0, 2]); // zeroes are walkable, 2 are exits, also walkable
}
private logGridToTheConsole(grid: number[][]): void {
+1 -7
View File
@@ -21,6 +21,7 @@ import type { Popup } from "./Api/iframe/Ui/Popup";
import type { Sound } from "./Api/iframe/Sound/Sound";
import { answerPromises, queryWorkadventure } from "./Api/iframe/IframeApiContribution";
import camera from "./Api/iframe/camera";
import {} from "./window";
const globalState = createState("global");
@@ -182,13 +183,6 @@ const wa = {
export type WorkAdventureApi = typeof wa;
declare global {
interface Window {
WA: WorkAdventureApi;
}
let WA: WorkAdventureApi;
}
window.WA = wa;
window.addEventListener(
+2
View File
@@ -16,6 +16,7 @@ import { coWebsiteManager } from "./WebRtc/CoWebsiteManager";
import { localUserStore } from "./Connexion/LocalUserStore";
import { ErrorScene } from "./Phaser/Reconnecting/ErrorScene";
import { iframeListener } from "./Api/IframeListener";
import { desktopApi } from "./Api/desktop/index";
import { SelectCharacterMobileScene } from "./Phaser/Login/SelectCharacterMobileScene";
import { HdpiManager } from "./Phaser/Services/HdpiManager";
import { waScaleManager } from "./Phaser/Services/WaScaleManager";
@@ -154,6 +155,7 @@ coWebsiteManager.onResize.subscribe(() => {
});
iframeListener.init();
desktopApi.init();
const app = new App({
target: HtmlUtils.getElementByIdOrFail("game-overlay"),
+10
View File
@@ -0,0 +1,10 @@
import { WorkAdventureApi } from "./iframe_api";
import { WorkAdventureDesktopApi } from "@wa-preload-app";
declare global {
interface Window {
WA: WorkAdventureApi;
WAD: WorkAdventureDesktopApi;
}
let WA: WorkAdventureApi;
}
+4 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
set -x
set -o nounset errexit
index_file=dist/index.html
index_file=/usr/share/nginx/html/index.html
tmp_trackcodefile=/tmp/trackcode
# To inject tracking code, you have two choices:
@@ -10,12 +10,12 @@ tmp_trackcodefile=/tmp/trackcode
# The ANALYTICS_CODE_PATH is the location of a file inside the container
ANALYTICS_CODE_PATH="${ANALYTICS_CODE_PATH:-dist/ga.html.tmpl}"
if [[ "${INSERT_ANALYTICS:-NO}" == "NO" ]]; then
if [ "${INSERT_ANALYTICS:-NO}" = "NO" ]; then
echo "" > "${tmp_trackcodefile}"
fi
# Automatically insert analytics if GA_TRACKING_ID is set
if [[ "${GA_TRACKING_ID:-}" != "" || "${INSERT_ANALYTICS:-NO}" != "NO" ]]; then
if [ "${GA_TRACKING_ID:-}" != "" ] || [ "${INSERT_ANALYTICS:-NO}" != "NO" ]; then
echo "Templating code from ${ANALYTICS_CODE_PATH}"
sed "s#<!-- TRACKING NUMBER -->#${GA_TRACKING_ID:-}#g" "${ANALYTICS_CODE_PATH}" > "$tmp_trackcodefile"
fi
+4 -1
View File
@@ -27,7 +27,10 @@
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
"paths": {
"@wa-preload-app": ["../desktop/electron/src/preload-app/types.ts"],
}
},
"exclude": [
"node_modules",
+1 -6
View File
@@ -475,12 +475,7 @@ ansi-escapes@^4.3.0:
dependencies:
type-fest "^0.21.3"
ansi-regex@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
ansi-regex@^5.0.1:
ansi-regex@^5.0.0, ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==