The online racing simulator
Experimenting with adding a method similar to Send, that allows you to send buttons. Right now it's called InSim.Button(). As with Send it's a convenience method and not a complete replacement for all the functionality that the IS_BTN packet provides.

Here's how you use it. There are a couple of different overloads for it.


insim.Button(
ucid: 255,
clickid: 1,
bstyle: ButtonStyles.ISB_CLICK | ButtonStyles.ISB_DARK,
left: 40,
top: 40,
width: 40,
height: 10,
text: "Hello, Buttons!");

You can find it in the latest changeset on the repository.
Maybe there is a problem with this lib. Im getting NewPlayer packet reported twice sometimes.. It happend rarely..

Here some of the log working fine:

[INFO] 2011-09-04 19:17:22,603 Program - ENTRANDO A: NewConnection ( Cajiao )
[INFO] 2011-09-04 19:17:22,603 Program - AÑADO A ESTE PILOTO ( Cajiao )
[INFO] 2011-09-04 19:17:22,603 Program - ENTRANDO A: ConnectToCesavStats
[INFO] 2011-09-04 19:17:22,775 Program - SALIENDO DE: ConnectToCesavStats
[INFO] 2011-09-04 19:17:22,775 Program - SALIENDO DE: NewConnection ( Cajiao )
[B][INFO] 2011-09-04 19:17:31,931 Program - ENTRANDO A: NewPlayer ( ^0-^1VR^0- ^7Borjita )[/B]
[INFO] 2011-09-04 19:17:31,931 Program - SUBLOG: NewPlayer ( Cajiao )
[INFO] 2011-09-04 19:17:31,931 Program - ENTRANDO A: ConnectToCesavStats
[INFO] 2011-09-04 19:17:32,321 Program - SALIENDO DE: ConnectToCesavStats
[INFO] 2011-09-04 19:17:32,321 Program - SALIENDO DE: numeroVueltas Valor=0
[INFO] 2011-09-04 19:17:32,321 Program - ENTRANDO A: creaVuelta
[INFO] 2011-09-04 19:17:32,321 Program - SALIENDO DE: creaVuelta
[INFO] 2011-09-04 19:17:32,321 Program - SALIENDO DE:NewPlayer

But check this other:

[INFO] 2011-09-04 21:02:03,900 Program - ENTRANDO A: NewConnection ( rariga2 )
[INFO] 2011-09-04 21:02:03,900 Program - AÑADO A ESTE PILOTO ( rariga2 )
[INFO] 2011-09-04 21:02:03,900 Program - ENTRANDO A: ConnectToCesavStats
[INFO] 2011-09-04 21:02:04,040 Program - SALIENDO DE: ConnectToCesavStats
[INFO] 2011-09-04 21:02:04,040 Program - SALIENDO DE: NewConnection ( rariga2 )
[B][INFO] 2011-09-04 21:02:10,712 Program - ENTRANDO A: NewPlayer ( ^0-^1VR^0- ^7Rafa )[/B]
[INFO] 2011-09-04 21:02:10,712 Program - SUBLOG: NewPlayer ( rariga2 )
[INFO] 2011-09-04 21:02:10,712 Program - ENTRANDO A: ConnectToCesavStats
[INFO] 2011-09-04 21:02:11,290 Program - SALIENDO DE: ConnectToCesavStats
[INFO] 2011-09-04 21:02:11,290 Program - SALIENDO DE: numeroVueltas Valor=0
[INFO] 2011-09-04 21:02:11,290 Program - ENTRANDO A: creaVuelta
[INFO] 2011-09-04 21:02:11,290 Program - SALIENDO DE: creaVuelta
[INFO] 2011-09-04 21:02:11,290 Program - SALIENDO DE:NewPlayer
[B][INFO] 2011-09-04 21:02:36,181 Program - ENTRANDO A: NewPlayer ( ^0-^1VR^0- ^7Rafa )[/B]
[INFO] 2011-09-04 21:02:36,181 Program - SUBLOG: NewPlayer ( rariga2 )
[INFO] 2011-09-04 21:02:36,181 Program - ENTRANDO A: ConnectToCesavStats
[INFO] 2011-09-04 21:02:36,321 Program - SALIENDO DE: ConnectToCesavStats
[INFO] 2011-09-04 21:02:36,321 Program - SALIENDO DE: numeroVueltas Valor=0
[INFO] 2011-09-04 21:02:36,321 Program - ENTRANDO A: creaVuelta
[INFO] 2011-09-04 21:02:36,321 Program - SALIENDO DE: creaVuelta
[INFO] 2011-09-04 21:02:36,321 Program - SALIENDO DE:NewPlayer

I attach the replay of this second log part..


I forgot to add the version Im using, 2.0.12.0 version.
Attached files
KY1X_0R_13.mpr - 55.6 KB - 344 views
I watched the packets in InSimSniffer and no NPL packets are sent by LFS during the replay. All I can imagine is that you are requesting for the NPL packet to be sent in your own code, and at some point in your logic you are requesting it twice.

These are all the packets sent by LFS during the replay, any other packets you receive you must have requested.
Attached files
InSimSniffer Export 05092011 1121.txt - 12.7 KB - 484 views
The only time I request NPL packet is in :

static void InSimMulti(InSim insim, IS_ISM ism)
{
_log.Info("ENTRANDO A: InSimMulti");
...
insim.Send(new IS_TINY { ReqI = 1, SubT = TinyType.TINY_NPL });
...
_log.Info("SALIENDO DE:InSimMulti");
}

But, the program didnt join in that part of the code :S
In the replay you posted there are no NPL packets sent, I've tested it and InSim.NET does not raise any NPL events during that replay. That suggests to me that the problem is in your code, you are requesting the packets somehow, but without knowing more or seeing your code I can't say for certain.
What is best time for Interval? I am trying from 10ms but program will not connect. Sometimes with 1000 also will not connect from the first.
Quote from M.M.L. :What is best time for Interval? I am trying from 10ms but program will not connect. Sometimes with 1000 also will not connect from the first.

According to InSim.txt the minimum interval is 40ms.
With 50ms in 95% I get this exception

05.09.2011 14:54:12: Insim greska pri konektovanju 2
InSimDotNet.InSimException: InSim is not connected
at InSimDotNet.InSim.ThrowIfNotConnected() in C:\Users\Alex\Documents\Visual Studio 2010\Projects\InSimDotNet2\InSimDotNet\InSim.cs:line 491
at InSimDotNet.InSim.Send(ISendable packet) in C:\Users\Alex\Documents\Visual Studio 2010\Projects\InSimDotNet2\InSimDotNet\InSim.cs:line 229
at InSimDotNet.InSim.Send(String message, Object[] args) in C:\Users\Alex\Documents\Visual Studio 2010\Projects\InSimDotNet2\InSimDotNet\InSim.cs:line 266
at ConsoleApplication1.Program.Main() in J:\Projekti\insimmm\insimmm\Program.cs:line 1956

Code is:
try
{
insim.Send("/msg " + uspesnakonekcija);
insim.Send(new IS_TINY { SubT = TinyType.TINY_NCN, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_NPL, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_SST, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_RST, ReqI = 255 });
}
catch (InSimException ex)
{
Logiraj("Insim greska pri konektovanju 2", ex.ToString());
}

This works fine for me:


<?php 
var insim = new InSim();

insim.Initialize(new InSimSettings {
    
Host "127.0.0.1",
    
Port 29999,
    
UdpPort 30000,
    
Interval 50// Milliseconds
});

insim.Send("/msg I don't know what this contains...");
insim.Send(new IS_TINY SubT TinyType.TINY_NCNReqI 255 });
insim.Send(new IS_TINY SubT TinyType.TINY_NPLReqI 255 });
insim.Send(new IS_TINY SubT TinyType.TINY_SSTReqI 255 });
insim.Send(new IS_TINY SubT TinyType.TINY_RSTReqI 255 });

Console.ReadKey();
?>

That error message means you are trying to send a packet when LFS is not connected. Where in your code are you trying to send the packets? Have you made sure that you have initialized the connection (InSim.Initialize()) before sending those packets?
try
{
insim.Initialize(new InSimSettings
{
Host = IPAddress,
Port = Port,
Admin = AdminPW,
Prefix = '!',
Flags = InSimFlags.ISF_MCI | InSimFlags.ISF_CON | InSimFlags.ISF_MSO_COLS,
Interval = 50, // The interval at which updates are sent (milliseconds)

});
Logiraj("################### Uspesno konektovan: ################### ", IPAddress + "; " + Port + "; " + AdminPW + ";");
}
catch(InSimException ex)
{
Logiraj("Insim greska pri konektovanju 1",ex.ToString());
}

Program.UcitajPodesavanja();
UcitajJezik();
TimerReset(insim);
UcitajPorukeIzFajla();
if (userest == true)
{
UcitajRest(insim, 0);
}
try
{
insim.Send("/msg " + uspesnakonekcija);
insim.Send(new IS_TINY { SubT = TinyType.TINY_NCN, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_NPL, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_SST, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_RST, ReqI = 255 });
}
catch (InSimException ex)
{
Logiraj("Insim greska pri konektovanju 2", ex.ToString());
}

Is the first exception being thrown when this happens? One issue I can see that would cause that error message is that, if the first exception is thrown, the rest of the code will still try to execute, even though the connection has not been established. What I would do is this:

try
{
insim.Initialize(new InSimSettings
{
Host = IPAddress,
Port = Port,
Admin = AdminPW,
Prefix = '!',
Flags = InSimFlags.ISF_MCI | InSimFlags.ISF_CON | InSimFlags.ISF_MSO_COLS,
Interval = 50, // The interval at which updates are sent (milliseconds)
});
Logiraj("################### Uspesno konektovan: ################### ", IPAddress + "; " + Port + "; " + AdminPW + ";");
}
catch(InSimException ex)
{
Logiraj("Insim greska pri konektovanju 1",ex.ToString());

[b]// Connection to LFS has failed, exit program.
Environment.Exit(1);[/b]
}

Program.UcitajPodesavanja();
UcitajJezik();
TimerReset(insim);
UcitajPorukeIzFajla();
if (userest == true)
{
UcitajRest(insim, 0);
}

try
{
insim.Send("/msg " + uspesnakonekcija);
insim.Send(new IS_TINY { SubT = TinyType.TINY_NCN, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_NPL, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_SST, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_RST, ReqI = 255 });
}
catch (InSimException ex)
{
Logiraj("Insim greska pri konektovanju 2", ex.ToString());
}

It's hard to bug fix someone else's code by looking at a small section of it, but that's the first thing that jumps out at me.
He is throwing exception on second part. First part is ok...
05.09.2011 15:21:01: Insim greska pri konektovanju 2... //Error on part 2, first is ok....

try
{
insim.Initialize(new InSimSettings
{
Host = IPAddress,
Port = Port,
Admin = AdminPW,
Prefix = '!',
IName = "RaceCommander",
Flags = InSimFlags.ISF_MCI | InSimFlags.ISF_CON | InSimFlags.ISF_MSO_COLS,
Interval = 100, // The interval at which updates are sent (milliseconds)

});
Logiraj("################### Uspesno konektovan: ################### ", IPAddress + "; " + Port + "; " + AdminPW + ";");
}
catch(InSimException ex)
{
Logiraj("Insim greska pri konektovanju 1",ex.ToString());
Environment.Exit(1);
}

Program.UcitajPodesavanja(); //reading from file
UcitajJezik(); //reading from file
TimerReset(insim); //seting timer
UcitajPorukeIzFajla(); //reading from file
if (userest == true)
{
UcitajRest(insim, 0);
}
try
{
insim.Send("/msg " + uspesnakonekcija);
insim.Send(new IS_TINY { SubT = TinyType.TINY_NCN, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_NPL, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_SST, ReqI = 255 });
insim.Send(new IS_TINY { SubT = TinyType.TINY_RST, ReqI = 255 });
}
catch (InSimException ex)
{
Logiraj("Insim greska pri konektovanju 2", ex.ToString());
}

Also have problem with Serbian characters like "Ć Č Š Đ Ž". What i need to do?
Quote from M.M.L. :Also have problem with Serbian characters like "Ć Č Š Đ Ž". What i need to do?

What do you mean by "problem"? You'll need to be more specific if you want me to help you.

Edit: I've had a look at the encoding for those characters, it seems that .NET is happy to convert something like 'Ć' into a basic latin 'C'. I'm not sure what solution, if any, there is to this issue. Fact is that CP1252 encoding (the default) doesn't regard 'Ć' as an error, it just converts it to the closest match. I'm not sure if there is any way to make the encodings more strict about what they accept, which will cause InSim.NET to search the codepages for the correct character. 'Ć' is in CP1250.

Of course I don't know if this is the problem you are referring to.
Yes that is problem. Letters Ž and Š is OK, but Č,Ć and Đ = C, C and D
Sorry, but I don't really have a solution to this issue. Turns out the .NET encoding code has decided that Č should turn into C. The InSim.NET EncodingHelper class relies on the fact that Windows will return an error if you try to convert a unicode char to a Windows codepage char that doesn't exist. While the codepage 1252 doesn't have Č, it seems happy to provide an alternative. I don't see any way to change this default behaviour.

If anyone has a better idea please let me know! Seriously.
Hi..

Im using SMALL packet to know when race is restarted. First, I tried this:

if (small.SubT == SmallType.SMALL_VTA && small.UVal.Equals(VoteAction.VOTE_RESTART))
{
...
}

But didnt work, then I used Sniffer to know the param of UVal on restart and modified the code to

if (small.SubT == SmallType.SMALL_VTA && small.UVal == long.Parse("2"))
{
...
}

Working fine..

Whats wrong with the first way?
You need to cast the UVal to a VoteAction.

if (small.SubT == SmallType.SMALL_VTA && VoteAction.VOTE_RESTART == (VoteAction)small.UVal)
{

}

I've been messing around with Visual Studio 11 and I'm quite impressed with the new async stuff in .NET 4.5.

It doesn't work on sockets directly, so you need to use it in conjunction with the TcpClient and NetworkStream classes. I had a go at writing a InSim.NET style TcpSocket with .NET 4.5. It's not complete, just a proof of concept, but you can see how much it simplifies the asynchronous code.


<?php 
public class TcpSocket {
    private const 
int BufferSize 1024;

    private 
TcpClient _client;
    private 
NetworkStream _stream;
    private 
byte[] _temp = new byte[BufferSize];
    private List<
byte_buffer = new List<byte>(BufferSize);

    public 
TcpSocket() {
        
_client = new TcpClient();
        
_client.Client.NoDelay true;
    }

    public 
async Task ConnectAsync(string hostint port) {
        
await _client.ConnectAsync(hostport);

        
_stream _client.GetStream();

        
HandleReceive();
    }

    public 
void Close() {
        if (
_stream != null) {
            
_stream.Close();
        }

        
_client.Close();
    }

    public 
async Task SendAsync(byte[] buffer) {
        
await _stream.WriteAsync(buffer0buffer.Length);
    }

    private 
async void HandleReceive() {
        
int count await _stream.ReadAsync(_temp0_temp.Length);

        if (
count == 0) {
            
Close(); // Lost connection.
        
}
        else {
            
_buffer.AddRange(_temp.Take(count));

            while (
_buffer.Any() && _buffer.Count >= _buffer.First()) {
                
int size _buffer.First();

                
byte[] packet _buffer.Take(size).ToArray();

                
HandlePacket(packet);

                
_buffer.RemoveRange(0size);
            }

            
HandleReceive();
        }
    }

    private 
void HandlePacket(byte[] packet) {
        
// do something...
        
Debug.WriteLine(packet.Length);
    }
}
?>

They patched Visual Studio 2010 recently (go to Windows Update), and it seems they've changed the way the Console works (this might be to do with the unicode support they're adding to the console, which is good for InSim.NET apps). Anyway, it means you cannot do a WriteLine if you've already called ReadKey, that means you cannot do...

Console.ReadKey(true);

... to stop the program closing. Instead I recommend just going with the old...

while (insim.IsConnected) {
Thread.Sleep(200);
}

... method.

I might be wrong about this, of course, but it seems to be the case on the two computers I've tested. I need to investigate more.
Here is a sample i made with full control of connections and players with some examples on how to use commands MCI packet and tracking Track and Layout name(if you load a layout through a remote player the name wont be available. to 'fix it' you can make a command which will do /axsave [yourname] and /axload so it will save it to the server and reload it with the connect name)

Suggestions are welcome and fixes in case i've done something wrong.

Link: http://www.mediafire.com/?qqhhrr1mtk4x0qh
and @ attachment
Attached files
InSimNETSampleByDK.rar - 392 KB - 629 views
Is there any vb.net sample codes?
C# samples work but I can't get the syntax working with vb.net (no events triggered and also shows no connection).


<?php 
  Dim LFSOut 
As OutSim
    
Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgsHandles MyBase.Load
        Dim timeout 
As TimeSpan TimeSpan.FromSeconds(10)
        
LFSOut = New OutSim(timeout)
        
AddHandler LFSOut.PacketReceivedAddressOf outsim_PacketReceived
        AddHandler LFSOut
.TimedOutAddressOf outsim_TimedOut
        LFSOut
.Connect("127.0.0.1"10001)
    
End Sub

    
Private Sub outsim_PacketReceived(ByVal sender As ObjectByVal e As OutSimEventArgs)
        
TextBox1.Text e.Accel.X
    End Sub

    
Private Sub outsim_TimedOut(ByVal sender As ObjectByVal e As EventArgs)
        
TextBox1.Text "timeout"
    
End Sub
?>


I fixed a small bug that could cause the MSO msg text to be wrong if the player's name contained non-ASCII characters.

Download V2.0.13
I have been contiuning work on InSim.NET 3.0.0, and it's coming along, although slowly. I posted before about how I wanted to fix the mishmash of naming conventions and also make it generally more conhesive and easier to use. Anyway, I thought I'd give a little preview of how the library is looking at the moment. Here is a typical small example app that prints the lap time of each player to the console whenever they complete a lap.


<?php 
using System
;
using System.Collections.Generic;
using InSimDotNet;
using InSimDotNet.Packets;

namespace 
InSimTest {
    class 
ExampleInSimApp {
        
Dictionary<intNewPlayerplayers = new Dictionary<intNewPlayer>(32);

        
void RunInSim() {
            
// Create new InSimClient object.
            
InSimClient client = new InSimClient();

            
// Hook up packet events.
            
client.InSimMultiPacket += client_InSimMultiPacket;
            
client.NewPlayerPacket += client_NewPlayerPacket;
            
client.PlayerLeavePacket += client_PlayerLeavePacket;
            
client.LapPacket += client_LapPacket;

            
// Initialize InSim.
            
client.Initialize(new InSimSettings {
                
Host "127.0.0.1",
                
Port 29999,
                
Admin String.Empty,
                
Name "Test",
            });

            
// Request ISM packet to be sent.
            
client.Send(new Tiny 
                
RequestId 1
                
SubType TinyType.InSimMulti 
            
});

            
// Stop program from exiting.
            
Console.WriteLine("Press any key to exit...");
            
Console.ReadKey(true);
        }

        
void client_InSimMultiPacket(object senderPacketEventArgs<InSimMultie) {
            
InSimClient client = (InSimClient)sender// Get InSimClient.

            // Request all players to be sent.
            
client.Send(new Tiny 
                
RequestId 1
                
SubType TinyType.NewPlayer
            
});
        }

        
void client_NewPlayerPacket(object senderPacketEventArgs<NewPlayere) {
            
NewPlayer player e.Packet;

            
players[player.PlayerId] = player // Add player to players dictionary.
        
}

        
void client_PlayerLeavePacket(object senderPacketEventArgs<PlayerLeavee) {
            
players.Remove(e.Packet.PlayerId); // Remove player from dictionary.
        
}

        
void client_LapPacket(object senderPacketEventArgs<Lape) {
            
// The EventArgs contains the packet.
            
Lap lap e.Packet;

            
// Get player from players dictionary.
            
NewPlayer player players[lap.PlayerId];

            
// Write lap time to console.
            
Console.WriteLine("Lap {0} ({1}): "player.PlayerNamelap.LapTime);
        }
    }
}
?>

A lot has changed, in no particular order:
  • InSim has been renamed InSimClient
  • Packets are no longer bound, they're just events
  • The names of packets and attributes have been changed to be consistent with .NET naming guidelines
  • The packet attributes have been improved to make it easier to access information
Plus a huge amount more! Anyway as I say just a preview, it might all change.
Keep up with the progress updates
Hi. I've got one problem with InSim.NET library. (I think is my bad, but I would like ask you...)

I would like to make an application for LFS with .NET. I do the next:

- Declare outsim/outgage variables
- Initialize variables
- Subscribe to outsim_PacketReceived event
- Enter in a loop:
- is outsim disconnect? (no)-> Connect to outsim
- get all variable set in outsim_PacketReceived event

But there is a problem with the loop. The IsConnected property is lying me, is not connected but the value is true! If I close connection and try to reconnect, I'm getting a exception... And I don't know what can I do here¿?

Sorry for my bad english, the question is simply, what is the operation for get an application is connected to outsim automatically?

Thank you!

FGED GREDG RDFGDR GSFDG