Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 1 addition & 19 deletions src/engine/systems/BuildingPlacementSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,6 @@ export class BuildingPlacementSystem extends System {
attachTo?: number; // Parent building ID for addons
parentBuildingId?: number; // Alternative name for parent (used by AI)
}): void {
// Diagnostic: confirm event handler is being called
console.log(`[BuildingPlacement] Received building:place event: ${data.buildingType} at (${data.position?.x}, ${data.position?.y}) for ${data.playerId}`);

const { buildingType, playerId = getLocalPlayerId() ?? 'player1' } = data;
const definition = BUILDING_DEFINITIONS[buildingType];
const isAddon = data.isAddon === true;
Expand Down Expand Up @@ -368,31 +365,23 @@ export class BuildingPlacementSystem extends System {
const aiPlayer = !isPlayerLocal ? aiSystem?.getAIPlayer(playerId) : undefined;
const isPlayerAI = aiPlayer !== undefined;

// Debug: Log player type detection
console.log(`[BuildingPlacement] Player check: playerId=${playerId}, isLocal=${isPlayerLocal}, hasAISystem=${!!aiSystem}, isAI=${isPlayerAI}`);

// Check resources (local player via game store, AI via AI state)
if (isPlayerLocal) {
if (this.game.statePort.getMinerals() < definition.mineralCost) {
this.game.eventBus.emit('alert:notEnoughMinerals', {});
this.game.eventBus.emit('warning:lowMinerals', {});
console.log(`[BuildingPlacement] FAIL: Local player lacks minerals`);
return;
}
if (this.game.statePort.getVespene() < definition.vespeneCost) {
this.game.eventBus.emit('alert:notEnoughVespene', {});
this.game.eventBus.emit('warning:lowVespene', {});
console.log(`[BuildingPlacement] FAIL: Local player lacks vespene`);
return;
}
} else if (isPlayerAI && aiPlayer) {
if (aiPlayer.minerals < definition.mineralCost || aiPlayer.vespene < definition.vespeneCost) {
console.log(`[BuildingPlacement] FAIL: AI ${playerId} lacks resources for ${buildingType} (need ${definition.mineralCost}M/${definition.vespeneCost}G, have ${Math.floor(aiPlayer.minerals)}M/${Math.floor(aiPlayer.vespene)}G)`);
debugBuildingPlacement.log(`AI ${playerId} lacks resources for ${buildingType}`);
return;
}
} else {
// Neither local nor AI player - this shouldn't happen
console.log(`[BuildingPlacement] WARNING: Player ${playerId} is neither local nor AI - skipping resource check`);
}

// Check building dependencies (tech requirements)
Expand Down Expand Up @@ -425,20 +414,16 @@ export class BuildingPlacementSystem extends System {
// so we can exclude them from collision detection
const worker = this.findWorkerForConstruction(data.workerId, playerId);
if (!worker) {
console.log(`[BuildingPlacement] FAIL: No worker available for ${playerId} to build ${buildingType}`);
this.game.eventBus.emit('ui:error', { message: 'No worker available', playerId });
return;
}
console.log(`[BuildingPlacement] Found worker ${worker.entity.id} for ${buildingType}`);

// Check placement validity using center position (exclude builder from collision)
// Skip collision check for extractors since they go on vespene geysers
if (buildingType !== 'extractor' && !this.isValidPlacement(snappedX, snappedY, definition.width, definition.height, worker.entity.id)) {
console.log(`[BuildingPlacement] FAIL: Invalid placement at (${snappedX}, ${snappedY}) for ${buildingType}`);
this.game.eventBus.emit('ui:error', { message: 'Cannot build here - area blocked', playerId });
return;
}
console.log(`[BuildingPlacement] Placement valid at (${snappedX}, ${snappedY}) for ${buildingType}`);

// Deduct resources (local player via store, AI via AI state)
if (isPlayerLocal) {
Expand All @@ -459,9 +444,6 @@ export class BuildingPlacementSystem extends System {
.add(health)
.add(new Selectable(Math.max(definition.width, definition.height) * 0.6, 10, playerId));

// Diagnostic: confirm building entity was created (helps debug AI placement issues)
console.log(`[BuildingPlacement] ${playerId}: Created ${buildingType} entity #${buildingEntity.id} at (${snappedX}, ${snappedY})`);

// Building starts in 'waiting_for_worker' state (from constructor)
// Construction will start when worker arrives at site

Expand Down
10 changes: 0 additions & 10 deletions src/engine/systems/SpawnSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,6 @@ export class SpawnSystem extends System {
// Create the entity
const entity = this.world.createEntity();

// Diagnostic: confirm entity creation
console.log(`[SpawnSystem] Created ${unitType} entity #${entity.id} at (${x.toFixed(1)}, ${y.toFixed(1)}) for ${playerId}`);

// Calculate visual properties for selection
// Flying units need visualHeight to match their rendered position
const isFlying = definition.isFlying ?? false;
Expand All @@ -90,13 +87,6 @@ export class SpawnSystem extends System {
.add(new Selectable(selectionRadius, 5, playerId, visualScale, visualHeight))
.add(new Velocity());

// TEMP: Verify all required components are present
const hasTransform = entity.has('Transform');
const hasUnit = entity.has('Unit');
const hasHealth = entity.has('Health');
const hasSelectable = entity.has('Selectable');
console.log(`[SpawnSystem] Entity #${entity.id} components: T=${hasTransform}, U=${hasUnit}, H=${hasHealth}, S=${hasSelectable}`);

// Add abilities if the unit has any
if (definition.abilities && definition.abilities.length > 0) {
const maxEnergy = definition.maxEnergy ?? 0;
Expand Down
15 changes: 1 addition & 14 deletions src/engine/systems/ai/AIBuildOrderExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,15 +188,6 @@ export class AIBuildOrderExecutor {
const currentTick = this.game.getCurrentTick();
const shouldLog = currentTick % 200 === 0;

// One-time diagnostic at tick 100 to help debug AI issues
if (currentTick === 100) {
const aiBuildings = buildings.filter(b => b.get<Selectable>('Selectable')?.playerId === ai.playerId);
console.log(`[AIBuildOrder] ${ai.playerId} tick 100 diagnostic: Looking for producer of "${unitType}". Total buildings=${buildings.length}, AI buildings=${aiBuildings.length}`);
for (const b of aiBuildings) {
const building = b.get<Building>('Building');
console.log(` - ${building?.buildingId}: complete=${building?.isComplete()}, canProduce=[${building?.canProduce?.join(',')}]`);
}
}

// Debug: log what we're looking for
if (shouldLog && buildings.length === 0) {
Expand Down Expand Up @@ -458,8 +449,6 @@ export class AIBuildOrderExecutor {
workerId,
});

// Always log successful building placement (helps diagnose AI issues)
console.log(`[AIBuildOrder] ${ai.playerId}: SUCCESS - Building ${buildingType} at (${buildPos.x.toFixed(1)}, ${buildPos.y.toFixed(1)}) with worker ${workerId}`);
debugAI.log(`[AIBuildOrder] ${ai.playerId}: Placed ${buildingType} at (${buildPos.x.toFixed(1)}, ${buildPos.y.toFixed(1)}) with worker ${workerId}`);

return true;
Expand Down Expand Up @@ -612,9 +601,7 @@ export class AIBuildOrderExecutor {
ai.supply += unitDef.supplyCost; // Track supply used
building.addToProductionQueue('unit', unitType, unitDef.buildTime, unitDef.supplyCost);

// Always log successful unit training (helps diagnose AI issues)
console.log(`[AIBuildOrder] ${ai.playerId}: SUCCESS - Queued ${unitType} at ${building.buildingId} (minerals: ${Math.floor(ai.minerals)}, supply: ${ai.supply}/${ai.maxSupply})`);
debugAI.log(`[AIBuildOrder] ${ai.playerId}: Queued ${unitType} at ${building.buildingId} (minerals: ${Math.floor(ai.minerals)})`);
debugAI.log(`[AIBuildOrder] ${ai.playerId}: Queued ${unitType} at ${building.buildingId} (minerals: ${Math.floor(ai.minerals)}, supply: ${ai.supply}/${ai.maxSupply})`);
return true;
}

Expand Down
9 changes: 2 additions & 7 deletions src/engine/workers/GameWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,11 +580,6 @@ export class WorkerGame extends GameCore {
const states: UnitRenderState[] = [];
const entities = this.world.getEntitiesWith('Transform', 'Unit', 'Health', 'Selectable');

if (this.renderStatesSent <= 5 || this.renderStatesSent % 100 === 0) {
const allEntities = this.world.getEntities();
const unitsOnly = this.world.getEntitiesWith('Unit');
console.log(`[GameWorker] collectUnitRenderState: total=${allEntities.length}, withUnit=${unitsOnly.length}, fullQuery=${entities.length}`);
}

for (const entity of entities) {
const transform = entity.get<Transform>('Transform')!;
Expand Down Expand Up @@ -794,7 +789,7 @@ export class WorkerGame extends GameCore {
// ============================================================================

public spawnInitialEntities(mapData: SpawnMapData): void {
console.log('[GameWorker] spawnInitialEntities called:', {
debugInitialization.log('[GameWorker] spawnInitialEntities called:', {
resourceCount: mapData.resources?.length ?? 0,
spawnCount: mapData.spawns?.length ?? 0,
playerSlotCount: mapData.playerSlots?.length ?? 0,
Expand Down Expand Up @@ -1054,7 +1049,7 @@ if (typeof self !== 'undefined') {
}

case 'spawnEntities': {
console.log('[GameWorker] Received spawnEntities message');
debugInitialization.log('[GameWorker] Received spawnEntities message');
game?.spawnInitialEntities(message.mapData);
break;
}
Expand Down
4 changes: 0 additions & 4 deletions src/engine/workers/RenderStateAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -609,10 +609,6 @@ export class RenderStateWorldAdapter implements IWorldProvider {
try {
this._updateCount++;

// TEMP: Always log first 10 updates for debugging render pipeline
if (this._updateCount <= 10 || this._updateCount % 100 === 0) {
console.log(`[RenderStateWorldAdapter] updateFromRenderState #${this._updateCount}: tick=${state.tick}, units=${state.units.length}, buildings=${state.buildings.length}, resources=${state.resources.length}`);
}

// Debug: log first significant update
if (!this.hasLoggedFirstUpdate && (state.units.length > 0 || state.buildings.length > 0 || state.resources.length > 0)) {
Expand Down
4 changes: 0 additions & 4 deletions src/rendering/BuildingRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,10 +484,6 @@ export class BuildingRenderer {
// PERF: Only re-sort when entity count changes (add/remove) to avoid O(n log n) every frame
const rawEntities = this.world.getEntitiesWith('Transform', 'Building');

// TEMP: Log entity count for debugging render pipeline
if (this.debugFrameCount <= 10 || this.debugFrameCount % 300 === 0) {
console.log(`[BuildingRenderer] update #${this.debugFrameCount}: rawEntities=${rawEntities.length}, world=${this.world.constructor.name}`);
}

if (rawEntities.length !== this.cachedEntityCount) {
// Rebuild cache - entity count changed (add/remove occurred)
Expand Down
4 changes: 0 additions & 4 deletions src/rendering/UnitRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -876,10 +876,6 @@ export class UnitRenderer {
// PERF: Only re-sort when entity count changes (add/remove) to avoid O(n log n) every frame
const rawEntities = this.world.getEntitiesWith('Transform', 'Unit');

// TEMP: Log entity count for debugging render pipeline
if (this.frameCount <= 10 || this.frameCount % 300 === 0) {
console.log(`[UnitRenderer] update #${this.frameCount}: rawEntities=${rawEntities.length}, world=${this.world.constructor.name}`);
}

if (rawEntities.length !== this.cachedEntityCount) {
// Rebuild cache - entity count changed (add/remove occurred)
Expand Down