1. Request to control what a player can spectate and to cancel switching targets
    Code:
    // BasePlayer
    public void UpdateSpectateTarget(string strName)
        {
            this.spectateFilter = strName;
            IEnumerable<BaseEntity> baseEntities = null;
            if (!this.spectateFilter.StartsWith("@"))
            {
                IEnumerable<BasePlayer> basePlayers =
                    from x in BasePlayer.activePlayerList
                    where (x.IsSpectating() || x.IsDead() ? false : !x.IsSleeping())
                    select x;
                if (strName.Length > 0)
                {
                    basePlayers =
                        from x in basePlayers
                        where (x.displayName.Contains(this.spectateFilter, CompareOptions.IgnoreCase) ? true : x.UserIDString.Contains(this.spectateFilter))
                        where x != this
                        select x;
                }
                basePlayers =
                    from x in basePlayers
                    orderby x.displayName
                    select x;
                baseEntities = basePlayers.Cast<BaseEntity>();
            }
            else
            {
                string str = this.spectateFilter.Substring(1);
                IEnumerable<BaseNetworkable> baseNetworkables =
                    from x in BaseNetworkable.serverEntities
                    where x.name.Contains(str, CompareOptions.IgnoreCase)
                    where x != this
                    select x;
                baseEntities = baseNetworkables.Cast<BaseEntity>();
            }
            BaseEntity[] array = baseEntities.ToArray<BaseEntity>();
            if ((int)array.Length == 0)
            {
                this.ChatMessage("No valid spectate targets!");
                return;
            }
            BaseEntity baseEntity = array[this.SpectateOffset % (int)array.Length];
            if (baseEntity != null)
            {
                object[] objArray = new object[] {this, baseEntity };  
                object obj = Interface.CallHook("OnUpdateSpectateTarget", objArray);
                if (obj is BaseEntity)
                {
                     baseEntity = (BaseEntity)obj;
                }
                else if (obj is bool && !(bool)obj)
                {                
                     return;
                }            if (!(baseEntity is BasePlayer))
                {
                    this.ChatMessage(string.Concat("Spectating: ", baseEntity.ToString()));
                }
                else
                {
                    this.ChatMessage(string.Concat("Spectating: ", (baseEntity as BasePlayer).displayName));
                }
                this.ClearEntityQueue(null);
                using (TimeWarning timeWarning = TimeWarning.New("SendEntitySnapshot", 0.1f))
                {
                    this.SendEntitySnapshot(baseEntity);
                }
                base.gameObject.Identity();
                using (TimeWarning timeWarning1 = TimeWarning.New("SetParent", 0.1f))
                {
                    base.SetParent(baseEntity, 0);
                }
            }
        }
     
  2. Wulf

    Wulf Community Admin

    As of right now, this would either need 3-4 modify hooks to make it, a wrapper, or changes to the patcher.
     
  3. No biggie, I ended up writing something to manage it