1
0
Fork 0
polaris-task-force/src/collections/world/MapZones.ts
Z8MB1E cc0a7facd0 feat(map): political zone types, road label tri-state, authoring snapping lib
- map-zones type gains territory and country border (informational political
  boundaries that never gate placement, default fills amber 0.1 / violet 0.06)
- map-roads labelVisible is tri-state: unset means auto, where paved roads
  always label and dirt/trail only label at 4 m/px or finer (roadLabelShown)
- migration clears the old implicit label default on non-paved roads
- new pure snapping lib: findSnap (vertices own their neighborhood, edges must
  be twice as close), closestPointOnSegment, segmentMidpoints
- tests for label angles, tri-state rule, snapping, political zones
2026-09-17 16:27:55 -04:00

125 lines
3.3 KiB
TypeScript

import { CollectionConfig } from "payload";
import { requirePermission } from "@/utils/access-control/hasPermission";
import { validateHexColor } from "@/lib/map/style";
import { validatePolygon } from "@/lib/map/points";
/**
* GM-drawn terrain zones. Land blueprints cannot be placed inside water
* polygons; water blueprints require one. Default terrain (no zones on the
* map) accepts everything.
*/
export const MapZones: CollectionConfig = {
slug: "map-zones",
admin: {
group: "World",
useAsTitle: "name",
},
access: {
read: ({ req }) => !!req.user,
create: requirePermission("maps:create"),
update: requirePermission("maps:update"),
delete: requirePermission("maps:delete"),
},
fields: [
{
name: "name",
type: "text",
admin: {
description: 'Zone label (e.g. "Altis bay", "Flood plain").',
},
},
{
name: "description",
type: "textarea",
admin: {
description: "Shown in the zone's tooltip and popup on the map.",
},
},
{
name: "map",
type: "relationship",
relationTo: "maps",
required: true,
},
{
name: "type",
type: "select",
required: true,
options: [
{ label: "Water", value: "water" },
{ label: "Land", value: "land" },
{ label: "Territory", value: "territory" },
{ label: "Country Border", value: "border" },
],
admin: {
description:
"Water zones block land-blueprint placement. Land zones are informational; default terrain is buildable land. Territory and Country Border are political boundaries (informational).",
},
},
{
name: "fillColor",
type: "text",
validate: validateHexColor,
admin: {
description: "Polygon fill as hex (e.g. #38bdf8). Empty = default color for the type.",
},
},
{
name: "strokeColor",
type: "text",
validate: validateHexColor,
admin: {
description: "Outline color as hex. Empty = default color for the type.",
},
},
{
name: "fillOpacity",
type: "number",
min: 0,
max: 1,
admin: {
description:
"Fill opacity 0-1. Empty = default (0.25 water, 0.08 land, 0.1 territory, 0.06 border).",
},
},
{
name: "strokeWeight",
type: "number",
min: 0,
max: 10,
defaultValue: 1,
admin: {
description: "Outline thickness in pixels. 0 hides the outline.",
},
},
{
name: "resources",
type: "relationship",
relationTo: "resources",
hasMany: true,
admin: {
description:
"Resources contained in this zone (e.g. an oil field). A zone with resources satisfies blueprint resourcesInRange requirements for any site inside it.",
},
},
{
name: "labelVisible",
type: "checkbox",
defaultValue: true,
label: "Show Name Label",
admin: {
description: "Renders the zone's name at the polygon's center.",
},
},
{
name: "points",
type: "json",
required: true,
validate: validatePolygon,
admin: {
description:
"Polygon ring as an array of [x, y] meter tuples (need not repeat the first point).",
},
},
],
};