Feat : lobby
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
[submodule "netcode/interfaces"]
|
||||
path = netcode/interfaces
|
||||
url = git@git.legonzaur.fr:heronfief/ts-interfaces.git
|
||||
@@ -2,110 +2,15 @@
|
||||
// import goStore, { oauth2_register_discord, setup_websocket, heron_cookie_login } from "@/netcode";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// useHead
|
||||
// ({
|
||||
// title
|
||||
// : 'Héron Realms',
|
||||
// })
|
||||
|
||||
// const heron_session = useCookie('heron_session')
|
||||
// const route = useRoute()
|
||||
|
||||
// onMounted(async () => {
|
||||
// const code = route.query.code
|
||||
// if (!code) { return }
|
||||
// if (Array.isArray(code)) { return }
|
||||
// await setup_websocket()
|
||||
// oauth2_register_discord(code)
|
||||
// history.pushState(
|
||||
// {},
|
||||
// '',
|
||||
// '/'
|
||||
// )
|
||||
// })
|
||||
const authStore = useAuthStore()
|
||||
await authStore.whoami()
|
||||
|
||||
|
||||
// onMounted(async () => {
|
||||
// if (!heron_session.value) { return }
|
||||
// heron_cookie_login(heron_session.value)
|
||||
// })
|
||||
|
||||
// function keyDownHandler(e: KeyboardEvent) {
|
||||
// if (e.repeat) { return }
|
||||
// console.log(e.code)
|
||||
// if (e.code != "AltLeft") { return }
|
||||
// goStore.zoomKeyPressed = true
|
||||
// e.preventDefault()
|
||||
// return false
|
||||
// }
|
||||
|
||||
// function keyUpHandler(e: KeyboardEvent) {
|
||||
// if (e.repeat) { return }
|
||||
// if (e.code != "AltLeft") { return }
|
||||
// goStore.zoomKeyPressed = false
|
||||
// e.preventDefault()
|
||||
// return false
|
||||
// }
|
||||
|
||||
// function contextMenuHandler(e: MouseEvent) {
|
||||
// e.preventDefault()
|
||||
// }
|
||||
|
||||
// function mouseDownHandler(e: MouseEvent) {
|
||||
// if (e.button !== 2) { return }
|
||||
// goStore.zoomKeyPressed = true
|
||||
// e.preventDefault()
|
||||
// return false
|
||||
// }
|
||||
|
||||
// function mouseUpHandler(e: MouseEvent) {
|
||||
// if (e.button !== 2) { return }
|
||||
// goStore.zoomKeyPressed = false
|
||||
// e.preventDefault()
|
||||
// return false
|
||||
// }
|
||||
|
||||
// function follow_mouse(e: MouseEvent) {
|
||||
// goStore.clientMouseX = e.clientX
|
||||
// goStore.clientMouseY = e.clientY
|
||||
// }
|
||||
|
||||
// onMounted(() => {
|
||||
// window.addEventListener("contextmenu", contextMenuHandler)
|
||||
// window.addEventListener("mousedown", mouseDownHandler)
|
||||
// window.addEventListener("mouseup", mouseUpHandler)
|
||||
// document.addEventListener("mousemove", follow_mouse)
|
||||
// })
|
||||
|
||||
// import goStore, { setReady, oauth2_register_discord, setup_websocket, heron_cookie_login } from "@/netcode";
|
||||
|
||||
// await setup_websocket()
|
||||
|
||||
// useHead
|
||||
// ({
|
||||
// title
|
||||
// : 'Héron Realms',
|
||||
// })
|
||||
|
||||
|
||||
|
||||
// const heron_session = useCookie('heron_session')
|
||||
// const route = useRoute()
|
||||
|
||||
// onMounted(async () => {
|
||||
// const code = route.query.code
|
||||
// if (!code) { return }
|
||||
// if (Array.isArray(code)) { return }
|
||||
// await setup_websocket()
|
||||
// oauth2_register_discord(code)
|
||||
// history.pushState(
|
||||
// {},
|
||||
// '',
|
||||
// '/'
|
||||
// )
|
||||
// })
|
||||
|
||||
useHead
|
||||
({
|
||||
title
|
||||
: 'Héron Realms',
|
||||
})
|
||||
|
||||
// onMounted(async () => {
|
||||
// if (!heron_session.value) { return }
|
||||
@@ -171,7 +76,13 @@ const router = useRouter();
|
||||
<template>
|
||||
<div class="root_dom_div">
|
||||
<!-- <CardOverlay v-if="goStore.zoomKeyPressed" :card_id="goStore.hoveredCard" /> -->
|
||||
<NuxtLoadingIndicator>
|
||||
Loading...
|
||||
</NuxtLoadingIndicator>
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import goStore from '~/netcode';
|
||||
import { useSettingsStore } from '~/stores/settingsStore';
|
||||
// import goStore from '~/netcode';
|
||||
// import { useSettingsStore } from '~/stores/settingsStore';
|
||||
|
||||
export interface Props {
|
||||
card_id: number | undefined
|
||||
@@ -32,10 +32,10 @@ function cardClick() {
|
||||
const rotation = ref(0)
|
||||
|
||||
function mouseenter(e: Event) {
|
||||
goStore.hoveredCard = props.card_id
|
||||
// goStore.hoveredCard = props.card_id
|
||||
}
|
||||
function mouseleave(e: Event) {
|
||||
goStore.hoveredCard = undefined
|
||||
// goStore.hoveredCard = undefined
|
||||
}
|
||||
|
||||
watch(
|
||||
|
||||
+48
-37
@@ -1,61 +1,72 @@
|
||||
export default defineNuxtRouteMiddleware
|
||||
(async (to, from) => {
|
||||
if (to.path == '/login') {
|
||||
return
|
||||
}
|
||||
import { useAuthStore } from "#imports";
|
||||
|
||||
if (to.path == '/') {
|
||||
const code = to.query.code
|
||||
export default defineNuxtRouteMiddleware(async (to, from) => {
|
||||
const authStore = useAuthStore();
|
||||
if (to.path == "/login") {
|
||||
const code = to.query.code;
|
||||
if (code) {
|
||||
if (!Array.isArray(code)) {
|
||||
try {
|
||||
await oauth2_register_discord(code)
|
||||
return navigateTo('/lobby')
|
||||
await authStore.whoami();
|
||||
return navigateTo("/lobby");
|
||||
} catch {
|
||||
return navigateTo('/login')
|
||||
return navigateTo("/login");
|
||||
}
|
||||
} else {
|
||||
return navigateTo('/login')
|
||||
return navigateTo("/login");
|
||||
}
|
||||
}
|
||||
return navigateTo("/lobby")
|
||||
return navigateTo("/lobby");
|
||||
}
|
||||
|
||||
if (!goStore.discordId) {
|
||||
const heron_session = useCookie('heron_session')
|
||||
if (!heron_session.value) { return navigateTo('/login') }
|
||||
// if (to.path == '/') {
|
||||
// const code = to.query.code
|
||||
// if (code) {
|
||||
// if (!Array.isArray(code)) {
|
||||
// try {
|
||||
// await oauth2_register_discord(code)
|
||||
// return navigateTo('/lobby')
|
||||
// } catch {
|
||||
// return navigateTo('/login')
|
||||
// }
|
||||
// } else {
|
||||
// return navigateTo('/login')
|
||||
// }
|
||||
// }
|
||||
// return navigateTo("/lobby")
|
||||
// }
|
||||
|
||||
try {
|
||||
await heron_cookie_login(heron_session.value)
|
||||
if (to.path == '/') {
|
||||
return navigateTo("/lobby")
|
||||
}
|
||||
} catch {
|
||||
return navigateTo('/login')
|
||||
}
|
||||
}
|
||||
// if (!goStore.discordId) {
|
||||
// const heron_session = useCookie('heron_session')
|
||||
// if (!heron_session.value) { return navigateTo('/login') }
|
||||
|
||||
// try {
|
||||
// await heron_cookie_login(heron_session.value)
|
||||
// if (to.path == '/') {
|
||||
// return navigateTo("/lobby")
|
||||
// }
|
||||
// } catch {
|
||||
// return navigateTo('/login')
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
if (to.path.startsWith("/games")) {
|
||||
if (Array.isArray(to.params.id)) { return navigateTo('/lobby') }
|
||||
try {
|
||||
await join_game(to.params.id)
|
||||
return
|
||||
} catch {
|
||||
return navigateTo("/lobby")
|
||||
if (to.path.startsWith("/game")) {
|
||||
if (Array.isArray(to.params.id)) {
|
||||
return navigateTo("/lobby");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (to.path == "/lobby") {
|
||||
return
|
||||
return;
|
||||
}
|
||||
if (to.path == "/rules") {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// In a real app you would probably not redirect every route to `/`
|
||||
// however it is important to check `to.path` before redirecting or you
|
||||
// might get an infinite redirect loop
|
||||
if (to.path !== '/') {
|
||||
return navigateTo('/')
|
||||
if (to.path !== "/") {
|
||||
return navigateTo("/");
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import type { Game, User } from "./interfaces";
|
||||
|
||||
export function subscribe(endpoint: string) {
|
||||
const config = useRuntimeConfig();
|
||||
const evtSource = new EventSource(new URL(endpoint, config.public.endpoint), {
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
return evtSource;
|
||||
}
|
||||
|
||||
export async function getLobby() {
|
||||
const config = useRuntimeConfig();
|
||||
const req = await useFetch<Array<Game>>(
|
||||
new URL("/games", config.public.endpoint).href,
|
||||
{
|
||||
credentials: "include",
|
||||
}
|
||||
);
|
||||
if (req.data.value == null) {
|
||||
throw new Error("Lobby answer is empty");
|
||||
}
|
||||
return req.data as Ref<Game[]>;
|
||||
}
|
||||
|
||||
export async function whoami() {
|
||||
const config = useRuntimeConfig();
|
||||
const req = useFetch<User>(new URL("/whoami", config.public.endpoint).href, {
|
||||
credentials: "include",
|
||||
});
|
||||
if (
|
||||
req.error.value?.statusCode &&
|
||||
[401].includes(req.error.value.statusCode)
|
||||
) {
|
||||
await navigateTo(config.public.discordLoginEndpoint, {
|
||||
external: true,
|
||||
});
|
||||
throw new Error("You are not logged in");
|
||||
}
|
||||
if (req.error.value) {
|
||||
throw new Error(
|
||||
"Something went wrong while trying to get user information"
|
||||
);
|
||||
}
|
||||
return req.data;
|
||||
}
|
||||
|
||||
export function createGame() {}
|
||||
@@ -1,12 +0,0 @@
|
||||
import type { IGameObject } from "../interfaces/generic";
|
||||
|
||||
export abstract class GameObject implements IGameObject {
|
||||
static readonly instances = new Map<string, GameObject>()
|
||||
readonly uuid: string;
|
||||
readonly socket: WebSocket
|
||||
constructor(socket: WebSocket, { uuid }: { uuid: string }) {
|
||||
this.uuid = uuid
|
||||
this.socket = socket
|
||||
GameObject.instances.set(this.uuid, this)
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { GameObject } from "./GameObject";
|
||||
import type { ICLobby } from "../interfaces/client";
|
||||
|
||||
|
||||
|
||||
export class Lobby extends GameObject implements ICLobby {
|
||||
static instance: Lobby
|
||||
constructor(socket: WebSocket, data: { uuid: string, games: Array<string> }) {
|
||||
if (Lobby.instance) { return Lobby.instance }
|
||||
super(socket, data)
|
||||
Lobby.instance = this
|
||||
}
|
||||
|
||||
|
||||
onAddGame() {
|
||||
|
||||
}
|
||||
onRemoveGame() {
|
||||
|
||||
}
|
||||
|
||||
async request_createGame() {
|
||||
throw Error("not implemented")
|
||||
}
|
||||
|
||||
removeGame() {
|
||||
throw Error("not implemented")
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,66 @@
|
||||
<script setup lang="ts">
|
||||
import goStore, { setReady } from '../../netcode';
|
||||
import type { Player } from '../../netcode/Player';
|
||||
import { playSound } from '../../helpers/audioHelpers';
|
||||
import { CardType, type Card } from '../../netcode/Card';
|
||||
import { CardEffects, type Effect } from '../../netcode/Effect';
|
||||
import type { Team } from '~/netcode/Team';
|
||||
import { subscribe } from '~/netcode';
|
||||
import { type Game } from '~/netcode/interfaces';
|
||||
|
||||
const current_players = computed<Array<Player>>(() => Array.from(goStore.current_game?.players ?? []).filter(p => p.team === goStore.current_game?.current_turn))
|
||||
|
||||
watch(
|
||||
() => goStore.current_game?.current_turn?.uuid,
|
||||
() => {
|
||||
if (goStore.current_game?.current_turn?.uuid == goStore.self?.team?.uuid) {
|
||||
playSound('/sounds/ding.mp3')
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
const route = useRoute()
|
||||
const gameId = route.params.id
|
||||
|
||||
const { data: game, pending, error, refresh } = await useFetch<Game>(
|
||||
new URL(`/games/${gameId}`, config.public.endpoint).href,
|
||||
{
|
||||
credentials: "include",
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
watch(
|
||||
() => goStore.current_game?.losers,
|
||||
() => {
|
||||
if (goStore.self?.uuid && goStore.current_game?.losers && goStore.current_game.losers.includes(goStore.self.uuid)) {
|
||||
showLoserScreen()
|
||||
}
|
||||
})
|
||||
const eventSource = subscribe(`/games/${gameId}/subscribe`)
|
||||
|
||||
watch(
|
||||
() => goStore.current_game?.ended,
|
||||
() => {
|
||||
if (goStore.current_game?.ended && goStore.self?.uuid && goStore.current_game?.losers && !goStore.current_game.losers.includes(goStore.self.uuid)) {
|
||||
showWinnerScreen()
|
||||
}
|
||||
})
|
||||
eventSource.addEventListener("message", (message) => {
|
||||
const data = JSON.parse(message.data)
|
||||
});
|
||||
|
||||
watch(
|
||||
() => goStore.current_game?.players,
|
||||
(newList, oldList) => {
|
||||
if (!oldList || !newList) { return }
|
||||
if (goStore.current_game?.started) { return }
|
||||
if (newList?.length > oldList.length) {
|
||||
playSound('/sounds/teleport.mp3')
|
||||
}
|
||||
const authStore = useAuthStore()
|
||||
|
||||
})
|
||||
|
||||
// const current_players = computed<Array<Player>>(() => Array.from(goStore.current_game?.players ?? []).filter(p => p.team === goStore.current_game?.current_turn))
|
||||
|
||||
// watch(
|
||||
// () => goStore.current_game?.current_turn?.uuid,
|
||||
// () => {
|
||||
// if (goStore.current_game?.current_turn?.uuid == goStore.self?.team?.uuid) {
|
||||
// playSound('/sounds/ding.mp3')
|
||||
// }
|
||||
// })
|
||||
|
||||
// watch(
|
||||
// () => goStore.current_game?.losers,
|
||||
// () => {
|
||||
// if (goStore.self?.uuid && goStore.current_game?.losers && goStore.current_game.losers.includes(goStore.self.uuid)) {
|
||||
// showLoserScreen()
|
||||
// }
|
||||
// })
|
||||
|
||||
// watch(
|
||||
// () => goStore.current_game?.ended,
|
||||
// () => {
|
||||
// if (goStore.current_game?.ended && goStore.self?.uuid && goStore.current_game?.losers && !goStore.current_game.losers.includes(goStore.self.uuid)) {
|
||||
// showWinnerScreen()
|
||||
// }
|
||||
// })
|
||||
|
||||
// watch(
|
||||
// () => goStore.current_game?.players,
|
||||
// (newList, oldList) => {
|
||||
// if (!oldList || !newList) { return }
|
||||
// if (goStore.current_game?.started) { return }
|
||||
// if (newList?.length > oldList.length) {
|
||||
// playSound('/sounds/teleport.mp3')
|
||||
// }
|
||||
|
||||
// })
|
||||
|
||||
const showResults = ref(false)
|
||||
const showOptions = ref(false)
|
||||
@@ -60,24 +79,24 @@ function showWinnerScreen() {
|
||||
}
|
||||
|
||||
const discard_unwrapped = ref(false)
|
||||
const focusedPlayer = ref<Player>((goStore.current_game?.players.find(p => p.team == goStore.current_game?.current_turn) ?? goStore.current_game?.players[0])!)
|
||||
const clientStore = useClientSideStore()
|
||||
const restack_discarded_champion = (target: Card) => clientStore.findUseEffect(CardEffects.RESTACK_DISCARDED_CHAMPION, target)
|
||||
const restack_discarded_card = (target: Card) => clientStore.findUseEffect(CardEffects.RESTACK_DISCARDED_CARD, target)
|
||||
const sacrifice = (target: Card) => clientStore.findUseEffect(CardEffects.SACRIFICE, target);
|
||||
// const focusedPlayer = ref<Player>((goStore.current_game?.players.find(p => p.team == goStore.current_game?.current_turn) ?? goStore.current_game?.players[0])!)
|
||||
// const clientStore = useClientSideStore()
|
||||
// const restack_discarded_champion = (target: Card) => clientStore.findUseEffect(CardEffects.RESTACK_DISCARDED_CHAMPION, target)
|
||||
// const restack_discarded_card = (target: Card) => clientStore.findUseEffect(CardEffects.RESTACK_DISCARDED_CARD, target)
|
||||
// const sacrifice = (target: Card) => clientStore.findUseEffect(CardEffects.SACRIFICE, target);
|
||||
|
||||
function focusPlayer(p: Player) {
|
||||
focusedPlayer.value = p
|
||||
}
|
||||
// function focusPlayer(p: Player) {
|
||||
// focusedPlayer.value = p
|
||||
// }
|
||||
|
||||
watch<Team>(() => goStore.current_game!.current_turn, (new_team, old_team) => {
|
||||
if (focusedPlayer.value.team != old_team) { return }
|
||||
const first_player = goStore.current_game?.players.find(p => p.team == goStore.current_game?.current_turn)
|
||||
if (!first_player) {
|
||||
return
|
||||
}
|
||||
focusPlayer(first_player)
|
||||
})
|
||||
// watch<Team>(() => goStore.current_game!.current_turn, (new_team, old_team) => {
|
||||
// if (focusedPlayer.value.team != old_team) { return }
|
||||
// const first_player = goStore.current_game?.players.find(p => p.team == goStore.current_game?.current_turn)
|
||||
// if (!first_player) {
|
||||
// return
|
||||
// }
|
||||
// focusPlayer(first_player)
|
||||
// })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -85,7 +104,7 @@ watch<Team>(() => goStore.current_game!.current_turn, (new_team, old_team) => {
|
||||
<AnimatedBackground></AnimatedBackground>
|
||||
<div id="game_status">
|
||||
|
||||
<template v-if="goStore.self && !goStore.current_game?.started">
|
||||
<template v-if="authStore.logged && game?.started">
|
||||
<input @click.prevent="setReady(($event.target as HTMLInputElement).checked)" type="checkbox" id="ready"
|
||||
:checked="goStore.self?.ready" />
|
||||
<label for="ready">Ready</label>
|
||||
@@ -110,7 +129,7 @@ watch<Team>(() => goStore.current_game!.current_turn, (new_team, old_team) => {
|
||||
<CardPreview :tilted="false" v-if="discard_unwrapped" :card_id="c.card_id"
|
||||
v-for="c in p.discard_pile">
|
||||
<template
|
||||
v-if="goStore.self?.turn && c && p == goStore.self && goStore.current_game?.current_turn == goStore.self.team">
|
||||
v-if="goStore.self?.turn && c && p == goStore.self && game.current_turn == goStore.self.team">
|
||||
<button
|
||||
v-if="clientStore.activatedClientside.find((e: Effect) => (e.effect == CardEffects.SACRIFICE) && e.usable)"
|
||||
@click.stop="sacrifice(c)">
|
||||
@@ -139,7 +158,7 @@ watch<Team>(() => goStore.current_game!.current_turn, (new_team, old_team) => {
|
||||
|
||||
<div id="player_list_container">
|
||||
<div id="player_list">
|
||||
<PlayerListElement v-for="p in goStore.current_game?.players" :player="p" @click="focusPlayer(p)"
|
||||
<PlayerListElement v-for="p in game.players" :player="p" @click="focusPlayer(p)"
|
||||
:focused="focusedPlayer">
|
||||
</PlayerListElement>
|
||||
</div>
|
||||
@@ -153,8 +172,7 @@ watch<Team>(() => goStore.current_game!.current_turn, (new_team, old_team) => {
|
||||
|
||||
|
||||
</div>
|
||||
<ResultDialog :isVisible="showResults" :won="isWinner" :players="goStore.current_game?.players"
|
||||
@close="showResults = false">
|
||||
<ResultDialog :isVisible="showResults" :won="isWinner" :players="game.players" @close="showResults = false">
|
||||
</ResultDialog>
|
||||
<GlobalOverlay></GlobalOverlay>
|
||||
<SelfView></SelfView>
|
||||
+63
-41
@@ -1,23 +1,46 @@
|
||||
<script setup lang="ts">
|
||||
import goStore, { netcode_create_game, join_game } from '~/netcode';
|
||||
import { playSound } from '~/helpers/audioHelpers';
|
||||
import { ref } from 'vue';
|
||||
// import { playSound } from '~/helpers/audioHelpers';
|
||||
import { playSound } from "~/helpers/audioHelpers";
|
||||
import { createGame, getLobby, subscribe } from "~/netcode"
|
||||
import type { Player } from "~/netcode/interfaces";
|
||||
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const games = await getLobby()
|
||||
|
||||
const eventSource = subscribe("/games/subscribe")
|
||||
|
||||
eventSource.addEventListener("message", (message) => {
|
||||
const data = JSON.parse(message.data)
|
||||
if (data.type == "create") {
|
||||
games.value.push(data)
|
||||
} else if (data.type == "delete") {
|
||||
const index = games.value.findIndex(g => g._id == data._id)
|
||||
if (index == -1) {
|
||||
throw new Error("Couldn't delete game")
|
||||
}
|
||||
games.value.splice(index, 1)
|
||||
} else if (data.type == "update") {
|
||||
throw new Error("not implemented")
|
||||
} else if (data.type == "start") {
|
||||
throw new Error("not implemented")
|
||||
}
|
||||
});
|
||||
|
||||
const erika_alive = ref(true);
|
||||
const router = useRouter();
|
||||
|
||||
|
||||
|
||||
function killErika() {
|
||||
playSound('/sounds/splat1.mp3')
|
||||
erika_alive.value = false;
|
||||
}
|
||||
|
||||
// Autojoin broken
|
||||
// watch(() => goStore.context, () => {
|
||||
// console.log(goStore.context)
|
||||
// if (goStore.context == "pregame") {
|
||||
// router.push(`/games/${goStore.current_game?.uuid}`)
|
||||
// }
|
||||
// })
|
||||
onUnmounted(() => {
|
||||
eventSource.close()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -29,35 +52,34 @@ function killErika() {
|
||||
|
||||
<div class="middle-row">
|
||||
<div class="create-game-zone">
|
||||
<button @click="netcode_create_game">Create Game</button>
|
||||
<button @click="createGame">Create Game</button>
|
||||
</div>
|
||||
|
||||
<div class="games-list-zone">
|
||||
<div v-for="g in goStore.lobby?.games">
|
||||
<button v-if="g" @click="router.push({ path: `/games/${g.uuid}` })"
|
||||
:class="goStore.discordId == g.owner ? 'own_game' : ''">
|
||||
<div v-for="g in games">
|
||||
<button v-if="g" @click="router.push({ path: `/game/${g._id}` })"
|
||||
:class="authStore.selfUser.userId == g.owner.userId ? 'own_game' : ''">
|
||||
<template v-if="g.started && g.ended">
|
||||
GAME OVER
|
||||
</template>
|
||||
<template v-if="g.players.every(p => p.discord_id !== goStore.discordId)">
|
||||
<template v-if="!g.started">
|
||||
JOIN
|
||||
</template>
|
||||
<template v-if="g.started && !g.ended">
|
||||
<template
|
||||
v-else-if="g.teams.every(t => t.players.every(p => p.user.userId !== authStore.selfUser.userId))">
|
||||
SPECTATE
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="g.players.some(p => p.discord_id == goStore.discordId)">
|
||||
<template v-else>
|
||||
<template v-if="!g.started">
|
||||
JOIN BACK
|
||||
</template>
|
||||
<template v-if="g.started && !g.ended">
|
||||
<template v-else>
|
||||
CONTINUE
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<br>
|
||||
{{ g.players.length }} current players:<br><span>{{ g.players.map(p => p.username).join(",")
|
||||
{{ g.teams.reduce((prev, curr) => prev.concat(curr.players), [] as Player[]).length }} current
|
||||
players:<br><span>{{
|
||||
g.teams.reduce((prev, curr) => prev.concat(curr.players), [] as Player[]).map(p =>
|
||||
p.user.username).join(",")
|
||||
}}</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -83,7 +105,6 @@ function killErika() {
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -120,7 +141,9 @@ function killErika() {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
button {
|
||||
}
|
||||
|
||||
.create-game-zone button {
|
||||
background-color: #4CAF50;
|
||||
border: none;
|
||||
color: white;
|
||||
@@ -138,7 +161,6 @@ function killErika() {
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.games-list-zone {
|
||||
@@ -146,7 +168,10 @@ function killErika() {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
|
||||
button {
|
||||
|
||||
}
|
||||
|
||||
.games-list-zone button {
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
border: none;
|
||||
color: white;
|
||||
@@ -164,11 +189,10 @@ function killErika() {
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
button.own_game {
|
||||
.games-list-zone button.own_game {
|
||||
border: solid yellow 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
@@ -187,22 +211,26 @@ function killErika() {
|
||||
height: 40%;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.overlay-image {
|
||||
.overlay-image {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
.overlay-button {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 300px;
|
||||
box-sizing: border-box;
|
||||
pointer-events: none;
|
||||
|
||||
.kill-erika-button {
|
||||
|
||||
}
|
||||
|
||||
.kill-erika-button {
|
||||
display: none;
|
||||
pointer-events: all;
|
||||
background-color: #f44336;
|
||||
@@ -220,8 +248,6 @@ function killErika() {
|
||||
transition-duration: 0.4s;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.speech-bubble {
|
||||
@@ -241,11 +267,7 @@ function killErika() {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.erika-zone:hover {
|
||||
.overlay-button {
|
||||
.kill-erika-button {
|
||||
.erika-zone:hover .overlay-button .kill-erika-button {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { navigateTo, useRuntimeConfig } from 'nuxt/app';
|
||||
import goStore, { netcode_create_game, join_game } from '../netcode';
|
||||
// import { navigateTo, useRuntimeConfig } from 'nuxt/app';
|
||||
// import goStore, { netcode_create_game, join_game } from '../netcode';
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
@@ -24,15 +24,15 @@ async function discordLogin() {
|
||||
<CardPreview :card_id="undefined"></CardPreview>
|
||||
</div>
|
||||
|
||||
<div v-if="goStore.current_game?.started">
|
||||
<!-- <div v-if="goStore.current_game?.started">
|
||||
<b>Mode spectateur</b>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<template v-if="!goStore.current_game?.started">
|
||||
<!-- <template v-if="!goStore.current_game?.started"> -->
|
||||
<!-- <input type="text" v-model="username" />
|
||||
<button @click="register(username)">LOGIN</button> -->
|
||||
<button class="menu-button" @click="discordLogin()">Se connecter via Discord</button>
|
||||
</template>
|
||||
<!-- <button class="menu-button" @click="discordLogin()">Se connecter via Discord</button>
|
||||
</template> -->
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
|
||||
+9
-8
@@ -1,7 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import type { Card } from '~/netcode/Card';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
</script>
|
||||
@@ -10,7 +7,7 @@ const router = useRouter();
|
||||
<div class="background">
|
||||
<div class="overlay-2">
|
||||
<div class="erika-zone-2">
|
||||
<img @click="router.push({ path: '/' })" class="overlay-image"
|
||||
<img @click="router.push({ path: '/lobby' })" class="overlay-image"
|
||||
src="https://static.wikia.nocookie.net/umineko/images/9/9d/PC_Erika.Casual.Sprite_36.png"
|
||||
alt="pétasse" />
|
||||
</div>
|
||||
@@ -298,7 +295,10 @@ const router = useRouter();
|
||||
top: 0;
|
||||
pointer-events: none;
|
||||
|
||||
.erika-zone-2 {
|
||||
|
||||
}
|
||||
|
||||
.erika-zone-2 {
|
||||
position: absolute;
|
||||
top: 300px;
|
||||
display: flex;
|
||||
@@ -308,12 +308,13 @@ const router = useRouter();
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
|
||||
.overlay-image {
|
||||
|
||||
}
|
||||
|
||||
.overlay-image {
|
||||
position: sticky;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,33 +0,0 @@
|
||||
import path from "path"
|
||||
import type { IUser } from "~/netcode/interfaces"
|
||||
|
||||
|
||||
enum HTTPMethods {
|
||||
GET = "GET",
|
||||
POST = "POST"
|
||||
}
|
||||
|
||||
|
||||
const Endpoints = {
|
||||
LOGIN: { url: "/login", method: HTTPMethods.POST, body: null }
|
||||
} as const
|
||||
|
||||
type ReturnTypes = {
|
||||
LOGIN: IUser
|
||||
}
|
||||
|
||||
|
||||
type EnpointsNames = keyof typeof Endpoints
|
||||
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
|
||||
export default async function api<T extends EnpointsNames>(target: T, body?: typeof Endpoints[T]["body"]): Promise<ReturnTypes[T]> {
|
||||
const data = await fetch(path.join(config.public.endpoint, Endpoints[target].url), {
|
||||
credentials: "same-origin",
|
||||
mode: "same-origin",
|
||||
method: Endpoints[target].method,
|
||||
body,
|
||||
})
|
||||
return await data.json() as ReturnTypes[T]
|
||||
}
|
||||
+10
-10
@@ -1,19 +1,19 @@
|
||||
import path from "path";
|
||||
import { defineStore } from "pinia";
|
||||
import api from "~/services";
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
import { whoami } from "~/netcode";
|
||||
|
||||
export const useAuthStore = defineStore("auth", {
|
||||
state: () => ({
|
||||
self: { id: 0, image: "" }
|
||||
selfUser: {} as { userId?: string; image?: string; username?: string },
|
||||
logged: false,
|
||||
}),
|
||||
actions: {
|
||||
login: async () => {
|
||||
await api("LOGIN")
|
||||
async whoami() {
|
||||
const data = await whoami();
|
||||
Object.assign(this.selfUser, data.value);
|
||||
this.logged = true;
|
||||
},
|
||||
oauth2_register_discord: () => {
|
||||
throw Error("not implemented")
|
||||
}
|
||||
}
|
||||
throw Error("not implemented");
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user