4 using System.Collections.Generic;
5 using System.Collections.Immutable;
6 using System.Diagnostics.CodeAnalysis;
8 using System.Reflection;
9 using System.Runtime.CompilerServices;
12 using Microsoft.Xna.Framework;
38 [AttributeUsage(AttributeTargets.Field | AttributeTargets.Struct | AttributeTargets.Property)]
60 [SuppressMessage(
"ReSharper",
"RedundantTypeArgumentsOfMethod")]
61 static class NetSerializableProperties
87 ReadAction = (inc, attribute, bitField) => readAction(inc, attribute, bitField);
88 WriteAction = (o, attribute, msg, bitField) => writeAction((T)o!, attribute, msg, bitField);
114 case PropertyInfo pi:
115 Type = pi.PropertyType;
125 throw new ArgumentException($
"Expected {nameof(FieldInfo)} or {nameof(PropertyInfo)} but found {info.GetType()}.", nameof(info));
133 else if (baseClassType.GetCustomAttribute<
NetworkSerialize>() is { } globalAttribute)
140 throw new InvalidOperationException($
"Unable to serialize \"{Type}\" in \"{baseClassType}\" because it has no {nameof(NetworkSerialize)} attribute.");
145 private static readonly Dictionary<Type, ImmutableArray<CachedReflectedVariable>> CachedVariables =
new Dictionary<Type, ImmutableArray<CachedReflectedVariable>>();
147 private static readonly Dictionary<Type, IReadWriteBehavior> TypeBehaviors
148 =
new Dictionary<Type, IReadWriteBehavior>
150 { typeof(Boolean),
new ReadWriteBehavior<Boolean>(ReadBoolean, WriteBoolean) },
151 { typeof(Byte),
new ReadWriteBehavior<Byte>(ReadByte, WriteByte) },
152 { typeof(UInt16),
new ReadWriteBehavior<UInt16>(ReadUInt16, WriteUInt16) },
153 { typeof(Int16),
new ReadWriteBehavior<Int16>(ReadInt16, WriteInt16) },
154 { typeof(UInt32),
new ReadWriteBehavior<UInt32>(ReadUInt32, WriteUInt32) },
155 { typeof(Int32),
new ReadWriteBehavior<Int32>(ReadInt32, WriteInt32) },
156 { typeof(UInt64),
new ReadWriteBehavior<UInt64>(ReadUInt64, WriteUInt64) },
157 { typeof(Int64),
new ReadWriteBehavior<Int64>(ReadInt64, WriteInt64) },
158 { typeof(Single),
new ReadWriteBehavior<Single>(ReadSingle, WriteSingle) },
159 { typeof(Double),
new ReadWriteBehavior<Double>(ReadDouble, WriteDouble) },
160 { typeof(String),
new ReadWriteBehavior<String>(ReadString, WriteString) },
161 { typeof(Identifier),
new ReadWriteBehavior<Identifier>(ReadIdentifier, WriteIdentifier) },
162 { typeof(AccountId),
new ReadWriteBehavior<AccountId>(ReadAccountId, WriteAccountId) },
163 { typeof(Color),
new ReadWriteBehavior<Color>(ReadColor, WriteColor) },
164 { typeof(Vector2),
new ReadWriteBehavior<Vector2>(ReadVector2, WriteVector2) },
165 { typeof(SerializableDateTime),
new ReadWriteBehavior<SerializableDateTime>(ReadSerializableDateTime, WriteSerializableDateTime) },
166 { typeof(NetLimitedString),
new ReadWriteBehavior<NetLimitedString>(ReadNetLString, WriteNetLString) }
169 private static readonly ImmutableDictionary<Predicate<Type>, Func<Type, IReadWriteBehavior>> BehaviorFactories =
new Dictionary<Predicate<Type>, Func<Type, IReadWriteBehavior>>
172 { type => type.IsArray, CreateArrayBehavior },
175 { type => typeof(INetSerializableStruct).IsAssignableFrom(type), CreateINetSerializableStructBehavior },
178 { type => type.IsEnum, CreateEnumBehavior },
181 { type => Nullable.GetUnderlyingType(type) !=
null, CreateNullableStructBehavior },
184 { type => IsOfGenericType(type, typeof(ImmutableArray<>)), CreateImmutableArrayBehavior },
187 { type => IsOfGenericType(type, typeof(Option<>)), CreateOptionBehavior }
188 }.ToImmutableDictionary();
198 private static IReadWriteBehavior CreateBehavior<TDelegateBase>(Type behaviorGenericParam,
199 Type funcGenericParam,
200 ReadWriteBehavior<TDelegateBase>.ReadDelegate readFunc,
201 ReadWriteBehavior<TDelegateBase>.WriteDelegate writeFunc)
203 var behaviorType = typeof(ReadWriteBehavior<>).MakeGenericType(behaviorGenericParam);
205 var readDelegateType = typeof(ReadWriteBehavior<>.ReadDelegate).MakeGenericType(behaviorGenericParam);
206 var writeDelegateType = typeof(ReadWriteBehavior<>.WriteDelegate).MakeGenericType(behaviorGenericParam);
208 var constructor = behaviorType.GetConstructor(
new[]
210 readDelegateType, writeDelegateType
213 return (constructor!.Invoke(
new object[]
215 readFunc.Method.GetGenericMethodDefinition().MakeGenericMethod(funcGenericParam).CreateDelegate(readDelegateType),
216 writeFunc.Method.GetGenericMethodDefinition().MakeGenericMethod(funcGenericParam).CreateDelegate(writeDelegateType)
217 }) as IReadWriteBehavior)!;
220 private static IReadWriteBehavior CreateArrayBehavior(Type arrayType) =>
223 arrayType.GetElementType()!,
227 private static IReadWriteBehavior CreateINetSerializableStructBehavior(Type structType) =>
231 ReadINetSerializableStruct<INetSerializableStruct>,
232 WriteINetSerializableStruct<INetSerializableStruct>);
234 private static IReadWriteBehavior CreateEnumBehavior(Type enumType) =>
241 private static IReadWriteBehavior CreateNullableStructBehavior(Type nullableType) =>
244 Nullable.GetUnderlyingType(nullableType)!,
248 private static IReadWriteBehavior CreateOptionBehavior(Type optionType) =>
251 optionType.GetGenericArguments()[0],
253 WriteOption<object>);
255 private static IReadWriteBehavior CreateImmutableArrayBehavior(Type arrayType) =>
258 arrayType.GetGenericArguments()[0],
259 ReadImmutableArray<object>,
260 WriteImmutableArray<object>);
262 private static ImmutableArray<T> ReadImmutableArray<T>(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : notnull
264 return ReadArray<T>(inc, attribute, bitField).ToImmutableArray();
267 private static void WriteImmutableArray<T>(ImmutableArray<T> array, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) where T : notnull
269 ToolBox.ThrowIfNull(array);
270 WriteIReadOnlyCollection<T>(array, attribute, msg, bitField);
273 private static T[] ReadArray<T>(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : notnull
275 int length = bitField.ReadInteger(0, attribute.ArrayMaxSize);
277 T[] array =
new T[length];
279 if (!TryFindBehavior(out ReadWriteBehavior<T> behavior))
281 throw new InvalidOperationException($
"Could not find suitable behavior for type {typeof(T)} in {nameof(ReadArray)}");
284 for (
int i = 0; i < length; i++)
286 array[i] = behavior.ReadActionDirect(inc, attribute, bitField);
292 private static void WriteArray<T>(T[] array, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) where T : notnull
294 ToolBox.ThrowIfNull(array);
295 WriteIReadOnlyCollection(array, attribute, msg, bitField);
298 private static void WriteIReadOnlyCollection<T>(IReadOnlyCollection<T> array, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) where T : notnull
300 bitField.WriteInteger(array.Count, 0, attribute.ArrayMaxSize);
302 if (!TryFindBehavior(out ReadWriteBehavior<T> behavior))
304 throw new InvalidOperationException($
"Could not find suitable behavior for type {typeof(T)} in {nameof(WriteArray)}");
307 foreach (T o
in array)
309 behavior.WriteActionDirect(o, attribute, msg, bitField);
313 private static T ReadINetSerializableStruct<T>(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : INetSerializableStruct
315 return INetSerializableStruct.ReadInternal<T>(inc, bitField);
318 private static void WriteINetSerializableStruct<T>(T serializableStruct, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) where T : INetSerializableStruct
320 ToolBox.ThrowIfNull(serializableStruct);
321 serializableStruct.WriteInternal(msg, bitField);
324 private static T ReadEnum<T>(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : Enum
326 var type = typeof(T);
328 Range<int> range = GetEnumRange(type);
329 int enumIndex = bitField.ReadInteger(range.Start, range.End);
331 if (typeof(T).GetCustomAttribute<FlagsAttribute>() !=
null)
333 return (T)(object)enumIndex;
336 foreach (T e
in (T[])Enum.GetValues(type))
338 if (((
int)(
object)e) == enumIndex) {
return e; }
341 throw new InvalidOperationException($
"An enum {type} with value {enumIndex} could not be found in {nameof(ReadEnum)}");
344 private static void WriteEnum<T>(T value, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) where T : Enum
346 ToolBox.ThrowIfNull(value);
348 Range<int> range = GetEnumRange(typeof(T));
349 bitField.WriteInteger((
int)Convert.ChangeType(value, value.GetTypeCode()), range.Start, range.End);
352 private static T? ReadNullable<T>(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T :
struct =>
353 ReadOption<T>(inc, attribute, bitField).TryUnwrap(out var value) ? value : null;
355 private static void WriteNullable<T>(T? value, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) where T : struct =>
356 WriteOption<T>(value.HasValue ? Option<T>.Some(value.Value) : Option<T>.None(), attribute, msg, bitField);
358 private static Option<T> ReadOption<T>(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : notnull
360 bool hasValue = bitField.ReadBoolean();
363 return Option<T>.None();
366 if (TryFindBehavior(out ReadWriteBehavior<T> behavior))
368 return Option<T>.Some(behavior.ReadActionDirect(inc, attribute, bitField));
371 throw new InvalidOperationException($
"Could not find suitable behavior for type {typeof(T)} in {nameof(ReadOption)}");
374 private static void WriteOption<T>(Option<T> option, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) where T : notnull
376 ToolBox.ThrowIfNull(option);
378 if (option.TryUnwrap(out T? value))
380 bitField.WriteBoolean(
true);
381 if (TryFindBehavior(out ReadWriteBehavior<T> behavior))
383 behavior.WriteActionDirect(value, attribute, msg, bitField);
388 bitField.WriteBoolean(
false);
392 private static bool ReadBoolean(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => bitField.ReadBoolean();
393 private static void WriteBoolean(
bool b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { bitField.WriteBoolean(b); }
395 private static byte ReadByte(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadByte();
396 private static void WriteByte(
byte b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteByte(b); }
398 private static ushort ReadUInt16(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadUInt16();
399 private static void WriteUInt16(ushort b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteUInt16(b); }
401 private static short ReadInt16(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadInt16();
402 private static void WriteInt16(
short b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteInt16(b); }
404 private static uint ReadUInt32(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadUInt32();
405 private static void WriteUInt32(uint b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteUInt32(b); }
407 private static int ReadInt32(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
409 if (IsRanged(attribute.MinValueInt, attribute.MaxValueInt))
411 return bitField.ReadInteger(attribute.MinValueInt, attribute.MaxValueInt);
417 private static void WriteInt32(
int i, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField)
419 ToolBox.ThrowIfNull(i);
421 if (IsRanged(attribute.MinValueInt, attribute.MaxValueInt))
423 bitField.WriteInteger(i, attribute.MinValueInt, attribute.MaxValueInt);
430 private static ulong ReadUInt64(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.
ReadUInt64();
431 private static void WriteUInt64(ulong b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteUInt64(b); }
433 private static long ReadInt64(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.
ReadInt64();
434 private static void WriteInt64(
long b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteInt64(b); }
436 private static float ReadSingle(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
438 if (IsRanged(attribute.MinValueFloat, attribute.MaxValueFloat))
440 return bitField.ReadFloat(attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits);
446 private static void WriteSingle(
float f, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField)
448 ToolBox.ThrowIfNull(f);
450 if (IsRanged(attribute.MinValueFloat, attribute.MaxValueFloat))
452 bitField.WriteFloat(f, attribute.MinValueFloat, attribute.MaxValueFloat, attribute.NumberOfBits);
459 private static double ReadDouble(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.
ReadDouble();
460 private static void WriteDouble(
double b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteDouble(b); }
465 private static NetLimitedString ReadNetLString(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) =>
new NetLimitedString(inc.
ReadString());
466 private static void WriteNetLString(NetLimitedString b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteString(b.Value); }
468 private static string ReadString(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.
ReadString();
469 private static void WriteString(
string b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteString(b); }
471 private static Identifier ReadIdentifier(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.
ReadIdentifier();
472 private static void WriteIdentifier(Identifier b, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField) { msg.
WriteIdentifier(b); }
474 private static AccountId ReadAccountId(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
477 return AccountId.Parse(str).TryUnwrap(out var accountId)
479 :
throw new InvalidCastException($
"Could not parse \"{str}\" as an {nameof(AccountId)}");
482 private static void WriteAccountId(AccountId accountId, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField)
489 private static void WriteColor(Color color, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField)
491 ToolBox.ThrowIfNull(color);
493 if (attribute.IncludeColorAlpha)
502 private static Vector2 ReadVector2(
IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
504 float x = ReadSingle(inc, attribute, bitField);
505 float y = ReadSingle(inc, attribute, bitField);
507 return new Vector2(x, y);
510 private static void WriteVector2(Vector2 vector2, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField)
512 ToolBox.ThrowIfNull(vector2);
514 var (x, y) = vector2;
515 WriteSingle(x, attribute, msg, bitField);
516 WriteSingle(y, attribute, msg, bitField);
519 private static readonly Range<Int64> ValidTickRange
521 start: DateTime.MinValue.Ticks,
522 end: DateTime.MaxValue.Ticks);
523 private static readonly Range<Int16> ValidTimeZoneMinuteRange
525 start: (Int16)TimeSpan.FromHours(-12).TotalMinutes,
526 end: (Int16)TimeSpan.FromHours(14).TotalMinutes);
528 private static SerializableDateTime ReadSerializableDateTime(
529 IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
534 if (!ValidTickRange.Contains(ticks))
536 throw new Exception($
"Incoming SerializableDateTime ticks out of range (ticks: {ticks}, timezone: {timezone})");
538 if (!ValidTimeZoneMinuteRange.Contains(timezone))
540 throw new Exception($
"Incoming SerializableDateTime timezone out of range (ticks: {ticks}, timezone: {timezone})");
543 return new SerializableDateTime(
new DateTime(ticks),
544 new SerializableTimeZone(TimeSpan.FromMinutes(timezone)));
547 private static void WriteSerializableDateTime(
548 SerializableDateTime dateTime, NetworkSerialize attribute,
IWriteMessage msg, WriteOnlyBitField bitField)
551 msg.
WriteInt16((Int16)(dateTime.TimeZone.Value.Ticks / TimeSpan.TicksPerMinute));
554 private static bool IsRanged(
float minValue,
float maxValue) => minValue >
float.MinValue || maxValue <
float.MaxValue;
555 private static bool IsRanged(
int minValue,
int maxValue) => minValue >
int.MinValue || maxValue <
int.MaxValue;
557 private static Range<int> GetEnumRange(Type type)
559 ImmutableArray<int> values = Enum.GetValues(type).Cast<
int>().ToImmutableArray();
560 return new Range<int>(values.Min(), values.Max());
563 private static bool TryFindBehavior<T>(out ReadWriteBehavior<T> behavior) where T : notnull
565 bool found = TryFindBehavior(typeof(T), out var bhvr);
566 behavior = found ? (ReadWriteBehavior<T>)bhvr :
default;
570 private static bool TryFindBehavior(Type type, out IReadWriteBehavior behavior)
572 if (TypeBehaviors.TryGetValue(type, out var outBehavior))
574 behavior = outBehavior;
578 foreach (var (predicate, factory) in BehaviorFactories)
580 if (!predicate(type)) {
continue; }
582 behavior = factory(type);
583 TypeBehaviors.Add(type, behavior);
591 public static ImmutableArray<CachedReflectedVariable> GetPropertiesAndFields(Type type)
593 if (CachedVariables.TryGetValue(type, out var cached)) {
return cached; }
595 List<CachedReflectedVariable> variables =
new List<CachedReflectedVariable>();
597 IEnumerable<PropertyInfo> propertyInfos = type.GetProperties().Where(HasAttribute).Where(NotStatic);
598 IEnumerable<FieldInfo> fieldInfos = type.GetFields().Where(HasAttribute).Where(NotStatic);
600 foreach (PropertyInfo info
in propertyInfos)
602 if (info.SetMethod is
null)
609 if (TryFindBehavior(info.PropertyType, out IReadWriteBehavior behavior))
611 variables.Add(
new CachedReflectedVariable(info, behavior, type));
615 throw new Exception($
"Unable to serialize type \"{type}\".");
619 foreach (FieldInfo info
in fieldInfos)
621 if (TryFindBehavior(info.FieldType, out IReadWriteBehavior behavior))
623 variables.Add(
new CachedReflectedVariable(info, behavior, type));
627 throw new Exception($
"Unable to serialize type \"{type}\".");
631 ImmutableArray<CachedReflectedVariable> array = variables.All(v => v.HasOwnAttribute) ? variables.OrderBy(v => v.Attribute.OrderKey).ToImmutableArray() : variables.ToImmutableArray();
632 CachedVariables.Add(type, array);
635 bool HasAttribute(MemberInfo info) => (info.GetCustomAttribute<NetworkSerialize>() ?? type.GetCustomAttribute<NetworkSerialize>()) !=
null;
637 static bool NotStatic(MemberInfo info)
640 PropertyInfo
property =>
property.GetGetMethod() is { IsStatic:
false },
641 FieldInfo field => !field.IsStatic,
646 private static bool IsOfGenericType(Type type, Type comparedTo)
648 return type.IsGenericType && type.GetGenericTypeDefinition() == comparedTo;
704 internal interface INetSerializableStruct
731 public static T Read<T>(
IReadMessage inc) where T : INetSerializableStruct
733 ReadOnlyBitField bitField =
new ReadOnlyBitField(inc);
734 return ReadInternal<T>(inc, bitField);
737 public static T ReadInternal<T>(
IReadMessage inc, ReadOnlyBitField bitField) where T : INetSerializableStruct
739 object? newObject = Activator.CreateInstance(typeof(T));
740 if (newObject is
null) {
return default!; }
742 var properties = NetSerializableProperties.GetPropertiesAndFields(typeof(T));
743 foreach (NetSerializableProperties.CachedReflectedVariable property in properties)
745 object? value =
property.Behavior.ReadAction(inc, property.Attribute, bitField);
748 property.SetValue(newObject, value);
750 catch (Exception exception)
752 throw new Exception($
"Failed to assign" +
753 $
" {value ?? "[NULL]
"} ({value?.GetType().Name ?? "[NULL]
"})" +
754 $
" to {typeof(T).Name}.{property.Name} ({property.Type.Name})", exception);
787 WriteOnlyBitField bitField =
new WriteOnlyBitField();
789 WriteInternal(structWriteMsg, bitField);
790 bitField.WriteToMessage(msg);
794 public void WriteInternal(
IWriteMessage msg, WriteOnlyBitField bitField)
796 var properties = NetSerializableProperties.GetPropertiesAndFields(GetType());
798 foreach (NetSerializableProperties.CachedReflectedVariable property in properties)
800 object? value =
property.GetValue(
this);
801 property.Behavior.WriteAction(value!, property.Attribute, msg, bitField);
805 public static bool TryRead<T>(
IReadMessage inc,
AccountInfo sender, [NotNullWhen(
true)] out T? data) where T : INetSerializableStruct
819 void LogError(Exception e)
823 StringBuilder hexData =
new();
828 hexData.Append($
"{b:X2} ");
831 if (hexData.Length > 0) { hexData.Length--; }
837 string accountInfoName = AccountInfoToName(sender);
838 DebugConsole.ThrowErrorOnce(
839 identifier: $
"INetSerializableStruct.TryRead:{accountInfoName}",
840 errorMsg: $
"Failed to read a message by {accountInfoName}. Data: \"{hexData}\"", e);
844 var connectedClients =
845 GameMain.NetworkMember?.ConnectedClients ?? Array.Empty<
Client>();
847 foreach (
Client c
in connectedClients)
855 return info.
AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation :
"Unknown";
Marks fields and properties as to be serialized and deserialized by INetSerializableStruct....
NetworkSerialize([CallerLineNumber] int lineNumber=0)
delegate void WriteDelegate(object? obj, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField)
WriteDelegate WriteAction
delegate? object ReadDelegate(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
Microsoft.Xna.Framework.Color ReadColorR8G8B8A8()
Microsoft.Xna.Framework.Color ReadColorR8G8B8()
Identifier ReadIdentifier()
void WriteBytes(byte[] val, int startIndex, int length)
void WriteInt64(Int64 val)
void WriteString(string val)
void WriteUInt16(UInt16 val)
void WriteDouble(Double val)
void WriteColorR8G8B8A8(Microsoft.Xna.Framework.Color val)
void WriteIdentifier(Identifier val)
void WriteInt32(Int32 val)
void WriteSingle(Single val)
void WriteInt16(Int16 val)
void WriteColorR8G8B8(Microsoft.Xna.Framework.Color val)
void WriteUInt64(UInt64 val)
void WriteUInt32(UInt32 val)
delegate? object GetValueDelegate(object? obj)
readonly GetValueDelegate GetValue
readonly IReadWriteBehavior Behavior
readonly SetValueDelegate SetValue
delegate void SetValueDelegate(object? obj, object? value)
readonly bool HasOwnAttribute
readonly NetworkSerialize Attribute
CachedReflectedVariable(MemberInfo info, IReadWriteBehavior behavior, Type baseClassType)
IReadWriteBehavior.ReadDelegate ReadAction
delegate void WriteDelegate(T obj, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField)
WriteDelegate WriteActionDirect
ReadWriteBehavior(ReadDelegate readAction, WriteDelegate writeAction)
delegate T ReadDelegate(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
ReadDelegate ReadActionDirect
IReadWriteBehavior.WriteDelegate WriteAction
readonly Option< AccountId > AccountId
The primary ID for a given user