The online racing simulator
Updated: uploaded 1.0.10 with two bug fixes

I've uploaded version 1.0.9 to the first post, which has a few changes.
  • Fixed bug in TCP send code, that could cause some weird issues in certain cases
  • Added overridden Bind() method (see below)
  • Added overriden Send() method for sending messages (see below)
  • Obsoleted several old methods which will one day be removed
  • Changed the internal socket used in TcpSocket and UdpSocket to be protected
  • General code improvements
  • Fixed bug with NullReferenceException when calling InSim.Dispose()
  • Fixed bug with 'Spark.TcpSocket not connected' InSim error when calling InSim.Disconnect()
I would like to spend more time updating this, adding the long overdue string encoding stuff and many other fixes, but at the moment I'm hampered by a fault with my computer that makes it sound like a grumpy hornet, and am unable to program for long periods without going insane from the noise. A new part should arrive during the week, and if it doesn't I fear I may have to set myself on fire.

Anyway... you can now bind packets like this:

insim.Bind<IS_NCN>(NewConnection);

void NewConnection([b]InSim insim[/b], IS_NCN ncn)
{
// Pass.
}

With this binding method Spark will pass a reference to the InSim instance that raised the packet event, so you can easily access the specific host a packet was sent from. This is useful, even required, when using a single program instance to manage multiple hosts.

In addition the two old Send(string message) and Send(string message, int ucid, int plid) have been replaced with a single method that uses C# 4.0 optional parameters. This method has the prototype Send(string message, int ucid=0, int plid=0). You can use it like so:

// Send MST or MSX
insim.Send("Hello, InSim!");

// Send MTC to connection
insim.Send("Hello, you!", ucid: 0);

// Or send MTC to player
insim.Send("Hello, you!", plid: 0);

As I'm trying to maintain backwards compatibility I have left the old methods intact, but have marked them with obsolete attributes that will give you a friendly compiler warning when you use them. I have also obsoleted a few other small things that I plan one day to remove.

Please let me know if you have any problems.
Windows Form Application Base
Since I saw that I wasn't the only one, who wants to use Spark in a windows form application, here I am, posting the insim app i have started.

The base is still rough, but also pretty easy to understand(I hope).

The only condition is, that I am not responsible for any damage caused by it.

Feel free to upload any changes/improvements you apply to it. I'd be more than happy if somebody improves it.

The only neat feature there is to it is the button queue. You will see, that I have tested it with 88 buttons. I think that 10ms interval between each button is pretty safe. But you can change the interval, and how many buttons are sent at once too.

So, without any further ado, here's the source.

[E] Also, I have one question. In LFS_External, there was a very easy way to set the title of the typein box. But how do you do it with Spark? I didn't understand the logic from InSim.txt. =/
Attached files
Dizplay Cruise A.0.1.zip - 1.6 MB - 853 views
What exactly do you mean by 'title'? You set the text on the TypeIn box the same way you set the text on a normal button, with the Text property on the IS_BTN packet.

Anyway, I had written a small GUI example I was meaning to post, you can download it below. Nothing to complex, it just prints the contents of each MSO packet to a TextBox.
Attached files
SparkGuiExample.zip - 66.5 KB - 676 views
I'm sorry, I guess it was too late, so I couldn't explain what I meant well. Let me just quote InSim.txt.

Quote :// On clicking the button, a text entry dialog will be opened, allowing the specified number of
// characters to be typed in. The caption on the text entry dialog is optionally customisable using
// Text in the IS_BTN packet. If the first character of IS_BTN's Text field is zero, LFS will read
// the caption up to the second zero. The visible button text then follows that second zero.

// Text : 0-65-66-0 would display button text "AB" and no caption

// Text : 0-65-66-67-0-68-69-70-71-0-0-0 would display button text "DEFG" and caption "ABC"

So, I guess the question would be how do I have to trick the Text property, so I can get a caption, different from the button's text.

I'm sure that I'll figure it out if I just push my brain more, but yknow...
OK, I forgot about that sorry. Scawen is saying that you deliminate the text from the caption with a null character, which is the character '\0'. So what you would do is:

Text = "\0DEFG\0ABC";

Or if you wanted to do it in a more C# way:

Text = Char.MinValue + "DEFG" + Char.MinValue + "ABC";

Or more readable C# way:

Text = String.Format("{0}DEFG{0}ABC", Char.MinValue);

I have Updated the IS_BTN packet with a new Caption property. As I'm not ready to create a full release, here is some code you can copy and paste into the IS_BTN.cs file.

using System;

namespace Spark.Packets
{
/// <summary>
/// BuTton, for sending a button to InSim.
/// </summary>
public sealed class IS_BTN : IPacket, ISendable
{
/// <summary>
/// Gets the size of the packet.
/// </summary>
public byte Size { get; private set; }

/// <summary>
/// Gets the type of the packet.
/// </summary>
public PacketType Type { get; private set; }

/// <summary>
/// Gets or sets the packet request ID (returned in <see cref="IS_BTC"/> and <see cref="IS_BTT"/> packets).
/// </summary>
public byte ReqI { get; set; }

/// <summary>
/// Gets or sets the connection to display the button (0 = local / 255 = all).
/// </summary>
public byte UCID { get; set; }

/// <summary>
/// Gets or sets the unique button click ID.
/// </summary>
public byte ClickID { get; set; }

/// <summary>
/// Used internally by InSim.
/// </summary>
public byte Inst { get; set; }

/// <summary>
/// Gets or sets the button style flags.
/// </summary>
public ButtonStyles BStyle { get; set; }

/// <summary>
/// Gets or sets the max characters the user is allowed to type in.
/// </summary>
public byte TypeIn { get; set; }

/// <summary>
/// Gets or sets the distance from the left of the screen the button will be displayed (0 to 200).
/// </summary>
public byte L { get; set; }

/// <summary>
/// Gets or sets the distance from the top of the screen the button will be displayed (0 to 200).
/// </summary>
public byte T { get; set; }

/// <summary>
/// Gets or sets the width of the button (0 to 200).
/// </summary>
public byte W { get; set; }

/// <summary>
/// Gets or sets the height of the button (0 to 200).
/// </summary>
public byte H { get; set; }

/// <summary>
/// Gets or sets the text of the button.
/// </summary>
public string Text { get; set; }

/// <summary>
/// Gets or sets the caption for a type-in button.
/// </summary>
public string Caption { get; set; }

/// <summary>
/// Creates a new <see cref="IS_BTN"/> object.
/// </summary>
public IS_BTN()
{
Size = 12;
Type = PacketType.ISP_BTN;
}

/// <summary>
/// Creates a new <see cref="IS_BTN"/> object.
/// </summary>
public byte[] Pack()
{
string text = Text;

if (!String.IsNullOrEmpty(Caption))
{
text = String.Format("{0}{1}{0}{2}", Char.MinValue, Caption, text);
}

if (!String.IsNullOrEmpty(text))
{
Size = text.Length < 240 ? (byte)(12 + (text.Length + (4 - (text.Length % 4)))) : (byte)252;
}

var writer = new PacketWriter(Size);
writer.Write(Size);
writer.Write((byte)Type);
writer.Write(ReqI);
writer.Write(UCID);
writer.Write(ClickID);
writer.Write(Inst);
writer.Write((byte)BStyle);
writer.Write(TypeIn);
writer.Write(L);
writer.Write(T);
writer.Write(W);
writer.Write(H);
writer.Write(text, Size - 12);
return writer.GetData();
}
}
}

And you wonder why I love you.
I've been working on this quite a bit this week, and despite occasionally being driven from my computer by the noise, I've gotten a fair amount done.
  • Library is now fully CLS compliant and conforms to Microsoft Guidelines All (except naming)
  • New simplified initialization code and support for seperate UDP connection for MCI and NLP packets
  • Complete OutSim and OutGauge support
  • Complete documentation for all packets!
  • Thousands (literally) of small tweaks and changes
I still need to finish the string encoding logic and figure out a few issues let over with that, but I'm going to leave that until after my new computer part arrives sometime this week. I also want to make a CodePlex site for the project but I've run into a few issues with the name Spark. I plan to rename the library InSim.NET for the next release, unless anyone can think of something better.
SparkSim.NET
InCLSim
InSparkSim.NET
I have to say this InSim library is very nice, since the support of different characters.

I'm loving the syntax of Send()!

I hope you continue developing this library actively!
Quote from PoVo :I hope you continue developing this library actively!

As I said in my last post I've been working on Spark this week and I've made many improvements to the library. So many improvements that what was going to be version 1.1 has now changed to version 2.0.

I'm still working on the string encoding stuff though, which I know I've been going on about for ages, but it's complicated and I want to get it right. As far as I'm aware no other InSim library (besides pyinsim) correctly deals with all of the LFS codepages, so it should be cool when it's finished. Most libraries use the code from LFSLib.NET, which is old and does not handle double-byte character sets like Traditional Chinese.

The new string code is slightly slower, but fact is we're still talking in the region of factions of a millisecond, even for a worst-case scenario string (240 chars, lots of codepage changes, special chars, colours etc..). In tests last night I was able to parse a MSO packet 100,000 times in well under a second (even on my crappy old PC). While there is an efficiency overhead, I honestly don't think it will be perceptible. I was thinking of implementing a lazy string class, that only decoded strings if and when they're needed, and while I still may implement something like that in the future, from my tests I've decided I don't think it's necessary and I can't be bothered right now with the additional complexity.

On the plus side I've learned more about unicode and character sets than I can stand.

My new power-supply arrived today, plus a shiny new copy of Windows 7, so I have the joy of spending the rest of the day upgrading my development machine!
We will wait for that and thanks to updates of your library I really like it! thanks
Quote from DarkTimes :So many improvements that what was going to be version 1.1 has now changed to version 2.0.

I wish PRISM could keep up with this pace, but medic school is killing me. So DarkTimes, fight the good fight for me, ok?
Windows 7 is shiny.
Attached images
Windows7.png
In keeping with my other projects I've codeplexified this. You can find the project page at:

http://insimdotnet.codeplex.com/

I've uploaded the current codebase, although it still needs a few tweaks and fixes here and there. I'm going insane trying to get encoding stuff to work, so I've just included a modified version of the old LFSLib encoding code, which works great for single-byte character sets, but not double-byte characters such as Chinese. Also now included is full OutSim and OutGauge support, plus lots of other API improvements. I need to create some documentation for the changes, amongst other things.

I'm trying to get all this stuff finished to I can stop bloody working on LFS related things and program something more interesting.
I have decided that the best way to test the new version of the library is to write an application that uses it. So... if you have a good idea for a InSim program or tool, let me know and I might write it for you. And no, I'm not going to write a cruise server.

At the moment I'm thinking I might build a LFSRemote/LFSSpecator style tool with WPF, that lets you spectate races outside of LFS. I already have the track rendering code written, and I think drawing all the cars and stuff would be quite easy and fun.

But I'm open to suggestions.
Erm, a plugin interface using Source:Pawn as the plugin language.
As you know I'm using Spark in LFS Record. Recently I discovered that I can load the whole Spark project into mine (duh ) for easy debugging of Spark.
I wouldn't mind opening up the source of LFS Record if you're interested in contributing to such a thing. There are many things that can still be done with it (and I wouldn't mind some pointers on what I did wrong in My First Application).

Though it has intense insim usage in certain areas of insim, other areas are pretty much left untouched (the whole race tracking side really), so I can imagine if you'd be more interested in something that'll cover the whole insim spectrum.

I'm just throwing it out there
Yeah I'd be happy to contribute to LFS Record. The first thing I'd do is port the InSim code over to InSim.NET, which shouldn't be very difficult. It's not so much about testing every part of the code, most of it is fundamentally unchanged, but just taking care of those small things that only crop up when you're running in a real environment.

Once I'd done that I can take a look around and help with anything else that needs doing. I must admit that I've already had a peek at the disassembly, but it's hard to see exactly what's going on if you don't have the original source files.

So yeah, sounds good.
Alright. Over the weekend I'll do some cleaning up and add extra commenting where appropriate as so to make your life a little easier.
I think then I'll just mail you the solution first, before thinking about github or sorts. That mail will be accompanied with a bunch of questions from me as well I'm sure
OK cool.
I realise I'd haven't mentioned the new OutSim and OutGauge support in the next version of Spark/InSim.NET (source available on CodePlex), it's now only a few lines of code to add OutGauge or OutSim support to your application.

Here is a full OutGauge program that prints your current RPM to the console.

void InitializeOutGauge()
{
// Create OutGauge listener.
using (OutGauge outgauge = new OutGauge())
{
// Hook OutGauge packet event.
outgauge.PacketReceived += new EventHandler<OutGaugeEventArgs>(outgauge_PacketReceived);

// Start listening.
outgauge.Connect("127.0.0.1", 30000);
}
}

void outgauge_PacketReceived(object sender, OutGaugeEventArgs e)
{
// Handle OutGauge packet.
Console.WriteLine("RPM: {0}", e.Packet.RPM);
}

Simples!

You can download InSim.NET from CodePlex now and compile it yourself, or wait until just after Christmas for the official release.

FGED GREDG RDFGDR GSFDG