create alliance request flow

This commit is contained in:
evanpelle
2024-09-17 19:43:45 -07:00
parent 149ffaa026
commit 44877b8e59
8 changed files with 141 additions and 13 deletions
+11
View File
@@ -10,6 +10,7 @@ import {TerrainMap} from "../core/TerrainMapLoader";
import {and, bfs, dist, manhattanDist} from "../core/Util";
import {TerrainLayer} from "./graphics/layers/TerrainLayer";
import {WinCheckExecution} from "../core/execution/WinCheckExecution";
import {SendAllianceRequestEvent} from "./graphics/layers/UILayer";
@@ -121,6 +122,7 @@ export class ClientGame {
this.eventBus.on(PlayerEvent, (e) => this.playerEvent(e))
this.eventBus.on(MouseUpEvent, (e) => this.inputEvent(e))
this.eventBus.on(SendAllianceRequestEvent, (e) => this.onSendAllianceRequest(e))
this.renderer.initialize()
this.input.initialize()
@@ -269,6 +271,15 @@ export class ClientGame {
}
}
private onSendAllianceRequest(event: SendAllianceRequestEvent) {
this.sendIntent({
type: "allianceRequest",
clientID: this.id,
requestor: event.requestor.id(),
recipient: event.recipient.id(),
})
}
private sendSpawnIntent(cell: Cell) {
this.sendIntent({
type: "spawn",
+21 -4
View File
@@ -1,7 +1,7 @@
import {Theme} from "../../../core/configuration/Config";
import {EventBus} from "../../../core/EventBus";
import {GameEnv, Theme} from "../../../core/configuration/Config";
import {EventBus, GameEvent} from "../../../core/EventBus";
import {WinEvent} from "../../../core/execution/WinCheckExecution";
import {Game, Player} from "../../../core/Game";
import {AllianceRequest, Game, Player} from "../../../core/Game";
import {ClientID} from "../../../core/Schemas";
import {renderTroops} from "../Utils";
import winModalHtml from '../WinModal.html';
@@ -9,6 +9,12 @@ import {RightClickEvent} from "../../InputHandler";
import {Layer} from "./Layer";
import {TransformHandler} from "../TransformHandler";
export class SendAllianceRequestEvent implements GameEvent {
constructor(
public readonly requestor: Player,
public readonly recipient: Player
) { }
}
interface MenuOption {
label: string;
@@ -228,6 +234,13 @@ export class UILayer implements Layer {
if (owner.clientID() == this.clientID) {
return
}
// TODO: check if already allied with
const myPlayer = this.game.players().find(p => p.clientID() == this.clientID)
if (!myPlayer) {
console.warn('my player not found')
return
}
this.customMenu!.style.display = 'block';
this.customMenu!.style.left = `${e.x}px`;
@@ -235,7 +248,11 @@ export class UILayer implements Layer {
this.populateMenu([
{
label: "Request Alliance",
action: (): void => { },
action: (): void => {
this.eventBus.emit(
new SendAllianceRequestEvent(myPlayer, owner)
)
},
}
])
}
+20 -2
View File
@@ -46,6 +46,24 @@ export interface Execution extends ExecutionView {
owner(): MutablePlayer
}
export interface AllianceRequest {
requestor(): Player
recipient(): Player
}
export interface MutableAllianceRequest extends AllianceRequest {
accept(): void
reject(): void
}
export class Alliance {
constructor(
public readonly requestor: Player,
public readonly recepient: Player
) { }
}
export class PlayerInfo {
constructor(
public readonly name: string,
@@ -159,10 +177,10 @@ export interface MutableGame extends Game {
addPlayer(playerInfo: PlayerInfo, troops: number): MutablePlayer
executions(): Execution[]
removeInactiveExecutions(): void
removeExecution(exec: Execution)
removeExecution(exec: Execution): void
allianceRequest(requestor: Player, recipient: Player): MutableAllianceRequest
}
export class TileEvent implements GameEvent {
constructor(public readonly tile: Tile) { }
}
+39 -1
View File
@@ -1,7 +1,7 @@
import {info} from "console";
import {Config} from "./configuration/Config";
import {EventBus} from "./EventBus";
import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Boat, MutableBoat, BoatEvent, TerrainType, PlayerType} from "./Game";
import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Boat, MutableBoat, BoatEvent, TerrainType, PlayerType, MutableAllianceRequest} from "./Game";
import {ClientID} from "./Schemas";
import {Terrain, TerrainMap} from "./TerrainMapLoader";
import {simpleHash} from "./Util";
@@ -115,6 +115,27 @@ class TileImpl implements Tile {
}
}
export class AllianceRequestImpl implements MutableAllianceRequest {
constructor(private requestor_, private recipient_, private game: GameImpl) { }
requestor(): Player {
return this.requestor_
}
recipient(): Player {
return this.recipient_
}
accept(): void {
throw new Error("Method not implemented.");
}
reject(): void {
throw new Error("Method not implemented.");
}
}
export class BoatImpl implements MutableBoat {
private _active = true
@@ -297,6 +318,8 @@ export class GameImpl implements MutableGame {
private _numLandTiles: number
_terraNullius: TerraNulliusImpl
private allianceRequests: AllianceRequestImpl[] = []
constructor(terrainMap: TerrainMap, private eventBus: EventBus, private _config: Config) {
this._terraNullius = new TerraNulliusImpl(this)
this._width = terrainMap.width();
@@ -311,6 +334,21 @@ export class GameImpl implements MutableGame {
}
}
}
allianceRequest(requestor: Player, recipient: Player): MutableAllianceRequest {
const ar = new AllianceRequestImpl(requestor, recipient, this)
this.allianceRequests.push(ar)
return ar
}
acceptAllianceRequest() {
}
rejectAllianceRequest() {
}
numLandTiles(): number {
return this._numLandTiles
}
+9 -3
View File
@@ -4,13 +4,13 @@ import {PlayerType} from './Game';
export type GameID = string
export type ClientID = string
export type Intent = SpawnIntent | AttackIntent | BoatAttackIntent | UpdateNameIntent
export type Intent = SpawnIntent | AttackIntent | BoatAttackIntent | UpdateNameIntent | AllianceRequestIntent
export type AttackIntent = z.infer<typeof AttackIntentSchema>
export type SpawnIntent = z.infer<typeof SpawnIntentSchema>
export type BoatAttackIntent = z.infer<typeof BoatAttackIntentSchema>
export type UpdateNameIntent = z.infer<typeof UpdateNameIntentSchema>
export type AllianceRequestIntent = z.infer<typeof AllianceRequestIntentSchema>
export type Turn = z.infer<typeof TurnSchema>
@@ -76,7 +76,13 @@ export const UpdateNameIntentSchema = BaseIntentSchema.extend({
name: z.string(),
})
const IntentSchema = z.union([AttackIntentSchema, SpawnIntentSchema, BoatAttackIntentSchema, UpdateNameIntentSchema]);
export const AllianceRequestIntentSchema = BaseIntentSchema.extend({
type: z.literal('allianceRequest'),
requestor: z.string(),
recipient: z.string(),
})
const IntentSchema = z.union([AttackIntentSchema, SpawnIntentSchema, BoatAttackIntentSchema, UpdateNameIntentSchema, AllianceRequestIntentSchema]);
const TurnSchema = z.object({
turnNumber: z.number(),
+2 -2
View File
@@ -19,12 +19,12 @@ export const devConfig = new class extends DefaultConfig {
}
numBots(): number {
return 0
return 400
}
numFakeHumans(gameID: GameID): number {
return 0
return 10
}
// startTroops(playerInfo: PlayerInfo): number {
@@ -0,0 +1,35 @@
import {AllianceRequest, Execution, MutableGame, MutablePlayer, Player, PlayerID} from "../Game";
export class AllianceRequestExecution implements Execution {
private active = true
private mg: MutableGame = null
private requestor: Player;
private recipient: Player
constructor(private requestorID: PlayerID, private recipientID: PlayerID) { }
init(mg: MutableGame, ticks: number): void {
this.mg = mg
this.requestor = mg.player(this.requestorID)
this.recipient = mg.player(this.recipientID)
}
tick(ticks: number): void {
alert('recied request')
this.active = false
}
owner(): MutablePlayer {
return null
}
isActive(): boolean {
return this.active
}
activeDuringSpawnPhase(): boolean {
return false
}
}
+4 -1
View File
@@ -1,4 +1,4 @@
import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerInfo, TerraNullius, Tile, PlayerType} from "../Game";
import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerInfo, TerraNullius, Tile, PlayerType, Alliance} from "../Game";
import {AttackIntent, BoatAttackIntentSchema, GameID, Intent, Turn} from "../Schemas";
import {AttackExecution} from "./AttackExecution";
import {SpawnExecution} from "./SpawnExecution";
@@ -9,6 +9,7 @@ import {UpdateNameExecution} from "./UpdateNameExecution";
import {FakeHumanExecution} from "./FakeHumanExecution";
import Usernames from '../../../resources/Usernames.txt'
import {simpleHash} from "../Util";
import {AllianceRequestExecution} from "./AllianceRequestExecution";
@@ -55,6 +56,8 @@ export class Executor {
intent.name,
intent.clientID
)
} else if (intent.type == "allianceRequest") {
return new AllianceRequestExecution(intent.requestor, intent.recipient)
} else {
throw new Error(`intent type ${intent} not found`)
}