Skip to content

Commit

Permalink
Broadcast game
Browse files Browse the repository at this point in the history
  • Loading branch information
magnetenstad committed Jan 30, 2024
1 parent e3cd31d commit 15f12ed
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 285 deletions.
389 changes: 134 additions & 255 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
},
"dependencies": {
"@formkit/auto-animate": "^0.8.0",
"@supabase/supabase-js": "^2.36.0",
"@supabase/supabase-js": "^2.39.3",
"@types/node": "^20.7.1",
"chart.js": "^4.4.0",
"chartjs-adapter-date-fns": "^3.0.0",
"date-fns": "^2.30.0",
"mobile-drag-drop": "^3.0.0-rc.0",
"nanoid": "^5.0.1",
"pinia": "^2.1.6",
"vue": "^3.3.4",
"vue": "^3.4.15",
"vue-router": "^4.2.5"
},
"devDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions src/stores/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '@/types/game'
import { acceptHMRUpdate, defineStore } from 'pinia'
import { useEloStore } from './elo'
import { useOnlineStore } from './online'
import { upsertLegStatistics, useStatsStore } from './stats'
import { useUsersStore } from './users'

Expand Down Expand Up @@ -49,6 +50,7 @@ export const useGameStore = defineStore('game', {
this.gameState = this.getController().getGameState()
if (this.game) {
this.game.result = this.gameState.rank
useOnlineStore().sendGame(this.game)
}
this.tryPlayWalkOn()
return this.gameState
Expand Down
67 changes: 50 additions & 17 deletions src/stores/online.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { supabase } from '@/supabase'
import { Game } from '@/types/game'
import { RealtimeChannel } from '@supabase/supabase-js'
import { acceptHMRUpdate, defineStore } from 'pinia'

type OnlinePresence = {
Expand All @@ -8,38 +10,69 @@ type OnlinePresence = {
}

export const useOnlineStore = defineStore('online', {
state: () => {
const room = supabase.channel('online')

return {
room,
presences: [] as OnlinePresence[],
spectating: null as string | null,
presence: {} as Partial<OnlinePresence>,
}
},
state: () => ({
presences: [] as OnlinePresence[],
spectating: null as string | null,
spectatingGame: null as Game | null,
presence: {
inGame: false,
date: new Date(),
} as Partial<OnlinePresence>,
room: null as RealtimeChannel | null,
inChannel: null as RealtimeChannel | null,
outChannel: null as RealtimeChannel | null,
}),

actions: {
initRoom(userId: string) {
async initRoom(userId: string) {
await supabase.removeAllChannels()

this.room = supabase.channel('online')
this.room
.on('presence', { event: 'sync' }, () => {
const state = this.room.presenceState()
const state = this.room?.presenceState()
// @ts-ignore
this.presences = Object.values(state).flat()
})
.subscribe(async (status) => {
if (status !== 'SUBSCRIBED') {
return
}

if (status !== 'SUBSCRIBED') return
this.sendUpdate({ userId })
})

this.outChannel = supabase.channel(`game-${userId}`).subscribe()
},

async sendUpdate(presence: Partial<OnlinePresence>) {
this.presence = { ...this.presence, ...presence }
if (!this.presence.userId) return
await this.room.track(this.presence)
await this.room?.track(presence)
},

async startSpectating(userId: string) {
this.spectating = userId
await this.inChannel?.unsubscribe()
this.inChannel = supabase
.channel(`game-${this.spectating}`)
.on('broadcast', { event: 'game' }, (game) => {
// @ts-ignore
this.spectatingGame = game as Game
})
.subscribe()
},

async stopSpectating() {
await this.inChannel?.unsubscribe()
this.inChannel = null
this.spectating = null
this.spectatingGame = null
},

sendGame(game: Game) {
this.outChannel?.send({
type: 'broadcast',
event: 'game',
payload: game,
})
},
},

Expand Down
19 changes: 15 additions & 4 deletions src/views/GameView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ import Youtube from '@/components/Youtube.vue'
import { speak } from '@/functions/speak'
import { getGameDisplayName, getInputComponent } from '@/games/games'
import { router } from '@/router'
import { useAuthStore } from '@/stores/auth'
import { useEloStore } from '@/stores/elo'
import { useGameStore } from '@/stores/game'
import { useLoadingStore } from '@/stores/loading'
Expand All @@ -120,6 +121,7 @@ const gameStore = useGameStore()
const usersStore = useUsersStore()
const loadingStore = useLoadingStore()
const onlineStore = useOnlineStore()
const authStore = useAuthStore()

const eloDeltas = ref<{ userId: string; eloDelta: number }[]>([])

Expand Down Expand Up @@ -149,14 +151,23 @@ const displayVisit = computed(() => {
return { visit: visit ?? [null, null, null], isPrev: false }
})

onMounted(() => {
onMounted(async () => {
if (!gameStore.game) {
quit()
}
onlineStore.sendUpdate({ inGame: true })
await onlineStore.sendUpdate({
inGame: true,
userId: authStore.auth?.id,
date: new Date(),
})
})
onUnmounted(() => {
onlineStore.sendUpdate({ inGame: false })

onUnmounted(async () => {
await onlineStore.sendUpdate({
inGame: false,
userId: authStore.auth?.id,
date: new Date(),
})
})

const quit = () => {
Expand Down
12 changes: 6 additions & 6 deletions src/views/SpectateLobbyView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@
<button
v-for="presence in onlineStore.presences"
:disabled="presence.userId == useAuthStore().auth?.id"
@click="
() => {
onlineStore.spectating = presence.userId
router.push({ name: 'spectate' })
}
"
@click="spectate(presence.userId)"
>
{{ useUsersStore().getUser(presence.userId)?.name }}
</button>
Expand All @@ -23,4 +18,9 @@ import { useOnlineStore } from '@/stores/online'
import { useUsersStore } from '@/stores/users'
const onlineStore = useOnlineStore()
const spectate = async (userId: string) => {
await onlineStore.startSpectating(userId)
router.push({ name: 'spectate' })
}
</script>
8 changes: 7 additions & 1 deletion src/views/SpectateView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@

<p v-if="onlineStore.getSpectating.inGame">{{ name }} is in game.</p>
<p v-else>{{ name }} is not in game.</p>

{{ onlineStore.spectatingGame }}
</template>
</template>

<script lang="ts" setup>
import { router } from '@/router'
import { useOnlineStore } from '@/stores/online'
import { useUsersStore } from '@/stores/users'
import { computed, watch } from 'vue'
import { computed, onUnmounted, watch } from 'vue'
const onlineStore = useOnlineStore()
Expand All @@ -32,4 +34,8 @@ watch(
},
{ immediate: true }
)
onUnmounted(() => {
onlineStore.stopSpectating()
})
</script>

0 comments on commit 15f12ed

Please sign in to comment.