Skip to content

feat: fence and gate lines as their own layer - #4

Merged
neovolgan merged 2 commits into
claude/rotated-projectionfrom
claude/fence-lines
Oct 16, 2026
Merged

neovolgan merged 2 commits into
claude/rotated-projectionfrom
claude/fence-lines

Conversation

@neovolgan

Copy link
Copy Markdown
Collaborator

Implements section 4 of the transfer contract (#2). It is stacked on #3 because both raise the world format to 7. Merge #3 first; this PR then retargets to develop.

Why a separate layer:

  • LinearFeature allows 64 features per map, and fences built as decorations take the single decoration slot of a cell.
  • One Pilna section has more than 1000 fence lines and about 41k fence edges, so neither fits.

Model (FenceLines.cs; MapProject and WorldProject both get Fences, FenceStyles and GateStyles):

  • FenceLine:
    • grid points; runs must be horizontal or vertical along cell edges;
    • a style;
    • PostSpacing, with posts at corners and every N edges;
    • gates;
    • source ID, tags and lon/lat path.
  • FenceStyle: W, N, optional NW corner, Post, and WAlt/NAlt every AltEvery edges (a brick pillar between forged sections).
  • GateStyle: 1–8 edges wide, closed pieces plus optional open pieces. OpensTo = left mirrors the piece order.

Composition and export:

  • A horizontal edge gives N on the cell to its south, and a vertical edge gives W on the cell to its east.
  • When both edges of one style are plain, the cell gets NW.
  • Edge pieces carry the native navigation bits (2 = N, 4 = W). Gates carry none.
  • Edges on building footprints or water are skipped and counted per reason; overlaps are counted too.
  • TileComposer adds the pieces after decorations, so a fence and a decoration (bush, lamp, bench) share a cell.
  • World fences are projected into every section they cross, with section-local coordinates, and clipped per cell, so a fence stays continuous across seams.
  • A style ID used by both the world and a section must mean the same tiles, otherwise validation fails.

Formats:

  • A fence layer raises the map format to 12 and the world format to 7, in C# and JS.
  • Geographic reimport with Preserve edits keeps fences.
  • The editor accepts format 12. Drawing and editing fences in the UI is left to the editor-side work, per the split in docs: real-place transfer contract v1 #2.

Tests (FenceLineTests):

  • edges, NW merge, double gate order, opened wicket, navigation bits, pillar pattern;
  • left-opening mirror, post spacing, blocked and counted building edges;
  • validation:
    • diagonal runs;
    • unknown style;
    • a gate around a corner;
    • overlapping gates;
    • bad opening side;
    • a gate set open without open pieces;
    • bad tile;
    • duplicate line;
  • JSON round-trip and format 12;
  • a fence and a decoration on the same cell both reach the native .lotheader;
  • a world fence crossing a 256-tile seam has 6 + 6 continuous edges and reaches both cells' lot headers;
  • conflicting world and section styles are rejected.

Results: dotnet run --project tests/SimplePZMapmaker.Tests 343/343 passed, npm test 184/184 passed.

Next from my side: GeoJSON barrier=* lines → fence lines (style mapping, staircase for diagonals, gate points), and the Pilna pipeline switching its fences to this layer.

🤖 Generated with Claude Code

https://claude.ai/code/session_015ECCGjSrSADcjxBmXdCBpm


Generated by Claude Code

Fences run along cell edges in a dedicated map/world layer with named
fence styles (W, N, NW corner, post, alternating pillar edges) and gate
styles (1-8 edges, closed/open pieces, mirrored when opening left). The
exporter adds them as wall objects with native edge bits, so a fence no
longer takes a cell's single decoration slot. World fences are projected
into every section they cross, so they stay continuous at seams.
Building and water cells are skipped and counted. A fence layer raises
the map format to 12 and the world format to 7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ECCGjSrSADcjxBmXdCBpm
@neovolgan
neovolgan added this pull request to stack #7 October 16, 2026 21:14
@neovolgan
neovolgan merged commit 81d162e into develop Oct 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants