Allow pre-ready heartbeat pings and include local doc updates

This commit is contained in:
Jage9
2026-02-28 21:20:59 -05:00
parent aa5bcd12cc
commit a57e48a265
5 changed files with 37 additions and 12 deletions

View File

@@ -3,6 +3,7 @@
{ {
"date": "February 28, 2026", "date": "February 28, 2026",
"items": [ "items": [
"Added Item Management menu with z, to transfer items or delete them. Shift+D is gone now.",
"Added initial delay and loop delay for widgets, letting you do looped audio that has pauses." "Added initial delay and loop delay for widgets, letting you do looped audio that has pauses."
] ]
}, },

View File

@@ -88,10 +88,6 @@
{ {
"keys": "Enter", "keys": "Enter",
"description": "Use item" "description": "Use item"
},
{
"keys": "Piano mode",
"description": "When using a piano: press question mark for piano help. 1-9 (and 0 for the 10th slot) changes instrument, -/= changes octave, ASDFGHJKL;' plays C major notes, WETYUOP] plays sharps, Z starts/pauses/resumes recording, X plays recording, Enter plays demo, C stops demo/playback/recording, Escape exits"
} }
] ]
}, },

View File

@@ -1,5 +1,5 @@
// Maintainer-controlled web client version. // Maintainer-controlled web client version.
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2) // Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
window.CHGRID_WEB_VERSION = "2026.03.01 R330"; window.CHGRID_WEB_VERSION = "2026.03.01 R331";
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid. // Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
window.CHGRID_TIME_ZONE = "America/Detroit"; window.CHGRID_TIME_ZONE = "America/Detroit";

View File

@@ -2094,6 +2094,13 @@ class SignalingServer:
await self._activate_authenticated_client(client) await self._activate_authenticated_client(client)
return return
if isinstance(packet, PingPacket):
await self._send(
client.websocket,
PongPacket(type="pong", clientSentAt=packet.clientSentAt),
)
return
if not client.world_ready: if not client.world_ready:
PACKET_LOGGER.info("ignoring pre-ready packet id=%s type=%s", client.id, packet.type) PACKET_LOGGER.info("ignoring pre-ready packet id=%s type=%s", client.id, packet.type)
return return
@@ -2332,13 +2339,6 @@ class SignalingServer:
) )
return return
if isinstance(packet, PingPacket):
await self._send(
client.websocket,
PongPacket(type="pong", clientSentAt=packet.clientSentAt),
)
return
if isinstance(packet, ItemAddPacket): if isinstance(packet, ItemAddPacket):
if not self._client_has_permission(client, "item.create"): if not self._client_has_permission(client, "item.create"):
await self._send_item_result(client, False, "add", "Not authorized to create items.") await self._send_item_result(client, False, "add", "Not authorized to create items.")

View File

@@ -314,6 +314,34 @@ async def test_auth_login_defers_activation_until_welcome_ready(monkeypatch: pyt
assert any("has logged in" in getattr(packet, "message", "") for packet in broadcast_payloads) assert any("has logged in" in getattr(packet, "message", "") for packet in broadcast_payloads)
@pytest.mark.asyncio
async def test_ping_works_before_welcome_ready(monkeypatch: pytest.MonkeyPatch) -> None:
server = SignalingServer("127.0.0.1", 8765, None, None)
username = f"ping_{uuid.uuid4().hex[:8]}"
server.auth_service.register(username, "password99")
ws = _fake_ws()
client = ClientConnection(websocket=ws, id="u1", nickname="tester")
send_payloads: list[object] = []
async def fake_send(websocket: ServerConnection, packet: object) -> None:
send_payloads.append(packet)
monkeypatch.setattr(server, "_send", fake_send)
await server._handle_message(
client,
json.dumps({"type": "auth_login", "username": username, "password": "password99"}),
)
assert client.world_ready is False
await server._handle_message(client, json.dumps({"type": "ping", "clientSentAt": -1}))
pong_packets = [packet for packet in send_payloads if getattr(packet, "type", "") == "pong"]
assert pong_packets
assert pong_packets[-1].clientSentAt == -1
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_auth_resume_failure_message_is_generic(monkeypatch: pytest.MonkeyPatch) -> None: async def test_auth_resume_failure_message_is_generic(monkeypatch: pytest.MonkeyPatch) -> None:
server = SignalingServer("127.0.0.1", 8765, None, None) server = SignalingServer("127.0.0.1", 8765, None, None)