Sign In Register

How can we help you today?

Start a new topic

[C#] RTData.Get() returns dirty object

when I get an RTData it should be empty, but it contains data if that instance was used in the past

using (var d1 = GameSparks.RT.RTData.Get ()) {
			d1.SetInt (1, 1);
			d1.SetString (2, "asdf");
		}
		using (var d2 = GameSparks.RT.RTData.Get ()) {
			Debug.LogFormat ("{0} {1}", d2.GetInt (1), d2.GetString (2)); // instance is not reset
		}

it may be a problem if I have a larger initialization packet and send smaller packets after it, the data I don't overwrite remains and get sent as garbage

or if I receive a small packet and I get passed an RTData with garbage that I hopefully don't read, but sometimes I have to read an array of objects and I keep reading until I get null


Hi,

extension method are just syntactic sugar for static methods and therefore can only access the public stuff, exactly as they would be if I implemented them in a controller. (there is also a controller that manages the packet, it just delegates the serialization stuff in a separate class (in it's own namespace))

I also have a SetSeat/SetMatchOrder pair as extension, and that enables fluent syntax when I send/receive packets     

using (var packet = RTData.Get ())
    SendRTPacket (OpCode.StartMatch,
                  packet.SetInt (1, matchId)
                        .SetMatchInitializer (2, matchInitializer));

     

and this is all built on top of the public stuff

a "change in the implementation" will not break extension method specifically, but any method that relies on the concrete type (and I don't see any IRTData interface to use) if the change regards the public part (and public stuff is not to be considered implementation but part of the API) or hacky stuff involving reflection to access internals (that I don't do in production code)


ps: your GetVector3 is an extension method too

Hi Mauro,


Was there any particular reason you implemented these as extension methods? In general, its recommended that you implement extension methods sparingly and only when you have to. When using an extension method to extend a type whose source code you cannot change, you run the risk that a change in the implementation of the type will cause your extension method to break. Would it be easier / safer if you implemented a controller to handle the incoming packet from the RTPacket type this should avoid any previous instance data with RTData.


Kind regards,

 - Steve

for simple struct, I did it exactly like that.

but I have an array that I read like  

public static Seat GetSeat (this RTData data, uint index)
		{
			data = data.GetData (index);
			if (data == null)
				return null;
			var status = (SeatStatus)data.GetInt (1).Value;
			switch (status) {
			case SeatStatus.Empty:
				return Seat.Empty ();
			case SeatStatus.InvitePending:
				return Seat.Invitation (data.GetString (2), data.GetString (3));
			case SeatStatus.PlayerSeated:
			case SeatStatus.Bot:
				return new Seat (status, data.GetString (2), data.GetString (3), data.GetInt (4).Value);
			}
			return null;
		}

  

		public static Seat[] GetMatchOrder (this RTData data, uint index)
		{
			data = data.GetData (index);
			if (data == null)
				return null;
			Seat seat;
			index = 1;
			var matchOrder = new List<Seat> ();
			while ((seat = data.GetSeat (index++)) != null)
				matchOrder.Add (seat);
			return matchOrder.ToArray ();
		}

 not really yet a problem because I read the MatchOrder only once in the Init packet, but I need some move recover mechanism (e.g. if a player disconnects mid-game and lose some packets, then he reconnects and asks the server for "all actions between <last id received> and latest")

(i'm considering to implement this as a series of single-move packets)

(manually validating everything is ok, but I could forget something and get bitten later, a single null check at the beginning is more consistent)

Hi Mauro,


Would you be able to provide a sample of the way you are receiving your packets. One way I generally recommend is to follow the structure below. This should avoid that issue of previous instance data.

  

private void OnPacketReceived(RTPacket packet)
{
    switch (packet.OpCode)
    {
        // Player Position Update
        case 1:
            _playerController.DoSomething(_packet); 
            break;
    }
}

  

public static PositionUpdateModel DoSomething(RTPacket packet)
{
    var int1 = packet.Data.GetInt(1);
    var vector1 = packet.Data.GetVector3(2);
    var vector2 = packet.Data.GetVector3(3);
    if (vector1 == null || vector2 == null || int1 == null) return null;
        return new PositionUpdateModel(
            (int) int1,
            (Vector3) vector1,
            (Vector3) vector2);
    }
}

  

Kind regards,

 - Steve

             

                

Hi Steve,

that's what I currently do when sending packets. when I receive them, the SDK internally does RTData.Get()


fortunately I don't do heavy stuff, but I manage some arrays with "keep reading sequentially until you get null". if the packet is too dirty I risk overreading my data


and it causes some WTFs when debugging and I see stuff that shouldn't exist

Hi Mauro,


One way to get a new instance of RTData would be to just new up one, so like so var data = new RTData(); do you think this would suit your needs?


Kind regards,

 - Steve

Login to post a comment