The online racing simulator
Hello World!
1
(39 posts, started )
Hello World!
With these ominous words, it begins...

Now. I need a bit 'o help.
Can anyone pm/post a hello world example using insim, c#, .NET lfs external?

I'm trying to do my first C# app (got some college experience, but with java). But frankly, I'm not familiar with the documentation style in c#, and am at a loss where to begin.
So I need a very simple prog that would send to LFS via lfsexternal libs a "hello world" message.
Hello world could be either a regular message (as if the user typed it),
or a message that would remain on-screen in a definite location.(like most cruise server's money display).
As an added bonus, how bout one that also retrieves some kind of data from lfs - like a laptime?

In general something like(very poor pseudocode ahead, beware!)

Insim = createNewInsimConnection();
Insim.sendMessage("hello world");
Insim.sendCustomMessage("Hello World Too");
myVariable = Insim.retrieve(car1'slaptime);


with that info, I can start having a go at my project (a simple pitboard program), and begin retrieving data from lfs, sending back info to display, etc.
While I wait, Ill keep doing research. If I manage to do the hello world prog myself in the meantime, Ill post it here
There's a very simple example that comes with LFS_External, complete with project files that will open in Visual Studio, or SharpDevelop. It will maintain a connection and do one or two other things, if I remember correctly.

Have you tried giving that a go?
BIG Thanxs TAA - I didn't notice it - thats pure gold. Not quite what I wanted, but it is broader and more informative.
Plus, well commented

If I have doubts, Ill post here. If I have solutions, Ill post

Eventually, I might use this experience to create a starting point tutorial to c# + lfs external. Kinda like the one you got sticked up there, TAA.
Truth be told... really usefull client-side insim apps are getting rarer and rarer....
Like a mod to show you the gap in seconds to the guy in front and the guy behind (thats my project), one that would tell you when close opposition entered pitlane, a driver list that would only show the 2 cars in front and the 2 cars behind instead of all 32 drivers... stuff like that.
Quote from Stigpt :Eventually, I might use this experience to create a starting point tutorial to c# + lfs external. Kinda like the one you got sticked up there, TAA.

Please, do feel free to add to that stickied thread with a tutorial for C# and LFS_External :up:
weee
work is progressing nicely - found out how to send text messages to LFS (later on will do it in buttons and stuff), and how to receive data.
AND how to get the car data so I can know which car is in what position.
The "tutorial " will be done hopefully later tonight.
Problem myProblem = new Problem(c#, lfs_external, MSI_Packet);
I got a problem.
I'm in need of maitaining a list detailing which player(PLID) is in what position.
What I did was to edit the example code from LFS External, and add to the clsPLayer class a "position" attribute.

Now, to update it, I had it whenever a car goes over a finishline/split time (i.e. the packets corresponding to that are received), it fires a method to update the positions.
That method does a request MSI packet., then the MSI packet handler method processes the response, and updates the positions.
It works.. sort of.
Cause the MSI packet only has 8 cars, it only updates the same 8 cars all the time. All other cars have position=0 (my init value)

How can I do it so I can get all the car's positions?
MSI Isnt a packet? I think you mean MCI. You are best off using the MCI packet to maintain the positions. Then you will have a constantly updated list of positions. You can turn them on in the ISI packet, Or in LFS_External the connect method. All you have to do, In the MCI method, Is make a for loop and iterate through the MCI packet.


for(int i = 0; i < MCI.NumC; i++)
{
Players[GetPlyIdx(MCI.Info[i].PLID)].position = ++MCI.Info[i].Position;
}

If your wondering why I have put ++MCI.Info[i].Position, Thats because LFS counts from zero (Example: 1st = 0, 2nd = 1; 3rd = 2..etc etc) So it makes your life a little simpler. That also should work if there is more then 8 players.

HTH
Thats the problem.
here is my code:


private void MCI_CarInformation(Packets.IS_MCI MCI)
{
myMCI = MCI;//myMC is a variable that stores the latest MCI Packet to arrive.
//For use in other methods
}
//for example, this one here below
InSim.Request_MCI_MCIPacket();//gets A MCI p, then the above method should "update" the myMCI var.

Packets.CompCar[] compCar = myMCI.Info;

//Cycles each of the cars in the MSI packet
for (int i = 0; i < compCar.Length - 1; i++)
{
byte tempPLID = compCar[i].PLID;
byte tempPOS = compCar[i].Position;
//Cycles all players in list,
for (int j = 0; j < Players.Count; j++)
{//Trying to find the right one to update its position.
if(Players[j].PlayerID==tempPLID)
Players[j].setPosition(tempPOS);//CompCar.Position
}

This is apparently the same code as yours, but without using the "GetPlyIdx(PlayerID)" function - I'm not familiar with the LFS external API yet.
Thing is - only works for the first8 players. All the MCI packets have the same car...

This has a few extra lines of code, like Packets.CompCar[] compCar = myMCI.Info;
I KNOW it can be switched with myMCI.Info[i] whenever I would need it, but as a first approach, I'd rather keep the code longer, but simpler so I can easily find bugs, change stuff, etc.
TBH, I dont mean to be rude, but your making a mountain out of a molehill. You could update the player(All of them on the track 8+) in a very simple way.


private void MCI_CarInformation(Packets.IS_MCI MCI)
{
for (int i = 0; i < MCI.NumC; i++)
{
Players[GetPlyIdx(MCI.Info[i].PLID)].position = ++MCI.Info[i].Position;
}
}

That code WILL work for more then 8 players, Its cleaner and its a lot smaller. Unless im missing something, why not just do that.
big thanxs, it does work - but I dont quite understand why.

I guess this line in the documentation-
"Info car info for each player, 1 to 8 of these (NumC)"

Made me think the wrong way.
I though that EACH MCI packet had an array of 8 CompCar structs - meaning each MCI had the info from 8 cars.
And indeed, cycling from 0 to compcar length only cycled from 0 to 7.
numC is the amount of compCar strucs in the MCI packet, and I guess it CAN be greater than 8 - its the actual number of cars in the track, meaning each MCI has the full grid stored in the Info array.

big thanxs.

(and you didnt sound rude at all - you should hear me straightening out freshmen code )

As I said, Im not familiar with C# syntax, or the lib's API - so I Am stumbling along, drunkenly. Which is a lot of fun, btw.
I can now do the full grid, and display it in neat buttons. (though for the project I do not want to display it, just need it
One thing I dunno (yet) is: what is the special character for a newline (so I put a button with 2 lines of text - in java its \n)
And how to color the text in the button/put a special character there. Im guessing its some codes inserted into the string, but I dunno which.

EDIT: Found out what was wrong (and I write here so you all can laugh at my idiocy, and hopefully dont make the same mistake)
I didnt notice the settings had already made the MCI packets sending every 500ms automatic.
Then, the way I had coded it, my big position update method was only using the LAST MCI packet to be received. (the myMCI var)
And since right before I started updating it, I explicitly asked for a new MCI packet, the game would send me ONE packet, not the 2-3 that it would need to show all the cars in the grid. That ONE packet was always the first packet in the list of 2-3, so it was always the same one, so Only the same 8 cars got processed. So removing that request_MCIpacket line would make it work.
Now that I understand the why, Im using the (MUCH better) code by mcgas001.

And for the record I understand now that MCI packets have 8 cars. if more cars are on-track, it sends more packets in sucession.
So its important to make a general method to process the packets - one that just puts the data where the method finds out it should go, not where the programmer guesses it problably is gonna go(which was my mistake) - which in turn is good programming practice anyways
Quote from Stigpt :One thing I dunno (yet) is: what is the special character for a newline (so I put a button with 2 lines of text - in java its \n)

The newline character can vary for different operating systems. For Unix-like the new-line escape char is '\n', for Windows it's a string "\r\n", for Mac I believe it's '\r', but I might be wrong.

In C# '\n' and '\r' are interchangeable, but .NET has a special static property called System.Environment.NewLine which will insert a line-break appropriate for the OS environment the program is being run on, so really you should take advantage of that.

In LFS you cannot split a string into separate lines though, you need to create multiple buttons or send multiple messages to display a string over different lines.
big thanxs, very informative indeed.
Java suffered from what I called "Instruction Trains" - which are instructions that due to all the megaclass.class.miniclass.method() etc. created huuuuuuuuuuuuge instruction lines. C# seems even worse on the other hand, you can do sooo much in one line

Now - a bit more help.
In using the lfs external example as a "framework" for my project, the program doesnt exit correctly. Window closes, but the process remains running in the background - though the tcp connection IS closed.
What is wrong?

The only code I got with any mention of closing is this:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
InSim.Close();
}

#13 - sun
hello world ?

its simple



using System;
class MyClass
{

static void main()
{

Console.WriteLine("Hello World");
}

}
Can I suggest that you read the thread a little more than the title in future sun?
Karl...

You didn't expect this?!

Shocked... to think I was gonna FedEx you some nice Guinness beer, for you go and blow it like that?!.

Shocking...
The example is incorrect as well.
Quote from Stigpt :Now - a bit more help.
In using the lfs external example as a "framework" for my project, the program doesnt exit correctly. Window closes, but the process remains running in the background - though the tcp connection IS closed.

Do you have any worker threads still running maybe?

A good way to debug this is to start the application from VS, close it (via the application interface, not with the "stop debugging" button), and then if Visual Studio stays in debugging mode, hit the pause button. This should highlight (green) the current statement of the last active thread. Then you can open Debug > Windows > Threads, which allows you to switch context between the different running threads (giving your threads a name as you start them makes identifying them much easier, btw ). With that it should be easy to find out where and why the thread hangs.

If you're not using threads, you'll have to post a bit more code of your application so we can find out what's going wrong. The LFS External example code opens and closes flawlessly on my side, so it must be something you added.
no, it was something I DIDNT add.
Nothin called the close method.
This last release has a quit button that calls the close button, then activeform.close() - and it exits correctly.
D'oh
Another question:
I COULD go research for this, but it will go faster and better if I ask
How do I open a file using c#?

This is so I can "save" my program settings, and read the settings from the file, and hopefully, read the user's admin password from cfg.txt - so it isnt necessary to ALWAYS type it

In the meantime I will try to research it
You need use System.IO, I am wanting information for create .cfg
It took me 10 seconds with google to find out how to do it "the .NET" way:
http://www.codeproject.com/KB/dotnet/config.aspx

To do it the general way you need to apply some basic thought processes. If you want to create something like LFS uses, or some basic key = value system you need to read the file line by line. Read up until your key delimiter (in this case a = symbol), strip any additional spaces, assign the key in some sort of array or dictionary or some other medium for saving your data. Read the rest of the line, stripping out your delimiter, and assign this as your value for your key in the same array or dictionary, or whatever it is you're using to store your configuration values. If you want to do it this way you need to lookup how to read a file line by line (Readline from the StreamReader object will do nicely) and then how to split a string (String.Split). I'm guessing you'll also want information on storing this information, which you can use what some languages would call a dictionary, or an associative array.

Alternatively you can do it the "ini way", which would either be to write up something that basically does the above, or you can use the win32 api (example here: http://jachman.wordpress.com/2 ... ccess-ini-files-in-c-net/, or a pre-wrapped class here: http://www.doogal.co.uk/inifile.php).

Now let me point something out. I don't use any of the .NET languages. I don't have any of the .NET related tools on any of my machines bar the actual framework. I'm not a brilliant programmer at all. The simple fact is that I've spent less time doing some research than you guys have actually spent typing a post(!!!)
woah there taa
I see why you're the ANGRY angel.
I just asked for some help, so I didnt have to do the research (which I did in paralell, btw) This gave me a better picture of what to do. In the meantime, I was debugging my app, and trying to decide when and where to write/read.
As an added bonus, the next guy coming to this forum will find a little gem of knowledge on how to write to the disk
Well, I believe TAA's point was that this stuff is not difficult to find out if you do a bit of research. Also, you should really do the research yourself before posting questions for help, as you can't expect people to go out of their way to help you if you are not willing to put in any effort yourself. Really, reading and writing text files is a topic covered by pretty much every beginners programming tutorial I've seen, so it's not something hard to find out.

Anyway... I posted an example of how to do this a while ago... http://www.lfsforum.net/showthread.php?p=666922#post666922
Quote :private void MCI_CarInformation(Packets.IS_MCI MCI)
{
for (int i = 0; i < MCI.NumC; i++)
{
Players[GetPlyIdx(MCI.Info[i].PLID)].position = ++MCI.Info[i].Position;
}
}

Still struggling with this, I post it and debug and get a list of errors, but no idea what else to do,

Mick
1

Hello World!
(39 posts, started )
FGED GREDG RDFGDR GSFDG