From fb038f241917ac1ebd9d5482f15b0f4b558f53d9 Mon Sep 17 00:00:00 2001 From: DevelopingTom Date: Sun, 24 Aug 2025 19:41:51 +0200 Subject: [PATCH] Create stations regardless of factory ownership (#1904) ## Description: Bug fix: cities and ports would only connect to factories owned by the current player, ignoring those belonging to other players. This update makes the player ID optional when searching for nearby units: if no player ID is provided, unit ownership is disregarded, allowing connections to all factories regardless of ownership. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: IngloriousTom --- src/core/execution/CityExecution.ts | 1 - src/core/execution/PortExecution.ts | 1 - src/core/game/Game.ts | 2 +- src/core/game/GameImpl.ts | 2 +- src/core/game/UnitGrid.ts | 25 +++++++++++++++++++------ 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/core/execution/CityExecution.ts b/src/core/execution/CityExecution.ts index 863ba716e..69d39977d 100644 --- a/src/core/execution/CityExecution.ts +++ b/src/core/execution/CityExecution.ts @@ -52,7 +52,6 @@ export class CityExecution implements Execution { this.city.tile(), this.mg.config().trainStationMaxRange(), UnitType.Factory, - this.player.id(), ); if (nearbyFactory) { this.mg.addExecution(new TrainStationExecution(this.city)); diff --git a/src/core/execution/PortExecution.ts b/src/core/execution/PortExecution.ts index fc8971b2d..5c7dfc566 100644 --- a/src/core/execution/PortExecution.ts +++ b/src/core/execution/PortExecution.ts @@ -97,7 +97,6 @@ export class PortExecution implements Execution { this.port.tile(), this.mg.config().trainStationMaxRange(), UnitType.Factory, - this.player.id(), ); if (nearbyFactory) { this.mg.addExecution(new TrainStationExecution(this.port)); diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 2486e57ac..2416371da 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -673,7 +673,7 @@ export type Game = { tile: TileRef, searchRange: number, type: UnitType, - playerId: PlayerID, + playerId?: PlayerID, ): boolean; nearbyUnits( tile: TileRef, diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 91e6ff98d..9d1898910 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -752,7 +752,7 @@ export class GameImpl implements Game { tile: TileRef, searchRange: number, type: UnitType, - playerId: PlayerID, + playerId?: PlayerID, ) { return this.unitGrid.hasUnitNearby(tile, searchRange, type, playerId); } diff --git a/src/core/game/UnitGrid.ts b/src/core/game/UnitGrid.ts index 2f17d9ee9..bb8b52d0d 100644 --- a/src/core/game/UnitGrid.ts +++ b/src/core/game/UnitGrid.ts @@ -170,12 +170,28 @@ export class UnitGrid { return nearby; } + private unitIsInRange( + unit: Unit | UnitView, + tile: TileRef, + rangeSquared: number, + playerId?: PlayerID, + ): boolean { + if (!unit.isActive()) { + return false; + } + if (playerId !== undefined && unit.owner().id() !== playerId) { + return false; + } + const distSquared = this.squaredDistanceFromTile(unit, tile); + return distSquared <= rangeSquared; + } + // Return true if it finds an owned specific unit in range hasUnitNearby( tile: TileRef, searchRange: number, type: UnitType, - playerId: PlayerID, + playerId?: PlayerID, ): boolean { const { startGridX, endGridX, startGridY, endGridY } = this.getCellsInRange( tile, @@ -187,11 +203,8 @@ export class UnitGrid { const unitSet = this.grid[cy][cx].get(type); if (unitSet === undefined) continue; for (const unit of unitSet) { - if (unit.owner().id() === playerId && unit.isActive()) { - const distSquared = this.squaredDistanceFromTile(unit, tile); - if (distSquared <= rangeSquared) { - return true; - } + if (this.unitIsInRange(unit, tile, rangeSquared, playerId)) { + return true; } } }