diff --git a/TODO.txt b/TODO.txt
index d76f7148b..f4f3806cd 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -242,6 +242,10 @@
* better error logging in server DONE 12/16/2024
* store and archive player cookies DONE 12/17/2024
* make ips less precise for user safety DONE 12/17/2024
+* send client logs back to server DONE 12/18/2024
+* render more info in info overlay
+* right click brings up player info menu
+* create new view for enemies & personal units
* send client logs back to server DONE 12/17/2024
* make info panel merge with X, display more info
* right click brings up player info menu
diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts
index 2226b3a19..a35459948 100644
--- a/src/client/graphics/GameRenderer.ts
+++ b/src/client/graphics/GameRenderer.ts
@@ -68,6 +68,7 @@ export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus:
playerInfo.eventBus = eventBus
playerInfo.clientID = clientID
playerInfo.transform = transformHandler
+ playerInfo.game = game
const layers: Layer[] = [
diff --git a/src/client/graphics/layers/PlayerInfoOverlay.ts b/src/client/graphics/layers/PlayerInfoOverlay.ts
index 4eac09d54..5cdb26699 100644
--- a/src/client/graphics/layers/PlayerInfoOverlay.ts
+++ b/src/client/graphics/layers/PlayerInfoOverlay.ts
@@ -6,51 +6,64 @@ import { ClientID } from '../../../core/Schemas';
import { EventBus } from '../../../core/EventBus';
import { TransformHandler } from '../TransformHandler';
import { MouseMoveEvent } from '../../InputHandler';
-import { dist, distSortUnit, euclideanDist, manhattanDist } from '../../../core/Util';
+import { euclideanDist, distSortUnit } from '../../../core/Util';
+import { renderNumber, renderTroops } from '../../Utils';
@customElement('player-info-overlay')
export class PlayerInfoOverlay extends LitElement implements Layer {
- private game: Game;
- public clientID: ClientID;
- public eventBus: EventBus;
- public transform: TransformHandler;
+ @property({ type: Object })
+ public game!: Game;
+
+ @property({ type: String })
+ public clientID!: ClientID;
+
+ @property({ type: Object })
+ public eventBus!: EventBus;
+
+ @property({ type: Object })
+ public transform!: TransformHandler;
@state()
- private selectedType: "player" | "unit" | null = null
+ private player: Player | null = null;
@state()
- private player: Player
-
- @state()
- private unit: Unit
+ private unit: Unit | null = null;
@state()
private _isVisible: boolean = false;
init(game: Game) {
this.game = game;
- this.eventBus.on(MouseMoveEvent, e => this.onMouseEvent(e));
+ this.eventBus.on(MouseMoveEvent, (e: MouseMoveEvent) => this.onMouseEvent(e));
}
private onMouseEvent(event: MouseMoveEvent) {
- this._isVisible = false;
+ this.setVisible(false);
+ this.unit = null;
+ this.player = null;
+
const worldCoord = this.transform.screenToWorldCoordinates(event.x, event.y);
if (!this.game.isOnMap(worldCoord)) {
return;
+ return;
}
+
const tile = this.game.tile(worldCoord);
- let owner = tile.owner();
- if (!owner.isPlayer()) {
- if (tile.isLand()) {
- return;
+ const owner = tile.owner();
+
+ if (owner.isPlayer()) {
+ this.player = owner;
+ this.setVisible(true);
+ } else if (!tile.isLand()) {
+ const units = this.game.units()
+ .filter(u => euclideanDist(worldCoord, u.tile().cell()) < 50)
+ .sort(distSortUnit(tile));
+
+ if (units.length > 0) {
+ this.unit = units[0];
+ this.setVisible(true);
}
- const units = this.game.units().filter(u => euclideanDist(worldCoord, u.tile().cell()) < 50).sort(distSortUnit(tile));
- if (units.length == 0) {
- return;
- }
- owner = units[0].owner();
}
- this._isVisible = true;
}
private onExitButtonClick() {
@@ -58,11 +71,14 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
}
tick() {
- this.unit = this.unit
+ if (this.game.ticks() % 10 == 0) {
+ this.requestUpdate()
+ }
+ // Implementation for Layer interface
}
renderLayer(context: CanvasRenderingContext2D) {
- // Render any necessary canvas elements
+ // Implementation for Layer interface
}
shouldTransform(): boolean {
@@ -74,47 +90,70 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
this.requestUpdate();
}
+ private myPlayer(): Player | null {
+ if (!this.game) {
+ return null;
+ }
+ return this.game.playerByClientID(this.clientID);
+ }
+
+ private renderPlayerInfo(player: Player) {
+ const isAlly = (this.myPlayer()?.isAlliedWith(player) || player == this.myPlayer()) ?? false;
+ return html`
+
+
${player.name()}
+
Troops: ${renderTroops(player.troops())}
+
Gold: ${renderNumber(player.gold())}
+
+ `;
+ }
+
+ private renderUnitInfo(unit: Unit) {
+ const isAlly = (unit.owner() == this.myPlayer() || this.myPlayer()?.isAlliedWith(unit.owner())) ?? false;
+ return html`
+
+
${unit.owner().name()}
+
+
+ `
+ }
+
+ render() {
+ return html`
+
+
+
+
+
+ ${this.player != null ? this.renderPlayerInfo(this.player) : ''}
+ ${this.unit != null ? this.renderUnitInfo(this.unit) : ''}
+
+
+ `;
+ }
+
static styles = css`
:host {
display: block;
}
- .overlay-container {
+
+ .container {
position: fixed;
top: 10px;
right: 10px;
z-index: 9999;
display: flex;
flex-direction: column;
- align-items: flex-end;
}
+
.controls {
- position: relative;
- display: flex;
- justify-content: flex-end;
- width: 40px; /* Same as button width */
- margin-bottom: 10px;
- }
- .exit-button {
- width: 40px;
- height: 40px;
- font-size: 20px;
- font-weight: bold;
- background-color: rgba(255, 0, 0, 0.4);
- color: white;
- border: none;
- border-radius: 50%;
- cursor: pointer;
- display: flex;
- justify-content: center;
- align-items: center;
- transition: background-color 0.3s;
- }
- .exit-button:hover {
- background-color: rgba(255, 0, 0, 0.5);
- }
- .exit-button:active {
- background-color: rgba(255, 0, 0, 0.6);
+ align-self: flex-end;
+ margin-bottom: 4px;
+ z-index: 2;
}
+
.player-info {
background-color: rgba(30, 30, 30, 0.7);
padding: 8px 12px;
@@ -123,84 +162,85 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
backdrop-filter: blur(5px);
transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out;
color: white;
+ font-size: 18px;
min-width: 120px;
text-align: left;
- font-size: 18px;
}
.hidden {
opacity: 0;
visibility: hidden;
- display: none;
+ pointer-events: none;
+ }
+
+ .info-content {
+ margin-top: 8px;
}
.player-name {
font-weight: bold;
margin-bottom: 4px;
}
+
.player-name.ally {
color: #4CAF50;
}
+
+ .type-label {
+ font-size: 14px;
+ opacity: 0.8;
+ }
+
+ .unit-details {
+ margin-top: 4px;
+ }
+
+ .health-bar {
+ height: 4px;
+ background-color: rgba(255, 255, 255, 0.2);
+ border-radius: 2px;
+ margin-top: 4px;
+ }
+
+ .health-fill {
+ height: 100%;
+ background-color: #4CAF50;
+ border-radius: 2px;
+ transition: width 0.2s ease-out;
+ }
+
+ .exit-button {
+ background: none;
+ border: none;
+ color: white;
+ font-size: 40px;
+ cursor: pointer;
+ padding: 4px;
+ opacity: 0.7;
+ transition: opacity 0.2s;
+ }
+
+ .exit-button:hover {
+ opacity: 1;
+ }
+
@media (max-width: 768px) {
- .overlay-container {
+ .container {
top: 5px;
right: 5px;
}
- .controls {
- width: 30px;
- }
+
.player-info {
padding: 6px 10px;
font-size: 12px;
min-width: 100px;
}
+
.exit-button {
- width: 30px;
- height: 30px;
- font-size: 16px;
- .exit-button {
- width: 30px;
- height: 30px;
font-size: 16px;
}
+
+ .type-label {
+ font-size: 12px;
+ }
}
`;
-
- private renderPlayerInfo(player: Player) {
- return html`
-
-
${player.name}
-
Player Territory
-
- `;
- }
-
- private renderUnitInfo(unit: Unit) {
- return html`
-
- `;
- }
-
- render() {
- return html`
-
-
-
-
-
- ${this._infoType === 'player' && this._playerInfo
- ? this.renderPlayerInfo(this._playerInfo)
- : this._infoType === 'unit' && this._unitInfo
- ? this.renderUnitInfo(this._unitInfo)
- : nothing}
-
-
- `;
- }
}
\ No newline at end of file
diff --git a/src/client/graphics/layers/UILayer.ts b/src/client/graphics/layers/UILayer.ts
index 601a2db27..8912a76de 100644
--- a/src/client/graphics/layers/UILayer.ts
+++ b/src/client/graphics/layers/UILayer.ts
@@ -1,13 +1,9 @@
-import { GameEnv, Theme } from "../../../core/configuration/Config";
import { EventBus } from "../../../core/EventBus";
import { WinEvent } from "../../../core/execution/WinCheckExecution";
import { AllianceRequest, AllianceRequestReplyEvent, Game, Player } from "../../../core/game/Game";
import { ClientID } from "../../../core/Schemas";
-import { ContextMenuEvent } from "../../InputHandler";
import { Layer } from "./Layer";
import { TransformHandler } from "../TransformHandler";
-import { MessageType } from "./EventsDisplay";
-import { SendBreakAllianceIntentEvent } from "../../Transport";
import { consolex } from "../../../core/Consolex";
interface MenuOption {
@@ -151,6 +147,7 @@ export class UILayer implements Layer {
button.onmouseout = () => button.style.backgroundColor = '#4A90E2';
}
+
onWinEvent(event: WinEvent) {
consolex.log(`${event.winner.name()} won the game!!}`)
this.showWinModal(event.winner)
diff --git a/src/core/configuration/DevConfig.ts b/src/core/configuration/DevConfig.ts
index c51099402..9b472ef3b 100644
--- a/src/core/configuration/DevConfig.ts
+++ b/src/core/configuration/DevConfig.ts
@@ -8,7 +8,7 @@ export const devConfig = new class extends DefaultConfig {
unitInfo(type: UnitType): UnitInfo {
const info = super.unitInfo(type)
const oldCost = info.cost
- info.cost = (p: Player) => oldCost(p) / 20
+ info.cost = (p: Player) => oldCost(p) / 10000
return info
}