fix sending of map fragments

This commit is contained in:
Tim Felgentreff 2022-01-15 20:18:07 +01:00
parent c76fffdb79
commit 6a3e5cbb44
2 changed files with 25 additions and 10 deletions

View file

@ -539,7 +539,7 @@ CInitMessage_MapFileFragment::CInitMessage_MapFileFragment(const char *path, con
{
int pathSize = strlen(path);
Assert(pathSize <= 256);
Assert(sizeof(this->Data) < pathSize + 1 + dataSize);
Assert(sizeof(this->Data) >= pathSize + dataSize);
this->PathSize = pathSize;
this->DataSize = dataSize;
memcpy(this->Data, path, pathSize);
@ -547,7 +547,6 @@ CInitMessage_MapFileFragment::CInitMessage_MapFileFragment(const char *path, con
this->FragmentIndex = FragmentIndex;
}
const unsigned char *CInitMessage_MapFileFragment::Serialize() const
{
unsigned char *buf = new unsigned char[Size()];

View file

@ -1096,15 +1096,21 @@ void CServer::Send_Map(const CNetworkHost &host)
void CServer::Send_MapFragment(const CNetworkHost &host, uint32_t fragmentIdx)
{
std::string prefix = NetworkMapName;
size_t loc = NetworkMapName.find(".smp");
if (loc != std::string::npos) {
prefix = NetworkMapName.substr(0, loc);
fs::path prefix = fs::path(NetworkMapName);
while (prefix.stem() != prefix) { // may have .gz, .bz2 ...
prefix = prefix.stem();
}
fs::path mapDirectory(StratagusLibPath);
mapDirectory /= NetworkMapName;
mapDirectory = mapDirectory.parent_path();
std::set<fs::path> sortedFilenames;
for (const auto &entry : fs::directory_iterator(StratagusLibPath)) {
if (entry.path().u8string().rfind(prefix, 0) == 0) {
for (const auto &entry : fs::directory_iterator(mapDirectory)) {
fs::path entryPath(entry.path());
while (entryPath.stem() != entryPath) {
entryPath = entryPath.stem();
}
if (entryPath == prefix) {
sortedFilenames.insert(entry.path());
}
}
@ -1113,14 +1119,24 @@ void CServer::Send_MapFragment(const CNetworkHost &host, uint32_t fragmentIdx)
std::string networkName;
uint32_t fragmentDataSize;
uint32_t fragmentIdxStartForFile = 0;
fs::path libPath(StratagusLibPath);
for (fs::path p : sortedFilenames) {
currentPath = p;
networkName = fs::relative(p, fs::path(StratagusLibPath)).u8string();
// work around fs::relative not being available in some experimental fs impls
fs::path networkPathEnd(p.filename());
fs::path networkPathStart(p.parent_path());
while (networkPathStart != libPath) {
networkPathEnd = *--networkPathStart.end() / networkPathEnd;
networkPathStart = networkPathStart.parent_path();
}
networkName = networkPathEnd.u8string();
fragmentDataSize = sizeof(CInitMessage_MapFileFragment::Data) - networkName.size();
uint32_t fileSize = fs::file_size(p);
uint32_t fragmentCountForFile = (fileSize + fragmentDataSize - 1) / fragmentDataSize;
if (fragmentIdxStartForFile + fragmentCountForFile < fragmentIdx) {
if ((fragmentIdxStartForFile <= fragmentIdx) && (fragmentIdx < fragmentIdxStartForFile + fragmentCountForFile)) {
break;
} else {
// next file starts at the next fragment