You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
hexmap/client/src/ui/debug/ConsoleConnection.tsx

176 lines
5.8 KiB

import {
ActionFailure,
CLIENT_SENT,
ClientAction,
ClientSentAction,
isClientSentAction,
SendableAction,
SentAction,
SERVER_FAILED,
SERVER_GOODBYE,
SERVER_HELLO,
SERVER_OK,
SERVER_SENT,
SERVER_SOCKET_STARTUP,
ServerAction,
SocketState
} from "../../actions/NetworkAction";
import {HexagonOrientation, HexMapRepresentation, initializeMap, LineParity} from "../../state/HexMap";
import {ReactElement, useContext, useEffect, useRef, useState} from "react";
import {DispatchContext} from "../context/DispatchContext";
import {USER_ACTIVE_COLOR} from "../../actions/UserAction";
import {CELL_COLOR} from "../../actions/CellAction";
export enum OrientationConstants {
ROWS = "ROWS",
COLUMNS = "COLUMNS",
EVEN_ROWS = "EVEN_ROWS",
EVEN_COLUMNS = "EVEN_COLUMNS"
}
export function orientationFromString(string: string): HexMapRepresentation {
const normalized = string.toUpperCase().trim()
switch (normalized) {
case OrientationConstants.ROWS:
return { orientation: HexagonOrientation.POINTY_TOP, indentedLines: LineParity.ODD }
case OrientationConstants.COLUMNS:
return { orientation: HexagonOrientation.FLAT_TOP, indentedLines: LineParity.ODD }
case OrientationConstants.EVEN_ROWS:
return { orientation: HexagonOrientation.POINTY_TOP, indentedLines: LineParity.EVEN }
case OrientationConstants.EVEN_COLUMNS:
return { orientation: HexagonOrientation.FLAT_TOP, indentedLines: LineParity.EVEN }
default:
return { orientation: HexagonOrientation.POINTY_TOP, indentedLines: LineParity.ODD }
}
}
/** Fake "connection" to a "server" that actually just goes back and forth with the console. */
export class ConsoleConnection {
public receivedMessages: ClientAction[] = []
private dispatch: (action: ServerAction) => void
constructor(dispatch: (action: ServerAction) => void) {
this.dispatch = dispatch
}
receive(action: ClientAction): void {
this.receivedMessages.push(action)
if (isClientSentAction(action)) {
console.log(`Received Sent action containing: ${action.nested.map((value) => `${value.id}/${value.action.type}`).join(", ")}`)
} else {
console.log(`Received: ${action.type}`)
}
}
public sendSocketConnecting(): void {
this.dispatch({
type: SERVER_SOCKET_STARTUP,
state: SocketState.CONNECTING
})
}
public sendSocketConnected(): void {
this.dispatch({
type: SERVER_SOCKET_STARTUP,
state: SocketState.OPEN
})
}
public sendHello({color = "#0000FF", displayMode = "ROWS", xid = "TotallyCoolXID", lines = 10, cells = 10}: {
color?: string,
displayMode?: string,
xid?: string,
lines?: number,
cells?: number
} = {}): void {
this.dispatch({
type: SERVER_HELLO,
version: 1,
state: {
map: initializeMap({
lines,
cellsPerLine: cells,
displayMode: orientationFromString(displayMode),
xid
}),
user: {activeColor: color}
}
})
}
public sendOK(ids: readonly number[]): void {
this.dispatch({
type: SERVER_OK,
ids
})
}
public sendFailed(failures: readonly ActionFailure[]): void {
this.dispatch({
type: SERVER_FAILED,
failures
})
}
public sendGoodbye({code = 1000, reason = "Okay, bye then!"}: { code?: number, reason?: string } = {}): void {
this.dispatch({
type: SERVER_GOODBYE,
code,
reason,
currentTime: new Date()
})
}
public sendColorChange(color: string = "#FF0000FF"): void {
this.dispatch({
type: SERVER_SENT,
actions: [{
type: USER_ACTIVE_COLOR,
color
}]
})
}
public sendColorAtTile(color: string = "#FFFF00FF", line: number = 0, cell: number = 0): void {
this.dispatch({
type: SERVER_SENT,
actions: [{
type: CELL_COLOR,
at: { line, cell },
color
}]
})
}
}
export function ConsoleConnector({specialMessage, pendingMessages, nextID}: {specialMessage: ClientAction|null, pendingMessages: readonly SendableAction[], nextID: number}): ReactElement {
const dispatch = useContext(DispatchContext)
const connector = useRef(new ConsoleConnection(dispatch || (() => null)))
const [lastSpecialMessage, setLastSpecialMessage] = useState<ClientAction|null>(null)
useEffect(() => {
// @ts-ignore
window.fakedServerConnection = connector.current
}, []);
useEffect(() => {
if (dispatch !== null) {
if (pendingMessages.length > 0) {
const sentMessages: SentAction[] = pendingMessages.map((action, index) => {
return { id: index + nextID, action }
});
const sentMessage: ClientSentAction = {
type: CLIENT_SENT,
nested: sentMessages
};
connector.current.receive(sentMessage)
dispatch(sentMessage)
}
}
}, [nextID, dispatch, pendingMessages])
useEffect(() => {
if (specialMessage !== null && specialMessage !== lastSpecialMessage) {
connector.current.receive(specialMessage);
setLastSpecialMessage(specialMessage);
}
}, [specialMessage, lastSpecialMessage, setLastSpecialMessage])
return <div className="consoleConnector">Console connection active</div>
}