mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-16 03:23:15 +01:00
Fix client being stuck on empty object list
This commit is contained in:
@@ -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<NetworkPacket> packet(NetworkPacket::Allocate());
|
||||
*packet << static_cast<uint32_t>(NETWORK_COMMAND_OBJECTS_LIST) << startOfObjectList
|
||||
*packet << static_cast<uint32_t>(NETWORK_COMMAND_OBJECTS_LIST) << static_cast<uint32_t>(0)
|
||||
<< static_cast<uint32_t>(objects.size());
|
||||
|
||||
log_verbose("Object %.8s (checksum %x)", object->ObjectEntry.name, object->ObjectEntry.checksum);
|
||||
packet->Write(reinterpret_cast<const uint8_t*>(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<NetworkPacket> packet(NetworkPacket::Allocate());
|
||||
*packet << static_cast<uint32_t>(NETWORK_COMMAND_OBJECTS_LIST) << static_cast<uint32_t>(i)
|
||||
<< static_cast<uint32_t>(objects.size());
|
||||
|
||||
log_verbose("Object %.8s (checksum %x)", object->ObjectEntry.name, object->ObjectEntry.checksum);
|
||||
packet->Write(reinterpret_cast<const uint8_t*>(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<const char*>(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<const char*>(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<uint32_t>(_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);
|
||||
|
||||
Reference in New Issue
Block a user