The online racing simulator
InSim and C++
(21 posts, started )
InSim and C++
Oh joy, InSim and C++. You know I bother people so much that they should program in C++, but when it comes to me doing it. Well these are the results. This is about 45 minutes in and not even 45 lines of code have been made. I have some major fundimental problems I need to overcome before I can really start programing this thing. This compiles and works, to a point, but it does not even connect to InSim thanks to the hole struct malarkey that I have to endure.


<?php 
#include <stdio.h>

struct InSimInit                // UDP packet to initialise the InSim system
{
    
char            Id    [4];    // ISI + zero
    
unsigned short    Port;        // Port for UDP replies from LFS (0...65535)
    
unsigned short    Flags;        // Bit flags for options - see below
    
unsigned short    NodeSecs;    // Number of seconds between NLP or MCI packets (0=none)
    
char            Admin[16];    // Admin password (required if set in LFS host options)
};

int main int argcchar *argv[] )
{
    if ( 
argc != )
        
printf("usage: %s <PORT> <PASSWORD>\n"argv[0]);
    else
    {
        
InSimInit ISI;
        
ISI.Id[0] = 'I';
        
ISI.Id[1] = 'S';
        
ISI.Id[2] = 'I';
        
ISI.Port 65000;
        
ISI.Flags16;
        
ISI.Admin[0] = 'A';
        
ISI.Admin[1] = 'S';
        
ISI.Admin[2] = 'D';
        
ISI.Admin[3] = 'F';
        
printf("ID : %s\n"ISI.Id);
        
printf("PA : %s\n"ISI.Admin);
    }
    return 
0;
}
?>

When I try to do something like
ISI.Id = "ISI"; // or
SI.Id = 'ISI';
for that matter anything with the double quotation marks, I get an error. Did I miss something in the fundiments of C++ that stings that are char arrays can't have the double quotes thing around them? And here's another thing that bothers the crap out of me.
ISI.Admin = argv[1];
Why does that not work? "incompatible types in assignment of `char*' to `char[16]'" That's ridiculous. Its a freaking char, what does it matter if its 16 or 1600 charters long. I think I have done to much work in PHP, its been pampering me to much. It's just that is so god damn convoluted to get any work done in here.
-
(JogDive) DELETED by JogDive : Faulty
// ISI + zero

A
char [4] array means a field between 0 and 3:
ISI.Id[3] = 0;

0 not the '0' char code !!! thats diffrent !


btw....a example

char v = 0;
InSimInit init_pack;
memset(&init_pack, 0, sizeof(InSimInit));
strcpy(init_pack.Id, "ISI" + v);
init_pack.Port = 12345;
init_pack.Flags = ISF_RACE_TRACKING|ISF_KEEP_ALIVE;
init_pack.NodeSecs = 0;
strcpy(init_pack.Admin,Text.c_str()); UDP1->SendBuffer((char*)&init_pack,1024,sizeof(InSimInit));

My app connects always
#3 - Stuff
I'm no C++ person either but don't forget the example Scawen posted? Hrm.. searched for it.. Where'd it go?
Quote from Dygear :
ISI.Admin = argv[1];
Why does that not work? "incompatible types in assignment of `char*' to `char[16]'" That's ridiculous. Its a freaking char, what does it matter if its 16 or 1600 charters long.

argv[1] is a pointer to array not an array itself. And even if it was you can't just copy from array to array with = operator (unless properly overloaded) in C/C++.
Use strcpy or sth like that...
Quote from JogDive :A char [4] array means a field between 0 and 3:
ISI.Id[3] = 0;

$ISI = array(
[0] => 'I'
[1] => 'S'
[2] => 'I'
[3] => '\0'
)

Now, $ISI[4] would also equal '\0' due to that being the array terminator correct?

There was a memory copy function, where you could litarly copy the string from one memory location.
You'll need to put in error handling for the size of the strings, and strncpy isn't the safest to use, but this is quick and dirty for ya.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct InSimInit // UDP packet to initialise the InSim system
{
char Id [4]; // ISI + zero
unsigned short Port; // Port for UDP replies from LFS (0...65535)
unsigned short Flags; // Bit flags for options - see below
unsigned short NodeSecs; // Number of seconds between NLP or MCI packets (0=none)
char Admin[16]; // Admin password (required if set in LFS host options)
}InSimInit;

int main ( int argc, char *argv[] )
{
InSimInit ISI;
printf ("ArgCount %d\n", argc);
if ( argc < 2 )
printf("usage: %s <PORT> <PASSWORD>\n", argv[0]);
else
{
printf ("argv[0] %s\n", argv[0]);
printf ("argv[1] %s\n", argv[1]);
printf ("argv[2] %s\n", argv[2]);
ISI.Port = 65000;
ISI.Flags= 16;
strncpy (ISI.Id, argv[1], strlen (argv[1]));
ISI.Id [strlen(argv[1])] = '\0';
strncpy (ISI.Admin, argv[2], strlen (argv[2]));
ISI.Admin[strlen(argv[2])] = '\0';
printf("ID : %s\n", ISI.Id);
printf("PA : %s\n", ISI.Admin);
}
return 0;
}


Quote from Dygear :$ISI = array(
[0] => 'I'
[1] => 'S'
[2] => 'I'
[3] => '\0'
)

Now, $ISI[4] would also equal '\0' due to that being the array terminator correct?

There was a memory copy function, where you could litarly copy the string from one memory location.

i think not backslash zero, zero
\0 terminates a string

@der_jackal: This is not the error, just an enhancement


EDIT:Hey guy, you used the ' ' char brackets. Zero terminated means terminating with a zero and not with the char code !!!

please try that:

[3] => 0

does it work ?
#8 - Stuff
Quote from JogDive :i think not backslash zero, zero
\0 terminates a string

@der_jackal: This is not the error, just an enhancement

?

Quote from JogDive :
EDIT:Hey guy, you used the ' ' char brackets. Zero terminated means terminating with a zero and not with the char code !!!

please try that:

[3] => 0

does it work ?

Since it's 0 terminated;

ISI.Id [strlen(argv[1])] = 0;
ISI.Admin[strlen(argv[2])] = 0;

But 0 and '\0' are the same thing in this sense.
Thank you all for this. . . Thanks alot to Staff, for finding me that code, and to der_jackal for making some up for me.

I looked at the code, and attempted a compile with Dev-C++ 4.9.9.2, with no such luck. So it does not compile. But god its some good code, I will look over it and learn it. Thank you.
Downloaded and installed Visual C++ 2005 Express Edition.

1>------ Build started: Project: LFSControl, Configuration: Release Win32 ------
1>Compiling...
1>StdAfx.cpp
1>d:\workdir\lfs\lfscontrolproject\stdafx.h(17) : fatal error C1083: Cannot open include file: 'windows.h': No such file or directory
1>Build log was saved at "file://d:\WorkDir\LFS\LFSControlProject\Release\BuildLog.htm"
1>LFSControl - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Oh fantastic . . .
Yes, I had installed that even before I had posted that message.
That is for the x86 platform, I have the AMD64 platform aka x64.

EDIT1 : Ok, I went though the steps, against my better jugement, and it still fails to compile . . .
Not even there little defult one will not compile.

EDIT2 : Time to RTFM, huh? Yea, I think it is, so that's what I am going to do right now.

EDIT3 : Here's a question for the devs, what do you guys use to work on LFS? Just a regular text editor, or something more extravagant?
It would be a better idea to know what they work in so we are all on the same page.

EDIT4 : der_jackal, thank you mate, the code you had made for me worked. Now I just need to figure out how to get this thing to connect to the server.

EDIT5 : Oh it would seem that we are infact getting some where.
1>------ Build started: Project: LFSControl, Configuration: Debug Win32 ------
1>Compiling...
1>StdAfx.cpp
1>c:\program files\microsoft platform sdk\include\windows.h(157) : fatal error C1083: Cannot open include file: 'excpt.h': No such file or directory
1>Build log was saved at "file://d:\WorkDir\LFS\LFSControlProject\Debug\BuildLog.htm"
1>LFSControl - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Any particular reason you are punishing yourself with C++ Messiah and myself have tackled InSim in C# already. Even if you don't want to use someone else's Lib, we're both released under GPL, so you could always use our source to learn how to do it in C#.

Personally, I avoid languages that make me manage my own memory, because these days the performance gains just don't seem to be there unless you are writing video games (and even Managed DirectX games are making inroads). Not trying to start any language preference war, just trying to make sure you are choosing C++ for the right reasons.

If your concern is ability to move your code to other platforms, I know my lib runs under mono, and pretty much anything written against the 1.1 spec of .NET will run under mono. The way I see it, the only real drawback to .NET/mono is having to install the runtime (23MB). However, it comes standard with every windows OS shipped and installs with SP2 for XP and the new Ubuntu and Fedora Core distributions come with mono pre-installed, so the runtime requirement is quickly becoming a non-issue.

Just a thought.

cheers,
ether
I programming for this program in C++ for if, and hopefully when, the devs release LFS : S2 for linux I don't have to rewrite everything. There is no need to download some runtime files. The speed is second only to assembler. Don't get me wrong, I love the work you have done. It is very good, and I will most likey use some of your code to help me along. But C++ is the way to go for this project.

This is what I am looking to do, the list is provisional . . .
// SET SERVER
set_server_track(string name[32] || int number); // EX. Blackwood GP || 001
set_server_cars(string car[64] || int number); // EX. FO8+FZR || 000000000000001001
set_server_name(char name[24] ); // EX. ^1www.Eagle^7Race^4Team.com
set_server_host(char name[24] ); // EX. ^1(E^7AGL^3E)^7Host

// GET USER
get_user_speed(int id);// Speed of the car. Float.
get_user_nick(int id); // Name Used In Game. String.
get_user_name(int id); // Name Used For LFS. String.
get_user_time(int id); // Time Array. Array ( Lap array ( int Sector1, int Sector2, int Sector3, int Sector4 )
get_user_pos(int id); // Posision Array. Array (int X, int Y, int Z )
get_user_lap(int id); // Lap the driver is on. Returns Int.
get_user_car(int id); // Car the driver is in. Returns String.
// GET SERVER
get_server_track(); // Get Track. String.
get_server_cars(); // Get Cars. Int.
get_server_drivercount(); // Get's the number of drivers in the game. Int.
get_server_name(); // Get Name of the server. String.
get_server_host();

EDIT : Ya know what sdether, I might try C# providing one thing. You help me setup what I have to, in order to get a simple LFS InSim program to connect to InSim. For example, it connects to InSim and asks for LFS version. Ok?

First Step, what do you use to program in, and how do you set that up. (I sware if I have to install those stupid playform files, I am sticking with C++).
Second Step, some example code to get the example program to connect to the LFS server and ask for the version.
I'll take over from there.
Quote from sdether :If your concern is ability to move your code to other platforms, I know my lib runs under mono, and pretty much anything written against the 1.1 spec of .NET will run under mono. The way I see it, the only real drawback to .NET/mono is having to install the runtime (23MB). However, it comes standard with every windows OS shipped and installs with SP2 for XP and the new Ubuntu and Fedora Core distributions come with mono pre-installed, so the runtime requirement is quickly becoming a non-issue.

Erm, sorry for the stupid question, but: what's the point of supporting other platforms when LFS only runs on Windows?
-
(MonkOnHotTinRoof) DELETED by MonkOnHotTinRoof
-
(MonkOnHotTinRoof) DELETED by MonkOnHotTinRoof
Quote from Dygear :Ya know what sdether, I might try C# providing one thing. You help me setup what I have to, in order to get a simple LFS InSim program to connect to InSim. For example, it connects to InSim and asks for LFS version. Ok?

First Step, what do you use to program in, and how do you set that up. (I sware if I have to install those stupid playform files, I am sticking with C++).
Second Step, some example code to get the example program to connect to the LFS server and ask for the version.
I'll take over from there.

I program in Visual Studio, but I realize that that is a luxury. Visual C# Express, SharpDevelop or MonoDevelop are all good, free resources. One way or another you will have to have .NET installed (or mono on linux).

If you look at http://www.claassen.net/geek/lfs/ you will see a zip file with a GUI tester application. However, below is a simple, command line example to do what you asked for:


using System;
using LiveForSpeed.InSim;

namespace ConsoleTester
{
class Program
{
static void Main(string[] args)
{
InSimHandler handler = new InSimHandler(false, false);
Configuration config = handler.Configuration;
config.LFSHost = "127.0.0.1";
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);
handler.Close();
Console.WriteLine("Press RETURN to exit");
Console.ReadLine();
}
}
}

Basically with my lib, by virtue of connecting to LFS, the handler object will already have the version information. The ouput looks like this:


LFS info:
Product: S2
Version: 0.5Q
Serial: 2
Press RETURN to exit

Hope that helps.
You rock!
Edit1, just noticed in Express, they change all of my tabs to spaces. Is there anyway to keep it tabbed?
Edit2, Oh error, "Exception of type 'LiveForSpeed.InSim.Exceptions.InSimHandlerException+NoVersion' was thrown." On line 18.

// Random Tibbit, this is the port number I am going to use by defult, 30228.

Edit3, this is what I have extrapilated from your code . . .
using System;
using LiveForSpeed.InSim;

namespace ConsoleTester
{
class Program
{
static void Main(string[] args)
{
// Passes the InSimHandler Name Space to handler.
InSimHandler handler = new InSimHandler(false, false);
// Passes the handler.Configuration (InSimHandler.Configuration) to config.
Configuration config = handler.Configuration;
// Sets InSimHandler.Configuration.LFSHost to 127.0.0.1
config.LFSHost = "127.0.0.1";
// Sets InSimHandler.Configuration.LFSHost to 30000
config.LFSHostPort = 30000;
// Sets InSimHandler.Configuration.ReplyPort to 30001
config.ReplyPort = 30001;
// Sets InSimHandler.Configuration.UseKeepAlives to TRUE
config.UseKeepAlives = true;
// Sets InSimHandler.Configuration.UseSplitMessages to TRUE
config.UseSplitMessages = true;
// Sets InSimHandler.Configuration.GuaranteedDelivery to TRUE
config.GuaranteedDelivery = true;
// Sends the InSimHandler variables to LFS.
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);
// Closes the connection to LFS.
handler.Close();
Console.WriteLine("Press RETURN to exit");
Console.ReadLine();
}
}
}

Quote from Dygear :You rock!
Edit1, just noticed in Express, they change all of my tabs to spaces. Is there anyway to keep it tabbed?

Don't know about Express, but in Visual Studio under Tools->Options->Text Editor->C#->Tabs, you can change that behavior.

Quote from Dygear :
Edit2, Oh error, "Exception of type 'LiveForSpeed.InSim.Exceptions.InSimHandlerException+NoVersion' was thrown." On line 18.

LiveForSpeed.InSim.Exceptions. ... andlerException+NoVersion generally means that LFS didn't respond. Either you connected on the wrong port (set config.LFSHostPort = 30228; for your setup) or LFS wasn't ready yet. Basically it takes about 10 seconds after LFS shows the first splash screen before it accepts insim connections.

using System;
using LiveForSpeed.InSim;

namespace ConsoleTester
{
class Program
{
static void Main(string[] args)
{
// Create InSimHandler option. The first false tells it that we don't
// want Asynchronous event handling, the second false tells it
// that we don't want to use the App Config to set up configuration
InSimHandler handler = new InSimHandler(false, false);
// Gets the config object (this is just for easier access to it)
Configuration config = handler.Configuration;
// The IP address that LFS is on
config.LFSHost = "127.0.0.1";
// The port LFS listens for InSim on ( /insim= )
config.LFSHostPort = 30000;
// The port we want LFS to talk back to us on
config.ReplyPort = 30001;
// Should LFS send keep alive ACKs and should we automatically reply
config.UseKeepAlives = true;
// Use the split message package structure
config.UseSplitMessages = true;
// Turn on guaranteed Delivery
config.GuaranteedDelivery = true;
// Send ISI packet.. Also sends VER packet to make sure
// that we're talking to an instance of LFS that's compatible
handler.Initialize();
// Now we should be connected and know the LFS version, so
// we query it
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);
// Closes the connection to LFS.
handler.Close();
Console.WriteLine("Press RETURN to exit");
Console.ReadLine();
}
}
}

Conclusion to this topic. If your trying to program in C++, try C#.
Quote from Dygear :Conclusion to this topic. If your trying to program in C++, try C#.

lol

Quote from der_jackal : But 0 and '\0' are the same thing in this sense.

Yes, absolute right. Sorry for my misleading

InSim and C++
(21 posts, started )
FGED GREDG RDFGDR GSFDG