Check out Amazon.com!

BlitzCoder WorklogsMain Worklogs Page
"[BlitzPlay - Pro]"
Owner: surreal
Showcase Entry: None
Total Entries: 3
surreal
Entry: 3
06/17/2002
10:49 PM
Sweet!!

I found a bug in the reliability code that has been causing me alot of grief over the past few days.. basically sometimes the header was being tacked on twice on resends, but its all fixed now. Now the reliability system is complete.. and fast as hell! Now all thats left for me to do is to packetloss-proof the initial connecting phase, and I'm done!

This has me excited, hopefully the first complete version of blitzplay - pro will be ready within days. I still have to write up docs and do a demo prog, so the release may still be a little ways away, but definately within sight!

woo :) It seems like I've been working on this forever.. I'll be so happy when its complete!
surreal
Entry: 2
06/11/2002
05:28 PM
Well here I am bored at work again, might as well whip up another log showing what I've been able to do recently..

I've figured out a solution which should clear a couple of my reliability woes right up! The main goals that I have with regards to reliability are: speed, speed, and oh yeah, efficiency. The method that I had used before (in older versions of BlitzPlay) was *fairly* quick, and moderately efficient, but it had a few drawbacks..

Namely, it used 2 bytes to identify packets, whereas I was determined to shave it down to 1. Also another problem I had with my older method was that it used the somewhat straightforward approach of having a type list for reliability info, and then creating a new instance of this type every time a new reliable message was sent. (and of course, deleting that instance when the message was acknowledged) This means that along with the actual variable assignment that was and has to take place, there was the additional overhead of constantly allocating and deallocating memory.

So how did I get around this? Well, I made a little discovery about types which enabled me to completely change how I keep track of the info within memory. I already have every single variable relevant to individuals stored within a type list. Now I simply have another type, specific to reliable packet info (ip, port, contents, etc), which I have as a field to the parent Type list. "Wow, types within types, thats not that amazing" Well aside from the fact that I had never tried to/had to do that, and was pleased that I figured it out, I also discovered that: *you can have arrays of types, within types!*

This is key to my new approach, as because of this, it allows me to have an individual "reliability buffer" for every single player. Otherwise.. the problem that I was facing before with limiting ACK info to 1 byte meant having only 256 seperate messages available to be "in use" at any given point. Say you have a 10 client game, thats like 25 messages *per client only* that could have been in use.. And obviously anything MMORPG is at that point out of the question. So, *this* means that the Host can keep track of seperate ACK lists for each player, and have 256 available "message slots" *per person*! (whenever I refer to message slots, I'm just talking about the type instances within the array)

I was pretty excited about this, as it also meant that I was now using Arrays (of types) instead of simply types. This meant that upon initializing the new type instance for a new player, I could also allocate all the memory I'd require for the reliability information, and then never have to worry about that again! So I managed to deal with the problem of the constant creating and deleting types, as well as bringing the ACK ID size down to a single byte :) It also meant that I had the additional bonus of quicker memory access through the array, since I could easily "get at" the info for ACK 200 without looping through the 199 before it :)

But! I wasn't quite finished yet. As I started to implement these ideas, I quickly realized that I would have to change over how I scanned through the reliable packets that had been sent, to see if they would require a resend. The way I had done it before was the obvious way of doing something like a "For msg.ReliableMessage = Each ReliableMessage" and then dealing with each message that way. With this new method however, this was obviously no longer possible as scanning through each element of the ReliableMessage type list would simply mean scanning *everyone's* ACK "buffer". Another problem was that there was going to be 256 message slots that would have to be scanned through, per person, and that scanning through the entire array every single BP_UpdateNetwork() call wouldn't be very efficient at all, possibly even outweighing the speed gained compared to the old system (at least in comparing minimal traffic, ie scanning w/ a For Each loop through say 3 messages would probably be faster than scanning through 256 elements of an array)

So I decided that my approach to that situation would be to have an extra element of the array, and use it as an index to the highest ACK in use. This way I could simply scan from 0 to (howevermanyacksinuse) and that would save a *lot* of scanning through empty slots. Then it just became an issue of making sure to assign ACK's to the lowest open slot, just to ensure that there were as little blank slots that would be scanned through.

This of course brought me to the problem that I was talking about in my previous worklog! How could I keep ACK's quick to scan through, but also keep them sequentially incrementing so that storing a buffer of received ACK's would be meaningful to determinining if a packet received is a duplicate or not? This is when I went back to the drawing board and modified the reliability even more! :D Hehe, what a perfectionist, eh?

Fortunately, I'm back at the office at my job, and well working for an ISP during the summer is a hella slow job, so I've got time to kill :) In other words, I've already thought up another solution and have implemented it! :D And as of last night, I think I may have even cleaned the bugs up. (Need more time to test, but the supervisors will be going home soon, so I'll be able to fire up some Blitz soon!) Anyhow I don't want to give all my secrets away, so I think I'll let this worklog entry come to a close right around here.. but lets just say I'm very excited about all this, BP-Pro is getting closer and closer to being! :)
surreal
Entry: 1
06/07/2002
09:25 PM
So.. what all has been done, and whats left to go?

Well I've already rewritten the underlying message sending code, so the header info is now contained within a single byte. Its been working quite well and I'm satisfied that its stable!

I've also already finished writing the reliability code, although after seeing how it can react on a bad connection, I've planned another way of structuring and identifying the ACK info. A problem I've seen can be described by the following scenario: PlayerA sends packet #1 to PlayerB. PlayerB receives the packet and replies with an ACK #1 packet, however it gets dropped. PlayerA therefore does *not* get the ACK, and assumes that the packet never got to PlayerB, and thus resends packet #1. PlayerB then gets the packet again, and thus has a duplicate packet..

For example if it was a chat packet, the message would show up twice. The way that I could get around this before was to simply have (in this example, PlayerB) keep track of the recently received ack #'s and then check against this list when every new reliable packet is received. This way you could easily ignore packets that were duplicates..

Unfortunately though the way I'm structuring the ACK data I have BP ensure that its always using the lowest ACK ID possible (it has to do with how ACK's are maintained within an array now for speed, and to maintain some sort of order so that they can be scanned more efficiently), therefore its possible for packet #1 to be sent, acknowledged, and then that 'spot' is 'cleared', and then the next packet would also be #1 as well. This obviously renders it useless to track the last received packet #'s! So! I've decided to change how I keep track of ACK's and which are in use, and it will still be extremely fast to scan through (now relying on bit operations, what computers are best at!), but will also lend itself to having a sequentially incrementing ACK index number, which will mean that it will again be possible and meaningful to keep track of the received packets.

I already have the necessary changes planned out in my notebook.. just have to implement them the next time I get a chance to sit down at my computer and work at it. (Writing this to kill time at work, hehe)

Aside from that.. Ping tracking is back in, as well as packet loss tracking, so as before the clients will be aware of their connection status to the host, and the host will track all clients. A few new functions this brings in are BP_GetMyPing(), BP_GetMyPacketLoss(), BP_GetClientPing(client_id%), and BP_GetClientPacketLoss(client_id%).

My GameTime concept is also recently in, but I haven't had time to test it thoroughly. If you're not sure what it is, its basically a clock that will be the same consistent "game time" across all clients, making it much easier to do prediction/interpolation/movement schemes since you'll have a uniform Time which is the same across the network (in other words, you don't have to worry about everyone having different times returned by their MilliSecs() function). Also this value is constantly updated throughout the game to eliminate discrepencies that can emerge due to inconsistent lag, and its set up to update at a variable rate which you can set. (And don't worry.. bp-pro won't update and send packets behind your back, I have it set up so it piggy-backs on reliable packets that your game will send anyways, so the updates will be nearly invisible to you, bandwidth and traffic-wise)

I've already imported the code into one of my old demo's and got it working locally, but I haven't had much time to test it online. (It seems I need to make more internet friends who are up and bored at roughly midnight-5am, CST, heh) However I'm being much more careful with this project, with constant debugging and painstaking stepping through code line by line to ensure that its all behaving.

I've also kept the code relatively clean and modular, one change I'll make before release is to add Constants to represent all of BP's message types, so that it will be easier to program for. I've optimized the code quite a bit, even just by doing small things like only scanning for connection loss once a second, instead of every frame.

As soon as I do the reliability re-write and testing, add Cubic Spline functions, and then whip up some documentation, I should be ready for release! Overall I'm satisfied with how BP-Pro is coming along, and with one pre-order already in, I feel an obligation to try and get it out as soon as I can! :)
Copyright(c) 2000-2004, BlitzCoder. All Rights Reserved.

Plan software created by Krylar's Kreations