Gravwell-Online/web-svelte/src/views/lobby/multiplayer.svelte

224 lines
4.4 KiB
Svelte

<script lang="ts">
import ShipDesigner from "../../components/modals/ShipDesigner.svelte";
import OptionInfo from "../../components/modals/OptionInfo.svelte";
import SciFiCheckbox from "../../components/SciFi-Checkbox.svelte";
import SciFiButton from "../../components/SciFi-Button.svelte";
import { ILobbyInfo, Status, gameOptions } from "common";
import Player from "../../components/Player.svelte";
import { isHost, players } from "../../stores";
import { socket } from "../../main";
import { onMount } from "svelte";
function handleLobbyInfo(data: ILobbyInfo) {
if (data.status == Status.Success) {
for (const player of data.players) {
$players[player.id] = player;
}
} else {
console.table(data);
};
};
onMount(() => {
socket.on(`res:lobby.info`, handleLobbyInfo);
return () => {
socket.off(`res:lobby.info`);
};
});
function tempButtonHandler() {};
// The modals that can appear in the lobby
const modal = {
options: false,
shipDesigner: false,
};
$: visibleOptions = gameOptions.filter(x => !x.hidden);
/** Copies the game link to clipboard for easy sharing */
function copyLinkToClipboard() {
navigator.clipboard.writeText(window.location.href);
};
/**
* What gets called when the host toggles one of the options in the lobby so
* that the other players can see the change happen on their screen.
*/
function toggleOption(e: CustomEvent<string>) {
let option = visibleOptions.find(x => x.id == e.detail);
console.debug(`Toggled option: ${option.name}`);
// TODO: Send websocket event to server
};
</script>
<OptionInfo
open="{modal.options}"
{visibleOptions}
on:close="{_ => modal.options = false}"
/>
<ShipDesigner
open="{modal.shipDesigner}"
on:selectColour="{tempButtonHandler}"
on:close="{_ => modal.shipDesigner = false}"
/>
<main>
<div>
<h1>Gravwell</h1>
<SciFiButton
width="69%"
on:click={copyLinkToClipboard}
>
Copy Game Link
</SciFiButton>
<div class="sci-fi-box">
<h2>Players</h2>
<div class="player-box">
{#each Object.entries($players) as [id, p], i (id)}
<Player
name="{p.name}"
colour="{p.colour}"
on:changeColour="{_ => modal.shipDesigner = true}"
/>
{#if i == 1}
<div class="divider"></div>
{/if}
{/each}
</div>
</div>
<div class="sci-fi-box">
<div class="info-button-container">
<SciFiButton
on:click={_ => modal.options = true}
height="60px"
width="60px"
>
<div style="display: flex; align-items: center; justify-content: center;">
<span class="material-icons">help_outline</span>
</div>
</SciFiButton>
</div>
<h2>Options</h2>
<div class="options-box">
{#each visibleOptions as option}
<div>
<SciFiCheckbox
name="{option.name}"
id="{option.id}"
disabled="{!$isHost}"
bind:state="{option.active}"
on:toggle="{toggleOption}"
>
{option.name}
</SciFiCheckbox>
</div>
{/each}
</div>
</div>
<div class="flex-row">
<SciFiButton
title="Starts the game"
on:click={tempButtonHandler}
>
Start Game
</SciFiButton>
<SciFiButton
title="Delete the lobby, preventing further games from being played"
background="#ff0000"
on:click={tempButtonHandler}
>
Delete Game
</SciFiButton>
</div>
</div>
</main>
<style lang="scss">
main {
color: #FFFFFF;
width: 100%;
height: 100%;
text-align: center;
display: flex;
justify-content: center;
}
h1 {
font-size: 4rem;
font-weight: 100;
line-height: 1.1;
}
.sci-fi-box {
border-radius: 10px;
border-width: 2px;
border-style: solid;
border-color: white;
margin: 5px;
background: rgba(0, 0, 0, 0.5);
position: relative;
h2 {
margin: 10px 0px;
}
}
.player-box {
display: flex;
flex-wrap: wrap;
justify-content: center;
> .divider {
width: 100%;
}
> :global(div) {
flex-grow: 1;
}
}
.options-box {
padding-bottom: 5px;
display: flex;
justify-content: space-evenly;
flex-wrap: wrap;
> div {
background: rgba(255, 255, 255, 0.1);
border-radius: 5px;
padding: 3px 7px;
margin: 5px 5px 10px 5px;
}
> div:first-child {
margin-left: 10px;
}
> div:last-child {
margin-right: 10px;
}
}
.info-button-container {
position: absolute;
top: -2px;
right: -2px;
}
.flex-row {
display: flex;
align-items: center;
justify-content: center;
}
.flex-row > :global(div) {
flex-grow: 1;
}
@media (min-width: 480px) {
h1 {
max-width: none;
}
}
</style>