processServerEvent function
Implementation
ServerProcessed processServerEvent(
ServerWorldEvent event,
WorldState state, {
required List<SignatureMetadata> signature,
}) {
if (!isValidServerEvent(event, state)) return ServerProcessed(null);
switch (event) {
case WorldInitialized():
final serverSignature = event.packsSignature;
final supported = serverSignature == null
? true
: isServerSupported(signature, serverSignature);
if (!supported) {
throw InvalidPacksError(
signature: serverSignature,
expected: signature,
);
}
return ServerProcessed(
state.copyWith(
table: event.table ?? state.table,
id: event.id ?? state.id,
teamMembers: event.teamMembers ?? state.teamMembers,
info: event.info ?? state.info,
dialogs: event.clearUserInterface ? [] : state.dialogs,
images: event.clearUserInterface ? {} : state.images,
gameState: GameState.play,
authRequest: null,
),
);
case TeamJoined():
return ServerProcessed(
state.copyWith(
teamMembers: {
...state.teamMembers,
event.team: {...?state.teamMembers[event.team], event.user},
},
),
);
case TeamLeft():
final members = Set<Channel>.from(state.teamMembers[event.team] ?? {});
members.remove(event.user);
final allMembers = Map<String, Set<int>>.from(state.teamMembers);
if (members.isEmpty) {
allMembers.remove(event.team);
} else {
allMembers[event.team] = members;
}
return ServerProcessed(state.copyWith(teamMembers: allMembers));
case ObjectsChanged():
return ServerProcessed(
state.mapTableOrDefault(event.cell.table, (table) {
final cell = table.cells[event.cell.position] ?? TableCell();
final newCell = cell.copyWith(objects: event.objects);
if (newCell.isEmpty) {
return table.copyWith.cellsBox(
content: Map<VectorDefinition, TableCell>.from(table.cells)
..remove(event.cell.position),
);
}
return table.copyWith.cellsBox(
content: Map<VectorDefinition, TableCell>.from(table.cells)
..[event.cell.position] = newCell,
);
}),
);
case CellShuffled(positions: final positions):
return ServerProcessed(
state.mapTableOrDefault(event.cell.table, (table) {
final cell = table.cells[event.cell.position] ?? TableCell();
final objects = cell.objects;
final newObjects = List<GameObject>.from(objects);
for (var i = 0; i < positions.length; i++) {
newObjects[positions[i]] = objects[i];
}
return table.copyWith.cellsBox(
content: Map<VectorDefinition, TableCell>.from(table.cells)
..[event.cell.position] = cell.copyWith(objects: newObjects),
);
}),
);
case BackgroundChanged():
return ServerProcessed(
state.copyWith.table(background: event.background),
);
case ObjectsSpawned():
return ServerProcessed(
state.mapTableOrDefault(event.table, (table) {
var newTable = table;
for (final entry in event.objects.entries) {
final cell = newTable.cells[entry.key] ?? TableCell();
newTable = newTable.copyWith.cellsBox(
content: Map<VectorDefinition, TableCell>.from(newTable.cells)
..[entry.key] = cell.copyWith(objects: entry.value),
);
}
return newTable;
}),
);
case ObjectsMoved():
return ServerProcessed(
state.mapTableOrDefault(event.table, (table) {
var from = table.cells[event.from] ?? TableCell();
var to = table.cells[event.to] ?? TableCell();
final toRemove = List<int>.from(event.objects)
..sort((a, b) => b.compareTo(a));
final toAdd = toRemove.map((e) => from.objects[e]).toList();
final newObjects = List<GameObject>.from(from.objects);
for (final i in toRemove) {
newObjects.removeAt(i);
}
from = from.copyWith(objects: newObjects);
to = to.copyWith(objects: [...to.objects, ...toAdd]);
final cells = Map<VectorDefinition, TableCell>.from(table.cells)
..[event.to] = to;
if (from.isEmpty) {
cells.remove(event.from);
} else {
cells[event.from] = from;
}
return table.copyWith.cellsBox(content: cells);
}),
);
case CellHideChanged():
return ServerProcessed(
state.mapTableOrDefault(event.cell.table, (table) {
final cell = table.cells[event.cell.position] ?? TableCell();
final objectIndex = event.object;
if (objectIndex != null) {
final object = cell.objects[objectIndex];
return table.copyWith.cellsBox(
content: Map<VectorDefinition, TableCell>.from(table.cells)
..[event.cell.position] = cell.copyWith.objects.replace(
objectIndex,
object.copyWith(hidden: event.hide ?? !object.hidden),
),
);
}
final hidden =
!(event.hide ?? cell.objects.firstOrNull?.hidden ?? false);
return table.copyWith.cellsBox(
content: Map<VectorDefinition, TableCell>.from(table.cells)
..[event.cell.position] = cell.copyWith(
objects: cell.objects
.map((e) => e.copyWith(hidden: hidden))
.toList(),
),
);
}),
);
case ObjectsRemoved():
return ServerProcessed(
state.mapTableOrDefault(event.cell.table, (table) {
final cell = table.cells[event.cell.position] ?? TableCell();
final objectIndex = event.objects;
var newCell = cell;
if (objectIndex != null) {
final objects = List<GameObject>.from(cell.objects);
final indexes = objectIndex.toList()
..sort((a, b) => b.compareTo(a));
for (final index in indexes) {
objects.removeAt(index);
}
newCell = cell.copyWith();
} else {
newCell = cell.copyWith(objects: []);
}
if (newCell.isEmpty) {
return table.copyWith.cellsBox(
content: Map<VectorDefinition, TableCell>.from(table.cells)
..remove(event.cell.position),
);
}
return table.copyWith.cellsBox(
content: Map<VectorDefinition, TableCell>.from(table.cells)
..[event.cell.position] = newCell,
);
}),
);
case ObjectIndexChanged():
return ServerProcessed(
state.mapTableOrDefault(event.cell.table, (table) {
final cell = table.cells[event.cell.position] ?? TableCell();
final object = cell.objects[event.object];
final newObjects = List<GameObject>.from(cell.objects);
newObjects.removeAt(event.object);
newObjects.insert(event.index, object);
return table.copyWith.cellsBox(
content: Map<VectorDefinition, TableCell>.from(table.cells)
..[event.cell.position] = cell.copyWith(objects: newObjects),
);
}),
);
case TeamChanged():
var info = state.info;
var newName = event.newName;
var teamMembers = Map<String, Set<int>>.from(state.teamMembers);
if (newName != null) {
final teams = Map<String, GameTeam>.fromEntries(
info.teams.entries.map((e) {
if (e.key == event.name) {
return MapEntry(newName, event.team);
}
return e;
}),
);
info = info.copyWith(teams: teams);
teamMembers[newName] = teamMembers.remove(event.name) ?? {};
} else {
info = info.copyWith.teams.put(event.name, event.team);
}
return ServerProcessed(
state.copyWith(info: info, teamMembers: teamMembers),
);
case TeamRemoved():
return ServerProcessed(
state.copyWith(
info: state.info.copyWith.teams.remove(event.team),
teamMembers: Map.from(state.teamMembers)..remove(event.team),
),
);
case MetadataChanged():
return ServerProcessed(state.copyWith(metadata: event.metadata));
case MessageSent():
return ServerProcessed(
state.copyWith.messages.add(
ChatMessage(
author: event.user,
content: event.message,
timestamp: DateTime.now(),
),
),
);
case TableRenamed():
final data = state.data.getTable(event.name);
return ServerProcessed(
state.copyWith(
tableName: event.name == state.tableName
? event.newName
: state.tableName,
data: data == null
? state.data
: state.data
.removeTable(event.name)
.setTable(data, event.newName),
),
);
case TableRemoved():
return ServerProcessed(
state.copyWith(
tableName: state.tableName == event.name ? '' : state.tableName,
data: state.data.removeTable(event.name),
),
);
case NoteChanged():
return ServerProcessed(
state.copyWith(data: state.data.setNote(event.name, event.content)),
);
case NoteRemoved():
return ServerProcessed(
state.copyWith(data: state.data.removeNote(event.name)),
);
case BoardTilesSpawned():
return ServerProcessed(
state.mapTableOrDefault(event.table, (table) {
final cells = Map<VectorDefinition, TableCell>.from(table.cells);
for (final entry in event.tiles.entries) {
cells[entry.key] = table
.getCell(entry.key)
.copyWith
.tiles
.addAll(entry.value);
}
return table.copyWith.cellsBox(content: cells);
}),
);
case BoardTilesChanged():
return ServerProcessed(
state.mapTableOrDefault(event.table, (table) {
final cells = Map<VectorDefinition, TableCell>.from(table.cells);
for (final entry in event.tiles.entries) {
final newCell = table
.getCell(entry.key)
.copyWith(tiles: entry.value);
if (newCell.isEmpty) {
cells.remove(entry.key);
} else {
cells[entry.key] = newCell;
}
}
return table.copyWith.cellsBox(content: cells);
}),
);
case DialogOpened():
final index = state.dialogs.indexWhere((e) => e.id == event.dialog.id);
final image = event.dialog.image;
final responses = <ClientWorldEvent>[];
if (image != null && !state.images.containsKey(image)) {
responses.add(ImagesRequest([image]));
}
if (index != -1) {
return ServerProcessed(
state.copyWith.dialogs.replace(index, event.dialog),
responses,
);
}
return ServerProcessed(
state.copyWith.dialogs.add(event.dialog),
responses,
);
case DialogsClosed():
return ServerProcessed(
state.copyWith.dialogs.where(
(e) => !(event.ids?.contains(e.id) ?? true),
),
);
case ImagesUpdated():
return ServerProcessed(
state.copyWith(images: {...state.images, ...event.images}),
);
case ServerStateUpdated():
return ServerProcessed(state.copyWith(serverState: event.state));
case AuthenticatedRequested():
return ServerProcessed(state.copyWith(authRequest: event));
}
}