tayoung
tayoung

Reputation: 463

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?

Upvotes: 1

Views: 1074

Answers (4)

user2534096
user2534096

Reputation:

The original scenario posted can be handled using an interface e.g. IPeerPlayer that only exposes what other players should see and hides other properties (i.e. the other properties would not be in the IPeerPlayer interface.)

Upvotes: 0

serious6
serious6

Reputation: 307

That won't work. If Pos is a property with a private setter (as it is) the only way they could change it would be by calling a public method from within otherPlayer. Something like otherPlayer.SetPos(new Vector2(34,151)), where SetPos() is:

public void SetPos(Vector2 NewPos)
    { Pos = NewPos; }

Upvotes: 0

CodingYoshi
CodingYoshi

Reputation: 27009

If this is the property and you are worried about being set from elsewhere:

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

This will NOT work. So you do not need to worry:

Player otherPlayer = GetNearestEnemy();
otherPlayer.Pos = new Vector2(34,151); // <--- no this will not work

That property can only be set from within the class.

Upvotes: 0

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391346

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.

Upvotes: 1

Related Questions