Synchronizing values
From NetGore Wiki
| Difficulty | |
|---|---|
| Topics | File IO,Networking |
| (view all tutorials) | |
This page describes synchronizing values between the client and server, and serializing them to and from streams of data.
Contents |
Introduction
NetGore supplies its own form of serialization for properties. While .NET already employs some good and faster serialization methods, NetGore's demands for serialization are pretty high since a lot of the serialized data ends up going over the network. This means data needs to be serialized quickly and have a small output. Monitored values also need to be able to be automatically detected for changes, and sent over the network when changed.
SyncValue attribute
The NetGore.SyncValueAttribute is an attribute that can be attached to properties. This is typically done on a DynamicEntity (see page for details). While it is possible to manually set up usage of the SyncValueAttribute for other classes manually, it is generally not needed.
Over the network
Information about a DynamicEntity will always go from server to client. When the DynamicEntity is first created, it is sent to the client by including the name of the class, the MapEntityIndex, and the value of every property with the SyncValue. After being constructed, values are only sent when they are changed, and are sent to everyone in the map.
Updating values over the network can be skipped by specifying SkipNetworkSync = true on the SyncValueAttribute. Set this property to true when you have a property that the client does not need to know about. For example, a client should know that a teleport entity exists (so they can use it), but does not need to know where the teleporter goes since that is handled in the server.
File IO
The NetGore.SyncValueAttribute also allows for specifying what properties should be included in serialization and deserialization of an object to file. The primary function of this feature is to allow you to add a DynamicEntity to a map, then have it automatically load with the server at runtime. This is how teleports are handled in the engine by default, and makes it very easy to add other new types of entities to maps.
PropertySync classes
For serialization to take place, the engine needs to know how to read and write the values to and from an IValueReader and IValueWriter. This is done by using the NetGore.IO.PropertySync.PropertySyncHandlerAttribute. This attribute is attached to a class that defines how to read and write a single type.
It is required for one of these classes to be defined for each unique type being used with SyncValue. A large number of types are defined in the engine by default, but you will likely need to define your own at some point. If no class with the PropertySyncHandlerAttribute can be found when needed, you will see an error message that says something like:
No PropertySyncHandler exists for type `YouTypeHere`...
To create the PropertySync class, it is easiest to just look at how the existing classes are done. For the most part, your class will look something like the following (for an enum):
[PropertySyncHandler(typeof(MY_ENUM_NAME))] public sealed class PropertySyncMY_ENUM_NAME : PropertySyncBase<MY_ENUM_NAME> { public PropertySyncMY_ENUM_NAME(SyncValueAttributeInfo syncValueAttributeInfo) : base(syncValueAttributeInfo) { } protected override MY_ENUM_NAME Read(string name, IValueReader reader) { return reader.ReadEnum<MY_ENUM_NAME>(name); } protected override void Write(string name, IValueWriter writer, MY_ENUM_NAME value) { writer.WriteEnum(name, value); } }
Place this class in the same project and scope as the type you are defining it for.
Usage of this class is automatic. Once you define it, the engine handles the rest.