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.

297 lines
6.0 KiB

2 years ago
function serializer_create(size) {
const buffer = new ArrayBuffer(size);
return {
'offset': 0,
'size': size,
'buffer': buffer,
'view': new DataView(buffer),
'strview': new Uint8Array(buffer),
};
}
function ser_extend(s, by) {
const old_view = s.strview;
const old_offset = s.offset;
const s_copy = serializer_create(s.size + by)
s_copy.strview.set(old_view);
s_copy.offset = old_offset;
return s_copy;
}
2 years ago
function ser_u8(s, value) {
s.view.setUint8(s.offset, value);
s.offset += 1;
}
function ser_u16(s, value) {
s.view.setUint16(s.offset, value, true);
s.offset += 2;
}
2 years ago
function ser_f32(s, value) {
s.view.setFloat32(s.offset, value, true);
s.offset += 4;
}
2 years ago
function ser_u32(s, value) {
s.view.setUint32(s.offset, value, true);
s.offset += 4;
}
2 years ago
function ser_align(s, to) {
// TODO: non-stupid version of this
2 years ago
while (s.offset % to != 0) {
s.offset++;
}
}
2 years ago
function ser_event(s, event) {
ser_u8(s, event.type);
2 years ago
2 years ago
switch (event.type) {
case EVENT.PREDRAW: {
2 years ago
ser_f32(s, event.x);
ser_f32(s, event.y);
2 years ago
break;
}
case EVENT.CLEAR: {
break;
}
case EVENT.SET_COLOR: {
ser_u32(s, event.color);
break;
}
case EVENT.SET_WIDTH: {
ser_u16(s, event.width);
break;
}
2 years ago
case EVENT.STROKE: {
ser_u16(s, event.points.length);
ser_u16(s, event.width);
ser_u32(s, event.color);
2 years ago
if (config.debug_print) console.debug('original', event.points);
2 years ago
2 years ago
ser_align(s, 4);
2 years ago
for (const point of event.points) {
2 years ago
ser_f32(s, point.x);
ser_f32(s, point.y);
2 years ago
}
break;
}
case EVENT.IMAGE:
case EVENT.IMAGE_MOVE: {
2 years ago
const image_id = parseInt(event.image_id);
ser_u32(s, image_id);
2 years ago
ser_f32(s, event.x);
ser_f32(s, event.y);
2 years ago
break;
}
2 years ago
case EVENT.UNDO:
case EVENT.REDO: {
break;
}
2 years ago
case EVENT.ERASER: {
ser_u32(s, event.stroke_id);
break;
}
2 years ago
default: {
console.error('fuck');
}
}
}
async function send_ack(sn) {
const s = serializer_create(1 + 4);
ser_u8(s, MESSAGE.ACK);
ser_u32(s, sn);
if (config.debug_print) console.debug(`ack ${sn} out`);
2 years ago
try {
if (ws) await ws.send(s.buffer);
} catch(e) {
ws.close();
}
2 years ago
}
2 years ago
async function sync_queue(state) {
2 years ago
if (ws === null) {
if (config.debug_print) console.debug('socket has closed, stopping SYNs');
2 years ago
return;
}
2 years ago
let size = 1 + 3 + 4 + 4; // opcode + lsn + event count
let count = state.lsn - state.server_lsn;
2 years ago
if (count === 0) {
if (config.debug_print) console.debug('server ACKed all events, clearing queue');
2 years ago
state.queue.length = 0;
2 years ago
return;
}
for (let i = count - 1; i >= 0; --i) {
2 years ago
const event = state.queue[state.queue.length - 1 - i];
2 years ago
size += event_size(event);
}
const s = serializer_create(size);
ser_u8(s, MESSAGE.SYN);
2 years ago
ser_u32(s, state.lsn);
2 years ago
ser_u32(s, count);
for (let i = count - 1; i >= 0; --i) {
2 years ago
const event = state.queue[state.queue.length - 1 - i];
2 years ago
ser_event(s, event);
}
2 years ago
if (config.debug_print) console.debug(`syn ${state.lsn} out`);
2 years ago
try {
if (ws) await ws.send(s.buffer);
} catch(e) {
ws.close();
}
2 years ago
2 years ago
setTimeout(() => sync_queue(state), config.sync_timeout);
2 years ago
}
2 years ago
function push_event(state, event) {
state.lsn += 1;
2 years ago
switch (event.type) {
case EVENT.STROKE: {
2 years ago
state.queue.push({
'type': EVENT.STROKE,
2 years ago
'points': event.points,
'width': event.width,
'color': event.color,
});
2 years ago
break;
}
case EVENT.RULER: {
event.type = EVENT.STROKE;
2 years ago
state.queue.push(event);
break;
}
2 years ago
case EVENT.ERASER:
2 years ago
case EVENT.IMAGE:
case EVENT.IMAGE_MOVE:
2 years ago
case EVENT.UNDO:
case EVENT.REDO: {
2 years ago
state.queue.push(event);
2 years ago
break;
}
2 years ago
default: {
console.error('fuck');
}
2 years ago
}
}
// Queue an event and initialize repated sends until ACKed
2 years ago
function queue_event(state, event, skip = false) {
if (!state.online) { return; }
2 years ago
push_event(state, event);
2 years ago
if (skip) {
return;
}
2 years ago
if (state.timers.queue_sync) {
clearTimeout(state.timers.queue_sync);
2 years ago
}
2 years ago
sync_queue(state);
2 years ago
}
// Fire and forget. Doesn't do anything if we are offline
async function fire_event(state, event) {
if (!state.online) { return; }
2 years ago
const s = serializer_create(1 + event_size(event));
ser_u8(s, MESSAGE.FIRE);
ser_event(s, event);
try {
if (ws) await ws.send(s.buffer);
} catch(e) {
ws.close();
}
2 years ago
}
function predraw_event(x, y) {
return {
'type': EVENT.PREDRAW,
'x': x,
'y': y
};
}
function color_event(color_u32) {
return {
'type': EVENT.SET_COLOR,
'color': color_u32,
};
}
function width_event(width) {
return {
'type': EVENT.SET_WIDTH,
'width': width,
};
}
2 years ago
function image_event(image_id, x, y) {
return {
'type': EVENT.IMAGE,
'image_id': image_id,
'x': x,
'y': y,
};
}
function image_move_event(image_id, x, y) {
return {
'type': EVENT.IMAGE_MOVE,
'image_id': image_id,
'x': x,
'y': y,
};
}
2 years ago
function stroke_event(state) {
2 years ago
const stroke = geometry_prepare_stroke(state);
2 years ago
return {
'type': EVENT.STROKE,
2 years ago
'points': stroke.points,
'width': stroke.width,
'color': stroke.color,
2 years ago
};
}
function clear_event(state) {
return {
'type': EVENT.CLEAR
};
}