103 lines
2.4 KiB
Vue
103 lines
2.4 KiB
Vue
<script lang="ts">
|
|
import { defineComponent, PropType } from 'vue';
|
|
|
|
interface Player {
|
|
id: number,
|
|
name: string
|
|
}
|
|
|
|
interface Model {
|
|
yourId: number,
|
|
players: Player[]
|
|
}
|
|
|
|
function getPlayer(model: Model, id: number): Player | undefined {
|
|
return model.players.find(player => player.id === id)
|
|
}
|
|
|
|
/*
|
|
Handles all game business. Sends (local) player input to the server for distribution.
|
|
Receives player input from the server and manages state accordingly.
|
|
*/
|
|
export default defineComponent({
|
|
props: {
|
|
ws: { type: WebSocket, required: true },
|
|
model: { type: Object as PropType<Model>, required: true }
|
|
},
|
|
data() {
|
|
return {
|
|
chatMessages: [] as string[],
|
|
|
|
playerName: '',
|
|
chatMessage: ''
|
|
}
|
|
},
|
|
created() {
|
|
this.ws.addEventListener('message', (ev) => {
|
|
const message = JSON.parse(ev.data)
|
|
const payload = message.payload
|
|
console.log(`Message from player ${message.from}:`)
|
|
console.log(payload)
|
|
|
|
switch (payload.type) {
|
|
case 'join':
|
|
this.model.players.push({
|
|
id: message.from,
|
|
name: ''
|
|
})
|
|
break
|
|
case 'leave':
|
|
this.model.players = this.model.players.filter(player => player.id !== message.from)
|
|
break
|
|
case 'chat':
|
|
this.chatMessages.push(payload.message)
|
|
break
|
|
case 'set-name':
|
|
getPlayer(this.model, message.from)!.name = payload.name
|
|
break
|
|
}
|
|
})
|
|
},
|
|
methods: {
|
|
setName() {
|
|
this.ws.send(JSON.stringify({
|
|
type: 'set-name',
|
|
name: this.playerName
|
|
}))
|
|
},
|
|
sendChat() {
|
|
if (this.chatMessage === '') {
|
|
return
|
|
}
|
|
|
|
this.ws.send(JSON.stringify({
|
|
type: 'chat',
|
|
message: this.chatMessage
|
|
}))
|
|
this.chatMessage = ''
|
|
}
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<pre>{{ JSON.stringify(model, null, 2) }}</pre>
|
|
<h1>I am #{{ model.yourId }}</h1>
|
|
<form @submit.prevent="setName">
|
|
<input v-model="playerName" placeholder="enter your name...">
|
|
<button >set name</button>
|
|
</form>
|
|
<form @submit.prevent="sendChat">
|
|
<input v-model="chatMessage">
|
|
<button>Post</button>
|
|
</form>
|
|
<h2>players</h2>
|
|
<ul v-if="model">
|
|
<li v-for="player in model.players" :key="player.id">{{ player.name }}#{{ player.id }}</li>
|
|
</ul>
|
|
<h2>chat</h2>
|
|
<ul v-if="model">
|
|
<li v-for="message in chatMessages">{{ message }}</li>
|
|
</ul>
|
|
</template>
|