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.
176 lines
5.8 KiB
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,
|
|
cells_per_line: 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>
|
|
} |