Fastwalk system

Archive of the older Feature Request Forum Posts

Moderator: POL Developer

User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

Actually we found, as common as loading up a 3D client. This was a problem for a while on my shard too... now I have a different solution but requires a lot of staff monitoring. I have the move packet hooked to only count up a prop #moves if they move. Then I have a script run once per second on everyone online taking that prop, subtract 5 or 10 from it (5 if on foot, 10 if on mount) and add it to an array prop. Then clear that #moves prop. My staff have a command that will bring up a list in an HTML gump with every result from the last 5 minutes (in 5 second intervals) of everyone online. The +'s (moving faster than normal) in red text, the others in black. We easily spot who is speedhacking this way. But this is the same old monitor move instead of prevention which would be great to be able to do.
Repsak
Master Poster
Posts: 91
Joined: Sun Feb 05, 2006 2:00 am
Location: Denmark

Post by Repsak »

Don’t you have problems with 3D clients?

Our test shows that 3D client run 5-10% faster then 2D clients. More and more players are beginning to use 3D, because 2D client above 3.X will lag if the latency between the server clients is 140+ ping. 3D does not lag for the same player, so 3D is the only choose if someone want to play on a server located on another continent (EU Vs. US).

The fact that 3D are faster then 2D, are a huge problem in PvP for obvious reasons, and we currently have no way of even out that advantage.
The only solution I can see to this problem is to hope that a core fastwalk prevention system will also limit the 3D client to the same speed as a 2D client.
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

3D clients have been tested and have a faster running speed than 2D. up to 3 steps per second faster on a mount. I have tested this on the same comp POL is on so no lag. And my comp is fast enough to run 2D extremely smooth with POL along side it.
qrak
Grandmaster Poster
Posts: 198
Joined: Sun Feb 05, 2006 4:35 pm
Location: Poland

Post by qrak »

I have an idea. Write some external anti cheat program which would look for malicious tools inside ultima online folder. Without this tool connecting to shard wouldn't be possible. It can be done with aux scripts i think because i know one shard which is using such "gate" to verify player if they have that tool running or not.
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

The thing is, you dont need a tool running to speedhack. The speedhack I've tested just modifies the client a little bit and thats it. It never needs to be run again.
Repsak
Master Poster
Posts: 91
Joined: Sun Feb 05, 2006 2:00 am
Location: Denmark

Post by Repsak »

This is becoming a bigger and bigger problem on our shard, so I’m desperate searching for options.
The biggest problem is not speedhack, but that 3D clients run faster then 2D client, making PvP in 3D the only option if you want to stand a chance.
Why don’t you just disconnect all clients using 3D you might ask? Because all 4.0+ 2D clients lag if you latency is 125+, but 3D clients does not have this flaw, forcing many player to play 3D.

How fast was the server you (CWO) tried that script solution on?
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

Running on Windows XP
Pentium 4 3.4GHz HT
2GB Dual Channel PC4200 RAM

The server can run about 40 million instructions/min without much lag in tests. Although mine runs less than a million under normal conditions.
Repsak
Master Poster
Posts: 91
Joined: Sun Feb 05, 2006 2:00 am
Location: Denmark

Post by Repsak »

How big was your player base at the time you tested it?
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

40-50 at the time.

Probably what made it so harsh on the shard is that all instructions are critical and theres pretty much no way around it.
Repsak
Master Poster
Posts: 91
Joined: Sun Feb 05, 2006 2:00 am
Location: Denmark

Post by Repsak »

My main concern is, as already stated, the faster 3D client, do you have any experince with this problem?
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

Code: Select all

use uo;
use os;

program clientchecker(who)
 sleep(10);
 if(who.clientversion["3D"] || who.clientversion ["Dawn"] || who.clientversion ["TD"])
   SendSysMessage(who, "Sorry 3D is not supported on this server. Please log in with a 2D client.");
   Sleep(3);
   DisconnectClient(who);
   return;
 endif
endprogram
its not foolproof by far but I fire this script from the login and reconnect scripts with Start_Script()

Theres no other known way to me right now.

If I find someone running constantly faster on my server or using 3D past this script, they're considered cheating.
Repsak
Master Poster
Posts: 91
Joined: Sun Feb 05, 2006 2:00 am
Location: Denmark

Post by Repsak »

Repsak wrote:Why don’t you just disconnect all clients using 3D you might ask? Because all 4.0+ 2D clients lag if you latency is 125+, but 3D clients does not have this flaw, forcing many player to play 3D.
My server is located in Denmark, and most/all players from the US, Canada etc have at least 125 ms latency/ping, meaning they will with newer 2D clients, so they have no other choose then to use 3D.
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

Currently you only have 3 choices...

Just accept 3D logging into the shard
Lagging your shard down with a speedhack stopper
Putting in a 3D deterrent like I just posted above

Other than that, theres no other way.
Repsak
Master Poster
Posts: 91
Joined: Sun Feb 05, 2006 2:00 am
Location: Denmark

Post by Repsak »

Seem you are right. I have tested the speed of 2D and 3D clients on a RunUO server, and the problem is exactly the same. I don’t know if it’s the same problem on OSI, but at least it’s not solely related to POL servers.
tartaros
New User
Posts: 28
Joined: Tue Mar 27, 2007 6:30 am
Contact:

Post by tartaros »

just for the record of how this thing might work:
You wouldn't send "denywalk" packets to clients that are too fast, you would only "postpone" the sending of the "walk ok" packets (along with postponing of the actual movement and broadcasting the new position to other clients etc.)
The problem with the deny packet is following - Sometimes the client does a little "lag" between steps all by itself... The result is that instead of 3 walkrequest packets being sent with two equal pauses, it will be one "big" pause followed by the two other packets immediately one after another, even when the player is not speedhacking at all.
The solution is to have a "buffer" that stores the time of say last 3 steps, so that the speed checking system won't interfere with clients that have "in average" proper speed, only their connection/computer is a little jumpy.
Also never deny movement based on speed, simply maintain a queue of the incoming walk requests, and don't process them before they should be processed. That way you don't even need the "fastwalk prevention" that is built-in into the UO network protocol (i.e. the 0xBF subcommands, etc.) - those are actually useless.
Not sure about how this is or isn't possible in scripts, but if properly coded (into core), it shouldn't be CPU intensive at all. Just one little queue of walkrequest packets (which would be empty most of the time) and a speedmeter of last 3 steps...
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

tartaros, my packethook (the one that lags too much to use) kinda handles that. Theres a "fastwalk stack" built into the client. The script sends random 32-bit Integers to the client that the client sends back in the walk packet. Initially I sent 6 of them to the client then more at regular intervals based on if you were on a mount or not. Then the hook checks the integer when it comes in with the walk packet and if it passes, will allow the packet to pass to the core. If not, the deny packet is sent back and the walk request is blocked from the core.
mr bubbles
Grandmaster Poster
Posts: 120
Joined: Thu Jan 18, 2007 2:34 am

Post by mr bubbles »

id pay for an external speedhack checker, just for the 2d clients :P
Repsak
Master Poster
Posts: 91
Joined: Sun Feb 05, 2006 2:00 am
Location: Denmark

Post by Repsak »

CWO wrote:tartaros, my packethook (the one that lags too much to use) kinda handles that. Theres a "fastwalk stack" built into the client. The script sends random 32-bit Integers to the client that the client sends back in the walk packet. Initially I sent 6 of them to the client then more at regular intervals based on if you were on a mount or not. Then the hook checks the integer when it comes in with the walk packet and if it passes, will allow the packet to pass to the core. If not, the deny packet is sent back and the walk request is blocked from the core.
Based on your script, I have adjusted the system a bit, but my testing proved the system inadequate.
Take the 3D client, that send the walk packets about 5% faster then the 2D client.
1. The first walk packet is send and the server returns a "walk ok" packet, hence client can move.
2. The second packet is send, but 5% to fast, so the server will deny it and the client is forced back to the original location.
3. The third walk packet is send and accepted by the server.
So basically every other walk packet for 3D will be denied, creating a very bouncy movement experience. To solve this problem I tried to raise the timer, allowed more walk packet to be accepted, but it only improved the solution, it didn't solve it.

Tartaros suggestion, to postpone the handling of the walk packets might work, but it all depends on how the client will react to these delayed packets.
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

Are you sending the initialization at login/reconnect? And yes, it will cause bouncy movement because its moving partially too fast. You'll never force the client to slow down unless you actually bounce them back a bit. What you're talking about is smoothing it out which would have to be a modified on the client.
tartaros
New User
Posts: 28
Joined: Tue Mar 27, 2007 6:30 am
Contact:

Post by tartaros »

I have tested the system I described with GodClient - it's walking speed is about twice the speed of normal clients... The only little problem with it is that the first few steps are faster (which would be the same in case of sending 6 hashes in advance) , then it is forced to slow down, but since I don't deny the walkrequests, the result is that the movement is still pretty smooth.

Don't ask for scripts tho as I don't use POL (it's my own emulator)...
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

if you dont send the deny then how are you slowing the movement or are you just logging it? The scripts I put up are designed to stop the movement from going too fast period. If you don't send either the accept or deny packets, either you'll hang up the client making it think its lagging or the client and server go out of sync.
Repsak
Master Poster
Posts: 91
Joined: Sun Feb 05, 2006 2:00 am
Location: Denmark

Post by Repsak »

CWO wrote:Are you sending the initialization at login/reconnect?
Yep.


Here is my modified packet, but it can only handle speekhack, not the the movement difference in the clients :cry:
Let me point out that I am not using this on a live shard, since I was not happy with the results.

uopacket.cfg

Code: Select all

Packet 0x02
{
  Length 7
  ReceiveFunction antispeed:HandleSpeedHackers
}
pkg.cfg

Code: Select all

Enabled		1
Name		antispeedhack
Maintainer	Repsak
Email		repsak@pangaea-world.dk
CoreRequired	96
Version		1.0
Author/Basis	CWO
logon.src

Code: Select all

use uo;
use polsys;
use util;

program Login_AntiSpeedHack(who)
        
        SetObjProperty(who, "#moves", CInt(0));
        SetObjProperty(who, "#shackwarning", CInt(0));
        EraseObjProperty(who, "#movepid");
        var shackstack := array;
        shackstack[1] := RandomInt(0x4000000000000)+1;
        shackstack[2] := RandomInt(0x4000000000000)+1;
        shackstack[3] := RandomInt(0x4000000000000)+1;
        shackstack[4] := RandomInt(0x4000000000000)+1;
        shackstack[5] := RandomInt(0x4000000000000)+1;
        shackstack[6] := RandomInt(0x4000000000000)+1;
        var shstack := CreatePacket(0xBF, 29);
        shstack.SetInt16(1,0x001D);
        shstack.SetInt16(3,0x0001);
        shstack.SetInt32(5, shackstack[1]);
        shstack.SetInt32(9, shackstack[2]);
        shstack.SetInt32(13, shackstack[3]);
        shstack.SetInt32(17, shackstack[4]);
        shstack.SetInt32(21, shackstack[5]);
        shstack.SetInt32(25, shackstack[6]);
        shstack.SendPacket(who);
        SetObjProperty(who, "#shackstack", shackstack);

endprogram
reconnect.src

Code: Select all

use uo;
use polsys;
use util;

program Reconnect_AntiSpeedHack(who)

        SetObjProperty(who, "#moves", CInt(0));
        SetObjProperty(who, "#shackwarning", CInt(0));
        EraseObjProperty(who, "#movepid");
        var shackstack := array;
        shackstack[1] := RandomInt(0x4000000000000)+1;
        shackstack[2] := RandomInt(0x4000000000000)+1;
        shackstack[3] := RandomInt(0x4000000000000)+1;
        shackstack[4] := RandomInt(0x4000000000000)+1;
        shackstack[5] := RandomInt(0x4000000000000)+1;
        shackstack[6] := RandomInt(0x4000000000000)+1;
        var shstack := CreatePacket(0xBF, 29);
        shstack.SetInt16(1,0x001D);
        shstack.SetInt16(3,0x0001);
        shstack.SetInt32(5, shackstack[1]);
        shstack.SetInt32(9, shackstack[2]);
        shstack.SetInt32(13, shackstack[3]);
        shstack.SetInt32(17, shackstack[4]);
        shstack.SetInt32(21, shackstack[5]);
        shstack.SetInt32(25, shackstack[6]);
        shstack.SendPacket(who);
        SetObjProperty(who, "#shackstack", shackstack);

endprogram
antispeedhelper.src

Code: Select all

use uo;
use os;
use polsys;
use util;

program antispeed(who)

        SetObjProperty(who, "#movepid", GetPid());
        var packet, newkey, shackwarning;
        while(GetObjProperty(who, "#moves"))
             if (GetEquipmentByLayer(who, 25))
                  sleepms(80); // 80
             else
                  sleepms(160); // 160
             endif
             set_critical(1);
             newkey := RandomInt(0x4000000000000)+1;
             packet := CreatePacket(0xBF, 9);
             packet.SetInt16(1,0x0009);
             packet.SetInt16(3,0x0002);
             packet.SetInt32(5,newkey);
             packet.SendPacket(who);
             shackwarning := CInt(GetObjProperty(who, "#shackwarning"));
             SetObjProperty(who, "#moves", CInt(GetObjProperty(who, "#moves")-1));
             var shackstack := GetObjProperty(who, "#shackstack");
             shackstack.append(newkey);
             SetObjProperty(who, "#shackstack", shackstack);
             set_critical(0);
             if (shackwarning)
                  SetObjProperty(who, "#shackwarning", shackwarning-1);
                  if (shackwarning > 5)
                       Print(who.name + " is getting excessive speedhack warnings!");
                       SetObjProperty(who, "#shackwarning", CInt(0));
                  endif
             endif
        endwhile
        SetObjProperty(who, "#shackwarning", CInt(0));
        EraseObjProperty(who, "#movepid");
        
endprogram
antispeed.src

Code: Select all

use uo;
use os;
use polsys;
use unicode;
use util;

program AntiSpeedHack()
        Print("PacketHooks - Anti SpeedHack" );
        return 1;
endprogram

exported function HandleSpeedHackers(character, byref packet)

        var direction := packet.GetInt8(1);
        var shackcheck := packet.GetInt32(3);
        if ((character.facing != direction) && (character.facing != (direction - 128) ))
             //Changed facing, send a new key since this isn't really a move
             //var newkey := RandomInt(0x4000000000000)+1;
             //var sstack := GetObjProperty(character, "#shackstack");
             //sstack[6] := newkey;
             //SetObjProperty(character, "#shackstack", sstack);
             var packet := CreatePacket(0xBF, 9);
             packet.SetInt16(1,0x0009);
             packet.SetInt16(3,0x0002);
             //packet.SetInt32(5,newkey);
             packet.SetInt32(5, shackcheck);
             packet.SendPacket(character);
             return 0;
        endif

        var sstack := GetObjProperty(character, "#shackstack");
        var moves := CInt(GetObjProperty(character, "#moves"));

        if(shackcheck and shackcheck in sstack and moves < 6)
             var newstack := array;
             foreach num in sstack
                  if (num != shackcheck)
                       newstack.append(num);
                  endif
             endforeach
             SetObjProperty(character, "#moves", moves+1);
             SetObjProperty(character, "#shackstack", newstack);
             if (!GetObjProperty(character, "#movepid"))
                  Start_Script("antispeedhelper", character);
             endif
        else
             SendSysMessage(character, "Too fast");
             SetObjProperty(character, "#shackwarning", GetObjProperty(character, "#shackwarning")+2);
             var reject := CreatePacket(0x21, 8);
             reject.SetInt8(1, packet.GetInt8(2));
             reject.SetInt16(2, character.x);
             reject.SetInt16(4, character.y);
             reject.SetInt8(6, direction);
             reject.SetInt8(7, character.z);
             reject.SendPacket(character);
             return 1;
        endif

        return 0;
        
endfunction

antispeed.src is the one I have worked the most with, trying the change the upper time (80 and 160) to see hot the client would react.
I should add that the original pkg did not work, so I had to make a few modification on the original design.
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

My originals didn't work? Maybe I changed something since working with it last... I know when I actually last used it on my shard it would be fine until a certain number of people would log on then the shard sysload would start going up and everyone would get bogged down by that hook.

My shard has been under a total rewrite and I actually don't use that system anymore. Now I just have a counter on the script and it logs how many moves you've done while another script loops through everyone every second and logs how many moves you did against how many possible moves. My staff can see the last 5 minutes of moves to track people. At least it doesn't lag my shard anymore.
tartaros
New User
Posts: 28
Joined: Tue Mar 27, 2007 6:30 am
Contact:

Post by tartaros »

CWO wrote:if you dont send the deny then how are you slowing the movement or are you just logging it? The scripts I put up are designed to stop the movement from going too fast period. If you don't send either the accept or deny packets, either you'll hang up the client making it think its lagging or the client and server go out of sync.
If the client works correctly (i.e. it's not modified in any way, like for example by enabling "smooth walk" in injection), it will not go more than 3 steps "in advance" from the server responses.
They will not go out of sync if you properly queue the too-early-incoming packets.
User avatar
CWO
POL Expert
Posts: 1159
Joined: Sat Feb 04, 2006 5:49 pm
Location: Chicago, IL USA

Post by CWO »

Thats what I was saying, the deny packet is the only way to say to the client that you can not move so you wont advance faster than you should. By not sending either, you're imitating lag which smoothwalk will override. This will just start causing problems later because the client and server aren't at the same spot. With the deny packet, you focus the client back to that spot so even with smoothwalk, you'll be forced back to that spot. This prevents severe jumping from another client's point of view. Now if someone blocks deny packets, the client will be farther forward than the server wants which would likely cause a sync error and disconnection.
Locked