The online racing simulator
InSim in C# With an LFS Lib.
(21 posts, started )
InSim in C# With an LFS Lib.
Well, after the good result of the last programming topic I had made, found here, we concluded that if you want to try making a InSim program in C++ you should try C# first. So with that inmind, I am going to attempt to teach myself with the help of sdether (Yea, your in this too buddy) how to make a pretty good program for LFS's InSim.

Here is where we start.
using System;
using LiveForSpeed.InSim;

namespace ConsoleTester
{
class Program
{
static void Main( string[] args )
{
InSimHandler handler = new InSimHandler( false, false );
Configuration config = handler.Configuration;
Console.WriteLine( "Enter Your Server IP." );
config.LFSHost = Console.ReadLine( );
Console.WriteLine( "Enter Your Server Password." );
config.AdminPass = Console.ReadLine( );
Console.WriteLine( "Enter Your Server InSim Port." );
config.LFSHostPort = 30000;
config.ReplyPort = 30001;
config.UseKeepAlives = true;
config.UseSplitMessages = true;
config.GuaranteedDelivery = true;
handler.Initialize( );
Console.WriteLine( "LFS info :" );
Console.WriteLine( "Product : {0}", handler.Version.Product );
Console.WriteLine( "Version : {0}", handler.Version.Version );
Console.WriteLine( "Serial : {0}", handler.Version.Serial );
// Resets the cam.
// handler.SetCamera( handler.GetCameraPositionInfo( ) );
Console.WriteLine( "Press RETURN to exit" );
Console.ReadLine( );
handler.Close( );
}
}
}

As you can see, I have played with the code abit, but there are things that I want to do, but don't quite understand. Such as, I want to make a function. This function would ask the user if they want to send a message to the server. If they reply with the Y key, then they are prompted to enter the message. The only problem is now, I don't have a clue how to make functions in C#, so this is where sdether comes in. (I bet he wishes he never helped me now.)

This is how you get a message you have typed to the LFS Server Via InSim.
handler.SendMessage( Console.ReadLine( ) );

Now if we wanted to do that over and over, and not to mention get the reply, how would we go about doing that?
#2 - filur
Seems to me this has very little to do with insim at all, and i'd feel quite confident about saying google knows how to define a function in c-sharp, etc.
That's not the point. I would like people to learn how to buld an InSim app along with myself.
[EDIT] Hey, I have been looking and looking, but I can't find a way to get the messages from the clients on the server. How do I do that one? I would like all of the messages to go into TextBox2. FE.
TextBox2 += Message + System.Environment.NewLine;

Quote from Dygear :That's not the point. I would like people to learn how to buld an InSim app along with myself.

If you are trying to build a GUI application, look at the Tester App that's on the page linked to by my sig. It's a simple Windows.Forms application for connecting to LFS, sending and receiving messages, etc.
Yea I had looked there, and I will look once more, but it's hard to understand the flow of code when its broken up in to so many parts like it is in the Visual C# IDE. Anyway, I will look over your code once more, I do hope to find it. I am very sleepy now, so I am going to sleep (4 hours is just not enought for me to program on.) Night.

[EDIT]
Ok, so I have been trying to get my head around your code. Keep in mind, I have never programmed in C Sharp, and I have only ever used Express once. Now this is my theory.

/* All code found in the InitializeComponent function from State.cs (In Tester Project). */

// Part of the buttonConnect_Click.
// Ran if the you press the button and your not connected to LFS.
tester = new LFSTester(
textBoxServer.Text,
Convert.ToInt32(textBoxPort.Text),
Convert.ToInt32(textBoxReplyPort.Text),
textBoxAdminPass.Text
);
tester.Handler.LFSMessage += new MessageEventHandler(Handler_LFSMessage);

// The Handler_LFSMessage Function it self.
private void Handler_LFSMessage(LiveForSpeed.InSim.Events.Message e)
{
string[] lines = textBoxIncoming.Lines;
int copyLength = (lines.Length>9)?9:lines.Length;
string[] newLines = new string[10];
Array.Copy(lines,0,newLines,1,copyLength);
if( e.IsSplitMessage )
{
newLines[0] = e.UserName+"/"+e.PlayerName+": " + e.MessageText;
}
else
{
newLines[0] = e.MessageText;
}
textBoxIncoming.Lines = newLines;
}

for the line "tester = new LFSTester" my guess is that your making a new thread inside the program. Now as for the line, "MessageEventHandler(Handler_LFSMessage)" I don't get this what so ever. Looking at the function itself, how on earth are you getting the functions to fire? How do you know when the message has changed. Looks like I am going to have to take a deeper look at the "LiveForSpeed.InSim.Events.Message" (I don't know what it is called, NameSpace, Function, Class?)

[EDIT3] I have tryed, and I have try, nothing is working for me. I don't get this. What ever I try, I get A) A thread error for your program. B) Problem with logging. C) The program does not lunch at all due to another log error. For my program, I get A) a miss match type error. Blah is name space and can't be used in this context kinda error.

Handler_LFSMessage(LiveForSpeed.InSim.EventHandlers.MessageEventHandler).
What does Handler_LFSMessage want from me? What is going wrong? Could you please help.

*Off to hit a pellow REALLY hard.*
#6 - Woz
From the sort of questions you are asking I can only say you need to stop trying to write an application in C# when you do not know anything about the language.

C# is like the rest of the C based languages in that it is terse but that what looks simple code hides a great deal of complexity. Similar to C++ even a simple + sign in the code can really be a function call if someove has overloaded + for the classes either side of the + sign.

The line:

tester.Handler.LFSMessage += new MessageEventHandler(Handler_LFSMessage);

is what lets the function Handler_LFSMessage get called when the LFS InSim wrapper fires an LFSMessage event. The function gets called along with all other event handlers attached to the event.

I think you need to read up on .NET and C# or pick a different language.

Sorry.
I think I have said this, I have never programmed in C#. I never got into the more advanced programing of C, or C++. The only programing langue I can claim to really know is PHP. Now I have talked about using PHP with InSim, and I get the same old reply. Don't do it. You'll waste your time. And looking at raw InSim packets themself, I think they are right.

[EDIT] To put something in my defense, I have learnt to program on a basic level (Not the programing language basic) by my self. The only way I know how to program is what I can find on line, and what I have done by my self. I have nerver used C# in my life. You can't expect me to jump into a programming langue and know it all. If you don't want to help, then please don't post.

Woz, I thank you for the explanation, I'll have another crack at this.
#8 - filur
PHP works as good as anything else you could use, probably more a waste of your time trying to learn something harder to do the exact same thing.
Yea, but it's quite hard to keep open a persistent connection. In PHP.
private void Handler_LFSMessage(LiveForSpeed.InSim.Events.Message e)
{
string[] lines = textBoxIncoming.Lines;
int copyLength = (lines.Length>9)?9:lines.Length;
string[] newLines = new string[10];
Array.Copy(lines,0,newLines,1,copyLength);
if( e.IsSplitMessage )
{
newLines[0] = e.UserName+"/"+e.PlayerName+": " + e.MessageText;
}
else
{
newLines[0] = e.MessageText;
}
textBoxIncoming.Lines = newLines;
}

Ok, I have a question. Does the "LiveForSpeed.InSim.Events.Message" get fired and therefor call that function by the fact that it is simply in the function declaration statement? I simply want to get messages from the server. That is it. That is what I am stuck on. I don't need a mult-threaded application to do that.
#11 - Woz
Quote from Dygear :Ok, I have a question. Does the "LiveForSpeed.InSim.Events.Message" get fired and therefor call that function by the fact that it is simply in the function declaration statement? I simply want to get messages from the server. That is it. That is what I am stuck on. I don't need a mult-threaded application to do that.

As stated before

tester.Handler.LFSMessage += new MessageEventHandler(Handler_LFSMessage);

Is the line of code that passes the address of the function Handler_LFSMessage along with its context. The event system uses this address to call the function when the event is fired. All messages are really callback functions so each message is just linked to the list of functions that should be called when the event fires.

tester is the instance of an LFSTester object and is created by the new operator.

The private callback function will belong to some class object, I have no idea without the class wrapper and other related source.

The following are the minimum you should have at least knowledge of before you open Visual Studio again.

1) Read up on storage types provided by .NET and where they are stored in memory and know the difference between value and reference types and how something it created or wrapped will depend on where it is stored and hence its lifetime.

2) You will not be able to just create everything in main() and there is no such thing an stand alone functions in C#. So you are going to have to learn about classes and structs, how they are built, created and destroyed etc You need to understand classes if you want to receive events.

3) You will need a form if you want user input so you need to learn how forms work and how you talk with controls.

4) Namespaces will be needed to get .NET to do anything. Unless the compiler knows where to find the code for objects and services you pull into your project it will not be able to compile your code.


This is the absolute minimum you will need to understand to work in this language.

If you are looking for a quick way into programming then VB 6 is your best bet. Powerful enough for your needs, very quick and natural to work with. Do not confuse VB 6 and VB.NET as VB.NET is really C# with different syntax and hence includes the same learning curve.
Quote from Dygear :Yea, but it's quite hard to keep open a persistent connection. In PHP.

Again there's no difference, keeping a persistent connection is in theory exactly the same as any other language, making your application do something over and over again without stopping.


<?php 
set_time_limit
(0);
while (
1) {
  
do_something();
}
?>

Launch as you would launch your C# program, ie. not from a webserver.
Thanks Woz, I'll go and RTFM.
#14 - Woz
Quote from Dygear :Thanks Woz, I'll go and RTFM.

If you really want a far easier route into windows development that will at least let you see how you can use events etc couple with a quick way to work then VB6 really is your route. Its fast to prototype with and easy to understand without too many things that catch you out. It should also be very cheap to pick up on ebay now, just look for VS97 Professional or VB6 Professional and you should be set.

While the 97 year tag might put you off you will find that VS97 (The last pre .NET dev tools from MS) are still used throughout the computer world and will be for some time. I still use VB6 most days for work along with .NET. I would say .NET really didn't become too viable until the 2.0 runtime anyway when generics made it into the language, that is when I started to take it serious. By the 2005 release it also had been used in anger enough for MS to iron out the issues with the framework and tools.

If you really are serious about .NET then you should probably forget this project for a while and spend some time just playing with the language. Creating forms, play with variables and objects and see how they react when you interact with them. Also learn to debug applications and trace code etc. It might mean you have to set aside a month or two but when you come back and re-visit LFS lib you will have a far better understanding and hence be able to make sense of what is going on

If you want a great book then "Professional C#" by Wrox press is the one I would say get but you should be warned its $50US and runs into 1000+ pages but once you come out the other side you will understand the language and runtime environments which is more than can be said about most MS documentation (As the EU have found out )
I don't need nor want an easy route. I learn best from my own code, but I can learn a lot from other people's code (providing it works). I simply don't find it help full to read books about programing, when you could be doing and learning about programing by doing it yourself. I understand programing theory for the most part, but this syle of programing is totally alien to me. Going to RTFM now.
#16 - Woz
Quote from Dygear :I don't need nor want an easy route. I learn best from my own code, but I can learn a lot from other people's code (providing it works). I simply don't find it help full to read books about programing, when you could be doing and learning about programing by doing it yourself. I understand programing theory for the most part, but this syle of programing is totally alien to me. Going to RTFM now.

While this might be the case for many languages this is simple NOT the case for an Object Oriented (OO) language. There is so much to learn about and so much knowledge you have to store in your head about the code and its shape before you can use that code in a productive manner.

I have not used the C# lib for lfs but I would asume it has beeen used by other and does in fact work. Its more the fact you are fighting with the language so do not have anything left to actually understand what the object is doing or how to use it. The fact that you assumed that the new operator started a thread shows how far you have to come before you can even think of using the object.

C# is what comes under the banner of OO along with a whole raft of languages such as Delphi, Smalltalk, C++ etc etc. OO is a style of programming where you group objects that are similar to each other through classes. You then extract their common code into a separate base class which is then used by all the similar classes to provide a common interface and code base. Classes that inherit from that base all share the common interface and code.

The classic example in all the texts is the Vector based drawing package but as this is LFS I will use engines

(NOTE: Might not compile as just written in forum without compile etc.


namespace Demo.Car.Engine
{
class Engine
{
// Takes throttle pos, return power output
public virtual double ChangeThrottlePosition(double position)
{
return position * 5;
}
}

class V4Engine : Engine
{
}

class V8Engine : Engine
{
public override double ChangeThrottlePosition(double position)
{
return position * 10;
}

public double GetEngineTemp()
{
}
}
}

The code above gives us 3 objects. Engine, V4Engine and V8Engine. We can treat these all as an engine if required and all provide the same interface of ChangeThrottlePosition that gives us power output. You will see that V4Engine does not define ChangeThrottlePosition but later I will call as thought it has. V4Engine picks up code from Engine as does V8Engine but in that case it did not want to use the base engine code so overrides it.


// Create one of each
Engine base = new Engine(); // Create base object.
Engine v4 = new V4Engine(); // Create a V4 type engine
Engine v8 = new V8Engine(); // Create a V8 type engine

Engine test;
double power;
double temp;

test = base;
power = test.ChangeThrottlePosition(50); // Returns 250 (50 * 5)
test = v4;
power = test.ChangeThrottlePosition(50); // Returns 250 (50 * 5)
test = v8;
power = test.ChangeThrottlePosition(50); // Returns 500 (50 * 10)
temp = test.GetEngineTemp(); // Will cause compiler error as Engine does not have function
temp = v8.GetEngineTemp(); // Fine as does have function

You will notice that it is possible to assign classes that come from the base to a reference to base. With GetEngineTemp() this is only present in V8Engine in the example. So even though test and v8 variables both point to the same object we can only call the function on the second as this is the one that holds that interface definition. Engine does not know this function exists.

It should also be noted that in the case of v8:

power = test.ChangeThrottlePosition(50);

Calls the version present in V8Engine even though we are referencing through a base object because we have overloaded that function through virtual routing so it always calls the correct verion.

OO is a massive mind shift from code techniques in procedural languages. It is not something you can pick up from code unless you know what you are actually looking for.


Thats me done now. If you feel you can jump into .NET development without reading anything on OO, .NET and C# then good luck, I wish you all the best but I think you are kidding yourself
On connect I call this function.
handler.LFSMessage += new LiveForSpeed.InSim.EventHandlers.MessageEventHandler(Handler_LFSMessage);

That in turns calls this function.
private void Handler_LFSMessage(LiveForSpeed.InSim.Events.Message e)
{
if(e.IsSplitMessage)
textBox2.Text += e.UserName + "/" + e.PlayerName + ": " + e.MessageText;
else
textBox2.Text += e.MessageText;
}

Now the program runs, but when ever a user sends a message, the program crashes when trying to right to textBox2 thanks to the multithreaded problem. Do you know of a quick way of turning off, or just plain getting around this issue?
#18 - Woz
I dont understand this at all. Where do you think this extra thread is being started?

I have not seen a single piece of code in this topic that would hint at a thread starting. "new" DOES NOT start a thread, it creates an object. The object might start a thread in its constrcutor or methods but you have to read the code to confirm this. As stated messages are passed via function callbacks and most of the time are on same thread.

Here are the questions you should ask yourself....

1) When is textBox2 created? (Not declared as created and declared are VERY different.)

2) Can you read the event data within the event callback?

3) Is the reference to textBox2 still valid when the event fires or has it left scope?

4) What is the error you get and what does that mean?

Once you have answered the these questions above you should be able to find the solution.

I am not answering any more questions now. You complete determination to learn C# without knowing or even having an interest in reading about the language and environment first astounds me. Sounds like you are the sort of person that would expect to be able to fix an engine without knowing how it works in the first place and then wondering why you have a pile of bits and no idea how to put back together again.
Dygear, to get an intro to object-oriented programming, try it in the language you know, PHP. It doesn't go all the way but kind of "emulates" similar technique. You can do classes and methods, extend to inherit properties and functions, create and handle classes as objects. etc.


<?php 
/* pseudocode, OO in php */
$stdClass = &new stdClass;
$stdClass->aWidget = &new GtkWidget(new GtkWidgetOption(GTK_OPTION));
?>

Woz you simply don't understand how I learn. I have had to teach myself eveything, and that can take some time, so I though I would ask here to give me a head start. I am going to contiune to learn about C#, and finish off this program. Thank you filur, but that is not how my minds work. It must learn in a pure environment.

Topic Closed, I will do this on my own, like eveything else.
Quote from Dygear :
Now the program runs, but when ever a user sends a message, the program crashes when trying to right to textBox2 thanks to the multithreaded problem. Do you know of a quick way of turning off, or just plain getting around this issue?

Your problem is that the event gets fired on a thread different than the thread in control of the UI and only the UI thread can change UI elements. Here's details on the issue:

http://www.codeproject.com/csharp/begininvoke.asp

InSim in C# With an LFS Lib.
(21 posts, started )
FGED GREDG RDFGDR GSFDG