This repository has been archived on 2026-05-04. You can view files and clone it, but cannot push or open issues or pull requests.
Galaxy-Strike-Online/GameServer/systems/GalaxySystem.js

113 lines
3.8 KiB
JavaScript

/**
* Galaxy Strike Online - Galaxy System
* Procedurally generates and manages sectors
*/
class GalaxySystem {
constructor() {
this.GRID_W = 30;
this.GRID_H = 20;
this.TYPES = ['empty','empty','empty','asteroid','asteroid','trade_hub','npc_territory','ruins','void_rift'];
this._sectors = null;
}
/** Lazy-generate the galaxy grid once */
getSectors() {
if (!this._sectors) this._sectors = this._generate();
return this._sectors;
}
_generate() {
const sectors = {};
for (let y = 0; y < this.GRID_H; y++) {
for (let x = 0; x < this.GRID_W; x++) {
const id = `${x}_${y}`;
const distFromCenter = Math.hypot(x - 15, y - 10) / 18;
// Richer regions further from core
const typeRoll = Math.random();
let type = 'empty';
if (typeRoll > 0.70) type = 'asteroid';
if (typeRoll > 0.88) type = 'npc_territory';
if (typeRoll > 0.94) type = 'trade_hub';
if (typeRoll > 0.97 && distFromCenter > 0.4) type = 'ruins';
if (typeRoll > 0.99 && distFromCenter > 0.6) type = 'void_rift';
const richness = Math.random();
sectors[id] = {
id, x, y, type,
name: this._sectorName(x, y),
threat: Math.min(10, Math.floor(distFromCenter * 10 + Math.random() * 3)),
richness: type === 'asteroid' ? (0.3 + richness * 0.7) : 0,
owner: null,
explored: false,
};
}
}
// Always make start sector safe
sectors['15_10'] = { id:'15_10', x:15, y:10, type:'trade_hub', name:'New Haven', threat:0, richness:0, owner:null, explored:true };
return sectors;
}
_sectorName(x, y) {
const prefixes = ['Alpha','Beta','Gamma','Delta','Sigma','Tau','Zeta','Omega','Nova','Vega','Lyra','Cygni'];
const suffixes = ['Prime','Station','Reach','Deep','Expanse','Crossing','Rift','Gate','Void','Fields'];
const seed = (x * 31 + y * 17) % (prefixes.length * suffixes.length);
return prefixes[seed % prefixes.length] + ' ' + suffixes[Math.floor(seed / prefixes.length) % suffixes.length];
}
/** Returns the sector or null */
getSector(id) {
return this.getSectors()[id] || null;
}
/** Mark a sector explored by a player */
exploreSector(sectorId, playerData) {
const sector = this.getSector(sectorId);
if (!sector) throw new Error('Sector not found');
const explored = playerData.exploredSectors || [];
if (!explored.includes(sectorId)) {
explored.push(sectorId);
playerData.exploredSectors = explored;
}
return sector;
}
/** Return list of sectors visible to player (explored + adjacent) */
getVisibleSectors(playerData) {
const explored = new Set(playerData.exploredSectors || ['15_10']);
const visible = new Set(explored);
// Reveal adjacent sectors to all explored
for (const id of explored) {
const [x, y] = id.split('_').map(Number);
for (const [dx, dy] of [[-1,0],[1,0],[0,-1],[0,1]]) {
const nid = `${x+dx}_${y+dy}`;
if (this.getSector(nid)) visible.add(nid);
}
}
const all = this.getSectors();
return Array.from(visible).map(id => {
const s = { ...all[id] };
s.explored = explored.has(id);
if (!s.explored) {
// Fog: hide details of unexplored but adjacent sectors
s.name = '???';
s.richness = 0;
s.owner = null;
}
return s;
});
}
/** Player claims/sets base in a sector */
claimSector(sectorId, playerData) {
const sector = this.getSector(sectorId);
if (!sector) throw new Error('Sector not found');
if (sector.type === 'void_rift') throw new Error('Cannot claim Void Rift sectors');
sector.owner = playerData.userId;
this.exploreSector(sectorId, playerData);
playerData.homeSector = sectorId;
return sector;
}
}
module.exports = GalaxySystem;