UNPKG

@tamgl/colyseus-schema

Version:

Binary state serializer with delta encoding for games

194 lines (189 loc) 6.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generate = generate; const types_1 = require("../types"); const typeMaps = { "string": "string", "number": "float", "boolean": "bool", "int8": "sbyte", "uint8": "byte", "int16": "short", "uint16": "ushort", "int32": "int", "uint32": "uint", "int64": "long", "uint64": "ulong", "float32": "float", "float64": "double", }; /** * C# Code Generator */ const capitalize = (s) => { if (typeof s !== 'string') return ''; return s.charAt(0).toUpperCase() + s.slice(1); }; function generate(context, options) { // enrich typeMaps with enums context.enums.forEach((structure) => { typeMaps[structure.name] = structure.name; }); return [ ...context.classes.map(structure => ({ name: `${structure.name}.cs`, content: generateClass(structure, options.namespace) })), ...context.interfaces.map(structure => ({ name: `${structure.name}.cs`, content: generateInterface(structure, options.namespace, options.using), })), ...context.enums.filter(structure => structure.name !== 'OPERATION').map((structure) => ({ name: `${structure.name}.cs`, content: generateEnum(structure, options.namespace), })), ]; } function generateClass(klass, namespace) { const indent = (namespace) ? "\t" : ""; return `${(0, types_1.getCommentHeader)()} using Colyseus.Schema; using UnityEngine.Scripting; ${namespace ? `\nnamespace ${namespace} {` : ""} ${indent}public partial class ${klass.name} : ${klass.extends} { ${indent}\t[Preserve] ${indent}\tpublic ${klass.name}() { } ${klass.properties.map((prop) => generateProperty(prop, indent)).join("\n\n")} ${indent}} ${namespace ? "}" : ""} `; } function generateEnum(_enum, namespace) { const indent = namespace ? "\t" : ""; if (_enum.name.endsWith('Enum')) { return `${(0, types_1.getCommentHeader)()} ${namespace ? `\nnamespace ${namespace} {` : ""} ${indent}public enum ${_enum.name} : int { ${_enum.properties .map((prop) => { let dataType = "int"; let value; if (prop.type) { if (isNaN(Number(prop.type))) { value = `"${prop.type}"`; dataType = "string"; } else { value = Number(prop.type); dataType = Number.isInteger(value) ? 'int' : 'float'; } } else { value = _enum.properties.indexOf(prop); } return `${indent}\t${prop.name} = ${value},`; }) .join("\n")} ${indent}} ${namespace ? "}" : ""}`; } return `${(0, types_1.getCommentHeader)()} ${namespace ? `\nnamespace ${namespace} {` : ""} ${indent}public struct ${_enum.name} { ${_enum.properties .map((prop) => { let dataType = "int"; let value; if (prop.type) { if (isNaN(Number(prop.type))) { value = `"${prop.type}"`; dataType = "string"; } else { value = Number(prop.type); dataType = Number.isInteger(value) ? 'int' : 'float'; } } else { value = _enum.properties.indexOf(prop); } return `${indent}\tpublic const ${dataType} ${prop.name} = ${value};`; }) .join("\n")} ${indent}} ${namespace ? "}" : ""}`; } function generateProperty(prop, indent = "") { let typeArgs = `"${prop.type}"`; let property = "public"; let langType; let initializer = ""; if (prop.childType) { const isUpcaseFirst = prop.childType.match(/^[A-Z]/); langType = getType(prop); typeArgs += `, typeof(${langType})`; if (!isUpcaseFirst) { typeArgs += `, "${prop.childType}"`; } initializer = `new()`; } else { langType = getType(prop); initializer = `default`; } property += ` ${langType} ${prop.name}`; let ret = (prop.deprecated) ? `\t\t[System.Obsolete("field '${prop.name}' is deprecated.", true)]\n` : ''; return ret + `\t${indent}[Type(${prop.index}, ${typeArgs})] \t${indent}${property} = ${initializer};`; } function generateInterface(struct, namespace, using) { const indent = (namespace) ? "\t" : ""; return `${(0, types_1.getCommentHeader)()} using MessagePack; ${using ? `using ${using};` : ""} ${namespace ? `\nnamespace ${namespace} {` : ""} ${indent}[MessagePackObject(keyAsPropertyName: true)] ${indent}public class ${struct.name} { ${struct.properties.map(prop => `\t${indent}public ${getTypeForInterface(prop)} ${prop.name};`).join("\n")} ${indent}} ${namespace ? "}" : ""} `; } function getTypeForInterface(prop) { let langType = getType(prop); if (langType.startsWith('ArraySchema<')) { langType = `${typeMaps[prop.childType] || prop.childType}[]`; } return langType; } function getChildType(prop) { return typeMaps[prop.childType]; } function getType(prop) { if (prop.enumType) { return prop.enumType; } else if (prop.childType) { const isUpcaseFirst = prop.childType.match(/^[A-Z]/); let type; if (prop.type === "ref") { type = (isUpcaseFirst) ? prop.childType : getChildType(prop); } else { const containerClass = capitalize(prop.type); type = (isUpcaseFirst) ? `${containerClass}Schema<${prop.childType}>` : `${containerClass}Schema<${getChildType(prop)}>`; } return type; } else { return (prop.type === "array") ? `${typeMaps[prop.childType] || prop.childType}[]` : typeMaps[prop.type]; } } //# sourceMappingURL=csharp.js.map