ws2_32: HACK: Hold a BattlEye ack for The Crew Motorfest. - #352
ws2_32: HACK: Hold a BattlEye ack for The Crew Motorfest.#352PhialsBasement wants to merge 1 commit into
Conversation
The Crew Motorfest (appid 2698940) resends its BattlEye report every 7s until the server kicks it at 210s, whenever it sees the ack of the 94 byte control record sent before the report ahead of fragment 0. Leave that ack queued in the socket until fragment 0 has been sent. ValveSoftware/Proton#9119
|
Well, this is not a matter of bargaining the number of lines. TBH we don't have any criteria for hack acceptance, if anything, we try to avoid adding Proton and game specific hacks whenever possible and work on proper fixes itself in the right place so that improves Proton and makes it more compatible or performant for any games instead of making it worse by slapping some ad-hoc tweaks which happen to help. The hack still fiddles with ad-hoc timing based on ad-hoc conditions which are based are gory specifics of internal game and BE functioning. It perhaps would be very interesting if you could elaborate a bit more / in a stricter way on those conditions, I can't say I am following exactly what is the failure condition, how do you identify the type of package and what do you think is expected result with quicker or slower data send request. Maybe it will be useful for future reference. Or what if mentioned 500ms, depending on some details, is something actually improvable in Proton (the time actually involves some Wine calls) or maybe on BE side. In that case that would maybe open the possibility for an improvement outside of any game specific hacks. |
|
WRT the details, note that on Windows the initial pattern, without artificial packet delays, is the same as I see on Proton here, it is interesting, if you know that, how exactly things go different on Proton, in the presence of packet delays when things do look different vs Windows in terms of resends / failure. |
By payload size on port 4000. 1038 in is the BE query, 94 out is a control record sent 10 to 16 ms after it, 62 in with byte 2 = 0xdb is its ack, 1118 out are the 20 report fragments on a 100 ms tick, the first one 486 to 524 ms after the record.
The client seeing that ack before it sends fragment 0. It then resends the whole report every 6.9 s until the server terminates at +209.5 s. On Proton at 220 ms RTT the ack lands 280 ms before fragment 0 every time. If the ack reaches the client within about 80 ms after fragment 0 (the hook, or tc delaying the record 330 ms) it sends the report twice and stops. 206 ms after fragment 0 is too late and the loop returns. The same six fragments are dropped either way.
The 500 ms is BE building the report. perf over that window shows the main thread busy 410 ms with 716 of 842 samples in BEClient_x64.dll and 19 syscalls total, so no Wine call is on that path. ((unless you have contacts over at BE))
Your Windows client sent once and stopped, so its ack arrived after fragment 0, meaning the Windows BE client builds the report faster than the added RTT. The gap from the outgoing 94 byte record to the first outgoing 1118 in your capture would confirm that. |
|
No bargaining intended on the line count btw, I hated the 319 line version more than you did. Mostly I wanted to get to the bottom of it, and I finally finished a summit in one sitting yesterday, so the week wasn't wasted either way. |
The Crew Motorfest (appid 2698940) resends its BattlEye report every 7s until the server kicks it at 210s, whenever it sees the ack of the 94 byte control record sent before the report ahead of fragment 0. Leave that ack queued in the socket until fragment 0 has been sent.
ValveSoftware/Proton#9119
@gofman reworked this after digging further, turns out the missing fragments were never what got you kicked. The client resends the whole report every 7s if it sees the ack of the 94 byte control record before fragment 0 goes out, and the server drops it after 31 resends. On Windows the ack lands after fragment 0 because BE builds the report faster, which is why you saw it send once and stop. On Proton BEClient spends ~500ms on the main thread building it (perf, Wine is 3% of that), so the ack always lands first. So the hack is now just leave that one ack queued until fragment 0 has been sent. 56 lines, no RTT or timing involved, appid gated, once per session, and inert if any packet size changes. Should fulfill the criteria since its fairly maintainable.