CarbonEngineJS-facing reader for Carbon .black binary data. It consumes
canonical Black schema metadata and emits compact public Black payload JSON
by default.
The package does not import @carbonenginejs/format-carbon at runtime. Schema
JSON produced by format-carbon can be passed in as data, which keeps
format-black focused on reading binary payloads.
CarbonEngine and Fenris Creations (CCP Games) are named in this package for
interoperability and schema-provenance context only. The Black format behavior
was informed by the MIT-licensed rawrafox/black-reader-js project by
rawrafox; see NOTICE for attribution. This package is not affiliated with or
endorsed by CCP Games.
- package:
@carbonenginejs/format-black - version:
0.1.2 - license:
MIT - runtime: Node
>=18, modern ESM runtimes - module: ESM, package root exports
CjsFormatBLACK - dependency:
@carbonenginejs/core-types
npm install @carbonenginejs/format-blackThe package root exports one public class: CjsFormatBLACK. The Cjs prefix
marks this as a CarbonEngineJS format/construction boundary, not an engine
runtime class.
import CjsFormatBLACK from "@carbonenginejs/format-black";
const black = new CjsFormatBLACK({
emit: "json", // "json" (default) | "payload" | "runtime" | "document" | "raw"
schema: blackSchema, // format-carbon bundle, class schema, or black-only shape map
rootFields: ["generic", "hull"]
});
const payload = black.Read(dataBlackBytes);
const summary = black.Inspect(dataBlackBytes);
const text = JSON.stringify(black.ToJSON(payload));The named export is the same class for callers that prefer named imports:
import { CjsFormatBLACK } from "@carbonenginejs/format-black";Static one-shot methods are also available:
const payload = CjsFormatBLACK.readPayload(bytes, { schema });
const document = CjsFormatBLACK.readDocument(bytes, { schema });
const runtime = CjsFormatBLACK.readRuntime(bytes, { schema, registry });Runtime reads can construct caller-supplied classes. The classes map is keyed
by Black/Carbon class name; constructors are called with no arguments and then
payload fields are assigned by public Black property name.
import CjsFormatBLACK from "@carbonenginejs/format-black";
import blackSchema from "@carbonenginejs/format-black/schema";
class EveSOFData
{
constructor()
{
this.generic = null;
this.hull = [];
}
}
class EveSOFDataHull
{
constructor()
{
this.name = "";
this.geometryResFilePath = "";
}
}
const { root } = CjsFormatBLACK.readRuntime(dataBlackBytes, {
schema: blackSchema,
classes: {
EveSOFData,
EveSOFDataHull
}
});
console.log(root instanceof EveSOFData);
console.log(root.hull[0] instanceof EveSOFDataHull);Large runtime libraries can provide the same constructors through registry
instead of passing a local classes map.
- The package root exports one public format class:
CjsFormatBLACK. - Instance methods are PascalCase because format instances can hydrate or sit beside CarbonClasses without colliding with camelCase data fields.
- Static one-shot methods are camelCase because they live on
CjsFormatBLACKitself, not on hydrated CarbonClass instances. src/CjsFormatBLACK.jsis the public format boundary. Binary parsing, Black property readers, and schema adaptation live undersrc/core.Read/ staticreadreturn the public payload surface by default.ReadPayload/ staticreadPayloadare explicit aliases for the default compact payload output.ReadDocument/ staticreadDocumentreturn a neutralCjsCarbonDocumentgraph for diagnostics and trace/debug work.ReadRuntime/ staticreadRuntimehydrate registered runtime classes when callers provide a registry, otherwise plain source-shaped objects are used.Inspect/ staticinspectvalidates the Black header and reports string table metadata without reading the object graph.ToJSON/ statictoJSONconverts typed arrays and class instances to JSON-compatible data. It is not a.blackwriter and does not return JSON text.
The generated Black definitions are owned by @carbonenginejs/format-carbon.
This package imports that canonical output and re-exports its class map through
@carbonenginejs/format-black/schema; it stores no generated schema folder.
The canonical class map is the default reader schema; pass schema: null only
for an intentional schema-less read.
import blackSchema from "@carbonenginejs/format-black/schema";
import blackEnums from "@carbonenginejs/format-black/enums";
import blackVersion from "@carbonenginejs/format-black/version";
import { definitions as blackDefinitions } from "@carbonenginejs/format-carbon/definitions/black";
const sofData = blackSchema.EveSOFData;
const buildClass = blackEnums.BuildClass;
const formatVersion = blackVersion.version;
const sourceDate = blackDefinitions.generatedAt;Tooling that needs the complete bundle or dated JSON imports it from
@carbonenginejs/format-carbon/definitions/black.
schema may be any of these shapes:
- a format-carbon schema bundle
- a generated format-black Black definition class map
- a format-carbon family document
- a format-carbon class schema
- a map/object of class schemas
- a black-only source-shape map
Generated Black definitions are a single schema bundle with version metadata,
enum maps, and a class map. Each classes property is a Black class name, and
the value is that class's compact field map. Ordinary fields are just
property-name to reader-type pairs:
{
"schema": "carbonenginejs.blackDefinitions",
"version": 1,
"generatedAt": "2026-07-11T14:52:36.015Z",
"enums": {},
"classes": {
"EveSOFDataHull": {
"name": "string",
"geometryResFilePath": "path",
"boundingSphere": "vector4",
"hull": "array"
}
}
}Fields that need enum or chooser/index metadata use a small object:
{
"Primary": {
"type": "color",
"field": "colors",
"index": "primary",
"token": "SOFDataFactionColorChooser::TYPE_PRIMARY"
}
}enums contains enum name-to-value maps. Generated class-map entries only exist
for classes with exposed Black fields; empty objects do not need class
definitions to be read.
Canonical format-carbon class schemas may still use the role map:
{ "name": "name fieldName", "m_name": "cppName member memberPath memberRoot" }The fieldName role is the public payload property name. The reader accepts
name, fieldName, member, memberPath, memberRoot, cppName, and
nameExpression as wire-name matches.
Manual type decoration can be supplied with jsType. Expression string fields,
for example, can be marked as:
{ "jsType": { "kind": "expression", "js": "string" } }Payload reads return:
{
comments: [],
object: {
_type: "EveSOFData",
generic: {},
hull: []
}
}Repeated Black object references emit { _reference: id }; the first emitted
target gains _id lazily when it is referenced. The reference field names can
be changed with payload options.
rootFields or payloadRootFields materializes only selected root payload
fields while safely skipping the rest of the stream. This is intended for large
files such as SOF data.black, where consumers may want generic, hull, or
another top-level section independently.
emit:"json"default."json"and"payload"return public payloads;"runtime"returns runtime read results;"document"and"raw"return a neutral document graph.schema: canonical schema data used to resolve Black fields to public names.registry: optional generated runtime registry withGetSourceShapeand/or constructor lookup helpers.sourceShapes: optional source-shape map or registry-like object.rootFields/payloadRootFields: optional root-level payload field slice.payloadTypeField: default"_type". Set tofalseto omit type markers.payloadIdField: default"_id". Set tofalseto omit lazy id markers.payloadReferenceField: default"_reference". Set tofalseto reuse the original object instead of emitting reference stubs.pathHandler: optional function for path normalization. Ordinary strings and expression strings are not passed through this hook.decodeBinaryBlocks: defaultfalsefor document reads. Runtime and payload reads decode recognized SOFindexBufferbinary blocks asUint32Array.trace/debug/includeMetadata/includeFieldTrace/includeClassMetadata/includeRefIndex: diagnostic metadata controls.captureUnknownBlackFields,captureUnknownResourceFields,captureUnknownWhenNoBlackFields,allowUnknownStringFallback: escape hatches for schema gaps while definitions are being cleaned.classes: optional constructor map keyed by Black class name forReadRuntime/readRuntimeoutput.
npm test
npm run lint