2021-07-24 18:00:42 +00:00
|
|
|
import * as avro from "avro-js";
|
|
|
|
import { CreatureDesign } from "./core";
|
2021-08-15 18:41:05 +00:00
|
|
|
import {
|
|
|
|
AvroAttachedCreatureSymbol,
|
|
|
|
AvroCreatureDesign,
|
|
|
|
AvroCreatureSymbol,
|
|
|
|
AvroNestedCreatureSymbol,
|
|
|
|
} from "./creature-design.avsc";
|
2021-07-24 18:00:42 +00:00
|
|
|
import { fromBase64, toBase64 } from "../../base64";
|
|
|
|
import CreatureAvsc from "./creature-design.avsc.json";
|
|
|
|
import { Packer, SvgCompositionContextPacker } from "../../serialization";
|
2021-08-15 18:41:05 +00:00
|
|
|
import {
|
|
|
|
AttachedCreatureSymbol,
|
|
|
|
CreatureSymbol,
|
|
|
|
NestedCreatureSymbol,
|
|
|
|
} from "../../creature-symbol";
|
|
|
|
import { SvgVocabulary } from "../../svg-vocabulary";
|
|
|
|
import { ATTACHMENT_POINT_TYPES } from "../../specs";
|
2021-07-24 18:00:42 +00:00
|
|
|
|
2021-08-15 18:41:05 +00:00
|
|
|
const LATEST_VERSION = "v2";
|
2021-07-24 18:00:42 +00:00
|
|
|
|
|
|
|
const avroCreatureDesign = avro.parse<AvroCreatureDesign>(CreatureAvsc);
|
|
|
|
|
2021-08-15 18:41:05 +00:00
|
|
|
const ATTACHMENT_POINT_MAPPING = new Map(
|
|
|
|
ATTACHMENT_POINT_TYPES.map((name, i) => {
|
|
|
|
return [name, i];
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
const NestedCreatureSymbolPacker: Packer<
|
|
|
|
NestedCreatureSymbol,
|
|
|
|
AvroNestedCreatureSymbol
|
|
|
|
> = {
|
|
|
|
pack: (value) => {
|
|
|
|
return {
|
|
|
|
base: CreatureSymbolPacker.pack(value),
|
|
|
|
indices: Buffer.from(value.indices),
|
|
|
|
};
|
|
|
|
},
|
|
|
|
unpack: (value) => {
|
|
|
|
return {
|
|
|
|
...CreatureSymbolPacker.unpack(value.base),
|
|
|
|
indices: Array.from(value.indices),
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const AttachedCreatureSymbolPacker: Packer<
|
|
|
|
AttachedCreatureSymbol,
|
|
|
|
AvroAttachedCreatureSymbol
|
|
|
|
> = {
|
|
|
|
pack: (value) => {
|
|
|
|
const attachTo = ATTACHMENT_POINT_MAPPING.get(value.attachTo);
|
|
|
|
if (attachTo === undefined) {
|
|
|
|
throw new Error(`Invalid attachment type "${value.attachTo}"`);
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
base: CreatureSymbolPacker.pack(value),
|
|
|
|
attachTo,
|
|
|
|
indices: Buffer.from(value.indices),
|
|
|
|
};
|
|
|
|
},
|
|
|
|
unpack: (value) => {
|
|
|
|
const attachTo = ATTACHMENT_POINT_TYPES[value.attachTo];
|
|
|
|
if (attachTo === undefined) {
|
|
|
|
throw new Error(`Invalid attachment type "${value.attachTo}"`);
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
...CreatureSymbolPacker.unpack(value.base),
|
|
|
|
attachTo,
|
|
|
|
indices: Array.from(value.indices),
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const CreatureSymbolPacker: Packer<CreatureSymbol, AvroCreatureSymbol> = {
|
2021-07-24 18:00:42 +00:00
|
|
|
pack: (value) => {
|
|
|
|
return {
|
|
|
|
...value,
|
2021-08-15 18:41:05 +00:00
|
|
|
symbol: value.data.name,
|
|
|
|
attachments: value.attachments.map(AttachedCreatureSymbolPacker.pack),
|
|
|
|
nests: value.nests.map(NestedCreatureSymbolPacker.pack),
|
2021-07-24 18:00:42 +00:00
|
|
|
};
|
|
|
|
},
|
|
|
|
unpack: (value) => {
|
|
|
|
return {
|
|
|
|
...value,
|
2021-08-15 18:41:05 +00:00
|
|
|
data: SvgVocabulary.get(value.symbol),
|
|
|
|
attachments: value.attachments.map(AttachedCreatureSymbolPacker.unpack),
|
|
|
|
nests: value.nests.map(NestedCreatureSymbolPacker.unpack),
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const DesignConfigPacker: Packer<CreatureDesign, AvroCreatureDesign> = {
|
|
|
|
pack: (value) => {
|
|
|
|
return {
|
|
|
|
creature: CreatureSymbolPacker.pack(value.creature),
|
|
|
|
compCtx: SvgCompositionContextPacker.pack(value.compCtx),
|
|
|
|
};
|
|
|
|
},
|
|
|
|
unpack: (value) => {
|
|
|
|
return {
|
|
|
|
creature: CreatureSymbolPacker.unpack(value.creature),
|
2021-07-24 18:00:42 +00:00
|
|
|
compCtx: SvgCompositionContextPacker.unpack(value.compCtx),
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
export function serializeCreatureDesign(value: CreatureDesign): string {
|
|
|
|
const buf = avroCreatureDesign.toBuffer(DesignConfigPacker.pack(value));
|
|
|
|
return `${LATEST_VERSION}.${toBase64(buf)}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function deserializeCreatureDesign(value: string): CreatureDesign {
|
2021-08-15 18:41:05 +00:00
|
|
|
const [version, serialized] = value.split(".", 2);
|
|
|
|
if (version === "v1") {
|
|
|
|
throw new Error(`Sorry, we no longer support loading v1 creatures!`);
|
|
|
|
}
|
2021-07-24 18:00:42 +00:00
|
|
|
const buf = fromBase64(serialized);
|
|
|
|
return DesignConfigPacker.unpack(avroCreatureDesign.fromBuffer(buf));
|
|
|
|
}
|