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.
50 lines
2.1 KiB
50 lines
2.1 KiB
import {SyncedState} from "../state/SyncedState";
|
|
import {isMapAction, MapAction} from "../actions/MapAction";
|
|
import {hexMapReducer} from "./HexMapReducer";
|
|
import {isUserAction, UserAction} from "../actions/UserAction";
|
|
import {userReducer} from "./UserReducer";
|
|
import {exhaustivenessCheck} from "../util/TypeUtils";
|
|
import {SyncableAction} from "../actions/ServerAction";
|
|
|
|
export function syncedStateReducer(state: SyncedState, action: (MapAction|UserAction)): SyncedState {
|
|
if (isMapAction(action)) {
|
|
const newMap = hexMapReducer(state.map, action)
|
|
return newMap === state.map ? state : {
|
|
...state,
|
|
map: newMap
|
|
}
|
|
} else if (isUserAction(action)) {
|
|
const newUser = userReducer(state.user, action)
|
|
return newUser === state.user ? state : {
|
|
...state,
|
|
user: newUser
|
|
}
|
|
}
|
|
exhaustivenessCheck(action)
|
|
}
|
|
|
|
interface SyncableActionApplicationResults<T> {
|
|
state: SyncedState
|
|
appliedActions: readonly T[]
|
|
}
|
|
/** Applies a sequence of actions, skipping failed actions, and returns an array of the successful ones. */
|
|
export function applySyncableActions<T extends SyncableAction>(state: SyncedState, actions: readonly T[]): SyncableActionApplicationResults<T> {
|
|
return actions.reduce(({state, appliedActions}: SyncableActionApplicationResults<T>, action) => {
|
|
// Save our breath by reusing the actions array if this is the last action in the list.
|
|
const resultActions = (appliedActions.length === actions.length - 1) ? actions : [...appliedActions, action]
|
|
try {
|
|
const newState = syncedStateReducer(state, action)
|
|
if (newState === state) {
|
|
// Act as if it wasn't there - it did nothing.
|
|
return { state, appliedActions }
|
|
}
|
|
return {
|
|
state: newState,
|
|
appliedActions: resultActions
|
|
}
|
|
} catch (e) {
|
|
// Just skip it - continue as if it wasn't there, and don't let the exception escape.
|
|
return { state, appliedActions }
|
|
}
|
|
}, {state: state, appliedActions: []})
|
|
} |