From 87c0a69cc23c97e690e82c1637fab11f287e19f9 Mon Sep 17 00:00:00 2001 From: Hamcha Date: Tue, 17 Sep 2019 13:22:43 +0000 Subject: [PATCH] Integrate draft/network stack via Vuex (#26) --- src/network/PeerClient.ts | 10 ++++++ src/network/PeerServer.ts | 4 +++ src/store/draft/actions.ts | 12 ++++++++ src/store/draft/getters.ts | 12 ++++++++ src/store/draft/index.ts | 27 ++++++++++++++++ src/store/draft/mutations.ts | 37 ++++++++++++++++++++++ src/store/draft/types.ts | 21 +++++++++++++ src/store/index.ts | 8 ++++- src/store/network/actions.ts | 29 ++++++++++++++++++ src/store/network/getters.ts | 21 +++++++++++++ src/store/network/index.ts | 24 +++++++++++++++ src/store/network/mutations.ts | 38 +++++++++++++++++++++++ src/store/network/types.ts | 56 ++++++++++++++++++++++++++++++++++ src/views/Draft.vue | 8 +---- 14 files changed, 299 insertions(+), 8 deletions(-) create mode 100644 src/store/draft/actions.ts create mode 100644 src/store/draft/getters.ts create mode 100644 src/store/draft/index.ts create mode 100644 src/store/draft/mutations.ts create mode 100644 src/store/draft/types.ts create mode 100644 src/store/network/actions.ts create mode 100644 src/store/network/getters.ts create mode 100644 src/store/network/index.ts create mode 100644 src/store/network/mutations.ts create mode 100644 src/store/network/types.ts diff --git a/src/network/PeerClient.ts b/src/network/PeerClient.ts index b728dab..2dc1a09 100644 --- a/src/network/PeerClient.ts +++ b/src/network/PeerClient.ts @@ -25,6 +25,12 @@ export class PeerClient extends Client { this.connection.on("open", () => { this.emit("connected"); }); + this.connection.on("close", () => { + this.emit("disconnected"); + }); + this.connection.on("error", err => { + this.emit("error", err); + }); this.connection.on("data", data => { this._received(data); }); @@ -34,6 +40,10 @@ export class PeerClient extends Client { return this.metadata.name; } + public get id(): string { + return this.peer.id; + } + public send(data: T) { if (!this.connection) { throw new Error("Client is not connected to a server"); diff --git a/src/network/PeerServer.ts b/src/network/PeerServer.ts index bfadda2..e88ffbf 100644 --- a/src/network/PeerServer.ts +++ b/src/network/PeerServer.ts @@ -234,6 +234,10 @@ export class PeerServer extends EventEmitter { this.send(player, message); } } + + public get id(): string { + return this.peer.id; + } } export default PeerServer; diff --git a/src/store/draft/actions.ts b/src/store/draft/actions.ts new file mode 100644 index 0000000..0f45d61 --- /dev/null +++ b/src/store/draft/actions.ts @@ -0,0 +1,12 @@ +import { ActionTree } from "vuex"; +import { AppState } from "../types"; +import { DraftState } from "./types"; +import { Card } from "@/mlpccg"; + +const actions: ActionTree = { + pickCard({ commit }, card: Card) { + //TODO + } +}; + +export default actions; diff --git a/src/store/draft/getters.ts b/src/store/draft/getters.ts new file mode 100644 index 0000000..e082c81 --- /dev/null +++ b/src/store/draft/getters.ts @@ -0,0 +1,12 @@ +import { GetterTree } from "vuex"; +import { AppState } from "../types"; +import { DraftState } from "./types"; +import { createPonyheadURL } from "@/mlpccg"; + +const getters: GetterTree = { + ponyheadURL(state): string { + return createPonyheadURL(state.picks); + } +}; + +export default getters; diff --git a/src/store/draft/index.ts b/src/store/draft/index.ts new file mode 100644 index 0000000..6e55ea1 --- /dev/null +++ b/src/store/draft/index.ts @@ -0,0 +1,27 @@ +import { DraftState } from "./types"; +import { AppState } from "../types"; +import { Module } from "vuex"; + +const namespaced = true; + +import actions from "./actions"; +import mutations from "./mutations"; +import getters from "./getters"; + +export const state: DraftState = { + cards: [], + picks: [], + pod: [], + packCount: 0, + currentPack: 0 +}; + +export const draft: Module = { + namespaced, + state, + actions, + mutations, + getters +}; + +export default draft; diff --git a/src/store/draft/mutations.ts b/src/store/draft/mutations.ts new file mode 100644 index 0000000..94d2494 --- /dev/null +++ b/src/store/draft/mutations.ts @@ -0,0 +1,37 @@ +import { MutationTree } from "vuex"; +import { DraftState, PlayerStatus } from "./types"; +import { Card } from "@/mlpccg"; + +const mutations: MutationTree = { + playerPicked(state, payload: { name: string; picked: boolean }) { + const idx = state.pod.findIndex(p => p.name == payload.name); + state.pod[idx].picked = payload.picked; + }, + + resetPickStatus(state) { + state.pod = state.pod.map(p => ({ ...p, picked: false })); + }, + + setCardPool(state, pool: Card[]) { + state.cards = pool; + }, + + setPackInfo(state, payload: { current: number; total: number }) { + state.currentPack = payload.current; + state.packCount = payload.total; + }, + + addPicks(state, pick: Card) { + state.picks.push(pick); + }, + + setPod(state, pod: PlayerStatus[]) { + state.pod = pod; + }, + + resetPicks(state) { + state.picks = []; + } +}; + +export default mutations; diff --git a/src/store/draft/types.ts b/src/store/draft/types.ts new file mode 100644 index 0000000..3de4bf7 --- /dev/null +++ b/src/store/draft/types.ts @@ -0,0 +1,21 @@ +import { Session } from "@/mlpccg/draft"; +import { Card } from "@/mlpccg"; + +export interface DraftState { + session?: Session; + + pod: PlayerStatus[]; + cards: Card[]; + picks: Card[]; + + // Multiple pack draft + packCount: number; + currentPack: number; +} + +export interface PlayerStatus { + name: string; + isBot: boolean; + isMe: boolean; + picked: boolean; +} diff --git a/src/store/index.ts b/src/store/index.ts index 4909137..8bef26a 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -8,6 +8,9 @@ import actions from "./actions"; import mutations from "./mutations"; import getters from "./getters"; +import network from "./network"; +import draft from "./draft"; + const store: StoreOptions = { state: { loaded: false, @@ -17,7 +20,10 @@ const store: StoreOptions = { actions, mutations, getters, - modules: {} + modules: { + network, + draft + } }; export default new Vuex.Store(store); diff --git a/src/store/network/actions.ts b/src/store/network/actions.ts new file mode 100644 index 0000000..dfc9f4b --- /dev/null +++ b/src/store/network/actions.ts @@ -0,0 +1,29 @@ +import { ActionTree } from "vuex"; +import { AppState } from "../types"; +import { NetworkState, StartServerOptions, ConnectOptions } from "./types"; +import { PeerServer, LocalClient, PeerClient } from "@/network"; + +const actions: ActionTree = { + startServer({ commit }, options: StartServerOptions) { + const local = new LocalClient(options.playerInfo); + const server = new PeerServer(options.roomInfo, local, options._customPeer); + commit("becomeServer", { local, server }); + }, + + connect({ commit }, options: ConnectOptions) { + const client = new PeerClient(options.playerInfo, options._customPeer); + commit("becomeClient", { peer: client }); + client.on("connected", () => { + commit("connected"); + }); + client.on("disconnected", () => { + commit("disconnected"); + }); + client.on("error", err => { + commit("connectionError", err); + }); + client.connect(options.serverID); + } +}; + +export default actions; diff --git a/src/store/network/getters.ts b/src/store/network/getters.ts new file mode 100644 index 0000000..3840b22 --- /dev/null +++ b/src/store/network/getters.ts @@ -0,0 +1,21 @@ +import { GetterTree } from "vuex"; +import { AppState } from "../types"; +import { NetworkState } from "./types"; + +const getters: GetterTree = { + peerID(state): string | null { + switch (state.peerType) { + case "server": + return state.server.id; + case "client": + return state.peer.id; + } + return null; + }, + + connectionType(state): "client" | "server" | "none" { + return state.peerType; + } +}; + +export default getters; diff --git a/src/store/network/index.ts b/src/store/network/index.ts new file mode 100644 index 0000000..9a0ca12 --- /dev/null +++ b/src/store/network/index.ts @@ -0,0 +1,24 @@ +import { NetworkState } from "./types"; +import { AppState } from "../types"; +import { Module } from "vuex"; + +import actions from "./actions"; +import mutations from "./mutations"; +import getters from "./getters"; + +const namespaced = true; + +export const state: NetworkState = { + peerType: "none", + chatLog: [] +}; + +export const network: Module = { + namespaced, + state, + actions, + mutations, + getters +}; + +export default network; diff --git a/src/store/network/mutations.ts b/src/store/network/mutations.ts new file mode 100644 index 0000000..5a0d135 --- /dev/null +++ b/src/store/network/mutations.ts @@ -0,0 +1,38 @@ +import { MutationTree } from "vuex"; +import { NetworkState, ServerNetworkState, ClientNetworkState } from "./types"; +import { LocalClient, PeerServer, PeerClient } from "@/network"; + +const mutations: MutationTree = { + becomeServer(state, payload: { local: LocalClient; server: PeerServer }) { + state = { + ...state, + peerType: "server", + local: payload.local, + server: payload.server + }; + }, + + becomeClient(state, payload: { peer: PeerClient }) { + state = { + ...state, + connectionStatus: "connecting", + peerType: "client", + peer: payload.peer + }; + }, + + connected(state) { + (state as ClientNetworkState).connectionStatus = "connected"; + }, + + disconnected(state) { + (state as ClientNetworkState).connectionStatus = "disconnected"; + }, + + connectionError(state, error) { + (state as ClientNetworkState).connectionStatus = "error"; + (state as ClientNetworkState).connectionError = error; + } +}; + +export default mutations; diff --git a/src/store/network/types.ts b/src/store/network/types.ts new file mode 100644 index 0000000..4c8e555 --- /dev/null +++ b/src/store/network/types.ts @@ -0,0 +1,56 @@ +import { + PeerClient, + PeerServer, + LocalClient, + RoomInfo, + PeerMetadata +} from "@/network"; +import Peer from "peerjs"; + +export interface ChatMessage { + who: string; + to: string; + message: string; +} + +export interface SharedNetworkState { + chatLog: ChatMessage[]; +} + +export interface NoNetworkState extends SharedNetworkState { + peerType: "none"; +} + +export interface ClientNetworkState extends SharedNetworkState { + peerType: "client"; + connectionStatus: "connecting" | "connected" | "disconnected" | "error"; + connectionError?: Error; + peer: PeerClient; +} + +export interface ServerNetworkState extends SharedNetworkState { + peerType: "server"; + server: PeerServer; + local: LocalClient; +} + +export type NetworkState = + | NoNetworkState + | ClientNetworkState + | ServerNetworkState; + +export interface StartServerOptions { + roomInfo: RoomInfo; + playerInfo: PeerMetadata; + + // Testing utils + _customPeer?: Peer; +} + +export interface ConnectOptions { + serverID: string; + playerInfo: PeerMetadata; + + // Testing utils + _customPeer?: Peer; +} diff --git a/src/views/Draft.vue b/src/views/Draft.vue index 9a699b0..6a68139 100644 --- a/src/views/Draft.vue +++ b/src/views/Draft.vue @@ -152,13 +152,7 @@ import { Component, Vue } from "vue-property-decorator"; import { getCards, CardSlot, cardLimit, Card } from "@/mlpccg"; import CardPicker from "@/components/DeckBuilder/CardPicker.vue"; import DeckList from "@/components/DeckBuilder/DeckList.vue"; - -interface PlayerStatus { - name: string; - isBot: boolean; - isMe: boolean; - picked: boolean; -} +import { PlayerStatus } from "@/store/draft/types"; @Component({ components: {