| 679 | { |
| 680 | NetworkMessageRaw rawMsg(buffer, bufferSize); |
| 681 | client->DecodeMessage(TO_SERVER, rawMsg); |
| 682 | } |
| 683 | else |
| 684 | { |
| 685 | Fail("Bad CRC for incoming message"); |
| 686 | } |
| 687 | } |
| 688 | |
| 689 | void OnClientRawMagicMessage(int magic, const char* buffer, int bufferSize, void* context) |
| 690 | { |
| 691 | NetworkClient* client = (NetworkClient*)context; |
| 692 | client->OnRawMagicMessage(magic, buffer, bufferSize); |
| 693 | } |
| 694 | |
| 695 | void OnClientSendComplete(DWORD msgID, bool ok, void* context) |
| 696 | { |
| 697 | NetworkClient* client = (NetworkClient*)context; |
| 698 | client->OnSendComplete(msgID, ok); |
| 699 | } |
| 700 | |
| 701 | void NetworkClient::ReceiveSystemMessages() |
| 702 | { |
| 703 | if (!_client) |
| 704 | { |
| 705 | LOG_DEBUG(Network, "[disconnect] ReceiveSystemMessages: _client is null, serverState={}", (int)_serverState); |
| 706 | return; |
| 707 | } |
| 708 | if (_client->IsSessionTerminated()) |
| 709 | { |
| 710 | LOG_INFO(Network, "[disconnect] Session terminated, reason={}", (int)_client->GetWhySessionTerminated()); |
| 711 | _state = NGSNone; |
| 712 | _serverState = NGSNone; |
| 713 | |
| 714 | // In mp-assign mode, exit directly — the display chain may not unwind |
| 715 | // (DestroyAllObjects can null _cameraOn, preventing SimulateHUD calls) |
| 716 | if (!AppConfig::Instance().GetMPAssign().empty()) |
| 717 | { |
| 718 | GApp->m_exitCode = |
| 719 | ResolveMultiplayerAutomationExitCode(GApp->m_exitCode, GApp->m_closeRequest, _serverReachedPlay); |
| 720 | GApp->m_closeRequest = true; |
| 721 | LOG_INFO(Network, "[mp-assign] Session lost, exitCode={}", GApp->m_exitCode); |
| 722 | return; |
| 723 | } |
| 724 | |
| 725 | // GChatList.Add(CCGlobal, nullptr, "Session lost", false, true); |
| 726 | NetTerminationReason reason = _client->GetWhySessionTerminated(); |
| 727 | RString format = LocalizeString(IDS_MP_SESSION_LOST); |
| 728 | RString message = format; |
| 729 | RString name = GetLocalPlayerName(); |
| 730 | const PlayerIdentity* id = FindIdentity(_player); |
| 731 | if (id) |
| 732 | { |
| 733 | name = id->name; |
| 734 | } |
| 735 | switch (reason) |
| 736 | { |
| 737 | case NTRTimeout: |
nothing calls this directly
no test coverage detected