The online racing simulator
I'm not sure I understand what you're talking about, sorry.

OutSim and OutGauge use UDP which is a connectionless protocol. There is not really a concept of being connected or disconnected with UDP. There is no way to figure out if a UDP socket is connected or not, other than to check if you have received any data on the socket recently. If no data is received within the timeout you specify then the connection is closed. OutSim.IsConnected property returns true until the connection times out. If no timeout is set then the connection never times out and IsConnected is always true.

Maybe if you post some code showing what it is you're doing I can help you more specifically with your problem.
Hi DarkTimes. Here is my code:

MainLoop Code:

void mainLoop()
{
testlfs.LFS testfls = new LFS();
float pitch = 0;
while (true)
{
if (!testfls.IsConnected)
testfls.Connect();
else
pitch = testfls.pitch;

System.Threading.Thread.Sleep(20);
}
}

LFS Class:


class LFS
{
private OutSim outsim;
public bool IsConnected = false;
public float pitch = 0;

public LFS()
{
outsim = new OutSim(1);
outsim.PacketReceived += new EventHandler<OutSimEventArgs>(outsim_PacketReceived);
}

public void Connect()
{
if (!outsim.IsConnected)
{
outsim.Connect("127.0.0.1", 29999);
this.IsConnected = true;
}
}

void outsim_PacketReceived(object sender, OutSimEventArgs e)
{
this.pitch = e.Pitch;
}
}

If I run this program with LFS, all works perfect. But if I start this program without LFS and, I run LFS, it never launch outsim_PacketReceived, I must stop and run the program. I need do this automatically.

Thanks for your response!
outsim = new OutSim(1);

In this line you have only specified a 1 millisecond timeout, that's not long enough. You should specify a much greater timeout period such as a minute, or leave it blank so the connection never times out. You only need to call Connect once to tell it what host/port to listen for packets on, as I said above OutSim does not have a concept of being connected, it just listens for packets.

Anyway, this code works for me.

using System;
using InSimDotNet.Out;

class Program {
static void Main() {
new Program().mainLoop();
}

void mainLoop() {
LFS testfls = new LFS();

// Only need to call connect once.
testfls.Connect();

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

class LFS {
private OutSim outsim;
public float pitch = 0;

public LFS() {
// Leave timeout blank to stop program from ever timing out.
outsim = new OutSim();
outsim.PacketReceived += new EventHandler<OutSimEventArgs>(outsim_PacketReceived);
}

public void Connect() {
outsim.Connect("127.0.0.1", 30000);
}

void outsim_PacketReceived(object sender, OutSimEventArgs e) {
this.pitch = e.Pitch;

Console.WriteLine("OutSim packet received");
}
}

DarkTimes, you are right! With

outsim = new OutSim();

it's work perfect! I don't know what I was doing...

Thank you very much!.
I'm still working on InSim.NET 3.0 but I think I will delay its release for a little while. With the Visual Studio 11 Beta just released I plan to make InSim.NET 3 target .NET 4.5. This makes a lot of sense as .NET 4.5 has big improvements to the asynchronous programming model, that would simplify the socket code in InSim.NET a lot. It would also allow changes to improve the overall API of the library. The plan is for InSim.NET 3.0 to be the last version of the library (except for smallish updates), so it makes the most sense to target .NET 4.5 in order to future-proof the code as much as possible.

I don't know when .NET 4.5 will be officially released, but obviously you can download Visual Studio 11 Beta right now.
I've been messing around some more with C# 5.0 and I'm getting my head around how this whole async stuff works. It's not as 'magical' as it first appears, which of course, nothing really is. One thing that bugged me when first trying out the new async library was that the basic Socket class didn't support it, instead you had to create a TcpClient and then get a NetworkStream from it. This isn't a big deal of course, but I would also quite liked to have had the async features available on the socket itself.

After messing around with the library for a while and doing a bit of disassembly I found a few helpful classes and methods that allow you to implement your own async code. The first one was the Task.Factory.FromAsync method, that provides a helper function for turning a traditional asynchronous begin/end operation into a task, and it's easy to wire this up to the Socket.BeginConnect and Socket.EndConnect methods.

I created a little Socket.ConnectAsync extension method:


<?php 
public static class SocketExtensionMethods {
    public static 
Task ConnectAsync(this Socket socketstring hostint port) {
        return 
Task.Factory.FromAsync<stringint>(
            
socket.BeginConnect
            
socket.EndConnect
            
host
            
port
            
null);
    }
}
?>

This allows you to now await the socket connect method, which is nice.


<?php 
async void SocketStuff
() {
    
Socket socket = new Socket(SocketType.StreamProtocolType.Tcp);

    
// Connect to socket asynchronously.
    
await socket.ConnectAsync("127.0.0.1"29999);
}
?>

The FromAsync method is really cool, but it only appears to support up to three generic type arguments, which mean it can't be used for stuff like Socket.BeginSend or Socket.BeingReceive. After a bit more poking around I discovered the TaskCompletionSouce class, which allows you to build your own Task. This allowed me to create SendAsync and ReceiveAsync extension methods.


<?php 
public static class SocketExtensionMethods {
    public static 
Task<intSendAsync(this Socket socketbyte[] bufferint offsetint sizeSocketFlags socketFlags) {
        
TaskCompletionSource<inttaskCompletionSource = new TaskCompletionSource<int>();
        
socket.BeginSend(bufferoffsetsizesocketFlagsar => {
            try {
                
taskCompletionSource.SetResult(socket.EndSend(ar));
            }
            catch (
Exception ex) {
                
taskCompletionSource.SetException(ex);
            }
        }, 
null);
        return 
taskCompletionSource.Task;
    }

    public static 
Task<intReceiveAsync(this Socket socketbyte[] bufferint offsetint sizeSocketFlags socketFlags) {
        
TaskCompletionSource<inttaskCompletionSource = new TaskCompletionSource<int>();
        
socket.BeginReceive(bufferoffsetsizesocketFlagsar => {
            try {
                
taskCompletionSource.SetResult(socket.EndReceive(ar));
            }
            catch (
Exception ex) {
                
taskCompletionSource.SetException(ex);
            }
        }, 
null);
        return 
taskCompletionSource.Task;
    }
}
?>

This allows you to await both send and receive operations.


<?php 
async void SocketStuff
() {
    
Socket socket = new Socket(SocketType.StreamProtocolType.Tcp);

    
// Connect to socket asynchronously.
    
await socket.ConnectAsync("127.0.0.1"29999);

    
// Send data asynchronously.
    
byte[] sendBuffer GetBufferToSend();
    
await socket.SendAsync(sendBuffer0sendBuffer.LengthSocketFlags.None);
    
    
// Receive data asynchronously.
    
byte[] receiveBuffer = new byte[1024];
    
int recevied await socket.ReceiveAsync(receiveBuffer0receiveBuffer.LengthSocketFlags.None);
    if (
received 0) {
        
// Handle data etc..
    

}
?>

So yeah, it seems pretty easy to knock together your own asynchronous socket code that supports the new await keyword. I may well create extension methods for all the asynchronous socket stuff, as it's actually not that complicated. I must say I've been really impressed with C# 5.0 so far, these are really lovely features which are going to make writing async code so much simpler in the future.
Quote from DarkTimes :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.

I believe I've fixed this error. I have a new version of InSim.NET that includes this fix, as well as several code optimisations when sending messages. I'll try and release it as soon as I can.
I've uploaded InSim.NET 2.0.14 beta to CodePlex.

Changes:
  • Various improvements to InSim.Send() methods.
  • Fixed bug where OutSim and OutGauge IsConnected would throw an exception if no connection timeout was specified.
  • Unicode string encoding is now more strict (see above post).
There was a problem in previous versions where the InSim.Send(string) method would sometimes send an IS_MSX message packet instead of the smaller IS_MST. The logic has been updated so now the correct sized packet always gets sent. This can save bandwidth when sending large amounts of message packets.

In addition I also added a bunch of overloads for the InSim.Send(string) and InSim.Send(byte, byte, string) methods, to make passing a format string perform much better. For instance doing something like the following can perform faster than it did before.

// Send formatted string.
insim.Send("Hello, {0}", playerName);

Lastly, as mentioned above, the unicode string encoding has been updated to be more strict. This should alleviate some situations where InSim.NET would convert a unicode character to a close match instead of an exact match, for instance the Serbian character 'Ć' being interpreted as 'C' etc..

There may be some bugs, as I was messing around a lot with the string encoding code, so I've marked it as beta. Please let me know of any bugs or problems you have.

As always you can download InSim.NET from the CodePlex site.
I have been using InSim.NET for over a year now and I'm very happy with it I'm glad you are still on the ball and continue improving this library. Over the past few months I used the 2.0.12 version. I recently switched to 2.0.13 and everything seemed to work well. No major anomaly whatsoever (apart from a little concern I will mention below). 2.0.14 is a different story unfortunately...

concerning 2.0.14:
=============


2.0.14 hasn't been "plug & play" so far. For some reason LFS dedi shouts "InSim: password does not match your multiplayer admin password". I have not tested in debt yet but it is the first time I experience compatibility issues. All previous versions didn't require me to alter any of my codes. Could it be IS_ISI related? I will pursue my investigation and report back once I have more solid information.

concerning 2.0.12 & 2.0.13:
===================


I have spent some time fiddling with the IS_AXM packet for the past few months. When a packet is received with the ActionFlags.PMO_DEL_OBJECTS flag I noticed a small but noticable delay. It only occurs with this parameter. The delay didn't seem to be influenced by the amount of Object Information included in the packet. I have not yet found out a good way to benchmark this and am not 100% convinced it is related to the library. Again the delay is only noticable when you delete objects. It works flawlessly when you add objects.
Yes, you are correct about the issue with the password. There was a small bug that crept into the code for v2.0.14 that I have now fixed. I have uploaded a new version of 2.0.14 called InSim.NET 2.0.14b. Sorry about that!

I'm not sure what's going on with the IS_AXM packet, I will need to look into it and get back to you.

Edit: I've tested the AXM packet and I don't notice any delay when deleting packets. What sort of delay are we talking about? Is it a delay between you sending the request to delete the packet and the packet being deleted? Or is it a delay between when you delete an object in shift+u mode and the packet being received? Also are connected to a local copy of LFS when you notice the delay, or to a remote dedicated server?
Quote :There was a small bug that crept into the code for v2.0.14 that I have now fixed.

I confirm, a good thing it was an easy fix

Quote :What sort of delay are we talking about?

It's a small almost irrelevant delay. Around 100ms to make a wild guess.

Quote : Is it a delay between you sending the request to delete the packet and the packet being deleted? Or is it a delay between when you delete an object in shift+u mode and the packet being received?

The delay occurs when you send multiple IS_AXM Del requests one after another. The first Del request seems barely executed when the next one is sent. That is where the delay is noticable. It only happens when you spam Del requests (not using shift+U). I suspect my code might be to blame, it currently stores the Object Info in a List. The delay might be caused when a request is made to retrieve the stored Object Info (in order to delete the object) from the List.
And the delay is barely (if at all) noticable when you select and delete an object with shift + U using your mouse.

Quote : Also are connected to a local copy of LFS when you notice the delay, or to a remote dedicated server?

I only tested locally but will test it soon online. Hopefully I'm to blame. The process of storing, reading and retrieving Object Information from a List multiple times per second could be the cause?
Something like that could be the cause of it. InSim.NET does not start receiving the next packet until the packet-handler for the previous packet returns. This means if that if your packet-hanlder method takes a long time, it can delay the processing of the next InSim packet. For this reason you should try and keep your packet-handlers as simple as possible.

You can demonstrate this very simply by adding an artificial delay to a packet-handler.

void AutoXMulti(InSim insim, IS_AXM axm) {
// Sleep thread for two seconds.
System.Threading.Thread.Sleep(2000);
}

If you had a packet-handler like this then the next InSim packet, of any type, would not be processed for two seconds. The whole packet receive thread would actually be slept in this example. The same is true of any long running operation that happens inside a packet-handler.

The alternative would be for InSim.NET to start processing the next packet in the stream before calling the packet-handler, but that would introduce the (likely) risk of multiple packet-handlers being called at the same time, which would mean serious multi-threading issues to deal with, as race conditions and deadlocks could occur as those handlers tried to access the same resources in your code.

It would depend of course on what you're actually doing, 100ms seems quite a long time for normal list processing. Are you doing any database or IO stuff as well? You can use a Stopwatch to measure the execution speed of your packet-handler, place a start call at the beginning of the method and a stop call at the end, then output the elapsed time.

void AutoXMulti(InSim insim, IS_AXM axm) {
Stopwatch sw = new Stopwatch();
sw.Start();

// Your AXM code here...

sw.Stop();
Debug.WriteLine("AXM elapsed time: " + sw.Elapsed);
}

This will give you the raw execution time of the method, as all the actual packet processing by InSim.NET is finished by this point.
IS_AXM
======

Thanks for the suggestions. Testing with a Stopwatch gave me values well under 1 MilliSecond (between 100 to 1000 stopwatch ticks but I don't know how many NanoSeconds/MicroSeconds 1 stopwatch tick is) both for Add & Del. The issue must be elsewhere.

Is it a certainty that receiving IS_AXM packets does not take significantly more time than sending IS_AXM packets? There is a high probability that I'm doing something else wrong. Furthermore I noticed that I didn't setup the UCID when sending the IS_AXM packet. I haven't found out how to setup the UCID correctly yet. More testing will have to be done before I can narrow it down. At the moment it just seems faster to Add & Del objects repeatedly without using the IS_AXM receive event.

My explanations may be incomprehensible. You would understand the problem on sight if you try it out yourself on my server. If you want to we could meet for a few minutes on my server?

IS_CPP
=====

Concerning other packets, do you know an efficient way to force the shift+U view with the IS_CPP packet? I'm currently fiddling with it unsuccessfully.
Quote from sicotange :
My explanations may be incomprehensible. You would understand the problem on sight if you try it out yourself on my server. If you want to we could meet for a few minutes on my server?

Yeah sure, I could join your server for a few minutes. I see you're online now, I guess I can join.

Quote :IS_CPP
=====

Concerning other packets, do you know an efficient way to force the shift+U view with the IS_CPP packet? I'm currently fiddling with it unsuccessfully.

You can do this by setting the ISS_SHIFT_U flag for the Flags property.

insim.Send(new IS_CPP {
Flags = StateFlags.ISS_SHIFTU,
});

The user can still exit Shift+U mode, you could watch for the STA event and switch it back on, although it might be better to just respect the users decision.
I applied a "hybrid" solution concerning the IS_AXM receive events. I have alot more to test though, for example is their a significant performance difference if you don't set the ISF_AXM_LOAD flag etc.

IS_CPP remains a mystery to me. Perhaps I fail to setup the viewPLID correctly. Can you confirm you tested it successfully before?
You just set the flag to ISS_SHIFTU and LFS will switch to SHIFT+U mode.

From InSim.txt:

// The ISS state flags that can be set are :

// ISS_SHIFTU - in SHIFT+U mode
// ISS_SHIFTU_FOLLOW - FOLLOW view
// ISS_VIEW_OVERRIDE - override user view

// On receiving this packet, LFS will set up the camera to match the values in the packet,
// including switching into or out of SHIFT+U mode depending on the ISS_SHIFTU flag.

You can also set SHIFT+U mode by sending a key-press:

insim.Send(new IS_SCH {
CharB = 'U',
Flags = CharacterModifiers.SHIFT,
});

Edit: I realised now that you might be trying to use this on a dedi-server, which won't work. Switching to SHIFT+U mode only works if you're connected to a local copy of LFS.
I have this very basic question. When you go to the Visual Studio 11 download page, which download should I pick? (I told you it was very basic)
Quote from broken :I have this very basic question. When you go to the Visual Studio 11 download page, which download should I pick? (I told you it was very basic)

There is a simple download page here: http://www.microsoft.com/download/en/details.aspx?id=28975

I downloaded Visual Studio 11 Ultimate beta as an ISO. That way you can either burn it to disk or use a disk mounter like VirtualCloneDrive to install it. Alternatively you can download the web installer, which will download and install it automatically. Personally I prefer having an ISO as that way if there are problems with the install it's easy to reinstall it. I've not tried the Express versions.
Quote from DarkTimes :There is a simple download page here: http://www.microsoft.com/download/en/details.aspx?id=28975

I downloaded Visual Studio 11 Ultimate beta as an ISO. That way you can either burn it to disk or use a disk mounter like VirtualCloneDrive to install it. Alternatively you can download the web installer, which will download and install it automatically. Personally I prefer having an ISO as that way if there are problems with the install it's easy to reinstall it. I've not tried the Express versions.

Yeah I went for ultimate too, just after I posted the question, though I'm not sure what I downloaded. I guess a web installer. I just got really confused with those lots of buttons, so I went for what sounded the coolest to me - "ultimate".

Thanks though, and sorry for the pretty much pointless question.. I have my dumb moments.. pretty frequently..
Quote :Edit: I realised now that you might be trying to use this on a dedi-server, which won't work. Switching to SHIFT+U mode only works if you're connected to a local copy of LFS.

I knew I overlooked something

Did any of you guys experience stability issues with VS 11 beta (ultimate)? I had 3 rather random crashes after roughly 2 hours of use. Apart from these I must say I like VS11.
I have pushed the development version of InSim.NET 3.0 onto BitBucket, as after stalling for a while, the development is coming along quite nicely now. Still lots of work to do, things to fix and code to refactor, but I'm reasonably happy with it.

https://bitbucket.org/alexmcbride/insimdotnet

I'll do a write up of the changes soon, but here's a basic code example to show how the new API changes are working. It's important to note that this version of InSim.NET is not backwards compatible, it has lots of big breaking changes and won't work with code written for older versions of the library. Currently the library supports .NET 4.0 and .NET 4.5, but because of changes to the way packets are created it no longer supports .NET 3.5.


<?php 
// InSim.NET 3.0 Example Code

using System;
using System.Text;
using System.Threading;
using InSimDotNet;
using InSimDotNet.Packets;

namespace 
InSimTest {
    class 
Program {
        static 
void Main() {
            new 
Program().Run();
        }

        
void Run() {
            
// Set console to unicode encoding (you also need to set 
            // the console to use a unicode font in Windows).
            
Console.OutputEncoding = new UTF8Encoding();

            
// Create new InSim object.
            
InSimClient client = new InSimClient();

            
// Hook up packet events.
            
client.Version += client_Version;
            
client.MessageOut += client_MessageOut;

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

            
// Send message packet to LFS.
            
client.Send(new MessageTypePacket {
                
Message "Hello, InSim!"
            
});

            
// Stop program from exiting while LFS is connected.
            
while (client.IsConnected) {
                
Thread.Sleep(100);
            }
        }

        
void client_Version(object senderPacketEventArgs<VersionPackete) {
            
// Write version info to the console.
            
Console.WriteLine(
                
"Version: {0}{1} InSim: {2}",
                
e.Packet.Product,
                
e.Packet.Version,
                
e.Packet.InSimVersion);
        }

        
void client_MessageOut(object senderPacketEventArgs<MessageOutPackete) {
            
// Write any messages typed by users to the console.
            
if (e.Packet.UserType == UserType.User) {
                
Console.WriteLine("Message: {0}"e.Packet.Message);
            }
        }
    }
}
?>

I'd urge anyone trying it to pay attention to the API and intellisense in Visual Studio, as it's been designed to help you adapt from the old version as seamlessly as possible.

As it's not even a beta version yet, it will have one or three bugs, also the API may still change wildly before it's finished.
I've been messing around with Entity Framework Code First for .NET and it's really useful for making little databases, such as you would use in a InSim program. I figured I'd do a quick tutorial on using it, as it's really very simple.

First of all boot up Visual Studio 2010 and create a new C# Console Application project, call it what you like. Before we can use the EntityFramework we'll need to include the assemblies in our project, but this is easy using the .NET package manager, called NuGet. In Visual Studio go to View > Other Windows > Package Manager Console and in the console window type the following command then hit enter.

Install-Package EntityFramework

This should download and install the EntityFramework for you automatically. Now we need to create a simple model to store in the database, which for the purposes of this example will represent a simple cruise server. Here is the code for the model


<?php 
public class User {
    public 
int ID getset; }
    public 
string UserName getset; }
    public 
string PlayerName getset; }
    public 
int Cash getset; }
    public 
virtual List<CarCars getset; }
}

public class 
Car {
    public 
int ID getset; }
    public 
int UserID getset; }
    public 
string CarName getset; }
    public 
User User getset; }
}
?>

We create a User object and a Car object, that will have a one-to-many relationship. One user will have many cars, one car will have one user. As the EntityFramework follows a convention over configuration coding style, the relationships between the keys will be setup for us automatically. We will be able to access a user's cars through the User.Cars property, and access a car's user through its Car.User property.

Next we need to create a DbContext for our model, which will represent our connection with the database, and also tell the EntityFramework which model classes to use. This is extremely simple code.


<?php 
public class CruiseContext DbContext {
    public 
DbSet<UserUsers getset; }
    public 
DbSet<CarCars getset; }
}
?>

Finally we need to tell the EntityFramework which database we want to use to store our data. By default it uses a SQLServer Express instance to store it, but I'd rather use SQLServer Compact instead, as it's simpler. SQLServer Compact is a simple file-based database, similar in nature to SQLite, that requires no installation or configuration. It can store up to 4GB of data if I remember correctly, so it's very useful for this kind of thing. Anyway, open you projects app.config file and change to contents to look like this:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<connectionStrings>
<add name="CruiseContext"
providerName="System.Data.SqlServerCe.4.0"
connectionString="Data Source=CruiseDB.sdf"/>
</connectionStrings>
</configuration>

The important bit is the connectionStrings element, which we use to define which database our 'CruiseContext' is to use. The 'System.Data.SqlServerCe.4.0' bit tells it to use a SQLServer Compact 4.0 database, and 'CruiseDB.sdf' is used to specify the actual name of the database file where we want to store our data. If this file does not exist then the EntityFramework will create it for us. If we delete it, it will recreate it.

Now all that's left is to write some code that actually access our database and saves and retrieves some data in order to test (prove) that it's working.


<?php 
class Program {
    static 
void Main() {
        
// Save some data to the database.
        
SaveUserToDatabase();

        
// Read the data back out of the database.
        
RetrieveUserFromDatabase();

        
Console.ReadLine();
    }

    private static 
void SaveUserToDatabase() {
        
// Create database connection.
        
CruiseContext db = new CruiseContext();

        
// Create a new user.
        
User user = new User {
            
UserName "DarkTimes",
            
PlayerName "Alex",
            
Cash 1000,
            
Cars = new List<Car>(), // empty car list
        
};

        
// Add some cars.
        
user.Cars.Add(new Car CarName "UF1" });
        
user.Cars.Add(new Car CarName "XFG" });
        
user.Cars.Add(new Car CarName "XRG" });

        
// Add the user to the database.
        
db.Users.Add(user);

        
// Save the changes to the database.
        
db.SaveChanges();
    }

    private static 
void RetrieveUserFromDatabase() {
        
// Create new database connection.
        
CruiseContext db = new CruiseContext();

        
// Query the database for the user.
        
User user = (from u in db.Users
                     where u
.UserName == "DarkTimes"
                     
select u).Single();

        
// Write the user info to the console.
        
Console.WriteLine("UserName: {0}"user.UserName);
        
Console.WriteLine("PlayerName: {0}"user.PlayerName);
        
Console.WriteLine("Cash: {0}"user.Cash);
        
Console.WriteLine("Cars:");

        foreach (
Car car in user.Cars) {
            
Console.WriteLine(car.CarName);
        }
    }
}
?>

It might take a few moments for the program to run the first time you start it, as it needs to create the database and all the tables etc.. but after that the performance should be fine.

Well, it looks like more work than it really is the first time you see it, once you've tried it, however, you'll see that it makes it very simple and easy to create a database for your InSim app. I've found it very useful.

Here is the complete project to download.
Attached files
CruiseContextExample.zip - 1.1 MB - 438 views
This is a rather compelling database "model". I might make it compliant with my application
I have created a NuGet package for InSimDotNet, which makes it very easy to download and install the library in your Visual Studio project. Here are the steps to use it.
  • Create a new Visual Studio project
  • Go to View > Other Windows > Package Manager Console
  • In the console type 'Install-Package InSimDotNet' then hit enter
  • That's it!
Visual Studio will now download and install the library automatically!

If you are using Visual Studio 11 Beta you can also use the option Project > Manage NuGet Packages, which will allow you to use the new Package Manager UI. Once the manager has opened, just click Online tab and search for 'InSimDotNet', finally click install.

This is the first NuGet package I've created, so let me know if you have any problems.

I created a screenshot with the Package Manager Console at the bottom and the Package Manager UI in the centre, to help people show what I'm talking about.
Attached images
InSimDotNetNuGet.png
Has anyone had a chance to checkout the InSim.NET 3.0 stuff I posted a week or so ago? It features a quite radical (for the most part) redesign of the core API, so I'd appreciate any feedback, especially bad feedback, from people who've tried it.

You can find the development repository on my BitBucket account (it's like GitHub except for Mercurial source control). You can either download the source as a .zip file, or clone the repository with the command:

hg clone https://bitbucket.org/alexmcbride/insimdotnet

You can find an excellent tutorial on using Mercurial at hginit.com. Mercurial is like Git, except simpler to use and much more Windows friendly. You don't have to use the source control though, just download the zip by clicking the 'get source' link on the far-right.

If you don't understand the new InSim.NET API, let me know, and I'll post some more example code. I am hopeful, however, that you should be able to figure out how it works purely by looking at the intellisense data inside Visual Studio, as that's how I tried to design it.

Anyway, let me know what you think!

Edit: For extra credit I've also made public my InSimSniffer WPF port on BitBucket. It's a version of InSimSniffer I wrote a few weeks ago, that ports the UI to WPF using the MVVM design pattern. I wrote it in a day and a bit, so the code isn't super-awesome. I didn't see the point in releasing it as it doesn't add any extra functionality over the original app, although I might in the future. Still, the presence of such code might interest a few other .NET developers on here.

FGED GREDG RDFGDR GSFDG