Created
January 12, 2022 05:07
-
-
Save daeken/de98704a1ffcabe8e6cdee4e584fc8b7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from yaml import load | |
try: | |
from yaml import CLoader as Loader | |
except ImportError: | |
from yaml import Loader | |
spec = load(file('spec.yaml'), Loader=Loader) | |
import pprint | |
pprint.pprint(spec) | |
namespaces = {} | |
namespace = None | |
def genName(name): | |
if '.' in name: | |
return name | |
assert namespace is not None | |
nsl = namespace.split('.') | |
name = '.'.join(nsl[:-3] + [name] + nsl[-3:]) | |
return name | |
def splitNamespace(name): | |
nl = name.split('.') | |
namespace = '.'.join(nl[:-4]) | |
name = nl[-4] | |
return namespace, name | |
def getNs(namespace): | |
if namespace not in namespaces: | |
namespaces[namespace] = dict( | |
structs={}, | |
interfaces={}, | |
enums={} | |
) | |
return namespaces[namespace] | |
def title(x): | |
return x[0].upper() + x[1:] | |
def parseType(type): | |
if type.startswith('array['): | |
return ['array', parseType(type[6:-1])] | |
elif type.startswith('callback['): | |
type = type[9:-1] + ',' | |
elems = [] | |
bracket = 0 | |
last = 0 | |
for i, c in enumerate(type): | |
if c == '[': | |
bracket += 1 | |
elif c == ']': | |
bracket -= 1 | |
elif bracket == 0 and c == ',': | |
elems.append(type[last:i]) | |
last = i + 1 | |
return ['callback'] + map(parseType, elems) | |
else: | |
return [type] | |
def parseInterface(elem): # TODO: Handle inheritance | |
if 'name' in elem: | |
name = genName(elem['name']) | |
else: | |
name = namespace | |
assert name is not None | |
def proc(elem): | |
if isinstance(elem, dict): | |
name = elem.keys()[0] | |
oparams = elem[name] | |
params = [] | |
for elem in oparams: | |
if isinstance(elem, dict): | |
type = elem.keys()[0] | |
pname = elem[type] | |
params.append((type, pname)) | |
else: | |
params.append(elem) | |
else: | |
name = elem | |
params = [] | |
if len(params) == 0: | |
params = ['void'] | |
return name, params | |
events = map(proc, elem['events']) if 'events' in elem else [] | |
methods = map(proc, elem['methods']) if 'methods' in elem else [] | |
emethods = [] | |
for ename, params in events: | |
if len(params) == 1: | |
cparams = 'callback[%s]' % params[0], 'callback' | |
else: | |
cparams = 'callback[%s,%s]' % (params[0], ','.join(type for type, _ in params[1:])), 'callback' | |
emethods.append(('Subscribe' + title(ename), ['void', cparams])) | |
emethods.append(('Unsubscribe' + title(ename), ['void', cparams])) | |
methods = emethods + methods | |
methods = [(ename, [parseType(params[0])] + [(parseType(type), pname) for type, pname in params[1:]]) for ename, params in methods] | |
ns, name = splitNamespace(name) | |
ns = getNs(ns) | |
ns['interfaces'][name] = {'methods' : methods} | |
def parseExtension(elem): | |
global namespace | |
assert len(elem) >= 1 and 'name' in elem[0] | |
namespace = elem[0]['name'] | |
nsl = namespace.split('.') | |
assert len(nsl) > 3 and nsl[-3].startswith('v') | |
parse(elem[1:]) | |
def parseStruct(elem): | |
assert len(elem) >= 1 and 'name' in elem[0] | |
name = genName(elem[0]['name']) | |
ns, name = splitNamespace(name) | |
ns = getNs(ns) | |
def proc(elem): | |
type = elem.keys()[0] | |
return parseType(type), elem[type] | |
ns['structs'][name] = map(proc, elem[1:]) | |
def parseFlags(elem): | |
assert len(elem) >= 2 and 'name' in elem[0] and 'type' in elem[1] | |
name = genName(elem[0]['name']) | |
type = elem[1]['type'] # TODO: Support enum types | |
ns, name = splitNamespace(name) | |
ns = getNs(ns) | |
bit = [0] | |
def proc(elem): | |
if isinstance(elem, dict): | |
name = elem.keys()[0] | |
return (name, elem[name]) | |
value = 1 << bit[0] | |
bit[0] += 1 | |
return (elem, value) | |
ns['enums'][name] = (False, map(proc, elem[2:])) | |
def parseEnum(elem): | |
pass | |
def parse(data): | |
for elem in data: | |
if 'interface' in elem: | |
parseInterface(elem['interface']) | |
elif 'extension' in elem: | |
parseExtension(elem['extension']) | |
elif 'struct' in elem: | |
parseStruct(elem['struct']) | |
elif 'flags' in elem: | |
parseFlags(elem['flags']) | |
elif 'enum' in elem: | |
parseEnum(elem['enum']) | |
else: | |
print 'Unhandled:', `elem` | |
parse(spec) | |
btypes = dict( | |
void='void', | |
string='string', | |
uuid='Uuid', | |
u8='byte', | |
i8='sbyte', | |
u16='ushort', | |
i16='short', | |
u32='uint', | |
i32='int', | |
vu32='uint', | |
vi32='int', | |
u64='ulong', | |
i64='long', | |
vu64='ulong', | |
vi64='long', | |
matrix4x4='Matrix4x4', | |
) | |
vtypes = ( | |
'vu32', 'vi32', | |
'vu64', 'vi64', | |
) | |
def typed(type, isRet=False): | |
if isRet: | |
if type == ['void']: | |
return 'Task' | |
else: | |
return 'Task<%s>' % typed(type) | |
if type[0] == 'array': | |
return '%s[]' % typed(type[1]) | |
elif type[0] == 'callback': | |
ret = typed(type[1], True) | |
params = type[2:] | |
if len(params): | |
return 'Func<%s, %s>' % (', '.join(map(typed, params)), ret) | |
else: | |
return 'Func<%s>' % ret | |
elif type[0] in btypes: | |
return btypes[type[0]] | |
assert len(type) == 1 | |
return title(type[0]) | |
with file('../NetLib/Generated/Protocol.cs', 'w') as fp: | |
print >>fp, '''#pragma warning disable CS1998 | |
// ReSharper disable ConvertClosureToMethodGroup | |
// ReSharper disable MemberCanBePrivate.Global | |
// ReSharper disable UseObjectOrCollectionInitializer | |
// ReSharper disable RedundantUsingDirective | |
// ReSharper disable RedundantAssignment''' | |
print >>fp, 'using System;' | |
print >>fp, 'using System.Numerics;' | |
print >>fp, 'using System.Collections.Generic;' | |
print >>fp, 'namespace NetLib.Generated;' | |
for nsn, ns in namespaces.items(): | |
def genDeserialize(type, name, depth = 0): | |
ws = '\t\t' + '\t' * depth | |
if type[0] == 'array': | |
print >>fp, ws + '%s = new %s[(int) NetExtensions.DeserializeVu64(buf, ref offset)];' % (name, typed(type[1])) | |
print >>fp, ws + 'for(var i%i = 0; i%i < %s.Length; ++i%i) {' % (depth, depth, name, depth) | |
genDeserialize(type[1], '%s[i%i]' % (name, depth), depth + 1) | |
print >>fp, ws + '}' | |
elif type[0] in btypes and type[0] != 'uuid': | |
print >>fp, ws + '%s = NetExtensions.Deserialize%s(buf, ref offset);' % (name, title(type[0])) | |
elif type[0] in ns['enums']: | |
print >>fp, ws + '%s = (%s) NetExtensions.DeserializeVu64(buf, ref offset);' % (name, title(type[0])) # TODO: Support enum types | |
elif type[0] == 'object' or type[0] in ns['interfaces']: | |
assert False | |
else: | |
print >>fp, ws + '%s = %s.Deserialize(buf, ref offset);' % (name, title(type[0])) | |
def genMsgDeserialize(type, name, depth = 0): | |
ws = '\t\t\t\t' + '\t' * depth | |
if type[0] == 'array': | |
print >>fp, ws + '%s%s = new %s[(int) NetExtensions.DeserializeVu64(buf.Span, ref offset)];' % ('var ' if depth == 0 else '', name, typed(type[1])) | |
print >>fp, ws + 'for(var i%i = 0; i%i < %s.Length; ++i%i) {' % (depth, depth, name, depth) | |
genMsgDeserialize(type[1], '%s[i%i]' % (name, depth), depth + 1) | |
print >>fp, ws + '}' | |
elif type[0] in btypes and type[0] != 'uuid': | |
print >>fp, ws + '%s%s = NetExtensions.Deserialize%s(buf.Span, ref offset);' % ('var ' if depth == 0 else '', name, title(type[0])) | |
elif type[0] in ns['enums']: | |
print >>fp, ws + '%s%s = (%s) NetExtensions.DeserializeVu64(buf.Span, ref offset);' % ('var ' if depth == 0 else '', name, title(type[0])) # TODO: Support enum types | |
elif type[0] == 'object' or type[0] in ns['interfaces']: | |
assert False | |
elif type[0] == 'callback': | |
print >>fp, ws + '%s%s = Connection.GetCallback<%s>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () =>' % ('var ' if depth == 0 else '', name, typed(type)) | |
print >>fp, ws + '\tasync (%s) => {' % ', '.join('_%i' % i for i, _ in enumerate(type[2:])) | |
print >>fp, ws + '\t}' | |
print >>fp, ws + ');' | |
else: | |
print >>fp, ws + '%s%s = %s.Deserialize(buf.Span, ref offset);' % ('var ' if depth == 0 else '', name, title(type[0])) | |
def genSerialize(type, value, depth = 0): | |
ws = '\t\t' + '\t' * depth | |
if type[0] == 'array': | |
print >>fp, ws + 'NetExtensions.SerializeVu64((ulong) %s.Length, buf, ref offset);' % value | |
print >>fp, ws + 'foreach(var _%i in %s) {' % (depth, value) | |
genSerialize(type[1], '_%i' % depth, depth+1) | |
print >>fp, ws + '}' | |
elif type[0] in btypes and type[0] != 'uuid': | |
print >>fp, ws + 'NetExtensions.Serialize%s(%s, buf, ref offset);' % (title(type[0]), value) | |
elif type[0] in ns['enums']: | |
genSerialize(['vu64'], '(ulong) ' + value, depth) # TODO: Support enum types | |
elif type[0] == 'object' or type[0] in ns['interfaces']: | |
assert False | |
else: | |
print >>fp, ws + '%s.Serialize(buf, ref offset);' % value | |
def genMsgSerialize(type, value, depth = 0): | |
ws = '\t\t\t\t\t' + '\t' * depth | |
if type[0] == 'array': | |
print >>fp, ws + 'NetExtensions.SerializeVu64((ulong) %s.Length, buf.Span, ref offset);' % value | |
print >>fp, ws + 'foreach(var _%i in %s) {' % (depth, value) | |
genMsgSerialize(type[1], '_%i' % depth, depth+1) | |
print >>fp, ws + '}' | |
elif type[0] in btypes and type[0] != 'uuid': | |
print >>fp, ws + 'NetExtensions.Serialize%s(%s, buf.Span, ref offset);' % (title(type[0]), value) | |
elif type[0] in ns['enums']: | |
genMsgSerialize(['vu64'], '(ulong) ' + value, depth) # TODO: Support enum types | |
elif type[0] == 'object' or type[0] in ns['interfaces']: | |
genMsgSerialize(['vu64'], '%s.ObjectId' % value, depth) | |
else: | |
print >>fp, ws + '%s.Serialize(buf.Span, ref offset);' % value | |
def genSize(type, value, depth = 0): | |
if type[0] == 'array': | |
return 'NetExtensions.SizeVu64((ulong) %s.Length) + %s.Select(_%i => %s).Sum()' % (value, value, depth, genSize(type[1], '_%i' % depth, depth + 1)) | |
elif type[0] == 'uuid': | |
return '16' | |
elif type[0] in btypes: | |
return 'NetExtensions.Size%s(%s)' % (title(type[0]), value) | |
elif type[0] in ns['enums']: | |
return 'NetExtensions.SizeVu64((ulong) %s)' % value | |
elif type[0] == 'object' or type[0] in ns['interfaces']: | |
return 'NetExtensions.SizeVu64(%s.ObjectId)' % value | |
else: | |
return '%s.SerializedSize' % value | |
for name, iface in ns['interfaces'].items(): | |
print >>fp | |
print >>fp, 'public interface %s%s {' % (title(name), ' : Object' if nsn != 'hypercosm' or name != 'object' else '') | |
if nsn == 'hypercosm' and name == 'object': | |
print >>fp, '\tulong ObjectId { get; }' | |
for mname, params in iface['methods']: | |
print >>fp, '\t%s %s(%s);' % (typed(params[0], isRet=True), title(mname), ', '.join('%s %s' % (typed(type), pname) for type, pname in params[1:])) | |
print >>fp, '}' | |
print >>fp, 'public abstract class Base%s : %s%s {' % (title(name), 'BaseObject, ' if nsn != 'hypercosm' or name != 'object' else 'ILocalObject, ', title(name)) | |
if nsn == 'hypercosm' and name == 'object': | |
print >>fp, '\tprotected readonly IConnection Connection;' | |
print >>fp, '\tpublic ulong ObjectId { get; }' | |
print >>fp, '\tprotected BaseObject(IConnection connection) {' | |
print >>fp, '\t\tConnection = connection;' | |
print >>fp, '\t\tObjectId = Connection.RegisterLocalObject(this);' | |
print >>fp, '\t}' | |
else: | |
print >>fp, '\tprotected Base%s(IConnection connection) : base(connection) {}' % title(name) | |
for mname, params in iface['methods']: | |
print >>fp, '\tpublic abstract %s %s(%s);' % (typed(params[0], isRet=True), title(mname), ', '.join('%s %s' % (typed(type), pname) for type, pname in params[1:])) | |
print >>fp | |
print >>fp, '\tpublic %sasync Task HandleMessage(ulong sequence, int commandNumber, Memory<byte> buf, int offset) {' % ('new ' if nsn != 'hypercosm' or name != 'object' else '') | |
print >>fp, '\t\tswitch(commandNumber) {' | |
cmdNum = 0 | |
if nsn != 'hypercosm' or name != 'object': | |
cmdNum = 2 | |
print >>fp, '\t\t\tcase 0 or 1: await ((BaseObject) this).HandleMessage(sequence, commandNumber, buf, offset); break;' | |
for mname, params in iface['methods']: | |
print >>fp, '\t\t\tcase %i: {' % cmdNum | |
for type, pname in params[1:]: | |
genMsgDeserialize(type, title(pname)) | |
if params[0] == ['void']: | |
ret = '' | |
else: | |
ret = 'var __ret = ' | |
print >>fp, '\t\t\t\t%sawait %s(%s);' % (ret, title(mname), ', '.join(title(pname) for _, pname in params[1:])) | |
print >>fp, '\t\t\t\tif(sequence != 0) {' | |
if params[0] == ['void']: | |
print >>fp, '\t\t\t\t\tawait Connection.Respond(sequence, Memory<byte>.Empty);' | |
else: | |
print >>fp, '\t\t\t\t\tbuf = new byte[%s];' % genSize(params[0], '__ret') | |
print >>fp, '\t\t\t\t\toffset = 0;' | |
genMsgSerialize(params[0], '__ret') | |
print >>fp, '\t\t\t\t\tawait Connection.Respond(sequence, buf);' | |
print >>fp, '\t\t\t\t}' | |
print >>fp, '\t\t\t\tbreak;' | |
print >>fp, '\t\t\t}' | |
cmdNum += 1 | |
print >>fp, '\t\t\tdefault:' | |
print >>fp, '\t\t\t\tthrow new UnknownCommandException();' | |
print >>fp, '\t\t}' | |
print >>fp, '\t}' | |
print >>fp, '}' | |
print >>fp, 'public class Remote%s : %s%s {' % (title(name), 'RemoteObject, ' if nsn != 'hypercosm' or name != 'object' else 'IRemoteObject, ', title(name)) | |
for mname, params in iface['methods']: | |
print >>fp, '\tpublic async %s %s(%s) {' % (typed(params[0], isRet=True), title(mname), ', '.join('%s %s' % (typed(type), pname) for type, pname in params[1:])) | |
print >>fp, '\t}' | |
print >>fp, '}' | |
for name, struct in ns['structs'].items(): | |
print >>fp | |
print >>fp, 'public struct %s {' % title(name) | |
for type, fname in struct: | |
print >>fp, '\tpublic %s %s;' % (typed(type), title(fname)) | |
print >>fp | |
if len(struct) == 0: | |
print >>fp, '\tpublic int SerializedSize => 0;' | |
else: | |
print >>fp, '\tpublic int SerializedSize => %s;' % ' + '.join(genSize(type, title(fname)) for type, fname in struct) | |
print >>fp, '\tpublic void Serialize(IConnection connection, Span<byte> buf, ref int offset) {' | |
for type, fname in struct: | |
genSerialize(type, title(fname)) | |
print >>fp, '\t}' | |
print >>fp, '\tpublic static %s Deserialize(IConnection connection, Span<byte> buf, ref int offset) {' % title(name) | |
print >>fp, '\t\tvar obj = new %s();' % title(name) | |
for type, fname in struct: | |
genDeserialize(type, 'obj.' + title(fname)) | |
print >>fp, '\t\treturn obj;' | |
print >>fp, '\t}' | |
print >>fp, '}' | |
for name, (isFlags, enum) in ns['enums'].items(): | |
print >>fp | |
if isFlags: | |
print >>fp, '[Flags]' | |
print >>fp, 'public enum %s : ulong {' % title(name) # TODO: Support enum types | |
for ename, value in enum: | |
print >>fp, '\t%s = %s,' % (title(ename), value) | |
print >>fp, '}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma warning disable CS1998 | |
// ReSharper disable ConvertClosureToMethodGroup | |
// ReSharper disable MemberCanBePrivate.Global | |
// ReSharper disable UseObjectOrCollectionInitializer | |
// ReSharper disable RedundantUsingDirective | |
// ReSharper disable RedundantAssignment | |
using System; | |
using System.Numerics; | |
using System.Collections.Generic; | |
namespace NetLib.Generated; | |
public interface World : Object { | |
Task SubscribeAddEntities(Func<EntityInfo[], Task> callback); | |
Task UnsubscribeAddEntities(Func<EntityInfo[], Task> callback); | |
Task SubscribeUpdateEntities(Func<EntityInfo[], Task> callback); | |
Task UnsubscribeUpdateEntities(Func<EntityInfo[], Task> callback); | |
Task SubscribeRemoveEntities(Func<Entity[], Task> callback); | |
Task UnsubscribeRemoveEntities(Func<Entity[], Task> callback); | |
} | |
public abstract class BaseWorld : BaseObject, World { | |
protected BaseWorld(IConnection connection) : base(connection) {} | |
public abstract Task SubscribeAddEntities(Func<EntityInfo[], Task> callback); | |
public abstract Task UnsubscribeAddEntities(Func<EntityInfo[], Task> callback); | |
public abstract Task SubscribeUpdateEntities(Func<EntityInfo[], Task> callback); | |
public abstract Task UnsubscribeUpdateEntities(Func<EntityInfo[], Task> callback); | |
public abstract Task SubscribeRemoveEntities(Func<Entity[], Task> callback); | |
public abstract Task UnsubscribeRemoveEntities(Func<Entity[], Task> callback); | |
public new async Task HandleMessage(ulong sequence, int commandNumber, Memory<byte> buf, int offset) { | |
switch(commandNumber) { | |
case 0 or 1: await ((BaseObject) this).HandleMessage(sequence, commandNumber, buf, offset); break; | |
case 2: { | |
var Callback = Connection.GetCallback<Func<EntityInfo[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await SubscribeAddEntities(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 3: { | |
var Callback = Connection.GetCallback<Func<EntityInfo[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await UnsubscribeAddEntities(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 4: { | |
var Callback = Connection.GetCallback<Func<EntityInfo[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await SubscribeUpdateEntities(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 5: { | |
var Callback = Connection.GetCallback<Func<EntityInfo[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await UnsubscribeUpdateEntities(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 6: { | |
var Callback = Connection.GetCallback<Func<Entity[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await SubscribeRemoveEntities(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 7: { | |
var Callback = Connection.GetCallback<Func<Entity[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await UnsubscribeRemoveEntities(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
default: | |
throw new UnknownCommandException(); | |
} | |
} | |
} | |
public class RemoteWorld : RemoteObject, World { | |
public async Task SubscribeAddEntities(Func<EntityInfo[], Task> callback) { | |
} | |
public async Task UnsubscribeAddEntities(Func<EntityInfo[], Task> callback) { | |
} | |
public async Task SubscribeUpdateEntities(Func<EntityInfo[], Task> callback) { | |
} | |
public async Task UnsubscribeUpdateEntities(Func<EntityInfo[], Task> callback) { | |
} | |
public async Task SubscribeRemoveEntities(Func<Entity[], Task> callback) { | |
} | |
public async Task UnsubscribeRemoveEntities(Func<Entity[], Task> callback) { | |
} | |
} | |
public interface Object { | |
ulong ObjectId { get; } | |
Task<string[]> ListInterfaces(); | |
Task Release(); | |
} | |
public abstract class BaseObject : ILocalObject, Object { | |
protected readonly IConnection Connection; | |
public ulong ObjectId { get; } | |
protected BaseObject(IConnection connection) { | |
Connection = connection; | |
ObjectId = Connection.RegisterLocalObject(this); | |
} | |
public abstract Task<string[]> ListInterfaces(); | |
public abstract Task Release(); | |
public async Task HandleMessage(ulong sequence, int commandNumber, Memory<byte> buf, int offset) { | |
switch(commandNumber) { | |
case 0: { | |
var __ret = await ListInterfaces(); | |
if(sequence != 0) { | |
buf = new byte[NetExtensions.SizeVu64((ulong) __ret.Length) + __ret.Select(_0 => NetExtensions.SizeString(_0)).Sum()]; | |
offset = 0; | |
NetExtensions.SerializeVu64((ulong) __ret.Length, buf.Span, ref offset); | |
foreach(var _0 in __ret) { | |
NetExtensions.SerializeString(_0, buf.Span, ref offset); | |
} | |
await Connection.Respond(sequence, buf); | |
} | |
break; | |
} | |
case 1: { | |
await Release(); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
default: | |
throw new UnknownCommandException(); | |
} | |
} | |
} | |
public class RemoteObject : IRemoteObject, Object { | |
public async Task<string[]> ListInterfaces() { | |
} | |
public async Task Release() { | |
} | |
} | |
public interface Root : Object { | |
Task<string[]> ListExtensions(); | |
Task Ping(); | |
Task<Object> GetObjectById(Uuid id); | |
Task<Object> GetObjectByName(string name); | |
} | |
public abstract class BaseRoot : BaseObject, Root { | |
protected BaseRoot(IConnection connection) : base(connection) {} | |
public abstract Task<string[]> ListExtensions(); | |
public abstract Task Ping(); | |
public abstract Task<Object> GetObjectById(Uuid id); | |
public abstract Task<Object> GetObjectByName(string name); | |
public new async Task HandleMessage(ulong sequence, int commandNumber, Memory<byte> buf, int offset) { | |
switch(commandNumber) { | |
case 0 or 1: await ((BaseObject) this).HandleMessage(sequence, commandNumber, buf, offset); break; | |
case 2: { | |
var __ret = await ListExtensions(); | |
if(sequence != 0) { | |
buf = new byte[NetExtensions.SizeVu64((ulong) __ret.Length) + __ret.Select(_0 => NetExtensions.SizeString(_0)).Sum()]; | |
offset = 0; | |
NetExtensions.SerializeVu64((ulong) __ret.Length, buf.Span, ref offset); | |
foreach(var _0 in __ret) { | |
NetExtensions.SerializeString(_0, buf.Span, ref offset); | |
} | |
await Connection.Respond(sequence, buf); | |
} | |
break; | |
} | |
case 3: { | |
await Ping(); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 4: { | |
var Id = Uuid.Deserialize(buf.Span, ref offset); | |
var __ret = await GetObjectById(Id); | |
if(sequence != 0) { | |
buf = new byte[NetExtensions.SizeVu64(__ret.ObjectId)]; | |
offset = 0; | |
NetExtensions.SerializeVu64(__ret.ObjectId, buf.Span, ref offset); | |
await Connection.Respond(sequence, buf); | |
} | |
break; | |
} | |
case 5: { | |
var Name = NetExtensions.DeserializeString(buf.Span, ref offset); | |
var __ret = await GetObjectByName(Name); | |
if(sequence != 0) { | |
buf = new byte[NetExtensions.SizeVu64(__ret.ObjectId)]; | |
offset = 0; | |
NetExtensions.SerializeVu64(__ret.ObjectId, buf.Span, ref offset); | |
await Connection.Respond(sequence, buf); | |
} | |
break; | |
} | |
default: | |
throw new UnknownCommandException(); | |
} | |
} | |
} | |
public class RemoteRoot : RemoteObject, Root { | |
public async Task<string[]> ListExtensions() { | |
} | |
public async Task Ping() { | |
} | |
public async Task<Object> GetObjectById(Uuid id) { | |
} | |
public async Task<Object> GetObjectByName(string name) { | |
} | |
} | |
public interface Assetdelivery : Object { | |
Task SubscribeLoadAssets(Func<Asset[], Task> callback); | |
Task UnsubscribeLoadAssets(Func<Asset[], Task> callback); | |
Task SubscribeUnloadAssets(Func<Uuid[], Task> callback); | |
Task UnsubscribeUnloadAssets(Func<Uuid[], Task> callback); | |
Task<Asset> FetchAssetById(Uuid id); | |
Task<Asset> FetchAssetByName(string name); | |
Task<Asset[]> FetchAssetsByIds(Uuid[] ids); | |
Task<Asset[]> FetchAssetsByNames(string[] names); | |
Task<Uuid> GetId(string name); | |
} | |
public abstract class BaseAssetdelivery : BaseObject, Assetdelivery { | |
protected BaseAssetdelivery(IConnection connection) : base(connection) {} | |
public abstract Task SubscribeLoadAssets(Func<Asset[], Task> callback); | |
public abstract Task UnsubscribeLoadAssets(Func<Asset[], Task> callback); | |
public abstract Task SubscribeUnloadAssets(Func<Uuid[], Task> callback); | |
public abstract Task UnsubscribeUnloadAssets(Func<Uuid[], Task> callback); | |
public abstract Task<Asset> FetchAssetById(Uuid id); | |
public abstract Task<Asset> FetchAssetByName(string name); | |
public abstract Task<Asset[]> FetchAssetsByIds(Uuid[] ids); | |
public abstract Task<Asset[]> FetchAssetsByNames(string[] names); | |
public abstract Task<Uuid> GetId(string name); | |
public new async Task HandleMessage(ulong sequence, int commandNumber, Memory<byte> buf, int offset) { | |
switch(commandNumber) { | |
case 0 or 1: await ((BaseObject) this).HandleMessage(sequence, commandNumber, buf, offset); break; | |
case 2: { | |
var Callback = Connection.GetCallback<Func<Asset[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await SubscribeLoadAssets(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 3: { | |
var Callback = Connection.GetCallback<Func<Asset[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await UnsubscribeLoadAssets(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 4: { | |
var Callback = Connection.GetCallback<Func<Uuid[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await SubscribeUnloadAssets(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 5: { | |
var Callback = Connection.GetCallback<Func<Uuid[], Task>>(NetExtensions.DeserializeVu64(buf.Span, ref offset), () => | |
async (_0) => { | |
} | |
); | |
await UnsubscribeUnloadAssets(Callback); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
case 6: { | |
var Id = Uuid.Deserialize(buf.Span, ref offset); | |
var __ret = await FetchAssetById(Id); | |
if(sequence != 0) { | |
buf = new byte[__ret.SerializedSize]; | |
offset = 0; | |
__ret.Serialize(buf.Span, ref offset); | |
await Connection.Respond(sequence, buf); | |
} | |
break; | |
} | |
case 7: { | |
var Name = NetExtensions.DeserializeString(buf.Span, ref offset); | |
var __ret = await FetchAssetByName(Name); | |
if(sequence != 0) { | |
buf = new byte[__ret.SerializedSize]; | |
offset = 0; | |
__ret.Serialize(buf.Span, ref offset); | |
await Connection.Respond(sequence, buf); | |
} | |
break; | |
} | |
case 8: { | |
var Ids = new Uuid[(int) NetExtensions.DeserializeVu64(buf.Span, ref offset)]; | |
for(var i0 = 0; i0 < Ids.Length; ++i0) { | |
Ids[i0] = Uuid.Deserialize(buf.Span, ref offset); | |
} | |
var __ret = await FetchAssetsByIds(Ids); | |
if(sequence != 0) { | |
buf = new byte[NetExtensions.SizeVu64((ulong) __ret.Length) + __ret.Select(_0 => _0.SerializedSize).Sum()]; | |
offset = 0; | |
NetExtensions.SerializeVu64((ulong) __ret.Length, buf.Span, ref offset); | |
foreach(var _0 in __ret) { | |
_0.Serialize(buf.Span, ref offset); | |
} | |
await Connection.Respond(sequence, buf); | |
} | |
break; | |
} | |
case 9: { | |
var Names = new string[(int) NetExtensions.DeserializeVu64(buf.Span, ref offset)]; | |
for(var i0 = 0; i0 < Names.Length; ++i0) { | |
Names[i0] = NetExtensions.DeserializeString(buf.Span, ref offset); | |
} | |
var __ret = await FetchAssetsByNames(Names); | |
if(sequence != 0) { | |
buf = new byte[NetExtensions.SizeVu64((ulong) __ret.Length) + __ret.Select(_0 => _0.SerializedSize).Sum()]; | |
offset = 0; | |
NetExtensions.SerializeVu64((ulong) __ret.Length, buf.Span, ref offset); | |
foreach(var _0 in __ret) { | |
_0.Serialize(buf.Span, ref offset); | |
} | |
await Connection.Respond(sequence, buf); | |
} | |
break; | |
} | |
case 10: { | |
var Name = NetExtensions.DeserializeString(buf.Span, ref offset); | |
var __ret = await GetId(Name); | |
if(sequence != 0) { | |
buf = new byte[16]; | |
offset = 0; | |
__ret.Serialize(buf.Span, ref offset); | |
await Connection.Respond(sequence, buf); | |
} | |
break; | |
} | |
default: | |
throw new UnknownCommandException(); | |
} | |
} | |
} | |
public class RemoteAssetdelivery : RemoteObject, Assetdelivery { | |
public async Task SubscribeLoadAssets(Func<Asset[], Task> callback) { | |
} | |
public async Task UnsubscribeLoadAssets(Func<Asset[], Task> callback) { | |
} | |
public async Task SubscribeUnloadAssets(Func<Uuid[], Task> callback) { | |
} | |
public async Task UnsubscribeUnloadAssets(Func<Uuid[], Task> callback) { | |
} | |
public async Task<Asset> FetchAssetById(Uuid id) { | |
} | |
public async Task<Asset> FetchAssetByName(string name) { | |
} | |
public async Task<Asset[]> FetchAssetsByIds(Uuid[] ids) { | |
} | |
public async Task<Asset[]> FetchAssetsByNames(string[] names) { | |
} | |
public async Task<Uuid> GetId(string name) { | |
} | |
} | |
public struct Asset { | |
public Uuid Id; | |
public string Name; | |
public byte[] Data; | |
public int SerializedSize => 16 + NetExtensions.SizeString(Name) + NetExtensions.SizeVu64((ulong) Data.Length) + Data.Select(_0 => NetExtensions.SizeU8(_0)).Sum(); | |
public void Serialize(Span<byte> buf, ref int offset) { | |
Id.Serialize(buf, ref offset); | |
NetExtensions.SerializeString(Name, buf, ref offset); | |
NetExtensions.SerializeVu64((ulong) Data.Length, buf, ref offset); | |
foreach(var _0 in Data) { | |
NetExtensions.SerializeU8(_0, buf, ref offset); | |
} | |
} | |
public static Asset Deserialize(Span<byte> buf, ref int offset) { | |
var obj = new Asset(); | |
obj.Id = Uuid.Deserialize(buf, ref offset); | |
obj.Name = NetExtensions.DeserializeString(buf, ref offset); | |
obj.Data = new byte[(int) NetExtensions.DeserializeVu64(buf, ref offset)]; | |
for(var i0 = 0; i0 < obj.Data.Length; ++i0) { | |
obj.Data[i0] = NetExtensions.DeserializeU8(buf, ref offset); | |
} | |
return obj; | |
} | |
} | |
public interface Entity : Object { | |
Task Interact(); | |
} | |
public abstract class BaseEntity : BaseObject, Entity { | |
protected BaseEntity(IConnection connection) : base(connection) {} | |
public abstract Task Interact(); | |
public new async Task HandleMessage(ulong sequence, int commandNumber, Memory<byte> buf, int offset) { | |
switch(commandNumber) { | |
case 0 or 1: await ((BaseObject) this).HandleMessage(sequence, commandNumber, buf, offset); break; | |
case 2: { | |
await Interact(); | |
if(sequence != 0) { | |
await Connection.Respond(sequence, Memory<byte>.Empty); | |
} | |
break; | |
} | |
default: | |
throw new UnknownCommandException(); | |
} | |
} | |
} | |
public class RemoteEntity : RemoteObject, Entity { | |
public async Task Interact() { | |
} | |
} | |
public struct EntityInfo { | |
public Uuid AssetId; | |
public Entity Entity; | |
public Matrix4x4 Transformation; | |
public EntityFlags Flags; | |
public int SerializedSize => 16 + NetExtensions.SizeVu64(Entity.ObjectId) + NetExtensions.SizeMatrix4x4(Transformation) + NetExtensions.SizeVu64((ulong) Flags); | |
public void Serialize(Span<byte> buf, ref int offset) { | |
AssetId.Serialize(buf, ref offset); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment