I think my commit notes are verbose enough that they do not warrant another post here. Still...
As you maybe saw from the ticker apart from server side chat filtering, persistent cooldown timers for spells and abilities, i also had to refactor the teleport player method while they are on a boat.
This was one of the things where you thought everything is working perfectly, and then there still was the case you never imagined that it would not work.
On some boat routes, there is a shuttle ship which brings you from the dock to the boat, for example in Erudin. The client tells the server that he either enters or leaves a boat, so we can keep track which player is on which boat, and we know which players to transport to the new zone when the boat wants to zone.
Now the client "feature" is, that it will not tell the server any changes when the player is walking from the shuttle directly on the boat. The client only checks if he should sent new information to the server every 1 sec - since the player immediately is on another boat the client does not feel the need to sent the information that the boat changes. The server will still think the player is on the shuttle ship, even if the player is on the boat. And when the boat tries to zone the server thinks there are no players on the boat and just zones and you fall off the boat in the current zone because it is removed.
Now we still do know that the player is on a boat - but we cant say for certain on which one. So i changed the logic that there isnt a passenger list for each boat anymore. Upon zoning the zone will simply look if there are players near the location of the boats final stop point before zoning. This works pretty well, the correct boat name is then transmitted anyway the moment the client zones and sents us his profile with the boatname information.
As you can see, such a small client "feature" required some refactoring of existing working code - it didnt take too long tho.
5. August 2011
31. Juli 2011
Necessary Boat Enhancements
Previously, upon zoning with a boat the passengers relative location on the boat would be calculated server side - so that on the next zonin the passenger could be put near the location the boat was. This was not very accurate and there were two problems associated with this method. The first one is that passengers could fall into water upon zoning right next to the boat, because the server side coordinates and the client side coordinates do not match perfectly (due different time intervals on position updates). The next issue was, that boats have to wait after zoning in for the passengers to zone too. But what would happen when the player disconnected or the boat already moved? They would also fall into the water.
Also you shouldnt camp while on the boat because it would put you at the exact same spot in the ocean you logged out.
Now i knew it was possible to retrieve the correct relative position of the client on the boat somehow - because if you remember - when you camped/zoned on the boat - the exact same spot where you zoned would be memorized somehow.
After tinkering a bit and searching for some unknown values in the playerprofile it dawned on me - that the position is already in the normal x,y,z coordinate fields. However while on a boat - these values are no longer absolute for the zone, but relative to the boat. That means if we save these values and sent them to the client upon zoning in - he would calculate where the boat is and put us on the correct spot.
For this to work we also needed to signal the client that the player was previously on the boat - i already figured this out last year, but there was still the issue when the boat was not in the zone the client tries to login to, that the client would sent a request to ask where the boat currently is. So i had to extend the logic to ask the worldserver in what zone the requested boat is, then sent the correct opcode (i call it boat locate answer, which is also the same when you tell the client the boat you are on is now zoning) so that the client will try to zone into the new zone.
So to sumarize, the boats are now more fail proof - you should generally be put at the exact spot on the boat (on or within the boat doesn't matter) when you zone or camp/login again - it is not possible anymore to fall into water - even if for some reason we cannot find the boat in any zone, you will be teleported to the zones safe coordinates (these are mostly the boat footbridges in each zone). Also you can simply logout in one zone when you are on the boat, and when the boat is in another zone on login, you will be automatically transfered to that zone (so roleplay wise, you slept on the boat all the times =).
Now i can go back to the easier task and finishing the boat routes for the Kunark boats.
Also you shouldnt camp while on the boat because it would put you at the exact same spot in the ocean you logged out.
Now i knew it was possible to retrieve the correct relative position of the client on the boat somehow - because if you remember - when you camped/zoned on the boat - the exact same spot where you zoned would be memorized somehow.
After tinkering a bit and searching for some unknown values in the playerprofile it dawned on me - that the position is already in the normal x,y,z coordinate fields. However while on a boat - these values are no longer absolute for the zone, but relative to the boat. That means if we save these values and sent them to the client upon zoning in - he would calculate where the boat is and put us on the correct spot.
For this to work we also needed to signal the client that the player was previously on the boat - i already figured this out last year, but there was still the issue when the boat was not in the zone the client tries to login to, that the client would sent a request to ask where the boat currently is. So i had to extend the logic to ask the worldserver in what zone the requested boat is, then sent the correct opcode (i call it boat locate answer, which is also the same when you tell the client the boat you are on is now zoning) so that the client will try to zone into the new zone.
So to sumarize, the boats are now more fail proof - you should generally be put at the exact spot on the boat (on or within the boat doesn't matter) when you zone or camp/login again - it is not possible anymore to fall into water - even if for some reason we cannot find the boat in any zone, you will be teleported to the zones safe coordinates (these are mostly the boat footbridges in each zone). Also you can simply logout in one zone when you are on the boat, and when the boat is in another zone on login, you will be automatically transfered to that zone (so roleplay wise, you slept on the boat all the times =).
Now i can go back to the easier task and finishing the boat routes for the Kunark boats.
16. Juli 2011
Boaaaaaaaaaaaats
My current field of work is, if you followed our site for the last few month, boats. I'd like to finish the basic travel methods in EQ - i started with getting the zone points and intra zone teleporters working - so that all means available for travel are finished.
The roadmap states that boats are implemented "99%" (synthetic number), this is from a technical point of view - true. Taz implemented the boat routes in 2009, but only added the erudin<->qeynos boats.
So my first task at hand was understanding how the system works and how you add additional routes - i documented the process to make it easier for others to follow.
Basically, to add a new route you dont have to touch the server code - hence 99% complete status. What you need is the meta data - these are basically command files in text format. One for the world server which is the main controller of a boat.
In the world command files, you tell the boat where to spawn, to teleport passengers, how long to wait at certain places etc. There are no coordinates here yet, except for spawning. The coordinates for travel are in the zone command files, each boat has a command file for each zone it travels too - these include travel points, rotation and boat group checks. A boat group is, when one vessel needs to wait for another because they meet inbetween (think erudin).
Now the world command tells the zone server, travel your route from 1 to 20, the zone server looks into the zone command file, and does all steps from 1 to 20 for this boat, e.g. either constantly move or rotate, or check a group. After its finished moving, it signals the world server im done with what i had todo - than the world server does the next step in the world command file, e.g. wait for 60s because we reached a stop, then proceed with route from 21 to 40 or similar.
I also added some admin commands to make testing the boats easier, i.e. i can now jump to desintations with the boat while in a zone - so i would not have to wait 15min in oot to reach the zone line.
There where no manual zoning points in classic, you could not swim to another zone - because only people on a boat would have triggered a zone - we have a similar concept.
When the boat reaches the final step in a zone, it will transport itself and all the people to the new zone (a simple teleport to specific coordinates), after that the boat currently waits a certain amount of time at the teleport location to make sure everybody made it to the other side (zoning back in the days was longer for some people).
The last part is actually not needed, because i figured once out, that the client is able to automatically teleport the player to where the boat currently is. So even if the boat started moving again, the player would be teleported there. I will implement this sooner or later - this is needed anyway when a player disconnects or logs out while on a boat (you dont want to fall into the water swimming 10.000 /locs in one direction =p)
The roadmap states that boats are implemented "99%" (synthetic number), this is from a technical point of view - true. Taz implemented the boat routes in 2009, but only added the erudin<->qeynos boats.
So my first task at hand was understanding how the system works and how you add additional routes - i documented the process to make it easier for others to follow.
Basically, to add a new route you dont have to touch the server code - hence 99% complete status. What you need is the meta data - these are basically command files in text format. One for the world server which is the main controller of a boat.
In the world command files, you tell the boat where to spawn, to teleport passengers, how long to wait at certain places etc. There are no coordinates here yet, except for spawning. The coordinates for travel are in the zone command files, each boat has a command file for each zone it travels too - these include travel points, rotation and boat group checks. A boat group is, when one vessel needs to wait for another because they meet inbetween (think erudin).
Now the world command tells the zone server, travel your route from 1 to 20, the zone server looks into the zone command file, and does all steps from 1 to 20 for this boat, e.g. either constantly move or rotate, or check a group. After its finished moving, it signals the world server im done with what i had todo - than the world server does the next step in the world command file, e.g. wait for 60s because we reached a stop, then proceed with route from 21 to 40 or similar.
I also added some admin commands to make testing the boats easier, i.e. i can now jump to desintations with the boat while in a zone - so i would not have to wait 15min in oot to reach the zone line.
There where no manual zoning points in classic, you could not swim to another zone - because only people on a boat would have triggered a zone - we have a similar concept.
When the boat reaches the final step in a zone, it will transport itself and all the people to the new zone (a simple teleport to specific coordinates), after that the boat currently waits a certain amount of time at the teleport location to make sure everybody made it to the other side (zoning back in the days was longer for some people).
The last part is actually not needed, because i figured once out, that the client is able to automatically teleport the player to where the boat currently is. So even if the boat started moving again, the player would be teleported there. I will implement this sooner or later - this is needed anyway when a player disconnects or logs out while on a boat (you dont want to fall into the water swimming 10.000 /locs in one direction =p)
2. Februar 2011
no commit today
spent the last 5 hours reversing the client sides spell stacking mechanism and the hard coded exceptions the client put in, this should be a good start for YL to continue the spell work
24. Januar 2011
Zoning looking good
I've integrated my latest findings into the code, the client will now receive upon zoning in a list of teleport destination points which are retrieved from a DB table. The client will then sent the destination zone when he hits a client side zone line to the server. The server will then try to find the correct destination x,y,z of the new zone.
This is an odd quirk actually - you would expect that the client (who already knows the destination x,y,z since i've sent him this info at zonein) would sent you the coordinates along with the zone name - or at least the zone teleport index # of the destination he wants to use, but that doesn't happened - i debugged that part of the client and im sure its not the intended way - maybe to prevent cheating with teleporting to specific X,Y,Z. We can at least make sure this way that the client really hit a zone line and can force a specific loc.
The db table i've found is pretty good actually, i've tested 20+ zone borders and intra zone teleports (even the ones i added manually previously like erudin and felwitheb) and it works just fine. I only found one issue from nro->freeport because these zones do not end/continue on the same X value as a zone like qeynos hills -> qeynos (when you paste these zones together, they end where the other starts /loc wise for either x or y) - this is useful for putting the player at the exact X or Y when he hits a large zone line - it would be odd when you zone from the right most corner from freeport to nro but zone in in the center of this zone line.
Oh, btw i actually had an issue with the server side "find the destination point where the client wants to zone to" logic, all zones worked fine till i tested freeport, where i zoned ALWAYS into the sewers when i went from freportw to freporte or other way around - well turns out that somebody switched X and Y for finding the correct zone entry point when calculating deltaX²*deltaY²... a few hours lost on this tiny bug
This is an odd quirk actually - you would expect that the client (who already knows the destination x,y,z since i've sent him this info at zonein) would sent you the coordinates along with the zone name - or at least the zone teleport index # of the destination he wants to use, but that doesn't happened - i debugged that part of the client and im sure its not the intended way - maybe to prevent cheating with teleporting to specific X,Y,Z. We can at least make sure this way that the client really hit a zone line and can force a specific loc.
The db table i've found is pretty good actually, i've tested 20+ zone borders and intra zone teleports (even the ones i added manually previously like erudin and felwitheb) and it works just fine. I only found one issue from nro->freeport because these zones do not end/continue on the same X value as a zone like qeynos hills -> qeynos (when you paste these zones together, they end where the other starts /loc wise for either x or y) - this is useful for putting the player at the exact X or Y when he hits a large zone line - it would be odd when you zone from the right most corner from freeport to nro but zone in in the center of this zone line.
Oh, btw i actually had an issue with the server side "find the destination point where the client wants to zone to" logic, all zones worked fine till i tested freeport, where i zoned ALWAYS into the sewers when i went from freportw to freporte or other way around - well turns out that somebody switched X and Y for finding the correct zone entry point when calculating deltaX²*deltaY²... a few hours lost on this tiny bug
21. Januar 2011
Its been a while...
I've been doing some reverse engineering work since the beginning of the new year.
I noticed that the intra zone teleports do not work for most zones, so i manually added them for felwitheb and erudin. While testing out the zoning, i finally figured out how to set the initial camera position upon zoning, i.e. we can no specify that a player should look up or down after zoning - useful so that the player faces the right direction.
Upon till then, our zoning worked server side, that means when the player moved to a specific location the server noticed it and if the player hit a zone border of teleport pad, we moved him manually. This works fine but is alot of unneeded overhead.
Now back to the intra zone teleporting, it was weird that some teleports did work without any interaction, in erudin for example, the pad from the harbor up to the palace worked. That meant the client knew some coordinates already.
YL provided some interesting input, he noticed that when using eye of zoom near a zone line/pad - the eye would vanishe - the client would kill it. So the client somehow must already knew the locations from WHERE a player should be teleported too, what he didnt knew was the destination of the teleport.
Well after further reverse engineering, i found out that the client had some kind of teleport table with indexes. I found the opcode which needed to be sent to the client along with an array of teleport destination and each specific magic number of each teleport destination. The client already scans the area when a player enters a zone point, he has a hard coded ID for each of these - and we just have to tell him for each of these ID where to teleport the player.
So what that means is, in classic (and afaik still to date) - the client knows only the zone lines but the server will tell him where he should teleport too upon zoning in. After some research i found that eqemu developers could simply take a live packet dump and extract the zone points from there. This is of course 1000 times easier than manually adding each destination teleport point from your own memory (setting up only 8 intra zone points took me around 5h). Of course the destinations change of time so we cant simply take a live dump now, but some older data might be useful, i think i got that covered.
BTW: One interesting info i found during reverse engineering was a funny opcode - it enables us to play a specific sound file to the player. The are all indexed by ID - so any wave file the client knows, we can play it. And the funny part is - if you use an unknown ID you get "This is an error message, please report the bug" in a muffled developer voice =p
I noticed that the intra zone teleports do not work for most zones, so i manually added them for felwitheb and erudin. While testing out the zoning, i finally figured out how to set the initial camera position upon zoning, i.e. we can no specify that a player should look up or down after zoning - useful so that the player faces the right direction.
Upon till then, our zoning worked server side, that means when the player moved to a specific location the server noticed it and if the player hit a zone border of teleport pad, we moved him manually. This works fine but is alot of unneeded overhead.
Now back to the intra zone teleporting, it was weird that some teleports did work without any interaction, in erudin for example, the pad from the harbor up to the palace worked. That meant the client knew some coordinates already.
YL provided some interesting input, he noticed that when using eye of zoom near a zone line/pad - the eye would vanishe - the client would kill it. So the client somehow must already knew the locations from WHERE a player should be teleported too, what he didnt knew was the destination of the teleport.
Well after further reverse engineering, i found out that the client had some kind of teleport table with indexes. I found the opcode which needed to be sent to the client along with an array of teleport destination and each specific magic number of each teleport destination. The client already scans the area when a player enters a zone point, he has a hard coded ID for each of these - and we just have to tell him for each of these ID where to teleport the player.
So what that means is, in classic (and afaik still to date) - the client knows only the zone lines but the server will tell him where he should teleport too upon zoning in. After some research i found that eqemu developers could simply take a live packet dump and extract the zone points from there. This is of course 1000 times easier than manually adding each destination teleport point from your own memory (setting up only 8 intra zone points took me around 5h). Of course the destinations change of time so we cant simply take a live dump now, but some older data might be useful, i think i got that covered.
BTW: One interesting info i found during reverse engineering was a funny opcode - it enables us to play a specific sound file to the player. The are all indexed by ID - so any wave file the client knows, we can play it. And the funny part is - if you use an unknown ID you get "This is an error message, please report the bug" in a muffled developer voice =p
27. Juli 2010
I took some time to find unknown opcodes the client can possibly sent.
I found a few, for example an opcode sent by the client when he receives a new spawn (player) with an unknown guild id. Normally all guilds and their ids are sent upon zoning, but if a new guild is created meanwhile the client does not know anything about the guild (name etc).
I also found a client command i had forgotten about or never used anyway, the /channel command. Apart from the server side filter command this command enables you to turn off the specific chat channels like gsay,ooc,auction,shout,ooc etc. The client can inform the server that he wants to either turn on/off a channel. I identified the requests from the client, we only need to add the filtering to the server which shouldn't be hard.
~ 240min
= 10020min (167h)
I found a few, for example an opcode sent by the client when he receives a new spawn (player) with an unknown guild id. Normally all guilds and their ids are sent upon zoning, but if a new guild is created meanwhile the client does not know anything about the guild (name etc).
I also found a client command i had forgotten about or never used anyway, the /channel command. Apart from the server side filter command this command enables you to turn off the specific chat channels like gsay,ooc,auction,shout,ooc etc. The client can inform the server that he wants to either turn on/off a channel. I identified the requests from the client, we only need to add the filtering to the server which shouldn't be hard.
~ 240min
= 10020min (167h)
Abonnieren
Posts (Atom)