Skip to content

refactor: unify world configuration in shared package#71

Merged
ComBba merged 6 commits intomainfrom
refactor/unified-world-config
Feb 12, 2026
Merged

refactor: unify world configuration in shared package#71
ComBba merged 6 commits intomainfrom
refactor/unified-world-config

Conversation

@ComBba
Copy link
Copy Markdown
Contributor

@ComBba ComBba commented Feb 12, 2026

Summary

  • Centralize world configuration (zone bounds, spawn point, map config) in @openclawworld/shared
  • Fix server/client map mismatch that caused collision to not work for human players
  • Add F3 debug overlay enhancement showing zones, collision tiles, spawn point
  • Add map synchronization mechanism to ensure consistency

Problem

Server was using an outdated village.json (64x52, 277 blocked tiles) while client had the correct map (64x64, 546 blocked tiles). This caused:

  • Human players could walk through walls
  • Zone boundaries were inconsistent
  • Spawn point was misconfigured

Solution

1. Unified World Constants (packages/shared/src/world.ts)

  • ZONE_BOUNDS: Zone boundary definitions
  • DEFAULT_SPAWN_POINT: Spawn location (1024, 1024)
  • MAP_CONFIG: Map dimensions (64x64 tiles, 2048x2048 pixels)
  • ZONE_COLORS, DEBUG_COLORS: UI color palettes
  • ZONE_IDS: List of all zone identifiers

2. Server Integration

  • ZoneSystem: Uses getZoneBoundsMap() from shared
  • GameRoom: Uses DEFAULT_SPAWN_POINT from shared

3. Client Integration

  • GameScene: Uses shared constants for F3 debug overlay
  • Minimap: Uses shared constants for zone rendering

4. Map Synchronization

  • Added scripts/sync-maps.sh to sync world pack map to server/client
  • Integrated into build process (pnpm build runs sync first)

Commits

  1. feat(shared): Add unified world configuration constants
  2. refactor(server): Use shared world constants
  3. refactor(client): Use shared world constants
  4. build: Add map synchronization mechanism

Testing

  • pnpm typecheck passes
  • pnpm test passes (958 tests)
  • pnpm build succeeds
  • Map sync script works correctly
  • Manual testing: Human player collision (requires server restart)

F3 Debug Mode Enhancement

Press F3 in-game to see:

  • 🔴 Collision tiles (blocked)
  • 🟢 Spawn point
  • ⚪ Map boundary
  • 🟡 Current zone highlight
  • Zone boundaries with labels and colors

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 게임 내 디버그 시각화 기능 추가 (충돌 영역, 맵 경계, 스폰 지점, 존 정보 표시)
    • 존 진입/퇴출 시 배너 및 알림 추가
  • 개선사항

    • 마을 맵 완전 재설계 및 레이아웃 최적화
    • 맵 동기화 자동화 스크립트 추가
    • 맵 설정 및 존 정보 중앙화 관리

Previously, zone exit notification only fired when entering a new zone.
Now correctly handles three cases:
- Zone → Gap: Shows exit notification immediately
- Zone → Zone: Shows both exit and enter notifications
- Gap → Zone: Shows enter notification only
Add centralized world configuration in shared package:
- ZONE_BOUNDS: zone boundary definitions
- DEFAULT_SPAWN_POINT: spawn location (1024, 1024)
- MAP_CONFIG: map dimensions (64x64 tiles, 2048x2048 pixels)
- ZONE_COLORS: zone color palette for UI
- DEBUG_COLORS: debug overlay colors
- ZONE_IDS: list of all zone identifiers
- getZoneBoundsMap(): helper to get Map<ZoneId, ZoneBounds>
- ZoneSystem: import ZoneBounds and getZoneBoundsMap from shared
- GameRoom: import DEFAULT_SPAWN_POINT from shared
- Remove duplicated zone bounds definitions from server
- GameScene: import ZONE_BOUNDS, ZONE_COLORS, DEBUG_COLORS,
  DEFAULT_SPAWN_POINT from shared for debug overlay
- Minimap: import ZONE_BOUNDS, ZONE_COLORS, MAP_CONFIG, ZONE_IDS
  from shared for minimap rendering
- Remove duplicated zone definitions from client
- Enhanced F3 debug mode shows zones, collision, spawn point
- Add scripts/sync-maps.sh to sync world pack map to server/client
- Integrate sync-maps into build process (runs before pnpm -r build)
- Sync server village.json with world pack grid_town_outdoor.json
  to fix collision mismatch (was 64x52, now 64x64 with correct tiles)

This ensures server and client always use the same map data.
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@github-actions
Copy link
Copy Markdown

This PR is quite large. Consider breaking it into smaller PRs for easier review.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @ComBba, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the game's world configuration by centralizing critical constants such as map dimensions, zone boundaries, and spawn points into a shared package. This unification addresses a significant problem where server and client map data diverged, leading to gameplay inconsistencies like players walking through walls. The changes also introduce a robust map synchronization mechanism to prevent future discrepancies and enhance the developer experience with a more informative debug overlay, improving overall game stability and maintainability.

Highlights

  • Unified World Configuration: Centralized all world-related constants, including zone bounds, default spawn point, and map dimensions, into a new shared package (@openclawworld/shared) for consistent access across client and server.
  • Map Synchronization Mechanism: Implemented a new sync-maps.sh script and integrated it into the build process to ensure that the server and client always use the same village.json map file, resolving previous inconsistencies.
  • F3 Debug Overlay Enhancement: Significantly enhanced the client-side F3 debug overlay to visualize collision tiles, the spawn point, map boundaries, and zone boundaries with labels and colors, along with a detailed info panel.
  • Collision and Zone Consistency Fix: Resolved a critical bug where server and client map mismatches caused human players to walk through walls due to inconsistent collision data and misconfigured zone boundaries.
Changelog
  • package.json
    • Added a new sync-maps script to synchronize map files.
    • Integrated the sync-maps script into the build command to run automatically.
  • packages/client/src/game/scenes/GameScene.ts
    • Imported ZONE_BOUNDS, ZONE_COLORS, DEBUG_COLORS, and DEFAULT_SPAWN_POINT from the shared package.
    • Added new private properties for zoneDebug, debugInfoPanel, debugLegend, and debugZoneLabels to support enhanced debug visuals.
    • Refactored the toggleDebug method to clear and redraw all debug elements using new helper methods.
    • Implemented drawDebugMapBoundary to render the map's outer limits.
    • Implemented drawDebugZones to visualize zone boundaries, colors, and labels, highlighting the current player's zone.
    • Implemented drawDebugCollisionTiles to display collision areas with distinct styling.
    • Implemented drawDebugSpawnPoint to mark the default spawn location.
    • Implemented createDebugLegend to provide a key for the debug overlay elements.
    • Implemented createDebugInfoPanel to show real-time player and map information.
    • Updated checkZoneChange logic to handle zone entry/exit notifications more robustly, including cases where a player leaves all defined zones.
    • Added updateDebugInfoPanel to refresh the debug information display during game updates.
  • packages/client/src/ui/Minimap.ts
    • Imported ZONE_BOUNDS, ZONE_COLORS, MAP_CONFIG, and ZONE_IDS from the shared package.
    • Updated DEFAULT_CONFIG to use MAP_CONFIG.pixelWidth and MAP_CONFIG.pixelHeight for minimap dimensions.
    • Replaced hardcoded ZONE_COLORS object with EXTRA_COLORS for water and road, and used the shared ZONE_COLORS for actual zones.
    • Modified zone rendering logic to iterate through ZONE_IDS and use ZONE_BOUNDS for drawing zone rectangles, ensuring consistency with shared definitions.
  • packages/server/assets/maps/village.json
    • Updated map height from 52 to 64 to match the new standard map dimensions.
    • Adjusted nextobjectid and mapId property to grid_town.
    • Completely replaced the layer data to reflect the updated 64x64 map layout and collision information.
  • packages/server/src/rooms/GameRoom.ts
    • Imported DEFAULT_SPAWN_POINT from the shared package.
    • Initialized the spawnPoint property using the DEFAULT_SPAWN_POINT from the shared configuration.
  • packages/server/src/zone/ZoneSystem.ts
    • Imported ZoneBounds and getZoneBoundsMap from the shared package.
    • Removed the local ZoneBounds type definition, now importing it from shared.
    • Replaced the hardcoded DEFAULT_ZONE_BOUNDS map with a call to getZoneBoundsMap() from the shared package.
  • packages/shared/src/index.ts
    • Exported all members from the new world.js module.
  • packages/shared/src/world.ts
    • Added new file to define shared world configuration constants and types.
    • Defined ZoneBounds and SpawnPoint types.
    • Exported MAP_CONFIG with consistent map dimensions and tile size.
    • Exported ZONE_BOUNDS as a record of ZoneId to ZoneBounds.
    • Exported DEFAULT_SPAWN_POINT with its coordinates and tile position.
    • Exported ZONE_COLORS for consistent zone visualization.
    • Exported DEBUG_COLORS for various debug overlay elements.
    • Exported ZONE_IDS as a readonly array of all defined zone identifiers.
    • Exported getZoneBoundsMap function to provide a Map instance of zone bounds.
  • scripts/sync-maps.sh
    • Added new shell script to copy the canonical map file (grid_town_outdoor.json) from the world/packs/base/maps directory to both the server and client asset paths.
    • Included error handling for missing source map and provided success messages with MD5 checksums for verification.
Activity
  • The author reported that pnpm typecheck passes.
  • The author reported that pnpm test passes with 958 tests.
  • The author reported that pnpm build succeeds.
  • The author reported that the map sync script works correctly.
  • Manual testing for human player collision is pending.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 12, 2026

Warning

Rate limit exceeded

@ComBba has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 14 minutes and 7 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

🎯 개요

이 PR은 공유 월드 구성(맵 차원, 영역 경계, 스폰 지점)을 새로운 packages/shared/src/world.ts 모듈로 추출하고, 클라이언트 및 서버 코드를 이 새로운 상수들을 사용하도록 리팩토링합니다. 또한 GameScene에 광범위한 디버그 기능과 향상된 영역 진입/퇴출 처리를 추가하며, 빌드 프로세스에 맵 동기화 스크립트를 통합합니다.

변경사항

집단 / 파일(들) 요약
공유 월드 모듈
packages/shared/src/world.ts, packages/shared/src/index.ts
새로운 world.ts 모듈을 도입하여 ZoneBounds, SpawnPoint 타입 및 MAP_CONFIG, ZONE_BOUNDS, DEFAULT_SPAWN_POINT, ZONE_COLORS, DEBUG_COLORS, ZONE_IDS 상수를 정의합니다. 공유 패키지 인덱스에서 재내보내기를 추가합니다.
클라이언트 게임씬 및 디버그
packages/client/src/game/scenes/GameScene.ts
광범위한 디버그 인프라(drawDebugMapBoundary, drawDebugZones, drawDebugCollisionTiles, drawDebugSpawnPoint, createDebugLegend, createDebugInfoPanel)를 추가합니다. currentZone/previousZone 추적으로 영역 진입/퇴출 처리를 개선하고 매 프레임 디버그 패널을 갱신합니다.
클라이언트 미니맵
packages/client/src/ui/Minimap.ts
하드코딩된 맵 차원을 MAP_CONFIG에서 동적으로 가져오도록 교체하고, 영역 렌더링을 ZONE_IDS 및 ZONE_BOUNDS 반복으로 리팩토링합니다.
서버 게임룸 및 영역 시스템
packages/server/src/rooms/GameRoom.ts, packages/server/src/zone/ZoneSystem.ts
GameRoom의 spawnPoint 초기화를 DEFAULT_SPAWN_POINT로 변경하고, ZoneSystem의 DEFAULT_ZONE_BOUNDS 초기화를 getZoneBoundsMap() 호출로 변경합니다. ZoneEvent에 zone.exit 변형을 추가합니다.
서버 맵 자산
packages/server/assets/maps/village.json
높이를 52에서 64로 변경하고, mapId를 "village"에서 "grid_town"으로 변경하며, 객체들을 시설 유형으로 광범위하게 재구성합니다(notice_board, office_terminal, whiteboard 등). 타일셋 섹션을 재배치합니다.
빌드 및 스크립트 자동화
package.json, scripts/sync-maps.sh
빌드 전 맵 동기화를 실행하도록 build 스크립트를 수정하고, 새로운 sync-maps.sh 스크립트를 추가하여 원본 맵을 서버/클라이언트 위치로 복사합니다.

예상 코드 리뷰 노력

🎯 4 (복합) | ⏱️ ~45분

연관될 수 있는 PR

제안 레이블

client, server, shared, world, tests, size/XL

🐰 세계 상수를 정렬하니 반짝반짝해졌네
공유 모듈에서 모두 함께 춤을 춘답니다
영역 경계와 스폰 지점, 맵 동기화까지
디버그 패널이 반짝이는 밤하늘처럼 빛나고
더 나은 게임 세상이 펼쳐져요! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main objective: centralizing world configuration into a shared package, which is reflected across multiple file changes (new world.ts module, refactored zone/spawn constants in GameScene, Minimap, ZoneSystem, and GameRoom).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/unified-world-config

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/client/src/game/scenes/GameScene.ts (1)

967-1001: ⚠️ Potential issue | 🟡 Minor

currentZone(null)과 previousZone(undefined) 간 null/undefined 혼용.

Line 968에서 currentZone?? null로 인해 ZoneId | null 타입이고, previousZone(line 61)은 ZoneId | undefined 타입입니다. Line 1001에서 this.previousZone = currentZonenullundefined 필드에 할당합니다.

또한 line 970에서 currentZone === this.previousZone 비교 시, 초기 상태에서 null !== undefined이므로 첫 프레임에서 불필요하게 change 로직에 진입합니다 (실질적 부작용은 없지만 비일관적).

null/undefined 중 하나로 통일하는 것을 권장합니다:

♻️ 제안된 변경
  private checkZoneChange(entity: Entity): void {
-   const currentZone = (entity as unknown as { currentZone?: ZoneId }).currentZone ?? null;
-
-   if (currentZone === this.previousZone) return;
-
-   if (this.previousZone && !currentZone) {
+   const currentZone = (entity as unknown as { currentZone?: ZoneId }).currentZone;
+
+   if (currentZone === this.previousZone) return;
+
+   if (this.previousZone && !currentZone) {

이렇게 하면 둘 다 ZoneId | undefined로 일관되게 됩니다.

🤖 Fix all issues with AI agents
In `@package.json`:
- Around line 16-17: The package.json "sync-maps" script calls a Bash-only
script ("bash scripts/sync-maps.sh"), which breaks on Windows; rewrite the shell
script as a cross-platform Node.js script (e.g., scripts/sync-maps.js) that
performs the same sync steps and errors with non-zero exit codes, then update
the "sync-maps" entry to run that Node script (and keep the "build" script
chaining to "pnpm run sync-maps && pnpm -r build"); reference the existing
"sync-maps" script name and the "build" script so you replace the Bash
dependency with a Node implementation that works on Windows, macOS, and Linux.

In `@packages/client/src/game/scenes/GameScene.ts`:
- Around line 625-638: Add a proper private class field instead of using a
type-unsafe cast: declare private _debugBlockedCount = 0; on the GameScene
class, then replace the hacky assignment `(this as unknown as {
_debugBlockedCount: number })._debugBlockedCount = blockedCount;` with
`this._debugBlockedCount = blockedCount;` so references to _debugBlockedCount
use the real private field rather than an unsafe cast.
- Around line 1187-1192: The updateDebugInfoPanel method is destroying and
recreating the entire debug panel every frame causing GC and allocation churn;
change it to create the panel once and only update text values: ensure
createDebugInfoPanel() constructs the Container/Graphics/Text objects and stores
references (e.g., this.debugInfoPanel, this.debugTextFields or similar) as
fields, call createDebugInfoPanel() only when debug is first enabled (or when
debugInfoPanel is null), and modify updateDebugInfoPanel() to simply call a new
refreshDebugInfoText() that updates existing Text objects via setText() instead
of destroying/creating the panel; keep references to individual Text nodes so
layout/redraw is minimal.

In `@packages/shared/src/world.ts`:
- Around line 3-8: The ZoneBounds type is duplicated; remove the local type in
WorldPackLoader.ts and import the shared definition instead. In
WorldPackLoader.ts add ZoneBounds to the existing import from the shared package
(so import { ZoneBounds } from 'packages/shared' or the existing shared module
import), then delete the local ZoneBounds type block (the lines currently
defining x, y, width, height). Ensure any references in functions/methods in
WorldPackLoader.ts continue to use ZoneBounds after the import.
🧹 Nitpick comments (7)
packages/shared/src/world.ts (2)

57-64: ZONE_IDSZONE_BOUNDS에서 파생하는 것을 고려하세요.

ZONE_IDS가 수동으로 관리되고 있어 ZoneId 타입이나 ZONE_BOUNDS 키와 불일치할 가능성이 있습니다. ZONE_BOUNDS에서 자동으로 파생하면 유지보수 부담을 줄일 수 있습니다.

♻️ 제안된 변경
-export const ZONE_IDS: readonly ZoneId[] = [
-  'plaza',
-  'north-block',
-  'west-block',
-  'east-block',
-  'south-block',
-  'lake',
-] as const;
+export const ZONE_IDS: readonly ZoneId[] = Object.keys(ZONE_BOUNDS) as ZoneId[];

66-68: getZoneBoundsMap()은 호출마다 새 Map을 생성합니다.

현재 사용 빈도가 낮아 문제가 되지 않지만, 핫 패스에서 반복 호출될 경우 불필요한 할당이 발생할 수 있습니다. 필요 시 모듈 레벨 캐싱을 고려하세요.

packages/client/src/ui/Minimap.ts (1)

83-119: 물/도로 영역의 hard-coded 타일 좌표가 남아있습니다.

zone 데이터는 shared 상수에서 가져오지만, 물(lines 83-93)과 도로(lines 95-119) 영역의 타일 좌표는 여전히 매직 넘버로 하드코딩되어 있습니다. 향후 맵 변경 시 함께 업데이트가 필요한 부분입니다. 이번 PR 범위를 넘어서지만 참고용으로 남깁니다.

packages/client/src/game/scenes/GameScene.ts (2)

558-558: Static analysis: forEach 콜백에서 불필요한 반환값.

label.destroy()의 반환값이 arrow function에 의해 암묵적으로 반환됩니다. 중괄호를 추가하여 의도를 명확히 하세요.

♻️ 제안된 변경
-   this.debugZoneLabels.forEach(label => label.destroy());
+   this.debugZoneLabels.forEach(label => { label.destroy(); });

583-586: Entity 타입에 currentZone을 반복적으로 unsafe cast하고 있습니다.

(entity as unknown as { currentZone?: ZoneId }).currentZone 패턴이 3곳(lines 584-586, 756-758, 968)에서 반복됩니다. Entity 타입에 currentZone 필드가 실제로 존재하지만 타입 정의에 누락된 것이라면, 타입을 확장하는 것이 근본적 해결책입니다. 그렇지 않다면 최소한 헬퍼 함수로 추출하여 cast를 한 곳에서만 관리하세요.

Also applies to: 755-758, 968-968

scripts/sync-maps.sh (2)

1-26: 대상 디렉토리 존재 여부 확인이 없습니다.

cp 전에 대상 디렉토리가 존재하지 않으면 실패합니다. 특히 fresh clone이나 CI 환경에서 발생할 수 있습니다. mkdir -p로 안전하게 보호하세요.

♻️ 제안된 변경
 echo "Syncing maps from world pack..."
+mkdir -p "$(dirname "$SERVER_MAP")"
+mkdir -p "$(dirname "$CLIENT_MAP")"
 cp "$SOURCE_MAP" "$SERVER_MAP"
 cp "$SOURCE_MAP" "$CLIENT_MAP"

7-9: 소스와 대상 파일명 불일치에 대한 문서화를 권장합니다.

소스 맵은 grid_town_outdoor.json이지만 대상은 village.json입니다. 이 의도적인 이름 차이에 대해 스크립트 내 주석으로 이유를 명시하면 향후 유지보수에 도움이 됩니다.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a significant refactoring that centralizes world configuration into a shared package, improving consistency between the client and server. It also includes a crucial map synchronization script to fix collision issues and enhances the F3 debug overlay. A security review found no vulnerabilities. However, there are areas for improvement regarding performance in the new debug panel, type safety, and script robustness.

Comment on lines +1187 to 1192
private updateDebugInfoPanel(): void {
if (!this.debugEnabled || !this.debugInfoPanel) return;

this.debugInfoPanel.destroy();
this.createDebugInfoPanel();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Calling destroy() and createDebugInfoPanel() on every frame within the update loop is highly inefficient. This will lead to performance issues and garbage collection stutter due to constant object creation and destruction.

A more performant approach is to create the panel and its text elements once, and then only update the text content each frame. I recommend the following refactor:

  1. Add a class property private debugInfoTexts: Phaser.GameObjects.Text[] = [];.
  2. In createDebugInfoPanel, create the text objects and push them to this.debugInfoTexts. This function should only be called once when the debug view is enabled (e.g., inside updateCollisionDebug).
  3. In updateDebugInfoPanel, you would then get the new data and update the .text property of each Phaser.GameObjects.Text object in this.debugInfoTexts.

}
});
});
(this as unknown as { _debugBlockedCount: number })._debugBlockedCount = blockedCount;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a type assertion (this as unknown as ...) to set _debugBlockedCount suggests that the property is missing from the class definition. This bypasses TypeScript's type safety and makes the code harder to maintain and reason about.

To fix this, please declare _debugBlockedCount as a private property at the top of the GameScene class:

private _debugBlockedCount = 0;

This will provide proper type-checking and improve code clarity.

private checkZoneChange(entity: Entity): void {
const currentZone = (entity as unknown as { currentZone?: ZoneId }).currentZone;
if (!currentZone) return;
const currentZone = (entity as unknown as { currentZone?: ZoneId }).currentZone ?? null;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The type assertion (entity as unknown as { currentZone?: ZoneId }) is used here and in other places to access currentZone. This suggests that the Entity type definition is missing this property. Repeatedly using unknown bypasses type safety and makes the code less maintainable.

The server-side EntitySchema appears to have this property. To improve type safety, the client-side Entity type (likely defined in src/network/ColyseusClient.ts) should be updated to include currentZone?: ZoneId;.

echo " -> Client: $CLIENT_MAP"
echo ""
echo "MD5 checksums:"
md5 "$SOURCE_MAP" "$SERVER_MAP" "$CLIENT_MAP" 2>/dev/null || md5sum "$SOURCE_MAP" "$SERVER_MAP" "$CLIENT_MAP"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of md5 ... || md5sum ... is a clever way to handle command differences between macOS and Linux. However, redirecting stderr with 2>/dev/null can hide legitimate errors if the md5 command fails for reasons other than not being found.

A more robust approach is to explicitly check for the command's existence first. This makes the script's behavior clearer and avoids suppressing potentially useful error messages.

Consider replacing this line with:

if command -v md5sum &> /dev/null; then
  md5sum "$SOURCE_MAP" "$SERVER_MAP" "$CLIENT_MAP"
elif command -v md5 &> /dev/null; then
  md5 "$SOURCE_MAP" "$SERVER_MAP" "$CLIENT_MAP"
else
  echo "Warning: Could not find md5 or md5sum to verify checksums."
fi

- GameScene: add private _debugBlockedCount field (type-safe)
- GameScene: optimize debug panel to update text instead of recreating
- GameScene: remove unnecessary type assertions for Entity.currentZone
- WorldPackLoader: import ZoneBounds from shared, remove duplicate type
- sync-maps.sh: improve md5 command detection with explicit checks
- sync-maps.mjs: add cross-platform Node.js version for Windows support
- package.json: use Node.js script for sync-maps (Windows compatible)
@ComBba ComBba merged commit 3fa94c0 into main Feb 12, 2026
10 checks passed
@ComBba ComBba deleted the refactor/unified-world-config branch February 12, 2026 03:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant