From ced4bdc2d177261661b5ce1cdc7033c7724361b0 Mon Sep 17 00:00:00 2001 From: Grant Date: Tue, 4 Jun 2024 16:02:14 -0600 Subject: [PATCH] prevent same color & same user pixels to be placed on top of each other (fixes #19) --- packages/client/src/lib/canvas.ts | 24 +++++++++++++++-- packages/lib/src/net.ts | 6 ++++- packages/server/src/lib/Canvas.ts | 35 ++++++++++--------------- packages/server/src/lib/SocketServer.ts | 11 ++++++++ 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/packages/client/src/lib/canvas.ts b/packages/client/src/lib/canvas.ts index 00b79eb..17bc05d 100644 --- a/packages/client/src/lib/canvas.ts +++ b/packages/client/src/lib/canvas.ts @@ -237,14 +237,34 @@ export class Canvas extends EventEmitter { this.lastPlace = Date.now(); this.handlePixel(ack.data); } else { - // TODO: handle undo pixel - toast.info(ack.error); console.warn( "Attempted to place pixel", { x, y, color: this.Pallete.getSelectedColor()!.id }, "and got error", ack ); + + switch (ack.error) { + case "invalid_pixel": + toast.error( + "Cannot place, invalid pixel location. Are you even on the canvas?" + ); + break; + case "no_user": + toast.error("You are not logged in."); + break; + case "palette_color_invalid": + toast.error("This isn't a color that you can use...?"); + break; + case "pixel_cooldown": + toast.error("You're on pixel cooldown, cannot place"); + break; + case "you_already_placed_that": + toast.error("You already placed this color at this location"); + break; + default: + toast.error("Error while placing pixel: " + ack.error); + } } }); } diff --git a/packages/lib/src/net.ts b/packages/lib/src/net.ts index 0774b63..26fb300 100644 --- a/packages/lib/src/net.ts +++ b/packages/lib/src/net.ts @@ -19,7 +19,11 @@ export interface ClientToServerEvents { ack: ( _: PacketAck< Pixel, - "no_user" | "invalid_pixel" | "pixel_cooldown" | "palette_color_invalid" + | "no_user" + | "invalid_pixel" + | "pixel_cooldown" + | "palette_color_invalid" + | "you_already_placed_that" > ) => void ) => void; diff --git a/packages/server/src/lib/Canvas.ts b/packages/server/src/lib/Canvas.ts index cfd4bba..76fa9d1 100644 --- a/packages/server/src/lib/Canvas.ts +++ b/packages/server/src/lib/Canvas.ts @@ -82,17 +82,7 @@ class Canvas { for (let x = 0; x < this.canvasSize[0]; x++) { for (let y = 0; y < this.canvasSize[1]; y++) { - const pixel = await prisma.pixel.findFirst({ - where: { - x, - y, - }, - orderBy: [ - { - createdAt: "asc", - }, - ], - }); + const pixel = await this.getPixel(x, y); await redis.set(key(x, y), pixel?.color || "transparent"); } @@ -152,12 +142,18 @@ class Canvas { } async getPixel(x: number, y: number) { - return await prisma.pixel.findFirst({ - where: { - x, - y, - }, - }); + return ( + await prisma.pixel.findMany({ + where: { + x, + y, + }, + orderBy: { + createdAt: "desc", + }, + take: 1, + }) + )?.[0]; } async setPixel(user: { sub: string }, x: number, y: number, hex: string) { @@ -194,10 +190,7 @@ class Canvas { const key = Redis.key("pixelColor", x, y); // find if any pixels exist at this spot, and pick the most recent one - const pixel = await prisma.pixel.findFirst({ - where: { x, y }, - orderBy: { createdAt: "desc" }, - }); + const pixel = await this.getPixel(x, y); let paletteColorID = -1; // if pixel exists in redis diff --git a/packages/server/src/lib/SocketServer.ts b/packages/server/src/lib/SocketServer.ts index db002e3..afc8deb 100644 --- a/packages/server/src/lib/SocketServer.ts +++ b/packages/server/src/lib/SocketServer.ts @@ -229,6 +229,17 @@ export class SocketServer { return; } + const pixelAtTheSameLocation = await Canvas.getPixel(pixel.x, pixel.y); + + if ( + pixelAtTheSameLocation && + pixelAtTheSameLocation.userId === user.sub && + pixelAtTheSameLocation.color === paletteColor.hex + ) { + ack({ success: false, error: "you_already_placed_that" }); + return; + } + await user.modifyStack(-1); await Canvas.setPixel(user, pixel.x, pixel.y, paletteColor.hex); // give undo capabilities