diff --git a/.idea/hexmap.iml b/.idea/hexmap.iml
index 3787fb9..1accc2b 100644
--- a/.idea/hexmap.iml
+++ b/.idea/hexmap.iml
@@ -13,7 +13,6 @@
-
diff --git a/client/src/actions/ClientAction.ts b/client/src/actions/ClientAction.ts
index 907e21f..7f69226 100644
--- a/client/src/actions/ClientAction.ts
+++ b/client/src/actions/ClientAction.ts
@@ -58,7 +58,7 @@ export function isClientCommand(action: AppAction): action is ClientCommand {
return isClientHelloCommand(action) || isClientRefreshCommand(action) || isClientActCommand(action)
}
-export type ClientAction = ClientHelloCommand | ClientRefreshCommand | ClientPendingAction | ClientActCommand
+export type ClientAction = ClientCommand | ClientPendingAction
export function isClientAction(action: AppAction): action is ClientAction {
return isClientCommand(action) || isClientPendingAction(action)
}
\ No newline at end of file
diff --git a/client/src/actions/ServerAction.ts b/client/src/actions/ServerAction.ts
index ea6c3a0..d2027a3 100644
--- a/client/src/actions/ServerAction.ts
+++ b/client/src/actions/ServerAction.ts
@@ -20,10 +20,10 @@ export const SERVER_GOODBYE = "SERVER_GOODBYE"
/** Synthesized out of the close message when the server closes the connection. */
export interface ServerGoodbyeCommand extends BaseAction {
readonly type: typeof SERVER_GOODBYE
- /** The error code sent with the close message by the server, or -1 if our side crashed.*/
+ /** The exit code sent with the close message by the server. */
readonly code: number
- /** The text of the server's goodbye message, or the exception if our side crashed. */
- readonly reason: string|Error
+ /** The text of the server's goodbye message. */
+ readonly reason: string
/** The current time when this close message was received. */
readonly currentTime: Date
}
diff --git a/client/src/state/NetworkState.ts b/client/src/state/NetworkState.ts
index c6208b2..43373f1 100644
--- a/client/src/state/NetworkState.ts
+++ b/client/src/state/NetworkState.ts
@@ -50,14 +50,13 @@ export interface NetworkState {
/**
* The error code of the close message.
* Non-null if and only if the current state is OFFLINE or REJECTED.
- * -1 means no onClose was called, and the reason is a stringized error from onError instead.
*/
readonly goodbyeCode: number | null
/**
* The error reason of the close message.
* Non-null if and only if the current state is OFFLINE or REJECTED.
*/
- readonly goodbyeReason: string | Error | null
+ readonly goodbyeReason: string | null
/** The time the client will attempt to reconnect, if at all. */
readonly autoReconnectAt: Date | null
/** The number of attempts at reconnecting. */
diff --git a/client/src/websocket/ClientToPb.ts b/client/src/websocket/ClientToPb.ts
new file mode 100644
index 0000000..7a82651
--- /dev/null
+++ b/client/src/websocket/ClientToPb.ts
@@ -0,0 +1,6 @@
+import {ClientCommand} from "../actions/ClientAction";
+import {ClientCommandPB} from "../proto/client";
+
+export function clientToPb(message: ClientCommand): ClientCommandPB {
+
+}
\ No newline at end of file
diff --git a/client/src/websocket/WebsocketTranslator.ts b/client/src/websocket/WebsocketTranslator.ts
new file mode 100644
index 0000000..01537ae
--- /dev/null
+++ b/client/src/websocket/WebsocketTranslator.ts
@@ -0,0 +1,96 @@
+/** Translates between websocket messages and Commands. */
+import {ClientCommand} from "../actions/ClientAction";
+import {
+ SERVER_GOODBYE,
+ SERVER_SOCKET_STARTUP,
+ ServerCommand,
+ ServerGoodbyeCommand,
+ ServerSocketStartupAction,
+ SocketState
+} from "../actions/ServerAction";
+
+class WebsocketTranslator {
+ readonly url: string
+ readonly protocols: readonly string[]
+ readonly onStartup: (startup: ServerSocketStartupAction) => void
+ readonly onMessage: (command: ServerCommand) => void
+ readonly onGoodbye: (goodbye: ServerGoodbyeCommand) => void
+ private socket: WebSocket|null
+
+ constructor({
+ url,
+ protocols,
+ onStartup,
+ onMessage,
+ onGoodbye
+ }: {
+ url: string,
+ protocols: readonly string[],
+ onStartup: (startup: ServerSocketStartupAction) => void,
+ onMessage: (command: ServerCommand) => void,
+ onGoodbye: (goodbye: ServerGoodbyeCommand) => void
+ }) {
+ this.url = url
+ this.protocols = protocols.slice()
+ this.onStartup = onStartup
+ this.onMessage = onMessage
+ this.onGoodbye = onGoodbye
+ this.socket = null
+ }
+
+ connect() {
+ if (this.socket != null) {
+ throw Error("Already running")
+ }
+ this.socket = new WebSocket(this.url, this.protocols.slice())
+ this.socket.addEventListener("open", this.handleOpen)
+ this.socket.addEventListener("message", this.handleMessage)
+ this.socket.addEventListener("close", this.handleClose)
+ this.socket.addEventListener("error", WebsocketTranslator.handleError)
+ this.onStartup({
+ type: SERVER_SOCKET_STARTUP,
+ state: SocketState.CONNECTING,
+ })
+ }
+
+ send(message: ClientCommand) {
+ // TODO: Protoitize the client message and send() it.
+ }
+
+ close(code: number, reason: string) {
+ this.socket?.close(code, reason)
+ }
+
+ private handleOpen(e: Event) {
+ this.onStartup({
+ type: SERVER_SOCKET_STARTUP,
+ state: SocketState.OPEN,
+ })
+ }
+
+ private handleMessage(e: MessageEvent) {
+ // TODO: Parse the server message and pass it to onMessage.
+ }
+
+ private handleClose(e: CloseEvent) {
+ this.onGoodbye({
+ type: SERVER_GOODBYE,
+ code: e.code,
+ reason: e.reason,
+ currentTime: new Date(),
+ })
+ this.clearSocket()
+ }
+
+ private static handleError(e: Event) {
+ console.log("Websocket error: ", e)
+ }
+
+ private clearSocket() {
+ this.socket?.removeEventListener("open", this.handleOpen)
+ this.socket?.removeEventListener("message", this.handleMessage)
+ this.socket?.removeEventListener("close", this.handleClose)
+ this.socket?.removeEventListener("error", WebsocketTranslator.handleError)
+ this.socket = null
+ }
+}
\ No newline at end of file