fix(security & perf): implement bearer session tokens, salted pbkdf2, object pooling and background caching
This commit is contained in:
+74
-16
@@ -9,13 +9,32 @@ window.GridSystem = class GridSystem {
|
||||
|
||||
this.graves = [];
|
||||
this.animTime = 0;
|
||||
this.bgCanvas = null;
|
||||
this.bgCtx = null;
|
||||
this.bgDirty = true;
|
||||
this.initBiome('day');
|
||||
}
|
||||
|
||||
initBackgroundCache() {
|
||||
if (!this.bgCanvas) {
|
||||
if (typeof document !== 'undefined') {
|
||||
this.bgCanvas = document.createElement('canvas');
|
||||
this.bgCanvas.width = 900;
|
||||
this.bgCanvas.height = 600;
|
||||
this.bgCtx = this.bgCanvas.getContext('2d');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
invalidateBackground() {
|
||||
this.bgDirty = true;
|
||||
}
|
||||
|
||||
initBiome(biome = 'day') {
|
||||
this.biome = biome;
|
||||
this.rows = (biome === 'pool' || biome === 'fog') ? 6 : 5;
|
||||
this.cellH = (biome === 'pool' || biome === 'fog') ? 80 : 96;
|
||||
this.invalidateBackground();
|
||||
|
||||
this.grid = [];
|
||||
for (let r = 0; r < this.rows; r++) {
|
||||
@@ -148,8 +167,25 @@ window.GridSystem = class GridSystem {
|
||||
}
|
||||
}
|
||||
|
||||
draw(ctx, hoverCell, selectedPlantType) {
|
||||
// 1. Draw Lawn Tiles or Pool
|
||||
get theme() {
|
||||
return this._theme || 'classic';
|
||||
}
|
||||
|
||||
set theme(val) {
|
||||
if (this._theme !== val) {
|
||||
this._theme = val;
|
||||
this.invalidateBackground();
|
||||
}
|
||||
}
|
||||
|
||||
renderBackgroundCache() {
|
||||
this.initBackgroundCache();
|
||||
if (!this.bgCtx) return;
|
||||
|
||||
const ctx = this.bgCtx;
|
||||
ctx.clearRect(0, 0, 900, 600);
|
||||
|
||||
// 1. Draw Static Lawn Tiles or Pool Base
|
||||
for (let r = 0; r < this.rows; r++) {
|
||||
const isWater = this.isWaterCell(r);
|
||||
|
||||
@@ -180,18 +216,9 @@ window.GridSystem = class GridSystem {
|
||||
ctx.lineTo(x + 60, y + this.cellH);
|
||||
ctx.stroke();
|
||||
} else if (isWater) {
|
||||
// Pool Water
|
||||
// Pool Water Base
|
||||
ctx.fillStyle = isEven ? '#0288d1' : '#039be5';
|
||||
ctx.fillRect(x, y, this.cellW, this.cellH);
|
||||
|
||||
// Subtle animated water ripples
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.25)';
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.beginPath();
|
||||
const waveOff = Math.sin(this.animTime * 3 + c * 0.8 + r) * 3;
|
||||
ctx.moveTo(x + 10, y + 20 + waveOff);
|
||||
ctx.quadraticCurveTo(x + 40, y + 15 + waveOff, x + 70, y + 20 + waveOff);
|
||||
ctx.stroke();
|
||||
} else if (this.theme === 'cyberpunk') {
|
||||
// Cyberpunk Grid Tiles
|
||||
ctx.fillStyle = isEven ? '#120326' : '#1d063d';
|
||||
@@ -249,13 +276,44 @@ window.GridSystem = class GridSystem {
|
||||
// 2b. Decorative Neighbour Fence along top edge (y: 86..108)
|
||||
this.drawNeighbourFence(ctx);
|
||||
|
||||
// 4. Draw Gravestones in Night Mode
|
||||
this.bgDirty = false;
|
||||
}
|
||||
|
||||
draw(ctx, hoverCell, selectedPlantType) {
|
||||
// 1. Offscreen Canvas Cached Static Background (Lawn, Porch/Chimney, Fence, Water Base)
|
||||
if (this.bgDirty || !this.bgCanvas) {
|
||||
this.renderBackgroundCache();
|
||||
}
|
||||
if (this.bgCanvas) {
|
||||
ctx.drawImage(this.bgCanvas, 0, 0);
|
||||
}
|
||||
|
||||
// 1b. Dynamic Animated Water Ripples (Pool & Fog)
|
||||
if (this.biome === 'pool' || this.biome === 'fog') {
|
||||
ctx.save();
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.25)';
|
||||
ctx.lineWidth = 1.5;
|
||||
for (let r = 2; r <= 3; r++) {
|
||||
for (let c = 0; c < this.cols; c++) {
|
||||
const x = this.startX + c * this.cellW;
|
||||
const y = this.startY + r * this.cellH;
|
||||
const waveOff = Math.sin(this.animTime * 3 + c * 0.8 + r) * 3;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + 10, y + 20 + waveOff);
|
||||
ctx.quadraticCurveTo(x + 40, y + 15 + waveOff, x + 70, y + 20 + waveOff);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
// 2. Draw Gravestones in Night Mode
|
||||
for (const grave of this.graves) {
|
||||
const bounds = this.getCellBounds(grave.col, grave.row);
|
||||
this.drawGravestone(ctx, bounds.centerX, bounds.centerY);
|
||||
}
|
||||
|
||||
// 5. Hover effect
|
||||
// 3. Hover effect
|
||||
if (hoverCell && selectedPlantType) {
|
||||
const bounds = this.getCellBounds(hoverCell.col, hoverCell.row);
|
||||
const isWater = this.isWaterCell(hoverCell.row);
|
||||
@@ -288,7 +346,7 @@ window.GridSystem = class GridSystem {
|
||||
ctx.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h);
|
||||
}
|
||||
|
||||
// 6. Draw Lawnmowers & Pool Cleaners
|
||||
// 4. Draw Lawnmowers & Pool Cleaners
|
||||
for (const mower of this.lawnmowers) {
|
||||
if (mower.used) continue;
|
||||
if (mower.isCleaner) {
|
||||
@@ -298,7 +356,7 @@ window.GridSystem = class GridSystem {
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Volumetric Fog Layer
|
||||
// 5. Volumetric Fog Layer
|
||||
if (this.biome === 'fog') {
|
||||
this.drawFogOverlay(ctx);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user