I'm using a LGPL library. I think that allows me to choose any license for my application, even one not GPL compatible. I think I'll be going with the MIT license.
I need to do some tasks before releasing it though:
Translate the code into English (var names, etc.)
Add comentaries so it's easy to follow.
Add license text and notices to the code and stuff like that.
I have made this "project" as a side job and I think I'll be releasing it tomorrow as a tutorial on InSim programming with C. It doesn't generate CSV files though.
I first made this as a feature for another bigger insim app, but thought it would be nice to have something like this as a standalone application that can be running all the time on a dedi server.
I hope some people will volunteer to do a little beta testing. And I hope someone takes a look at the code and corrects the many mistakes I must have done
Thanks for the info. I already have it working with Pthreads-w32 mentioned by Karl in the first reply. It's working nice but I don't like much that I need a dll for it to work. That's Windows for you
I wonder why it only happens to arrechee then. And double up-shift... how can you say that's a side effect of macro clutch? Dude, don't try to make up shit. Believe it or not there are guys FASTER than you (and quite a bunch, tbh).
This is a small quote extracted from a feature at f1.com website. These are words from Hirohide Hamashima, Bridgestone’s Director of Motorsport Tyre Development:
In some ways the behaviour we have in LFS is the opposite to what thery're saying here. What do you think?
I don't give a damn about the people who use the macro, which I don't like, but I also don't like people accusing someone without any evidence and just saying "take a look at the analyzer".
Donwload and play arrechee's WR for this combo (AS1 - UF1). You can see how many times there's a miss when he up-shifts. It was some weeks ago. I asked him directly and he told me that his old sidewinder (or whatever it is) wheel had the up-shift paddle a little broken and some times it won't make contact and the gear just won't kick in, so he has to keep pressing the clutch button and hitting the paddle until the paddle works. There's even a time when he shifts up involuntarily two gears because the paddle makes a double contact. Does the clutch macro generate that behaviour? I hope no one says now that this is macro clutch...
Now some people will say that using the clutch in a button -not using a macro- is also illegal.
Well, I'm a noob programmer and I don't think what I did could be of any use to the LFS programmers base, except for learning purposes.
What I've done is a simple class and a few independent functions that I use for my tests. I work with my little class and the original insim.h (InSim.txt in docs folders renamed to .h) which defines the C structs for all IS packets, enums, etc. Here is my CInsim.h file
#ifndef _CINSIM_H #define _CINSIM_H
typedef unsigned char byte; typedef unsigned short word;
// Custom InSim specific database types typedef struct NodeLap NodeLap; typedef struct CompCar CompCar; typedef struct { int x; int y; int z; } Vec; typedef struct { float x; float y; float z; } Vector;
// Definition for our buffer datatype struct buffer { char buffer[PACKET_BUFFER_SIZE]; // Packet buffer - 512 should be more than enough unsigned int bytes; // Number of bytes currently in buffer };
/** * CInsim class to manage the Insim connection and processing of the packets */ class CInsim { private: SOCKET sock; // Socket struct buffer gbuf; // Our global buffer struct buffer lbuf; // Our local buffer char packet[PACKET_MAX_SIZE]; // A buffer where the current packet is stored fd_set readfd, exceptfd; // File descriptor watches struct timeval select_timeout; // timeval struct for the select() call
public: CInsim::CInsim(); // Constructor // "int init(...)" Establishes connection with the socket and insim. //+ The last argument ch_ver is a pointer to a IS_VER struct. If it's used an IS_VER packet //+ will be returned. If ch_ver is not used in the call no IS_VER will be requested/returned. int init (int protocol, char *addr, word port, char *product, char *admin, byte prefix = 0, struct IS_VER *ch_ver = NULL); int isclose(); // Closes connection from insim and from the socket int next_packet(); // Gets next packet ready into "char packet[]" char peek_packet(); // Returns the type of the current packet void* get_packet(); // Returns a pointer to the current packet. Must be casted int send_packet(void* packet); // Sends a packet to the host };
/** * Other functions!!! */
char* mstostr (long milisecs, char *str); // Converts miliseconds to a C string.
#endif
In my main I start the connection, send some initialization packets to setup the host, and then I enter the main loop in which I get the next packet. Then I have a switch inside that loop that calls individual functions depending on the packet received.
If someone finds this interesting I have no problem releasing it to the community. I think that all the code related to my CInsim class is in English.
This also means that I don't have any intention to completely rewrite my API and all the code I've been doing. Most of all, I don't have experience with event based systems, so that would be a completely time consuming task to research. Maybe some day. Anyway, I don't think that event based, timed systems do any kind of magic. If you don't use threads for these kind of things I think any other solution would be slower.
OK. I have downloaded pthreads-w32 and I'll try those
Now I have another question related to RCMs. I've noticed that when I send a RCM to a user it will erase other RCMs like the ones that tell you about your lap and split times. My intention was to provide additional info on split times added to the standard RCMs. When I receive an IS_SPX packet the "split time xxx" appears for a fraction of a second and then it gets erased my my insim-created RCM. I'd like to know if any of these would be the solution:
- Somehow disable the standard RCM messages generated by LFS so the only ones that show are the ones my InSim app send.
- Use transparent buttons instead of RCMs and try to manually place them in the center if the screen below the standard generated RCMs.
EDIT: I already have a working example using Pthreads-w32, and it seems pretty fast. Now I need to add mutual exclusion checking and tidy up a little the code. I needed to make some basic structures global in order for the threads to be able to access some data, and that leads to mutex issues and blablabla... A pain, but thinking about it, it's the way it must be done (I think).
Hi, I'm working in my insim example app which I built from scratch -using karl's C example as a base to get the socket and insim connection to work- and I've reached a point where I'd like to use/test RCM messages.
The "problem" is that I know how to send a RCM to any player, but I'm guessing that the correct way to clear those RCMs would be using an independent thread that would act as a timer that clears one specific RCM message, or maybe even handles all RCMs present at one time. Maybe I'm totally wrong and there's another way to do it. Of course I don't want my main thread to be on an active wait for like 4 or 5 seconds to clear the RCM and then continue.
I haven't used threads in a LONG time, and I think that I would breaking platform compatibility because I think there are no standard libraries for threads in C/C++. Right now all my code would be linux/windows compatible with tiny changes to the InSim API I've created, and I wouldn't like to break compatiblity...
Can anyone point me into the right direction?
PS: Please no responses like "use LFS External, that will do the job" or the like. I'm just toying with InSim to learn how it works, and as an exercise on C/C++ programming. I have no intention to pick any already existing InSim library.
Have you actually checked this or are you talking just out of "what the physhics should be"? Because two people who have used the macro have already told me that with the macro clutch the temp gets higher. I'm not going to test it anyway.
And now I ask again why would someone need manual clutch in a button. In what circumstances is that useful?
Someone said earlier in the post that the macro clutch makes the clutch heat up faster. Later someone told me that it's not a good choice for races as clutch overheating become a real problem with macro clutch.
In one post someone said that having the clutch in a button is necessary in some situations for people that don't have a clutch pedal. Can anyone explain why? I didn't get what he said, and I have never used the clutch "manually" using a button/key, and I don't see in which situations I would need it.
About the autoclutch topic. Autoclutch was introduced in LFS as a necessity. We NEED the autoclutch to change gears using most controller configurations. But remember, we are using autoclutch on manual cars. So the devs must find a good autoclutch system that won't give people using it a major advantage over the ones using a clutch pedal. It wouldn't be fair to have an autoclutch system in a manual car that works as good as a pure sequential gearbox. So Scawen tries to tweak the autoclutch so it's well balanced against manual clutching, and people who don't have a clutch pedal don't have a great advantage over the ones who do.
Then button clutch appears as a means to get better shifting times, and turning what is supposed to be a simulation of a driver pressing/releasing the clutch pedal into something more like a full sequential gearbox. So, even if you can do it because the game allows it, it's indeed totally against the spirit of the game. This is not different from making a script that performs perfect gear blips when downshifting, when it was already removed from the game.
Another thing that I'd like to know is if it gives you any advantage in terms of clutch overheating. Does this button clutch cause the clutch temperature to rise less or more than autoclutch? It would be interesting to know.
In my opinion it should be studied and solved somehow. I don't know how, maybe having a static, non-configurable button rate for the clutch button.
Now, about cheating:
Let's think -again- about LFS vs real life driving. We are playing a simulator that tries to portray reality as best as possible. To achieve that we play using several kind of controllers that don't match those used in the cars that we are driving in the game.
Many people -I'd say most of us- have wheels with only two pedals, and don't have a clutch pedal. With those settings we are driving manual cars like XFG, XRG, the TBO class, etc. In real life we would need to press the clutch pedal to shift gears, but as we don't have a clutch we use autoclutch. I think everybody thinks this is ok, as somehow we must be able to shift gears! Now, how many of you use left foot braking with these cars? I'm sure that a lot of people do. Is that cheating?
Things that some people consider cheating:
Using a custom view.
Left foot braking in manual cars.
Up-shifting by pressing the clutch instead of releasing the gas pedal (in cars like the MRT or the FBM).
Copying setup parameters available in lfsworld analyser tool.
Using less degrees of rotation in your wheel than the actual car.
Using paddles instead of a shifter (even if you don't have one, then go and buy it! That's what they say...)
Turning smoke/dirt option to minimum in rally races to have a better view.
And a long etc.
People should be a little more open minded about cheating. There are a lot of things that will give you an advantage -big or small-, but... is it really worth it? Some of these things don't deserve a single word, but things like button clutch should be discussed seriously, with arguments. There are a lot of words in this thread but very few people tried to give a reason why button clutch should or shouldn't be used.
From the reference that info must be at the beginning here:
[FONT=FIXED SYS]num unit offset description --- ---- ------ -----------
6 char 0 LFSMPR : do not read file if no match 1 byte 6 game version : ignore 1 byte 7 game revision : ignore 1 byte 8 MPR version : ignore 1 byte 9 immediate start : joined already running game [COLOR=Red][B]1 byte 10 reserved : - 1 byte 11 reserved : - 1 int 12 rules : - 1 int 16 flags : -[/B][/COLOR] 1 byte 20 laps byte : laps / hours (see notes) 1 byte 21 skill : skill level (0,1,2,3,4) 1 byte 22 wind : 0=off 1=weak 2=strong 1 byte 23 num players : players at start of race 8 char 24 LFS version : text, ends 0 4 char 32 short track name : e.g. BL2R 1 int 36 start time (UTC) : seconds from 00:00 1/1/1970 32 char 40 track name : text, ends 0 1 byte 72 config : 1,2,3.. (first config is 1) 1 byte 73 reversed : 0=no 1=yes 1 byte 74 weather : 0,1,2.. (first weather is 0) 1 byte 75 num finished (NF) : players in results table 1 int 76 0 : - NF result 80 RESULT INFO : (see below)[/FONT]
In my opinion it should one of those fields. Maybe the best thing would be to generate a handful of mpr files and check those values with an hex editor.
Anyway, with practice sessions you can check the number of laps (must be 0), but I don't know if there's any reference on the content of the mpr depending on the type of the session. I think Scawen may be the only one capable of solving your doubts.
Hi. In one of my tests I've come to need to track and understand a little PLIDs and UCIDs.
As I'm not going to have AI cars, I'll I have to do is keep a static array that links UCIDs and PLIDs. But I''d like to know what should be the size of that array, and that depends on the maximum UCID value.
Let's say I have this array:
byte PLIDS[47];
(Using C++)
I've used 47 thinking that UCIDs keep it at the minimum possible values, and considering there is a maximum of 47 slots (connections) including spectators.
I use the UCID as the index for the array, and assign to it the corresponding PLID value. But if I ever get an UCID greater than 46 that will produce a violation.
I can't get the Hello World example to compile either in command line or using Eclipse. I don't care much about command line as I wouldn't be using it, but... damn Eclipse is such a bitch! I don't know how to create a project from an existing java file. The other day I think I got it, but there were errors everywhere and I think it was because I had to link the commons logging jar file to my project, and I couldn't do it. And Eclipse tutorials are quite poor...
Could anyone post a quick guide on running the Hello World example in Eclipse? It could be very useful for beginners in Java like me to get started
EDIT: OK, I finally got it to work I found the way to create a project from existing sources (it wasn't as hidden as I thought, I was just blind), and then I added the common logging JAR, but totally forgot to add the jinsim JAR Anyway, after that Eclipse asked me to move "package net.sf.jinsim.examples.helloworld" and so I did. Then I found how to add arguments to the run call, and there I go with my "driver says: Hello World"
As I've spent more and more time studying the code of that example I've come to realize that it was made from several pieces of code as you say.
Your answers have clarified my mind and I hope that I can get my library to work today. Yesterday when I finished it didn't work, the select() calls returned either several timeouts or directly an error.
Only one thing that you've misunderstood in your response:
I ask about the use of "socket_file_descriptor + 1" in the recv() call, not in the select() call. I had already checked the man pages for both of them, and I already understood that for select() you must use "the max file descriptor + 1", but I haven't found anything about that for recv(). I have also checked Microsoft's Winsock2 Reference for recv(). If I get my code to work then I'll try changing it, but until then I'll keep the +1 as it works in the original example.
When I finish this stuff I'll probably release it as an example/tutorial for people to laugh at my code
EDIT: By the way, I was recommended Beej's Guide to Network Programming as an introduction to programming with sockets. I found it quite useful. Anyone knows about any other good tutorial out there?
This matter is very personal, and you can't say things like "I do it this way because it's the right way to do it". I'm totally against GPL and similar licenses as to me they are the anti-freedom licenses. Yes, the source code is available, but you are not free to use it as you like. I'm all in favour of licenses that give you freedom to do what you like with the code.
Some of you are in favour of everything being released to the community. I'm ok with that, I just don't share that opinion.
Anyway, if I ever release something to the community it will be to ask for help and improvements in the coding style, I'm quite a noob programmer and I'm not gonna make anything worth like some of the cool applications out there I know that if I ever release code I'll feel more embarrasment than anything
An IS_TINY is sent as a "version packet". There's no checking the version after this. I mean, the version request is sent but the IS_VER packet returned by insim is not processed in any way.
Another thing is that in the current insim version (4) you can request the IS_VER directly in the IS_ISI setting ReqI to non-zero, there's no need to create a whole IS_TINY for that purpose if you are just checking right after the IS_ISI is sent -which is the case-.
Why do you use the "socket_file_descriptor + 1"? In the reference I've seen you have to use the socket file descriptor as the first parameter, so I don't know why the "+1". Can anyone explian this to me?
More stuff:
int ok = 1; while (ok > 0) { int rc; // Set the timeout period struct timeval select_timeout; select_timeout.tv_sec = IS_TIMEOUT; select_timeout.tv_usec = 0;
// Setup the file descriptor watches fd_set readfd, exceptfd;
// Clear them FD_ZERO(&readfd); FD_ZERO(&exceptfd);
// Set them to watch our socket for data to read and exceptions that maybe thrown FD_SET(s, &readfd); FD_SET(s, &exceptfd); ... }
All this stuff at the beginning of the main loop could, and in my opinion *should* be taken out of the while. I think the FD_SETs and the timeval struct are defined once and then they keep using the same values during the while, so there's no need to keep that inside.
Another thing I've noticed is that you declare many vars inside the main loop. Those vars get declared and deleted in every iteration. I think those declarations could be made outside the while, making a reference to what they're going to be used to in a comment.
Taking a look at the code, "tbytes" max value can be "PACKET_BUFFER_SIZE" (unless i've missed something). So "tbytes - anything" will always be lesser or equal to PACKET_BUFFER_SIZE. In my opinion that condition is always true and therefore can be taken out. I understand the other two parts of the whole expression, but this first part I don't see any sense in it.
I'll report more things like these if I notice anything suspicious
A little thing: Scawen, us who have been following patch Y through all of its test patches know about it, but I think you should point out in the first post that this patch is not compatible with hosts older than Y30, and also have a few words about the HLs that are going to be deleted from lfsworld due to changes in the physics of the updated cars.
I just wanted to point it out because people might get confused when most of their servers suddenly disappear after they install patch Z.
I already said it when Y30 was released but it hasn't been fixed: If you pause the game in hotlapping or single player mode and then go to the pits (either with "esc -> pits" or with "shift+P") the "pause" message doesn't disappear and keeps blinking while in the garage screen, even if you go to the car selection screen it's still there. It only disappears when you join the track again.
That is debatable. What many people do is release the code to the public after dropping the project in order to let anyone pick it up, but they keep it private while they are developing it actively. I don't see any problem with that. If I were to release any cool mod for LFS I would probably do it this way.
As someone said earlier in this thread libraries are a different matter, and I would release any SDK library with a MIT or similar license, but an entire application is something that you get attached to easily and possibly you don't do it for people to reuse it, but to enjoy it as you originally created it.
So I understand that using code for building websites is something much more flexible than using code for releasing applications.
As long as people don't download your website (or the part that made use of GPL-like licensed code) you are not releasing a product, and thus you don't have to release the code. I think some licenses may have some workaround about this to prevent building websites with licensed code (libraries or snippets or whatever) with intention of making it a commercial "product" -i.e. people being charged for using its services-.
With standalone applications it's completely different as you have to release them to the public for people to download and install/use them. In those cases you have to release the source code if you used licensed code that states so.
So, if I build a website and code my own insim applications that I run in my servers (people don't have to install anything), I can use any library/program under any kind of license that allows me to use and modify the source code, without worrying about having to release my source code, because actually I'm not releasing anything at all, I'm just providing services that people use without having to install or download anything.