// Only use is internal, but let those parameters be available Action* Replay::GetAction() { ASSERT(!is_recorder && replay_state == PLAYING); // Does it contain the 2 elements needed to decode at least // action header? if (MemUsed() > bufsize-sizeof(Action::Header)) { return NULL; } // Read action Action *a = new Action((char*)ptr, NULL); Action::Action_t type = a->GetType(); if (type > Action::ACTION_TIME_VERIFY_SYNC) { Error(Format(_("Malformed replay: action with unknow type %08X"), type)); StopPlaying(); return NULL; } // Move pointer uint size = a->GetSize(); if (MemUsed() > bufsize-size) { Error(Format(_("Malformed replay: action with datasize=%u"), size)); StopPlaying(); return NULL; } ptr += size; MSG_DEBUG("replay", "Read action %s: type=%u length=%i frameless=%i\n", ActionHandler::GetActionName(type).c_str(), type, size, a->IsFrameLess()); return a; }
void LuaInterface::GC() { unsigned int before = MemUsed(); lua_gc(_lua, LUA_GCCOLLECT, 0); unsigned int after = MemUsed(); logdebug("GC: before: %u KB, after: %u KB", before, after); }
bool Replay::SaveReplay(const std::string& name, const char *comment) { ASSERT(is_recorder); FILE *out; #ifdef _WIN32 // Only case where is_wide is true out = _wfopen((wchar_t*)name.c_str(), L"wb"); #else out = fopen(name.c_str(), "wb"); #endif if (!out) return false; // Generate replay info and dump it to file uint32_t total_time = old_time - start_time; ReplayInfo *info = ReplayInfo::ReplayInfoFromCurrent(total_time, comment); if (!info->DumpToFile(out)) { delete info; return false; } delete info; // Save seed Write32(out, seed); // Flush actions recorded #ifdef WMX_LOG uint32_t pos = ftell(out); MSG_DEBUG("replay", "Actions stored at %u on %u bytes in %s, seed %08X\n", pos, MemUsed(), name.c_str(), seed); #endif fwrite(buf, 1, MemUsed(), out); if (count) { count--; MSG_DEBUG("replay", "Storing final calculate frames: %u\n", count); Write32(out, count); } bool good = !ferror(out); fclose(out); // should maybe return length actually written return good; }
void Replay::ChangeBufsize(uint32_t n) { if (n <= bufsize) return; // All data is supposed to be consumed uint32_t offset = (bufsize) ? MemUsed() : 0; buf = (uint8_t*)realloc(buf, n); bufsize = n; ptr = buf + offset; }
// The Replay packet header: // u32: time (ms => 2^16=65s => u16 sufficient) // Packet is directly an action: // . u32 => type // . u32 => length // . data void Replay::StoreAction(const Action* a) { uint size; ASSERT(is_recorder && replay_state==RECORDING); Action::Action_t type = a->GetType(); if ((type!=Action::ACTION_CHAT_INGAME_MESSAGE && a->IsFrameLess()) || type == Action::ACTION_NETWORK_PING || type == Action::ACTION_NETWORK_VERIFY_RANDOM_SYNC || type == Action::ACTION_TIME_VERIFY_SYNC || type == Action::ACTION_RULES_SET_GAME_MODE) return; // Special case to convert into local packet if (type == Action::ACTION_REQUEST_BONUS_BOX_DROP) { // The timestamp shouldn't have moved Action a(Action::ACTION_DROP_BONUS_BOX); StoreAction(&a); return; } size = a->GetSize(); // Enlarge buffer if it can't contain max packet size if (MemUsed() > bufsize - size + 2) ChangeBufsize(bufsize+30000); if (type != Action::ACTION_GAME_CALCULATE_FRAME) { if (count) { count--; MSG_DEBUG("replay", "Calculate frame repeated %u\n", count); // 16 bits is sufficient, around 22 minutes without other actions SDLNet_Write16(count, ptr); ptr += 2; } MSG_DEBUG("replay", "Storing action %s: type=%i length=%i\n", ActionHandler::GetActionName(type).c_str(), type, size); a->Write((char*)ptr); ptr += size; count = 0; } else { if (!count) { // Packet body a->Write((char*)ptr); ptr += size; } count++; } // Check time if (start_time == 0) start_time = GameTime::GetInstance()->Read(); else old_time = GameTime::GetInstance()->Read(); }