/// <summary>
        /// instantiates a remote body syncer system
        /// </summary>
        /// <param name="syncer">the syncer</param>
        /// <param name="matcher">the matcher of entities whose bodies to sync</param>
        /// <param name="interpCacheSize">size (>=2) of the kinematic snapshot ring-buffer cache</param>
        /// <exception cref="ApplicationException">thrown if an invalid value is given for interpCacheSize</exception>
        public RemoteBodySyncerSystem(GameSyncer syncer, Matcher matcher,
                                      int interpCacheSize = 2) :
            base(matcher)
        {
            this.syncer = syncer;
            syncer.gamePeerConnected    += gamePeerConnected;
            syncer.gamePeerDisconnected += gamePeerDisconnected;
            this.interpCacheSize         = interpCacheSize;
            if (this.interpCacheSize < 2)
            {
                throw new ApplicationException(
                          $"invalid value {interpCacheSize} given for interpolation cache size. value must be at least 2.");
            }
#if DEBUG
            Global.log.trace($"body syncer interpolator cache size: {interpCacheSize}");
#endif
        }
 public ClientMessageHandler(GameSyncer syncer)
 {
     this.syncer = syncer;
 }
 public HeartbeatHandler(GameSyncer syncer) : base(syncer)
 {
 }
 public BodyUpdateHandler(GameSyncer syncer) : base(syncer)
 {
 }
 public BodyLifetimeUpdateHandler(GameSyncer syncer) : base(syncer)
 {
 }
 public BodyKinematicUpdateHandler(GameSyncer syncer) : base(syncer)
 {
 }
 public PresenceMessageHandler(GameSyncer syncer) : base(syncer)
 {
 }