The online racing simulator
#51 - jur
Looked through the sample code just out of interest and noticed one possible performance issue. Using reflection each time a packet is received doesn't look like a very good idea. I might be wrong though, please correct me in that case.
I'm not sure what you mean, what code are you specifically referring to?
I've been messing around with getting Spark to work as a WCF web service, so you can run it from a web site. I've not written anything like this before, so it's a bit of a learning curve, but I'm making slow progress. With Spark as a web service you could build Silverlight applications and lots of other things. Happily it seems that Spark is flexible enough that it won't require any changes to the core library, all I need to do is to create a WCF web service that relays the InSim data to a client, and then create a new Spark.ISocket derived class that, instead of wrapping a TCP socket, wraps the web service EndPoint instead. Then it will be easy to create Flash-style InSim apps using Silverlight and run Spark from an ASP.NET web site.
#54 - jur

static void insim_PacketReceived(object sender, PacketEventArgs e)
{
// Use reflection to get the packet properties.
var properties = e.Packet.GetType().GetProperties();

// Print out each packet property and its value.
foreach (var property in properties)
{
Console.WriteLine("{0}: {1}", property.Name, property.GetValue(e.Packet, null));
}

// Blank line.
Console.WriteLine();
}

I was referring to this code, where you use reflection to get the properties of a packet. Reflection is a bit slow and it's fine when there are not many calls. But (if I remember correctly) minimum InSim packets per second is 3, so it might be a problem. GetType is probably all right, but GetProperties (and maybe some others) is likely to be slow.
Yeah, I get you. The reflection code is really only useful for debugging and diagnostic purposes, it probably shouldn't be used (or needed) in production code. That being said, it's not that slow, InSimSniffer uses this type of reflection and it runs pretty fast.
Quote from jur :But (if I remember correctly) minimum InSim packets per second is 3, so it might be a problem.

Actually it would be quite fun to add a packets per second readout to InSimSniffer, as I have no idea if your figure is correct.

Edit: With everything on max I got up to 40 packets per second before InSimSniffer caused LFS to throw a WSAEWOULDBLOCK error (known issue with LFS in TCP mode), but that was a full 32 player race with the MCI interval at 50ms.

Without MCI packets turned on the average is about 3-4 packets per second.
Quote from DarkTimes :With everything on max I got up to 40 packets per second before InSimSniffer caused LFS to throw a WSAEWOULDBLOCK error (known issue with LFS in TCP mode)

Really! I never knew about this problem! It's the only outstanding bug within the InSim system?
#58 - jur
Quote from DarkTimes :Actually it would be quite fun to add a packets per second readout to InSimSniffer, as I have no idea if your figure is correct.

Nah, my figure is wrong. I just figured out, that I remembered the LFS pps, not InSim.
Any way, this library looks good, great job!
Quote from jur :Nah, my figure is wrong. I just figured out, that I remembered the LFS pps, not InSim.
Any way, this library looks good, great job!

LFS PPS != InSim PPS.
#60 - PoVo
Hey, so far Spark has been great to me.

But, i've come accross a problem.

I cannot sent special character messages.

E.g I send a message:


<?php 
_insim
.Send("/msg š " NCN.PName);
?>

Now the output in LFS is this:

? [Ls?C]Povo

Although my nickname should be : [Ls·C]Povo

So essentially the result should be "š [Ls·C]Povo".

Is there any fix to this?
Yes, Spark does not understand about different encodings, so this is an issue with the library. I was thinking about releasing a stand-alone LFS string library, which is why Spark does not include any encoding support, but while this was a good idea, I haven't been able to find the energy to finish it. This means I will need to add encoding to Spark, but I'm not sure when that will be.
#62 - PoVo
Ah what a pity, I really wanted to use this system. Is there any easy way of adding the encoding?
I will release a version with encoding support tomorrow. While adding encoding support isn't hard in itself, it's difficult to explain how to do it in a forum post.
#64 - PoVo
Quote from DarkTimes :I will release a version with encoding support tomorrow. While adding encoding support isn't hard in itself, it's difficult to explain how to do it in a forum post.

Great! Thank you
-
(DarkTimes) DELETED by DarkTimes
-
(DarkTimes) DELETED by DarkTimes
I have ported my cruise server example from Python over to C#. It is a very simple cruise server, where you drive around earning cash, which you can then spend on buying and selling cars.

This is not intended to be the worlds best cruise server, it's designed as an example of how to carry out lots of different InSim related tasks. Here is a rough list of the topics covered, in no particular order and from the top of my head.
  • Tracking users and players on a host
  • Persisting users between sessions using a SQL Compact database
  • Displaying user information using on-screen buttons
  • Handling commands of differing complexity (!buy, !sell, !give etc..)
  • Tracking the distance a user has travelled
  • Using timers to trigger events
  • Using LINQ to query user data
I wrote the code this morning, it isn't perfect and I've not had time to test it thoroughly, but it seems to work OK.

Anyway, you can download the project below.
Attached files
SparkCruise.zip - 135.4 KB - 1330 views
#66 - PoVo
Great cruise example! But I noticed a bug in the system.

When you enter !garage

I get this information :

| Garage:
| SparkCruise.Car: $3000

I don't think this is supposed to happen, and as far as I understand the code, it should write every car you own, and the name of it?

Anyway, not that I need it to be fixed, but I was just letting you know
Yes thanks, you are correct!

This bug has arisen because of the change to using a database to store user info. In the previous XML version cars were stored as a collection of strings, but to work with the database I had to change them to a collection of Car objects. I did not catch the bug as it caused no compilation errors, the C# compiler decided to call the Car objects ToString() method instead, which is why it printed SparkCruise.Car.

To fix the bug you can update the CommandGarage method to this:

private void CommandGarage(User user, string[] args)
{
if (user.Cars.Any())
{
MessageTo(user, "Garage:");
foreach (var car in user.Cars)
{
var price = Dealer.GetCarPrice(car.Name);
MessageTo(user, "{0}: ${1}", car.Name, price);
}
}
else
{
MessageTo(user, "You do not own any cars");
}
}

I've uploaded a fixed version.
-
(DarkTimes) DELETED by DarkTimes
I had a bit of a fiddle and uploaded another new version with some more features.
  • Added bonus and health
  • Made the onscreen display look cooler
  • Added !top command which shows a list of the top ten users
  • Changed !give to !send, and added new !give <username> <car> command
  • Added !stats <username> command, which will show you another users stats
  • Improved !showoff command output
I think I need to refactor the commands next, it's becoming a bit of an if-fest, I thought it was more readable at first, but now obviously I was wrong.
umm this is nice coding i try it but some problems...
-
(DarkTimes) DELETED by DarkTimes
-
(DarkTimes) DELETED by DarkTimes
What problems are you having?
I have uploaded a new version of the cruise example with much more logical code for the !sell, !buy, !send and !give commands.

Oh I also fixed a crash caused when you quit the server after having sold or given away a car.
Quote from DarkTimes :Yes, Spark does not understand about different encodings, so this is an issue with the library. I was thinking about releasing a stand-alone LFS string library, which is why Spark does not include any encoding support, but while this was a good idea, I haven't been able to find the energy to finish it. This means I will need to add encoding to Spark, but I'm not sure when that will be.

I think a reasonably default for encoding is default

PacketReader.cs:
public string ReadString(int count)
{
_position += count;
return Encoding.Default.GetString(_data, _position - count, count).TrimEnd(char.MinValue);
}



So Encoding.Default instead of ASCIIEncoding.ASCII.
This should do the job, since the client InSim apps mostly run on the same system as the InSim server.
Of course this is just a temp hack.
Quote from pezia :I think a reasonably default for encoding is default

So Encoding.Default instead of ASCIIEncoding.ASCII.
This should do the job, since the client InSim apps mostly run on the same system as the InSim server.
Of course this is just a temp hack.

Yeah, that might be worth a try in the mean time. I've updated the development version.

Edit: Seems cool, nothing has exploded yet.
-
(DarkTimes) DELETED by DarkTimes
-
(DarkTimes) DELETED by DarkTimes
Uploaded Spark 1.0.8 to the first post.

Changes
  • Fixed bug where host and port were missing from ConnectedEventArgs when the InSim.Connected event was raised by calling InSim.EndConnect.
  • Changed string encoding to use Encoding.Default (stopgap while I test my own string encoding code).
  • Added ParseCommand and TryParseCommand methods to StringHelper.
  • Added InSim.Unbind and InSim.IsBound methods.
  • Added MathHelper.Intersects and MathHelper.Contains methods.
  • Added more missing comments to packets (down to only 113 warnings of missing XML!)
  • Added optimizations to packet receive code.
  • Added protected BuildAllPackets property to InSim class, which when set to true will cause OnPacketReceived to be called on every packet.
Hello,

I started to learn C# language, so I am quite a beginnger with this, although I have some experience with PHP. I am having some problems with displaying buttons via Spark. It does not display any buttons anywhere. Everything else seems to work fine.

Here is my code:
using System;
using Spark;
using Spark.Packets;

namespace FlameSim
{
class Program
{
static void Main(string[] args)
{
// Create InSim object.
using (var insim = new InSim())
{
const string INSIM_NAME = "FlameSim";
const string INSIM_AUTHOR = "Martin Kapal";
const string SERVER_IP = "127.0.0.1";
const int SERVER_PORT = 30000;
const string ADMIN_PASS = "xxx";

insim.Connect(SERVER_IP, SERVER_PORT);

insim.Send(new IS_ISI { IName = INSIM_NAME, Admin = ADMIN_PASS });

insim.Send("/msg ^EConnected : ^7" + INSIM_NAME);
insim.Send("/msg ^EAuthor : ^7" + INSIM_AUTHOR);
[COLOR="Blue"]
[B]insim.Send(new IS_BTN
{
ReqI = 255,
UCID = 255,
ClickID = 2,
BStyle = ButtonStyles.ISB_DARK | ButtonStyles.ISB_LEFT,
T = 8,
L = 8,
W = 20,
H = 4,
Text = "Test",
});
[/B][/COLOR]
// Stop program from exiting.
insim.Run();
}
}
}
}

-
(DarkTimes) DELETED by DarkTimes

FGED GREDG RDFGDR GSFDG