@adatechnology/game-urban 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -0
- package/dist/index.d.ts +343 -2
- package/dist/index.global.js +536 -14
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +544 -17
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -49,6 +49,23 @@ createUrban({
|
|
|
49
49
|
- `block.fill(b, { cx, cz, size, minHeight, maxHeight, k, gap, lit, shop })`: a `k x k` split of the block less 2 m of street; a building a little smaller than its lot, as tall as `lerp(min, max, random^1.6)` (more low buildings than tall ones), drawn by `createCityBuilding` of game-floorplan with the shared generator. Returns the buildings for the game's bookkeeping. `block.building` places one.
|
|
50
50
|
- `props`: `fence`, `tent`, `pine`, `tree`, `container`, `watchtower` (with a searchlight whose beam circles the ground), `sandbags` (instances), `label` (two lines on a 22 x 4.4 m board) and `wires`.
|
|
51
51
|
|
|
52
|
+
### Towers
|
|
53
|
+
|
|
54
|
+
`createUrban({ towers: true })` (off by default; the output is then the same as before, byte for byte) draws a building of the block or of an avenue that is at least `minHeight` (60 m) tall as a **tower** instead of a box: a podium with a taller ground storey, the shaft with a row of windows on every storey of its four faces, darker bands without windows where the plant floors are, the top plant floor set back, the parapet and a mast. Which kind is drawn is chosen by weight among the `presets`, whose numbers are the ones of the typologies of `game-floorplan-commercial` (`office`: 4 m storeys, a plant floor every 20, glass curtain wall) and `game-floorplan-residential` (`residential`: 3.1 m storeys, every 25, masonry with a window in each bay); the tests keep them equal. A game turns them off, changes the cut-off height, the presets and their weights, or draws the tower itself:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
createUrban({
|
|
58
|
+
towers: {
|
|
59
|
+
minHeight: 80,
|
|
60
|
+
presets: [{ id: 'office', weight: 1, storeyHeight: 4, mechanicalEvery: 20, glass: true, color: 0x3c5a73 }],
|
|
61
|
+
mast: 0.04,
|
|
62
|
+
provider: (request, b) => myTower(request, b), // request: x, z, width, depth, height, color, preset, lit
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The heights come from where the building is drawn: `block.fill`'s `minHeight` and `maxHeight`, or the `buildings` of the `downtown` pattern (raise them with `patch`). The pack `TOWER_PATTERNS` (not in the sample sheet) adds `financial_district`, the avenue with 20 m lots and towers of 70 to 180 m: `createUrban({ packs: { neighbourhoods: TOWER_PATTERNS }, towers: true })`.
|
|
68
|
+
|
|
52
69
|
## Neighbourhood patterns
|
|
53
70
|
|
|
54
71
|
`urban.neighbourhoods` has the ten patterns of the Galeria's sample sheet: `downtown`, `suburb`, `working_class`, `historic_street`, `industrial_port`, `railway_village`, `mountain_resort`, `stilt_village`, `military` and `rural`. A pattern is data (`streetWidth`, `walkWidth`, `typologies`, `pole`, `lightColor`, `spacing`, `lit` = the share of lamps on and the rest burnt out, `marker`, `text` in `pt-BR` and `en`, and the `params` of its composer) plus a `compose` key into the registry of composers, which draw the street. A game changes a number with `patch`, adds a pattern with `packs` and a composer with `composers`, or takes one out with `remove`.
|
|
@@ -70,6 +87,55 @@ urban.neighbourhoods.composeSampleSheet(b) // the ground and the ten cells, in
|
|
|
70
87
|
|
|
71
88
|
`createVehicleProvider({ ids?, pick?, paint? })` parks a vehicle of `game-vehicles-fleet` (cars, SUVs, pickups and vans by default) where a pattern parks one, and `createPlantProvider({ region?, contexts?, seed?, pick? })` plants a species of `game-vegetation-species` where a pattern plants (a tree from the region's `sidewalk_tree` table, a pine from `square`). They do not draw: they add a `placement` part (`b.place(kind, id, x, z, { ry, scale, color, seed })`) that says what to put and where. The choice depends on the spot and not on `b.random`, so the scene around it keeps the same draw order. The drawer (`game-urban-three`) asks a resolver for each kind and leaves the spot empty when it has none.
|
|
72
89
|
|
|
90
|
+
## City plans (zoning)
|
|
91
|
+
|
|
92
|
+
A **district kind** (`urban.cities.kinds`, 22 shipped) says what a patch of the city is: its map `color`, the `zone` of the floorplan packages (`zt`, `zc`, `zr1`, ...), the neighbourhood `pattern` that dresses it (an id of `urban.neighbourhoods`, or `financial_district` of `TOWER_PATTERNS`), the `floors` `[min, max]`, the share of buildings by `uses` (`commercial`, `residential`, `industrial`, `institutional`, `agricultural`), the `block` size in metres (0 = no blocks) and its `text` in `pt-BR` and `en`. A **city plan** (`urban.cities.plans`) paints kinds on a map of metres (centre 0,0, x east, z south): `districts` (`{ id, kind, rect: [x0, z0, x1, z1], name?, floors?, uses? }`) listed from the outer to the inner one, so the **last district that contains a point wins**; `lines` (avenue, street, highway, rail, river) and `landmarks`. Plans are data: nothing is drawn unless you call `fillBlock`, and existing scenes do not change.
|
|
93
|
+
|
|
94
|
+
| id | scale | size (m) | what it is |
|
|
95
|
+
|---|---|---|---|
|
|
96
|
+
| `metropolis` | metropolis | 6000 x 6000 | Tower downtown ringed by commerce, high-rise and low-rise neighbourhoods, outskirts and industry on the railway |
|
|
97
|
+
| `regional_city` | city | 4000 x 4000 | Commercial centre with a few tall buildings, house neighbourhoods and an industrial district |
|
|
98
|
+
| `port_city` | city | 4000 x 3000 | Quays and warehouses on the shore, old town behind the port and neighbourhoods up the hill |
|
|
99
|
+
| `rail_town` | town | 3000 x 3000 | A town grown around its station: rail yard, old centre, company village |
|
|
100
|
+
| `country_town` | town | 2400 x 2400 | Main square with the church, ground-floor shops around, houses, a co-op and smallholdings |
|
|
101
|
+
| `mountain_village` | village | 1600 x 1200 | Church square, a street of inns up the slope and chalets scattered on the hill |
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
const urban = createUrban({ towers: true })
|
|
105
|
+
const layout = urban.cities.layout('regional_city', { locale: 'en', maxFloors: 40 })
|
|
106
|
+
layout.districtAt(0, 0) // { id, kind, color, zone, pattern, floors, uses, block, name, rect }
|
|
107
|
+
const center = layout.districts.find((d) => d.kind === 'commercial_center')!
|
|
108
|
+
const blocks = layout.blocks(center.id, { street: 10 }) // { x, z, size, district, building: { floors, uses, zone, pattern } }[]
|
|
109
|
+
const b = urban.builder({ seed: 7 })
|
|
110
|
+
for (const block of blocks) urban.cities.fillBlock(b, block) // block.fill with the block's floors and uses
|
|
111
|
+
urban.cities.stats(layout) // [{ kind, area, share, districts }] by kind
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`blocks` is the grid of the district's rectangle by the kind's `block` size, less the street, skipping the cells whose centre belongs to another district (one painted over it). `block.building` is the config a building generator takes. `fillBlock` calls `block.fill` with the block's `floors` and `uses` (and `storeyPresets` / `storeyHeight` when you pass them), so each building picks its use by weight and gets `floors x storey height` of that use's tower preset (`office` 4 m, `residential` 3.1 m; a game that changes the presets changes it); with `towers` on, tall commercial buildings become office towers and tall residential ones residential towers, capped by `towers.maxStoreys`. The ground-floor `shop` chance defaults to the commercial share. It draws nothing for kinds with no storeys or no pattern.
|
|
115
|
+
|
|
116
|
+
**Floors are capped at 60 by default**, after the district's own override: `createUrban({ cities: { maxFloors: 40 } })` or `layout(plan, { maxFloors })` clamp every district to `[0, maxFloors]`. A game raises the cap and the kind together.
|
|
117
|
+
|
|
118
|
+
A game adds its own city (or kind) with `packs`, changes numbers with `patch` and takes some out with `remove`, under the keys `districtKinds` and `cityPlans`. A plan can start from another with `extends`: its districts, lines and landmarks come first, a district or line with the same id replaces the parent's in place, new ones append (landmarks always append), and `size`, `scale` and `text` are inherited when omitted.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
createUrban({
|
|
122
|
+
cities: { maxFloors: 80 },
|
|
123
|
+
packs: {
|
|
124
|
+
districtKinds: [{ id: 'harbour_lofts', color: '#5aa0a8', zone: 'zr3_zm', pattern: 'downtown', floors: [3, 9], uses: { residential: 0.7, commercial: 0.3 }, block: 60,
|
|
125
|
+
text: { 'pt-BR': { name: 'Lofts do cais', description: 'Armazéns reformados.' }, en: { name: 'Harbour lofts', description: 'Converted warehouses.' } } }],
|
|
126
|
+
cityPlans: [{
|
|
127
|
+
id: 'my_port',
|
|
128
|
+
extends: 'port_city',
|
|
129
|
+
districts: [{ id: 'lofts', kind: 'harbour_lofts', rect: [-400, -200, 0, 300] }], // painted over what is there
|
|
130
|
+
lines: [{ id: 'ferry', kind: 'street', width: 12, points: [[-400, 0], [0, 0]] }],
|
|
131
|
+
landmarks: [{ kind: 'lighthouse', at: [-380, 120], name: 'Old light' }],
|
|
132
|
+
}],
|
|
133
|
+
},
|
|
134
|
+
patch: { districtKinds: { downtown: { floors: [30, 80] } } },
|
|
135
|
+
remove: { cityPlans: ['rail_town'] },
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
73
139
|
## Terrain
|
|
74
140
|
|
|
75
141
|
`urban.terrain(options)` is a ground made of layers, as the Galeria's Vale: a rolling base (waves), masked relief (mountains, hills: `mask · (level + waves)`), cities levelled flat, rivers carved to a bed, lakes carved to a level, a forest density, and a colour for every point by ordered rules (low ground, ellipses such as a bog, city rectangles, high rock, forest, then open fields picked by a hash of the map cell). It answers `heightAt(px, py)`, `forestAt`, `colorAt`, `nearRiver` and `toWorld`/`fromWorld` (the frame maps the plan to metres: `world = plan · scale + origin`), and hands a drawer `grid(segments)`: the 32-bit coordinates, heights and colours of the square mesh, rows along z. `urban.drawTerrain(b, terrain)` adds the mesh part and the water plane. `custom(px, py, h)` has the last word on a height.
|
|
@@ -79,3 +145,27 @@ The numbers of a place are the game's: the Vale Cinzento (4 rivers, 4 lakes, 5 c
|
|
|
79
145
|
## Same seed, same city
|
|
80
146
|
|
|
81
147
|
The page keeps one generator for everything it draws and draws from it in call order. The builder does the same: the facade colour, the shop signs, the lit windows and the heights come from `b.random`, in the page's order, so a scene drawn with the same seed and the same calls has the same parts. The golden test in `game-urban-three` compares 34 parts, the terrain mesh (181 x 181 vertices, heights and colours) and the whole sample sheet (1029 objects, the lists of instances and windows, the light budget left, the next number of the random and the map markers) with the page's scene hash, the lists the page keeps before its flush and the surface of each material.
|
|
148
|
+
|
|
149
|
+
### Configurar pelo jogo (torres da cidade)
|
|
150
|
+
|
|
151
|
+
`createUrban({ towers })` aceita `minHeight`, `maxStoreys` (padrão 60: um lote mais alto é desenhado com 60 andares do tipo), `presets` (cada um com `weight`, `storeyHeight`, `mechanicalEvery`, `glass`, `minStoreys`, `maxStoreys`), `mast`, `lit` e `provider`. `towerPresetOf` monta um preset a partir do layout de uma tipologia, para a cidade desenhar a mesma torre que o jogo configurou em `office_tower` / `residential_tower`.
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const office = officeTowerLayout({ storeys: 50, height: 3.4 })
|
|
155
|
+
const kit = createUrban({
|
|
156
|
+
packs: { neighbourhoods: TOWER_PATTERNS },
|
|
157
|
+
towers: {
|
|
158
|
+
maxStoreys: 70,
|
|
159
|
+
presets: [
|
|
160
|
+
towerPresetOf('office', 0.3, office, { mechanicalEvery: 18, minStoreys: 25, maxStoreys: 70 }),
|
|
161
|
+
{ ...DEFAULT_TOWER_PRESETS[1], weight: 0.7, maxStoreys: 40 },
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Por prédio, o bloco também aceita os andares e os usos (os mesmos nomes de `building` de um bloco de `urban.cities`): `block.fill(b, { ..., floors: [8, 40], uses: { commercial: 0.6, residential: 0.4 } })`. `floors` é um número ou `[min, max]` e vira altura (andares vezes o pé-direito do preset do uso; sem uso, `storeyHeight`); `uses` sorteia o uso de cada prédio por peso, e `storeyPresets` (padrão `{ commercial: 'office', residential: 'residential' }`) diz que tipo de torre cada uso desenha. Com `towers` ligado, prédios altos comerciais viram `office` e residenciais `residential` (o `TowerRequest` traz `use` e `storeys`); os baixos seguem o prédio comum com a altura dos andares pedidos. Sem `floors` e `uses` a saída não muda.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
kit.block.fill(b, { cx: 0, cz: 0, size: 100, minHeight: 20, maxHeight: 60, ...block.building }) // block.building = { floors: [10, 40], uses: { commercial: 1 } }
|
|
171
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -586,6 +586,83 @@ declare function drawGround(b: UrbanBuilder, color?: number, size?: number): voi
|
|
|
586
586
|
*/
|
|
587
587
|
declare function drawStreetGrid(b: UrbanBuilder, block: number, count: number, width: number, options?: StreetOptions): void;
|
|
588
588
|
|
|
589
|
+
/**
|
|
590
|
+
* One kind of tower the city can put on a tall lot: the numbers of a typology of `game-floorplan-commercial` (office) or `game-floorplan-residential`
|
|
591
|
+
* (residential), which the tests keep equal to theirs. The city only draws the outside; the plan of the inside is the typology's.
|
|
592
|
+
*/
|
|
593
|
+
type TowerPreset = {
|
|
594
|
+
id: string;
|
|
595
|
+
/** Chance weight among the presets (the one the random picks). */
|
|
596
|
+
weight: number;
|
|
597
|
+
/** Floor to floor in metres: the clear height of the typology plus its slab. */
|
|
598
|
+
storeyHeight: number;
|
|
599
|
+
/** A plant floor (darker band, no windows) every this many storeys; `false` none. */
|
|
600
|
+
mechanicalEvery: number | false;
|
|
601
|
+
/** A glass curtain wall (a ribbon of tall windows on a tinted skin) or a punched facade (a window in each bay of the masonry). */
|
|
602
|
+
glass: boolean;
|
|
603
|
+
/** Fewest and most storeys this preset's towers have (the lot height is raised or cut to it); omitted: no minimum, and `TowerOptions.maxStoreys` for the top. */
|
|
604
|
+
minStoreys?: number;
|
|
605
|
+
maxStoreys?: number;
|
|
606
|
+
/** Colour of the skin; omitted: the facade colour the block drew for the lot (glass: a blue tint of it). */
|
|
607
|
+
color?: number;
|
|
608
|
+
};
|
|
609
|
+
/** The two typologies: the office tower (4.0 m storeys: 3.6 clear and 0.4 slab, a plant floor every 20, glass) and the residential tower (3.1 m, every 25, masonry). */
|
|
610
|
+
declare const DEFAULT_TOWER_PRESETS: readonly TowerPreset[];
|
|
611
|
+
/**
|
|
612
|
+
* A preset from the layout of a typology (`officeTowerLayout(opts)`, `residentialTowerLayout(opts)`), so the city draws the tower the game configured:
|
|
613
|
+
* the storey pitch and the facade come from the layout, the storey range from its `range` when given.
|
|
614
|
+
*/
|
|
615
|
+
declare const towerPresetOf: (id: string, weight: number, layout: {
|
|
616
|
+
pitch: number;
|
|
617
|
+
facade: "curtain" | "punched";
|
|
618
|
+
}, extra?: Partial<Omit<TowerPreset, "id" | "weight" | "storeyHeight" | "glass">>) => TowerPreset;
|
|
619
|
+
/** What a game asks a tower provider to put on the ground: the lot, the height, the preset the random chose and the facade colour. */
|
|
620
|
+
type TowerRequest = {
|
|
621
|
+
x: number;
|
|
622
|
+
z: number;
|
|
623
|
+
width: number;
|
|
624
|
+
depth: number;
|
|
625
|
+
height: number;
|
|
626
|
+
color: number;
|
|
627
|
+
preset: TowerPreset;
|
|
628
|
+
lit: number;
|
|
629
|
+
use?: string;
|
|
630
|
+
storeys?: number;
|
|
631
|
+
};
|
|
632
|
+
/** Draws a tower in place of the default one (the game's own model, or the plan of the typology rendered by `game-floorplan-three`). */
|
|
633
|
+
type TowerProvider = (request: TowerRequest, b: UrbanBuilder) => void;
|
|
634
|
+
type TowerOptions = {
|
|
635
|
+
/** A building at least this tall (metres) is drawn as a tower. Default 60. */
|
|
636
|
+
minHeight?: number;
|
|
637
|
+
/** Kinds of tower and their weights. Default `DEFAULT_TOWER_PRESETS`. */
|
|
638
|
+
presets?: readonly TowerPreset[];
|
|
639
|
+
/** Replaces the default drawing. */
|
|
640
|
+
provider?: TowerProvider;
|
|
641
|
+
/** The crown: height of the mast over the roof as a share of the tower (default 0.06, at most 25 m), 0 for none. */
|
|
642
|
+
mast?: number;
|
|
643
|
+
/** Most storeys a tower may have (default 60, the structural limit of the kit): a taller lot is drawn at this many storeys of its preset. */
|
|
644
|
+
maxStoreys?: number;
|
|
645
|
+
/** Chance that a window is lit when the block did not say (default 0.12). */
|
|
646
|
+
lit?: number;
|
|
647
|
+
};
|
|
648
|
+
declare const TOWER_DEFAULTS: {
|
|
649
|
+
readonly minHeight: 60;
|
|
650
|
+
readonly maxStoreys: 60;
|
|
651
|
+
readonly mast: 0.06;
|
|
652
|
+
readonly lit: 0.12;
|
|
653
|
+
};
|
|
654
|
+
/** The preset the random picks by weight; draws once. */
|
|
655
|
+
declare function pickTowerPreset(b: UrbanBuilder, presets: readonly TowerPreset[]): TowerPreset;
|
|
656
|
+
/** Storeys of a tower of this height, the podium (a taller ground storey) included. */
|
|
657
|
+
declare const towerStoreys: (height: number, preset: TowerPreset) => number;
|
|
658
|
+
/**
|
|
659
|
+
* A tower: a podium with a taller ground storey, the shaft with a row of windows on every storey of its four faces, darker bands where the plant
|
|
660
|
+
* floors are (no windows), the top plant floor set back, the parapet and the mast. Draws one random per window (lit or not), after the preset's.
|
|
661
|
+
*/
|
|
662
|
+
declare function drawTower(b: UrbanBuilder, request: TowerRequest, options?: Pick<TowerOptions, 'mast'>): BlockBuilding;
|
|
663
|
+
/** The drawer a kit uses for a building of the block or the avenue: a tower from the minimum height up, the plain city building under it. */
|
|
664
|
+
declare function createTowerDrawer(towers: TowerOptions, plain: (b: UrbanBuilder, x: number, z: number, width: number, depth: number, height: number, color: number, o?: BuildingOptions) => BlockBuilding): (b: UrbanBuilder, x: number, z: number, width: number, depth: number, height: number, color: number, o?: BuildingOptions) => BlockBuilding;
|
|
665
|
+
|
|
589
666
|
/** Facade colours of the city buildings (the Galeria's `FAC`). */
|
|
590
667
|
declare const DEFAULT_FACADES: readonly number[];
|
|
591
668
|
type FillBlockOptions = {
|
|
@@ -599,6 +676,21 @@ type FillBlockOptions = {
|
|
|
599
676
|
shop?: number;
|
|
600
677
|
/** Facade colours. Default `DEFAULT_FACADES`. */
|
|
601
678
|
palette?: readonly number[];
|
|
679
|
+
/**
|
|
680
|
+
* Storeys of each building, a number or `[min, max]` (the same name and shape as a city block's `building.floors`). Given, the height is storeys times the
|
|
681
|
+
* storey height of the use's preset instead of `minHeight..maxHeight`; the random draws are the same.
|
|
682
|
+
*/
|
|
683
|
+
floors?: number | readonly [number, number];
|
|
684
|
+
/** Share of the buildings by use (`commercial`, `residential`, ...); each building picks one (one more random draw). Needs no `floors`. */
|
|
685
|
+
uses?: Readonly<Record<string, number>>;
|
|
686
|
+
/** Which tower preset gives the storey height of a use. Default `{ commercial: 'office', residential: 'residential' }`. */
|
|
687
|
+
storeyPresets?: Readonly<Record<string, string>>;
|
|
688
|
+
/** The presets whose storey heights are used (default `DEFAULT_TOWER_PRESETS`; the kit passes its `towers.presets`). */
|
|
689
|
+
presets?: readonly TowerPreset[];
|
|
690
|
+
/** Storey height when no preset applies, metres. Default the residential preset's. */
|
|
691
|
+
storeyHeight?: number;
|
|
692
|
+
/** Draws each building (default `drawBuilding`): the kit passes its own to put towers on the tall lots. */
|
|
693
|
+
draw?: (b: UrbanBuilder, x: number, z: number, width: number, depth: number, height: number, color: number, options: BuildingOptions) => BlockBuilding;
|
|
602
694
|
};
|
|
603
695
|
/** A building a block ended up with, for the game's own bookkeeping (collisions, minimap). */
|
|
604
696
|
type BlockBuilding = {
|
|
@@ -612,7 +704,14 @@ type BlockBuilding = {
|
|
|
612
704
|
type BuildingOptions = {
|
|
613
705
|
lit?: number;
|
|
614
706
|
shop?: number;
|
|
615
|
-
|
|
707
|
+
/** Use of the building (`commercial`, `residential`...), when the block gave `uses`. */
|
|
708
|
+
use?: string;
|
|
709
|
+
/** Storeys of the building, when the block gave `floors`; the height is already storeys times the storey height. */
|
|
710
|
+
storeys?: number;
|
|
711
|
+
/** Id of the tower preset the use maps to; a tower drawer with that preset uses it instead of picking at random. */
|
|
712
|
+
preset?: string;
|
|
713
|
+
};
|
|
714
|
+
declare const DEFAULT_STOREY_PRESETS: Readonly<Record<string, string>>;
|
|
616
715
|
/** One city building: block, roof slab, maybe a vent on the roof, maybe a shop front on both long faces, windows on the four faces. Draws from the builder's random. */
|
|
617
716
|
declare function drawBuilding(b: UrbanBuilder, x: number, z: number, width: number, depth: number, height: number, color: number, options?: BuildingOptions): BlockBuilding;
|
|
618
717
|
/**
|
|
@@ -827,6 +926,202 @@ type ComposeOptions = {
|
|
|
827
926
|
};
|
|
828
927
|
type SilhouetteFactory = (request: HouseRequest, random: () => number) => Silhouette;
|
|
829
928
|
|
|
929
|
+
type DistrictKindText = {
|
|
930
|
+
name: string;
|
|
931
|
+
description: string;
|
|
932
|
+
};
|
|
933
|
+
/**
|
|
934
|
+
* A kind of district: what a patch of the city is. Numbers a game can change; the ids of `zone` and `pattern` point into other catalogues.
|
|
935
|
+
*/
|
|
936
|
+
type DistrictKindDef = {
|
|
937
|
+
id: string;
|
|
938
|
+
/** Colour on the map (css hex). */
|
|
939
|
+
color: string;
|
|
940
|
+
/** Id of a zone of `game-floorplan-residential` / `game-floorplan-commercial` (`zt`, `zc`, `zr1`, ...); null for ground that is not built. */
|
|
941
|
+
zone: string | null;
|
|
942
|
+
/** Id of a neighbourhood pattern of `urban.neighbourhoods` (or `financial_district` of `TOWER_PATTERNS`); null for ground that is not built. */
|
|
943
|
+
pattern: string | null;
|
|
944
|
+
/** Storeys of the buildings, `[min, max]`. */
|
|
945
|
+
floors: readonly [number, number];
|
|
946
|
+
/** Share of the buildings by use (`commercial`, `residential`, `industrial`, `institutional`, `agricultural`, ...). */
|
|
947
|
+
uses: Readonly<Record<string, number>>;
|
|
948
|
+
/** Size of a block in metres; 0 means the kind has no blocks. */
|
|
949
|
+
block: number;
|
|
950
|
+
text: Record<Locale, DistrictKindText>;
|
|
951
|
+
};
|
|
952
|
+
type PlanRect = readonly [x0: number, z0: number, x1: number, z1: number];
|
|
953
|
+
type PlanPoint = readonly [x: number, z: number];
|
|
954
|
+
type PlanDistrict = {
|
|
955
|
+
id: string;
|
|
956
|
+
/** Id of a `DistrictKindDef`. */
|
|
957
|
+
kind: string;
|
|
958
|
+
rect: PlanRect;
|
|
959
|
+
/** Replaces the name of the kind; a string or one string by locale. */
|
|
960
|
+
name?: string | Partial<Record<Locale, string>>;
|
|
961
|
+
/** Replaces the storeys of the kind. */
|
|
962
|
+
floors?: readonly [number, number];
|
|
963
|
+
/** Replaces the shares of use of the kind. */
|
|
964
|
+
uses?: Readonly<Record<string, number>>;
|
|
965
|
+
};
|
|
966
|
+
type PlanLine = {
|
|
967
|
+
id: string;
|
|
968
|
+
/** `avenue`, `street`, `highway`, `rail`, `river` or any string a drawer knows. */
|
|
969
|
+
kind: string;
|
|
970
|
+
width: number;
|
|
971
|
+
points: readonly PlanPoint[];
|
|
972
|
+
};
|
|
973
|
+
type PlanLandmark = {
|
|
974
|
+
kind: string;
|
|
975
|
+
at: PlanPoint;
|
|
976
|
+
name?: string | Partial<Record<Locale, string>>;
|
|
977
|
+
};
|
|
978
|
+
type CityScale = 'metropolis' | 'city' | 'town' | 'village' | (string & {});
|
|
979
|
+
/**
|
|
980
|
+
* A city plan: districts painted on a map of metres (centre 0,0; x east, z south), roads, rails and rivers, and landmarks.
|
|
981
|
+
* Districts are listed from the outer to the inner one: the LAST district that contains a point wins.
|
|
982
|
+
*/
|
|
983
|
+
type CityPlanDef = {
|
|
984
|
+
id: string;
|
|
985
|
+
scale: CityScale;
|
|
986
|
+
/** Width and depth of the map in metres. */
|
|
987
|
+
size: readonly [w: number, d: number];
|
|
988
|
+
text: Record<Locale, {
|
|
989
|
+
name: string;
|
|
990
|
+
description: string;
|
|
991
|
+
}>;
|
|
992
|
+
/** Id of another plan to start from: its districts, lines and landmarks come first; a district or line of the same id replaces, a new one appends. */
|
|
993
|
+
extends?: string;
|
|
994
|
+
districts: readonly PlanDistrict[];
|
|
995
|
+
lines: readonly PlanLine[];
|
|
996
|
+
landmarks: readonly PlanLandmark[];
|
|
997
|
+
};
|
|
998
|
+
/** A plan as a game writes it: with `extends`, everything but the id is optional and comes from the parent. */
|
|
999
|
+
type CityPlanInput = {
|
|
1000
|
+
id: string;
|
|
1001
|
+
extends?: string;
|
|
1002
|
+
} & Partial<Omit<CityPlanDef, 'id' | 'extends'>>;
|
|
1003
|
+
type BlockUse = {
|
|
1004
|
+
floors: readonly [number, number];
|
|
1005
|
+
uses: Readonly<Record<string, number>>;
|
|
1006
|
+
zone: string | null;
|
|
1007
|
+
pattern: string | null;
|
|
1008
|
+
};
|
|
1009
|
+
type ResolvedDistrict = {
|
|
1010
|
+
id: string;
|
|
1011
|
+
kind: string;
|
|
1012
|
+
rect: PlanRect;
|
|
1013
|
+
name: string;
|
|
1014
|
+
description: string;
|
|
1015
|
+
color: string;
|
|
1016
|
+
zone: string | null;
|
|
1017
|
+
pattern: string | null;
|
|
1018
|
+
/** Storeys after the district's override, clamped to `[0, maxFloors]`. */
|
|
1019
|
+
floors: readonly [number, number];
|
|
1020
|
+
uses: Readonly<Record<string, number>>;
|
|
1021
|
+
block: number;
|
|
1022
|
+
};
|
|
1023
|
+
/** A block of a district: its centre, its dimensions less the street, and the config a building generator takes. */
|
|
1024
|
+
type Block = {
|
|
1025
|
+
x: number;
|
|
1026
|
+
z: number;
|
|
1027
|
+
size: readonly [w: number, d: number];
|
|
1028
|
+
district: string;
|
|
1029
|
+
building: BlockUse;
|
|
1030
|
+
};
|
|
1031
|
+
type CityLayout = {
|
|
1032
|
+
id: string;
|
|
1033
|
+
scale: string;
|
|
1034
|
+
size: readonly [number, number];
|
|
1035
|
+
name: string;
|
|
1036
|
+
description: string;
|
|
1037
|
+
districts: ResolvedDistrict[];
|
|
1038
|
+
lines: PlanLine[];
|
|
1039
|
+
landmarks: (Omit<PlanLandmark, 'name'> & {
|
|
1040
|
+
name?: string;
|
|
1041
|
+
})[];
|
|
1042
|
+
/** The district at a point; the last one in the list that contains it. */
|
|
1043
|
+
districtAt(x: number, z: number): ResolvedDistrict | undefined;
|
|
1044
|
+
/** The grid of blocks of a district (by the kind's block size), less the cells another district was painted over. */
|
|
1045
|
+
blocks(districtId: string, options?: {
|
|
1046
|
+
street?: number;
|
|
1047
|
+
}): Block[];
|
|
1048
|
+
};
|
|
1049
|
+
type LayoutOptions = {
|
|
1050
|
+
maxFloors?: number;
|
|
1051
|
+
locale?: Locale;
|
|
1052
|
+
};
|
|
1053
|
+
type KindStats = {
|
|
1054
|
+
kind: string;
|
|
1055
|
+
area: number;
|
|
1056
|
+
share: number;
|
|
1057
|
+
districts: number;
|
|
1058
|
+
};
|
|
1059
|
+
type FillBlockCityOptions = Omit<FillBlockOptions, 'shop'> & {
|
|
1060
|
+
/** Chance of a ground-floor shop; default the commercial share of the block. */
|
|
1061
|
+
shop?: number;
|
|
1062
|
+
/** Which tower preset gives the storey height of a use: default `{ commercial: 'office', residential: 'residential' }`. */
|
|
1063
|
+
storeyPresets?: Readonly<Record<string, string>>;
|
|
1064
|
+
/** Storey height when no preset applies, metres. Default the residential preset's. */
|
|
1065
|
+
storeyHeight?: number;
|
|
1066
|
+
};
|
|
1067
|
+
|
|
1068
|
+
/** Highest storey count a district may have unless the game raises it. */
|
|
1069
|
+
declare const DEFAULT_MAX_FLOORS = 60;
|
|
1070
|
+
declare const DEFAULT_STREET = 10;
|
|
1071
|
+
type CitiesOptions = {
|
|
1072
|
+
/** Most storeys any district may have, applied on top of the kinds and the districts' own numbers. Default 60. */
|
|
1073
|
+
maxFloors?: number;
|
|
1074
|
+
packs?: {
|
|
1075
|
+
kinds?: readonly DistrictKindDef[];
|
|
1076
|
+
plans?: readonly CityPlanInput[];
|
|
1077
|
+
};
|
|
1078
|
+
patch?: {
|
|
1079
|
+
kinds?: Record<string, DeepPartial<DistrictKindDef>>;
|
|
1080
|
+
plans?: Record<string, DeepPartial<CityPlanInput>>;
|
|
1081
|
+
};
|
|
1082
|
+
remove?: {
|
|
1083
|
+
kinds?: readonly string[];
|
|
1084
|
+
plans?: readonly string[];
|
|
1085
|
+
};
|
|
1086
|
+
/** Tower presets of the kit (storey heights by use). */
|
|
1087
|
+
presets: readonly TowerPreset[];
|
|
1088
|
+
fill(b: UrbanBuilder, g: {
|
|
1089
|
+
cx: number;
|
|
1090
|
+
cz: number;
|
|
1091
|
+
size: number;
|
|
1092
|
+
minHeight: number;
|
|
1093
|
+
maxHeight: number;
|
|
1094
|
+
} & FillBlockOptions): BlockBuilding[];
|
|
1095
|
+
};
|
|
1096
|
+
/** City plans as data: district kinds and plans are registries; a plan resolves to a layout with the district at a point and the grid of blocks of a district. */
|
|
1097
|
+
declare function createCities(o: CitiesOptions): {
|
|
1098
|
+
maxFloors: number;
|
|
1099
|
+
kinds: {
|
|
1100
|
+
ids: () => string[];
|
|
1101
|
+
list: () => DistrictKindDef[];
|
|
1102
|
+
has: (id: string) => boolean;
|
|
1103
|
+
get(id: string): DistrictKindDef;
|
|
1104
|
+
};
|
|
1105
|
+
plans: {
|
|
1106
|
+
/** The plan with everything inherited from the plans it extends. */
|
|
1107
|
+
resolve: (id: string) => CityPlanDef;
|
|
1108
|
+
ids: () => string[];
|
|
1109
|
+
list: () => CityPlanInput[];
|
|
1110
|
+
has: (id: string) => boolean;
|
|
1111
|
+
get(id: string): CityPlanInput;
|
|
1112
|
+
};
|
|
1113
|
+
layout: (planOrId: string | CityPlanInput, options?: LayoutOptions) => CityLayout;
|
|
1114
|
+
stats: (l: CityLayout) => KindStats[];
|
|
1115
|
+
fillBlock: (b: UrbanBuilder, block: Block, options?: FillBlockCityOptions) => BlockBuilding[];
|
|
1116
|
+
};
|
|
1117
|
+
type Cities = ReturnType<typeof createCities>;
|
|
1118
|
+
|
|
1119
|
+
/** The district kinds of the city plans: colour on the map, zone of the floorplan packages, neighbourhood pattern, storeys, share of buildings by use and block size. */
|
|
1120
|
+
declare const DEFAULT_DISTRICT_KINDS: readonly DistrictKindDef[];
|
|
1121
|
+
|
|
1122
|
+
/** The six city plans (metropolis, regional city, port city, rail town, country town, mountain village). Districts are listed from the outer to the inner one. */
|
|
1123
|
+
declare const DEFAULT_CITY_PLANS: readonly CityPlanDef[];
|
|
1124
|
+
|
|
830
1125
|
type Origin = {
|
|
831
1126
|
x: number;
|
|
832
1127
|
z: number;
|
|
@@ -893,21 +1188,31 @@ type UrbanOptions = {
|
|
|
893
1188
|
packs?: {
|
|
894
1189
|
poles?: readonly PoleDef[];
|
|
895
1190
|
neighbourhoods?: readonly NeighbourhoodPattern<any>[];
|
|
1191
|
+
districtKinds?: readonly DistrictKindDef[];
|
|
1192
|
+
cityPlans?: readonly CityPlanInput[];
|
|
896
1193
|
};
|
|
897
1194
|
/** Numbers changed on shipped entries, by id (objects merge, arrays replace). */
|
|
898
1195
|
patch?: {
|
|
899
1196
|
poles?: Record<string, DeepPartial<PoleDef>>;
|
|
900
1197
|
neighbourhoods?: Record<string, DeepPartial<NeighbourhoodPattern<any>>>;
|
|
1198
|
+
districtKinds?: Record<string, DeepPartial<DistrictKindDef>>;
|
|
1199
|
+
cityPlans?: Record<string, DeepPartial<CityPlanInput>>;
|
|
901
1200
|
};
|
|
902
1201
|
/** Ids taken out of the catalogues. */
|
|
903
1202
|
remove?: {
|
|
904
1203
|
poles?: readonly string[];
|
|
905
1204
|
neighbourhoods?: readonly string[];
|
|
1205
|
+
districtKinds?: readonly string[];
|
|
1206
|
+
cityPlans?: readonly string[];
|
|
906
1207
|
};
|
|
907
1208
|
/** Shape builders for the poles a pack adds; the five of the Galeria are always there. */
|
|
908
1209
|
shapes?: Readonly<Record<string, PoleShapeBuilder>>;
|
|
909
1210
|
/** Composers for the patterns a pack adds; the ten of the Galeria are always there. */
|
|
910
1211
|
composers?: Readonly<Record<string, Composer>>;
|
|
1212
|
+
/** City plans (zoning): district kinds and plans are catalogues (`packs`, `patch` and `remove` above, under `districtKinds` and `cityPlans`). */
|
|
1213
|
+
cities?: {
|
|
1214
|
+
maxFloors?: number;
|
|
1215
|
+
};
|
|
911
1216
|
lights?: {
|
|
912
1217
|
budget?: number;
|
|
913
1218
|
};
|
|
@@ -915,6 +1220,11 @@ type UrbanOptions = {
|
|
|
915
1220
|
/** Facade colours of the city buildings. */
|
|
916
1221
|
facades?: readonly number[];
|
|
917
1222
|
props?: Partial<PropColors>;
|
|
1223
|
+
/**
|
|
1224
|
+
* Towers on the tall lots, off by default. `true` or an object turns them on: a building of the block or of an avenue at least `minHeight` (60 m) tall is drawn as
|
|
1225
|
+
* a tower of one of the `presets` (the office and residential typologies), not as a box; a `provider` replaces the drawing. See `TowerOptions`.
|
|
1226
|
+
*/
|
|
1227
|
+
towers?: boolean | TowerOptions;
|
|
918
1228
|
};
|
|
919
1229
|
type Pole = {
|
|
920
1230
|
readonly def: PoleDef;
|
|
@@ -935,6 +1245,25 @@ declare function createUrban(options?: UrbanOptions): {
|
|
|
935
1245
|
list: () => PoleDef[];
|
|
936
1246
|
get(id: string): Pole;
|
|
937
1247
|
};
|
|
1248
|
+
cities: {
|
|
1249
|
+
maxFloors: number;
|
|
1250
|
+
kinds: {
|
|
1251
|
+
ids: () => string[];
|
|
1252
|
+
list: () => DistrictKindDef[];
|
|
1253
|
+
has: (id: string) => boolean;
|
|
1254
|
+
get(id: string): DistrictKindDef;
|
|
1255
|
+
};
|
|
1256
|
+
plans: {
|
|
1257
|
+
resolve: (id: string) => CityPlanDef;
|
|
1258
|
+
ids: () => string[];
|
|
1259
|
+
list: () => CityPlanInput[];
|
|
1260
|
+
has: (id: string) => boolean;
|
|
1261
|
+
get(id: string): CityPlanInput;
|
|
1262
|
+
};
|
|
1263
|
+
layout: (planOrId: string | CityPlanInput, options?: LayoutOptions) => CityLayout;
|
|
1264
|
+
stats: (l: CityLayout) => KindStats[];
|
|
1265
|
+
fillBlock: (b: UrbanBuilder, block: Block, options?: FillBlockCityOptions) => BlockBuilding[];
|
|
1266
|
+
};
|
|
938
1267
|
builder: (o?: BuilderOptions) => UrbanBuilder;
|
|
939
1268
|
neighbourhoods: {
|
|
940
1269
|
ids: () => string[];
|
|
@@ -964,6 +1293,10 @@ declare function createUrban(options?: UrbanOptions): {
|
|
|
964
1293
|
};
|
|
965
1294
|
terrain: (o: TerrainOptions) => Terrain;
|
|
966
1295
|
drawTerrain: typeof drawTerrain;
|
|
1296
|
+
towers: {
|
|
1297
|
+
enabled: boolean;
|
|
1298
|
+
options: TowerOptions | null;
|
|
1299
|
+
};
|
|
967
1300
|
streets: {
|
|
968
1301
|
road(b: UrbanBuilder, x: number, z: number, w: number, l: number, along: "x" | "z"): void;
|
|
969
1302
|
walk(b: UrbanBuilder, x: number, z: number, w: number, d: number): void;
|
|
@@ -1425,4 +1758,12 @@ declare const SAMPLE_CELLS: Readonly<Record<string, {
|
|
|
1425
1758
|
z: number;
|
|
1426
1759
|
}>>;
|
|
1427
1760
|
|
|
1428
|
-
|
|
1761
|
+
/** The patterns of the tower pack. */
|
|
1762
|
+
declare const TOWER_PATTERNS: readonly NeighbourhoodPattern<any>[];
|
|
1763
|
+
/** Where the sample sheet puts them (pass it as `cells`). */
|
|
1764
|
+
declare const TOWER_SAMPLE_CELLS: Readonly<Record<string, {
|
|
1765
|
+
x: number;
|
|
1766
|
+
z: number;
|
|
1767
|
+
}>>;
|
|
1768
|
+
|
|
1769
|
+
export { type BarSpec, type Block, type BlockBuilding, type BlockUse, type BuilderOptions, type BuildingOptions, COMPOSERS, type Cities, type CitiesOptions, type CityLayout, type CityPlanDef, type CityPlanInput, type CityScale, type ColorRule, type ComposeContext, type ComposeOptions, type Composer, type ConePart, type CrossarmSpec, type CrownPart, DEFAULT_CITY_PLANS, DEFAULT_DISTRICT_KINDS, DEFAULT_FACADES, DEFAULT_LIGHT_BUDGET, DEFAULT_MAX_FLOORS, DEFAULT_PATTERNS, DEFAULT_PLANT_CONTEXTS, DEFAULT_POLES, DEFAULT_PROP_COLORS, DEFAULT_ROAD_STYLE, DEFAULT_STOREY_PRESETS, DEFAULT_STREET, DEFAULT_TOWER_PRESETS, DEFAULT_URBAN_SEED, DEFAULT_WALK_STYLE, type DistrictKindDef, type DistrictKindText, type DoubleArmSpec, type DowntownParams, type FillBlockCityOptions, type FillBlockOptions, type Flatten, type FloodTowerSpec, type ForestOptions, type HistoricParams, type HouseProvider, type HouseRequest, type IndustrialParams, type ItemBox, type KindStats, type LabelPart, type Lake, type LampLightSpec, type LampSpec, type LanternSpec, type LayoutOptions, type LensSpec, type LightBudget, type LightPart, type Locale, type MastSpec, type MilitaryParams, type MountainParams, type NeighbourhoodPattern, type Origin, PARKED_VEHICLE_IDS, POLE_SHAPES, type PartStyle, type PatternText, type PlacementPart, type PlanDistrict, type PlanLandmark, type PlanLine, type PlanPoint, type PlanRect, type PlanePart, type PlantProvider, type PlantProviderOptions, type PlantRequest, type Point, type Pole, type PoleDef, type PoleOptions, type PoleShapeBuilder, type PropColors, type Providers, type RailwayParams, type Ramp, type Rect, type ResolvedDistrict, type River, type RiverBed, type RoadStyle, type RuralParams, SAMPLE_CELLS, SILHOUETTE_TYPOLOGIES, type SampleSheetOptions, type SilhouetteFactory, type SingleArmSpec, type StiltParams, type StreetOptions, type SuburbParams, TOWER_DEFAULTS, TOWER_PATTERNS, TOWER_SAMPLE_CELLS, type Terrain, type TerrainGrid, type TerrainLayer, type TerrainOptions, type TerrainPart, type TowerOptions, type TowerPreset, type TowerProvider, type TowerRequest, type Trig, type UrbanBuilder, type UrbanBuilderOptions, type UrbanKit, type UrbanKitCore, type UrbanOptions, type UrbanPart, type UrbanPlan, type UrbanScene, type VaultPart, type VehicleProvider, type VehicleProviderOptions, type VehicleRequest, type WalkStyle, type Wave, type WorkingClassParams, type WorldFrame, clamp, composePattern, createCities, createLightBudget, createPlantProvider, createSilhouetteHouses, createTerrain, createTowerDrawer, createUrban, createUrbanBuilder, createVehicleProvider, distanceToPolyline, drawBuilding, drawContainer, drawFence, drawGround, drawPine, drawRoad, drawSandbags, drawStreetGrid, drawStripLabel, drawTent, drawTerrain, drawTower, drawTree, drawWalk, drawWatchtower, drawWires, fillBlock, hash2, insideEllipse, insideRect, lerp, patternMarker, pickTowerPreset, smoothstep, towerPresetOf, towerStoreys };
|