diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index 29f6cdc76a..7c2f295b38 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -1490,19 +1490,30 @@ void Network::Server_Send_OBJECTS_LIST( { log_verbose("Server sends objects list with %u items", objects.size()); - bool startOfObjectList = true; - for (auto* object : objects) + if (objects.empty()) { std::unique_ptr packet(NetworkPacket::Allocate()); - *packet << static_cast(NETWORK_COMMAND_OBJECTS_LIST) << startOfObjectList + *packet << static_cast(NETWORK_COMMAND_OBJECTS_LIST) << static_cast(0) << static_cast(objects.size()); - log_verbose("Object %.8s (checksum %x)", object->ObjectEntry.name, object->ObjectEntry.checksum); - packet->Write(reinterpret_cast(object->ObjectEntry.name), 8); - *packet << object->ObjectEntry.checksum << object->ObjectEntry.flags; - connection.QueuePacket(std::move(packet)); - startOfObjectList = false; + } + else + { + for (size_t i = 0; i < objects.size(); ++i) + { + const auto* object = objects[i]; + + std::unique_ptr packet(NetworkPacket::Allocate()); + *packet << static_cast(NETWORK_COMMAND_OBJECTS_LIST) << static_cast(i) + << static_cast(objects.size()); + + log_verbose("Object %.8s (checksum %x)", object->ObjectEntry.name, object->ObjectEntry.checksum); + packet->Write(reinterpret_cast(object->ObjectEntry.name), 8); + *packet << object->ObjectEntry.checksum << object->ObjectEntry.flags; + + connection.QueuePacket(std::move(packet)); + } } } @@ -2571,12 +2582,13 @@ void Network::Client_Handle_OBJECTS_LIST(NetworkConnection& connection, NetworkP { auto& repo = GetContext()->GetObjectRepository(); - bool startOfObjectList = false; + uint32_t index = 0; uint32_t totalObjects = 0; - packet >> startOfObjectList >> totalObjects; + packet >> index >> totalObjects; - if (startOfObjectList) + if (index == 0) { + // Start of objects list. _missingObjects.clear(); } @@ -2588,41 +2600,44 @@ void Network::Client_Handle_OBJECTS_LIST(NetworkConnection& connection, NetworkP return; } - auto name = reinterpret_cast(packet.Read(8)); - // Required, as packet has no null terminators. - std::string s(name, name + 8); - uint32_t checksum = 0; - uint32_t flags = 0; - packet >> checksum >> flags; + if (totalObjects > 0) + { + char objectListMsg[256]; + const uint32_t args[] = { + index + 1, + totalObjects, + }; + format_string(objectListMsg, 256, STR_MULTIPLAYER_RECEIVING_OBJECTS_LIST, &args); - const auto* ori = repo.FindObject(s.c_str()); - // This could potentially request the object if checksums don't match, but since client - // won't replace its version with server-provided one, we don't do that. - if (ori == nullptr) - { - log_verbose("Requesting object %s with checksum %x from server", s.c_str(), checksum); - _missingObjects.push_back(s); - } - else if (ori->ObjectEntry.checksum != checksum || ori->ObjectEntry.flags != flags) - { - log_warning( - "Object %s has different checksum/flags (%x/%x) than server (%x/%x).", s.c_str(), ori->ObjectEntry.checksum, - ori->ObjectEntry.flags, checksum, flags); + auto intent = Intent(WC_NETWORK_STATUS); + intent.putExtra(INTENT_EXTRA_MESSAGE, std::string{ objectListMsg }); + intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { gNetwork.Close(); }); + context_open_intent(&intent); + + auto name = reinterpret_cast(packet.Read(8)); + // Required, as packet has no null terminators. + std::string s(name, name + 8); + uint32_t checksum = 0; + uint32_t flags = 0; + packet >> checksum >> flags; + + const ObjectRepositoryItem* ori = repo.FindObject(s.c_str()); + // This could potentially request the object if checksums don't match, but since client + // won't replace its version with server-provided one, we don't do that. + if (ori == nullptr) + { + log_verbose("Requesting object %s with checksum %x from server", s.c_str(), checksum); + _missingObjects.push_back(s); + } + else if (ori->ObjectEntry.checksum != checksum || ori->ObjectEntry.flags != flags) + { + log_warning( + "Object %s has different checksum/flags (%x/%x) than server (%x/%x).", s.c_str(), ori->ObjectEntry.checksum, + ori->ObjectEntry.flags, checksum, flags); + } } - char objectListMsg[256]; - uint32_t args[] = { - static_cast(_missingObjects.size()), - totalObjects, - }; - format_string(objectListMsg, 256, STR_MULTIPLAYER_RECEIVING_OBJECTS_LIST, &args); - - auto intent = Intent(WC_NETWORK_STATUS); - intent.putExtra(INTENT_EXTRA_MESSAGE, std::string{ objectListMsg }); - intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { gNetwork.Close(); }); - context_open_intent(&intent); - - if (_missingObjects.size() == totalObjects) + if (index + 1 >= totalObjects) { log_verbose("client received object list, it has %u entries", totalObjects); Client_Send_REQUESTMAP(_missingObjects);