In the code for my networked game, the client receives a message that a player entity is controlled by the user or solely by the server.
UserControlled = msg.ReadBoolean();
This variable is set in absolutely no other location other than when it is instantiated with a default value of false. I’ve double checked this with the “Find all references” feature in Visual C#. In addition, there is no local variable within the scope of this statement with the same name. I’ve found that within the scope of the statement above, everything is find and dandy; the variable is set to true as shown by printing it to the console directly afterwards. At this point, strange things happen. Any time the variable is referenced from outside my player’s class, it correctly displays as true – but any time it is referenced from inside the player’s code, it returns the default value that the Boolean was instantiated as; either true or false.
I’m clueless beyond measure as to the problem, and any information that would lead to the solution is much appreciated 🙂
If you’d like more code, I can certainly provide it. I just wasn’t sure what else to include other than random references to the variable, so I decided to leave them out.
Thanks!
Edit for more code:
UserControlled is defined as a normal class-wide variable.
public bool UserControlled = false;
The method that sets the value:
public override void ParseUpdateMsg(NetIncomingMessage msg)
{
switch (msg.ReadByte())
{
case 0: // positional message
//snip
break;
case 1: // other info
// The following simply reads in the information
// I'm using Lidgren Network Library. It's extensively tested so I don't suspect that it's the issue
Speed = msg.ReadInt16();
Username = msg.ReadString();
UserControlled = msg.ReadBoolean();
MovingDir = msg.ReadString();
Health = msg.ReadInt16();
Hunger = msg.ReadInt16();
Mana = msg.ReadInt16();
// The following is simply debugging information to the screen
// As said above, UserControlled at this point is correctly displayed as True
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("--------------------------");
Console.WriteLine("Update message received!");
Console.WriteLine("ID: " + ID + "\tType: " + this.GetType().ToString());
Console.WriteLine("Speed: " + Speed);
Console.WriteLine("Username: " + Username);
Console.WriteLine("UserControlled: " + UserControlled);
Console.WriteLine("MovingDir: " + MovingDir);
Console.WriteLine("--------------------------");
Console.ForegroundColor = ConsoleColor.White;
break;
}
}
The following is the client code which receives the message and passes it to the player entity to evaluate:
switch (msg.ReadInt16())
{
case 1:
// Entity message
switch (msg.ReadByte())
{
case 0: // Create entity
//snip
break;
case 1: // Update entity
int id1 = msg.ReadInt16();
Entities[id1].ParseUpdateMsg(msg); // the player entity is passed the information
// At this point, there is only one entity, and that is the player.
// More debug information. Still displayed correctly as true.
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("--------------------------");
Console.WriteLine("-analysis 1-");
Console.WriteLine("(Within scope of update-entity message)");
Console.WriteLine("UserControlled: " + ((ClientEntPlayer)Entities[id1]).UserControlled);
Console.WriteLine("--------------------------");
Console.ForegroundColor = ConsoleColor.White;
break;
case 2: // Destroy entity
//snip
break;
}
// Displayed correctly here as well!
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("--------------------------");
Console.WriteLine("-Post-analysis 2-");
Console.WriteLine("(Within scope of generic entity message)");
Console.WriteLine("UserControlled: " + player.UserControlled);
Console.WriteLine("--------------------------");
Console.ForegroundColor = ConsoleColor.White;
break;
}
All debug code above is correctly displayed as True after the value is set. However, once we start getting into timed checking, it starts to become incorrect (but still only from the player’s code!)
The following is from the client’s update code. It displays correctly the UserControlled value every 5 seconds.
if (gameTime.TotalGameTime.Seconds % 5 == 0 && player != null && debugTime != gameTime.TotalGameTime.Seconds)
{
Console.ForegroundColor = ConsoleColor.DarkMagenta;
Console.WriteLine("--------------------------");
Console.WriteLine("Client's Timed Post-Analysis");
Console.WriteLine("Elapsed time: " + gameTime.TotalGameTime.Seconds + " sec");
Console.WriteLine("(Within scope of client update)");
Console.WriteLine("UserControlled: " + player.UserControlled);
Console.WriteLine("--------------------------");
Console.ForegroundColor = ConsoleColor.White;
debugTime = gameTime.TotalGameTime.Seconds;
}
This is the part that shows the player’s value is incorrect after the function is left. It displays false (and other code that relies on the player being controlled, like responding to keyboard input.) It’s essentially the same code as the client’s timed debug information, only instead it’s inside of the player’s update function.
if (gameTime.TotalGameTime.Seconds % 5 == 0 && debugTime != gameTime.TotalGameTime.Seconds)
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine("--------------------------");
Console.WriteLine("Player's Timed Post-Analysis");
Console.WriteLine("(Within scope of player update)");
Console.WriteLine("Elapsed time: " + gameTime.TotalGameTime.Seconds +" sec");
Console.WriteLine("UserControlled: " + UserControlled);
Console.WriteLine("--------------------------");
Console.ForegroundColor = ConsoleColor.White;
debugTime = gameTime.TotalGameTime.Seconds;
}
That’s about it. Thanks for helping.
As my comment above says, I can’t tell you what is happening, but can only give advice on how to debug.
Firstly, you say you’ve checked this but ensure that you are setting the correct
UserControlled. If it’s a member of the class (assume it’s a property?) then prefix it withthis.From what I understand in your question,
UserControlledis true when interrogated inside the class, but false when queried from outside the class. This can only be two things:To investigate further, is your property doing anything clever – i.e. is it doing anything other that setting and getting a backing field? Are you sure that you’re using a single instance of your class?