Refactor scenario_write_packed_objects and friends

This commit is contained in:
Michał Janiszewski 2016-10-19 23:36:20 +02:00
parent 65c6cd5412
commit 194c9aed01
7 changed files with 86 additions and 80 deletions

View File

@ -28,18 +28,19 @@
#include "TcpSocket.h"
class NetworkPlayer;
struct ObjectRepositoryItem;
class NetworkConnection final
{
public:
ITcpSocket * Socket = nullptr;
NetworkPacket InboundPacket;
NETWORK_AUTH AuthStatus = NETWORK_AUTH_NONE;
NetworkPlayer * Player = nullptr;
uint32 PingTime = 0;
NetworkKey Key;
std::vector<uint8> Challenge;
std::vector<std::string> RequestedObjects;
ITcpSocket * Socket = nullptr;
NetworkPacket InboundPacket;
NETWORK_AUTH AuthStatus = NETWORK_AUTH_NONE;
NetworkPlayer * Player = nullptr;
uint32 PingTime = 0;
NetworkKey Key;
std::vector<uint8> Challenge;
std::vector<const ObjectRepositoryItem *> RequestedObjects;
NetworkConnection();
~NetworkConnection();

View File

@ -883,16 +883,16 @@ void Network::Server_Send_TOKEN(NetworkConnection& connection)
connection.QueuePacket(std::move(packet));
}
void Network::Server_Send_OBJECTS(NetworkConnection& connection, const rct_object_entry * object_list, uint32 size) const
void Network::Server_Send_OBJECTS(NetworkConnection& connection, const std::vector<const ObjectRepositoryItem *> &objects) const
{
log_verbose("Server sends objects list with %u items", size);
log_verbose("Server sends objects list with %u items", objects.size());
std::unique_ptr<NetworkPacket> packet(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_OBJECTS << size;
for (uint32 i = 0; i < size; i++)
*packet << (uint32)NETWORK_COMMAND_OBJECTS << (uint32)objects.size();
for (size_t i = 0; i < objects.size(); i++)
{
log_verbose("Object %.8s (checksum %x)", object_list[i].name, object_list[i].checksum);
packet->Write((const uint8 *)object_list[i].name, 8);
*packet << object_list[i].checksum << object_list[i].flags;
log_verbose("Object %.8s (checksum %x)", objects[i]->ObjectEntry.name, objects[i]->ObjectEntry.checksum);
packet->Write((const uint8 *)objects[i]->ObjectEntry.name, 8);
*packet << objects[i]->ObjectEntry.checksum << objects[i]->ObjectEntry.flags;
}
connection.QueuePacket(std::move(packet));
}
@ -947,7 +947,7 @@ void Network::Server_Send_MAP(NetworkConnection* connection)
free(header);
}
unsigned char * Network::save_for_network(SDL_RWops *rw_buffer, size_t &out_size, const std::vector<std::string> &objects) const
unsigned char * Network::save_for_network(SDL_RWops *rw_buffer, size_t &out_size, const std::vector<const ObjectRepositoryItem *> &objects) const
{
unsigned char * header = nullptr;
out_size = 0;
@ -1456,9 +1456,8 @@ void Network::Server_Client_Joined(const char* name, const std::string &keyhash,
const char * player_name = (const char *) player->name.c_str();
format_string(text, 256, STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME, &player_name);
chat_history_add(text);
rct_object_entry object_entries[OBJECT_ENTRY_COUNT];
int count = scenario_get_num_packed_objects_to_write(object_entries);
Server_Send_OBJECTS(connection, object_entries, count);
std::vector<const ObjectRepositoryItem *> objects = scenario_get_packable_objects();
Server_Send_OBJECTS(connection, objects);
}
}
@ -1506,12 +1505,19 @@ void Network::Server_Handle_OBJECTS(NetworkConnection& connection, NetworkPacket
uint32 size;
packet >> size;
log_verbose("Client requested %u objects", size);
IObjectRepository * repo = GetObjectRepository();
for (uint32 i = 0; i < size; i++)
{
const char * name = (const char *)packet.Read(8);
// This is required, as packet does not have null terminator
std::string s(name, name + 8);
log_verbose("Client requested object %s", s.c_str());
connection.RequestedObjects.push_back(s);
const ObjectRepositoryItem * item = repo->FindObject(s.c_str());
if (item == nullptr) {
log_warning("Client tried getting non-existent object %s from us.", s.c_str());
} else {
connection.RequestedObjects.push_back(item);
}
}
const char * player_name = (const char *) connection.Player->name.c_str();

View File

@ -83,6 +83,8 @@ enum {
NETWORK_TICK_FLAG_CHECKSUMS = 1 << 0,
};
class ObjectRepositoryItem;
class Network
{
public:
@ -143,7 +145,7 @@ public:
void Server_Send_EVENT_PLAYER_DISCONNECTED(const char *playerName, const char *reason);
void Client_Send_GAMEINFO();
void Client_Send_OBJECTS(const std::vector<std::string> &objects);
void Server_Send_OBJECTS(NetworkConnection& connection, const rct_object_entry *object_list, uint32 size) const;
void Server_Send_OBJECTS(NetworkConnection& connection, const std::vector<const ObjectRepositoryItem *> &objects) const;
std::vector<std::unique_ptr<NetworkPlayer>> player_list;
std::vector<std::unique_ptr<NetworkGroup>> group_list;
@ -241,7 +243,7 @@ private:
void Client_Handle_OBJECTS(NetworkConnection& connection, NetworkPacket& packet);
void Server_Handle_OBJECTS(NetworkConnection& connection, NetworkPacket& packet);
unsigned char * save_for_network(SDL_RWops *buffer, size_t &out_size, const std::vector<std::string> &objects) const;
unsigned char * save_for_network(SDL_RWops *buffer, size_t &out_size, const std::vector<const ObjectRepositoryItem *> &objects) const;
};
namespace Convert

View File

@ -48,7 +48,6 @@ extern "C"
S6Exporter::S6Exporter()
{
ExportObjects = false;
RemoveTracklessRides = false;
memset(&_s6, 0, sizeof(_s6));
}
@ -92,7 +91,7 @@ void S6Exporter::SaveScenario(SDL_RWops *rw)
void S6Exporter::Save(SDL_RWops * rw, bool isScenario)
{
_s6.header.type = isScenario ? S6_TYPE_SCENARIO : S6_TYPE_SAVEDGAME;
_s6.header.num_packed_objects = ExportObjects ? scenario_get_num_packed_objects_to_write(nullptr) : uint16(ExportObjectsList.size());
_s6.header.num_packed_objects = uint16(ExportObjectsList.size());
_s6.header.version = S6_RCT2_VERSION;
_s6.header.magic_number = S6_MAGIC_NUMBER;
@ -123,10 +122,11 @@ void S6Exporter::Save(SDL_RWops * rw, bool isScenario)
SDL_RWwrite(rw, buffer, encodedLength, 1);
}
log_warning("exporting %u objects", _s6.header.num_packed_objects);
// 2: Write packed objects
if (_s6.header.num_packed_objects > 0)
{
if (!scenario_write_packed_objects(rw, ExportObjectsList, ExportObjects))
if (!scenario_write_packed_objects(rw, ExportObjectsList))
{
free(buffer);
throw Exception("Unable to pack objects.");
@ -228,11 +228,6 @@ void S6Exporter::Save(SDL_RWops * rw, bool isScenario)
}
void S6Exporter::Export()
{
Export(std::vector<std::string>(), true);
}
void S6Exporter::Export(const std::vector<std::string> &objects, bool export_all)
{
_s6.info = gS6Info;
@ -337,7 +332,7 @@ void S6Exporter::Export(const std::vector<std::string> &objects, bool export_all
_s6.current_expenditure = gCurrentExpenditure;
_s6.current_profit = gCurrentProfit;
_s6.weekly_profit_average_dividend = gWeeklyProfitAverageDividend;
_s6.weekly_profit_average_divisor = gWeeklyProfitAverageDivisor;
_s6.weekly_profit_average_divisor = gWeeklyProfitAverageDivisor;
// pad_0135833A
memcpy(_s6.weekly_profit_history, gWeeklyProfitHistory, sizeof(_s6.weekly_profit_history));
@ -460,7 +455,7 @@ uint32 S6Exporter::GetLoanHash(money32 initialCash, money32 bankLoan, uint32 max
// Save game state without modifying any of the state for multiplayer
int scenario_save_network(SDL_RWops * rw, const std::vector<std::string> &objects)
int scenario_save_network(SDL_RWops * rw, const std::vector<const ObjectRepositoryItem *> &objects)
{
viewport_set_saved_view();
@ -468,7 +463,6 @@ int scenario_save_network(SDL_RWops * rw, const std::vector<std::string> &object
auto s6exporter = new S6Exporter();
try
{
s6exporter->ExportObjects = false;
s6exporter->ExportObjectsList = objects;
s6exporter->Export();
s6exporter->SaveGame(rw);
@ -513,37 +507,58 @@ int scenario_save_network(SDL_RWops * rw, const std::vector<std::string> &object
return 1;
}
int scenario_write_packed_objects(SDL_RWops* rw, std::vector<std::string> &objects, bool export_all)
static bool object_is_custom(const ObjectRepositoryItem * object)
{
Guard::ArgumentNotNull(object);
// Validate the object is not one from base game or expansion pack
return (object->LoadedObject != nullptr &&
object->LoadedObject->GetLegacyData() != nullptr
&& !(object->ObjectEntry.flags & 0xF0));
}
int scenario_write_packed_objects(SDL_RWops* rw, std::vector<const ObjectRepositoryItem *> &objects)
{
log_verbose("exporting packed objects");
if (export_all)
for (const auto &object : objects)
{
log_verbose("exporting all");
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++) {
const rct_object_entry *entry = get_loaded_object_entry(i);
void *entryData = get_loaded_object_chunk(i);
if (entryData != (void*)-1 && !(entry->flags & 0xF0)) {
if (!object_saved_packed(rw, entry)) {
return 0;
}
Guard::ArgumentNotNull(object);
log_verbose("exporting object %.8s", object->ObjectEntry.name);
if (object_is_custom(object))
{
if (!object_saved_packed(rw, &object->ObjectEntry))
{
return 0;
}
}
} else {
IObjectRepository * repo = GetObjectRepository();
for (const auto &name : objects)
else
{
log_verbose("exporting object %s", name.c_str());
const ObjectRepositoryItem *item = repo->FindObject(name.c_str());
if (intptr_t(item->LoadedObject->GetLegacyData()) != -1 && !(item->ObjectEntry.flags & 0xF0)) {
if (!object_saved_packed(rw, &item->ObjectEntry)) {
return 0;
}
}
log_warning("Refusing to pack vanilla/expansion object \"%s\"", object->ObjectEntry.name);
}
}
return 1;
}
/**
*
* rct2: 0x006AA244
*/
std::vector<const ObjectRepositoryItem *> scenario_get_packable_objects()
{
std::vector<const ObjectRepositoryItem *> objects;
IObjectRepository * repo = GetObjectRepository();
for (size_t i = 0; i < repo->GetNumObjects(); i++)
{
const ObjectRepositoryItem *item = &repo->GetObjects()[i];
// Validate the object is not one from base game or expansion pack
if (object_is_custom(item))
{
objects.push_back(item);
}
}
return objects;
}
extern "C"
{
enum {
@ -582,7 +597,9 @@ extern "C"
auto s6exporter = new S6Exporter();
try
{
s6exporter->ExportObjects = (flags & S6_SAVE_FLAG_EXPORT);
if (flags & S6_SAVE_FLAG_EXPORT) {
s6exporter->ExportObjectsList = scenario_get_packable_objects();
}
s6exporter->RemoveTracklessRides = true;
s6exporter->Export();
if (flags & S6_SAVE_FLAG_SCENARIO)

View File

@ -27,8 +27,11 @@ extern "C"
#include "../object_list.h"
}
int scenario_save_network(SDL_RWops* rw, const std::vector<std::string> &objects);
int scenario_write_packed_objects(SDL_RWops* rw, std::vector<std::string> &s, bool export_all);
class ObjectRepositoryItem;
int scenario_save_network(SDL_RWops* rw, const std::vector<const ObjectRepositoryItem *> &objects);
int scenario_write_packed_objects(SDL_RWops* rw, std::vector<const ObjectRepositoryItem *> &objects);
std::vector<const ObjectRepositoryItem *> scenario_get_packable_objects();
/**
* Class to export RollerCoaster Tycoon 2 scenarios (*.SC6) and saved games (*.SV6).
@ -36,9 +39,8 @@ int scenario_write_packed_objects(SDL_RWops* rw, std::vector<std::string> &s, bo
class S6Exporter final
{
public:
bool ExportObjects;
bool RemoveTracklessRides;
std::vector<std::string> ExportObjectsList;
std::vector<const ObjectRepositoryItem *> ExportObjectsList;
S6Exporter();
@ -47,7 +49,6 @@ public:
void SaveScenario(const utf8 * path);
void SaveScenario(SDL_RWops *rw);
void Export();
void Export(const std::vector<std::string> &objects, bool export_all = false);
private:
rct_s6_data _s6;

View File

@ -685,26 +685,6 @@ int scenario_prepare_for_save()
return 1;
}
/**
*
* rct2: 0x006AA244
*/
int scenario_get_num_packed_objects_to_write(rct_object_entry * object_list)
{
int count = 0;
for (int i = 0; i < OBJECT_ENTRY_COUNT; i++) {
const rct_object_entry *entry = get_loaded_object_entry(i);
void *entryData = get_loaded_object_chunk(i);
if (entryData != (void*)-1 && !(entry->flags & 0xF0)) {
if (object_list != NULL) {
object_list[count] = *entry;
}
count++;
}
}
return count;
}
/**
*
* rct2: 0x006AA039

View File

@ -416,7 +416,6 @@ unsigned int scenario_rand();
unsigned int scenario_rand_max(unsigned int max);
int scenario_prepare_for_save();
int scenario_save(SDL_RWops* rw, int flags);
int scenario_get_num_packed_objects_to_write(rct_object_entry *object_list);
void scenario_remove_trackless_rides(rct_s6_data *s6);
void scenario_fix_ghosts(rct_s6_data *s6);
void scenario_set_filename(const char *value);