thread_split: get units working

This commit is contained in:
Evan
2025-01-07 20:59:27 -08:00
parent fa02c7d6b5
commit 7d04d25e6f
9 changed files with 63 additions and 41 deletions
+14 -18
View File
@@ -24,6 +24,8 @@ export class StructureLayer implements Layer {
private unitImages: Map<string, HTMLImageElement> = new Map();
private theme: Theme = null;
private seenUnits = new Set<Unit>()
// Configuration for supported unit types only
private readonly unitConfigs: Partial<Record<UnitType, UnitRenderConfig>> = {
[UnitType.Port]: {
@@ -68,10 +70,10 @@ export class StructureLayer implements Layer {
}
tick() {
this.game.units().forEach(u => this.handleUnitRendering(new UnitEvent(u, u.tile())))
}
init() {
this.eventBus.on(UnitEvent, e => this.onUnitEvent(e));
this.redraw()
}
@@ -102,6 +104,15 @@ export class StructureLayer implements Layer {
const unitType = event.unit.type();
if (!this.isUnitTypeSupported(unitType)) return;
if (event.unit.isActive() && this.seenUnits.has(event.unit)) {
// Already rendered, so don't do anything.
return
}
if (!event.unit.isActive() && !this.seenUnits.has(event.unit)) {
// Has been deleted and render is cleared so don't do anything.
return
}
const config = this.unitConfigs[unitType];
const unitImage = this.unitImages.get(unitType);
@@ -112,8 +123,10 @@ export class StructureLayer implements Layer {
.forEach(t => this.clearCell(t.cell()));
if (!event.unit.isActive()) {
this.seenUnits.delete(event.unit)
return;
}
this.seenUnits.add(event.unit)
// Create temporary canvas for icon processing
const tempCanvas = document.createElement('canvas');
@@ -170,23 +183,6 @@ export class StructureLayer implements Layer {
}
}
onUnitEvent(event: UnitEvent) {
this.handleUnitRendering(event);
if (event.unit.type() == UnitType.DefensePost) {
if (!event.unit.isActive()) {
return
}
// Array.from(
// bfs(
// event.unit.tile(),
// dist(event.unit.tile(), this.game.config().defensePostRange())
// )
// ).filter(t => t.isBorder() && t.owner() == event.unit.owner()).forEach(t => {
// this.paintCell(t.cell(), colord({ r: 255, g: 255, b: 255 }), 255)
// })
}
}
paintCell(cell: Cell, color: Colord, alpha: number) {
this.clearCell(cell)
this.context.fillStyle = color.alpha(alpha / 255).toRgbString();
+3
View File
@@ -42,6 +42,9 @@ export class UnitLayer implements Layer {
if (this.myPlayer == null) {
this.myPlayer = this.game.playerByClientID(this.clientID)
}
for (const unit of this.game.units()) {
this.onUnitEvent(new UnitEvent(unit, unit.tile()))
}
}
init() {
@@ -274,7 +274,7 @@ export class RadialMenu implements Layer {
this.activateMenuElement(Slot.Boat, "#3f6ab1", boatIcon, () => {
this.eventBus.emit(
new SendBoatAttackIntentEvent(
myPlayer.id(),
tile.owner().id(),
this.clickedCell,
this.uiState.attackRatio * myPlayer.troops()
)
-2
View File
@@ -86,8 +86,6 @@ export class GameRunner {
packedTileUpdates: Array.from(this.updatedTiles).map(t => packTileData(t.toViewData())),
players: playerViewData
})
this.isExecuting = false
}
+26 -9
View File
@@ -64,6 +64,7 @@ export class TileView {
}
export interface UnitViewData extends ViewData<UnitView> {
id: number,
type: UnitType,
troops: number,
x: number,
@@ -73,23 +74,31 @@ export interface UnitViewData extends ViewData<UnitView> {
health?: number
}
export class UnitView {
constructor(private data: UnitViewData) { }
export class UnitView implements Unit {
constructor(private gameView: GameView, private data: UnitViewData) { }
update(data: UnitViewData) {
this.data = data
}
id(): number {
return this.data.id
}
type(): UnitType {
throw new Error("Method not implemented.");
return this.data.type
}
troops(): number {
throw new Error("Method not implemented.");
return this.data.troops
}
tile(): TileView {
throw new Error("Method not implemented.");
tile(): Tile {
return this.gameView.tile(new Cell(this.data.x, this.data.y))
}
owner(): PlayerView {
throw new Error("Method not implemented.");
return this.gameView.player(this.data.owner)
}
isActive(): boolean {
throw new Error("Method not implemented.");
return this.data.isActive
}
hasHealth(): boolean {
return this.data.health != undefined
@@ -276,6 +285,7 @@ export class GameView {
private tiles: TileView[][] = []
private smallIDToID = new Map<number, PlayerID>()
private _players = new Map<PlayerID, PlayerView>()
private _units = new Map<number, UnitView>()
constructor(public worker: WorkerClient, private _config: Config, private _terrainMap: TerrainMap) {
// Initialize the 2D array
@@ -310,6 +320,13 @@ export class GameView {
this._players.set(key, new PlayerView(this, value))
}
});
gu.units.forEach(unit => {
if (this._units.has(unit.id)) {
this._units.get(unit.id).update(unit)
} else {
this._units.set(unit.id, new UnitView(this, unit))
}
})
}
recentlyUpdatedTiles(): TileView[] {
@@ -377,7 +394,7 @@ export class GameView {
return this._config
}
units(...types: UnitType[]): Unit[] {
return []
return Array.from(this._units.values())
}
unitInfo(type: UnitType): UnitInfo {
return this._config.unitInfo(type)
+6 -6
View File
@@ -23,12 +23,12 @@ export class DevConfig extends DefaultConfig {
// return 100
}
// unitInfo(type: UnitType): UnitInfo {
// const info = super.unitInfo(type)
// const oldCost = info.cost
// info.cost = (p: Player) => oldCost(p) / 10000
// return info
// }
unitInfo(type: UnitType): UnitInfo {
const info = super.unitInfo(type)
const oldCost = info.cost
info.cost = (p: Player) => oldCost(p) / 10000
return info
}
// tradeShipSpawnRate(): number {
// return 10
+10 -3
View File
@@ -40,7 +40,8 @@ export class GameImpl implements MutableGame {
allianceRequests: AllianceRequestImpl[] = []
alliances_: AllianceImpl[] = []
private nextID = 1
private nextPlayerID = 1
private _nextUnitID = 1
constructor(
@@ -68,6 +69,12 @@ export class GameImpl implements MutableGame {
))
}
nextUnitID(): number {
const old = this._nextUnitID
this._nextUnitID++
return old
}
addFallout(tile: Tile) {
const ti = tile as TileImpl
if (tile.hasOwner()) {
@@ -247,8 +254,8 @@ export class GameImpl implements MutableGame {
}
addPlayer(playerInfo: PlayerInfo, manpower: number): MutablePlayer {
let player = new PlayerImpl(this, this.nextID, playerInfo, manpower)
this.nextID++
let player = new PlayerImpl(this, this.nextPlayerID, playerInfo, manpower)
this.nextPlayerID++
this._players.set(playerInfo.id, player)
return player
}
+1 -1
View File
@@ -424,7 +424,7 @@ export class PlayerImpl implements MutablePlayer {
buildUnit(type: UnitType, troops: number, spawnTile: Tile): UnitImpl {
const cost = this.gs.unitInfo(type).cost(this)
const b = new UnitImpl(type, this.gs, spawnTile, troops, this);
const b = new UnitImpl(type, this.gs, spawnTile, troops, this.gs.nextUnitID(), this);
this._units.push(b);
this.removeGold(cost)
this.removeTroops(troops)
+2 -1
View File
@@ -4,7 +4,6 @@ import { simpleHash, within } from "../Util";
import { MutableUnit, Tile, TerraNullius, UnitType, Player, UnitInfo } from "./Game";
import { GameImpl } from "./GameImpl";
import { PlayerImpl } from "./PlayerImpl";
import { TerraNulliusImpl } from "./TerraNulliusImpl";
export class UnitImpl implements MutableUnit {
@@ -16,6 +15,7 @@ export class UnitImpl implements MutableUnit {
private g: GameImpl,
private _tile: Tile,
private _troops: number,
private _id: number,
public _owner: PlayerImpl,
) {
// default to half health (or 1 is no health specified)
@@ -24,6 +24,7 @@ export class UnitImpl implements MutableUnit {
toViewData(): UnitViewData {
return {
id: this._id,
type: this._type,
troops: this._troops,
x: this.tile().cell().x,