mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 08:48:10 +00:00
buildableUnits perf and related refactor of StructureTypes/IsStructureType
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Execution, Game, isStructureType, Player } from "../game/Game";
|
||||
import { Execution, Game, Player } from "../game/Game";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { simpleHash } from "../Util";
|
||||
import { AllianceExtensionExecution } from "./alliance/AllianceExtensionExecution";
|
||||
@@ -84,7 +84,7 @@ export class BotExecution implements Execution {
|
||||
|
||||
private deleteAllStructures() {
|
||||
for (const unit of this.bot.units()) {
|
||||
if (isStructureType(unit.type()) && this.bot.canDeleteUnit()) {
|
||||
if (this.mg.isStructureType(unit.type()) && this.bot.canDeleteUnit()) {
|
||||
this.mg.addExecution(new DeleteUnitExecution(this.bot, unit.id()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
isStructureType,
|
||||
MessageType,
|
||||
Player,
|
||||
TerraNullius,
|
||||
@@ -333,7 +332,7 @@ export class NukeExecution implements Execution {
|
||||
private redrawBuildings(range: number) {
|
||||
const rangeSquared = range * range;
|
||||
for (const unit of this.mg.units()) {
|
||||
if (isStructureType(unit.type())) {
|
||||
if (this.mg.isStructureType(unit.type())) {
|
||||
if (
|
||||
this.mg.euclideanDistSquared(this.dst, unit.tile()) < rangeSquared
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NukeMagnitude } from "../configuration/Config";
|
||||
import { Game, Player, StructureTypes } from "../game/Game";
|
||||
import { Game, Player } from "../game/Game";
|
||||
import { euclDistFN, GameMap, TileRef } from "../game/GameMap";
|
||||
import { GameView } from "../game/GameView";
|
||||
|
||||
@@ -60,7 +60,7 @@ export function wouldNukeBreakAlliance(
|
||||
const wouldDestroyAlliedStructure = game.anyUnitNearby(
|
||||
targetTile,
|
||||
magnitude.outer,
|
||||
StructureTypes,
|
||||
game.getStructureTypes(),
|
||||
(unit) =>
|
||||
unit.owner().isPlayer() && allySmallIds.has(unit.owner().smallID()),
|
||||
);
|
||||
@@ -119,7 +119,7 @@ export function listNukeBreakAlliance(
|
||||
|
||||
// Also check if any allied structures would be destroyed
|
||||
game
|
||||
.nearbyUnits(targetTile, magnitude.outer, [...StructureTypes])
|
||||
.nearbyUnits(targetTile, magnitude.outer, game.getStructureTypes())
|
||||
.forEach(({ unit }) =>
|
||||
playersToBreakAllianceWith.add(unit.owner().smallID()),
|
||||
);
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
Player,
|
||||
PlayerType,
|
||||
Relation,
|
||||
StructureTypes,
|
||||
Unit,
|
||||
UnitType,
|
||||
} from "../../game/Game";
|
||||
@@ -347,7 +346,7 @@ export class NationStructureBehavior {
|
||||
*/
|
||||
private getTotalStructureDensity(): number {
|
||||
let totalStructures = 0;
|
||||
for (const type of StructureTypes) {
|
||||
for (const type of this.game.getStructureTypes()) {
|
||||
totalStructures += this.player.units(type).length; // ignoring levels
|
||||
}
|
||||
const tilesOwned = this.player.numTilesOwned();
|
||||
|
||||
+2
-15
@@ -258,21 +258,6 @@ export enum TrainType {
|
||||
Carriage = "Carriage",
|
||||
}
|
||||
|
||||
const _structureTypes: ReadonlySet<UnitType> = new Set([
|
||||
UnitType.City,
|
||||
UnitType.DefensePost,
|
||||
UnitType.SAMLauncher,
|
||||
UnitType.MissileSilo,
|
||||
UnitType.Port,
|
||||
UnitType.Factory,
|
||||
]);
|
||||
|
||||
export const StructureTypes: readonly UnitType[] = [..._structureTypes];
|
||||
|
||||
export function isStructureType(type: UnitType): boolean {
|
||||
return _structureTypes.has(type);
|
||||
}
|
||||
|
||||
export interface OwnerComp {
|
||||
owner: Player;
|
||||
}
|
||||
@@ -793,6 +778,8 @@ export interface Game extends GameMap {
|
||||
predicate?: UnitPredicate,
|
||||
includeUnderConstruction?: boolean,
|
||||
): Array<{ unit: Unit; distSquared: number }>;
|
||||
getStructureTypes(): UnitType[];
|
||||
isStructureType(type: UnitType): boolean;
|
||||
|
||||
addExecution(...exec: Execution[]): void;
|
||||
displayMessage(
|
||||
|
||||
@@ -97,6 +97,9 @@ export class GameImpl implements Game {
|
||||
private _miniWaterGraph: AbstractGraph | null = null;
|
||||
private _miniWaterHPA: AStarWaterHierarchical | null = null;
|
||||
|
||||
private _structureTypes: UnitType[];
|
||||
private _structureTypesSet: Set<UnitType>;
|
||||
|
||||
constructor(
|
||||
private _humans: PlayerInfo[],
|
||||
private _nations: Nation[],
|
||||
@@ -128,6 +131,11 @@ export class GameImpl implements Game {
|
||||
);
|
||||
}
|
||||
|
||||
this._structureTypes = Object.values(UnitType).filter(
|
||||
(t) => this._config.unitInfo(t).territoryBound,
|
||||
);
|
||||
this._structureTypesSet = new Set(this._structureTypes);
|
||||
|
||||
console.log(
|
||||
`[GameImpl] Constructor total: ${(performance.now() - constructorStart).toFixed(0)}ms`,
|
||||
);
|
||||
@@ -903,6 +911,14 @@ export class GameImpl implements Game {
|
||||
}>;
|
||||
}
|
||||
|
||||
getStructureTypes(): UnitType[] {
|
||||
return this._structureTypes;
|
||||
}
|
||||
|
||||
isStructureType(type: UnitType): boolean {
|
||||
return this._structureTypesSet.has(type);
|
||||
}
|
||||
|
||||
ref(x: number, y: number): TileRef {
|
||||
return this._map.ref(x, y);
|
||||
}
|
||||
|
||||
@@ -598,6 +598,9 @@ export class GameView implements GameMap {
|
||||
|
||||
private _map: GameMap;
|
||||
|
||||
private _structureTypes: UnitType[];
|
||||
private _structureTypesSet: Set<UnitType>;
|
||||
|
||||
constructor(
|
||||
public worker: WorkerClient,
|
||||
private _config: Config,
|
||||
@@ -626,6 +629,11 @@ export class GameView implements GameMap {
|
||||
flag: nation.flag,
|
||||
} satisfies PlayerCosmetics);
|
||||
}
|
||||
|
||||
this._structureTypes = Object.values(UnitType).filter(
|
||||
(t) => this._config.unitInfo(t).territoryBound,
|
||||
);
|
||||
this._structureTypesSet = new Set(this._structureTypes);
|
||||
}
|
||||
|
||||
isOnEdgeOfMap(ref: TileRef): boolean {
|
||||
@@ -754,6 +762,14 @@ export class GameView implements GameMap {
|
||||
);
|
||||
}
|
||||
|
||||
getStructureTypes(): UnitType[] {
|
||||
return this._structureTypes;
|
||||
}
|
||||
|
||||
isStructureType(type: UnitType): boolean {
|
||||
return this._structureTypesSet.has(type);
|
||||
}
|
||||
|
||||
myClientID(): ClientID {
|
||||
return this._myClientID;
|
||||
}
|
||||
|
||||
+16
-14
@@ -30,7 +30,6 @@ import {
|
||||
PlayerProfile,
|
||||
PlayerType,
|
||||
Relation,
|
||||
StructureTypes,
|
||||
Team,
|
||||
TerraNullius,
|
||||
Tick,
|
||||
@@ -52,6 +51,8 @@ import {
|
||||
} from "./TransportShipUtils";
|
||||
import { UnitImpl } from "./UnitImpl";
|
||||
|
||||
const UNIT_TYPES = Object.freeze(Object.values(UnitType));
|
||||
|
||||
interface Target {
|
||||
tick: Tick;
|
||||
target: Player;
|
||||
@@ -911,6 +912,10 @@ export class PlayerImpl implements Player {
|
||||
}
|
||||
|
||||
public findUnitToUpgrade(type: UnitType, targetTile: TileRef): Unit | false {
|
||||
if (!this.mg.config().unitInfo(type).upgradable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const range = this.mg.config().structureMinDist();
|
||||
const existing = this.mg
|
||||
.nearbyUnits(targetTile, range, type, undefined, true)
|
||||
@@ -958,23 +963,22 @@ export class PlayerImpl implements Player {
|
||||
|
||||
public buildableUnits(tile: TileRef | null): BuildableUnit[] {
|
||||
const validTiles = tile !== null ? this.validStructureSpawnTiles(tile) : [];
|
||||
return Object.values(UnitType).map((u) => {
|
||||
return UNIT_TYPES.map((u) => {
|
||||
const cost = this.mg.config().unitInfo(u).cost(this.mg, this);
|
||||
let canUpgrade: number | false = false;
|
||||
let canBuild: TileRef | false = false;
|
||||
if (!this.mg.inSpawnPhase()) {
|
||||
const existingUnit = tile !== null && this.findUnitToUpgrade(u, tile);
|
||||
if (tile !== null && !this.mg.inSpawnPhase()) {
|
||||
const existingUnit = this.findUnitToUpgrade(u, tile);
|
||||
if (existingUnit !== false) {
|
||||
canUpgrade = existingUnit.id();
|
||||
}
|
||||
if (tile !== null) {
|
||||
canBuild = this.canBuild(u, tile, validTiles);
|
||||
}
|
||||
canBuild = this.canBuild(u, tile, validTiles, cost);
|
||||
}
|
||||
return {
|
||||
type: u,
|
||||
canBuild,
|
||||
canUpgrade,
|
||||
cost: this.mg.config().unitInfo(u).cost(this.mg, this),
|
||||
cost,
|
||||
overlappingRailroads:
|
||||
canBuild !== false
|
||||
? this.mg.railNetwork().overlappingRailroads(canBuild)
|
||||
@@ -987,12 +991,13 @@ export class PlayerImpl implements Player {
|
||||
unitType: UnitType,
|
||||
targetTile: TileRef,
|
||||
validTiles: TileRef[] | null = null,
|
||||
knownCost: Gold | null = null,
|
||||
): TileRef | false {
|
||||
if (this.mg.config().isUnitDisabled(unitType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const cost = this.mg.unitInfo(unitType).cost(this.mg, this);
|
||||
const cost = knownCost ?? this.mg.unitInfo(unitType).cost(this.mg, this);
|
||||
if (
|
||||
unitType !== UnitType.MIRVWarhead &&
|
||||
(!this.isAlive() || this.gold() < cost)
|
||||
@@ -1054,7 +1059,7 @@ export class PlayerImpl implements Player {
|
||||
const wouldHitTeammate = this.mg.anyUnitNearby(
|
||||
tile,
|
||||
magnitude.outer,
|
||||
StructureTypes,
|
||||
this.mg.getStructureTypes(),
|
||||
(unit) => unit.owner().isPlayer() && this.isOnSameTeam(unit.owner()),
|
||||
);
|
||||
if (wouldHitTeammate) {
|
||||
@@ -1133,14 +1138,11 @@ export class PlayerImpl implements Player {
|
||||
}
|
||||
const searchRadius = 15;
|
||||
const searchRadiusSquared = searchRadius ** 2;
|
||||
const types = Object.values(UnitType).filter((unitTypeValue) => {
|
||||
return this.mg.config().unitInfo(unitTypeValue).territoryBound;
|
||||
});
|
||||
|
||||
const nearbyUnits = this.mg.nearbyUnits(
|
||||
tile,
|
||||
searchRadius * 2,
|
||||
types,
|
||||
this.mg.getStructureTypes(),
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user