# geodata > Handles pathfinding, collision detection, and line-of-sight calculations for the L2J gameserver. Use when: implementing movement validation, checking LOS for skills/attacks, adding dynamic objects (doors/fences), debugging player movement issues, or optimizing pathfinding performance - Author: valeriybaranyshyn-pixel - Repository: valeriybaranyshyn-pixel/Tales-of-Aden - Version: 20260202145225 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/valeriybaranyshyn-pixel/Tales-of-Aden - Web: https://mule.run/skillshub/@@valeriybaranyshyn-pixel/Tales-of-Aden~geodata:20260202145225 --- --- name: geodata description: | Handles pathfinding, collision detection, and line-of-sight calculations for the L2J gameserver. Use when: implementing movement validation, checking LOS for skills/attacks, adding dynamic objects (doors/fences), debugging player movement issues, or optimizing pathfinding performance allowed-tools: Read, Edit, Write, Glob, Grep, Bash --- # Geodata Skill The GeoEngine provides terrain collision, pathfinding, and line-of-sight (LOS) calculations using pre-computed `.l2d` geodata files. The system uses a hierarchical structure: World → Regions (176 total) → Blocks (256×256 per region) → Cells (8×8 per block). Each cell stores height data and NSWE movement flags indicating allowed directions. ## Quick Start ### LOS Check ```java // GeoEngine.java:518-585 if (GeoEngine.getInstance().canSeeTarget(attacker, target)) { // Target is visible, can attack/cast } ``` ### Movement Validation ```java // GeoEngine.java:972-997 if (GeoEngine.getInstance().canMoveToTarget(ox, oy, oz, tx, ty, tz)) { // Direct line movement is possible } else { // Use pathfinding instead List path = GeoEngine.getInstance().findPath(ox, oy, oz, tx, ty, tz, true); } ``` ### Height Correction ```java // Get correct Z coordinate for spawning/teleporting short correctZ = GeoEngine.getInstance().getHeight(worldX, worldY, worldZ); ``` ## Key Concepts | Concept | Usage | Example | |---------|-------|---------| | Cell | Smallest unit, 16×16 game units | `GeoStructure.CELL_SIZE = 16` | | NSWE flags | 8-bit directional movement mask | `CELL_FLAG_N = 0x08, CELL_FLAG_S = 0x04` | | Block types | Flat, Complex, Multilayer | `BlockFlat` = single height, `BlockMultilayer` = bridges | | Dynamic blocks | Runtime-modifiable for doors | `addGeoObject(door)` converts block type | | LOS cache | 1.5s TTL per target | Reduces redundant LOS calculations | ## Common Patterns ### AI Movement Check ```java // L2AttackableAI.java - Check if monster can reach target if (!GeoEngine.getInstance().canMoveToTarget( getActor().getX(), getActor().getY(), getActor().getZ(), target.getX(), target.getY(), target.getZ())) { // Find alternative path or abandon chase } ``` ### Skill Range Validation ```java // Before casting, verify LOS exists if (!GeoEngine.getInstance().canSeeTarget(caster, target)) { caster.sendPacket(SystemMessageId.CANT_SEE_TARGET); return false; } ``` ## See Also - [patterns](references/patterns.md) - [workflows](references/workflows.md) ## Related Skills - See the **ai-system** skill for AI movement integration - See the **l2j-gameserver** skill for server architecture - See the **configuration-management** skill for geoengine.properties settings - See the **java** skill for L2J coding conventions