From 64a4898c8212320e45f87d0687ac48ee689d83b2 Mon Sep 17 00:00:00 2001 From: sauerbraten Date: Sat, 10 Jul 2021 16:59:01 +0200 Subject: [PATCH] clean up and document p1xbraten detection --- README.md | 8 +++++ patches/extrapings.patch | 64 ++++++++++++++++++---------------------- src/fpsgame/client.cpp | 46 ++++++++++++++--------------- 3 files changed, 58 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index bcd13b2..b676ee6 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ This repository contains the source for my client mod, as well as the patches ap - [gamehud.patch](#gamehudpatch) - [chat_highlight_words.patch](#chat_highlight_wordspatch) - [server_ogzs.patch](#server_ogzspatch) + - [extrapings.patch](#extrapingspatch) - [Installation](#installation) - [Windows](#windows) - [macOS](#macos) @@ -193,6 +194,13 @@ Improves logging when running a dedicated server: - allows using slim .ogz files (see https://github.com/sauerbraten/genserverogz) on the server without getting `checkmaps` errors +### [extrapings.patch](./patches/extrapings.patch) + +- adds the `getpbconfidence ` command: returns a number between 0 and 1000, where 1000 means the player is almost certainly running p1xbraten, and 0 means the player is almost certainly not running p1xbraten (the confidence starts at 0 for all clients and increases the longer you are connected; usually 1000 is reached in less than one minute) +- adds the `enablep1xbratendetection` variable: set to 0 to disable broadcasting that you use p1xbraten (and detecting other p1xbraten players yourself) + +This lets you detect other p1xbraten users connected to the same server as you. It relies on p1xbraten clients sending additional packets to the server, which the server then broadcasts to all other clients. This means you receive this information about other players, and it also means the other players can tell you're using p1xbraten. No information other than "I use p1xbraten" is sent. The information is not sent to me (p1x) or any third party, just the server you're playing on and the other players on it. Opt out if you are firefly! + ## Installation The latest builds are always at https://github.com/sauerbraten/p1xbraten/releases/latest. diff --git a/patches/extrapings.patch b/patches/extrapings.patch index 51ed28c..8cdf2df 100644 --- a/patches/extrapings.patch +++ b/patches/extrapings.patch @@ -1,16 +1,17 @@ Index: src/fpsgame/client.cpp =================================================================== ---- src/fpsgame/client.cpp (revision 6488) +--- src/fpsgame/client.cpp (revision 6502) +++ src/fpsgame/client.cpp (working copy) -@@ -118,6 +118,7 @@ +@@ -118,6 +118,8 @@ bool senditemstoserver = false, sendcrc = false; // after a map change, since server doesn't have map data int lastping = 0; + int lastextraping = 0; ++ VARP(enablep1xbratendetection, 0, 1, 1); bool connected = false, remote = false, demoplayback = false, gamepaused = false; int sessionid = 0, mastermode = MM_OPEN, gamespeed = 100; -@@ -347,6 +348,8 @@ +@@ -347,6 +349,8 @@ } ICOMMAND(isai, "ii", (int *cn, int *type), intret(isai(*cn, *type) ? 1 : 0)); @@ -19,55 +20,46 @@ Index: src/fpsgame/client.cpp int parseplayer(const char *arg) { char *end; -@@ -1046,7 +1049,14 @@ +@@ -1046,7 +1050,15 @@ putint(p, N_PING); putint(p, totalmillis); lastping = totalmillis; + lastextraping = totalmillis; } -+ else if(totalmillis-lastextraping>99) // send two extra N_PING packets between each normal one ++ else if(totalmillis-lastextraping>99) // send two extra N_CLIENTPING packets between each normal one + { -+ putint(p, N_PING); -+ putint(p, (totalmillis-lastping)/99); // 1, 2, 1, 2, ... ++ putint(p, N_CLIENTPING); ++ int delta = ((totalmillis-lastping)/99)%2 ? -1 : 2; ++ putint(p, player1->ping+delta); // others will see 3 N_CLIENTPINGs from us within 250ms: ping (0ms), ping-1 (99ms), ping+2 (198ms) + lastextraping = totalmillis; + } sendclientpacket(p.finalize(), 1); } -@@ -1757,14 +1767,36 @@ - } - - case N_PONG: -- addmsg(N_CLIENTPING, "i", player1->ping = (player1->ping*5+totalmillis-getint(p))/6); -+ { -+ int pong = getint(p); -+ if(pong<3) // extra N_PING response -+ { -+ int sign = pong%2 ? -1 : 1; -+ addmsg(N_CLIENTPING, "i", player1->ping+(sign*pong)); -+ } -+ else addmsg(N_CLIENTPING, "i", player1->ping = (player1->ping*5+totalmillis-pong)/6); +@@ -1760,10 +1772,28 @@ + addmsg(N_CLIENTPING, "i", player1->ping = (player1->ping*5+totalmillis-getint(p))/6); break; -- -+ } case N_CLIENTPING: + { if(!d) return; - d->ping = getint(p); -+ int ping = getint(p); -+ d->extrapings++; -+ int sign = (d->extrapings)%2 ? -1 : 1; -+ if(ping==d->ping+sign*(d->extrapings)) -+ { -+ d->p1xbratenconfidence += d->extrapings * 2; -+ d->p1xbratenconfidence = min(d->p1xbratenconfidence, 1000); -+ } ++ if(!enablep1xbratendetection) d->ping = getint(p); + else + { -+ d->ping = ping; -+ d->p1xbratenconfidence -= d->extrapings; -+ d->p1xbratenconfidence = max(d->p1xbratenconfidence, -1000); -+ d->extrapings = 0; ++ int ping = getint(p); ++ int expecteddelta = (d->extrapings+1)%3 ? ((d->extrapings+1)%2 ? -1 : 2) : 0; // 0, -1, 2, 0 -1, 2, ... ++ if(expecteddelta && ping==d->ping+expecteddelta) ++ { ++ d->extrapings++; ++ d->p1xbratenconfidence += d->extrapings * 2; ++ d->p1xbratenconfidence = min(d->p1xbratenconfidence, 1000); ++ } ++ else ++ { ++ d->ping = ping; ++ if(expecteddelta) d->p1xbratenconfidence = max(d->p1xbratenconfidence-2, 0); ++ d->extrapings = 0; ++ } + } break; - @@ -77,9 +69,9 @@ Index: src/fpsgame/client.cpp break; Index: src/fpsgame/game.h =================================================================== ---- src/fpsgame/game.h (revision 6488) +--- src/fpsgame/game.h (revision 6502) +++ src/fpsgame/game.h (working copy) -@@ -565,9 +565,10 @@ +@@ -557,9 +557,10 @@ int playermodel; ai::aiinfo *ai; int ownernum, lastnode; diff --git a/src/fpsgame/client.cpp b/src/fpsgame/client.cpp index 03a3692..0ac2d54 100644 --- a/src/fpsgame/client.cpp +++ b/src/fpsgame/client.cpp @@ -120,6 +120,7 @@ namespace game bool senditemstoserver = false, sendcrc = false; // after a map change, since server doesn't have map data int lastping = 0; int lastextraping = 0; + VARP(enablep1xbratendetection, 0, 1, 1); bool connected = false, remote = false, demoplayback = false, gamepaused = false; int sessionid = 0, mastermode = MM_OPEN, gamespeed = 100; @@ -1105,10 +1106,11 @@ namespace game lastping = totalmillis; lastextraping = totalmillis; } - else if(totalmillis-lastextraping>99) // send two extra N_PING packets between each normal one + else if(totalmillis-lastextraping>99) // send two extra N_CLIENTPING packets between each normal one { - putint(p, N_PING); - putint(p, (totalmillis-lastping)/99); // 1, 2, 1, 2, ... + putint(p, N_CLIENTPING); + int delta = ((totalmillis-lastping)/99)%2 ? -1 : 2; + putint(p, player1->ping+delta); // others will see 3 N_CLIENTPINGs from us within 250ms: ping (0ms), ping-1 (99ms), ping+2 (198ms) lastextraping = totalmillis; } sendclientpacket(p.finalize(), 1); @@ -1825,33 +1827,29 @@ namespace game } case N_PONG: - { - int pong = getint(p); - if(pong<3) // extra N_PING response - { - int sign = pong%2 ? -1 : 1; - addmsg(N_CLIENTPING, "i", player1->ping+(sign*pong)); - } - else addmsg(N_CLIENTPING, "i", player1->ping = (player1->ping*5+totalmillis-pong)/6); + addmsg(N_CLIENTPING, "i", player1->ping = (player1->ping*5+totalmillis-getint(p))/6); break; - } + case N_CLIENTPING: { if(!d) return; - int ping = getint(p); - d->extrapings++; - int sign = (d->extrapings)%2 ? -1 : 1; - if(ping==d->ping+sign*(d->extrapings)) - { - d->p1xbratenconfidence += d->extrapings * 2; - d->p1xbratenconfidence = min(d->p1xbratenconfidence, 1000); - } + if(!enablep1xbratendetection) d->ping = getint(p); else { - d->ping = ping; - d->p1xbratenconfidence -= d->extrapings; - d->p1xbratenconfidence = max(d->p1xbratenconfidence, -1000); - d->extrapings = 0; + int ping = getint(p); + int expecteddelta = (d->extrapings+1)%3 ? ((d->extrapings+1)%2 ? -1 : 2) : 0; // 0, -1, 2, 0 -1, 2, ... + if(expecteddelta && ping==d->ping+expecteddelta) + { + d->extrapings++; + d->p1xbratenconfidence += d->extrapings * 2; + d->p1xbratenconfidence = min(d->p1xbratenconfidence, 1000); + } + else + { + d->ping = ping; + if(expecteddelta) d->p1xbratenconfidence = max(d->p1xbratenconfidence-2, 0); + d->extrapings = 0; + } } break; }