Bell 230 (N230H) corresponding source - GTLA, 2026-09-26

This is the source for the helicopter model GTLA shows for N230H, a privately
owned Bell 230. It holds what you need to build the published model again, and
to change it.

WHERE IT COMES FROM. The model is adapted from the FlightGear UK (FGUK) Bell 430:
https://sites.google.com/view/fgukhangar/flightgear-uk-home-page/hangar/rotary-wing/bell-430
Its authors, as named in Bell-430-set.xml: StuartC (model, plus flight model
changes), Maik Justus (flight model) and Garry Brown (paint), with the FGUK
contributors. We downloaded the FGUK archive, bell430.zip, on 2026-09-14
(SHA-256 7ceca5c3863c5c3053ad5a31c6642849a29781e5b033a6d251423d9f6c096f58);
outputs/N230H-Bell230/source-provenance.json records where from. See AUTHORS.

LICENCE. Bell-430-set.xml declares the aircraft "GPL v2" and names no later
version. GTLA's adaptation (the geometry changes, the new rotor, the livery and
the rotor animation) is distributed on the same terms: the GNU General Public
License, version 2 only. The FGUK archive carries no licence text of its own,
so COPYING is the verbatim GPL version 2 text as the Free Software Foundation
publishes it. No warranty. Names and registrations identify the aircraft shown
and imply no endorsement.

WHAT THE BUILD READS FROM UPSTREAM. One AC3D model file and the six images it
names. They are included unchanged, with the aircraft's set file, under
outputs/Bell430-family/source/FlightGear/bell430/:
  Models/bell430b.ac
  Models/Exterior.jpg
  Models/Exterior2.jpg
  Models/Misc.jpg
  Models/Misc3.jpg
  Models/interior.jpg
  Models/panel.jpg
  Bell-430-set.xml
ac_reader.py reads bell430b.ac as plain data. No FlightGear script is run.
build.py uses Misc.jpg, Misc3.jpg, interior.jpg and panel.jpg for the parts it
keeps in their original finish. Exterior.jpg and Exterior2.jpg are the Bell
430's own paint; our livery replaces it, so the build never opens them, but
they are included so bell430b.ac comes with every image it names.
Bell-430-set.xml is included because it names the authors and the licence.
The rest of the FGUK aircraft (the four-blade rotor files, flight model,
scripts, sounds, cockpit, other liveries) is flight-simulator material this
conversion never reads; it is available from the FGUK page above.

WHAT GTLA CHANGED. The Bell 430 is a longer, four-blade development of the
Bell 230. Every change is in code, with no hand edits:
  - build.py shortens the cabin by 0.4572 m (18 inches) ahead of the engine
    deck. The squeeze is spread smoothly over a 0.65 m band, so the engine
    deck, tail boom and rotor mast stay put and every panel and window edge
    still meets its neighbour.
  - build.py fills the narrow cabin window only the 430 has: those glass
    faces are painted as body instead.
  - rotor230.py builds a new two-blade main rotor and hub (spindle,
    crosshead, blade grips, pitch links and two broad blades, 12.8 m across).
    The 430's four-blade rotor files are not used.
  - build.py resizes the 430's own tail rotor to 2.1 m across, paints it with
    tail-blades.png; leaves out the three wheel-gear parts, a tail cable, the
    simulator's rotor blur discs and duplicated inner glass; and adds skids,
    cross tubes, boarding steps, dark smoked glazing, a red tail beacon and
    navigation lights.
  - paint.py draws the N230H livery: metallic blue with white and red swept
    stripes and the registration on the tail boom (textures/port.png and
    starboard.png, plain versions port-base.png and starboard-base.png for
    faces that do not look sideways, and tail-blades.png).
  - finalize.mjs adds the rotor and beacon animation, sizes the textures,
    compresses, validates, and writes the standard, HD and phone files.

LAYOUT. Paths are the ones the scripts expect, from this archive's root:
  outputs/Bell430-family/source/...      the upstream files above
  outputs/N230H-Bell230/ac_reader.py     reads AC3D files as data
  outputs/N230H-Bell230/paint.py         draws the livery images
  outputs/N230H-Bell230/build.py         Blender: imports the Bell 430,
                                         turns it into the Bell 230, paints it
                                         and writes exports/raw.glb
  outputs/N230H-Bell230/rotor230.py      the new main rotor (build.py runs it)
  outputs/N230H-Bell230/finalize.mjs     animation, compression, validation;
                                         writes the three sizes
  outputs/N230H-Bell230/verify.mjs       checks blades, pivots, animation and
                                         identity, and writes GTLA's map
                                         settings (wiring.json)
  outputs/N230H-Bell230/resolver-audit.json, feed-evidence.json
                                         verify.mjs's other inputs: how GTLA's
                                         map drew N230H before this model, and
                                         saved live-feed sightings (none)
  outputs/N230H-Bell230/package-source.py  the script that made this archive
  outputs/N230H-Bell230/source-provenance.json  where the upstream came from
  outputs/N230H-Bell230/aircraft/N230H/  config.json (see PACKED SETTINGS
                                         FILE below), geometry-build.json,
                                         references/faa-n230h.txt (the FAA
                                         registry record), and textures/, the
                                         livery images we drew
  data/rotorcraft-roster.json            N230H's registration and Mode S code
  package.json                           the Node packages and versions used

REBUILD. You need Blender 5.2, Python 3 with Pillow (paint.py only), and
Node 22 or later. We built with Blender 5.2.0 (build.py also uses Blender's own
bpy and mathutils). From this archive's root:
  npm install
  python3 outputs/N230H-Bell230/paint.py      (optional: redraws the livery)
  blender --background --factory-startup --disable-autoexec --python outputs/N230H-Bell230/build.py -- N230H
  node outputs/N230H-Bell230/finalize.mjs N230H
  node outputs/N230H-Bell230/verify.mjs N230H  (optional: checks the result)
build.py writes aircraft/N230H/exports/raw.glb, a Blender file
(aircraft/N230H/N230H.blend), geometry-build.json and four review pictures.
finalize.mjs writes exports/N230H-standard.glb, N230H-hd.glb and
N230H-mobile.glb and records their checksums in config.json. verify.mjs
checks them.

WHY THERE IS NO BLENDER FILE. build.py starts from an empty scene and saves
N230H.blend as one of its outputs; nothing in the build reads it back. It
holds nothing that build.py and the files here do not make, so build.py is the
form to edit, and the .blend is left out.

CHECKED. On 2026-09-26 we unpacked this archive into an empty folder, with
no Blender file anywhere, and rebuilt from it alone with the commands above
(Blender 5.2.0, Python 3.14 with Pillow 12.3, Node 24). paint.py redrew all
five livery images byte for byte. In the rebuilt standard, HD and phone files
every texture, the animation and every mesh matched the published copies
except three small ones: the red tail beacon and the two navigation lights.
Their triangles came out the same, but Blender listed them in a different
order, so their compressed bytes differ. Blender does that on its own from run
to run: two rebuilds on the same machine from the same files differed from
each other in the same three places. Run on our own 2026-09-26 Blender export,
finalize.mjs reproduces the published files byte for byte (before stamping),
and verify.mjs passes on the rebuilt files.

FONT. paint.py uses Arial Narrow Bold from /System/Library/Fonts/Supplemental/,
a proprietary macOS font that is not included. Use any font you have in its
place, or skip paint.py and build with the livery images already in
aircraft/N230H/textures/.

IDENTITY CHECKS. build.py, finalize.mjs and verify.mjs check the saved FAA
registry record for N230H by SHA-256 before they run (build.py also looks for
the model, serial number and Mode S code in it), so it is included. build.py
and verify.mjs also check the Mode S code against GTLA's aircraft list;
data/rotorcraft-roster.json is that list cut to N230H's registration and code.

PACKED SETTINGS FILE. config.json here is a copy of our own with our internal
review notes taken out: the records of the go-ahead for the HD file and for
adding the aircraft to our list (both quote the site owner), the bookkeeping
for that addition (including a copy of the list entry), flags recording
whether production files had changed and whether the Blender file could be
kept in version history, the review-stage build status, and the list of
identity references we rejected; the words "owner-approved" are also taken
out of identityBasis. Those notes were about our review, not the model. None
of the scripts here reads them, and package-source.py refuses to pack if one
ever does, so the build works exactly as before. Every setting the scripts
read is the same as in our build inputs, and our build inputs themselves are
unchanged.

NOT INCLUDED: reference photographs and our notes on them, the proprietary
font, the Blender file (see above), raw exports, review pictures and pages,
logs, our review reports, and the parts of the FlightGear aircraft this
conversion never reads. The downloaded FGUK archive itself is not repeated;
the files the build uses are included unchanged.

PUBLISHED FILES. The finished models are not repeated here. They are served at
  https://gtla.live/models/n230h.glb            standard
  https://gtla.live/models/n230h-hd.glb         HD
  https://gtla.live/models/mobile/n230h.glb     phones
SHA256SUMS-published.txt lists the checksums of the files as served. Those
copies carry an attribution and provenance stamp in the JSON part of the file
only. MODEL-BIN-CHUNK-SHA256.txt lists the checksum of each file's binary part
(the geometry, textures and animation), which the stamp never changes. A
rebuild matches everything in it except the triangle order of the beacon and
the two navigation lights (see CHECKED), so compare mesh by mesh rather than
expecting the same checksum.

SHA256SUMS lists every other file in this archive.
