Empeld
Empeld plugin documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events
pluginbase.Objects.Syncable.SyncableObject Class Reference

An object that acts as a base class for objects that want syncables as fields Most entities use this class More...

Inheritance diagram for pluginbase.Objects.Syncable.SyncableObject:
pluginbase.Objects.Syncable.SyncableBase< T > pluginbase.Objects.Syncable.INetSyncable pluginbase.Objects.Syncable.INetWatcher essentials.action.ItemFramework.Containers.InventorySync essentials.action.ItemFramework.ItemBase pluginbase.Objects.Syncable.Entity.EntityBase essentials.action.ItemFramework.Containers.SelectableInventorySync essentials.action.ItemFramework.BlockItem essentials.action.ItemFramework.Interactive.Bases.UseableItemBase essentials.action.ItemFramework.ItemBundle essentials.action.Entities.Actor.ActorBase essentials.action.ItemFramework.World.ItemDropEntity essentials.BlockEntities.BlockEntityBase< TBlock > essentials.Systems.Structures.Structure pluginbase.Objects.Syncable.Entity.Static.StaticEntityBase

Public Member Functions

 SyncableObject ()
 Initializes a new instance of the pluginbase.Objects.Syncable.SyncableObject class. More...
 

Protected Member Functions

sealed override void ResetWatch ()
 Reset variables watched status More...
 
sealed override void TouchRecurse ()
 Touch self, including all children of this syncable object More...
 
sealed override void EncodeTo (BinaryWriter writer, EncodeContext context)
 Encode changes to binary data More...
 
sealed override void DecodeFrom (BinaryReader reader, DecodeContext context)
 Decode changes from binary data More...
 
sealed override void Persist (IPersistObject obj)
 Build up a persistant object for this syncable, including all sync children and persist objects More...
 
sealed override void Load (IReadPersistObject obj)
 Load a given persistent object back into this instance More...
 
- Protected Member Functions inherited from pluginbase.Objects.Syncable.SyncableBase< T >
void Touch ()
 Touch the instance, notifying something has changed More...
 
virtual void OnChanged ()
 Raises the changed event. More...
 

Properties

virtual ushort NetOwnerId [get]
 Gets the network owner of this object (user id) More...
 
- Properties inherited from pluginbase.Objects.Syncable.INetSyncable
INetWatcher Watcher [get, set]
 Who is watching (who to inform of a change) More...
 
bool Modified [get]
 Gets a value indicating whether this pluginbase.Objects.Syncable.INetSyncable is modified. More...
 

Additional Inherited Members

- Events inherited from pluginbase.Objects.Syncable.SyncableBase< T >
Action< T > Changed
 Event triggered when any change occurs on this object, either locally or over the network More...
 
Action< T > NetUpdate
 Event triggered when a change occurs resulting from a change over the network More...
 
Action< T > Touched
 Event occurs only when an object is first touched. Usually the first instance of a local-change More...
 

Detailed Description

An object that acts as a base class for objects that want syncables as fields Most entities use this class

Constructor & Destructor Documentation

pluginbase.Objects.Syncable.SyncableObject.SyncableObject ( )

Initializes a new instance of the pluginbase.Objects.Syncable.SyncableObject class.

Attribute: prop.Member.Name

= syncObject;

41  {
42  Type myType = this.GetType();
43 
44  var syncProperties = myType
45  .GetAllMemberVars(x => Attribute.IsDefined(x, typeof(SyncableAttribute)))
46  .OrderBy(x => x.Member.Name);
47 
48  if (syncProperties.Count() > MAX_SYNC_VAR_COUNT)
49  {
50  throw new Exception(string.Format("Syncable class {0} has exceeded max property count of {1}/{2}", myType.Name, syncProperties.Count(), MAX_SYNC_VAR_COUNT));
51  }
52 
53  var watchList = new List<WatchItem>();
54  foreach (ReflectionExtensions.UnifiedVariable prop in syncProperties)
55  {
56  if (!prop.IsField || !(prop.IsPrivate || prop.IsProtected) || !prop.IsReadonly)
57  {
58  throw new Exception(string.Format("Syncable '{0}' must be a private/protected readonly field", prop.Member.Name));
59  }
60 
61  SyncableAttribute attr = (SyncableAttribute)prop.Member.GetCustomAttributes(typeof(SyncableAttribute), true).Single();
62  INetSyncable syncObject = prop.Getter(this) as INetSyncable;
63 
64  if (syncObject == null)
65  {
66  syncObject = Activator.CreateInstance(prop.Type) as INetSyncable;
67  }
68 
69  if (syncObject != null)
70  {
71  //Setup the new syncable with this as the watcher
72  syncObject.ResetWatch(); //It is possible that something poked it during setup. We don't really care
73  syncObject.Watcher = this;
74  watchList.Add(new WatchItem{
75  Var = syncObject,
76  Attr = attr,
77  Name = prop.Member.Name,
78  OwnerProp = prop
79  });
80 
81  prop.Setter(this, syncObject);
82 
83  //Attach any validators
84  if (syncObject is IValidatedNetSyncable)
85  {
86  IValidatedNetSyncable validatedObject = syncObject as IValidatedNetSyncable;
87  IEnumerable<ValidateAttribute> propertyValidators = prop.Member.GetCustomAttributes(typeof(ValidateAttribute), true).Cast<ValidateAttribute>();
88 
89  foreach(var validator in propertyValidators)
90  {
91  validatedObject.AddValidator(validator);
92  }
93  }
94 
95  _namedVars[prop.Member.Name] = syncObject;
96  }
97  else
98  {
99  throw new Exception(string.Format("Invalid watchable property {0} does not implement watchable interface", prop.Member.Name));
100  }
101  }
102  _watchedVars = watchList.ToArray();
103 
104 
105  //Collect up all persist items
106  _persistVars = myType.GetAllMemberVars(x => Attribute.IsDefined(x, typeof(PersistAttribute))).ToArray();
107  }
static IEnumerable< UnifiedVariable > GetAllMemberVars(this Type type, Predicate< MemberInfo > predicate)
Gets all member vars, including privates, of each class
Definition: ReflectionExtensions.cs:89
Definition: ReflectionExtensions.cs:8
Attribute to denote an item on a component, entity, or otherwise, as persisting to file ...
Definition: PersistAttribute.cs:9

Member Function Documentation

sealed override void pluginbase.Objects.Syncable.SyncableObject.DecodeFrom ( BinaryReader  reader,
DecodeContext  context 
)
protectedvirtual

Decode changes from binary data

Parameters
readerReader.
contextContext.

Attribute: varIndex

;

Implements pluginbase.Objects.Syncable.SyncableBase< T >.

310  {
311  byte varIndex;
312  while((varIndex = reader.ReadByte()) != byte.MaxValue)
313  {
314  if (varIndex < _watchedVars.Length)
315  {
316  var watchable = _watchedVars[varIndex];
317 
318 #if DEBUG
319  AssertWatchableValid(watchable);
320 #endif
321 
322  if ( ShouldDecodeField(watchable, context ) )
323  {
324  watchable.Var.DecodeFrom(reader, context);
325  context.Increment();
326  if (context.Touch)
327  {
328  watchable.Var.Touch();
329  }
330  }
331  else
332  {
333 #if DEBUG
334  //In normal situations, this would be a hacker. In debug situations, this isn't good
335  throw new Exception(string.Format("Client {0} changed syncable that belonged to {1}; var {2}:{3}", context.FromId, this.NetOwnerId, varIndex, watchable.Name));
336 #else
337  context.Fail(); //Failing a packet will usually trigger the server resending the entity to the client to keep them in-sync
338  //Someone changed something they weren't supposed to
339 #endif
340  }
341  }
342  else
343  {
344 #if DEBUG
345  //In normal situations, this might be a malformed packet. In debug situations, something broke
346  throw new Exception(string.Format("Syncable index higher than max objects {0}/{1}", varIndex, _watchedVars.Length));
347 #else
348  break;
349 #endif
350  }
351  }
352  }
sealed override void pluginbase.Objects.Syncable.SyncableObject.EncodeTo ( BinaryWriter  writer,
EncodeContext  context 
)
protectedvirtual

Encode changes to binary data

Parameters
writerWriter.
contextContext.

Attribute: i

; //alias

Implements pluginbase.Objects.Syncable.SyncableBase< T >.

245  {
246  for (int i=0; i<_watchedVars.Length; ++i)
247  {
248  WatchItem watchable = _watchedVars[i]; //alias
249 
250 #if DEBUG
251  AssertWatchableValid(watchable);
252 
253  //Check in DEBUG if we actually own what we're changing
254  //TODO: Disabled the ownership check for now because there's some logic in network pre-syncing that needs this
255  //IE: We move an entity based on their physics client-side only with no expectation of syncing
256  /*if (watchable.Var.Modified && !ContextOwnsField(watchable, context))
257  {
258  throw new Exception(string.Format("Client {0} changed syncable that belongs to {1}; var {2}:{3}", context.EncodingId, this.NetOwnerId, i, watchable.Name));
259  }*/
260 #endif
261 
262  if (ShouldEncodeField(watchable, context))
263  {
264  writer.Write((byte)i);
265  watchable.Var.EncodeTo(writer, context);
266  context.Increment();
267  }
268  }
269 
270  writer.Write(byte.MaxValue); //terminator
271  }
sealed override void pluginbase.Objects.Syncable.SyncableObject.Load ( IReadPersistObject  obj)
protectedvirtual

Load a given persistent object back into this instance

Parameters
objObject.

Attribute: item.Member.Name

;

Implements pluginbase.Objects.Syncable.SyncableBase< T >.

397  {
398  foreach(var item in _namedVars)
399  {
400  var sub = obj.GetObject(item.Key);
401  if (sub != null)
402  {
403  try
404  {
405  item.Value.Load(sub);
406  }
407  catch
408  {
409 #if DEBUG
410  throw;
411 #endif
412  }
413  }
414  }
415 
416  foreach(var item in _persistVars)
417  {
418  try
419  {
420  if (obj.Has(item.Member.Name))
421  {
422  object o = obj[item.Member.Name];
423  if (!item.Type.IsInstanceOfType(o))
424  {
425  o = Convert.ChangeType(o, item.Type);
426  }
427  item.Setter(this, o);
428  }
429  }
430  catch
431  {
432 #if DEBUG
433  throw;
434 #endif
435  }
436  }
437  }
IReadPersistObject GetObject(string name)
sealed override void pluginbase.Objects.Syncable.SyncableObject.Persist ( IPersistObject  obj)
protectedvirtual

Build up a persistant object for this syncable, including all sync children and persist objects

Parameters
objObject.

Attribute: item.Member.Name

= item.Getter(this);

Implements pluginbase.Objects.Syncable.SyncableBase< T >.

360  {
361  foreach(var item in _namedVars)
362  {
363  try
364  {
365  var sub = obj.GetOrCreateObject(item.Key);
366  item.Value.Persist(sub);
367  }
368  catch
369  {
370 #if DEBUG
371  throw;
372 #endif
373  }
374  }
375 
376  foreach(var item in _persistVars)
377  {
378  try
379  {
380  obj[item.Member.Name] = item.Getter(this);
381  }
382  catch
383  {
384 #if DEBUG
385  throw;
386 #endif
387  }
388  }
389 
390  }
IPersistObject GetOrCreateObject(string name)
sealed override void pluginbase.Objects.Syncable.SyncableObject.ResetWatch ( )
protectedvirtual

Reset variables watched status

Reimplemented from pluginbase.Objects.Syncable.SyncableBase< T >.

115  {
116  base.ResetWatch();
117  foreach(WatchItem watchable in _watchedVars)
118  {
119  watchable.Var.ResetWatch();
120  }
121  }
sealed override void pluginbase.Objects.Syncable.SyncableObject.TouchRecurse ( )
protectedvirtual

Touch self, including all children of this syncable object

Reimplemented from pluginbase.Objects.Syncable.SyncableBase< T >.

127  {
128  base.TouchRecurse();
129  foreach(WatchItem watchable in _watchedVars)
130  {
131  watchable.Var.TouchRecurse();
132  }
133  }

Property Documentation

virtual ushort pluginbase.Objects.Syncable.SyncableObject.NetOwnerId
getprotected

Gets the network owner of this object (user id)

The net owner identifier.


The documentation for this class was generated from the following file: