diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml
index 3e4b0fff..3bf00b99 100644
--- a/.github/workflows/build-and-deploy.yml
+++ b/.github/workflows/build-and-deploy.yml
@@ -149,6 +149,37 @@ jobs:
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@3.1.0
+ - name: Write certificate
+ run: echo "${CERTS_PRIVATE_KEY}" > secret.key && chmod 0600 secret.key
+ env:
+ CERTS_PRIVATE_KEY: ${{ secrets.CERTS_PRIVATE_KEY }}
+
+ - name: Download certificate
+ run: mkdir secrets && scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i secret.key ubuntu@cert.workadventu.re:./config/live/workadventu.re/* secrets/
+
+ - name: Create namespace
+ uses: steebchen/kubectl@v1.0.0
+ env:
+ KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_FILE_BASE64 }}
+ with:
+ args: create namespace workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
+ continue-on-error: true
+
+ - name: Delete old certificates in namespace
+ uses: steebchen/kubectl@v1.0.0
+ env:
+ KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_FILE_BASE64 }}
+ with:
+ args: -n workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} delete secret certificate-tls
+ continue-on-error: true
+
+ - name: Install certificates in namespace
+ uses: steebchen/kubectl@v1.0.0
+ env:
+ KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_FILE_BASE64 }}
+ with:
+ args: -n workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} create secret tls certificate-tls --key="secrets/privkey.pem" --cert="secrets/fullchain.pem"
+
- name: Deploy
uses: thecodingmachine/deeployer-action@master
env:
@@ -168,4 +199,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- msg: Environment deployed at https://play.${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re
+ msg: Environment deployed at https://play-${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re
diff --git a/deeployer.libsonnet b/deeployer.libsonnet
index f9dd87bd..8d9c2bfd 100644
--- a/deeployer.libsonnet
+++ b/deeployer.libsonnet
@@ -11,8 +11,7 @@
"back1": {
"image": "thecodingmachine/workadventure-back:"+tag,
"host": {
- "url": "api1."+url,
- "https": "enable",
+ "url": "api1-"+url,
"containerPort": 8080
},
"ports": [8080, 50051],
@@ -30,8 +29,7 @@
"back2": {
"image": "thecodingmachine/workadventure-back:"+tag,
"host": {
- "url": "api2."+url,
- "https": "enable",
+ "url": "api2-"+url,
"containerPort": 8080
},
"ports": [8080, 50051],
@@ -50,8 +48,7 @@
"replicas": 2,
"image": "thecodingmachine/workadventure-pusher:"+tag,
"host": {
- "url": "pusher."+url,
- "https": "enable"
+ "url": "pusher-"+url,
},
"ports": [8080],
"env": {
@@ -68,27 +65,25 @@
"front": {
"image": "thecodingmachine/workadventure-front:"+tag,
"host": {
- "url": "play."+url,
- "https": "enable"
+ "url": "play-"+url,
},
"ports": [80],
"env": {
- "PUSHER_URL": "//pusher."+url,
- "UPLOADER_URL": "//uploader."+url,
+ "PUSHER_URL": "//pusher-"+url,
+ "UPLOADER_URL": "//uploader-"+url,
"ADMIN_URL": "//"+url,
"JITSI_URL": env.JITSI_URL,
"SECRET_JITSI_KEY": env.SECRET_JITSI_KEY,
"TURN_SERVER": "turn:coturn.workadventu.re:443,turns:coturn.workadventu.re:443",
"JITSI_PRIVATE_MODE": if env.SECRET_JITSI_KEY != '' then "true" else "false",
- "START_ROOM_URL": "/_/global/maps."+url+"/Floor0/floor0.json"
+ "START_ROOM_URL": "/_/global/maps-"+url+"/Floor0/floor0.json"
//"GA_TRACKING_ID": "UA-10196481-11"
}
},
"uploader": {
"image": "thecodingmachine/workadventure-uploader:"+tag,
"host": {
- "url": "uploader."+url,
- "https": "enable",
+ "url": "uploader-"+url,
"containerPort": 8080
},
"ports": [8080],
@@ -98,16 +93,12 @@
"maps": {
"image": "thecodingmachine/workadventure-maps:"+tag,
"host": {
- "url": "maps."+url,
- "https": "enable"
+ "url": "maps-"+url
},
"ports": [80]
},
},
"config": {
- "https": {
- "mail": "d.negrier@thecodingmachine.com"
- },
k8sextension(k8sConf)::
k8sConf + {
back1+: {
@@ -122,6 +113,14 @@
}
}
}
+ },
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["api1-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
}
},
back2+: {
@@ -136,6 +135,14 @@
}
}
}
+ },
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["api2-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
}
},
pusher+: {
@@ -150,8 +157,46 @@
}
}
}
- }
- }
+ },
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["pusher-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
+ }
+ },
+ front+: {
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["play-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
+ }
+ },
+ uploader+: {
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["uploader-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
+ }
+ },
+ maps+: {
+ ingress+: {
+ spec+: {
+ tls+: [{
+ hosts: ["maps-"+url],
+ secretName: "certificate-tls"
+ }]
+ }
+ }
+ },
}
}
}
diff --git a/front/src/Components/VisitCard/VisitCard.svelte b/front/src/Components/VisitCard/VisitCard.svelte
index cc7f00d6..5cdb4cfe 100644
--- a/front/src/Components/VisitCard/VisitCard.svelte
+++ b/front/src/Components/VisitCard/VisitCard.svelte
@@ -1,39 +1,64 @@
-
-
-
-
-
+
+ {#if hidden}
+
+ {/if}
+
+ {#if !hidden}
+
+
+
+ {/if}
+
+
+
diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts
index b1e8dc73..2ff66178 100644
--- a/front/src/Phaser/Entity/Character.ts
+++ b/front/src/Phaser/Entity/Character.ts
@@ -56,7 +56,7 @@ export abstract class Character extends Container {
this.addTextures(textures, frame);
this.invisible = false
})
-
+
this.playerName = new Text(scene, 0, playerNameY, name, {fontFamily: '"Press Start 2P"', fontSize: '8px', strokeThickness: 2, stroke: "gray"});
this.playerName.setOrigin(0.5).setDepth(DEPTH_INGAME_TEXT_INDEX);
this.add(this.playerName);
@@ -80,7 +80,7 @@ export abstract class Character extends Container {
this.setDepth(-1);
this.playAnimation(direction, moving);
-
+
if (typeof companion === 'string') {
this.addCompanion(companion, companionTexturePromise);
}
@@ -94,7 +94,7 @@ export abstract class Character extends Container {
public addTextures(textures: string[], frame?: string | number): void {
for (const texture of textures) {
- if(!this.scene.textures.exists(texture)){
+ if(this.scene && !this.scene.textures.exists(texture)){
throw new TextureError('texture not found');
}
const sprite = new Sprite(this.scene, 0, 0, texture, frame);
@@ -239,23 +239,23 @@ export abstract class Character extends Container {
this.scene.sys.updateList.remove(sprite);
}
}
- this.list.forEach(objectContaining => objectContaining.destroy())
+ this.list.forEach(objectContaining => objectContaining.destroy())
super.destroy();
}
-
+
playEmote(emoteKey: string) {
this.cancelPreviousEmote();
const scalingFactor = waScaleManager.uiScalingFactor * 0.05;
const emoteY = -30 - scalingFactor * 10;
-
+
this.playerName.setVisible(false);
this.emote = new Sprite(this.scene, 0, 0, emoteKey);
this.emote.setAlpha(0);
this.emote.setScale(0.1 * scalingFactor);
this.add(this.emote);
this.scene.sys.updateList.add(this.emote);
-
+
this.createStartTransition(scalingFactor, emoteY);
}
diff --git a/front/src/Phaser/Entity/CustomizedCharacter.ts b/front/src/Phaser/Entity/CustomizedCharacter.ts
new file mode 100644
index 00000000..3a7f1597
--- /dev/null
+++ b/front/src/Phaser/Entity/CustomizedCharacter.ts
@@ -0,0 +1,20 @@
+import Container = Phaser.GameObjects.Container;
+import type {Scene} from "phaser";
+import Sprite = Phaser.GameObjects.Sprite;
+
+/**
+ * A sprite of a customized character (used in the Customize Scene only)
+ */
+export class CustomizedCharacter extends Container {
+ public constructor(scene: Scene, x: number, y: number, layers: string[]) {
+ super(scene, x, y);
+ this.updateSprites(layers);
+ }
+
+ public updateSprites(layers: string[]): void {
+ this.removeAll(true);
+ for (const layer of layers) {
+ this.add(new Sprite(this.scene, 0, 0, layer));
+ }
+ }
+}
diff --git a/front/src/Phaser/Login/CustomizeScene.ts b/front/src/Phaser/Login/CustomizeScene.ts
index cc0c7208..f1d48235 100644
--- a/front/src/Phaser/Login/CustomizeScene.ts
+++ b/front/src/Phaser/Login/CustomizeScene.ts
@@ -15,6 +15,7 @@ import {customCharacterSceneVisibleStore} from "../../Stores/CustomCharacterStor
import {selectCharacterSceneVisibleStore} from "../../Stores/SelectCharacterStore";
import {waScaleManager} from "../Services/WaScaleManager";
import {isMobile} from "../../Enum/EnvironmentVariable";
+import {CustomizedCharacter} from "../Entity/CustomizedCharacter";
export const CustomizeSceneName = "CustomizeScene";
@@ -25,12 +26,15 @@ export class CustomizeScene extends AbstractCharacterScene {
private Rectangle!: Rectangle;
private selectedLayers: number[] = [0];
- private containersRow: Container[][] = [];
+ private containersRow: CustomizedCharacter[][] = [];
public activeRow:number = 0;
private layers: BodyResourceDescriptionInterface[][] = [];
protected lazyloadingAttempt = true; //permit to update texture loaded after renderer
+ private moveHorizontally: number = 0;
+ private moveVertically: number = 0;
+
constructor() {
super({
key: CustomizeSceneName
@@ -88,10 +92,13 @@ export class CustomizeScene extends AbstractCharacterScene {
this.backToPreviousScene();
});
- this.input.keyboard.on('keyup-RIGHT', () => this.moveCursorHorizontally(1));
- this.input.keyboard.on('keyup-LEFT', () => this.moveCursorHorizontally(-1));
- this.input.keyboard.on('keyup-DOWN', () => this.moveCursorVertically(1));
- this.input.keyboard.on('keyup-UP', () => this.moveCursorVertically(-1));
+ // Note: the key bindings are not directly put on the moveCursorVertically or moveCursorHorizontally methods
+ // because if 2 such events are fired close to one another, it makes the whole application crawl to a halt (for a reason I cannot
+ // explain, the list of sprites managed by the update list become immense
+ this.input.keyboard.on('keyup-RIGHT', () => this.moveHorizontally = 1);
+ this.input.keyboard.on('keyup-LEFT', () => this.moveHorizontally = -1);
+ this.input.keyboard.on('keyup-DOWN', () => this.moveVertically = 1);
+ this.input.keyboard.on('keyup-UP', () => this.moveVertically = -1);
const customCursorPosition = localUserStore.getCustomCursorPosition();
if (customCursorPosition) {
@@ -104,7 +111,7 @@ export class CustomizeScene extends AbstractCharacterScene {
this.onResize();
}
- public moveCursorHorizontally(index: number): void {
+ public doMoveCursorHorizontally(index: number): void {
this.selectedLayers[this.activeRow] += index;
if (this.selectedLayers[this.activeRow] < 0) {
this.selectedLayers[this.activeRow] = 0
@@ -116,7 +123,7 @@ export class CustomizeScene extends AbstractCharacterScene {
this.saveInLocalStorage();
}
- public moveCursorVertically(index:number): void {
+ public doMoveCursorVertically(index:number): void {
this.activeRow += index;
if (this.activeRow < 0) {
@@ -165,20 +172,20 @@ export class CustomizeScene extends AbstractCharacterScene {
* @param selectedItem, The number of the item select (0 for black body...)
*/
private generateCharacter(x: number, y: number, layerNumber: number, selectedItem: number) {
- return new Container(this, x, y,this.getContainerChildren(layerNumber,selectedItem));
+ return new CustomizedCharacter(this, x, y, this.getContainerChildren(layerNumber,selectedItem));
}
- private getContainerChildren(layerNumber: number, selectedItem: number): Array {
- const children: Array = new Array();
+ private getContainerChildren(layerNumber: number, selectedItem: number): Array {
+ const children: Array = new Array();
for (let j = 0; j <= layerNumber; j++) {
if (j === layerNumber) {
- children.push(this.generateLayers(0, 0, this.layers[j][selectedItem].name));
+ children.push(this.layers[j][selectedItem].name);
} else {
const layer = this.selectedLayers[j];
if (layer === undefined) {
continue;
}
- children.push(this.generateLayers(0, 0, this.layers[j][layer].name));
+ children.push(this.layers[j][layer].name);
}
}
return children;
@@ -215,15 +222,15 @@ export class CustomizeScene extends AbstractCharacterScene {
* @return a new sprite
*/
private generateLayers(x: number, y: number, name: string): Sprite {
- return new Sprite(this, x, y, name);
+ //return new Sprite(this, x, y, name);
+ return this.add.sprite(0, 0, name);
}
private updateSelectedLayer() {
for(let i = 0; i < this.containersRow.length; i++){
for(let j = 0; j < this.containersRow[i].length; j++){
- const children = this.getContainerChildren(i, j);
- this.containersRow[i][j].removeAll(true);
- this.containersRow[i][j].add(children);
+ const children = this.getContainerChildren(i, j);
+ this.containersRow[i][j].updateSprites(children);
}
}
}
@@ -234,6 +241,15 @@ export class CustomizeScene extends AbstractCharacterScene {
this.moveLayers();
this.lazyloadingAttempt = false;
}
+
+ if (this.moveHorizontally !== 0) {
+ this.doMoveCursorHorizontally(this.moveHorizontally);
+ this.moveHorizontally = 0;
+ }
+ if (this.moveVertically !== 0) {
+ this.doMoveCursorVertically(this.moveVertically);
+ this.moveVertically = 0;
+ }
}
diff --git a/front/src/Phaser/Services/WaScaleManager.ts b/front/src/Phaser/Services/WaScaleManager.ts
index acbecc38..1da0fcf3 100644
--- a/front/src/Phaser/Services/WaScaleManager.ts
+++ b/front/src/Phaser/Services/WaScaleManager.ts
@@ -39,10 +39,11 @@ class WaScaleManager {
const style = this.scaleManager.canvas.style;
style.width = Math.ceil(realSize.width / devicePixelRatio) + 'px';
style.height = Math.ceil(realSize.height / devicePixelRatio) + 'px';
- // Note: onResize will be called twice (once here and once is Game.ts), but we have no better way.
+ // Note: onResize will be called twice (once here and once in Game.ts), but we have no better way.
for (const scene of this.game.scene.getScenes(true)) {
if (scene instanceof ResizableScene) {
- scene.onResize();
+ // We are delaying the call to the "render" event because otherwise, the "camera" coordinates are not correctly updated.
+ scene.events.once(Phaser.Scenes.Events.RENDER, () => scene.onResize());
}
}
diff --git a/front/src/Stores/ScreenSharingStore.ts b/front/src/Stores/ScreenSharingStore.ts
index 0a7ef3e6..ec5aa46f 100644
--- a/front/src/Stores/ScreenSharingStore.ts
+++ b/front/src/Stores/ScreenSharingStore.ts
@@ -169,6 +169,7 @@ export const screenSharingLocalStreamStore = derived