Files
novafarma/EMERGENCY_SYSTEMS_RECOVERY/ChunkManager.js
2026-01-16 02:43:46 +01:00

217 lines
6.6 KiB
JavaScript

// ChunkManager - Handles chunk-based terrain loading for large maps
class ChunkManager {
constructor(scene, chunkSize = 50) {
this.scene = scene;
this.chunkSize = chunkSize; // 50x50 tiles per chunk
this.biomeSystem = null; // Will be set by GameScene
// Active chunks (currently loaded)
this.activeChunks = new Map(); // Key: "chunkX,chunkY", Value: chunk data
// Chunk load radius (how many chunks around player)
this.loadRadius = 1; // Load 3x3 = 9 chunks at once
// Player position tracking
this.lastPlayerChunkX = -1;
this.lastPlayerChunkY = -1;
console.log(`💾 ChunkManager initialized (chunk size: ${chunkSize}x${chunkSize})`);
}
// Get chunk coordinates from world coordinates
worldToChunk(worldX, worldY) {
return {
chunkX: Math.floor(worldX / this.chunkSize),
chunkY: Math.floor(worldY / this.chunkSize)
};
}
// Get chunk key string
getChunkKey(chunkX, chunkY) {
return `${chunkX},${chunkY}`;
}
// Check if chunk is loaded
isChunkLoaded(chunkX, chunkY) {
return this.activeChunks.has(this.getChunkKey(chunkX, chunkY));
}
// Load a single chunk
loadChunk(chunkX, chunkY) {
const key = this.getChunkKey(chunkX, chunkY);
// Already loaded
if (this.activeChunks.has(key)) {
return this.activeChunks.get(key);
}
console.log(`📦 Loading chunk (${chunkX}, ${chunkY})`);
// Create chunk data
const chunk = {
chunkX,
chunkY,
key,
tiles: [],
objects: [], // Trees, rocks, decorations
sprites: [] // Phaser sprites for this chunk
};
// Generate or load chunk tiles
const startX = chunkX * this.chunkSize;
const startY = chunkY * this.chunkSize;
for (let y = 0; y < this.chunkSize; y++) {
for (let x = 0; x < this.chunkSize; x++) {
const worldX = startX + x;
const worldY = startY + y;
// Get biome for this tile
let biomeId = 'grassland';
if (this.biomeSystem) {
biomeId = this.biomeSystem.getBiomeAt(worldX, worldY);
}
chunk.tiles.push({
x: worldX,
y: worldY,
biome: biomeId
});
}
}
// Store chunk
this.activeChunks.set(key, chunk);
// Render chunk (if terrain system available)
if (this.scene.terrainSystem && this.scene.terrainSystem.renderChunk) {
this.scene.terrainSystem.renderChunk(chunk);
}
return chunk;
}
// Unload a single chunk
unloadChunk(chunkX, chunkY) {
const key = this.getChunkKey(chunkX, chunkY);
if (!this.activeChunks.has(key)) return;
console.log(`📤 Unloading chunk (${chunkX}, ${chunkY})`);
const chunk = this.activeChunks.get(key);
// Destroy all sprites in chunk
if (chunk.sprites) {
chunk.sprites.forEach(sprite => {
if (sprite && sprite.destroy) {
sprite.destroy();
}
});
}
// Remove chunk
this.activeChunks.delete(key);
}
// Update active chunks based on player position
updateActiveChunks(playerX, playerY) {
const { chunkX, chunkY } = this.worldToChunk(playerX, playerY);
// Player hasn't changed chunks
if (chunkX === this.lastPlayerChunkX && chunkY === this.lastPlayerChunkY) {
return;
}
console.log(`🔄 Player moved to chunk (${chunkX}, ${chunkY})`);
this.lastPlayerChunkX = chunkX;
this.lastPlayerChunkY = chunkY;
// Determine which chunks should be loaded
const chunksToLoad = new Set();
for (let dy = -this.loadRadius; dy <= this.loadRadius; dy++) {
for (let dx = -this.loadRadius; dx <= this.loadRadius; dx++) {
const targetChunkX = chunkX + dx;
const targetChunkY = chunkY + dy;
chunksToLoad.add(this.getChunkKey(targetChunkX, targetChunkY));
}
}
// Unload chunks that are too far
const chunksToUnload = [];
for (const [key, chunk] of this.activeChunks) {
if (!chunksToLoad.has(key)) {
chunksToUnload.push({ x: chunk.chunkX, y: chunk.chunkY });
}
}
chunksToUnload.forEach(({ x, y }) => this.unloadChunk(x, y));
// Load new chunks
for (let dy = -this.loadRadius; dy <= this.loadRadius; dy++) {
for (let dx = -this.loadRadius; dx <= this.loadRadius; dx++) {
const targetChunkX = chunkX + dx;
const targetChunkY = chunkY + dy;
if (!this.isChunkLoaded(targetChunkX, targetChunkY)) {
this.loadChunk(targetChunkX, targetChunkY);
}
}
}
}
// Force reload all chunks (for debugging)
reloadAllChunks() {
console.log('🔄 Reloading all chunks...');
const chunksToReload = [];
for (const [key, chunk] of this.activeChunks) {
chunksToReload.push({ x: chunk.chunkX, y: chunk.chunkY });
}
// Unload all
chunksToReload.forEach(({ x, y }) => this.unloadChunk(x, y));
// Reload based on player position
if (this.scene.player) {
const pos = this.scene.player.getPosition();
this.updateActiveChunks(pos.x, pos.y);
}
}
// Get chunk at world position
getChunkAt(worldX, worldY) {
const { chunkX, chunkY } = this.worldToChunk(worldX, worldY);
return this.activeChunks.get(this.getChunkKey(chunkX, chunkY));
}
// Get statistics
getStats() {
return {
activeChunks: this.activeChunks.size,
chunkSize: this.chunkSize,
loadRadius: this.loadRadius,
maxChunks: Math.pow((this.loadRadius * 2 + 1), 2),
totalTilesLoaded: this.activeChunks.size * this.chunkSize * this.chunkSize
};
}
// Destroy all chunks
destroy() {
console.log('💾 ChunkManager destroying all chunks...');
for (const [key, chunk] of this.activeChunks) {
if (chunk.sprites) {
chunk.sprites.forEach(sprite => {
if (sprite && sprite.destroy) sprite.destroy();
});
}
}
this.activeChunks.clear();
console.log('💾 ChunkManager destroyed');
}
}