That would be why I use the username, it is the one constant, that is always different for each user. I would not recommend keeping your own unique ID for 100 days per client... Instead, after 10 to 15 minutes of the client being, and staying disconnected from the server (perhaps longer if desired) be sure to remove the information - saving what is necessary (not the ID directly, although you can do that to if you make a unique id per username, although I prefer to keep the username the unique constant. (Did that make sense?).
The reason is simple, say you have your application on a public server that has been running for 100days, (over three months). Think of the number of different users that have connected and disconnected. Now for giggles, take that number an multiply by the amount of information you keep for each client; timeLastOnline, numLapsDriven, playerName, etc etc... It will be a lot of memory, and a lot that could be safely saved and stored until the next time that user jumps online, even if it is 20 minutes later.
But my first post describes the way I've used it, I would like to see other thoughts/takes on it. Though, my LFS to AIRS project uses it in slightly different way.
Connecting only to local copy, no servers. Making sure that only 1 connection exists (UCID = 0) and a few other things. Then I need to find the player's carm as that is the car my AI Controller can control and I need to save / update the PLID whenever it changes. Then I use MCI and OutGauge packets to update the AI by converting that information to a way that AIRS excepts and sending it to the AIRS project. Though, this is likely so far different than a server system, or even any other single player application that it doesn't exactly apply.
In my InSim applications I have a Connection/Driver manager. It allows only one -PLAYER- per connection. (With the exception of my AI project which is different altogether). I always use the UCID whereever possible, however more importantly almost all my lookups are done via username, which will get me the correct UCID or PLID (even if disconnect/reconnect, pit/spec/join had occurred). I use the username because it is unique _always_ for each individual racer, and it does not change for that racer. If a username is not connected for 10 minutes (on my casual systems that I've made) I throw the information about the user out of memory, saving what is needed to file/disk etc...
This was the easiest, most flexible way I found of doing this for Dash For Cash, and Head-to-Head. Both of which needed to keep information about a driver in the event of a disconnect/reconnect. By using the username I can get all information about the player; their current state, Playing, Spectating. Their Player Name (used for all LFS Displays), their UCID and PLID. Sure the downfall is a string comparison instead of a byte == byte comparison but for the flexibility, ease of use and everything this is well worth it - IMO. It would always be possible to make a new ID for my application to remove the need of string comparisons, but that has always been overkill IMO for something that runs with event-based structure. (I don't collect NLP / MCI messages during these applications, and if I was to start I would likely do my above example and create my own ID that stays the same for each racer.
I think that is what you were asking... It is how I work the system anyway during my casual and league systems.
Nowhere in there does it say you bought it from a store. You could have bought it online. Next time read your own damn post before accusing me, what was with the attitude?
Last edited by blackbird04217, .
Reason : Added Emphasis
You're complaining about downloading a game and not being able to activate/play it until it is released? That is idk, on the high end of idiocy...
Come on now, if the game is released for Feb th, 2010 you would need to expect that you can download, pre-order or 'get' your copy without being able to play it until it is officially released. Kinda like watching a band in concert, you don't complain when you get there 3hrs early to watch an empty stage... It is expected the band will come on at the time they said they would . . .
It really depends on the bank and other things. General policy here is the money will be transferred withing the 'business hours' of the 'business day'. So if it was place 8pm today it would be transferred tomorrow at 9am. (Business hours are typically 9am to 5pm). But if it was on 8pm Saturday, it would have taken until 9am this morning...
Also a catch a lot of banks have, that I've noticed, is they will hold the money until the check clears. Meaning, they give you the first $100 of the check, but the remainder will be held for two days, three days sometimes a full week before it 'clears'. Like I said though - this depends greatly on the bank policy. I've seen that transferring stuff online from my savings account to checkings account happens within the business hours, but I can initiate the transfer anytime. Since both accounts are with the same bank I do not need to wait for things to 'clear;.
I don't know the general rules of thumb over on that side of the puddle though.
That works great! Thanks Morpha, by the way I had to re-update my InSim.txt apparently ... I probably would have noticed that, but I didn't have RIP packets... Or Screenshot stuff... Hmm. Well, now I wonder if there is a way to detect Hotlap mode. Or at the very least to tell LFS to invalidate a hotlap. Not that I think my AI will compete with WRs but I don't want someone using it for any sort of malicious activity. Although I really don't know if I will share in the first place, but better to be safe all around than not.
Quick bragging note; my AI beat the LFS (pro) AI on the dragstip with LX6 (0.80) and FZR (0.24)... :P
Okay, so for my Artificial Intelligence in Racing Simulators project using Live For Speed, I really want to limit this to Single Player only, even better if I could limit to "Single Player" _ONLY_ meaning; no Multiplayer, no Hot lapping or Training.
Inside the IS_STA packet I can detect if the player is playing by checking to see if ISS_GAME is turned on _AND_ ISS_MULTI is turned off. However, using InSimSniffer, with many different situations I've found that even while watching a multiplayer replay ISS_GAME is turned on AND ISS_MULTI is turned off. Which would allow the LFS -> AIRS interface to believe it can successfully work, when it can not.
I can so far detect when the player is watching a SPR, connected to a server - including their own or multiplayer in general (which is a good elimination as that prevents people from abusing this to gain miles in LFS or compete with the AIRS).
But I still need to detect hotlapping and MPR correctly, any thoughts ideas or things I've overlooked?
EDIT: Ahaa. I can now detect the MPR correctly, actually I was already detecting it correctly. My detection works like this so far, still need to detect Hot Lap mode...
"OnConnect" -> Request IS_STA from LFS using the TINY...
When STA is received, set "IsSafeToUseAIRS = false".
Only set "IsSafeToUseAIRS = true" IF the ISS_MULTI is off and ISS_GAME is on.
If IsSafeToUseAIRS then request IS_NCN from LFS.
When NCN is sent, make sure there is only 1 Total connection, and that the UCID is 0, 'host'. Which will eliminate MPR, at least those where the player was not alone on the host. . . Hmmm.
Still would like a way to detect hotlapping, and perhaps a better way to detect MPR.
That would be because iSize is not a constant, so the size of the array is unknown - todo that you would need dynamic memory, which for your current situation I advise to stick with 1024, or 2048 if needed... At least for now.
I''m not too familiar with open source licenses, though recently I've been trying to use open source projects to get better at analyzing code. Something one of the companies I applied to mentioned I should practice by looking at open source projects. Problem is I haven't got a single one to build properly, they all have dependencies and strange stuff out of the gate... Why can't you just get a project and go? -sorry for the rant. I was going to ask if anyone knew of a small resource that described in laymen terms the advantages/disadvantages/purposes of each license as 'general overlook' versus getting nitty and gritty. Not exactly C++ related but it was brought up in the thread.
Side note, where cout has type checking, I find printf much more readable and at times easier to use. I'm not saying you can't make mistakes though;
//OR the equivalent cout << "char * = " << szHello << '\n'; cout << "string = " << strHello << '\n'; //works fine because string overloaded the << with iostream. cout << "string = " << strHello.c_str() << '\n'; //also works
So where as you do have to be more careful there is nothing wrong with it. In my opinion if you are coding you need to be careful so this helps stay on your toes.
Well, no - but yes all at the same time. The AI still has very limited knowledge / intelligence at this point. Here is a list of goals the AI does once it gets the 'green light'
Find Next DriveTo Target. If Target is to left, turn steering left, it Target is to the right, turn steering to the right. That as simple as that gets, but it does not look passed the next cone. Meaning, it always gets to cone A before going to cone B. Hence the subtle zig-zag you see. (I say subtle because if you look at the very first replay posted you will see funny stuff)
Now that the AI knows where it is going it tries to maintain a speed of 80mph. Way too fast for turning, but the primary goal was to make sure the AI shifted during this test, which it did successfully. Basically if speed is < 70mph hit full throttle. If 70 < speed < 80 it will fade off the throttle and aim for ~80mph.
Now that the AI can turn, and keep a desired speed it starts checking the driving functions. Should I be shifting up? (RPM too high) Should it be shifting down? (RPM too low). While shifting it presses clutch, releases throttle and performs the shifting. (Currently sequential although I have a feeling H-Shifter would be far easier to implement. Gear = X and be done... But sequential is finally working.
The last thing the AI does is checks for the RPM dipping too low, indicating a point of stalling at which point it hits the clutch.
That is all the intelligence so far, so there isn't much - in fact, the AI can not start the car if it stalls, can not shift into reverse, can not even hit the brakes as demonstrated by that beautiful replay! All it can do is turn from cone to cone, maintain speed and shift up/down depending on the GaugeSensor.
I think my next step is to take this to the drag strip, and try racing against the LFS AI with my own. . . Hmmm. Going to edit an AI layout for the dragstrip, consisting of 1 cone to DriveTo and then it's all about the shifting... Oughta be interesting! Will likely edit in ~5 minutes with a replay here. So do check.
EDIT: Can't race against the AI because of my LFS to AIRS interface needs some work. InSim needs to know which car is which, and handle it properly... Also, my AI does outstandingly bad at driving in a straight line at high speed... Especially in my 'drag set'
If you want direct contact with me, for throwing questions at or whatever, PM me and I'll give you my Instant Messenger info.
My example was a little over the top, really you would need to call the 'big' function anytime you go over 1kb, though like I said, in common practice I've never hit that limit in years of coding like that - then again, it is also ony used in debug builds for me- getting completely removed in Release builds.
For that particular functionality you can never know how big a buffer will be. Consider the case; ConsoleFormat("Blah %s, %s", "String of unknown length", "another unknown"); so you will never know. Either choose a high number and watch what you send in or have some idea of what your doing.
If you knew the size you could use dynamic memory. 'new' / 'malloc' and remember to call 'delete' / 'free' respectively. However, starting out, I would use the fixed size array, and make a solid note of the assumption and possible failure. The dynamic allocation won't work in this situation because you don't know the size of buffer you would need. So again you're stuck to some number that could be too small.
Like I've said, I've used that function and never run out of room, but I know it has limits and I don't use that function for dumping lots of data.
----------------
The final option, which I've used before is to allow the "caller" to send in their own buffer:
You could take in the bufferSize if needed as well, but this allows the caller to do something like.
char *pBigBuffer = new char[1024*1024*100]; //100mb buffer should be big enough for anything. Worry about running out of memory/slow allocation... ConsoleFormat(pBigBuffer, "%s%s%s", codeDump, dataDump, logDump"); delete [] pBigBuffer;
that is obviously not reccomended but pretend all the 'dumps' are large character arrays that end with a null-terminator of course since printf %s requires that. But since they are large they might fill a really big space, and in this version of the function it is flexible enough to do that. You can't have both functions because of the ... -the compiler won't know which to call. You can rename it ConsoleFormat and ConsoleFormatBig.
Last edited by blackbird04217, .
Reason : spelling
Okay guys some more fun action! I hope this doesn't cause out of sync errors... I've watched it three times and restarted my copy of LFS...
Here is the update; the AI shifts up/down at predetermined RPM settings. When the RPM drops below 1000 the AI applies full clutch to avoid stalling. Again the false start is my fault, mostly lack of patience to run a test.
You get to see the AI do something almost every player did their very first time entering a corner... It also happens quite frequently in the online environment from what I hear, haven't been there in ages...
Note that this is poor since if the string and inputs exceed 1kb it _WILL_ crash because you will run out of space within szBuffer. I've never used this with special 'large' cases and in practice I've never had an issue.
In my opinion this is more flexible, however for the needs of InSim, where the type is defined as a 3, 4byte floating point values for a Vec., I would stick with;
struct Vec { float x; float y; float z; };
But, this is half-dozen one way to a half dozen the other. Just my opinion on the 'fixed' status of the packets types. No need to further complicate things by accidentally typing Vec<int> somewhere you meant for a float.
I don't know why its not included, although my ideas are so you could do them yourself. 'byte' is commonly defined as unsigned char, but what it in some application they had defined it as char, first there would be errors of redefinition and second strange things might happen. Another possibility is that since InSim, OutSim and OutGauge work through sockets, it is language, compiler and platform independent so in C / C++
#define byte unsigned char
that is acceptable, where as in Visual Basic, Java? or other languages this may not be acceptable, so Scawen went the 'safe' route of just documenting the type and allowing the developer to do as needed. Although that said, maybe some languages don't allow struct { } or enum { } syntax... So I'm out of ideas for the moment but there you have it, it is what it is.
That said it is documented as far as what the types are and I am only speculating the reasons why they aren't defined.
Improved the HTML, although I still have a few warnings because of DOCTYPE and meta tags that I have not placed because I am not 100% sure how/what to do with them.
The new layout should fit well on 1024 monitor setups now. Overall it looks similar, with a few minor changes including all the small grammar/spelling errors you guys found. Becky will be happy to note I moved the pictures down the page a little, although someone with a taller resolution will likely see the top part of the pictures still, it is completely hidden at first glance on my screen in FF and IE. I also changed the ordering of the skills list to make a little more sense, I hope.
Added: A very simple Contact Page with my contact information, and a finishing picture of my adventure.
Soon to add a projects page. If you click on the current one you will get the old, crappy layout and lose the menu- so back would need to be pressed. The menu is nothing spectacular although it gets the job done. I was planning on adding small rounded edges, but decided that might be a bit of a challenge to get it lined up correctly; possible though and maybe an improvement I'll think about later as I think the square edges take away...
Thanks for your help and support with the process!
EDIT: Currently both Home and Resume go to 'different pages' with the same content...
I know my HTML skills are not the best, and that page you showed me is something I had been wishing existed for a long time!! That will help fix some of those silly issues... Also thanks for catching that error!
I managed to clean up the code a little bit, after reading that tags and attributes should be lowercase rather than uppercase - something I never knew/thought was important. I also removed some unneeded tables that I was using, I haven't quite figured out the purpose of <DIV> tags yet, but some people here seem sold on them, I have ready about them a bit more but still don't know how they useful...
In either way, the new coding is easier for me to read and maintain and is using CSS to help keep things more flexible with the overall page look. Does anyone know of a way to get text left-aligned "Blah Blah" and then some text right-aligned "Ha Ha" but both of these on the same line?
"Blah blah" "Ha ha"
Something like that so I can do my project name/ship date on the left and the dates I worked on the right - but to do this without a table? Maybe that would be a better implementation than adding tables to do what I want there. Sorry for the noob like question, but you guys have already helped quite a bit!
The radius is something I can change in my code. It just drives to where the cone is within a 2.5meter radius. I had to add the radius because with the first test when it came to some tighter turns the AI spun out and messed around trying to hit the exact spot. Though the idea of this radius thing was more of a quick way to indicate it is time to look for the next DriveTo point.
What really needs to happen is some algorithm for shifting up/down, braking and accelerating on a straight. For the moment I am on pause again while I consider my options as this is where 'intelligence' will start to come into play.
In the event of a 1 lap race, which most of my ties are in who has the fastest lap? Hint this is the reason why Head-to-Head started in the first place. When testing 1 lap races de Souza and I experienced our first tie. I made a you-tube movie of it, and its included in the TIES package. I get for longer races the user with the faster laptime is better detection than player id / connection id but best solution overall would be to compute the accurate time crossed - which would likely eliminate almost _all_ possibilities of ties because the precision would be a lot higher.