Add Lobby #43
7 changed files with 106 additions and 67 deletions
|
@ -1,10 +1,7 @@
|
|||
import {
|
||||
PeerMetadata,
|
||||
NetworkMessage,
|
||||
PasswordResponse,
|
||||
RoomInfo
|
||||
} from "./types";
|
||||
import EventEmitter from "eventemitter3";
|
||||
import Vue from "vue";
|
||||
|
||||
import { NetworkMessage, PasswordResponse, PeerMetadata, RoomInfo } from "./types";
|
||||
|
||||
export abstract class Client extends EventEmitter {
|
||||
public metadata: PeerMetadata;
|
||||
|
@ -30,7 +27,8 @@ export abstract class Client extends EventEmitter {
|
|||
if (data.oldname == this.metadata.name) {
|
||||
// We got a name change!
|
||||
this.metadata.name = data.newname;
|
||||
} else {
|
||||
}
|
||||
|
||||
let idx = this.players.indexOf(data.oldname);
|
||||
if (idx < 0) {
|
||||
// Weird
|
||||
|
@ -40,8 +38,7 @@ export abstract class Client extends EventEmitter {
|
|||
this.players.push(data.newname);
|
||||
break;
|
||||
}
|
||||
this.players[idx] = data.newname;
|
||||
}
|
||||
Vue.set(this.players, idx, data.newname);
|
||||
this.emit("rename", data.oldname, data.newname);
|
||||
break;
|
||||
// A new player joined the room (this includes us)
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
import EventEmitter from "eventemitter3";
|
||||
import Peer, { DataConnection } from "peerjs";
|
||||
|
||||
import { LocalClient } from ".";
|
||||
import {
|
||||
RoomInfo,
|
||||
PasswordRequest,
|
||||
Room,
|
||||
AckMessage,
|
||||
ChatMessage,
|
||||
ErrorMessage,
|
||||
JoinMessage,
|
||||
LeaveMessage,
|
||||
NetworkMessage,
|
||||
NetworkPlayer,
|
||||
PasswordRequest,
|
||||
PasswordResponse,
|
||||
PeerMetadata,
|
||||
JoinMessage,
|
||||
RoomInfoMessage,
|
||||
Player,
|
||||
NetworkMessage,
|
||||
RenameMessage,
|
||||
LeaveMessage,
|
||||
NetworkPlayer,
|
||||
AckMessage,
|
||||
ChatMessage
|
||||
Room,
|
||||
RoomInfo,
|
||||
RoomInfoMessage,
|
||||
} from "./types";
|
||||
import { LocalClient } from ".";
|
||||
import EventEmitter from "eventemitter3";
|
||||
|
||||
// Increment name, add number at the end if not present
|
||||
// Examples:
|
||||
|
@ -212,16 +213,30 @@ export class PeerServer extends EventEmitter {
|
|||
this.broadcast(data);
|
||||
} else {
|
||||
// Player is telling someone specifically
|
||||
if (data.to in this.players) {
|
||||
this.send<ChatMessage>(this.players[data.to], data);
|
||||
} else {
|
||||
if (!(data.to in this.players)) {
|
||||
this.send<ErrorMessage>(player, {
|
||||
kind: "error",
|
||||
error: `player not found: ${data.to}`
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.send<ChatMessage>(this.players[data.to], data);
|
||||
}
|
||||
break;
|
||||
// Player wants to change name
|
||||
case "rename":
|
||||
// Make sure new name is valid
|
||||
data.oldname = player.name;
|
||||
if (data.newname in this.players) {
|
||||
this.send<ErrorMessage>(player, {
|
||||
kind: "error",
|
||||
error: "name not available"
|
||||
});
|
||||
return;
|
||||
}
|
||||
player.name = data.newname;
|
||||
this.broadcast<RenameMessage>(data);
|
||||
break;
|
||||
// Player is leaving!
|
||||
case "leave-req":
|
||||
// If we're leaving, end the server
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
import { ChatMessage, Client, LocalClient, NetworkMessage, PeerClient, PeerServer } from "@/network";
|
||||
import { ActionTree, Commit } from "vuex";
|
||||
|
||||
import { AppState } from "../types";
|
||||
import { NetworkState, StartServerOptions, ConnectOptions } from "./types";
|
||||
import {
|
||||
PeerServer,
|
||||
LocalClient,
|
||||
PeerClient,
|
||||
NetworkMessage,
|
||||
Client,
|
||||
ChatMessage
|
||||
} from "@/network";
|
||||
import { ConnectOptions, NetworkState, StartServerOptions } from "./types";
|
||||
|
||||
function bindClientEvents(commit: Commit, client: Client) {
|
||||
client.on("handshake", () => {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { Client } from "@/network";
|
||||
import { GetterTree } from "vuex";
|
||||
|
||||
import { AppState } from "../types";
|
||||
import { NetworkState } from "./types";
|
||||
import { Client } from "@/network";
|
||||
|
||||
const getters: GetterTree<NetworkState, AppState> = {
|
||||
peerID(state): string | null {
|
||||
|
@ -32,6 +33,15 @@ const getters: GetterTree<NetworkState, AppState> = {
|
|||
return state.peerType;
|
||||
},
|
||||
|
||||
busy(state): boolean {
|
||||
if (state.peerType == "client") {
|
||||
if (state.connectionStatus == "connecting") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
inRoom(state): boolean {
|
||||
if (state.peerType == "client") {
|
||||
return state.connectionStatus == "connected";
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { ChatMessage, LocalClient, PeerClient, PeerServer } from "@/network";
|
||||
import Vue from "vue";
|
||||
import { MutationTree } from "vuex";
|
||||
|
||||
import { ClientNetworkState, ConnectionStatus, NetworkState, ServerNetworkState } from "./types";
|
||||
|
@ -36,7 +37,7 @@ const mutations: MutationTree<NetworkState> = {
|
|||
},
|
||||
|
||||
playerListChanged(state, players: string[]) {
|
||||
state.players = players;
|
||||
Vue.set(state, "players", players);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
import {
|
||||
PeerClient,
|
||||
PeerServer,
|
||||
LocalClient,
|
||||
RoomInfo,
|
||||
PeerMetadata,
|
||||
ChatMessage
|
||||
} from "@/network";
|
||||
import { ChatMessage, LocalClient, PeerClient, PeerMetadata, PeerServer, RoomInfo } from "@/network";
|
||||
import Peer from "peerjs";
|
||||
|
||||
export type ConnectionStatus =
|
||||
|
|
|
@ -93,6 +93,14 @@
|
|||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="player-options">
|
||||
<b-field label="Change name">
|
||||
<b-input :disabled="busy" v-model="wantedName"></b-input>
|
||||
</b-field>
|
||||
<b-button @click="changeName" :disabled="!nameAvailable"
|
||||
>Change name</b-button
|
||||
>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</template>
|
||||
|
@ -211,7 +219,9 @@ import { Component, Vue } from "vue-property-decorator";
|
|||
import TopNav from "@/components/Navigation/TopNav.vue";
|
||||
import { StartServerOptions, ConnectOptions } from "@/store/network/types";
|
||||
import { Action, Getter } from "vuex-class";
|
||||
import { Client } from "@/network";
|
||||
import { Client, NetworkMessage } from "@/network";
|
||||
|
||||
const networkNS = { namespace: "network" };
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -223,34 +233,41 @@ export default class Lobby extends Vue {
|
|||
private hostMaxPlayers!: number;
|
||||
private hostPassword!: string;
|
||||
private joinSessionID!: string;
|
||||
private busy!: boolean;
|
||||
private wantedName!: string;
|
||||
|
||||
@Action("startServer", { namespace: "network" })
|
||||
@Action("startServer", networkNS)
|
||||
private startServer!: (options: StartServerOptions) => void;
|
||||
|
||||
@Action("connect", { namespace: "network" })
|
||||
@Action("sendMessage", networkNS)
|
||||
private sendMessage!: (message: NetworkMessage) => void;
|
||||
|
||||
@Action("connect", networkNS)
|
||||
private connect!: (options: ConnectOptions) => void;
|
||||
|
||||
@Getter("inRoom", { namespace: "network" })
|
||||
@Getter("inRoom", networkNS)
|
||||
private inRoom!: boolean;
|
||||
|
||||
@Getter("sessionID", { namespace: "network" })
|
||||
@Getter("busy", networkNS)
|
||||
private busy!: boolean;
|
||||
|
||||
@Getter("sessionID", networkNS)
|
||||
private sessionID!: string | null;
|
||||
|
||||
@Getter("players", { namespace: "network" })
|
||||
@Getter("players", networkNS)
|
||||
private players!: string[];
|
||||
|
||||
private data() {
|
||||
return {
|
||||
playerName:
|
||||
const playerName =
|
||||
"Guest-" +
|
||||
Math.random()
|
||||
.toString()
|
||||
.slice(2, 8),
|
||||
busy: false,
|
||||
.slice(2, 8);
|
||||
return {
|
||||
playerName,
|
||||
hostMaxPlayers: 8,
|
||||
hostPassword: "",
|
||||
joinSessionID: ""
|
||||
joinSessionID: "",
|
||||
wantedName: playerName
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -262,7 +279,7 @@ export default class Lobby extends Vue {
|
|||
}
|
||||
|
||||
private async create() {
|
||||
this.busy = true;
|
||||
this.wantedName = this.playerName;
|
||||
this.startServer({
|
||||
playerInfo: {
|
||||
name: this.playerName
|
||||
|
@ -275,7 +292,7 @@ export default class Lobby extends Vue {
|
|||
}
|
||||
|
||||
private async join() {
|
||||
this.busy = true;
|
||||
this.wantedName = this.playerName;
|
||||
this.connect({
|
||||
serverID: this.joinSessionID,
|
||||
playerInfo: {
|
||||
|
@ -284,6 +301,14 @@ export default class Lobby extends Vue {
|
|||
});
|
||||
}
|
||||
|
||||
private async changeName() {
|
||||
this.sendMessage({
|
||||
kind: "rename",
|
||||
oldname: this.playerName,
|
||||
newname: this.wantedName
|
||||
});
|
||||
}
|
||||
|
||||
private get canJoin(): boolean {
|
||||
return this.joinSessionID != "";
|
||||
}
|
||||
|
@ -300,5 +325,9 @@ export default class Lobby extends Vue {
|
|||
}
|
||||
return `${location.origin}${subpath}/join/${this.sessionID}`;
|
||||
}
|
||||
|
||||
private get nameAvailable(): boolean {
|
||||
return this.wantedName != "" && !this.players.includes(this.wantedName);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
Loading…
Reference in a new issue