The online racing simulator
Searching in All forums
(921 results)
DarkTimes
S2 licensed
Brief example of parsing MSO commands.

using Spark;
using Spark.Packets;

class Program
{
InSim _insim;

Program()
{
using (_insim = new InSim())
{
_insim.Bind<IS_MSO>(MessageReceived);
_insim.Connect("127.0.0.1", 29999);
_insim.Send(new IS_ISI { Prefix = '!', IName = "^3Spark" });
_insim.Run();
}
}

void MessageReceived(IS_MSO mso)
{
string[] args;
if (TryParseCommand(mso, out args))
{
var command = args[0].ToLower();

switch (command)
{
case "!buy":
// Process !buy command.
break;
case "!sell":
// Process !sell command.
break;
}
}
}

bool TryParseCommand(IS_MSO mso, out string[] args)
{
if (mso.UserType == UserType.MSO_PREFIX)
{
var message = mso.Msg.Substring(mso.TextStart);
args = message.Split();
return args.Length > 0;
}

args = null;
return false;
}

static void Main()
{
new Program();
}
}

Last edited by DarkTimes, .
DarkTimes
S2 licensed
InSimSniffer in 57 lines!

using System;
using Spark;
using Spark.Packets;

namespace SimpleSniffer
{
class Program
{
Program()
{
using (var _insim = new InSim())
{
_insim.PacketReceived += new EventHandler<PacketEventArgs>(_insim_PacketReceived);
_insim.Connect("127.0.0.1", 29999);
_insim.Send(new IS_ISI { ReqI = 255, IName = "^3Sniffer", Flags = InSimFlags.ISF_MCI, Interval = 2000 });
_insim.Run();
}
}

void _insim_PacketReceived(object sender, PacketEventArgs e)
{
SniffPacket(e.Packet);

Console.WriteLine();
}

void SniffPacket<T>(T packet)
{
var properties = packet.GetType().GetProperties();

foreach (var property in properties)
{
var value = property.GetValue(packet, null);

if (value.GetType().IsArray)
{
foreach (var item in (Array)value)
{
if (property.Name == "CompCars" || property.Name == "NodeLaps")
SniffPacket(item); // Recursion!
else
Console.WriteLine("{0}: {1}", property.Name, item);
}
}
else
{
Console.WriteLine("{0}: {1}", property.Name, value);
}
}
}

static void Main()
{
new Program();
}
}
}

Last edited by DarkTimes, .
DarkTimes
S2 licensed
I'm bored so I rewrote my old example using Spark. You type !cd or !countdown and it shows a countdown in the middle of the screen.

using System.Timers;
using Spark;
using Spark.Packets;

namespace CountDown
{
class Program
{
InSim _insim;
Timer _timer;
int _count;
string[] _countdown = new string[] { "3", 2", "1", "GO!" };

public Program()
{
using (_insim = new InSim())
{
// Connect to InSim
_insim.Bind<IS_MSO>(MessageReceived);
_insim.Connect("127.0.0.1", 29999);
_insim.Send(new IS_ISI { IName = "^3CountDown", Prefix = '!' }); // Set prefix to '!'

// Initialize countdown timer.
_timer = new Timer();
_timer.AutoReset = true;
_timer.Interval = 1000; // Milliseconds
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);

// Go!
_insim.Run();
}
}

void MessageReceived(IS_MSO mso)
{
if (mso.UserType == UserType.MSO_PREFIX)
{
var message = mso.Msg.Substring(mso.TextStart);
if (message.StartsWith("!cd") || message.StartsWith("!countdown"))
{
// Start countdown!
_timer.Start();
}
}
}

void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (_count < _countdown.Length)
{
_insim.Send("/rcm {0}", _countdown[_count++]);
_insim.Send("/rcm_all");
}
else
{
_count = 0;
_timer.Stop();
_insim.Send("/rcc_all");
}
}

static void Main()
{
new Program();
}
}
}

Last edited by DarkTimes, .
DarkTimes
S2 licensed
Uploaded 1.0.4 to the first post.

Changes
  • Fixed bug with confirmation flags in IS_FIN.
  • Fixed bug with player flags in IS_LAP.
  • Added documentation for more packets (I'm up to NPL now).
  • Added StringHelper.ValidHost(string) and StringHelper.ValidPort(string) methods, which allow for easier checking for valid host and port numbers.
  • Some tweaks to CarHelper and TrackHelper, added some new methods and made them more reliable.
  • Added bool PacketEventArgs.TryCast<T>(out T) method.
Example of the new bool PacketEventArgs.TryCast<T>(out T) method:


void _insim_PacketReceived(object sender, PacketEventArgs e)
{
IS_VER ver;
if (e.TryCast(out ver))
{
Console.WriteLine("LFS: {0} {1} InSim: {2}", ver.Product, ver.Version, ver.InSimVer);
}
}

Last edited by DarkTimes, .
DarkTimes
S2 licensed
Uploaded 1.0.3 to the first post.

Changes
  • Fixed critical bug which was stopping the socket from correctly being released when the InSim connection closed. As a consequence InSim.Run() should now exit properly and InSim.IsConnected should now return the correct value in all situations.
  • Added InSim Relay support. Check Example 7 in SparkExamples for a detailed example.
Edit: I also changed the Car Update example to now spectate players who speed, as it makes more sense than just printing out car speeds.

InSim Relay

Connecting to InSim relay is pretty simple and support needed no additions to the main InSim class. In this example we connect to relay, request the host list, then print out the name of each LFS host that is received.

using System;
using Spark;
using Spark.Packets;
using Spark.Helpers;

class Program
{
static void Main()
{
using (var insim = new InSim())
{
// Relay packets begin with IR_*.
insim.Bind<IR_HOS>(HostListReceived);

// Connect to the relay host.
insim.Connect("isrelay.lfs.net", 47474);

// Request for the host list to be sent.
insim.Send(new IR_HLR { ReqI = 255 });

insim.Run();
}
}

static void HostListReceived(IR_HOS hos)
{
// Loop through each host in the list.
foreach (var host in hos.Info)
{
// Print out the host name.
Console.WriteLine("Host: {0}", StringHelper.StripColors(host.HName));

// If this is the last host, print a blank line after it.
if (host.Flags.HasFlag(InfoFlags.HOS_LAST))
Console.WriteLine();
}
}
}

Last edited by DarkTimes, .
DarkTimes
S2 licensed
Uploaded 1.0.2 to the first post.

Changes Since 1.0.1
  • Allowed reuse of InSim, TcpSocket and UdpSocket without needing to create a new instance each time
  • Added asyncronous connect, by calling InSim.BeginConnect(string, int, AsyncCallback) and InSim.EndConnect(IAsyncResult) methods
  • Added InSim.Connecting event which is raised when the connect operation is begun but before the connection is established
  • InSim.Connect and InSim.EndConnect try to throw an appropriate InSimException instead of a generic SocketException
  • Added IS_BTN patch supplied by filur
  • Fixed bug with MathHelper.SpeedToMph method where it was returning Kph
  • Fixed "existing connection closed by remote host" error when calling InSim.Disconnect()
  • Lots of small corrections and tweaks to the SparkExamples solution
DarkTimes
S2 licensed
Well actually an issue which could affect the dictionary of players is if you connect to LFS on the menu screen and then join a host. A better solution would be to request the players both when connecting to LFS and also when joining a multiplayer race.

using System;
using System.Collections.Generic;
using Spark;
using Spark.Packets;
using Spark.Helpers;

namespace Spark.Example5
{
class Program
{
static InSim _insim;
// We store the players in a dictionary.
static Dictionary<int, IS_NPL> _players = new Dictionary<int, IS_NPL>();

static void Main()
{
// Create new InSim object.
using (_insim = new InSim())
{
// Bind handlers.
_insim.Bind<IS_ISM>(MultiPlayerInfo);
_insim.Bind<IS_NPL>(NewPlayer);
_insim.Bind<IS_PLL>(PlayerLeft);
_insim.Bind<IS_MCI>(MultiCarInfo);

// Establish the InSim connection.
_insim.Connect("127.0.0.1", 29999);

// Initialize InSim.
_insim.Send(new IS_ISI { IName = "^3Example", Flags = InSimFlags.ISF_MCI, Interval = 500, Admin = string.Empty });

// Request for multiplayer info packet to be sent.
_insim.Send(new IS_TINY { SubT = TinyType.TINY_ISM, ReqI = 255 });

// Prevent program from exiting.
_insim.Run();
}
}

static void MultiPlayerInfo(IS_ISM ism)
{
// When joining multiplayer request for all connections and players to be sent.
_insim.Send(new IS_TINY { SubT = TinyType.TINY_NCN, ReqI = 255 });
_insim.Send(new IS_TINY { SubT = TinyType.TINY_NPL, ReqI = 255 });
}

static void NewPlayer(IS_NPL npl)
{
if (_players.ContainsKey(npl.PLID))
{
// Leaving pits, just update NPL object.
_players[npl.PLID] = npl;
}
else
{
// Add new player.
_players.Add(npl.PLID, npl);
}
}

static void PlayerLeft(IS_PLL pll)
{
// Remove player.
_players.Remove(pll.PLID);
}

static void MultiCarInfo(IS_MCI mci)
{
// Loop through each car on track.
foreach (var car in mci.CompCars)
{
// Get the player driving this car.
IS_NPL npl;
if (_players.TryGetValue(car.PLID, out npl))
{
// Check cars speed.
var kph = MathHelper.SpeedToKph(car.Speed);
if (kph > 80)
{
// Spectate player and send chat message.
_insim.Send("/spec {0}", npl.PName);
_insim.Send("{0} ^3spectated for speeding", npl.PName);
}
}
}
}
}
}

Last edited by DarkTimes, .
DarkTimes
S2 licensed
The dictionary should work, dunno what problems you're having.

There is a bug in the double MathHelper.SpeedToMph(int) method, I will release a fix at some point, but you can change it to this:

public static double SpeedToMph(int speed)
{
return speed / 146.486067;
}

Obviously there are several issues that need to be worked out in the library, my plan is to port InSimSniffer over to Spark which should let me resolve most of these problems.

I realise I also need to add proper string decoding, but I've been considering releasing a standalone library for this.
Last edited by DarkTimes, .
DarkTimes
S2 licensed
Schumi's aggressive moves were understandable when he was fighting for championships, but it's crazy (and dangerous) to keep doing them as a midfield car.
DarkTimes
S2 licensed
Quote from JCTK :I have a feeling this might be at least a 3 stop race. The hard tyres weren't lasting more than 15 laps~?!

That's what they're saying on the BBC feed.
DarkTimes
S2 licensed
Nice driving from Buemi. Go Hamilton!
DarkTimes
S2 licensed
Yup the problem of a word beginning with R is an issue. The word 'race' is the best I can think of...

Php Race InSim Mod
Last edited by DarkTimes, .
DarkTimes
S2 licensed
Quote from Dygear :Short name is PISM.

Invent an extra 'r' and it would become PRISM, which would be an awesome name.
DarkTimes
S2 licensed
It depends. My experience tells me that it's luck of the draw. Sometimes you will get a computer science student looking for some extra cash, other times it's some guy in India who has barely ever touched a computer. I find you're better off sending an email or using online help.

Also it's surprisingly effective to find out the email of the CEO of the company and email them. Their assistants will try to resolve it to avoid the bad PR.
Last edited by DarkTimes, .
DarkTimes
S2 licensed
I agree, calling Tiscali is a waste of time. I used to work in broadband tech support, and their service is just non-existent. Half the time they will just argue with you that you don't have a problem at all.
Last edited by DarkTimes, .
DarkTimes
S2 licensed
Ah sorry, trying to do things too fast. I've uploaded a fixed version.

As I say I'll try to do real work on it this weekend.
DarkTimes
S2 licensed
OK - Thanks for those!

I've uploaded a new version to the first post, with those fixes, as well as a couple of other things. I created a separate solution with all the examples in it, so it's easier for people to get off the ground. You can find it in the SparkExamples folder. I also added a readme and proper licenses.

In case I didn't mention it before the library is released under the LGPL.
DarkTimes
S2 licensed
Sorry, I've not had time to work on this since I posted it. Been very busy. I'll try to get all the kinks worked out over the weekend.

In terms of the car update sample, it appears I missed out a couple of things, mainly I forgot to set the MCI flag and interval in the ISI packet. I'm not at home to test this, but try this code:

using System;
using System.Collections.Generic;
using Spark;
using Spark.Packets;
using Spark.Helpers;

class Program
{
// We store the players in a dictionary.
static Dictionary<int, IS_NPL> _players = new Dictionary<int, IS_NPL>();

static void Main()
{
// Create new InSim object.
using (var insim = new InSim())
{
// Bind handlers.
insim.Bind<IS_NPL>(NewPlayer);
insim.Bind<IS_PLL>(PlayerLeft);
insim.Bind<IS_MCI>(MultiCarInfo);

// Establish the InSim connection.
insim.Connect("127.0.0.1", 29999);

// Initialize InSim.
insim.Send(new IS_ISI { IName = "^3Example", Flags = InSimFlags.ISF_MCI, Interval = 500 });

// Request players.
insim.Send(new IS_TINY { SubT = TinyType.TINY_NPL, ReqI = 255 });

// Prevent program from exiting.
insim.Run();
}
}

static void NewPlayer(IS_NPL npl)
{
if (_players.ContainsKey(npl.PLID))
{
// Leaving pits, just update NPL object.
_players[npl.PLID] = npl;
}
else
{
// Add new player.
_players.Add(npl.PLID, npl);
}
}

static void PlayerLeft(IS_PLL pll)
{
// Remove player.
_players.Remove(pll.PLID);
}

static void MultiCarInfo(IS_MCI mci)
{
// Loop through each car on track.
foreach (var car in mci.CompCars)
{
IS_NPL npl;
if (_players.TryGetValue(car.PLID, out npl))
{
// Convert LFS speed into Mph.
var mph = MathHelper.SpeedToMph(car.Speed);

// Print nicely formatted string to console.
Console.WriteLine("Speed: {0} {1:F2}", npl.PName, mph);
}
}
}
}

Last edited by DarkTimes, .
DarkTimes
S2 licensed
Obviously a bug.
.NET - InSim.NET - InSim library
DarkTimes
S2 licensed
InSim.NET is a InSim library for Live for Speed, written for the .NET Framework. It allows you to create a socket connection with the game and to send and receive packets of data. These packets can be used to control LFS, issue commands and request information. The library has been designed for flexibility, extensibility and performance. It tries to match the original InSim API as closely as possible, while taking care not to get in your way.

Note: InSim.NET was originally known as Spark, but changed its name to prevent it clashing with another .NET project with the same name. Note: Many code examples in this thread were written for version 1.0 the library and probably won't work correctly in the newer version. You can find up-to-date examples in the documentation.

Quick LinksWhat's New?

This release is for version 2.0 of the library, which has seen a number of large changes
  • Full support for InSim, InSim Relay, OutSim and OutGauge
  • Full support for all LFS character encodings
  • Improved API
  • Improved networking code
  • Improved documentation
  • A new home on GitHub
  • New Git source code repository
Requirements

InSim.NET requires .NET Framework 4.5 and is CLS compliant with all .NET languages. It is written in C# and compiled with Visual Studio 2013.

Source Code

InSim.NET now uses Git distributed source control, which means it's easy to clone the latest repository, create forks and make changes. Anyone is welcome to clone the repository and create their own version of the library.

License

InSim.NET is released under the Lesser General Public License (LGPL).

Download

InSim.NET is available through NuGet, the .NET package manager. To install it type the following command at the package manager console.

PM> Install-Package InSimDotNet

Alternatively you can download it from the GitHub project page.

https://github.com/alexmcbride/insimdotnet
Last edited by DarkTimes, .
DarkTimes
S2 licensed
Just watched the last episode. I enjoyed it, but am quite annoyed that none of my questions were answered. Seems the whole ending was just them setting up the mystery of season 2. And all the people who are saying this is shit can go and die.
DarkTimes
S2 licensed
Quote from Dygear :I know how that feels! I'm only 21 too, so this sucks massively.

Hah, I wish I was 21.

Actully I don't, being 21 was rubbish.
DarkTimes
S2 licensed
I've not been working on this for several months, as I had to cut back on my day-to-day coding due to carpel-tunnel syndrome. However I'm fully recovered and am able to return to spending many hours a day coding (albeit with a much improved posture and an ergonomic keyboard). This means I hope to finish up on this beta and finally get it out there. Sorry for the six month delay.
DarkTimes
S2 licensed
I have never downloaded a virus from this forum.
FGED GREDG RDFGDR GSFDG