mass-request pixels pt.1
This commit is contained in:
parent
2f04d24452
commit
e34609c046
|
@ -135,7 +135,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
|
||||
|
||||
// on captcha received
|
||||
// TODO: this really isn't beautiful
|
||||
window.onCaptcha = async function onCaptcha(token: string) {
|
||||
const body = JSON.stringify({
|
||||
token,
|
||||
|
|
|
@ -28,15 +28,18 @@ import { THREE_CANVAS_HEIGHT, THREE_TILE_SIZE, TILE_SIZE } from './constants';
|
|||
* @param canvasId
|
||||
* @param i Chunk coordinates
|
||||
* @param j
|
||||
* @param offset Offset of pixel withing chunk
|
||||
* @param pixels Array of indiviual pixels within the chunk, with:
|
||||
* [[offset, color], [offset2, color2],...]
|
||||
* Offset is the offset of the pixel within the chunk
|
||||
* @return Promise<Object>
|
||||
*/
|
||||
export async function drawByOffset(
|
||||
export async function drawByOffsets(
|
||||
user: User,
|
||||
canvasId: number,
|
||||
color: ColorIndex,
|
||||
i: number,
|
||||
j: number,
|
||||
offset: number,
|
||||
pixels: Array,
|
||||
): Promise<Object> {
|
||||
let wait = 0;
|
||||
let coolDown = 0;
|
||||
|
@ -55,6 +58,9 @@ export async function drawByOffset(
|
|||
|
||||
try {
|
||||
const tileSize = (is3d) ? THREE_TILE_SIZE : TILE_SIZE;
|
||||
/*
|
||||
* canvas/chunk validation
|
||||
*/
|
||||
if (i >= canvasSize / tileSize) {
|
||||
// x out of bounds
|
||||
throw new Error(2);
|
||||
|
@ -63,19 +69,6 @@ export async function drawByOffset(
|
|||
// y out of bounds
|
||||
throw new Error(3);
|
||||
}
|
||||
const maxSize = (is3d) ? tileSize * tileSize * THREE_CANVAS_HEIGHT
|
||||
: tileSize * tileSize;
|
||||
if (offset >= maxSize) {
|
||||
// z out of bounds or weird stuff
|
||||
throw new Error(4);
|
||||
}
|
||||
if (color >= canvas.colors.length
|
||||
|| (color < canvas.cli && !(canvas.v && color === 0))
|
||||
) {
|
||||
// color out of bounds
|
||||
throw new Error(5);
|
||||
}
|
||||
|
||||
if (canvas.req !== -1) {
|
||||
if (user.id === null) {
|
||||
// not logged in
|
||||
|
@ -89,8 +82,29 @@ export async function drawByOffset(
|
|||
}
|
||||
|
||||
const isAdmin = (user.userlvl === 1);
|
||||
/*
|
||||
* TODO benchmark if requesting by pixel or chunk
|
||||
* is better
|
||||
*/
|
||||
const chunk = await RedisCanvas.getChunk(canvasId, i, j);
|
||||
const setColor = await RedisCanvas.getPixelByOffset(canvasId, i, j, offset);
|
||||
|
||||
/*
|
||||
* pixel validation
|
||||
*/
|
||||
const maxSize = (is3d) ? tileSize * tileSize * THREE_CANVAS_HEIGHT
|
||||
: tileSize * tileSize;
|
||||
if (offset >= maxSize) {
|
||||
// z out of bounds or weird stuff
|
||||
throw new Error(4);
|
||||
}
|
||||
if (color >= canvas.colors.length
|
||||
|| (color < canvas.cli && !(canvas.v && color === 0))
|
||||
) {
|
||||
// color out of bounds
|
||||
throw new Error(5);
|
||||
}
|
||||
|
||||
if (setColor & 0x80
|
||||
/* 3D Canvas Minecraft Avatars */
|
||||
// && x >= 96 && x <= 128 && z >= 35 && z <= 100
|
||||
|
@ -331,7 +345,6 @@ export async function drawByCoords(
|
|||
* @param x
|
||||
* @param y
|
||||
* @param z (optional for 3d canvas)
|
||||
* @returns {Promise.<boolean>}
|
||||
*/
|
||||
export function drawSafeByCoords(
|
||||
user: User,
|
||||
|
@ -340,7 +353,7 @@ export function drawSafeByCoords(
|
|||
x: number,
|
||||
y: number,
|
||||
z: number = null,
|
||||
): Promise<Cell> {
|
||||
): Promise<Object> {
|
||||
// can just check for one unique occurence,
|
||||
// we use ip, because id for logged out users is
|
||||
// always null
|
||||
|
@ -364,20 +377,19 @@ export function drawSafeByCoords(
|
|||
*
|
||||
* @param user
|
||||
* @param canvasId
|
||||
* @param color
|
||||
* @param i Chunk coordinates
|
||||
* @param j
|
||||
* @param offset Offset of pixel withing chunk
|
||||
* @returns {Promise.<boolean>}
|
||||
* @param pixels Array of indiviual pixels within the chunk, with:
|
||||
* [[offset, color], [offset2, color2],...]
|
||||
* Offset is the offset of the pixel within the chunk
|
||||
* @return Promise<Object>
|
||||
*/
|
||||
export function drawSafeByOffset(
|
||||
export function drawSafeByOffsets(
|
||||
user: User,
|
||||
canvasId: number,
|
||||
color: ColorIndex,
|
||||
i: number,
|
||||
j: number,
|
||||
offset: number,
|
||||
): Promise<Cell> {
|
||||
pixels: Array,
|
||||
): Promise<Object> {
|
||||
// can just check for one unique occurence,
|
||||
// we use ip, because id for logged out users is
|
||||
// always null
|
||||
|
@ -387,7 +399,7 @@ export function drawSafeByOffset(
|
|||
using(
|
||||
redlock.disposer(`locks:${userId}`, 5000, logger.error),
|
||||
async () => {
|
||||
const ret = await drawByOffset(user, canvasId, color, i, j, offset);
|
||||
const ret = await drawByOffsets(user, canvasId, i, j, pixels);
|
||||
resolve(ret);
|
||||
},
|
||||
); // <-- unlock is automatically handled by bluebird
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/**
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
|
@ -125,11 +123,16 @@ class ProtocolClient extends EventEmitter {
|
|||
if (~pos) chunks.splice(pos, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send pixel request
|
||||
* @param i, j chunk coordinates
|
||||
* @param pixel Array of [[offset, color],...] pixels within chunk
|
||||
*/
|
||||
requestPlacePixel(
|
||||
i, j, offset,
|
||||
color,
|
||||
i: number, j: number,
|
||||
pixels: Array,
|
||||
) {
|
||||
const buffer = PixelUpdate.dehydrate(i, j, offset, color);
|
||||
const buffer = PixelUpdate.dehydrate(i, j, pixels);
|
||||
this.sendWhenReady(buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
/* @flow */
|
||||
/*
|
||||
* Packet for sending and receiving pixels per chunk
|
||||
* Multiple pixels can be sent at once
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
|
||||
import type { ColorIndex } from '../../core/Palette';
|
||||
|
@ -6,7 +11,7 @@ import type { ColorIndex } from '../../core/Palette';
|
|||
type PixelUpdatePacket = {
|
||||
x: number,
|
||||
y: number,
|
||||
color: ColorIndex,
|
||||
pixels: Array,
|
||||
};
|
||||
|
||||
const OP_CODE = 0xC1;
|
||||
|
@ -14,25 +19,50 @@ const OP_CODE = 0xC1;
|
|||
export default {
|
||||
OP_CODE,
|
||||
hydrate(data: DataView): PixelUpdatePacket {
|
||||
/*
|
||||
* chunk coordinates
|
||||
*/
|
||||
const i = data.getUint8(1);
|
||||
const j = data.getUint8(2);
|
||||
const offset = (data.getUint8(3) << 16) | data.getUint16(4);
|
||||
const color = data.getUint8(6);
|
||||
/*
|
||||
* 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;
|
||||
const pixels.push([offsetH | offsetL, color]);
|
||||
}
|
||||
return {
|
||||
i, j, offset, color,
|
||||
i, j, pixels,
|
||||
};
|
||||
},
|
||||
|
||||
dehydrate(i, j, offset, color): Buffer {
|
||||
const buffer = new ArrayBuffer(1 + 1 + 1 + 1 + 2 + 1);
|
||||
dehydrate(i, j, pixels): Buffer {
|
||||
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);
|
||||
view.setUint8(3, offset >>> 16);
|
||||
view.setUint16(4, offset & 0x00FFFF);
|
||||
view.setUint8(6, color);
|
||||
/*
|
||||
* offset and color of every pixel
|
||||
* 3 bytes offset
|
||||
* 1 byte color
|
||||
*/
|
||||
let cnt = 2;
|
||||
for (let i = 0; i < pixels.length; i += 1) {
|
||||
const [offset, color] = pixels[i];
|
||||
view.setUint8(cnt += 1, offset >>> 16);
|
||||
view.setUint16(cnt += 1, offset & 0x00FFFF);
|
||||
view.setUint8(cnt += 2, color);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
},
|
||||
|
|
|
@ -6,7 +6,7 @@ import type { ColorIndex } from '../../core/Palette';
|
|||
type PixelUpdatePacket = {
|
||||
x: number,
|
||||
y: number,
|
||||
color: ColorIndex,
|
||||
pixels: Array,
|
||||
};
|
||||
|
||||
const OP_CODE = 0xC1;
|
||||
|
@ -14,23 +14,49 @@ const OP_CODE = 0xC1;
|
|||
export default {
|
||||
OP_CODE,
|
||||
hydrate(data: Buffer): PixelUpdatePacket {
|
||||
/*
|
||||
* chunk coordinates
|
||||
*/
|
||||
const i = data.readUInt8(1);
|
||||
const j = data.readUInt8(2);
|
||||
const offset = (data.readUInt8(3) << 16) | data.readUInt16BE(4);
|
||||
const color = data.readUInt8(6);
|
||||
/*
|
||||
* offset and color of every pixel
|
||||
* 3 bytes offset
|
||||
* 1 byte color
|
||||
*/
|
||||
const pixels = [];
|
||||
let off = data.length;
|
||||
while (off >= 3) {
|
||||
const color = data.readUInt8(off -= 1);
|
||||
const offsetL = data.readUInt16BE(off -= 2);
|
||||
const offsetH = data.readUInt8(off -= 1) << 16;
|
||||
const pixels.push([offsetH | offsetL, color]);
|
||||
}
|
||||
return {
|
||||
i, j, offset, color,
|
||||
i, j, pixels,
|
||||
};
|
||||
},
|
||||
dehydrate(i, j, offset, color): Buffer {
|
||||
const buffer = Buffer.allocUnsafe(1 + 1 + 1 + 1 + 2 + 1);
|
||||
buffer.writeUInt8(OP_CODE, 0);
|
||||
|
||||
dehydrate(i, j, pixels): Buffer {
|
||||
const buffer = Buffer.allocUnsafe(1 + 1 + 1 + pixels.length * 4);
|
||||
buffer.writeUInt8(OP_CODE, 0);
|
||||
/*
|
||||
* chunk coordinates
|
||||
*/
|
||||
buffer.writeUInt8(i, 1);
|
||||
buffer.writeUInt8(j, 2);
|
||||
buffer.writeUInt8(offset >>> 16, 3);
|
||||
buffer.writeUInt16BE(offset & 0x00FFFF, 4);
|
||||
buffer.writeUInt8(color, 6);
|
||||
/*
|
||||
* offset and color of every pixel
|
||||
* 3 bytes offset
|
||||
* 1 byte color
|
||||
*/
|
||||
let cnt = 2;
|
||||
for (let i = 0; i < pixels.length; i += 1) {
|
||||
const [offset, color] = pixels[i];
|
||||
buffer.writeUInt8(offset >>> 16, cnt += 1);
|
||||
buffer.writeUInt16BE(offset & 0x00FFFF, cnt += 1);
|
||||
buffer.writeUInt8(color, cnt += 2);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue
Block a user