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.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
# common
|
||||
|
||||
Loader-agnostic Java: protocol types, config model, and the interfaces each leaf module
|
||||
(`forge-1_7_10`, `forge-1_12_2`, `neoforge-26_1`) implements against its own Minecraft/Forge
|
||||
API generation.
|
||||
|
||||
This module is **not** consumed as a compiled binary dependency. The legacy leaves (1.7.10,
|
||||
1.12.2) target Java 8; `neoforge-26_1` targets a modern JDK. To avoid cross-version binary
|
||||
compatibility issues, each leaf module adds `common/src/main/java` directly to its own source
|
||||
set (see the `sourceSets.main.java.srcDirs` line in each leaf's `build.gradle`) and compiles it
|
||||
itself, once per leaf, against its own toolchain. Keep this module free of any
|
||||
Minecraft/Forge/NeoForge API usage — it must compile standalone under plain `javac`.
|
||||
|
||||
## Layout
|
||||
|
||||
- `protocol/` — wire types shared with the backend (delta events, chat/waypoint payloads, link
|
||||
request/response). Mirrors the WS protocol described in the root plan.
|
||||
- `config/` — the common config model (backend URL, server token, tracking/reconciliation
|
||||
intervals) each leaf loads via its own loader-specific config system.
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.octoturge.mcmapper.common;
|
||||
|
||||
import com.octoturge.mcmapper.common.protocol.DeltaEvent;
|
||||
import com.octoturge.mcmapper.common.protocol.LinkRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Outbound WS client to the backend `api` service. One implementation shared by all leaf
|
||||
* modules (pure Java, no Minecraft API usage) — a docker-network hostname, LAN IP, or public
|
||||
* domain in {@code MapperConfig#backendUrl} all work identically.
|
||||
*
|
||||
* Left as an interface with a no-op stub for Phase 0 scaffolding; the real WS client
|
||||
* (handshake, reconnect/backoff, batching) lands in Phase 1.
|
||||
*/
|
||||
public interface BackendConnection {
|
||||
void connect(String url, String serverToken);
|
||||
|
||||
void sendDeltas(List<DeltaEvent> deltas);
|
||||
|
||||
void sendLinkRequest(LinkRequest request);
|
||||
|
||||
void disconnect();
|
||||
|
||||
final class NoOp implements BackendConnection {
|
||||
@Override
|
||||
public void connect(String url, String serverToken) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDeltas(List<DeltaEvent> deltas) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendLinkRequest(LinkRequest request) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.octoturge.mcmapper.common;
|
||||
|
||||
import com.octoturge.mcmapper.common.protocol.WaypointShare;
|
||||
|
||||
/**
|
||||
* Loader-specific chat integration. Implementations inject web-originated chat into real
|
||||
* in-game chat, and build the clickable waypoint chat component for whichever
|
||||
* {@link WaypointShare.Format} is configured — that's text-component API and is different
|
||||
* per Minecraft era, so it can't live in {@code common}.
|
||||
*/
|
||||
public interface ChatBridge {
|
||||
void injectWebChatMessage(String displayName, String message);
|
||||
|
||||
void injectWaypointShare(WaypointShare waypoint);
|
||||
|
||||
/** Called by the loader's own chat event hook; forwards to the backend over the WS connection. */
|
||||
interface OutboundSink {
|
||||
void onInGameChatMessage(String uuid, String username, String message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.octoturge.mcmapper.common;
|
||||
|
||||
import com.octoturge.mcmapper.common.protocol.DeltaEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The seam between a specific Minecraft/Forge API generation and the shared delta-capture and
|
||||
* networking logic. Each leaf module (forge-1_7_10, forge-1_12_2, neoforge-26_1) provides one
|
||||
* implementation, adapting its own era's block-id/block-state representation into the
|
||||
* {@code blockStateId} carried by {@link DeltaEvent}.
|
||||
*/
|
||||
public interface ChunkAdapter {
|
||||
/** Bulk-read a chunk's current state for initial sync / reconciliation, as delta events. */
|
||||
List<DeltaEvent> readChunk(String dimension, int chunkX, int chunkZ);
|
||||
|
||||
/** Register the loader-specific hooks (block place/break, chunk load/unload) that feed the dirty buffer. */
|
||||
void registerEventHooks(DeltaSink sink);
|
||||
|
||||
interface DeltaSink {
|
||||
void onDelta(DeltaEvent event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.octoturge.mcmapper.common.config;
|
||||
|
||||
/**
|
||||
* Loader-agnostic config model. Each leaf module owns loading/saving these values through
|
||||
* its own loader's config system (Forge Config API for the legacy leaves, NeoForge's config
|
||||
* system for neoforge-26_1) and constructs one of these to hand to the common connection code.
|
||||
*/
|
||||
public class MapperConfig {
|
||||
public String backendUrl = "ws://localhost:3000/ws";
|
||||
public String serverToken = "";
|
||||
|
||||
public boolean playerTrackingEnabled = true;
|
||||
public int deltaFlushIntervalTicks = 20;
|
||||
public int reconciliationIntervalTicks = 20 * 60 * 5;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.octoturge.mcmapper.common.protocol;
|
||||
|
||||
/**
|
||||
* A single block change, produced by either the event-driven capture path or the periodic
|
||||
* reconciliation sweep. {@code blockStateId} is a palette index into whatever block/state
|
||||
* palette the leaf module's {@code ChunkAdapter} maintains — the common module never
|
||||
* interprets it, it just carries it to the backend.
|
||||
*/
|
||||
public class DeltaEvent {
|
||||
public final String dimension;
|
||||
public final int x;
|
||||
public final int y;
|
||||
public final int z;
|
||||
public final int blockStateId;
|
||||
public final long timestamp;
|
||||
public final Source source;
|
||||
|
||||
public DeltaEvent(String dimension, int x, int y, int z, int blockStateId, long timestamp, Source source) {
|
||||
this.dimension = dimension;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.blockStateId = blockStateId;
|
||||
this.timestamp = timestamp;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public enum Source {
|
||||
EVENT,
|
||||
RECONCILIATION
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.octoturge.mcmapper.common.protocol;
|
||||
|
||||
/**
|
||||
* Sent when a player runs the link command in-game. {@code authMode} mirrors the MC server's
|
||||
* own online-mode setting and tells the backend whether {@code uuid} is a real Mojang UUID
|
||||
* (safe to merge across servers) or an offline-mode hash (scoped to this server only).
|
||||
*/
|
||||
public class LinkRequest {
|
||||
public final String uuid;
|
||||
public final String username;
|
||||
public final String code;
|
||||
public final AuthMode authMode;
|
||||
|
||||
public LinkRequest(String uuid, String username, String code, AuthMode authMode) {
|
||||
this.uuid = uuid;
|
||||
this.username = username;
|
||||
this.code = code;
|
||||
this.authMode = authMode;
|
||||
}
|
||||
|
||||
public enum AuthMode {
|
||||
ONLINE,
|
||||
OFFLINE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.octoturge.mcmapper.common.protocol;
|
||||
|
||||
/**
|
||||
* Structured payload pushed from the backend when a web visitor shares a marker to chat.
|
||||
* {@code x, y, z} are all populated by the backend (y auto-derived from its heightmap at
|
||||
* placement time) — the mod's only job is to render this as a clickable chat component in
|
||||
* whichever {@link Format} the server admin configured.
|
||||
*/
|
||||
public class WaypointShare {
|
||||
public final String name;
|
||||
public final int x;
|
||||
public final int y;
|
||||
public final int z;
|
||||
public final String dimension;
|
||||
public final String color;
|
||||
public final Format format;
|
||||
|
||||
public WaypointShare(String name, int x, int y, int z, String dimension, String color, Format format) {
|
||||
this.name = name;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.dimension = dimension;
|
||||
this.color = color;
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
public enum Format {
|
||||
JOURNEYMAP,
|
||||
XAERO
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user