Merge pull request #1183 from thecodingmachine/develop

Deploy 2021-06-14
This commit is contained in:
David Négrier 2021-06-14 22:19:02 +02:00 committed by GitHub
commit 9c14bd9c90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 213 additions and 66 deletions

View File

@ -149,6 +149,37 @@ jobs:
# Create a slugified value of the branch # Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@3.1.0 - 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 - name: Deploy
uses: thecodingmachine/deeployer-action@master uses: thecodingmachine/deeployer-action@master
env: env:
@ -168,4 +199,4 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: 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

View File

@ -11,8 +11,7 @@
"back1": { "back1": {
"image": "thecodingmachine/workadventure-back:"+tag, "image": "thecodingmachine/workadventure-back:"+tag,
"host": { "host": {
"url": "api1."+url, "url": "api1-"+url,
"https": "enable",
"containerPort": 8080 "containerPort": 8080
}, },
"ports": [8080, 50051], "ports": [8080, 50051],
@ -30,8 +29,7 @@
"back2": { "back2": {
"image": "thecodingmachine/workadventure-back:"+tag, "image": "thecodingmachine/workadventure-back:"+tag,
"host": { "host": {
"url": "api2."+url, "url": "api2-"+url,
"https": "enable",
"containerPort": 8080 "containerPort": 8080
}, },
"ports": [8080, 50051], "ports": [8080, 50051],
@ -50,8 +48,7 @@
"replicas": 2, "replicas": 2,
"image": "thecodingmachine/workadventure-pusher:"+tag, "image": "thecodingmachine/workadventure-pusher:"+tag,
"host": { "host": {
"url": "pusher."+url, "url": "pusher-"+url,
"https": "enable"
}, },
"ports": [8080], "ports": [8080],
"env": { "env": {
@ -68,27 +65,25 @@
"front": { "front": {
"image": "thecodingmachine/workadventure-front:"+tag, "image": "thecodingmachine/workadventure-front:"+tag,
"host": { "host": {
"url": "play."+url, "url": "play-"+url,
"https": "enable"
}, },
"ports": [80], "ports": [80],
"env": { "env": {
"PUSHER_URL": "//pusher."+url, "PUSHER_URL": "//pusher-"+url,
"UPLOADER_URL": "//uploader."+url, "UPLOADER_URL": "//uploader-"+url,
"ADMIN_URL": "//"+url, "ADMIN_URL": "//"+url,
"JITSI_URL": env.JITSI_URL, "JITSI_URL": env.JITSI_URL,
"SECRET_JITSI_KEY": env.SECRET_JITSI_KEY, "SECRET_JITSI_KEY": env.SECRET_JITSI_KEY,
"TURN_SERVER": "turn:coturn.workadventu.re:443,turns:coturn.workadventu.re:443", "TURN_SERVER": "turn:coturn.workadventu.re:443,turns:coturn.workadventu.re:443",
"JITSI_PRIVATE_MODE": if env.SECRET_JITSI_KEY != '' then "true" else "false", "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" //"GA_TRACKING_ID": "UA-10196481-11"
} }
}, },
"uploader": { "uploader": {
"image": "thecodingmachine/workadventure-uploader:"+tag, "image": "thecodingmachine/workadventure-uploader:"+tag,
"host": { "host": {
"url": "uploader."+url, "url": "uploader-"+url,
"https": "enable",
"containerPort": 8080 "containerPort": 8080
}, },
"ports": [8080], "ports": [8080],
@ -98,16 +93,12 @@
"maps": { "maps": {
"image": "thecodingmachine/workadventure-maps:"+tag, "image": "thecodingmachine/workadventure-maps:"+tag,
"host": { "host": {
"url": "maps."+url, "url": "maps-"+url
"https": "enable"
}, },
"ports": [80] "ports": [80]
}, },
}, },
"config": { "config": {
"https": {
"mail": "d.negrier@thecodingmachine.com"
},
k8sextension(k8sConf):: k8sextension(k8sConf)::
k8sConf + { k8sConf + {
back1+: { back1+: {
@ -122,6 +113,14 @@
} }
} }
} }
},
ingress+: {
spec+: {
tls+: [{
hosts: ["api1-"+url],
secretName: "certificate-tls"
}]
}
} }
}, },
back2+: { back2+: {
@ -136,6 +135,14 @@
} }
} }
} }
},
ingress+: {
spec+: {
tls+: [{
hosts: ["api2-"+url],
secretName: "certificate-tls"
}]
}
} }
}, },
pusher+: { 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"
}]
}
}
},
} }
} }
} }

View File

@ -1,39 +1,64 @@
<script lang="typescript"> <script lang="typescript">
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import {requestVisitCardsStore} from "../../Stores/GameStore"; import {requestVisitCardsStore} from "../../Stores/GameStore";
import {onMount} from "svelte";
export let visitCardUrl: string; export let visitCardUrl: string;
let w = '500px';
let h = '250px';
let hidden = true;
let cvIframe;
function closeCard() { function closeCard() {
requestVisitCardsStore.set(null); requestVisitCardsStore.set(null);
} }
function handleIframeMessage(message:any) {
if (message.data.type === 'cvIframeSize') {
w = (message.data.data.w) + 'px';
h = (message.data.data.h) + 'px';
}
}
onMount(() => {
cvIframe.onload = () => hidden = false
cvIframe.onerror = () => hidden = false
})
</script> </script>
<style lang="scss"> <style lang="scss">
.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 120px;
height: 120px;
margin:auto;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.visitCard { .visitCard {
pointer-events: all; pointer-events: all;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
width: 530px;
margin-top: 200px; margin-top: 200px;
max-width: 100vw; max-width: 80vw;
.defaultCard {
border-radius: 5px;
border: 2px black solid;
background-color: whitesmoke;
width: 530px;
header {
padding: 5px;
}
}
iframe { iframe {
border: 0; border: 0;
width: 530px; max-width: 80vw;
height: 270px;
overflow: hidden; overflow: hidden;
&.hidden {
visibility: hidden;
position: absolute;
}
} }
button { button {
@ -43,9 +68,17 @@
</style> </style>
<section class="visitCard" transition:fly="{{ y: -200, duration: 1000 }}"> <section class="visitCard" transition:fly="{{ y: -200, duration: 1000 }}" style="width: {w}">
<iframe title="visitCardTitle" src={visitCardUrl}></iframe> {#if hidden}
<div class="buttonContainer"> <div class="loader"></div>
<button class="nes-btn is-popUpElement" on:click={closeCard}>Close</button> {/if}
</div> <iframe title="visitCard" src={visitCardUrl} allow="clipboard-read; clipboard-write self {visitCardUrl}" style="width: {w}; height: {h}" class:hidden={hidden} bind:this={cvIframe}></iframe>
{#if !hidden}
<div class="buttonContainer">
<button class="nes-btn is-popUpElement" on:click={closeCard}>Close</button>
</div>
{/if}
</section> </section>
<svelte:window on:message={handleIframeMessage}/>

View File

@ -56,7 +56,7 @@ export abstract class Character extends Container {
this.addTextures(textures, frame); this.addTextures(textures, frame);
this.invisible = false this.invisible = false
}) })
this.playerName = new Text(scene, 0, playerNameY, name, {fontFamily: '"Press Start 2P"', fontSize: '8px', strokeThickness: 2, stroke: "gray"}); 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.playerName.setOrigin(0.5).setDepth(DEPTH_INGAME_TEXT_INDEX);
this.add(this.playerName); this.add(this.playerName);
@ -80,7 +80,7 @@ export abstract class Character extends Container {
this.setDepth(-1); this.setDepth(-1);
this.playAnimation(direction, moving); this.playAnimation(direction, moving);
if (typeof companion === 'string') { if (typeof companion === 'string') {
this.addCompanion(companion, companionTexturePromise); this.addCompanion(companion, companionTexturePromise);
} }
@ -94,7 +94,7 @@ export abstract class Character extends Container {
public addTextures(textures: string[], frame?: string | number): void { public addTextures(textures: string[], frame?: string | number): void {
for (const texture of textures) { 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'); throw new TextureError('texture not found');
} }
const sprite = new Sprite(this.scene, 0, 0, texture, frame); 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.scene.sys.updateList.remove(sprite);
} }
} }
this.list.forEach(objectContaining => objectContaining.destroy()) this.list.forEach(objectContaining => objectContaining.destroy())
super.destroy(); super.destroy();
} }
playEmote(emoteKey: string) { playEmote(emoteKey: string) {
this.cancelPreviousEmote(); this.cancelPreviousEmote();
const scalingFactor = waScaleManager.uiScalingFactor * 0.05; const scalingFactor = waScaleManager.uiScalingFactor * 0.05;
const emoteY = -30 - scalingFactor * 10; const emoteY = -30 - scalingFactor * 10;
this.playerName.setVisible(false); this.playerName.setVisible(false);
this.emote = new Sprite(this.scene, 0, 0, emoteKey); this.emote = new Sprite(this.scene, 0, 0, emoteKey);
this.emote.setAlpha(0); this.emote.setAlpha(0);
this.emote.setScale(0.1 * scalingFactor); this.emote.setScale(0.1 * scalingFactor);
this.add(this.emote); this.add(this.emote);
this.scene.sys.updateList.add(this.emote); this.scene.sys.updateList.add(this.emote);
this.createStartTransition(scalingFactor, emoteY); this.createStartTransition(scalingFactor, emoteY);
} }

View File

@ -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));
}
}
}

View File

@ -15,6 +15,7 @@ import {customCharacterSceneVisibleStore} from "../../Stores/CustomCharacterStor
import {selectCharacterSceneVisibleStore} from "../../Stores/SelectCharacterStore"; import {selectCharacterSceneVisibleStore} from "../../Stores/SelectCharacterStore";
import {waScaleManager} from "../Services/WaScaleManager"; import {waScaleManager} from "../Services/WaScaleManager";
import {isMobile} from "../../Enum/EnvironmentVariable"; import {isMobile} from "../../Enum/EnvironmentVariable";
import {CustomizedCharacter} from "../Entity/CustomizedCharacter";
export const CustomizeSceneName = "CustomizeScene"; export const CustomizeSceneName = "CustomizeScene";
@ -25,12 +26,15 @@ export class CustomizeScene extends AbstractCharacterScene {
private Rectangle!: Rectangle; private Rectangle!: Rectangle;
private selectedLayers: number[] = [0]; private selectedLayers: number[] = [0];
private containersRow: Container[][] = []; private containersRow: CustomizedCharacter[][] = [];
public activeRow:number = 0; public activeRow:number = 0;
private layers: BodyResourceDescriptionInterface[][] = []; private layers: BodyResourceDescriptionInterface[][] = [];
protected lazyloadingAttempt = true; //permit to update texture loaded after renderer protected lazyloadingAttempt = true; //permit to update texture loaded after renderer
private moveHorizontally: number = 0;
private moveVertically: number = 0;
constructor() { constructor() {
super({ super({
key: CustomizeSceneName key: CustomizeSceneName
@ -88,10 +92,13 @@ export class CustomizeScene extends AbstractCharacterScene {
this.backToPreviousScene(); this.backToPreviousScene();
}); });
this.input.keyboard.on('keyup-RIGHT', () => this.moveCursorHorizontally(1)); // Note: the key bindings are not directly put on the moveCursorVertically or moveCursorHorizontally methods
this.input.keyboard.on('keyup-LEFT', () => this.moveCursorHorizontally(-1)); // 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
this.input.keyboard.on('keyup-DOWN', () => this.moveCursorVertically(1)); // explain, the list of sprites managed by the update list become immense
this.input.keyboard.on('keyup-UP', () => this.moveCursorVertically(-1)); 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(); const customCursorPosition = localUserStore.getCustomCursorPosition();
if (customCursorPosition) { if (customCursorPosition) {
@ -104,7 +111,7 @@ export class CustomizeScene extends AbstractCharacterScene {
this.onResize(); this.onResize();
} }
public moveCursorHorizontally(index: number): void { public doMoveCursorHorizontally(index: number): void {
this.selectedLayers[this.activeRow] += index; this.selectedLayers[this.activeRow] += index;
if (this.selectedLayers[this.activeRow] < 0) { if (this.selectedLayers[this.activeRow] < 0) {
this.selectedLayers[this.activeRow] = 0 this.selectedLayers[this.activeRow] = 0
@ -116,7 +123,7 @@ export class CustomizeScene extends AbstractCharacterScene {
this.saveInLocalStorage(); this.saveInLocalStorage();
} }
public moveCursorVertically(index:number): void { public doMoveCursorVertically(index:number): void {
this.activeRow += index; this.activeRow += index;
if (this.activeRow < 0) { 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...) * @param selectedItem, The number of the item select (0 for black body...)
*/ */
private generateCharacter(x: number, y: number, layerNumber: number, selectedItem: number) { 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<Sprite> { private getContainerChildren(layerNumber: number, selectedItem: number): Array<string> {
const children: Array<Sprite> = new Array<Sprite>(); const children: Array<string> = new Array<string>();
for (let j = 0; j <= layerNumber; j++) { for (let j = 0; j <= layerNumber; j++) {
if (j === layerNumber) { if (j === layerNumber) {
children.push(this.generateLayers(0, 0, this.layers[j][selectedItem].name)); children.push(this.layers[j][selectedItem].name);
} else { } else {
const layer = this.selectedLayers[j]; const layer = this.selectedLayers[j];
if (layer === undefined) { if (layer === undefined) {
continue; continue;
} }
children.push(this.generateLayers(0, 0, this.layers[j][layer].name)); children.push(this.layers[j][layer].name);
} }
} }
return children; return children;
@ -215,15 +222,15 @@ export class CustomizeScene extends AbstractCharacterScene {
* @return a new sprite * @return a new sprite
*/ */
private generateLayers(x: number, y: number, name: string): 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() { private updateSelectedLayer() {
for(let i = 0; i < this.containersRow.length; i++){ for(let i = 0; i < this.containersRow.length; i++){
for(let j = 0; j < this.containersRow[i].length; j++){ for(let j = 0; j < this.containersRow[i].length; j++){
const children = this.getContainerChildren(i, j); const children = this.getContainerChildren(i, j);
this.containersRow[i][j].removeAll(true); this.containersRow[i][j].updateSprites(children);
this.containersRow[i][j].add(children);
} }
} }
} }
@ -234,6 +241,15 @@ export class CustomizeScene extends AbstractCharacterScene {
this.moveLayers(); this.moveLayers();
this.lazyloadingAttempt = false; 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;
}
} }

View File

@ -39,10 +39,11 @@ class WaScaleManager {
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';
// 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)) { for (const scene of this.game.scene.getScenes(true)) {
if (scene instanceof ResizableScene) { 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());
} }
} }

View File

@ -169,6 +169,7 @@ export const screenSharingLocalStreamStore = derived<Readable<MediaStreamConstra
return; return;
} catch (e) { } catch (e) {
currentStream = null; currentStream = null;
requestedScreenSharingState.disableScreenSharing();
console.info("Error. Unable to share screen.", e); console.info("Error. Unable to share screen.", e);
set({ set({
type: 'error', type: 'error',