Add rename
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/pr Build is failing Details

This commit is contained in:
Hamcha 2019-10-11 16:21:46 +02:00
parent ef3e10a6c4
commit 3a5989ea0d
Signed by: hamcha
GPG Key ID: 44AD3571EB09A39E
7 changed files with 106 additions and 67 deletions

View File

@ -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,18 +27,18 @@ 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
console.warn(
`Someone (${data.oldname}) changed name but wasn't on the player list`
);
this.players.push(data.newname);
break;
}
this.players[idx] = data.newname;
}
let idx = this.players.indexOf(data.oldname);
if (idx < 0) {
// Weird
console.warn(
`Someone (${data.oldname}) changed name but wasn't on the player list`
);
this.players.push(data.newname);
break;
}
Vue.set(this.players, idx, data.newname);
this.emit("rename", data.oldname, data.newname);
break;
// A new player joined the room (this includes us)

View File

@ -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

View File

@ -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", () => {

View File

@ -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";

View File

@ -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);
}
};

View File

@ -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 =

View File

@ -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() {
const playerName =
"Guest-" +
Math.random()
.toString()
.slice(2, 8);
return {
playerName:
"Guest-" +
Math.random()
.toString()
.slice(2, 8),
busy: false,
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>