1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Mediate objects to send over from server

This commit is contained in:
Michał Janiszewski
2016-10-14 07:29:45 +02:00
parent f3a2eb0247
commit 5ebc95e0b2
9 changed files with 188 additions and 79 deletions

View File

@@ -39,6 +39,7 @@ public:
uint32 PingTime = 0;
NetworkKey Key;
std::vector<uint8> Challenge;
std::vector<std::string> RequestedObjects;
NetworkConnection();
~NetworkConnection();

View File

@@ -68,6 +68,7 @@ bool NetworkPacket::CommandRequiresAuth()
case NETWORK_COMMAND_AUTH:
case NETWORK_COMMAND_TOKEN:
case NETWORK_COMMAND_GAMEINFO:
case NETWORK_COMMAND_OBJECTS:
return false;
default:
return true;

View File

@@ -56,6 +56,7 @@ enum NETWORK_COMMAND
NETWORK_COMMAND_GROUPLIST,
NETWORK_COMMAND_EVENT,
NETWORK_COMMAND_TOKEN,
NETWORK_COMMAND_OBJECTS,
NETWORK_COMMAND_MAX,
NETWORK_COMMAND_INVALID = -1
};

View File

@@ -50,6 +50,8 @@ int _pickup_peep_old_x = SPRITE_LOCATION_NULL;
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../core/Util.hpp"
#include "../object/ObjectRepository.h"
#include "../rct2/S6Exporter.h"
extern "C" {
#include "../config.h"
@@ -116,6 +118,7 @@ Network::Network()
client_command_handlers[NETWORK_COMMAND_EVENT] = &Network::Client_Handle_EVENT;
client_command_handlers[NETWORK_COMMAND_GAMEINFO] = &Network::Client_Handle_GAMEINFO;
client_command_handlers[NETWORK_COMMAND_TOKEN] = &Network::Client_Handle_TOKEN;
client_command_handlers[NETWORK_COMMAND_OBJECTS] = &Network::Client_Handle_OBJECTS;
server_command_handlers.resize(NETWORK_COMMAND_MAX, 0);
server_command_handlers[NETWORK_COMMAND_AUTH] = &Network::Server_Handle_AUTH;
server_command_handlers[NETWORK_COMMAND_CHAT] = &Network::Server_Handle_CHAT;
@@ -123,6 +126,7 @@ Network::Network()
server_command_handlers[NETWORK_COMMAND_PING] = &Network::Server_Handle_PING;
server_command_handlers[NETWORK_COMMAND_GAMEINFO] = &Network::Server_Handle_GAMEINFO;
server_command_handlers[NETWORK_COMMAND_TOKEN] = &Network::Server_Handle_TOKEN;
server_command_handlers[NETWORK_COMMAND_OBJECTS] = &Network::Server_Handle_OBJECTS;
OpenSSL_add_all_algorithms();
}
@@ -858,6 +862,19 @@ void Network::Client_Send_AUTH(const char* name, const char* password, const cha
server_connection.QueuePacket(std::move(packet));
}
void Network::Client_Send_OBJECTS(const std::vector<std::string> &objects)
{
log_verbose("client requests %u objects", uint32(objects.size()));
std::unique_ptr<NetworkPacket> packet(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_OBJECTS << (uint32)objects.size();
for (uint32 i = 0; i < objects.size(); i++)
{
log_verbose("client requests object %s", objects[i].c_str());
packet->Write((const uint8 *)objects[i].c_str(), 8);
}
server_connection.QueuePacket(std::move(packet));
}
void Network::Server_Send_TOKEN(NetworkConnection& connection)
{
std::unique_ptr<NetworkPacket> packet(NetworkPacket::Allocate());
@@ -866,6 +883,20 @@ void Network::Server_Send_TOKEN(NetworkConnection& connection)
connection.QueuePacket(std::move(packet));
}
void Network::Server_Send_OBJECTS(NetworkConnection& connection, rct_object_entry * object_list, uint32 size)
{
log_verbose("Server sends objects list with %u items", size);
std::unique_ptr<NetworkPacket> packet(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_OBJECTS << size;
for (uint32 i = 0; i < 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;
}
connection.QueuePacket(std::move(packet));
}
void Network::Server_Send_AUTH(NetworkConnection& connection)
{
uint8 new_playerid = 0;
@@ -894,7 +925,7 @@ void Network::Server_Send_MAP(NetworkConnection* connection)
SDL_RWops* rw = SDL_RWFromFP(temp, SDL_TRUE);
size_t out_size;
unsigned char *header;
header = save_for_network(rw, out_size);
header = save_for_network(rw, out_size, connection->RequestedObjects);
SDL_RWclose(rw);
if (header == nullptr) {
connection->SetLastDisconnectReason(STR_MULTIPLAYER_CONNECTION_CLOSED);
@@ -916,13 +947,13 @@ void Network::Server_Send_MAP(NetworkConnection* connection)
free(header);
}
unsigned char * Network::save_for_network(SDL_RWops *rw_buffer, size_t &out_size) const
unsigned char * Network::save_for_network(SDL_RWops *rw_buffer, size_t &out_size, const std::vector<std::string> &objects) const
{
unsigned char * header = nullptr;
out_size = 0;
bool RLEState = gUseRLE;
gUseRLE = false;
scenario_save_network(rw_buffer);
scenario_save_network(rw_buffer, objects);
gUseRLE = RLEState;
int size = (int)SDL_RWtell(rw_buffer);
std::vector<uint8> buffer(size);
@@ -1439,9 +1470,49 @@ void Network::Server_Handle_TOKEN(NetworkConnection& connection, NetworkPacket&
for (int i = 0; i < token_size; i++) {
connection.Challenge[i] = (uint8)(rand() & 0xff);
}
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);
Server_Send_TOKEN(connection);
}
void Network::Client_Handle_OBJECTS(NetworkConnection& connection, NetworkPacket& packet)
{
IObjectRepository * repo = GetObjectRepository();
uint32 size;
packet >> size;
log_verbose("client received object list, it has %u entries", size);
std::vector<std::string> requested_objects;
for (uint32 i = 0; i < size; i++)
{
const char * name = (const char *)packet.Read(8);
uint32 checksum;
packet >> checksum;
std::string s(name, name + 8);
const ObjectRepositoryItem * ori = repo->FindObject(s.c_str());
if (ori == nullptr || ori->ObjectEntry.checksum != checksum) {
log_verbose("Requesting object %s with checksum %x from server",
s.c_str(), checksum);
requested_objects.push_back(s);
}
}
Client_Send_OBJECTS(requested_objects);
}
void Network::Server_Handle_OBJECTS(NetworkConnection& connection, NetworkPacket& packet)
{
uint32 size;
packet >> size;
log_verbose("Client requested %u objects", size);
for (uint32 i = 0; i < size; i++)
{
const char * name = (const char *)packet.Read(8);
std::string s(name, name + 8);
log_verbose("Client requested object %s", s.c_str());
connection.RequestedObjects.push_back(s);
}
}
void Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet)
{
if (connection.AuthStatus != NETWORK_AUTH_OK) {

View File

@@ -142,6 +142,8 @@ public:
void Server_Send_EVENT_PLAYER_JOINED(const char *playerName);
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, rct_object_entry * object_list, uint32 size);
std::vector<std::unique_ptr<NetworkPlayer>> player_list;
std::vector<std::unique_ptr<NetworkGroup>> group_list;
@@ -236,8 +238,10 @@ private:
void Client_Handle_EVENT(NetworkConnection& connection, NetworkPacket& packet);
void Client_Handle_TOKEN(NetworkConnection& connection, NetworkPacket& packet);
void Server_Handle_TOKEN(NetworkConnection& connection, NetworkPacket& packet);
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;
unsigned char * save_for_network(SDL_RWops *buffer, size_t &out_size, const std::vector<std::string> &objects) const;
};
namespace Convert

View File

@@ -17,6 +17,8 @@
#include "../core/Exception.hpp"
#include "../core/IStream.hpp"
#include "../core/String.hpp"
#include "../object/ObjectRepository.h"
#include "../object/Object.h"
#include "S6Exporter.h"
extern "C"
@@ -90,7 +92,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() : 0;
_s6.header.num_packed_objects = !ExportObjects ? uint16(ExportObjectsList.size()) : scenario_get_num_packed_objects_to_write(nullptr);
_s6.header.version = S6_RCT2_VERSION;
_s6.header.magic_number = S6_MAGIC_NUMBER;
@@ -124,7 +126,7 @@ void S6Exporter::Save(SDL_RWops * rw, bool isScenario)
// 2: Write packed objects
if (_s6.header.num_packed_objects > 0)
{
if (!scenario_write_packed_objects(rw))
if (!scenario_write_packed_objects(rw, ExportObjectsList, ExportObjects))
{
free(buffer);
throw Exception("Unable to pack objects.");
@@ -226,6 +228,11 @@ 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;
@@ -451,6 +458,92 @@ uint32 S6Exporter::GetLoanHash(money32 initialCash, money32 bankLoan, uint32 max
return value;
}
// Save game state without modifying any of the state for multiplayer
int scenario_save_network(SDL_RWops * rw, const std::vector<std::string> &objects)
{
viewport_set_saved_view();
bool result = false;
auto s6exporter = new S6Exporter();
try
{
s6exporter->ExportObjects = false;
s6exporter->ExportObjectsList = objects;
s6exporter->Export();
s6exporter->SaveGame(rw);
result = true;
}
catch (Exception)
{
}
delete s6exporter;
if (!result)
{
return 0;
}
// Write other data not in normal save files
SDL_RWwrite(rw, gSpriteSpatialIndex, 0x10001 * sizeof(uint16), 1);
SDL_WriteLE32(rw, gGamePaused);
SDL_WriteLE32(rw, _guestGenerationProbability);
SDL_WriteLE32(rw, _suggestedGuestMaximum);
SDL_WriteU8(rw, gCheatsSandboxMode);
SDL_WriteU8(rw, gCheatsDisableClearanceChecks);
SDL_WriteU8(rw, gCheatsDisableSupportLimits);
SDL_WriteU8(rw, gCheatsDisableTrainLengthLimit);
SDL_WriteU8(rw, gCheatsEnableChainLiftOnAllTrack);
SDL_WriteU8(rw, gCheatsShowAllOperatingModes);
SDL_WriteU8(rw, gCheatsShowVehiclesFromOtherTrackTypes);
SDL_WriteU8(rw, gCheatsFastLiftHill);
SDL_WriteU8(rw, gCheatsDisableBrakesFailure);
SDL_WriteU8(rw, gCheatsDisableAllBreakdowns);
SDL_WriteU8(rw, gCheatsUnlockAllPrices);
SDL_WriteU8(rw, gCheatsBuildInPauseMode);
SDL_WriteU8(rw, gCheatsIgnoreRideIntensity);
SDL_WriteU8(rw, gCheatsDisableVandalism);
SDL_WriteU8(rw, gCheatsDisableLittering);
SDL_WriteU8(rw, gCheatsNeverendingMarketing);
SDL_WriteU8(rw, gCheatsFreezeClimate);
SDL_WriteU8(rw, gCheatsDisablePlantAging);
SDL_WriteU8(rw, gCheatsAllowArbitraryRideTypeChanges);
gfx_invalidate_screen();
return 1;
}
int scenario_write_packed_objects(SDL_RWops* rw, std::vector<std::string> &objects, bool export_all)
{
log_verbose("exporting packed objects");
if (export_all)
{
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;
}
}
}
} else {
IObjectRepository * repo = GetObjectRepository();
for (const auto &name : objects)
{
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;
}
}
}
}
return 1;
}
extern "C"
{
enum {
@@ -515,57 +608,4 @@ extern "C"
}
return result;
}
// Save game state without modifying any of the state for multiplayer
int scenario_save_network(SDL_RWops * rw)
{
viewport_set_saved_view();
bool result = false;
auto s6exporter = new S6Exporter();
try
{
s6exporter->ExportObjects = true;
s6exporter->Export();
s6exporter->SaveGame(rw);
result = true;
}
catch (Exception)
{
}
delete s6exporter;
if (!result)
{
return 0;
}
// Write other data not in normal save files
SDL_RWwrite(rw, gSpriteSpatialIndex, 0x10001 * sizeof(uint16), 1);
SDL_WriteLE32(rw, gGamePaused);
SDL_WriteLE32(rw, _guestGenerationProbability);
SDL_WriteLE32(rw, _suggestedGuestMaximum);
SDL_WriteU8(rw, gCheatsSandboxMode);
SDL_WriteU8(rw, gCheatsDisableClearanceChecks);
SDL_WriteU8(rw, gCheatsDisableSupportLimits);
SDL_WriteU8(rw, gCheatsDisableTrainLengthLimit);
SDL_WriteU8(rw, gCheatsEnableChainLiftOnAllTrack);
SDL_WriteU8(rw, gCheatsShowAllOperatingModes);
SDL_WriteU8(rw, gCheatsShowVehiclesFromOtherTrackTypes);
SDL_WriteU8(rw, gCheatsFastLiftHill);
SDL_WriteU8(rw, gCheatsDisableBrakesFailure);
SDL_WriteU8(rw, gCheatsDisableAllBreakdowns);
SDL_WriteU8(rw, gCheatsUnlockAllPrices);
SDL_WriteU8(rw, gCheatsBuildInPauseMode);
SDL_WriteU8(rw, gCheatsIgnoreRideIntensity);
SDL_WriteU8(rw, gCheatsDisableVandalism);
SDL_WriteU8(rw, gCheatsDisableLittering);
SDL_WriteU8(rw, gCheatsNeverendingMarketing);
SDL_WriteU8(rw, gCheatsFreezeClimate);
SDL_WriteU8(rw, gCheatsDisablePlantAging);
SDL_WriteU8(rw, gCheatsAllowArbitraryRideTypeChanges);
gfx_invalidate_screen();
return 1;
}
}

View File

@@ -16,6 +16,9 @@
#pragma once
#include <string>
#include <vector>
#include "../common.h"
extern "C"
@@ -24,6 +27,9 @@ 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 to export RollerCoaster Tycoon 2 scenarios (*.SC6) and saved games (*.SV6).
*/
@@ -32,6 +38,7 @@ class S6Exporter final
public:
bool ExportObjects;
bool RemoveTracklessRides;
std::vector<std::string> ExportObjectsList;
S6Exporter();
@@ -40,6 +47,7 @@ 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

@@ -696,30 +696,15 @@ int scenario_get_num_packed_objects_to_write(rct_object_entry * object_list)
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: 0x006AA26E
*/
int scenario_write_packed_objects(SDL_RWops* rw)
{
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;
}
}
}
return 1;
}
/**
*
* rct2: 0x006AA039

View File

@@ -416,9 +416,7 @@ 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_save_network(SDL_RWops* rw);
int scenario_get_num_packed_objects_to_write(rct_object_entry *object_list);
int scenario_write_packed_objects(SDL_RWops* rw);
void scenario_remove_trackless_rides(rct_s6_data *s6);
void scenario_fix_ghosts(rct_s6_data *s6);
void scenario_set_filename(const char *value);