Improve handling of the user pixel stack
This commit is contained in:
parent
c2fba721f4
commit
5a44446138
|
@ -18,6 +18,7 @@ const getTimeLeft = (pixels: { available: number }, config: ClientConfig) => {
|
||||||
const cooldown = CanvasLib.getPixelCooldown(pixels.available + 1, config);
|
const cooldown = CanvasLib.getPixelCooldown(pixels.available + 1, config);
|
||||||
const pixelExpiresAt =
|
const pixelExpiresAt =
|
||||||
Canvas.instance?.lastPlace && Canvas.instance.lastPlace + cooldown * 1000;
|
Canvas.instance?.lastPlace && Canvas.instance.lastPlace + cooldown * 1000;
|
||||||
|
|
||||||
const pixelCooldown = pixelExpiresAt && (Date.now() - pixelExpiresAt) / 1000;
|
const pixelCooldown = pixelExpiresAt && (Date.now() - pixelExpiresAt) / 1000;
|
||||||
|
|
||||||
if (!pixelCooldown) return undefined;
|
if (!pixelCooldown) return undefined;
|
||||||
|
@ -43,7 +44,7 @@ const PlaceCountdown = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{timeLeft
|
{timeLeft
|
||||||
? pixels.available + 1 < config.canvas.pixel.maxStack && timeLeft + "s"
|
? pixels.available < config.canvas.pixel.maxStack && timeLeft + "s"
|
||||||
: ""}
|
: ""}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -53,11 +53,9 @@ export class Canvas extends EventEmitter<CanvasEvents> {
|
||||||
this.PanZoom.addListener("click", this.handleMouseDown.bind(this));
|
this.PanZoom.addListener("click", this.handleMouseDown.bind(this));
|
||||||
this.PanZoom.addListener("longPress", this.handleLongPress);
|
this.PanZoom.addListener("longPress", this.handleLongPress);
|
||||||
|
|
||||||
Network.waitForState("pixelLastPlaced").then(
|
|
||||||
([time]) => (this.lastPlace = time)
|
|
||||||
);
|
|
||||||
Network.on("pixel", this.handlePixel);
|
Network.on("pixel", this.handlePixel);
|
||||||
Network.on("square", this.handleSquare);
|
Network.on("square", this.handleSquare);
|
||||||
|
Network.on("pixelLastPlaced", this.handlePixelLastPlaced);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
|
@ -70,6 +68,7 @@ export class Canvas extends EventEmitter<CanvasEvents> {
|
||||||
|
|
||||||
Network.off("pixel", this.handlePixel);
|
Network.off("pixel", this.handlePixel);
|
||||||
Network.off("square", this.handleSquare);
|
Network.off("square", this.handleSquare);
|
||||||
|
Network.off("pixelLastPlaced", this.handlePixelLastPlaced);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -309,6 +308,10 @@ export class Canvas extends EventEmitter<CanvasEvents> {
|
||||||
getRenderer().usePixel({ x, y, hex: palette?.hex || "null" });
|
getRenderer().usePixel({ x, y, hex: palette?.hex || "null" });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handlePixelLastPlaced = (time: number) => {
|
||||||
|
this.lastPlace = time;
|
||||||
|
};
|
||||||
|
|
||||||
Pallete = {
|
Pallete = {
|
||||||
getColor: (colorId: number) => {
|
getColor: (colorId: number) => {
|
||||||
return this.config.pallete.colors.find((c) => c.id === colorId);
|
return this.config.pallete.colors.find((c) => c.id === colorId);
|
||||||
|
@ -358,7 +361,6 @@ export class Canvas extends EventEmitter<CanvasEvents> {
|
||||||
)
|
)
|
||||||
.then((ack) => {
|
.then((ack) => {
|
||||||
if (ack.success) {
|
if (ack.success) {
|
||||||
this.lastPlace = Date.now();
|
|
||||||
this.handlePixel(ack.data);
|
this.handlePixel(ack.data);
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
console.warn(
|
||||||
|
|
|
@ -12,7 +12,7 @@ Table User {
|
||||||
display_name String
|
display_name String
|
||||||
picture_url String
|
picture_url String
|
||||||
profile_url String
|
profile_url String
|
||||||
lastPixelTime DateTime [default: `now()`, not null]
|
lastTimeGainStarted DateTime [default: `now()`, not null]
|
||||||
pixelStack Int [not null, default: 0]
|
pixelStack Int [not null, default: 0]
|
||||||
undoExpires DateTime
|
undoExpires DateTime
|
||||||
isAdmin Boolean [not null, default: false]
|
isAdmin Boolean [not null, default: false]
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE "User" RENAME COLUMN "lastPixelTime" TO "lastTimeGainStarted";
|
|
@ -25,7 +25,7 @@ model User {
|
||||||
picture_url String?
|
picture_url String?
|
||||||
profile_url String?
|
profile_url String?
|
||||||
|
|
||||||
lastPixelTime DateTime @default(now()) // the time the last pixel was placed at
|
lastTimeGainStarted DateTime @default(now()) // the time base used to determine the amount of stack the user should gain
|
||||||
pixelStack Int @default(0) // amount of pixels stacked for this user
|
pixelStack Int @default(0) // amount of pixels stacked for this user
|
||||||
undoExpires DateTime? // when the undo for the most recent pixel expires at
|
undoExpires DateTime? // when the undo for the most recent pixel expires at
|
||||||
|
|
||||||
|
|
|
@ -430,11 +430,6 @@ class Canvas {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await prisma.user.update({
|
|
||||||
where: { sub: user.sub },
|
|
||||||
data: { lastPixelTime: new Date() },
|
|
||||||
});
|
|
||||||
|
|
||||||
// maybe only update specific element?
|
// maybe only update specific element?
|
||||||
// i don't think it needs to be awaited
|
// i don't think it needs to be awaited
|
||||||
await this.updateCanvasRedisAtPos(x, y);
|
await this.updateCanvasRedisAtPos(x, y);
|
||||||
|
|
|
@ -63,7 +63,7 @@ prisma.paletteColor
|
||||||
Logger.error("Failed to get pallete colors", e);
|
Logger.error("Failed to get pallete colors", e);
|
||||||
});
|
});
|
||||||
|
|
||||||
const getClientConfig = (): ClientConfig => {
|
export const getClientConfig = (): ClientConfig => {
|
||||||
return {
|
return {
|
||||||
version: commitHash,
|
version: commitHash,
|
||||||
pallete: {
|
pallete: {
|
||||||
|
@ -122,12 +122,9 @@ export class SocketServer {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// time in seconds since last pixel placement
|
// time in seconds since last stack gain (including a potential bonus depending on previously remaining time)
|
||||||
// TODO: this causes a mismatch between placement times
|
|
||||||
// - going from 0 stack to 6 stack has a steady increase between each
|
|
||||||
// - going from 3 stack to 6 stack takes longer
|
|
||||||
const timeSinceLastPlace =
|
const timeSinceLastPlace =
|
||||||
(Date.now() - user.lastPixelTime.getTime()) / 1000;
|
(Date.now() - user.lastTimeGainStarted.getTime()) / 1000;
|
||||||
const cooldown = CanvasLib.getPixelCooldown(
|
const cooldown = CanvasLib.getPixelCooldown(
|
||||||
user.pixelStack + 1,
|
user.pixelStack + 1,
|
||||||
getClientConfig()
|
getClientConfig()
|
||||||
|
@ -180,7 +177,7 @@ export class SocketServer {
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
socket.emit("availablePixels", user.pixelStack);
|
socket.emit("availablePixels", user.pixelStack);
|
||||||
socket.emit("pixelLastPlaced", user.lastPixelTime.getTime());
|
socket.emit("pixelLastPlaced", user.lastTimeGainStarted.getTime());
|
||||||
|
|
||||||
const ban = user.getBan();
|
const ban = user.getBan();
|
||||||
socket.emit(
|
socket.emit(
|
||||||
|
|
|
@ -10,7 +10,8 @@ import {
|
||||||
import { Ban, User as UserDB } from "@prisma/client";
|
import { Ban, User as UserDB } from "@prisma/client";
|
||||||
import { Instance } from "./Instance";
|
import { Instance } from "./Instance";
|
||||||
import { ConditionalPromise } from "../lib/utils";
|
import { ConditionalPromise } from "../lib/utils";
|
||||||
|
import { CanvasLib } from "@sc07-canvas/lib/src/canvas";
|
||||||
|
import { getClientConfig } from "../lib/SocketServer";
|
||||||
const Logger = getLogger();
|
const Logger = getLogger();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +38,7 @@ export class User {
|
||||||
static instances: Map<string, User> = new Map();
|
static instances: Map<string, User> = new Map();
|
||||||
|
|
||||||
sub: string;
|
sub: string;
|
||||||
lastPixelTime: Date;
|
lastTimeGainStarted: Date;
|
||||||
pixelStack: number;
|
pixelStack: number;
|
||||||
authSession?: AuthSession;
|
authSession?: AuthSession;
|
||||||
undoExpires?: Date;
|
undoExpires?: Date;
|
||||||
|
@ -54,7 +55,7 @@ export class User {
|
||||||
Logger.debug("User class instansiated for " + data.sub);
|
Logger.debug("User class instansiated for " + data.sub);
|
||||||
|
|
||||||
this.sub = data.sub;
|
this.sub = data.sub;
|
||||||
this.lastPixelTime = data.lastPixelTime;
|
this.lastTimeGainStarted = data.lastTimeGainStarted;
|
||||||
this.pixelStack = data.pixelStack;
|
this.pixelStack = data.pixelStack;
|
||||||
this.undoExpires = data.undoExpires || undefined;
|
this.undoExpires = data.undoExpires || undefined;
|
||||||
|
|
||||||
|
@ -80,7 +81,7 @@ export class User {
|
||||||
|
|
||||||
if (!userData) throw new UserNotFound();
|
if (!userData) throw new UserNotFound();
|
||||||
|
|
||||||
this.lastPixelTime = userData.lastPixelTime;
|
this.lastTimeGainStarted = userData.lastTimeGainStarted;
|
||||||
this.pixelStack = userData.pixelStack;
|
this.pixelStack = userData.pixelStack;
|
||||||
this.undoExpires = userData.undoExpires || undefined;
|
this.undoExpires = userData.undoExpires || undefined;
|
||||||
this.isAdmin = userData.isAdmin;
|
this.isAdmin = userData.isAdmin;
|
||||||
|
@ -120,15 +121,53 @@ export class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
async modifyStack(modifyBy: number): Promise<any> {
|
async modifyStack(modifyBy: number): Promise<any> {
|
||||||
|
let new_date = new Date();
|
||||||
|
if (modifyBy > 0) {
|
||||||
|
let cooldown_to_add = 0.0;
|
||||||
|
for (let i = 0; i < modifyBy; i++) {
|
||||||
|
cooldown_to_add += CanvasLib.getPixelCooldown(
|
||||||
|
this.pixelStack + i + 1,
|
||||||
|
getClientConfig()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_date = new Date(
|
||||||
|
this.lastTimeGainStarted.valueOf() + cooldown_to_add * 1000
|
||||||
|
);
|
||||||
|
} else if (modifyBy < 0) {
|
||||||
|
const cooldown_before_change_s = CanvasLib.getPixelCooldown(
|
||||||
|
this.pixelStack + 1,
|
||||||
|
getClientConfig()
|
||||||
|
);
|
||||||
|
const cooldown_after_change_s = CanvasLib.getPixelCooldown(
|
||||||
|
this.pixelStack + 1 + modifyBy,
|
||||||
|
getClientConfig()
|
||||||
|
);
|
||||||
|
const would_gain_next_at_timestamp_ms =
|
||||||
|
this.lastTimeGainStarted.valueOf() + cooldown_before_change_s * 1000;
|
||||||
|
const time_before_next =
|
||||||
|
would_gain_next_at_timestamp_ms - Date.now().valueOf();
|
||||||
|
// To avoid issue if a negative value is present for some reason
|
||||||
|
if (time_before_next > 0) {
|
||||||
|
if (time_before_next < cooldown_after_change_s * 1000) {
|
||||||
|
new_date = new Date(
|
||||||
|
Date.now() - cooldown_after_change_s * 1000 + time_before_next
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const updatedUser = await prisma.user.update({
|
const updatedUser = await prisma.user.update({
|
||||||
where: { sub: this.sub },
|
where: { sub: this.sub },
|
||||||
data: {
|
data: {
|
||||||
pixelStack: { increment: modifyBy },
|
pixelStack: { increment: modifyBy },
|
||||||
|
lastTimeGainStarted: new_date,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const socket of this.sockets) {
|
for (const socket of this.sockets) {
|
||||||
socket.emit("availablePixels", updatedUser.pixelStack);
|
socket.emit("availablePixels", updatedUser.pixelStack);
|
||||||
|
socket.emit("pixelLastPlaced", updatedUser.lastTimeGainStarted.getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
// we just modified the user data, so we should force an update
|
// we just modified the user data, so we should force an update
|
||||||
|
|
Loading…
Reference in New Issue