The online racing simulator
Me again. I have another problem but this time it's more difficult to track down. This has happened a couple of times but it's not reproducible so I'm not sure how it can be investigated. It looks as though an empty string is being passed to the getCarByName method in the Car class which throws an IllegalArgumentException. The couple of times it's happened to me have been when I started my application during an online race session. The code is called from the construct method in the NewPlayerResponse:

public void construct(ByteBuffer buffer) throws BufferUnderflowException {
super.construct(buffer);
connectionId = buffer.get();
playerType = buffer.get();;
playerFlags = buffer.getShort();
playerName = getString(buffer, 24);
numberPlate = getString(buffer, 8);
[b]String carName = getString(buffer, 4);
car = Car.getCarByName(carName);[/b]
skinName = getString(buffer, 16);
tyres = new Tyres(buffer);
addedMass = buffer.get();
intakeRestriction = buffer.get();
model = buffer.get();
passengers = buffer.get();
buffer.position(buffer.position()+5);
numberInRace = buffer.get();
buffer.position(buffer.position()+2);
}

This is what I have in my log file:

Quote from Error Log File :163 [Thread-3] ERROR net.sf.jinsim.AbstractChannel - Something went wrong!
java.lang.IllegalArgumentException: No car for given name found:
at net.sf.jinsim.Car.getCarByName(Car.java:52)
at net.sf.jinsim.response.NewPlayerResponse.construct(NewPlayerResponse.java:87)
at net.sf.jinsim.response.ResponseFactory.getPacketData(ResponseFactory.java:145)
at net.sf.jinsim.AbstractChannel.run(AbstractChannel.java:105)
at java.lang.Thread.run(Unknown Source)
163 [Thread-3] ERROR net.sf.jinsim.AbstractChannel - Something went wrong!
java.lang.IllegalArgumentException: No car for given name found:
at net.sf.jinsim.Car.getCarByName(Car.java:52)
at net.sf.jinsim.response.NewPlayerResponse.construct(NewPlayerResponse.java:87)
at net.sf.jinsim.response.ResponseFactory.getPacketData(ResponseFactory.java:145)
at net.sf.jinsim.AbstractChannel.run(AbstractChannel.java:105)
at java.lang.Thread.run(Unknown Source)
163 [Thread-3] ERROR net.sf.jinsim.AbstractChannel - Something went wrong!
java.lang.IllegalArgumentException: No car for given name found:
at net.sf.jinsim.Car.getCarByName(Car.java:52)
at net.sf.jinsim.response.NewPlayerResponse.construct(NewPlayerResponse.java:87)
at net.sf.jinsim.response.ResponseFactory.getPacketData(ResponseFactory.java:145)
at net.sf.jinsim.AbstractChannel.run(AbstractChannel.java:105)
at java.lang.Thread.run(Unknown Source)
164 [Thread-3] ERROR net.sf.jinsim.AbstractChannel - Something went wrong!
java.lang.IllegalArgumentException: No car for given name found:
at net.sf.jinsim.Car.getCarByName(Car.java:52)
at net.sf.jinsim.response.NewPlayerResponse.construct(NewPlayerResponse.java:87)
at net.sf.jinsim.response.ResponseFactory.getPacketData(ResponseFactory.java:145)
at net.sf.jinsim.AbstractChannel.run(AbstractChannel.java:105)
at java.lang.Thread.run(Unknown Source)
164 [Thread-3] ERROR net.sf.jinsim.AbstractChannel - Something went wrong!
java.lang.IllegalArgumentException: No car for given name found:
at net.sf.jinsim.Car.getCarByName(Car.java:52)
at net.sf.jinsim.response.NewPlayerResponse.construct(NewPlayerResponse.java:87)
at net.sf.jinsim.response.ResponseFactory.getPacketData(ResponseFactory.java:145)
at net.sf.jinsim.AbstractChannel.run(AbstractChannel.java:105)
at java.lang.Thread.run(Unknown Source)
164 [Thread-3] ERROR net.sf.jinsim.AbstractChannel - Something went wrong!
java.lang.IllegalArgumentException: No car for given name found:
at net.sf.jinsim.Car.getCarByName(Car.java:52)
at net.sf.jinsim.response.NewPlayerResponse.construct(NewPlayerResponse.java:87)
at net.sf.jinsim.response.ResponseFactory.getPacketData(ResponseFactory.java:145)
at net.sf.jinsim.AbstractChannel.run(AbstractChannel.java:105)
at java.lang.Thread.run(Unknown Source)

...

10071 [Thread-3] ERROR net.sf.jinsim.AbstractChannel - Something went wrong!
java.lang.IllegalArgumentException: No car for given name found:
at net.sf.jinsim.Car.getCarByName(Car.java:52)
at net.sf.jinsim.response.NewPlayerResponse.construct(NewPlayerResponse.java:87)
at net.sf.jinsim.response.ResponseFactory.getPacketData(ResponseFactory.java:145)
at net.sf.jinsim.AbstractChannel.run(AbstractChannel.java:105)
at java.lang.Thread.run(Unknown Source)
10071 [Thread-3] ERROR net.sf.jinsim.AbstractChannel - Something went wrong!
java.lang.IllegalArgumentException: No car for given name found:
at net.sf.jinsim.Car.getCarByName(Car.java:52)
at net.sf.jinsim.response.NewPlayerResponse.construct(NewPlayerResponse.java:87)
at net.sf.jinsim.response.ResponseFactory.getPacketData(ResponseFactory.java:145)
at net.sf.jinsim.AbstractChannel.run(AbstractChannel.java:105)
at java.lang.Thread.run(Unknown Source)
10071 [Thread-3] ERROR net.sf.jinsim.AbstractChannel - Something went wrong!
java.lang.IllegalArgumentException: No car for given name found:
at net.sf.jinsim.Car.getCarByName(Car.java:52)
at net.sf.jinsim.response.NewPlayerResponse.construct(NewPlayerResponse.java:87)
at net.sf.jinsim.response.ResponseFactory.getPacketData(ResponseFactory.java:145)
at net.sf.jinsim.AbstractChannel.run(AbstractChannel.java:105)
at java.lang.Thread.run(Unknown Source)

I don't know if it's significant but the number at the start of the error (163 and 10071 in the above example) appears to be repeated 3 times in each case. The numbers do not increase in a uniform manner (e.g. 163, 164, 165, 166, 167, 168, 169, 170, 200, 201, 2072...). I can't follow the code from the AbstractChannel class because there isn't source included with the updated 0.5rc6 jar you've posted. Sorry I can't be more specific.

edit: Something else that's got me puzzled now too. I set up a single player race with some AIs. I put qualifying to 15 minutes and the race length to 4 hours. When I look at the values in the RaceLaps object (obtained from getNumLaps() in StateResponse class) I get the following properties:

isTimedRace(): false
isPractice(): false
geLaps(): -62

I would have expected the results to be:

isTimedRace(): true
isPractice(): false
getLaps(): 4

Looking at the code in the RaceLaps constructor (from 0.5rc5):

if (readLap == 0) {
isPractice = true;
isTimedRace = false;
laps = 0;
} else if (readLap > 190) {
isPractice = false;
isTimedRace = true;
laps = readLap - 190;
} else if (readLap > 100) {
isPractice = false;
isTimedRace = false;
laps = (readLap - 100) * 10 + 100;
} else {
isPractice = false;
isTimedRace = false;
laps = readLap;
}

The last 2 branches are the only ones with both isPractice and isTimedRace flags false. The last branch should be the one which is executed, according to the InSim documentation:

Quote from InSim.txt :// RaceLaps (rl) : (various meanings depending on range)

// 0 : practice
// 1-99 : number of laps... laps = rl
// 100-190 : 100 to 1000 laps... laps = (rl - 100) * 10 + 100
// 191-238 : 1 to 48 hours... hours = rl - 190

However, in that case the value of readLap should be 194, not -62.

Am I missing something here or is there a problem?
Another small thing. When the player name has a vertical bar (or pipe) in it, like the following:

MoE|B. Keough

When they talk the getDriverName() method in MessageResponse will return the following:

MoE^vB. Keough

edit: And something else a little more serious. Calling toString() on a RaceStartResponse and a StateResponse object. They show different wind and weather conditions (the actual conditions were high wind and cloudy sunset, so the RaceStartResponse is correct and the StateResponse looks like it's incorrect).

Quote :Mon 22 Jun 2009 07:37:46: SessionInformation : raceStartResponse.toString(): [net.sf.jinsim.response.RaceStartResponse],
raceLaps: 0,
qualifingMinutes: 0,
numberOfPlayers: 1,
track: SOUTH_CITY_LONG,
weather: CLOUDY_SUNSET_DUSK,
wind: HIGH,

raceFlags: 163,
numberOfNodes: 533,
finishLineNodeIndex: 455,
split1NodeIndex: 70,
split2NodeIndex: 262,
split3NodeIndex: -1
Mon 22 Jun 2009 07:37:46: SessionInformation : stateResponse.toString(): [net.sf.jinsim.response.StateResponse]
Replay speed: 1.0X normal
Flags:
Show 2D display.
Camera: Driver View
Player: 0
Number of players: 1
Number of connections: 1
Number of racers finished: 0
Race in progress: No
Qualifying length: 0 laps.
Race length: 10 laps.
Track name: SO4
Weather type: 0
Wind type: None

Quote from amp88 :

public void construct(ByteBuffer buffer) throws BufferUnderflowException {
super.construct(buffer);
connectionId = buffer.get();
playerType = buffer.get();;
playerFlags = buffer.getShort();
playerName = getString(buffer, 24);
numberPlate = getString(buffer, 8);
[b]String carName = getString(buffer, 4);
car = Car.getCarByName(carName);[/b]
skinName = getString(buffer, 16);
tyres = new Tyres(buffer);
addedMass = buffer.get();
intakeRestriction = buffer.get();
model = buffer.get();
passengers = buffer.get();
buffer.position(buffer.position()+5);
numberInRace = buffer.get();
buffer.position(buffer.position()+2);
}


changed that the Car.getCarByName() returns null if the carName is not defined instead of the IllegalArgumentException

Quote from amp88 :

isTimedRace(): false
isPractice(): false
geLaps(): -62

I would have expected the results to be:

isTimedRace(): true
isPractice(): false
getLaps(): 4

snip


Thats a bug in jinsim I have fixed now.

Both changes are in the updated jar: http://liveforspeed.at/download/jinsim-0.5rc6.jar

For the other two Issues I have to test it with LFS that I don't have on my computer now, cause I'm working on my Mac.
Thanks again, I really appreciate it.
Another issue. I'm not sure if this is to do with JInSim or InSim, but hopefully someone can point me in the right direction.

In the attached MPR there is a PitLaneResponse indicating the player entered the pitlane received immediately as the replay begins (when everyone is still waiting on the grid for the race to start). I don't understand why this is sent as it should only be sent when the player enters the pitlane from the race track.

As I said above, I don't know what the cause of this issue is, but please let me know what you think about it.

Thanks again.

edit: Just remembered another point. Would it be possible to make the InSimResponse a Serializable class?
Attached files
glancn pitlane response.mpr - 1.9 MB - 714 views
I believe ^9 returns the coloring back to the default from another color.
Quote from bdshan :I believe ^9 returns the coloring back to the default from another color.

Yeah, I actually just realised that as I hit the "Post Message" button, so I tried to just remove it before anyone saw it. It's one of those situations where you see the solution to the problem when you talk about it or tell someone about it.
Another small issue. The Car enum has SVW for the car code for the Scirocco but it should be VWS.
Another small issue and a question. The small issue is that the PacketType enum has "MULIT_CAR_INFO" rather than "MULTI_CAR_INFO" and the question is that I can't seen to find the button function request to clear all buttons made by an InSim application. I don't know whether I'm just missing it or if it's missing from JInSim.

Quote from InSim.txt :enum // the fourth byte of IS_BFN packets is one of these
{
BFN_DEL_BTN, // 0 - instruction : delete one button (must set ClickID)
BFN_CLEAR, // 1 - instruction : clear all buttons made by this insim instance
BFN_USER_CLEAR, // 2 - info : user cleared this insim instance's buttons
BFN_REQUEST, // 3 - user request : SHIFT+B or SHIFT+I - request for buttons
};

Thanks for the reports, I will check those issues on the weekend :magnify:
Quote from amp88 :I can't seen to find the button function request to clear all buttons made by an InSim application.

I wrote this utility function to remove buttons. To remove all buttons just send in the connection id of 255.


/*
* Utility function to clear a button from any connection
* or all connections
*/
public void clearButton(byte connid)
{
try
{
ButtonFunctionRequest r = new ButtonFunctionRequest();
r.setSubtype(ButtonSubtype.CLEAR);
r.setConnectionId(connid); // 255 is for all connections
r.setClickId(BTN_ID);
client.send(r);
}
catch (IOException e)
{
lg.writeToLog(e.toString());
}
}

Quote from Ramon F. :Thanks for the reports, I will check those issues on the weekend :magnify:

Thanks

Quote from bdshan :I wrote this utility function to remove buttons. To remove all buttons just send in the connection id of 255.

And thanks
Quote from bdshan :This is killing me and to save my life I can't figure out a solution.

I am trying to read a Path file, AS1.pth to be exact. It was going along swimmingly until I need the number of nodes. When I do a readInt() I get a wacky number 536936448, but I know for a fact that AS1 has 288 nodes. Am I using the wrong function call here? Any suggestions?

...

Bit of a necrobump here. I was just playing about with pth files. After facing the same problem as you I got it to work by using little endian ordering. I've attached a few of the classes I've created to test this out with. The code for actually reading in the PTH file is in the PTHFileTesting class. TrackData and OneNode classes are also included. The getTrackLength() method in TrackData is "borrowed" from avetere (originally from this post with the subsequent modification noted in this post).

edit: Just realised the finish node is missing from the TrackData class attached to this post.

edit2: Also forgot to credit this post of Greenseed's for the algorithm (in C Sharp?).
Attached files
pthtesting.zip - 11.4 KB - 783 views
Quote from amp88 :Bit of a necrobump here. I was just playing about with pth files. After facing the same problem as you I got it to work by using little endian ordering. I've attached a few of the classes I've created to test this out with.

<snip>

Do you want to include this into JInSim?
If yes, you can do it yourself. I can add you as developer to the JInSim project on sourceforge if you like.
Quote from Brilwing :Do you want to include this into JInSim?
If yes, you can do it yourself. I can add you as developer to the JInSim project on sourceforge if you like.

No, I was just looking through the thread and saw bdshan was doing some work in an area I'd just been working in and he had a problem. You can include it in JInSim if you'd like.
As a follow on from this thread it seems like some major changes may be required to JInSim. The problem is that bytes sent by LFS through InSim are unsigned whereas the byte in Java is signed. So, InSim's byte can have values from 0-255 whereas JInSim's byte can have values from -128-127. If you try to represent a value outwith that range you'll get -1 (which was the cause of my problem in the other thread). So, it looks like all the bytes that come from InSim may have to be represented with shorts or ints instead to cover the range 0-255.
Hi everyone:

I'm starting to use the JInSim library and I have one doubt about CameraPositionResponse class, in the InSim.txt of my game says that after the roll value comes the ID of the viewed player, but in the class I only could find a getPlayerIndex that I think is the same. Am I correct?? If so I would be nice to change the name of the method.

Thanks
Quote from davidmd :Hi everyone:

I'm starting to use the JInSim library and I have one doubt about CameraPositionResponse class, in the InSim.txt of my game says that after the roll value comes the ID of the viewed player, but in the class I only could find a getPlayerIndex that I think is the same. Am I correct?? If so I would be nice to change the name of the method.

Thanks

Yes, getPlayerIndex returns the unique player ID (PLID).
Quote from amp88 :Yes, getPlayerIndex returns the unique player ID (PLID).

Thanks
Quote from amp88 :As a follow on from this thread it seems like some major changes may be required to JInSim. The problem is that bytes sent by LFS through InSim are unsigned whereas the byte in Java is signed. So, InSim's byte can have values from 0-255 whereas JInSim's byte can have values from -128-127. If you try to represent a value outwith that range you'll get -1 (which was the cause of my problem in the other thread). So, it looks like all the bytes that come from InSim may have to be represented with shorts or ints instead to cover the range 0-255.

Quote from PAWN Language Guide, Pg 93 (Foot Note) :Modern CPUs use two’s complement integer arithmetic. For positive values, the bitwise representation of a value is the same in one’s complement and two’s complement, but the representations differ for negative values. For instance, the same bit pattern that means -5 in one’s complement stands for -6 in two’s complement

Wofford's Scientific Programmi ... s with Integer Arithmetic
Hi,
I'm trying to send to spectator a player, now I have the playerId, but I have could figured out how to send a packet forcing a player to spectate. Any help would be really appreciated.
Thanks.

FGED GREDG RDFGDR GSFDG