Phase 4: web markers and JourneyMap/Xaero waypoint chat sharing
Linked accounts can place 2D markers on the map (y auto-derived from the chunk store's heightmap); anonymous visitors keep a localStorage-only list via the same height lookup. Sharing a marker forwards a structured payload to the mod over its WS connection, which builds the actual chat text (see MCMapper-Mod for the JourneyMap/Xaero formatting). Built test-first per the project's TDD workflow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015tKdPZt78zbPUZMXWzKEKt
This commit is contained in:
@@ -10,6 +10,10 @@ export const servers = pgTable("servers", {
|
||||
// Phase 3: web chat is open to anonymous (unlinked) visitors by default; an admin can require
|
||||
// linking per-server. No admin UI to flip this yet (Phase 6) — set directly in the DB for now.
|
||||
anonymousChatAllowed: boolean("anonymous_chat_allowed").notNull().default(true),
|
||||
// Phase 4: which format `/mcmapper`-side chat waypoint links are built in when a marker is
|
||||
// shared — 'journeymap' (default), 'xaero', or 'off' to disable sharing entirely. No admin UI
|
||||
// to flip this yet (Phase 6) — set directly in the DB for now, same as anonymousChatAllowed.
|
||||
waypointFormat: text("waypoint_format").notNull().default("journeymap"),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
});
|
||||
|
||||
@@ -54,6 +58,28 @@ export const chatMessages = pgTable("chat_messages", {
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
});
|
||||
|
||||
// A web-placed marker, owned by a linked account (anonymous visitors keep their marker list in
|
||||
// browser localStorage only — see the plan's "Feature: web markers..." section — so there's
|
||||
// nothing to persist here for them). Placement is 2D-only (x/z picked on the Leaflet map); `y` is
|
||||
// resolved once at creation time from `chunkColumns`' heightmap and stored, not recomputed later,
|
||||
// so a marker doesn't silently move if the terrain above it changes afterward.
|
||||
export const markers = pgTable("markers", {
|
||||
id: uuid("id").defaultRandom().primaryKey(),
|
||||
accountId: uuid("account_id")
|
||||
.notNull()
|
||||
.references(() => accounts.id, { onDelete: "cascade" }),
|
||||
serverId: uuid("server_id")
|
||||
.notNull()
|
||||
.references(() => servers.id, { onDelete: "cascade" }),
|
||||
dimension: integer("dimension").notNull(),
|
||||
x: integer("x").notNull(),
|
||||
y: integer("y").notNull(),
|
||||
z: integer("z").notNull(),
|
||||
name: text("name").notNull(),
|
||||
color: text("color").notNull(),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
});
|
||||
|
||||
// Column-granularity world state: the topmost non-air block per (dimension, x, z), plus its
|
||||
// height. Kept deliberately separate from `chunkSections` below — cheap to write/read for 2D
|
||||
// tile rendering, which never needs full voxel data.
|
||||
|
||||
Reference in New Issue
Block a user