mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
wire stream: a teleport's two answer ticks compare with each other, the rest on the script's clock
Aligning every tick after the teleport on its acceptance moved the script's own packets (the button release, the 20-tick position) by the server's lag: on the desktop vanilla got the answer at tick 26, Horizon at 29, and both clients' packets were otherwise identical tick for tick. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
422c36b236
commit
8d09d8b3f2
3 files changed
+29
-6
No files matched your search
@@ -87,6 +87,19 @@ class WireStreamTest(unittest.TestCase):
|
||||
self.assertEqual(a[0][0]['packets'][0][1]['stale'], 0)
|
||||
self.assertEqual(b[0][1]['packets'][0][1]['stale'], 1)
|
||||
|
||||
def test_a_late_answer_compares_with_vanilla_s_answer_and_the_script_keeps_its_clock(self):
|
||||
tick = lambda *names: {'packets': [(n, {}) for n in names], 'frame': [], 'misplaced': []} # noqa
|
||||
# The server's answer (an abort) reaches vanilla in tick 1 and Horizon in tick 2; the script acts in tick 3.
|
||||
vanilla = [tick('punch'), tick('abort', 'punch'), tick('punch'), tick('pos'), tick()]
|
||||
horizon = [tick('punch'), tick('punch'), tick('abort', 'punch'), tick('pos'), tick()]
|
||||
self.assertEqual(wire_stream.compare_answered(vanilla, horizon, 4, 1, 2), [])
|
||||
# What the answer brings is compared: a new dig instead of the abort.
|
||||
restart = [tick('punch'), tick('punch'), tick('start', 'punch'), tick('pos'), tick()]
|
||||
self.assertEqual([d[0] for d in wire_stream.compare_answered(vanilla, restart, 4, 1, 2)], [1])
|
||||
# So is the script's clock: a packet a tick late anywhere else.
|
||||
late = [tick('punch'), tick('punch'), tick('abort', 'punch'), tick(), tick('pos')]
|
||||
self.assertEqual([d[0] for d in wire_stream.compare_answered(vanilla, late, 4, 1, 2)], [3, 4])
|
||||
|
||||
def test_compare_reports_the_first_field_that_differs(self):
|
||||
tick = lambda y: {'packets': [('move_player_pos', {'x': 0.5, 'y': y})], 'frame': [], 'misplaced': []} # noqa
|
||||
diffs = wire_stream.compare([tick(-60.0)], [tick(-60.0000001)], 0)
|
||||
|
||||
@@ -416,18 +416,15 @@ def run(args, out):
|
||||
|
||||
def anchored_diffs(v, h, ticks, anchor, problems):
|
||||
"""wire_stream.compare over the scenario's ticks. With an anchor (a frame packet the server's answer brings,
|
||||
as AcceptTeleportation), the ticks before it compare one to one and the ticks from it on are aligned on it:
|
||||
a loaded server answers a tick or more later in one run than in the other. Numbers are vanilla's ticks."""
|
||||
as AcceptTeleportation), the two ticks that answer arrived in compare with each other
|
||||
(wire_stream.compare_answered). Numbers are vanilla's ticks."""
|
||||
if not anchor:
|
||||
return wire_stream.compare(v, h, ticks)
|
||||
av, ah = wire_stream.first_frame(v, anchor), wire_stream.first_frame(h, anchor)
|
||||
if av is None or ah is None:
|
||||
problems.append(f' no {anchor}: vanilla at tick {av}, Horizon at tick {ah}')
|
||||
return wire_stream.compare(v, h, ticks)
|
||||
# Between the two anchors both clients wait for the server: the ticks after the shorter wait are left out.
|
||||
before = wire_stream.compare(v[:min(av, ah)], h[:min(av, ah)], min(av, ah) - 1)
|
||||
after = wire_stream.compare(v[av:], h[ah:], ticks - max(av, ah))
|
||||
return before + [(i + av, vt, ht) for i, vt, ht in after]
|
||||
return wire_stream.compare_answered(v, h, ticks, av, ah)
|
||||
|
||||
|
||||
def compare(captures, scenarios):
|
||||
|
||||
@@ -203,6 +203,19 @@ def compare(vanilla, horizon, ticks):
|
||||
return out
|
||||
|
||||
|
||||
def compare_answered(vanilla, horizon, ticks, av, ah):
|
||||
"""compare, for a scenario the server answers once (a teleport): the tick each client received the answer
|
||||
in (`av`, `ah`) compares with the other client's, every other tick with the same tick, on the script's
|
||||
clock. A loaded server answers a few ticks later in one run than in the other, while the script's own
|
||||
packets (a button released, the position resent every 20 ticks) keep its clock. Numbers are vanilla's."""
|
||||
out = [d for d in compare(vanilla, horizon, ticks) if d[0] not in (av, ah)]
|
||||
v = vanilla[av]['packets'] if av < len(vanilla) else None
|
||||
h = horizon[ah]['packets'] if ah < len(horizon) else None
|
||||
if v != h:
|
||||
out.append((av, v, h))
|
||||
return sorted(out, key=lambda d: d[0])
|
||||
|
||||
|
||||
def describe(packets):
|
||||
if packets is None:
|
||||
return ' (no such tick)'
|
||||
|
||||
Reference in new issue
Block a user