Search code examples
c#.netluamonogame

C# - make it so only the same instance can modify its properties/call methods?


I am making a game engine with the MonoGame Framework. Since this is a multiplayer game, other players need to know certain information about other players, such as position and velocity, typically for AI reaction.

I am about to implement Lua scripting for player actions. However, I can't currently think of a way to have it so a player cannot modify the other players' information, such as position and name.

For instance, say I have the following property in C#:

public Vector2 Pos { get { return pos; } private set { this.pos = value; } }
private Vector2 pos;

Looks good, right? Well not quite. Say I have a function that returns the closest enemy called GetNearestEnemy(), which returns another Player. Because the Player class has access to its own properties, I can just as easily do something like this in some other method:

public void DoStuff()
{
    Player otherPlayer = GetNearestEnemy();
    otherPlayer.Pos = new Vector2(34,151);
}

So I think "maybe I could just pass the instance as a parameter."

public void SetPos(Player instance, Vector2 pos)
{
    if (instance != this)
        return;
    else
        this.pos = pos;
}

... and always pass "this" as an argument. However, that also has the same problem: I could just as easily pass GetNearestEnemy() to the method and I'd be able to set the enemy position.

This is the type of behavior I am trying to prevent. Is there a way to preferably either:

  1. Get the instance that called the method?
  2. Implicitly set a parameter from the calling object without them knowing?

Or is there some other way to approach it that I'm not seeing?


Solution

  • Unfortunately not.

    There is no language support for what you want.

    Let me be specific about what you want just so that you understand what I answered.

    Your question is basically this: Given that I have two instances of an object, and I have properties in this object that have a private setter, is there any language support for ensuring that instance #1 cannot change this private information of instance #2?

    And the answer is no.

    This will compile and "work":

    public class Test
    {
        public void TestIt(Test t)
        {
            t.Value = 42;
        }
    
        public int Value
        {
            get;
            private set;
        }
    }
    
    ...
    var t1 = new Test();
    var t2 = new Test();
    t1.TestIt(t2); // will "happily" change t2.Value
    

    Basically, the onus is on you to make sure this doesn't happen if you don't want it to happen. There is no language or runtime support to prevent this.

    The access modifiers you can use are:

    • public: Anyone can access this
    • private: Only the type can access this
    • protected: Only the type, or a descendant of the type, can access this
    • internal: Any type in the same assembly can access this
    • internal protected: Any type in the same assembly or a descendant, can access this

    Other than this, you have no other options. So "only the same instance can access this" does not exist as an access modifier.