refactor websocket packets
This commit is contained in:
parent
693a403460
commit
7a2053fda3
|
@ -114,7 +114,7 @@ persistStore(store, {}, () => {
|
|||
store.dispatch(initTimer());
|
||||
|
||||
store.dispatch(fetchMe());
|
||||
SocketClient.connect();
|
||||
SocketClient.initialize(store);
|
||||
});
|
||||
|
||||
(function load() {
|
||||
|
|
|
@ -23,7 +23,7 @@ const GlobalCaptcha = ({ close }) => {
|
|||
<form
|
||||
onSubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
const text = e.target.captcha.value;
|
||||
const text = e.target.captcha.value.slice(0, 6);
|
||||
if (!text || text.length < 4) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
*
|
||||
*/
|
||||
import socketEvents from '../socket/socketEvents';
|
||||
import PixelUpdate from '../socket/packets/PixelUpdateServer';
|
||||
import {
|
||||
hydratePixelUpdate,
|
||||
} from '../socket/packets/server';
|
||||
import { setPixelByOffset } from './setPixel';
|
||||
import { TILE_SIZE } from './constants';
|
||||
import { CANVAS_ID } from '../data/redis/Event';
|
||||
|
@ -177,7 +179,7 @@ class Void {
|
|||
i: pi,
|
||||
j: pj,
|
||||
pixels,
|
||||
} = PixelUpdate.hydrate(buffer);
|
||||
} = hydratePixelUpdate(buffer);
|
||||
const { i, j } = this;
|
||||
// 3x3 chunk area (this is hardcoded on multiple places)
|
||||
if (pi >= i - 1 && pi <= i + 1 && pj >= j - 1 && pj <= j + 1) {
|
||||
|
|
|
@ -69,7 +69,7 @@ persistStore(store, {}, () => {
|
|||
|
||||
if (!parentExists()) {
|
||||
store.dispatch(fetchMe());
|
||||
SocketClient.connect();
|
||||
SocketClient.initialize(store);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -8,10 +8,20 @@
|
|||
|
||||
import { SHARD_NAME } from '../core/config';
|
||||
import SocketEvents from './SockEvents';
|
||||
import OnlineCounter from './packets/OnlineCounter';
|
||||
import PixelUpdate from './packets/PixelUpdateServer';
|
||||
import PixelUpdateMB from './packets/PixelUpdateMB';
|
||||
import ChunkUpdate from './packets/ChunkUpdate';
|
||||
import {
|
||||
ONLINE_COUNTER_OP,
|
||||
PIXEL_UPDATE_MB_OP,
|
||||
CHUNK_UPDATE_MB_OP,
|
||||
} from './packets/op';
|
||||
import {
|
||||
hydrateOnlineCounter,
|
||||
hydratePixelUpdateMB,
|
||||
hydrateChunkUpdateMB,
|
||||
dehydratePixelUpdate,
|
||||
dehydrateOnlineCounter,
|
||||
dehydratePixelUpdateMB,
|
||||
dehydrateChunkUpdateMB,
|
||||
} from './packets/server';
|
||||
import { pubsub } from '../data/redis/client';
|
||||
import { combineObjects } from '../core/utils';
|
||||
|
||||
|
@ -253,25 +263,25 @@ class MessageBroker extends SocketEvents {
|
|||
try {
|
||||
const opcode = buffer[0];
|
||||
switch (opcode) {
|
||||
case PixelUpdateMB.OP_CODE: {
|
||||
const puData = PixelUpdateMB.hydrate(buffer);
|
||||
case PIXEL_UPDATE_MB_OP: {
|
||||
const puData = hydratePixelUpdateMB(buffer);
|
||||
super.emit('pixelUpdate', ...puData);
|
||||
const chunkId = puData[1];
|
||||
const chunk = [chunkId >> 8, chunkId & 0xFF];
|
||||
super.emit('chunkUpdate', puData[0], chunk);
|
||||
break;
|
||||
}
|
||||
case ChunkUpdate.OP_CODE: {
|
||||
super.emit('chunkUpdate', ...ChunkUpdate.hydrate(buffer));
|
||||
case CHUNK_UPDATE_MB_OP: {
|
||||
super.emit('chunkUpdate', ...hydrateChunkUpdateMB(buffer));
|
||||
break;
|
||||
}
|
||||
case OnlineCounter.OP_CODE: {
|
||||
case ONLINE_COUNTER_OP: {
|
||||
const data = new DataView(
|
||||
buffer.buffer,
|
||||
buffer.byteOffset,
|
||||
buffer.length,
|
||||
);
|
||||
const cnt = OnlineCounter.hydrate(data);
|
||||
const cnt = hydrateOnlineCounter(data);
|
||||
this.updateShardOnlineCounter(shard, cnt);
|
||||
break;
|
||||
}
|
||||
|
@ -324,9 +334,9 @@ class MessageBroker extends SocketEvents {
|
|||
const j = chunkId & 0xFF;
|
||||
this.publisher.publish(
|
||||
this.thisShard,
|
||||
PixelUpdateMB.dehydrate(canvasId, i, j, pixels),
|
||||
dehydratePixelUpdateMB(canvasId, i, j, pixels),
|
||||
);
|
||||
const buffer = PixelUpdate.dehydrate(i, j, pixels);
|
||||
const buffer = dehydratePixelUpdate(i, j, pixels);
|
||||
super.emit('pixelUpdate', canvasId, chunkId, buffer);
|
||||
super.emit('chunkUpdate', canvasId, [i, j]);
|
||||
}
|
||||
|
@ -353,18 +363,18 @@ class MessageBroker extends SocketEvents {
|
|||
) {
|
||||
this.publisher.publish(
|
||||
this.thisShard,
|
||||
ChunkUpdate.dehydrate(canvasId, chunk),
|
||||
dehydrateChunkUpdateMB(canvasId, chunk),
|
||||
);
|
||||
super.emit('chunkUpdate', canvasId, chunk);
|
||||
}
|
||||
|
||||
broadcastOnlineCounter(online) {
|
||||
this.updateShardOnlineCounter(this.thisShard, online);
|
||||
let buffer = OnlineCounter.dehydrate(online);
|
||||
// send our online counter to other shards
|
||||
let buffer = dehydrateOnlineCounter(online);
|
||||
this.publisher.publish(this.thisShard, buffer);
|
||||
// send total counter to our players
|
||||
buffer = OnlineCounter.dehydrate(this.onlineCounter);
|
||||
buffer = dehydrateOnlineCounter(this.onlineCounter);
|
||||
super.emit('onlineCounter', buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
*/
|
||||
import EventEmitter from 'events';
|
||||
|
||||
import OnlineCounter from './packets/OnlineCounter';
|
||||
import PixelUpdate from './packets/PixelUpdateServer';
|
||||
|
||||
import {
|
||||
dehydrateOnlineCounter,
|
||||
dehydratePixelUpdate,
|
||||
} from './packets/server';
|
||||
|
||||
class SocketEvents extends EventEmitter {
|
||||
constructor() {
|
||||
|
@ -97,7 +98,7 @@ class SocketEvents extends EventEmitter {
|
|||
) {
|
||||
const i = chunkId >> 8;
|
||||
const j = chunkId & 0xFF;
|
||||
const buffer = PixelUpdate.dehydrate(i, j, pixels);
|
||||
const buffer = dehydratePixelUpdate(i, j, pixels);
|
||||
this.emit('pixelUpdate', canvasId, chunkId, buffer);
|
||||
this.emit('chunkUpdate', canvasId, [i, j]);
|
||||
}
|
||||
|
@ -254,7 +255,7 @@ class SocketEvents extends EventEmitter {
|
|||
*/
|
||||
broadcastOnlineCounter(online) {
|
||||
this.onlineCounter = online;
|
||||
const buffer = OnlineCounter.dehydrate(online);
|
||||
const buffer = dehydrateOnlineCounter(online);
|
||||
this.emit('onlineCounter', buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
|
||||
// allow the websocket to be noisy on the console
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import EventEmitter from 'events';
|
||||
|
||||
import CoolDownPacket from './packets/CoolDownPacket';
|
||||
import PixelUpdate from './packets/PixelUpdateClient';
|
||||
import PixelReturn from './packets/PixelReturn';
|
||||
import OnlineCounter from './packets/OnlineCounter';
|
||||
import RegisterCanvas from './packets/RegisterCanvas';
|
||||
import RegisterChunk from './packets/RegisterChunk';
|
||||
import RegisterMultipleChunks from './packets/RegisterMultipleChunks';
|
||||
import DeRegisterChunk from './packets/DeRegisterChunk';
|
||||
import ChangedMe from './packets/ChangedMe';
|
||||
import Ping from './packets/Ping';
|
||||
import {
|
||||
hydratePixelUpdate,
|
||||
hydratePixelReturn,
|
||||
hydrateOnlineCounter,
|
||||
hydrateCoolDown,
|
||||
dehydrateRegCanvas,
|
||||
dehydrateRegChunk,
|
||||
dehydrateRegMChunks,
|
||||
dehydrateDeRegChunk,
|
||||
dehydrateCaptchaSolution,
|
||||
dehydratePixelUpdate,
|
||||
dehydratePing,
|
||||
} from './packets/client';
|
||||
import {
|
||||
PIXEL_UPDATE_OP,
|
||||
PIXEL_RETURN_OP,
|
||||
ONLINE_COUNTER_OP,
|
||||
COOLDOWN_OP,
|
||||
CHANGE_ME_OP,
|
||||
} from './packets/op';
|
||||
import { shardHost } from '../store/actions/fetch';
|
||||
|
||||
const chunks = [];
|
||||
|
@ -22,8 +31,8 @@ class SocketClient extends EventEmitter {
|
|||
constructor() {
|
||||
super();
|
||||
console.log('Creating WebSocketClient');
|
||||
this.store = null;
|
||||
this.ws = null;
|
||||
this.canvasId = 0;
|
||||
this.channelId = 0;
|
||||
/*
|
||||
* properties set in connect and open:
|
||||
|
@ -38,6 +47,11 @@ class SocketClient extends EventEmitter {
|
|||
setInterval(this.checkHealth, 2000);
|
||||
}
|
||||
|
||||
initialize(store) {
|
||||
this.store = store;
|
||||
return this.connect();
|
||||
}
|
||||
|
||||
async connect() {
|
||||
this.readyState = WebSocket.CONNECTING;
|
||||
if (this.ws) {
|
||||
|
@ -70,7 +84,7 @@ class SocketClient extends EventEmitter {
|
|||
}
|
||||
if (now - 23000 > this.timeLastSent) {
|
||||
// make sure we send something at least all 25s
|
||||
this.send(Ping.dehydrate());
|
||||
this.send(dehydratePing());
|
||||
this.timeLastSent = now;
|
||||
}
|
||||
}
|
||||
|
@ -110,31 +124,28 @@ class SocketClient extends EventEmitter {
|
|||
|
||||
this.emit('open', {});
|
||||
this.readyState = WebSocket.OPEN;
|
||||
this.send(RegisterCanvas.dehydrate(this.canvasId));
|
||||
this.send(dehydrateRegCanvas(
|
||||
this.store.getState().canvas,
|
||||
));
|
||||
console.log(`Register ${chunks.length} chunks`);
|
||||
this.send(RegisterMultipleChunks.dehydrate(chunks));
|
||||
this.send(dehydrateRegMChunks(chunks));
|
||||
this.processMsgQueue();
|
||||
}
|
||||
|
||||
setCanvas(canvasId) {
|
||||
/* canvasId can be string or integer, thanks to
|
||||
* JSON not allowing integer keys
|
||||
*/
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (this.canvasId == canvasId || canvasId === null) {
|
||||
if (canvasId === null) {
|
||||
return;
|
||||
}
|
||||
console.log('Notify websocket server that we changed canvas');
|
||||
this.canvasId = canvasId;
|
||||
chunks.length = 0;
|
||||
this.send(RegisterCanvas.dehydrate(this.canvasId));
|
||||
this.send(dehydrateRegCanvas(canvasId));
|
||||
}
|
||||
|
||||
registerChunk(cell) {
|
||||
const [i, j] = cell;
|
||||
const chunkid = (i << 8) | j;
|
||||
chunks.push(chunkid);
|
||||
const buffer = RegisterChunk.dehydrate(chunkid);
|
||||
const buffer = dehydrateRegChunk(chunkid);
|
||||
if (this.readyState === WebSocket.OPEN) {
|
||||
this.send(buffer);
|
||||
}
|
||||
|
@ -143,7 +154,7 @@ class SocketClient extends EventEmitter {
|
|||
deRegisterChunk(cell) {
|
||||
const [i, j] = cell;
|
||||
const chunkid = (i << 8) | j;
|
||||
const buffer = DeRegisterChunk.dehydrate(chunkid);
|
||||
const buffer = dehydrateDeRegChunk(chunkid);
|
||||
if (this.readyState === WebSocket.OPEN) {
|
||||
this.send(buffer);
|
||||
}
|
||||
|
@ -151,6 +162,12 @@ class SocketClient extends EventEmitter {
|
|||
if (~pos) chunks.splice(pos, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
sendCaptchaSolution(solution) {
|
||||
const buffer = dehydrateCaptchaSolution(solution);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send pixel request
|
||||
* @param i, j chunk coordinates
|
||||
|
@ -160,7 +177,7 @@ class SocketClient extends EventEmitter {
|
|||
i, j,
|
||||
pixels,
|
||||
) {
|
||||
const buffer = PixelUpdate.dehydrate(i, j, pixels);
|
||||
const buffer = dehydratePixelUpdate(i, j, pixels);
|
||||
this.sendWhenReady(buffer);
|
||||
}
|
||||
|
||||
|
@ -196,7 +213,6 @@ class SocketClient extends EventEmitter {
|
|||
name, text, country, Number(channelId), userId);
|
||||
return;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
// signal
|
||||
const [signal, args] = data;
|
||||
|
@ -217,19 +233,19 @@ class SocketClient extends EventEmitter {
|
|||
this.timeLastPing = Date.now();
|
||||
|
||||
switch (opcode) {
|
||||
case PixelUpdate.OP_CODE:
|
||||
this.emit('pixelUpdate', PixelUpdate.hydrate(data));
|
||||
case PIXEL_UPDATE_OP:
|
||||
this.emit('pixelUpdate', hydratePixelUpdate(data));
|
||||
break;
|
||||
case PixelReturn.OP_CODE:
|
||||
this.emit('pixelReturn', PixelReturn.hydrate(data));
|
||||
case PIXEL_RETURN_OP:
|
||||
this.emit('pixelReturn', hydratePixelReturn(data));
|
||||
break;
|
||||
case OnlineCounter.OP_CODE:
|
||||
this.emit('onlineCounter', OnlineCounter.hydrate(data));
|
||||
case ONLINE_COUNTER_OP:
|
||||
this.emit('onlineCounter', hydrateOnlineCounter(data));
|
||||
break;
|
||||
case CoolDownPacket.OP_CODE:
|
||||
this.emit('cooldownPacket', CoolDownPacket.hydrate(data));
|
||||
case COOLDOWN_OP:
|
||||
this.emit('cooldownPacket', hydrateCoolDown(data));
|
||||
break;
|
||||
case ChangedMe.OP_CODE:
|
||||
case CHANGE_ME_OP:
|
||||
console.log('Websocket requested api/me reload');
|
||||
this.emit('changedMe');
|
||||
this.reconnect();
|
||||
|
|
|
@ -7,18 +7,28 @@ import logger from '../core/logger';
|
|||
import canvases from '../core/canvases';
|
||||
import Counter from '../utils/Counter';
|
||||
import { getIPFromRequest, getHostFromRequest } from '../utils/ip';
|
||||
|
||||
import CoolDownPacket from './packets/CoolDownPacket';
|
||||
import PixelUpdate from './packets/PixelUpdateServer';
|
||||
import PixelReturn from './packets/PixelReturn';
|
||||
import RegisterCanvas from './packets/RegisterCanvas';
|
||||
import RegisterChunk from './packets/RegisterChunk';
|
||||
import RegisterMultipleChunks from './packets/RegisterMultipleChunks';
|
||||
import DeRegisterChunk from './packets/DeRegisterChunk';
|
||||
import DeRegisterMultipleChunks from './packets/DeRegisterMultipleChunks';
|
||||
import ChangedMe from './packets/ChangedMe';
|
||||
import OnlineCounter from './packets/OnlineCounter';
|
||||
|
||||
import {
|
||||
REG_CANVAS_OP,
|
||||
PIXEL_UPDATE_OP,
|
||||
REG_CHUNK_OP,
|
||||
REG_MCHUNKS_OP,
|
||||
DEREG_CHUNK_OP,
|
||||
DEREG_MCHUNKS_OP,
|
||||
} from './packets/op';
|
||||
import {
|
||||
hydrateRegCanvas,
|
||||
hydrateRegChunk,
|
||||
hydrateDeRegChunk,
|
||||
hydrateRegMChunks,
|
||||
hydrateDeRegMChunks,
|
||||
hydrateCaptchaSolution,
|
||||
hydratePixelUpdate,
|
||||
dehydrateChangeMe,
|
||||
dehydrateOnlineCounter,
|
||||
dehydratePixelUpdate,
|
||||
dehydrateCoolDown,
|
||||
dehydratePixelReturn,
|
||||
} from './packets/server';
|
||||
import socketEvents from './socketEvents';
|
||||
import chatProvider, { ChatProvider } from '../core/ChatProvider';
|
||||
import authenticateClient from './authenticateClient';
|
||||
|
@ -88,7 +98,7 @@ class SocketServer {
|
|||
|
||||
const { ip } = user;
|
||||
|
||||
ws.send(OnlineCounter.dehydrate(socketEvents.onlineCounter));
|
||||
ws.send(dehydrateOnlineCounter(socketEvents.onlineCounter));
|
||||
|
||||
ws.on('error', (e) => {
|
||||
logger.error(`WebSocket Client Error for ${ws.name}: ${e.message}`);
|
||||
|
@ -341,7 +351,7 @@ class SocketServer {
|
|||
if (ws.name === name) {
|
||||
await ws.user.reload();
|
||||
ws.name = ws.user.getName();
|
||||
const buffer = ChangedMe.dehydrate();
|
||||
const buffer = dehydrateChangeMe();
|
||||
ws.send(buffer);
|
||||
}
|
||||
});
|
||||
|
@ -474,7 +484,7 @@ class SocketServer {
|
|||
try {
|
||||
const opcode = buffer[0];
|
||||
switch (opcode) {
|
||||
case PixelUpdate.OP_CODE: {
|
||||
case PIXEL_UPDATE_OP: {
|
||||
const { canvasId, user } = ws;
|
||||
const { ip } = user;
|
||||
|
||||
|
@ -499,7 +509,7 @@ class SocketServer {
|
|||
|
||||
const {
|
||||
i, j, pixels,
|
||||
} = PixelUpdate.hydrate(buffer);
|
||||
} = hydratePixelUpdate(buffer);
|
||||
const {
|
||||
wait,
|
||||
coolDown,
|
||||
|
@ -522,7 +532,7 @@ class SocketServer {
|
|||
}
|
||||
}
|
||||
|
||||
ws.send(PixelReturn.dehydrate(
|
||||
ws.send(dehydratePixelReturn(
|
||||
retCode,
|
||||
wait,
|
||||
coolDown,
|
||||
|
@ -531,42 +541,38 @@ class SocketServer {
|
|||
));
|
||||
break;
|
||||
}
|
||||
case RegisterCanvas.OP_CODE: {
|
||||
const canvasId = RegisterCanvas.hydrate(buffer);
|
||||
case REG_CANVAS_OP: {
|
||||
const canvasId = hydrateRegCanvas(buffer);
|
||||
if (!canvases[canvasId]) return;
|
||||
if (ws.canvasId !== null && ws.canvasId !== canvasId) {
|
||||
this.deleteAllChunks(ws);
|
||||
}
|
||||
ws.canvasId = canvasId;
|
||||
const wait = await ws.user.getWait(canvasId);
|
||||
ws.send(CoolDownPacket.dehydrate(wait));
|
||||
ws.send(dehydrateCoolDown(wait));
|
||||
break;
|
||||
}
|
||||
case RegisterChunk.OP_CODE: {
|
||||
const chunkid = RegisterChunk.hydrate(buffer);
|
||||
case REG_CHUNK_OP: {
|
||||
const chunkid = hydrateRegChunk(buffer);
|
||||
this.pushChunk(chunkid, ws);
|
||||
break;
|
||||
}
|
||||
case RegisterMultipleChunks.OP_CODE: {
|
||||
case REG_MCHUNKS_OP: {
|
||||
this.deleteAllChunks(ws);
|
||||
let posu = 2;
|
||||
while (posu < buffer.length) {
|
||||
const chunkid = buffer[posu++] | buffer[posu++] << 8;
|
||||
hydrateRegMChunks(buffer, (chunkid) => {
|
||||
this.pushChunk(chunkid, ws);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case DeRegisterChunk.OP_CODE: {
|
||||
const chunkidn = DeRegisterChunk.hydrate(buffer);
|
||||
this.deleteChunk(chunkidn, ws);
|
||||
break;
|
||||
}
|
||||
case DeRegisterMultipleChunks.OP_CODE: {
|
||||
let posl = 2;
|
||||
while (posl < buffer.length) {
|
||||
const chunkid = buffer[posl++] | buffer[posl++] << 8;
|
||||
case DEREG_CHUNK_OP: {
|
||||
const chunkid = hydrateDeRegChunk(buffer);
|
||||
this.deleteChunk(chunkid, ws);
|
||||
break;
|
||||
}
|
||||
case DEREG_MCHUNKS_OP: {
|
||||
hydrateDeRegMChunks(buffer, (chunkid) => {
|
||||
this.deleteChunk(chunkid, ws);
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
const OP_CODE = 0xA6;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
|
||||
dehydrate() {
|
||||
// Server (sender)
|
||||
return new Uint8Array([OP_CODE]).buffer;
|
||||
},
|
||||
};
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* notify that chunk changed
|
||||
* (not sent over websocket, server only)
|
||||
*/
|
||||
|
||||
const OP_CODE = 0xC4;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
/*
|
||||
* @return canvasId, [i, j]
|
||||
*/
|
||||
hydrate(data) {
|
||||
const canvasId = data[1];
|
||||
const i = data.readUInt8(2);
|
||||
const j = data.readUInt8(3);
|
||||
return [canvasId, [i, j]];
|
||||
},
|
||||
/*
|
||||
* @param canvasId,
|
||||
* chunkid id consisting of chunk coordinates
|
||||
*/
|
||||
dehydrate(canvasId, [i, j]) {
|
||||
return Buffer.from([
|
||||
OP_CODE,
|
||||
canvasId,
|
||||
i,
|
||||
j,
|
||||
]);
|
||||
},
|
||||
};
|
|
@ -1,16 +0,0 @@
|
|||
const OP_CODE = 0xC2;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
hydrate(data) {
|
||||
// client (receiver)
|
||||
return data.getUint32(1);
|
||||
},
|
||||
dehydrate(wait) {
|
||||
// Server (sender)
|
||||
const buffer = Buffer.allocUnsafe(1 + 4);
|
||||
buffer.writeUInt8(OP_CODE, 0);
|
||||
buffer.writeUInt32BE(wait, 1);
|
||||
return buffer;
|
||||
},
|
||||
};
|
|
@ -1,18 +0,0 @@
|
|||
const OP_CODE = 0xA2;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
hydrate(data) {
|
||||
// SERVER (Receiver)
|
||||
const i = data[1] << 8 | data[2];
|
||||
return i;
|
||||
},
|
||||
dehydrate(chunkid) {
|
||||
// CLIENT (Sender)
|
||||
const buffer = new ArrayBuffer(1 + 2);
|
||||
const view = new DataView(buffer);
|
||||
view.setInt8(0, OP_CODE);
|
||||
view.setInt16(1, chunkid);
|
||||
return buffer;
|
||||
},
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
const OP_CODE = 0xA4;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
/*
|
||||
* @param chunks Array of chunks
|
||||
*/
|
||||
dehydrate(chunks) {
|
||||
// CLIENT (Sender)
|
||||
const buffer = new ArrayBuffer(1 + 1 + chunks.length * 2);
|
||||
const view = new Uint16Array(buffer);
|
||||
// this will result into a double first byte, but still better than
|
||||
// shifting 16bit integers around later
|
||||
view[0] = OP_CODE;
|
||||
for (let cnt = 0; cnt < chunks.length; cnt += 1) {
|
||||
view[cnt + 1] = chunks[cnt];
|
||||
}
|
||||
return buffer;
|
||||
},
|
||||
};
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Numbers of online players per canvas
|
||||
*
|
||||
*/
|
||||
|
||||
const OP_CODE = 0xA7;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
// CLIENT (receiver)
|
||||
/*
|
||||
* {
|
||||
* total: totalOnline,
|
||||
* canvasId: online,
|
||||
* ....
|
||||
* }
|
||||
*/
|
||||
hydrate(data) {
|
||||
const online = {};
|
||||
online.total = data.getUint16(1);
|
||||
let off = data.byteLength;
|
||||
while (off > 3) {
|
||||
const onlineUsers = data.getUint16(off -= 2);
|
||||
const canvas = data.getUint8(off -= 1);
|
||||
online[canvas] = onlineUsers;
|
||||
}
|
||||
return online;
|
||||
},
|
||||
|
||||
dehydrate(online) {
|
||||
// SERVER (sender)
|
||||
if (!process.env.BROWSER) {
|
||||
const canvasIds = Object.keys(online).filter((id) => id !== 'total');
|
||||
|
||||
const buffer = Buffer.allocUnsafe(3 + canvasIds.length * (1 + 2));
|
||||
buffer.writeUInt8(OP_CODE, 0);
|
||||
buffer.writeUInt16BE(online.total, 1);
|
||||
let cnt = 1;
|
||||
for (let p = 0; p < canvasIds.length; p += 1) {
|
||||
const canvasId = canvasIds[p];
|
||||
const onlineUsers = online[canvasId];
|
||||
buffer.writeUInt8(Number(canvasId), cnt += 2);
|
||||
buffer.writeUInt16BE(onlineUsers, cnt += 1);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
const OP_CODE = 0xB0;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
|
||||
dehydrate() {
|
||||
// Client (sender)
|
||||
return new Uint8Array([OP_CODE]).buffer;
|
||||
},
|
||||
};
|
|
@ -1,38 +0,0 @@
|
|||
const OP_CODE = 0xC3;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
hydrate(data) {
|
||||
// Client (receiver)
|
||||
const retCode = data.getUint8(1);
|
||||
const wait = data.getUint32(2);
|
||||
const coolDownSeconds = data.getInt16(6);
|
||||
const pxlCnt = data.getUint8(8);
|
||||
const rankedPxlCnt = data.getUint8(9);
|
||||
return {
|
||||
retCode,
|
||||
wait,
|
||||
coolDownSeconds,
|
||||
pxlCnt,
|
||||
rankedPxlCnt,
|
||||
};
|
||||
},
|
||||
dehydrate(
|
||||
retCode,
|
||||
wait,
|
||||
coolDown,
|
||||
pxlCnt,
|
||||
rankedPxlCnt,
|
||||
) {
|
||||
// Server (sender)
|
||||
const buffer = Buffer.allocUnsafe(1 + 1 + 4 + 2 + 1 + 1);
|
||||
buffer.writeUInt8(OP_CODE, 0);
|
||||
buffer.writeUInt8(retCode, 1);
|
||||
buffer.writeUInt32BE(wait, 2);
|
||||
const coolDownSeconds = Math.round(coolDown / 1000);
|
||||
buffer.writeInt16BE(coolDownSeconds, 6);
|
||||
buffer.writeUInt8(pxlCnt, 8);
|
||||
buffer.writeUInt8(rankedPxlCnt, 9);
|
||||
return buffer;
|
||||
},
|
||||
};
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Packet for sending and receiving pixels per chunk
|
||||
* Multiple pixels can be sent at once
|
||||
* Client side
|
||||
*
|
||||
*/
|
||||
|
||||
const OP_CODE = 0xC1;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
/*
|
||||
* @param data DataVies
|
||||
*/
|
||||
hydrate(data) {
|
||||
/*
|
||||
* chunk coordinates
|
||||
*/
|
||||
const i = data.getUint8(1);
|
||||
const j = data.getUint8(2);
|
||||
/*
|
||||
* offset and color of every pixel
|
||||
* 3 bytes offset
|
||||
* 1 byte color
|
||||
*/
|
||||
const pixels = [];
|
||||
let off = data.byteLength;
|
||||
while (off > 3) {
|
||||
const color = data.getUint8(off -= 1);
|
||||
const offsetL = data.getUint16(off -= 2);
|
||||
const offsetH = data.getUint8(off -= 1) << 16;
|
||||
pixels.push([offsetH | offsetL, color]);
|
||||
}
|
||||
return {
|
||||
i, j, pixels,
|
||||
};
|
||||
},
|
||||
|
||||
dehydrate(i, j, pixels) {
|
||||
const buffer = new ArrayBuffer(1 + 1 + 1 + pixels.length * 4);
|
||||
const view = new DataView(buffer);
|
||||
view.setUint8(0, OP_CODE);
|
||||
/*
|
||||
* chunk coordinates
|
||||
*/
|
||||
view.setUint8(1, i);
|
||||
view.setUint8(2, j);
|
||||
/*
|
||||
* offset and color of every pixel
|
||||
* 3 bytes offset
|
||||
* 1 byte color
|
||||
*/
|
||||
let cnt = 2;
|
||||
let p = pixels.length;
|
||||
while (p) {
|
||||
p -= 1;
|
||||
const [offset, color] = pixels[p];
|
||||
view.setUint8(cnt += 1, offset >>> 16);
|
||||
view.setUint16(cnt += 1, offset & 0x00FFFF);
|
||||
view.setUint8(cnt += 2, color);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
},
|
||||
|
||||
};
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Packet for sending and receiving pixels over Message Broker between shards
|
||||
* Multiple pixels can be sent at once
|
||||
*
|
||||
*/
|
||||
|
||||
const OP_CODE = 0xC1;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
/*
|
||||
* returns info and PixelUpdate package to send to clients
|
||||
*/
|
||||
hydrate(data) {
|
||||
const canvasId = data[1];
|
||||
data.writeUInt8(OP_CODE, 1);
|
||||
const chunkId = data.readUInt16BE(2);
|
||||
const pixelUpdate = Buffer.from(
|
||||
data.buffer,
|
||||
data.byteOffset + 1,
|
||||
data.length - 1,
|
||||
);
|
||||
return [
|
||||
canvasId,
|
||||
chunkId,
|
||||
pixelUpdate,
|
||||
];
|
||||
},
|
||||
|
||||
/*
|
||||
* @param canvasId
|
||||
* @param chunkId id consisting of chunk coordinates
|
||||
* @param pixels Buffer with offset and color of one or more pixels
|
||||
*/
|
||||
dehydrate(canvasId, i, j, pixels) {
|
||||
const index = new Uint8Array([
|
||||
OP_CODE,
|
||||
canvasId,
|
||||
i,
|
||||
j,
|
||||
]);
|
||||
return Buffer.concat([index, pixels]);
|
||||
},
|
||||
};
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Packet for sending and receiving pixels per chunk
|
||||
* Multiple pixels can be sent at once
|
||||
* Server side.
|
||||
*
|
||||
* */
|
||||
|
||||
const OP_CODE = 0xC1;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
hydrate(data) {
|
||||
/*
|
||||
* chunk coordinates
|
||||
*/
|
||||
const i = data.readUInt8(1);
|
||||
const j = data.readUInt8(2);
|
||||
/*
|
||||
* offset and color of every pixel
|
||||
* 3 bytes offset
|
||||
* 1 byte color
|
||||
*/
|
||||
const pixels = [];
|
||||
let off = data.length;
|
||||
/*
|
||||
* limit the max amount of pixels that can be
|
||||
* receive to 500
|
||||
*/
|
||||
let pxlcnt = 0;
|
||||
while (off > 3 && pxlcnt < 500) {
|
||||
const color = data.readUInt8(off -= 1);
|
||||
const offsetL = data.readUInt16BE(off -= 2);
|
||||
const offsetH = data.readUInt8(off -= 1) << 16;
|
||||
pixels.push([offsetH | offsetL, color]);
|
||||
pxlcnt += 1;
|
||||
}
|
||||
return {
|
||||
i, j, pixels,
|
||||
};
|
||||
},
|
||||
|
||||
/*
|
||||
* @param chunkId id consisting of chunk coordinates
|
||||
* @param pixels Buffer with offset and color of one or more pixels
|
||||
*/
|
||||
dehydrate(i, j, pixels) {
|
||||
const index = new Uint8Array([OP_CODE, i, j]);
|
||||
return Buffer.concat([index, pixels]);
|
||||
},
|
||||
};
|
|
@ -1,6 +1,4 @@
|
|||
# Binary Websocket Packages
|
||||
|
||||
Note that the node Server receives in [Buffer](https://nodejs.org/api/buffer.html), while the client receives [DataViews](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) and sends ArrayBuffers.
|
||||
Therefor the server can't share the same code with the client for hydrate / dehydrate.
|
||||
Most packages are unidirectional so hydrate is for either client or server and dehydrate for the other one.
|
||||
Bidrectional packages have two files, one for Client, another one for Server.
|
||||
Note that the node Server receives and sends in [Buffer](https://nodejs.org/api/buffer.html), while the client receives [DataViews](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) and sends ArrayBuffers.
|
||||
Therefor the server can't share the same code with the client for hydrate / dehydrate and it's split in two files.
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
const OP_CODE = 0xA0;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
hydrate(data) {
|
||||
// SERVER (Receiver)
|
||||
const canvasId = data[1];
|
||||
return canvasId;
|
||||
},
|
||||
dehydrate(canvasId) {
|
||||
// CLIENT (Sender)
|
||||
const buffer = new ArrayBuffer(1 + 1);
|
||||
const view = new DataView(buffer);
|
||||
view.setInt8(0, OP_CODE);
|
||||
view.setInt8(1, Number(canvasId));
|
||||
return buffer;
|
||||
},
|
||||
};
|
|
@ -1,18 +0,0 @@
|
|||
const OP_CODE = 0xA1;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
hydrate(data) {
|
||||
// SERVER (Receiver)
|
||||
const i = data[1] << 8 | data[2];
|
||||
return i;
|
||||
},
|
||||
dehydrate(chunkid) {
|
||||
// CLIENT (Sender)
|
||||
const buffer = new ArrayBuffer(1 + 2);
|
||||
const view = new DataView(buffer);
|
||||
view.setInt8(0, OP_CODE);
|
||||
view.setInt16(1, chunkid);
|
||||
return buffer;
|
||||
},
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
const OP_CODE = 0xA3;
|
||||
|
||||
export default {
|
||||
OP_CODE,
|
||||
/*
|
||||
* @param chunks Array of chunks
|
||||
*/
|
||||
dehydrate(chunks) {
|
||||
// CLIENT (Sender)
|
||||
const buffer = new ArrayBuffer(1 + 1 + chunks.length * 2);
|
||||
const view = new Uint16Array(buffer);
|
||||
// this will result into a double first byte, but still better than
|
||||
// shifting 16bit integers around later
|
||||
view[0] = OP_CODE;
|
||||
for (let cnt = 0; cnt < chunks.length; cnt += 1) {
|
||||
view[cnt + 1] = chunks[cnt];
|
||||
}
|
||||
return buffer;
|
||||
},
|
||||
};
|
196
src/socket/packets/client.js
Normal file
196
src/socket/packets/client.js
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* client package hydration
|
||||
*/
|
||||
import {
|
||||
REG_CANVAS_OP,
|
||||
REG_CHUNK_OP,
|
||||
DEREG_CHUNK_OP,
|
||||
REG_MCHUNKS_OP,
|
||||
DEREG_MCHUNKS_OP,
|
||||
CAPTCHA_SOLUTION_OP,
|
||||
PING_OP,
|
||||
PIXEL_UPDATE_OP,
|
||||
} from './op';
|
||||
|
||||
/*
|
||||
* data in hydrate functions is DataView
|
||||
*/
|
||||
|
||||
/*
|
||||
* @return {
|
||||
* total: totalOnline,
|
||||
* canvasId: online,
|
||||
* ....
|
||||
* }
|
||||
*/
|
||||
export function hydrateOnlineCounter(data) {
|
||||
const online = {};
|
||||
online.total = data.getUint16(1);
|
||||
let off = data.byteLength;
|
||||
while (off > 3) {
|
||||
const onlineUsers = data.getUint16(off -= 2);
|
||||
const canvas = data.getUint8(off -= 1);
|
||||
online[canvas] = onlineUsers;
|
||||
}
|
||||
return online;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return chunk coordinates and array of pixel offset and colors
|
||||
*/
|
||||
export function hydratePixelUpdate(data) {
|
||||
const i = data.getUint8(1);
|
||||
const j = data.getUint8(2);
|
||||
/*
|
||||
* offset and color of every pixel
|
||||
* 3 bytes offset
|
||||
* 1 byte color
|
||||
*/
|
||||
const pixels = [];
|
||||
let off = data.byteLength;
|
||||
while (off > 3) {
|
||||
const color = data.getUint8(off -= 1);
|
||||
const offsetL = data.getUint16(off -= 2);
|
||||
const offsetH = data.getUint8(off -= 1) << 16;
|
||||
pixels.push([offsetH | offsetL, color]);
|
||||
}
|
||||
return {
|
||||
i, j, pixels,
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* @return cooldown in ms
|
||||
*/
|
||||
export function hydrateCoolDown(data) {
|
||||
return data.getUint32(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* @return see ui/placePixels
|
||||
*/
|
||||
export function hydratePixelReturn(data) {
|
||||
// Client (receiver)
|
||||
const retCode = data.getUint8(1);
|
||||
const wait = data.getUint32(2);
|
||||
const coolDownSeconds = data.getInt16(6);
|
||||
const pxlCnt = data.getUint8(8);
|
||||
const rankedPxlCnt = data.getUint8(9);
|
||||
return {
|
||||
retCode,
|
||||
wait,
|
||||
coolDownSeconds,
|
||||
pxlCnt,
|
||||
rankedPxlCnt,
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* dehydrate functions return ArrayBuffer object
|
||||
*/
|
||||
|
||||
/*
|
||||
* @param canvasId
|
||||
*/
|
||||
export function dehydrateRegCanvas(canvasId) {
|
||||
const buffer = new ArrayBuffer(1 + 1);
|
||||
const view = new DataView(buffer);
|
||||
view.setInt8(0, REG_CANVAS_OP);
|
||||
view.setInt8(1, Number(canvasId));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param chunkid
|
||||
*/
|
||||
export function dehydrateRegChunk(chunkid) {
|
||||
const buffer = new ArrayBuffer(1 + 2);
|
||||
const view = new DataView(buffer);
|
||||
view.setInt8(0, REG_CHUNK_OP);
|
||||
view.setInt16(1, chunkid);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param chunkid
|
||||
*/
|
||||
export function dehydrateDeRegChunk(chunkid) {
|
||||
const buffer = new ArrayBuffer(1 + 2);
|
||||
const view = new DataView(buffer);
|
||||
view.setInt8(0, DEREG_CHUNK_OP);
|
||||
view.setInt16(1, chunkid);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param chunks Array of chunkIds
|
||||
*/
|
||||
export function dehydrateRegMChunks(chunks) {
|
||||
const buffer = new ArrayBuffer(1 + 1 + chunks.length * 2);
|
||||
const view = new Uint16Array(buffer);
|
||||
// this will result into a double first byte, but still better than
|
||||
// shifting 16bit integers around later
|
||||
view[0] = REG_MCHUNKS_OP;
|
||||
for (let cnt = 0; cnt < chunks.length; cnt += 1) {
|
||||
view[cnt + 1] = chunks[cnt];
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param chunks Array of chunkIds
|
||||
*/
|
||||
export function dehydrateDeRegMChunks(chunks) {
|
||||
const buffer = new ArrayBuffer(1 + 1 + chunks.length * 2);
|
||||
const view = new Uint16Array(buffer);
|
||||
// this will result into a double first byte, but still better than
|
||||
// shifting 16bit integers around later
|
||||
view[0] = DEREG_MCHUNKS_OP;
|
||||
for (let cnt = 0; cnt < chunks.length; cnt += 1) {
|
||||
view[cnt + 1] = chunks[cnt];
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param solution string of entered captcha
|
||||
*/
|
||||
export function dehydrateCaptchaSolution(solution) {
|
||||
const encoder = new TextEncoder();
|
||||
const view = encoder.encode(solution);
|
||||
const buffer = new Uint8Array(view.byteLength + 1);
|
||||
buffer[0] = CAPTCHA_SOLUTION_OP;
|
||||
buffer.set(view, 1);
|
||||
return buffer.buffer;
|
||||
}
|
||||
|
||||
export function dehydratePing() {
|
||||
return new Uint8Array([PING_OP]).buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param i, j chunk coordinates
|
||||
* @param pixels array of offsets and colors of pixels
|
||||
*/
|
||||
export function dehydratePixelUpdate(i, j, pixels) {
|
||||
const buffer = new ArrayBuffer(1 + 1 + 1 + pixels.length * 4);
|
||||
const view = new DataView(buffer);
|
||||
view.setUint8(0, PIXEL_UPDATE_OP);
|
||||
view.setUint8(1, i);
|
||||
view.setUint8(2, j);
|
||||
/*
|
||||
* offset and color of every pixel
|
||||
* 3 bytes offset
|
||||
* 1 byte color
|
||||
*/
|
||||
let cnt = 2;
|
||||
let p = pixels.length;
|
||||
while (p) {
|
||||
p -= 1;
|
||||
const [offset, color] = pixels[p];
|
||||
view.setUint8(cnt += 1, offset >>> 16);
|
||||
view.setUint16(cnt += 1, offset & 0x00FFFF);
|
||||
view.setUint8(cnt += 2, color);
|
||||
}
|
||||
return buffer;
|
||||
}
|
21
src/socket/packets/op.js
Normal file
21
src/socket/packets/op.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* OP CODES
|
||||
*/
|
||||
|
||||
/*
|
||||
* we export code so that webpack can directly resolve them
|
||||
*/
|
||||
export const REG_CANVAS_OP = 0xA0;
|
||||
export const REG_CHUNK_OP = 0xA1;
|
||||
export const DEREG_CHUNK_OP = 0xA2;
|
||||
export const REG_MCHUNKS_OP = 0xA3;
|
||||
export const DEREG_MCHUNKS_OP = 0xA4;
|
||||
export const CAPTCHA_SOLUTION_OP = 0xA5;
|
||||
export const CHANGE_ME_OP = 0xA6;
|
||||
export const ONLINE_COUNTER_OP = 0xA7;
|
||||
export const PING_OP = 0xB0;
|
||||
export const PIXEL_UPDATE_OP = 0xC1;
|
||||
export const PIXEL_UPDATE_MB_OP = 0xC1;
|
||||
export const COOLDOWN_OP = 0xC2;
|
||||
export const PIXEL_RETURN_OP = 0xC3;
|
||||
export const CHUNK_UPDATE_MB_OP = 0xC4;
|
239
src/socket/packets/server.js
Normal file
239
src/socket/packets/server.js
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* server package hydration
|
||||
*/
|
||||
import {
|
||||
CHANGE_ME_OP,
|
||||
ONLINE_COUNTER_OP,
|
||||
PIXEL_UPDATE_OP,
|
||||
PIXEL_UPDATE_MB_OP,
|
||||
COOLDOWN_OP,
|
||||
PIXEL_RETURN_OP,
|
||||
CHUNK_UPDATE_MB_OP,
|
||||
} from './op';
|
||||
|
||||
/*
|
||||
* data in hydrate function is a nodejs Buffer
|
||||
*/
|
||||
|
||||
/*
|
||||
* @return canvasId
|
||||
*/
|
||||
export function hydrateRegCanvas(data) {
|
||||
const canvasId = data[1];
|
||||
return canvasId;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return {
|
||||
* total: totalOnline,
|
||||
* canvasId: online,
|
||||
* ....
|
||||
* }
|
||||
*/
|
||||
export function hydrateOnlineCounter(data) {
|
||||
const online = {};
|
||||
online.total = data.readUInt16BE(1);
|
||||
let off = data.length;
|
||||
while (off > 3) {
|
||||
const onlineUsers = data.readUInt16BE(off -= 2);
|
||||
const canvas = data.readUInt8(off -= 1);
|
||||
online[canvas] = onlineUsers;
|
||||
}
|
||||
return online;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return chunkId
|
||||
*/
|
||||
export function hydrateRegChunk(data) {
|
||||
const i = data[1] << 8 | data[2];
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return chunkId
|
||||
*/
|
||||
export function hydrateDeRegChunk(data) {
|
||||
const i = data[1] << 8 | data[2];
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* cb execute with individual chunkids
|
||||
*/
|
||||
export function hydrateRegMChunks(data, cb) {
|
||||
let posu = 2;
|
||||
while (posu < data.length) {
|
||||
const chunkid = data[posu++] | data[posu++] << 8;
|
||||
cb(chunkid);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* cb execute with individual chunkids
|
||||
*/
|
||||
export function hydrateDeRegMChunks(data, cb) {
|
||||
let posl = 2;
|
||||
while (posl < data.length) {
|
||||
const chunkid = data[posl++] | data[posl++] << 8;
|
||||
cb(chunkid);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @return captcha solution
|
||||
*/
|
||||
export function hydrateCaptchaSolution(data) {
|
||||
return data.toString('utf8', 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* @return chunk id and array of pixel offset and color
|
||||
*/
|
||||
export function hydratePixelUpdate(data) {
|
||||
const i = data.readUInt8(1);
|
||||
const j = data.readUInt8(2);
|
||||
const pixels = [];
|
||||
let off = data.length;
|
||||
let pxlcnt = 0;
|
||||
while (off > 3 && pxlcnt < 500) {
|
||||
const color = data.readUInt8(off -= 1);
|
||||
const offsetL = data.readUInt16BE(off -= 2);
|
||||
const offsetH = data.readUInt8(off -= 1) << 16;
|
||||
pixels.push([offsetH | offsetL, color]);
|
||||
pxlcnt += 1;
|
||||
}
|
||||
return {
|
||||
i, j, pixels,
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* @returns info and PixelUpdate package to send to clients
|
||||
*/
|
||||
export function hydratePixelUpdateMB(data) {
|
||||
const canvasId = data[1];
|
||||
data.writeUInt8(PIXEL_UPDATE_OP, 1);
|
||||
const chunkId = data.readUInt16BE(2);
|
||||
const pixelUpdate = Buffer.from(
|
||||
data.buffer,
|
||||
data.byteOffset + 1,
|
||||
data.length - 1,
|
||||
);
|
||||
return [
|
||||
canvasId,
|
||||
chunkId,
|
||||
pixelUpdate,
|
||||
];
|
||||
}
|
||||
|
||||
/*
|
||||
* @return canvasid and chunk coords
|
||||
*/
|
||||
export function hydrateChunkUpdateMB(data) {
|
||||
const canvasId = data[1];
|
||||
const i = data.readUInt8(2);
|
||||
const j = data.readUInt8(3);
|
||||
return [canvasId, [i, j]];
|
||||
}
|
||||
|
||||
/*
|
||||
* dehydrate functions return nodejs Buffer object
|
||||
*/
|
||||
|
||||
/*
|
||||
* returns buffer with only OP_CODE
|
||||
*/
|
||||
export function dehydrateChangeMe() {
|
||||
return Buffer.from([CHANGE_ME_OP]);
|
||||
}
|
||||
|
||||
/*
|
||||
* @param {
|
||||
* total: totalOnline,
|
||||
* canvasId: online,
|
||||
* ....
|
||||
* }
|
||||
*/
|
||||
export function dehydrateOnlineCounter(online) {
|
||||
const canvasIds = Object.keys(online).filter((id) => id !== 'total');
|
||||
const buffer = Buffer.allocUnsafe(3 + canvasIds.length * (1 + 2));
|
||||
buffer.writeUInt8(ONLINE_COUNTER_OP, 0);
|
||||
buffer.writeUInt16BE(online.total, 1);
|
||||
let cnt = 1;
|
||||
for (let p = 0; p < canvasIds.length; p += 1) {
|
||||
const canvasId = canvasIds[p];
|
||||
const onlineUsers = online[canvasId];
|
||||
buffer.writeUInt8(Number(canvasId), cnt += 2);
|
||||
buffer.writeUInt16BE(onlineUsers, cnt += 1);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param chunkId id consisting of chunk coordinates
|
||||
* @param pixels Buffer with offset and color of one or more pixels
|
||||
*/
|
||||
export function dehydratePixelUpdate(i, j, pixels) {
|
||||
const index = new Uint8Array([PIXEL_UPDATE_OP, i, j]);
|
||||
return Buffer.concat([index, pixels]);
|
||||
}
|
||||
|
||||
/*
|
||||
* @param canvasId
|
||||
* @param chunkId id consisting of chunk coordinates
|
||||
* @param pixels Buffer with offset and color of one or more pixels
|
||||
*/
|
||||
export function dehydratePixelUpdateMB(canvasId, i, j, pixels) {
|
||||
const index = new Uint8Array([
|
||||
PIXEL_UPDATE_MB_OP,
|
||||
canvasId,
|
||||
i,
|
||||
j,
|
||||
]);
|
||||
return Buffer.concat([index, pixels]);
|
||||
}
|
||||
|
||||
/*
|
||||
* @param wait cooldown in ms
|
||||
*/
|
||||
export function dehydrateCoolDown(wait) {
|
||||
const buffer = Buffer.allocUnsafe(1 + 4);
|
||||
buffer.writeUInt8(COOLDOWN_OP, 0);
|
||||
buffer.writeUInt32BE(wait, 1);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* for params see core/draw or ui/placePixel
|
||||
*/
|
||||
export function dehydratePixelReturn(
|
||||
retCode,
|
||||
wait,
|
||||
coolDown,
|
||||
pxlCnt,
|
||||
rankedPxlCnt,
|
||||
) {
|
||||
const buffer = Buffer.allocUnsafe(1 + 1 + 4 + 2 + 1 + 1);
|
||||
buffer.writeUInt8(PIXEL_RETURN_OP, 0);
|
||||
buffer.writeUInt8(retCode, 1);
|
||||
buffer.writeUInt32BE(wait, 2);
|
||||
const coolDownSeconds = Math.round(coolDown / 1000);
|
||||
buffer.writeInt16BE(coolDownSeconds, 6);
|
||||
buffer.writeUInt8(pxlCnt, 8);
|
||||
buffer.writeUInt8(rankedPxlCnt, 9);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param canvasId
|
||||
* @param Array with chunk coordinates
|
||||
*/
|
||||
export function dehydrateChunkUpdateMB(canvasId, [i, j]) {
|
||||
return Buffer.from([
|
||||
CHUNK_UPDATE_MB_OP,
|
||||
canvasId,
|
||||
i,
|
||||
j,
|
||||
]);
|
||||
}
|
|
@ -148,7 +148,7 @@ export function selectColor(color) {
|
|||
export function selectCanvas(canvasId) {
|
||||
return {
|
||||
type: 's/SELECT_CANVAS',
|
||||
canvasId,
|
||||
canvasId: String(canvasId),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -41,26 +41,25 @@ export default (store) => (next) => (action) => {
|
|||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
|
||||
const ret = next(action);
|
||||
|
||||
// executed after reducers
|
||||
switch (action.type) {
|
||||
case 'RELOAD_URL':
|
||||
case 's/SELECT_CANVAS':
|
||||
case 's/REC_ME': {
|
||||
const prevState = store.getState();
|
||||
const ret = next(action);
|
||||
const state = store.getState();
|
||||
const { canvasId } = state.canvas;
|
||||
if (prevState.canvas.canvasId === canvasId) {
|
||||
// TODO see if this is the case anywhere
|
||||
console.log('Not triggering change canvas');
|
||||
} else {
|
||||
SocketClient.setCanvas(canvasId);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
|
||||
return ret;
|
||||
return next(action);
|
||||
};
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
import SocketClient from '../../socket/SocketClient';
|
||||
|
||||
export default () => (next) => (action) => {
|
||||
export default (store) => (next) => (action) => {
|
||||
if (SocketClient.readyState === WebSocket.CLOSED) {
|
||||
if (action.type === 't/PARENT_CLOSED') {
|
||||
SocketClient.connect();
|
||||
SocketClient.initialize(store);
|
||||
}
|
||||
} else {
|
||||
switch (action.type) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user