Conversation
Co-authored-by: Copilot <copilot@github.com>
- Implemented the goods editor interface for managing resources. - Added functionality to edit resource properties including name, category, value, chance, model, and bonuses. - Introduced event listeners for user interactions such as adding, removing, and modifying goods. - Enabled the ability to toggle between absolute and percentage modes for resource visibility. - Implemented icon selection and color change features for goods. - Added functionality to regenerate and restore default goods. - Included CSV export functionality for goods data. - Enhanced user experience with confirmation dialogs and tooltips for actions. Co-authored-by: Copilot <copilot@github.com>
- Added ProductionModule to handle goods collection based on biome and river production. - Introduced goods editor UI for managing resource properties, including name, category, value, and bonuses. - Implemented functionality to add, remove, and modify goods, including visual representation on the map. - Added support for toggling goods visibility and editing styles with Ctrl+click. - Enhanced goods rendering logic to account for pinned resources and display options. Co-authored-by: Copilot <copilot@github.com>
- Removed goods rendering functions from `goods-renderer.ts` and moved them to a new file `draw-goods.ts`. - Updated global declarations to reflect the new location of `toggleGoods` and `drawGoods` functions. - Created a new `goods-editor.ts` file to handle the goods editing functionality, including UI interactions and data management. - Adjusted the global type definitions in `global.ts` to remove unused function declarations. - Ensured that the new structure maintains existing functionality while improving code organization and readability. Co-authored-by: Copilot <copilot@github.com>
…and enhance goods editor functionality Co-authored-by: Copilot <copilot@github.com>
✅ Deploy Preview for afmg ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
This PR introduces a “Trade Goods” system into the map generator by adding goods generation, a dedicated render layer, a UI editor, persistence in .map files, and a first pass at burg-level production derived from nearby goods/biomes.
Changes:
- Add
GoodsandProductionmodules, store goods on cells (pack.cells.good) and inpack.goods, and persist/load them in.mapfiles. - Add a new SVG
#goodslayer with rendering (drawGoods) + UI toggles/hotkeys + style-preset support. - Add a “Trade Goods Editor” controller for editing goods metadata, icons, and manual cell assignment.
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types/global.ts | Adds global typings for Goods, Production, goods layer, and legacy UI globals used by the new modules/UI. |
| src/types/PackedGraph.ts | Extends packed graph schema with cells.good and pack.goods. |
| src/renderers/draw-goods.ts | Implements goods layer toggle + rendering into the new #goods SVG group. |
| src/modules/production-generator.ts | Adds production calculation (burg.produced) based on nearby goods/biomes and burg population. |
| src/modules/markers-generator.ts | Formatting-only refactors (imports/arrow functions/object formatting). |
| src/modules/index.ts | Registers new modules and editor/renderer entrypoints. |
| src/modules/goods-generator.ts | Implements default goods catalog + spread models + cell assignment generation. |
| src/modules/burgs-generator.ts | Extends Burg type with produced and includes formatting refactors. |
| src/controllers/goods-editor.ts | Adds a full editor UI for goods (list, models, bonuses, icon upload, manual assignment). |
| src/controllers/coastline-editor.ts | Formatting-only refactors. |
| public/versioning.js | Bumps app version to 1.122.0. |
| public/styles/*.json | Adds default styling for the new #goods layer across presets. |
| public/modules/ui/tools.js | Hooks the goods editor and goods regeneration into UI tool actions. |
| public/modules/ui/style.js | Adds goods-specific style controls (data-circle, stroke width) to the style editor. |
| public/modules/ui/style-presets.js | Includes #goods properties in style preset serialization. |
| public/modules/ui/layers.js | Ensures goods are drawn in layer redraws and maps toggleGoods to #goods. |
| public/modules/ui/hotkeys.js | Adds hotkeys for opening the editor and toggling the goods layer. |
| public/modules/ui/general.js | Adds tooltip + cell info display for goods. |
| public/modules/ui/editors.js | Opens the goods editor when interacting with the goods layer. |
| public/modules/ui/burg-editor.js | Displays computed production (burg.produced) in the burg editor UI. |
| public/modules/io/save.js | Appends goods arrays to .map save format. |
| public/modules/io/load.js | Loads goods arrays from .map files into pack. |
| public/modules/dynamic/auto-update.js | Adds migration logic for maps older than 1.122.0 to initialize goods. |
| public/main.js | Adds #goods layer creation, goods generation during map generation, and goods bonus in rankCells. |
| public/index.css | Adds cursor + editor styling for goods UI elements. |
| function changeResourceOnCellClick(this: SVGElement) { | ||
| const body = ensureEl("goodsBody"); | ||
| const point = pointer(event, this); | ||
| const cellId = findCell(point[0], point[1]); | ||
| if (cellId === undefined) return; |
There was a problem hiding this comment.
changeResourceOnCellClick relies on the global event instead of accepting the event parameter from the D3 handler. This is brittle (and can be undefined in some contexts) and makes typing harder. Update the handler signature to accept the MouseEvent argument and pass it to pointer(...).
| const good: Good = { | ||
| i, | ||
| name: `Good${i}`, | ||
| category: "Unknown", | ||
| icon: "good-unknown", | ||
| color: "#ff5959", | ||
| value: 1, | ||
| chance: 10, | ||
| model: "habitability", | ||
| unit: "", | ||
| bonus: {population: 1} as Record<string, number>, | ||
| culture: {} as Record<string, number>, | ||
| cells: 0 |
There was a problem hiding this comment.
goodAdd sets model: "habitability", but Goods.models does not define a habitability key. This makes the default spread predicate evaluate to undefined (good never spawns) until the user manually changes the model. Initialize new goods with a valid default model key (e.g. More_habitable) or the first available model.
| const baseProduction = goodsPull[resourceId]; | ||
| const resource = Goods.get(+resourceId); | ||
|
|
||
| const cultureModifier = resource?.culture[type] || 1; | ||
| const production = baseProduction * cultureModifier; | ||
|
|
||
| const {value, category} = resource!; | ||
| const isFood = category === "Food"; | ||
|
|
There was a problem hiding this comment.
collectGoods assumes Goods.get(resourceId) always returns a resource and then dereferences resource!. This can crash if a map has cells referencing a removed/unknown good id (the editor allows deleting goods). Handle undefined by skipping the resource or providing a fallback value/category.
| getStroke(colorHex: string): string { | ||
| return (color(colorHex) as any).darker(2).hex(); | ||
| } |
There was a problem hiding this comment.
getStroke assumes d3.color(colorHex) always returns a valid color. If a user sets an invalid color string in the goods editor or a map file contains invalid data, color(...) can return null and this will throw. Add a null-check and fall back to a default stroke color.
| infoFeature.innerHTML = f ? (pack.features[f].group || pack.features[f].type) + " (" + f + ")" : "n/a"; | ||
| infoBiome.innerHTML = biomesData.name[cells.biome[i]]; | ||
| infoGood.innerHTML = cells.good[i] ? Goods.get(cells.good[i]).name + " (" + cells.good[i] + ")" : "no"; |
There was a problem hiding this comment.
updateCellInfo calls Goods.get(cells.good[i]).name without checking that Goods.get(...) returned a value. If cells.good[i] references an unknown/removed good id, this will throw and break the cell info panel. Please guard (e.g., resolve the good first and fall back to "no" if missing).
| const model = r.custom || this.models[r.model as keyof typeof this.models]; | ||
| const allMethods = `{${Object.keys(this.methods).join(", ")}}`; | ||
| r.fn = new Function(allMethods, `return ${model}`) as (methods: any) => boolean; | ||
| }); |
There was a problem hiding this comment.
Goods.generate builds spread predicates using new Function(...) from good.custom / models[...]. Since good.custom is persisted in .map files and user-editable in the UI, loading a map can execute arbitrary JavaScript in the page context. Please replace this with a safe expression evaluator/DSL (e.g., parse + interpret a limited grammar), or at minimum disallow persisted custom functions and only allow predefined models.
| if (customName && customFn) { | ||
| try { | ||
| const allMethods = `{${Object.keys(Goods.methods).join(", ")}}`; | ||
| const fn = new Function(allMethods, `return ${customFn}`); | ||
| fn({...Goods.methods}); | ||
| } catch (err) { | ||
| message.innerHTML = `Error. ${(err as Error).message || err}`; |
There was a problem hiding this comment.
The custom spread model validator uses new Function(...) and invokes it. Because customFn comes from user input / loaded map data, this provides an arbitrary code execution vector. Consider switching to a constrained expression language or a sandboxed evaluator, and avoid executing persisted custom code during load/validation.
- Updated goods structure to replace 'category' with 'type' and added 'tags' for better classification. - Introduced a normalization function for tags in the GoodsModule to handle legacy categories. - Adjusted production calculations to utilize the new 'tags' structure instead of 'category'. - Refactored utility functions to use a new TYPED_ARRAY_MAX structure for better clarity and maintainability. - Enhanced the goods editor UI in index.html to reflect the new tags and sorting options. - Cleaned up code formatting and improved readability across multiple files. Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
- Introduced getHeight function to convert height values from generator scale to real-world height with units. - Updated unitUtils to include height conversion logic based on selected unit (meters, feet, fathoms). - Exposed getHeight function to the global window object for accessibility. - Cleaned up the convertTemperature function formatting for consistency. Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
…nd functionality Co-authored-by: Copilot <copilot@github.com>
…sibility Co-authored-by: Copilot <copilot@github.com>
…duction and new goods - Added biome production capabilities to goods, allowing for specific production rates based on biome types. - Introduced new goods such as "Vinegar", "Preserved food", and "Candles" with associated recipes and attributes. - Updated existing goods to include biome production values and adjusted their properties (e.g., value, chance). - Refactored production generation logic to utilize new biome production data and improved recipe handling for manufactured goods. - Enhanced culture modifiers for goods production based on cultural types. Co-authored-by: Copilot <copilot@github.com>
…nd recipe yield calculation
…adability Co-authored-by: Copilot <copilot@github.com>
…rmation and improved scoring Co-authored-by: Copilot <copilot@github.com>
…data rendering Co-authored-by: Copilot <copilot@github.com>
…ice and tagged goods Co-authored-by: Copilot <copilot@github.com>
…tions and update schema documentation Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
- Added demand categories and profiles based on burg population. - Introduced supply attributes to goods to define how much each unit covers specific demand categories. - Updated production scoring to include a multiplier based on unmet demand, enhancing decision-making for extract and manufacture actions. - Refactored production logic to calculate demand coverage and contributions for better resource management. - Enhanced UI rendering to display demand effects in production overview. Co-authored-by: Copilot <copilot@github.com>
…chema Co-authored-by: Copilot <copilot@github.com>
…date resource terminology Co-authored-by: Copilot <copilot@github.com>
… capita in burg editor and overview Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
…rmats Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
- Simplified the structure and language of the production schema. - Removed redundant sections and streamlined the overview of the production process. - Clarified the roles of local resources, inventory, and the global market. - Enhanced explanations of demand targets and scoring mechanisms. - Updated the action types and phases to reflect current implementation details. - Improved the organization of sections for better readability and understanding. Co-authored-by: Copilot <copilot@github.com>
…flow animation and truncate good names
…ations; improve rendering and tooltip clarity
…and calculations; enhance decision candidate details
… overview; update amount handling in production generator
Description