235 lines
7.4 KiB
TypeScript
235 lines
7.4 KiB
TypeScript
import { Server, Socket } from "socket.io";
|
|
import { handleEvent } from "../handleEvent";
|
|
import { EditorState, MissionMap, missionStoreModel } from "../../storage/missionMap";
|
|
import * as Y from "yjs";
|
|
import MissionDocHelper from "../../helpers/missionDocHelper";
|
|
import randomColor from "randomcolor";
|
|
import { SocketMap } from "../../storage/socketMap";
|
|
|
|
export default (io: Server, socket: Socket) => {
|
|
socket.on(
|
|
"mission:join",
|
|
handleEvent(
|
|
{ type: "read", section: "operation", module: "mission" },
|
|
async (missionId: string, clientLastUpdate: missionStoreModel) => {
|
|
socket.rooms.forEach((room) => {
|
|
if (room !== socket.id && room != "home") {
|
|
socket.leave(room);
|
|
}
|
|
});
|
|
|
|
try {
|
|
socket.join(missionId);
|
|
|
|
if (!MissionMap.exists(missionId)) {
|
|
await MissionDocHelper.populateDoc(missionId);
|
|
}
|
|
|
|
if (clientLastUpdate && clientLastUpdate.timestamp) {
|
|
if (MissionDocHelper.docTimestamp(missionId) > clientLastUpdate.timestamp) {
|
|
socket.emit("package-sync", {
|
|
update: MissionDocHelper.docAsUpdate(missionId),
|
|
timestamp: MissionDocHelper.docTimestamp(missionId),
|
|
source: "server",
|
|
});
|
|
} else {
|
|
socket.emit("sync-get-missing-updates", {
|
|
stateVector: MissionDocHelper.docAsStateVector(missionId),
|
|
timestamp: MissionDocHelper.docTimestamp(missionId),
|
|
source: "server",
|
|
});
|
|
}
|
|
} else {
|
|
socket.emit("package-sync", {
|
|
update: MissionDocHelper.docAsUpdate(missionId),
|
|
timestamp: MissionDocHelper.docTimestamp(missionId),
|
|
source: "server",
|
|
});
|
|
}
|
|
|
|
socket.emit("package-init-awareness", {
|
|
update: MissionDocHelper.getAwarenessEditors(missionId),
|
|
type: "editors",
|
|
});
|
|
socket.emit("package-init-awareness", {
|
|
update: MissionDocHelper.getAwarenessState(missionId),
|
|
type: "state",
|
|
});
|
|
|
|
let newEditor = {
|
|
socketId: socket.id,
|
|
data: {
|
|
username: SocketMap.read(socket.id).username,
|
|
firstname: SocketMap.read(socket.id).firstname,
|
|
lastname: SocketMap.read(socket.id).lastname,
|
|
color: randomColor({ format: "hex" }),
|
|
},
|
|
};
|
|
MissionMap.updateAwareness(missionId, {
|
|
action: "update",
|
|
socketId: newEditor.socketId,
|
|
store: "editors",
|
|
update: newEditor.data,
|
|
});
|
|
socket.to(missionId).emit("package-sync-awareness", {
|
|
update: newEditor.data,
|
|
socketId: socket.id,
|
|
action: "update",
|
|
type: "editors",
|
|
});
|
|
|
|
return {
|
|
type: "status-mission:join",
|
|
answer: { status: "success" },
|
|
};
|
|
} catch (error) {
|
|
return { type: "status-join:join", answer: { status: "failed", msg: error.message } };
|
|
}
|
|
},
|
|
socket
|
|
)
|
|
);
|
|
|
|
socket.on(
|
|
"mission:sync-client-updates",
|
|
handleEvent(
|
|
{ type: "create", section: "operation", module: "mission" },
|
|
async (data: { update: Array<number>; timestamp: number }) => {
|
|
const socketRooms = Array.from(socket.rooms).filter((room) => room !== socket.id && room !== "home");
|
|
try {
|
|
MissionDocHelper.saveDoc(socketRooms[0], new Uint8Array(data.update));
|
|
|
|
return {
|
|
type: "package-sync",
|
|
answer: {
|
|
update: data.update,
|
|
timestamp: data.timestamp,
|
|
source: socket.id,
|
|
},
|
|
room: socketRooms[0],
|
|
};
|
|
} catch (error) {
|
|
socket.emit("package-sync", {
|
|
update: MissionDocHelper.docAsUpdate(socketRooms[0]),
|
|
timestamp: MissionDocHelper.docTimestamp(socketRooms[0]),
|
|
source: "server",
|
|
error: true,
|
|
});
|
|
return { type: "status-mission:sync-client-updates", answer: { status: "failed", msg: error.message } };
|
|
}
|
|
},
|
|
socket
|
|
)
|
|
);
|
|
|
|
socket.on(
|
|
"mission:sync-get-missing-updates",
|
|
handleEvent(
|
|
{ type: "create", section: "operation", module: "mission" },
|
|
async (data: any) => {
|
|
const socketRooms = Array.from(socket.rooms).filter((room) => room !== socket.id && room !== "home");
|
|
try {
|
|
const mission = MissionMap.read(socketRooms[0]);
|
|
const missingUpdates = Y.encodeStateAsUpdate(mission.doc, data.stateVector);
|
|
|
|
return {
|
|
type: "package-sync",
|
|
answer: {
|
|
update: missingUpdates,
|
|
timestamp: MissionDocHelper.docTimestamp(socketRooms[0]),
|
|
source: "server",
|
|
},
|
|
};
|
|
} catch (error) {
|
|
return { type: "status-mission:sync-get-missing-updates", answer: { status: "failed", msg: error.message } };
|
|
}
|
|
},
|
|
socket
|
|
)
|
|
);
|
|
|
|
socket.on(
|
|
"mission:sync-client-awareness",
|
|
handleEvent(
|
|
{ type: "create", section: "operation", module: "mission" },
|
|
async (data: EditorState) => {
|
|
const socketRooms = Array.from(socket.rooms).filter((room) => room !== socket.id && room !== "home");
|
|
try {
|
|
MissionMap.updateAwareness(socketRooms[0], {
|
|
action: "update",
|
|
store: "state",
|
|
update: data,
|
|
socketId: socket.id,
|
|
});
|
|
|
|
return {
|
|
type: "package-sync-awareness",
|
|
answer: {
|
|
type: "state",
|
|
action: "update",
|
|
update: data,
|
|
socketId: socket.id,
|
|
},
|
|
room: socketRooms[0],
|
|
};
|
|
} catch (error) {
|
|
socket.emit("package-sync-awareness", {
|
|
update: MissionDocHelper.docAsUpdate(socketRooms[0]),
|
|
source: "server",
|
|
error: true,
|
|
});
|
|
return { type: "status-mission:sync-client-updates", answer: { status: "failed", msg: error.message } };
|
|
}
|
|
},
|
|
socket
|
|
)
|
|
);
|
|
|
|
socket.on(
|
|
"mission:leave",
|
|
handleEvent(
|
|
{ type: "read", section: "operation", module: "mission" },
|
|
async (data: any) => {
|
|
const socketRooms = Array.from(socket.rooms).filter((room) => room !== socket.id && room !== "home");
|
|
socket.leave(socketRooms[0]);
|
|
|
|
const clients = io.sockets.adapter.rooms.get(socketRooms[0]);
|
|
if (!clients || clients.size == 0) {
|
|
MissionMap.delete(socketRooms[0]);
|
|
}
|
|
|
|
MissionMap.updateAwareness(socketRooms[0], {
|
|
action: "remove",
|
|
store: "editors",
|
|
update: undefined,
|
|
socketId: socket.id,
|
|
});
|
|
io.to(socketRooms[0]).emit("package-sync-awareness", {
|
|
type: "editors",
|
|
update: undefined,
|
|
action: "remove",
|
|
socketId: socket.id,
|
|
});
|
|
|
|
MissionMap.updateAwareness(socketRooms[0], {
|
|
action: "remove",
|
|
store: "state",
|
|
update: undefined,
|
|
socketId: socket.id,
|
|
});
|
|
io.to(socketRooms[0]).emit("package-sync-awareness", {
|
|
type: "state",
|
|
update: undefined,
|
|
action: "remove",
|
|
socketId: socket.id,
|
|
});
|
|
|
|
return {
|
|
type: "deleted",
|
|
answer: "leave instance",
|
|
};
|
|
},
|
|
socket
|
|
)
|
|
);
|
|
};
|