Commit Graph

11 Commits

Author SHA1 Message Date
octoturge 0d8e670cd8 Phase 9: implement forge-1_7_10 leaf (WS, deltas, chat, link, reconciliation, player tracking)
Ports the full feature set proven by forge-1_12_2 (Phases 1-2-3-7-7b) to MC 1.7.10's
older, pre-block-state Forge/FML generation: Forge1710ChunkAdapter reads raw Block+meta
via Chunk/ExtendedBlockStorage instead of IBlockState, hooks BlockEvent/ChunkEvent/TickEvent
under cpw.mods.fml, and MCMapperMod/LinkCommand/Forge1710ChatBridge adapt to 1.7.10's
CommandBase/ChatComponentText/ServerConfigurationManager API shapes. No MultiPlaceEvent hook
at this Forge version (falls back to the reconciliation sweep for multi-block placements).
Verified against real Forge 10.13.4.1614-1.7.10 via ./gradlew :forge-1_7_10:build.
2026-08-09 22:13:45 +02:00
octoturge 890ce46c4f Update README for Phase 7b and fix stale Phase 7 reference
Reconciliation sweep already shipped in 52583f2; document the new
playerTrackingEnabled/playerPositionIntervalTicks config options.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015tKdPZt78zbPUZMXWzKEKt
2026-08-09 20:06:48 +02:00
octoturge ef47d4481a Add throttled player-position tracking, mod side (Phase 7b)
Adds PlayerPosition (common/protocol) and BackendConnection.sendPlayerPositions(),
wired into MCMapperMod.java: a new playerPositionIntervalTicks-throttled tick timer
(gated by playerTrackingEnabled) sends the full current overworld online-player
roster to the backend each interval, mirroring the "current state, not a diff"
philosophy of columns/sections — a player logging out just stops appearing next
send, no separate leave message needed.

Wire message: {"type":"player_positions","dimension":0,"players":[...]}.
Backend-side receive/relay + admin visibility toggle land in a follow-up commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015tKdPZt78zbPUZMXWzKEKt
2026-08-09 19:38:16 +02:00
octoturge 52583f2056 Add periodic reconciliation sweep (Phase 7)
Adds a rotating, non-overlapping-batch ReconciliationScheduler (common/,
loader-agnostic) and wires it into the 1.12.2 leaf: a new tick timer
(reconciliationIntervalTicks, mirroring the existing delta-flush timer)
periodically re-reads and resends a bounded slice of currently-loaded
chunks, catching mutations that never fire a block event (world-gen,
other mods writing blocks directly, /fill, etc.).

ChunkAdapter gains loadedChunkKeys(); Forge1122ChunkAdapter implements it
via ChunkProviderServer.getLoadedChunks(). MapperConfig gains
reconciliationChunksPerSweep to bound sweep cost.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015tKdPZt78zbPUZMXWzKEKt
2026-08-09 19:30:32 +02:00
octoturge 41034356ac Phase 4: receive waypoint shares and render JourneyMap/Xaero chat links
DefaultBackendConnection handles the new waypoint_share message and
dispatches it through a WaypointShareListener. WaypointChatFormatter
builds the actual chat text for both formats from publicly documented
wire formats (see THIRD_PARTY_NOTICES.md for sources/attribution) —
neither needs a click-event component, since both client mods
auto-detect the right plain-text shape. Forge1122ChatBridge wires this
into a real broadcast; MCMapperMod registers the listener.

Built test-first per the project's TDD workflow; verified live against
the real backend, including a byte-exact JourneyMap-format chat
message produced from a real WS payload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015tKdPZt78zbPUZMXWzKEKt
2026-08-08 19:21:30 +02:00
octoturge 73e10d34e5 Phase 3: /mcmapper link command and two-way chat bridge
Test-first from here on (per request after Phase 2's backend commit):
LinkCodeGenerator has a standalone test (common/src/test) written and
confirmed failing before the implementation existed.

common: LinkCodeGenerator produces a 6-character code from an
unambiguous charset (excludes 0/O/1/I/L — it gets read off a chat line
and typed back). BackendConnection grows sendLinkRequest (now actually
implemented, was a Phase 1 stub), sendChatMessage, and setChatListener/
ChatListener for inbound web->game chat, all wired into
DefaultBackendConnection's existing JSON wire protocol.

forge-1_12_2: LinkCommand (/mcmapper link) generates a code, resolves
online/offline from the server's actual auth mode
(MinecraftServer#isServerInOnlineMode), and shows it to the player.
Forge1122ChatBridge implements the inbound half (injects web chat into
real in-game chat via the player list) — injectWaypointShare is a
documented Phase 4 stub, same pattern as sendLinkRequest was in Phase 1.
MCMapperMod hooks ServerChatEvent to forward in-game chat out and wires
the chat listener to the bridge.

Verified end-to-end against a live MCMapper-Backend instance through the
real Java client (not a stand-in): a mod-generated link code correctly
redeems via the backend's HTTP endpoint to an account with the mod-
supplied username, and a browser chat message correctly round-trips all
the way to the mod's live ChatListener callback.
2026-08-08 17:09:09 +02:00
octoturge ab94cca1b2 Document common test runner as 'bash run-tests.sh' (executable bit doesn't survive this filesystem's git add) 2026-08-08 16:40:33 +02:00
octoturge 53cba762b4 Add standalone test coverage for common/'s MiniJson
Requested after MCMapper-Backend's Phase 2: development follows TDD
(test-first) from here on — this retrofits the piece already built
(MiniJson, the hand-rolled JSON codec) before that request landed.

No JUnit/Gradle involved, matching common/'s "must compile standalone
under plain javac" constraint (see README.md) — a hand-rolled assertion
runner in src/test/java, compiled and run via the new run-tests.sh.
Covers write escaping, nested object/array encoding, parsing (including
the exact columns-message shape DefaultBackendConnection actually
builds), and a write-then-parse round-trip.

Deliberately not wired into either leaf's build.gradle sourceSets (which
only pull in src/main/java) — verified both forge-1_12_2 and forge-1_7_10
still compile with src/test/ present, confirming test code doesn't leak
into the shipped mod jar.
2026-08-08 16:39:56 +02:00
octoturge 2b7e0e090d Phase 2: forge-1_12_2 full chunk section backfill/flush
Extends ChunkAdapter with readSections() (reads non-empty 16x16x16
sections via the chunk's ExtendedBlockStorage array, skipping fully-air
ones for free) and DeltaSink with onChunkDirty(), additive to Phase 1's
column-based readChunk()/onDelta — 2D column tracking is unchanged.
BackendConnection grows sendSections(), base64-encoding each section's
4096-entry char[] (char, not short, since short would overflow for any
blockId >= 2048 — see SectionData's javadoc) into the wire protocol's new
"sections" message, mirrored in MCMapper-Backend's matching commit.

MCMapperMod now tracks dirty chunks (not just dirty columns) and, on the
same flush tick as column deltas, re-reads and resends full section data
for any chunk touched since the last flush — same "current state, not a
diff" approach as columns, at chunk instead of column granularity.

Verified against a live MCMapper-Backend instance: a known half-solid
section sent through this exact code path round-trips to a mesh with
exactly 24 vertices / 36 indices at the backend's mesh-serving endpoint,
matching the worker's greedy-mesher unit tests for a uniform section.
2026-08-08 16:19:32 +02:00
octoturge 699f09f081 Phase 1: forge-1_12_2 WS connection and column delta capture
Adds a hand-rolled RFC 6455 WS client and minimal JSON codec to common/ (no
third-party deps, keeping legacy ForgeGradle's classpath untouched), a
DefaultBackendConnection implementing hello/hello_ack auth and reconnect
with backoff, and Forge1122ChunkAdapter deriving top-of-column state from
the vanilla heightmap for both initial chunk backfill and event-driven
deltas (block break/place, deferred one tick to read post-mutation state).
MCMapperMod wires it up with config-driven backendUrl/serverToken and a
tick-based flush batch. Verified against a live MCMapper-Backend api
instance (real WS handshake, hello_ack, and 256-column batch landing
correctly in Postgres).
2026-08-08 15:35:51 +02:00
octoturge 621ea7c10d Phase 0: scaffold Gradle multi-project mod skeleton
common/ (shared source) plus three leaf modules: forge-1_12_2 (primary,
Enigmatica 2 target) and forge-1_7_10 both build via anatawa12's
Gradle-7-compatible ForgeGradle 1.2/2.3 forks (verified: both leaves build
clean on Gradle 7.6 / JDK 8). neoforge-26_1 is structurally scaffolded but
excluded from the default build pending its own toolchain in Phase 10.
2026-08-08 14:10:01 +02:00