The online racing simulator
Quote from sicotange :I have a note somewhere about this. I will get back to you once I can give you info on how to reproduce it easily.

OK - thanks! It's possible I've looked at this before and don't remember, but if you could find some steps to reproduce the error that would be great.

Quote :For example, you have a panel of 200 buttons. All 47 players of a full server should be shown this panel at the same time. I'm looking for the best & fastest way to do this. Same for buttons who get updated often (text updates every 100ms of several buttons for example). Basically a way to queue packets, making batches and send them at appropriate intervals. You master this stuff. I don't have enough knowledge about sockets & netcode to implement this well.

This may be a silly question, but what's the problem that occurs when you send all those buttons to all those players? Is it that there is an error, does the connection close, does LFS grumble, or is it just really slow? I know we may have talked about this before, but I don't work on the library often and so will forget things. The main problem is that I don't have a server with 47 players to test it on, I just test on my own machine, and in that case I can send 239 buttons each with 240 characters of text over and over again and it works fine.

Quote :Thanks for the library updates (EventHelper & 0.6K13). I will test EventHelper once I'm done updating my program with IS_UCO & IS_JRR.

I was going to post about the EventHelper, it's an experimental thing I knocked together in a short while. Basically, I thought the best way to deal with multiple hosts was just to be able to think of them as one host. So EventHelper is a wrapper that wraps a collection of InSim objects, when you bind a packet or send a packet, it loops through the collection of hosts and performs the operation on all of them. Here is some code to demonstrate:


<?php 
void Test
() {
    var 
hosts = new EventHelper();

    
// Add the settings for each host you want to connect to
    
hosts.AddInSim(new InSimSettings {
        
// host 1 settings
    
});
    
hosts.AddInSim(new InSimSettings {
        
// host 2 settings
    
});
    
hosts.AddInSim(new InSimSettings {
        
// host 3 settings
    
});

    
// Bind packets and events as normal
    
hosts.InSimError += hosts_InSimError;

    
// when you bind a packet or event it's bound to all the InSim objects
    
hosts.Bind<IS_STA>(StateChanged);

    
// Initialize all the hosts you added earlier.
    
hosts.Initialize();

    
// You can send a packet to all hosts.
    
hosts.Send(new IS_TINY ReqI 1SubT TinyType.TINY_SST });
}

void hosts_InSimError(object senderInSimErrorEventArgs e) {
    
// the sender object is the host that raised the event.
    
InSim insim = (InSim)sender;
}

void StateChanged(InSim insimIS_STA packet) {
    
// the insim parameter is the host that received the packet, so you can use it to send a packet back
    
insim.Send("got yer state"); 
}
?>

I hope that makes sense. As I say I put it together this morning, it just a rough idea right now. I may well change the name to HostsHelper, or something else. I don't think EventHelper is very descriptive.
I think I might have just figured out a very large bug in the string encoding class that's beset InSim.NET for a long time. It is the bug that was reported in this post a few months ago. It's hard to say right now but this might be the root cause of a lot of the string encoding problems people have been experiencing. Whatever the results I think I've definitely fixed that bug that I linked. I've not uploaded the fix yet as I'll need to rewrite my hacky fix into nice neat efficient code. However, I'm cautiously optimistic that I've taken a big step forward.
Yeah, there was a patch I made ages ago which turned out to be quite wrong. Sorry. I'm not using InSim.NET now but I modified the current library I use to work satisfactorily without errors.

There's also a problem in that LFS to unicode is not lossless: different LFS characters can resolve to the same unicode codepoint, and so converting back from unicode to LFS can result in a different string and different glyphs.
I know about the issue with the string encoding not being lossless. The bug I have fixed was one where sometimes stray language tags could sneak in to the output and that would cause strings to be garbled in LFS. The solution was to make sure there were no existing tags in the string before Insim.NET started to convert it.

I've been thinking about the string stuff this morning and I may have had an idea. Up until now I've been converting the strings to unicode and removing the language tags (^C, ^J etc..). But what if I just left those in? That way when concerting back to LFS strings I could use those as hints for which codepage to use.

For instance if you had this unicode string:

"^Ltesting testing ^J捨捦べ 裃壎 ず愦ひ嶥鄥"

It could see that the Japanese codepage is being suggested, so it will look for the codepoint in that codepage first, if it didn't find it then it would search the rest.

The only drawback is that any program that displayed strings in its own UI would need to remove language tags before displaying them, however I could just add a new StringHelper.StripTags(string) method.

I might have a go at implementing this today.
OK - I have rewritten the LfsEncoding class. It still converts the LFS encoded string to unicode, but it also now leaves the language tags intact. Then when converting from unicode back into LFS strings it tries first to use the encoding specified in the tags, only when it doesn't find the codepoint in that encoding does it look up its own.

I've been messing around with this today and I think it's a much better solution than how it was handled before, which was difficult to understand and the root of many bugs. The string encoding stuff is now very simplified, it converts the strings to unicode but it tries to leave everything else untouched.

Because of this I have reworked the StringHelper class to add more stuff.
  • StringHelper.StripColors(string) - removes colour codes from a string
  • StringHelper.StripLanguage(string) - remove language codes from a string
  • StringHelper.Escape(string) - Escapes all LFS special characters (e.g. ^, |, ? etc..)
  • StringHelper.Unescape(string) - Unescapes the LFS special characters (e.g. ^v, ^q etc..)
  • StringHelper.Strip(string) - Strips colour and language tags, and also unescapes the string. This is what you would use if you were going to display the string in your own UI.
All of this code is freshly written, there was a lot to change, and almost certainly it will have bugs.

This quite a big change to the library. For now all you need to know is that InSim.NET no longer tries to hide language tags (^L, ^J etc..) from you. These will appear in strings sent from LFS but also you can use them to hint to InSim.NET what the correct encoding for a string is.
Hello, does anyone know why i have this error ?
Quote :This may be a silly question, but what's the problem that occurs when you send all those buttons to all those players? Is it that there is an error, does the connection close, does LFS grumble, or is it just really slow? I know we may have talked about this before, but I don't work on the library often and so will forget things. The main problem is that I don't have a server with 47 players to test it on, I just test on my own machine, and in that case I can send 239 buttons each with 240 characters of text over and over again and it works fine.

I can actually reproduce it easily. If I send 200 buttons continuously to several players online this is the result after less than a minute:
Quote :
07/02/2016 21:19:29 System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.IO.Stream.<BeginEndReadAsync>b__d(Stream stream, ReadWriteParameters args, AsyncCallback callback, Object state)
at System.Threading.Tasks.TaskFactory`1.FromAsyncTrim[TInstance,TArgs](TInstance thisRef, TArgs args, Func`5 beginMethod, Func`3 endMethod)
at System.IO.Stream.BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count)
at InSimDotNet.TcpSocket.<ReceiveAsync>d__50.MoveNext()

It seems to slow down over time and then fail eventually.

Ignore the time of the logs (I did several tests) but this is what LFS dedi reports near the crash:

Quote :Feb 07 21:28:13 TCP ERROR : INSIM LIMIT
Feb 07 21:28:13 INSIM ERROR : INSIM LIMIT
Feb 07 21:28:13 TCP ERROR : INSIM LIMIT
Feb 07 21:28:13 INSIM ERROR : WOULDBLOCK
Feb 07 21:28:13 TCP ERROR : INSIM LIMIT
Feb 07 21:28:13 INSIM ERROR : INSIM LIMIT
Feb 07 21:28:13 TCP ERROR : INSIM LIMIT
Feb 07 21:28:13 FATAL INSIM ERROR : BUFFER SIZE
Feb 07 21:28:13 InSim closed : ClaViCo

Quote :All of this code is freshly written, there was a lot to change, and almost certainly it will have bugs.

This quite a big change to the library. For now all you need to know is that InSim.NET no longer tries to hide language tags (^L, ^J etc..) from you. These will appear in strings sent from LFS but also you can use them to hint to InSim.NET what the correct encoding for a string is.

I hate to bring you the bad news, I hope it is an easy fix (?) (see attachment).

Quote :public const string EXIT_BUTTON_RED = "^1^S¡Á"; //NOT OK
public const string ARROW_UP = "^H¡¶"; //NOT OK
public const string ARROW_DOWN = "^H¡¿"; //NOT OK
public const string ARROW_LEFT = "‹"; //OK displays correctly
public const string ARROW_RIGHT = "›"; //OK displays correctly

The strings above give the following output (EXIT_BUTTON_RED should have been a red cross in upper right corner):
Attached images
insim.net encoding.jpg
OK - thanks. I'll look into all these issues.
Quote from sicotange :I hate to bring you the bad news, I hope it is an easy fix (?) (see attachment).

The strings above give the following output (EXIT_BUTTON_RED should have been a red cross in upper right corner):

OK - I have figured this out. I've only looked at the first one but the others are the same.

The reason you're seeing the wrong text is because you're actually using a bit of a weird hack to get the Chinese multiplication symbol × to show. I will explain that hack in detail below, but for now you should remember that InSim.NET uses unicode to represent strings. Then when you send packets to LFS the library converts the unicode into a format that LFS can understand.

The solution then is to just use the actual unicode versions of the characters that you want to send, so to display that Chinese multiplication symbol you would just send that character:

<?php 
public const string EXIT_BUTTON_RED "^1^S×";
?>

Or you can even specify its unicode codepoint precisely.

<?php 
public const string EXIT_BUTTON_RED "^1^S\u00D7";
?>

Now I will explain the reason that this hack sort of worked. If you don't know much about character encodings and unicode then read this first.

The string ¡Á that you were sending is made up of two characters. At first this confused me, why would you be sending two seemingly random characters and expecting to get one Simplifed Chinese one? Of course Simplfied Chinese is a DBCS (double byte character set), each character above 127 is represented by two bytes, a lead byte that defines a page within that codepage and a trailing byte that defines the specific character.

I looked up the byte values for the two ASCII characters ¡Á and they came to 0xA1 and 0xC0 respectively. I then looked up the those bytes in the Simplified Chinese charset (cp936). So if you take 0xA1 as the lead byte it takes you to this page, then if you lookup 0xC0 you'll see it takes you to the unicode codepoint \u00D7, which is the Chinese multiplication symbol.

So basically by putting in the ASCII chars ¡Á and forcing the codepage to Simplified Chinese you were able to display the character ×.

And that's why that worked. But you don't need to do that, just use unicode.

Edit: OK - just to help you out these are the three unicode characters you're using.
  • \u00D7
  • \u25B2
  • \u25BC
Quote from DarkTimes :The IS_CON packet doesn't contain the player name, you need to watch for the IS_CPR (Connection / Player Rename) packet and then update the player's name in your list of active players.

Really I do not know how to do that. You could give an example, please?
Firstly, thanks for the information. Granted at the moment my program doesn't deal with unicode. It is a mistake but it is mainly because I could happily throw any string at InSim.NET without it complaining or give distorted results.

Quote :Edit: OK - just to help you out these are the three unicode characters you're using.
\u00D7
\u25B2
\u25BC

Your quick fix gave semi-distorted results (see attachment). The red cross is fine but those arrows now have an unwanted dot behind them. Could it be related to the issue PeterN reported: https://www.lfs.net/forum/post/1901919#post1901919


Secondly, all InSim.NET updates (in sync with Scawen's patches, thanks for that) went fine until the last one concerning 0.6K18 & 0.6K19. I'm talking about the IS_AXM updates. I had to fix some things with PMOFlags (cast enum to byte and vice versa) but the recent implementations quoted below don't seem to work. Am I missing something? Could you check please before I report it in the incompatible test patch thread. I have a vague suspicion it is InSim.NET related.

Quote :Changes from 0.6K17 to 0.6K18 :

InSim :

Added TINY_SEL to request an IS_AXM with layout editor selection
New IS_AXM option PMO_SELECTION to set the current editor selection

Attached images
lfs_00000004.jpg
Sorry about the missing PMOFlags cast, I updated the code quickly last night, I forgot about that bit.

That text issue does look like the bug PeterN is describing. I don't see those dots on my LFS. I attached a screenshot with the result of sending a button with those characters to my local LFS instance. I tried messing with the language and font selection but I couldn't reproduce it.

Quote :Changes from 0.6K17 to 0.6K18 :

InSim :

Added TINY_SEL to request an IS_AXM with layout editor selection
New IS_AXM option PMO_SELECTION to set the current editor selection

I'll look into it this evening.
Attached images
unicode_lfs.png
OK - I've looked into those two options and they seem to work fine for me. I can send a TINY_SEL and LFS replies with a IS_AXM containing only the objects that are currently selected. I can send a IS_AXM with PMO_SELECTION set and it will select the specified objects.

Exactly what issue are you having?
Quote :I can send a IS_AXM with PMO_SELECTION set and it will select the specified objects.

Sorry, I wasted your time. This does work well (apart from 1 anomaly I will report). I didn't think things through and thought it would work on a host (without UCID "setable" it should have been obvious it isn't possible Face -> palm so LFS dedi reported "TINY_SEL - not for dedicated host".

Small typo:


Quote :public enum ActionFlags {
/// <summary>
/// Sent by the layout loading system only.
/// </summary>
PMO_LOADING_FILE,

/// <summary>
/// Adding objects (from InSim or editor).
/// </summary>
PMO_ADD_OBJECTS,

/// <summary>
/// Delete objects (from InSim or editor).
/// </summary>
PMO_DEL_OBJECTS,

/// <summary>
/// Clear all objects (NumO must be zero).
/// </summary>
PMO_CLEAR_ALL,

/// <summary>
/// A reply to a TINY_AXM request.
/// </summary>
PMO_TINY_AXM,

/// <summary>
/// A reply to a TINY_SELL request.
/// </summary>
PMIO_TINY_SEL,

/// <summary>
/// Set the current editor selection.
/// </summary>
PMO_SELECTION,
}

Hi, bro Insim.Net library sample source code cruise or drift insim share ?
-
(DarkTimes) DELETED by DarkTimes
I have decided, along with others on this forum, to stop responding to requests from demo users. People without an account who actually need to email me will be able to figure out how. From now on I will only answer support requests from people who have an S1 license or higher.
I think that's a good decision.

Sico, how does that animated gate work? Is that a new kind of feature in these test patches?

I really need to check out the new packages and maybe revive LFSSumo... I think a lot of those packages will come in handy!
Quote :Sico, how does that animated gate work? Is that a new kind of feature in these test patches?

These are just selections of autocross objects opened/closed by the new InSim checkpoints.

Quoting GitHub:
Quote :Updated for 6K20, added IS_OCO packet and associated enums.

DarkTimes, I made an account on GitHub. I haven't looked into it enough yet to help but I'm tracking down an IS_OCO bug. I can make track start lights work although there seems to be an issue with BulbInfo. On the other hand setting the movable lights (autocross object: AXO_START_LIGHTS (index 149)) won't work at all.
OK - I fixed the BulbInfo issue. I can change the main start lights, I'll need to look into the other layout stuff.

This packet will set the main start lights to red for instance.

insim.Send(new IS_OCO {
Data = BulbInfo.Red1,
Index = IS_OCO.OCO_INDEX_MAIN,
OCOAction = OCOAction.OCO_LIGHTS_SET,
});

I still can't make it work properly.
I can change the main start lights but not the AutoX ones. I don't know if I'm doing something wrong. I set the data bits correctly, I set index to AXM_START_LIGHTS, I set the action to OCO_SET_LIGHTS and the identifier to the correct one for my start light object. But I can't get it to work.
Yes, I read that, that's not the problem.
By the way, any chance on implementing IS_TTC tonight? If not I might attempt it, I want to have a version ready for tomorrow because I might be away this weekend.

FGED GREDG RDFGDR GSFDG