Negative pixel patch
This commit is contained in:
parent
95b61fa050
commit
d61530f91d
|
@ -403,6 +403,9 @@ export class Canvas extends EventEmitter<CanvasEvents> {
|
||||||
case "no_user":
|
case "no_user":
|
||||||
toast.error("You are not logged in.");
|
toast.error("You are not logged in.");
|
||||||
break;
|
break;
|
||||||
|
case "pixel_already_pending":
|
||||||
|
toast.error("You are already placing a pixel");
|
||||||
|
break;
|
||||||
case "palette_color_invalid":
|
case "palette_color_invalid":
|
||||||
toast.error("This isn't a color that you can use...?");
|
toast.error("This isn't a color that you can use...?");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -20,6 +20,12 @@ export const CanvasLib = new (class {
|
||||||
|
|
||||||
// oh god last minute change to match activity cooldown
|
// oh god last minute change to match activity cooldown
|
||||||
// 100 = user count
|
// 100 = user count
|
||||||
|
|
||||||
|
// band aid over negative nums
|
||||||
|
if (pixelNumber < 1) {
|
||||||
|
pixelNumber = 1
|
||||||
|
}
|
||||||
|
|
||||||
return (2.5 * Math.sqrt(100 + 11.96) + 6.5) * 1 * pixelNumber;
|
return (2.5 * Math.sqrt(100 + 11.96) + 6.5) * 1 * pixelNumber;
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -55,6 +55,7 @@ export interface ClientToServerEvents {
|
||||||
| "palette_color_invalid"
|
| "palette_color_invalid"
|
||||||
| "you_already_placed_that"
|
| "you_already_placed_that"
|
||||||
| "banned"
|
| "banned"
|
||||||
|
| "pixel_already_pending"
|
||||||
>
|
>
|
||||||
) => void
|
) => void
|
||||||
) => void;
|
) => void;
|
||||||
|
|
|
@ -85,6 +85,13 @@ type Socket = RawSocket<ClientToServerEvents, ServerToClientEvents>;
|
||||||
export class SocketServer {
|
export class SocketServer {
|
||||||
static instance: SocketServer;
|
static instance: SocketServer;
|
||||||
io: Server<ClientToServerEvents, ServerToClientEvents>;
|
io: Server<ClientToServerEvents, ServerToClientEvents>;
|
||||||
|
/**
|
||||||
|
* Prevent users from time attacking pixel placements to place more pixels than stacked
|
||||||
|
*
|
||||||
|
* @key user sub (grant@grants.cafe)
|
||||||
|
* @value timestamp
|
||||||
|
*/
|
||||||
|
userPlaceLock = new Map<string, number>();
|
||||||
|
|
||||||
constructor(server: http.Server) {
|
constructor(server: http.Server) {
|
||||||
SocketServer.instance = this;
|
SocketServer.instance = this;
|
||||||
|
@ -96,6 +103,29 @@ export class SocketServer {
|
||||||
this.io.engine.use(session);
|
this.io.engine.use(session);
|
||||||
this.io.on("connection", this.handleConnection.bind(this));
|
this.io.on("connection", this.handleConnection.bind(this));
|
||||||
|
|
||||||
|
// clear pixel locks if they have existed for more than a minute
|
||||||
|
setInterval(() => {
|
||||||
|
const oneMinuteAgo = new Date();
|
||||||
|
oneMinuteAgo.setMinutes(oneMinuteAgo.getMinutes() - 1);
|
||||||
|
|
||||||
|
const expired = [...this.userPlaceLock.entries()].filter(
|
||||||
|
([user, time]) => time < oneMinuteAgo.getTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (expired.length > 0) {
|
||||||
|
Logger.warn(
|
||||||
|
"A pixel lock has existed for too long for " +
|
||||||
|
expired.length +
|
||||||
|
" users : " +
|
||||||
|
expired.map((a) => a[0]).join(",")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const expire of expired) {
|
||||||
|
this.userPlaceLock.delete(expire[0]);
|
||||||
|
}
|
||||||
|
}, 1000 * 30);
|
||||||
|
|
||||||
// pixel stacking
|
// pixel stacking
|
||||||
// - needs to be exponential (takes longer to aquire more pixels stacked)
|
// - needs to be exponential (takes longer to aquire more pixels stacked)
|
||||||
// - convert to config options instead of hard-coded
|
// - convert to config options instead of hard-coded
|
||||||
|
@ -254,19 +284,29 @@ export class SocketServer {
|
||||||
// force a user data update
|
// force a user data update
|
||||||
await user.update(true);
|
await user.update(true);
|
||||||
|
|
||||||
|
if (this.userPlaceLock.has(user.sub)) {
|
||||||
|
ack({ success: false, error: "pixel_already_pending" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.userPlaceLock.set(user.sub, Date.now());
|
||||||
|
|
||||||
if (bypassCooldown && !user.isModerator) {
|
if (bypassCooldown && !user.isModerator) {
|
||||||
// only moderators can do this
|
// only moderators can do this
|
||||||
ack({ success: false, error: "invalid_pixel" });
|
ack({ success: false, error: "invalid_pixel" });
|
||||||
|
this.userPlaceLock.delete(user.sub);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bypassCooldown && user.pixelStack < 1) {
|
if (!bypassCooldown && user.pixelStack < 1) {
|
||||||
ack({ success: false, error: "pixel_cooldown" });
|
ack({ success: false, error: "pixel_cooldown" });
|
||||||
|
this.userPlaceLock.delete(user.sub);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((user.getBan()?.expires || 0) > new Date()) {
|
if ((user.getBan()?.expires || 0) > new Date()) {
|
||||||
ack({ success: false, error: "banned" });
|
ack({ success: false, error: "banned" });
|
||||||
|
this.userPlaceLock.delete(user.sub);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,6 +320,7 @@ export class SocketServer {
|
||||||
success: false,
|
success: false,
|
||||||
error: "palette_color_invalid",
|
error: "palette_color_invalid",
|
||||||
});
|
});
|
||||||
|
this.userPlaceLock.delete(user.sub);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +332,7 @@ export class SocketServer {
|
||||||
pixelAtTheSameLocation.color === paletteColor.hex
|
pixelAtTheSameLocation.color === paletteColor.hex
|
||||||
) {
|
) {
|
||||||
ack({ success: false, error: "you_already_placed_that" });
|
ack({ success: false, error: "you_already_placed_that" });
|
||||||
|
this.userPlaceLock.delete(user.sub);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,6 +361,7 @@ export class SocketServer {
|
||||||
data: newPixel,
|
data: newPixel,
|
||||||
});
|
});
|
||||||
socket.broadcast.emit("pixel", newPixel);
|
socket.broadcast.emit("pixel", newPixel);
|
||||||
|
this.userPlaceLock.delete(user.sub);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("undo", async (ack) => {
|
socket.on("undo", async (ack) => {
|
||||||
|
|
Loading…
Reference in New Issue