1. I'm wondering if I can make a player invisible to only one specific player, but be visible to everyone else. Is there any way I could do this?
     
  2. Wulf

    Wulf Community Admin

    Yes, take a look at the Vanish plugin of mine for an example. It involves the CanNetworkTo hook.
     
  3. Code:
    object CanNetworkTo(BaseNetworkable entity_to_stream, BasePlayer player_to_receive_data)
            {
                BasePlayer player_to_stream = entity_to_stream.gameObject.ToBaseEntity().ToPlayer();
                if(!player_to_stream.IsValid()) return null; // Make sure to get the player from the entity and check if it's valid
                if(player_to_receive_data.displayName.Equals("Your custom checks here ..."))
                    return false; // Return non null so the callback will cancel the default procedur
                return null; // If nothing happens, return nothing so the callback can continue to proceed normally
            }
    You also need to send a fake entity destroy packet to all clients except yourself.

    Made this function from the Vanish plugin. You might still want to add linked or parented entites on your player and destroy them aswell.
    Code:
            void MakeInvisible(BasePlayer Player, bool State)
            {
                if(State)
                {
                    Invisible.Add(Player);
                    var connections = new List<Connection>();
                    foreach(var basePlayer in Utils.GetPlayers())
                    {
                        if(Player == basePlayer || !basePlayer.IsConnected) continue;
                        connections.Add(basePlayer.net.connection);
                    }                if(Net.sv.write.Start()) // Try catch?
                    {
                        Net.sv.write.PacketID(Network.Message.Type.EntityDestroy);
                        Net.sv.write.EntityID(Player.net.ID);
                        Net.sv.write.UInt8((byte)BaseNetworkable.DestroyMode.None);
                        Net.sv.write.Send(new SendInfo(connections));
                    }
                    var item = Player.GetActiveItem();
                    if(item?.GetHeldEntity() != null && Net.sv.write.Start())
                    {
                        Net.sv.write.PacketID(Network.Message.Type.EntityDestroy);
                        Net.sv.write.EntityID(item.GetHeldEntity().net.ID);
                        Net.sv.write.UInt8((byte)BaseNetworkable.DestroyMode.None);
                        Net.sv.write.Send(new SendInfo(connections));
                    }
                }
                else
                {
                    Invisible.Remove(Player);
                    Player.SendNetworkUpdate();
                    Player.GetActiveItem()?.GetHeldEntity()?.SendNetworkUpdate();
                }
            }

    Should work, didn't test it. This won't remove attached entities on your player.
    I don't know if
    Code:
    entity_to_stream.gameObject.ToBaseEntity().ToPlayer();
    Is faster than
    Code:
    entity_to_stream as BasePlayer;