Integrate draft/network stack via Vuex (#26)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
412bb56b32
commit
87c0a69cc2
14 changed files with 299 additions and 8 deletions
|
@ -25,6 +25,12 @@ export class PeerClient extends Client {
|
||||||
this.connection.on("open", () => {
|
this.connection.on("open", () => {
|
||||||
this.emit("connected");
|
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.connection.on("data", data => {
|
||||||
this._received(data);
|
this._received(data);
|
||||||
});
|
});
|
||||||
|
@ -34,6 +40,10 @@ export class PeerClient extends Client {
|
||||||
return this.metadata.name;
|
return this.metadata.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get id(): string {
|
||||||
|
return this.peer.id;
|
||||||
|
}
|
||||||
|
|
||||||
public send<T extends NetworkMessage>(data: T) {
|
public send<T extends NetworkMessage>(data: T) {
|
||||||
if (!this.connection) {
|
if (!this.connection) {
|
||||||
throw new Error("Client is not connected to a server");
|
throw new Error("Client is not connected to a server");
|
||||||
|
|
|
@ -234,6 +234,10 @@ export class PeerServer extends EventEmitter {
|
||||||
this.send<T>(player, message);
|
this.send<T>(player, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get id(): string {
|
||||||
|
return this.peer.id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PeerServer;
|
export default PeerServer;
|
||||||
|
|
12
src/store/draft/actions.ts
Normal file
12
src/store/draft/actions.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { ActionTree } from "vuex";
|
||||||
|
import { AppState } from "../types";
|
||||||
|
import { DraftState } from "./types";
|
||||||
|
import { Card } from "@/mlpccg";
|
||||||
|
|
||||||
|
const actions: ActionTree<DraftState, AppState> = {
|
||||||
|
pickCard({ commit }, card: Card) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default actions;
|
12
src/store/draft/getters.ts
Normal file
12
src/store/draft/getters.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { GetterTree } from "vuex";
|
||||||
|
import { AppState } from "../types";
|
||||||
|
import { DraftState } from "./types";
|
||||||
|
import { createPonyheadURL } from "@/mlpccg";
|
||||||
|
|
||||||
|
const getters: GetterTree<DraftState, AppState> = {
|
||||||
|
ponyheadURL(state): string {
|
||||||
|
return createPonyheadURL(state.picks);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getters;
|
27
src/store/draft/index.ts
Normal file
27
src/store/draft/index.ts
Normal file
|
@ -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<DraftState, AppState> = {
|
||||||
|
namespaced,
|
||||||
|
state,
|
||||||
|
actions,
|
||||||
|
mutations,
|
||||||
|
getters
|
||||||
|
};
|
||||||
|
|
||||||
|
export default draft;
|
37
src/store/draft/mutations.ts
Normal file
37
src/store/draft/mutations.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { MutationTree } from "vuex";
|
||||||
|
import { DraftState, PlayerStatus } from "./types";
|
||||||
|
import { Card } from "@/mlpccg";
|
||||||
|
|
||||||
|
const mutations: MutationTree<DraftState> = {
|
||||||
|
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;
|
21
src/store/draft/types.ts
Normal file
21
src/store/draft/types.ts
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -8,6 +8,9 @@ import actions from "./actions";
|
||||||
import mutations from "./mutations";
|
import mutations from "./mutations";
|
||||||
import getters from "./getters";
|
import getters from "./getters";
|
||||||
|
|
||||||
|
import network from "./network";
|
||||||
|
import draft from "./draft";
|
||||||
|
|
||||||
const store: StoreOptions<AppState> = {
|
const store: StoreOptions<AppState> = {
|
||||||
state: {
|
state: {
|
||||||
loaded: false,
|
loaded: false,
|
||||||
|
@ -17,7 +20,10 @@ const store: StoreOptions<AppState> = {
|
||||||
actions,
|
actions,
|
||||||
mutations,
|
mutations,
|
||||||
getters,
|
getters,
|
||||||
modules: {}
|
modules: {
|
||||||
|
network,
|
||||||
|
draft
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default new Vuex.Store<AppState>(store);
|
export default new Vuex.Store<AppState>(store);
|
||||||
|
|
29
src/store/network/actions.ts
Normal file
29
src/store/network/actions.ts
Normal file
|
@ -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<NetworkState, AppState> = {
|
||||||
|
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;
|
21
src/store/network/getters.ts
Normal file
21
src/store/network/getters.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { GetterTree } from "vuex";
|
||||||
|
import { AppState } from "../types";
|
||||||
|
import { NetworkState } from "./types";
|
||||||
|
|
||||||
|
const getters: GetterTree<NetworkState, AppState> = {
|
||||||
|
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;
|
24
src/store/network/index.ts
Normal file
24
src/store/network/index.ts
Normal file
|
@ -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<NetworkState, AppState> = {
|
||||||
|
namespaced,
|
||||||
|
state,
|
||||||
|
actions,
|
||||||
|
mutations,
|
||||||
|
getters
|
||||||
|
};
|
||||||
|
|
||||||
|
export default network;
|
38
src/store/network/mutations.ts
Normal file
38
src/store/network/mutations.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { MutationTree } from "vuex";
|
||||||
|
import { NetworkState, ServerNetworkState, ClientNetworkState } from "./types";
|
||||||
|
import { LocalClient, PeerServer, PeerClient } from "@/network";
|
||||||
|
|
||||||
|
const mutations: MutationTree<NetworkState> = {
|
||||||
|
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;
|
56
src/store/network/types.ts
Normal file
56
src/store/network/types.ts
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -152,13 +152,7 @@ import { Component, Vue } from "vue-property-decorator";
|
||||||
import { getCards, CardSlot, cardLimit, Card } from "@/mlpccg";
|
import { getCards, CardSlot, cardLimit, Card } from "@/mlpccg";
|
||||||
import CardPicker from "@/components/DeckBuilder/CardPicker.vue";
|
import CardPicker from "@/components/DeckBuilder/CardPicker.vue";
|
||||||
import DeckList from "@/components/DeckBuilder/DeckList.vue";
|
import DeckList from "@/components/DeckBuilder/DeckList.vue";
|
||||||
|
import { PlayerStatus } from "@/store/draft/types";
|
||||||
interface PlayerStatus {
|
|
||||||
name: string;
|
|
||||||
isBot: boolean;
|
|
||||||
isMe: boolean;
|
|
||||||
picked: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
|
Loading…
Reference in a new issue