mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #5194 from IntelOrca/refactor/more-istream
Use IStream instead of SDL in more places
This commit is contained in:
commit
c4e89278c1
|
@ -21,6 +21,7 @@
|
|||
#include "../core/Guard.hpp"
|
||||
#include "../core/Path.hpp"
|
||||
#include "../ParkImporter.h"
|
||||
#include "../rct2/S6Exporter.h"
|
||||
#include "CommandLine.hpp"
|
||||
|
||||
extern "C"
|
||||
|
@ -102,74 +103,56 @@ exitcode_t CommandLine::HandleCommandConvert(CommandLineArgEnumerator * enumerat
|
|||
WriteConvertFromAndToMessage(sourceFileType, destinationFileType);
|
||||
|
||||
gOpenRCT2Headless = true;
|
||||
if (!openrct2_initialise()) {
|
||||
if (!openrct2_initialise())
|
||||
{
|
||||
Console::Error::WriteLine("Error while initialising OpenRCT2.");
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
|
||||
if (sourceFileType == FILE_EXTENSION_SV4 ||
|
||||
sourceFileType == FILE_EXTENSION_SC4)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
auto s4Importer = std::unique_ptr<IParkImporter>(ParkImporter::CreateS4());
|
||||
if (sourceFileType == FILE_EXTENSION_SC4)
|
||||
{
|
||||
s4Importer->LoadScenario(sourcePath);
|
||||
}
|
||||
if (sourceFileType == FILE_EXTENSION_SV4)
|
||||
{
|
||||
s4Importer->LoadSavedGame(sourcePath);
|
||||
}
|
||||
|
||||
s4Importer->Import();
|
||||
|
||||
if (sourceFileType == FILE_EXTENSION_SC4)
|
||||
{
|
||||
// We are converting a scenario, so reset the park
|
||||
scenario_begin();
|
||||
}
|
||||
}
|
||||
catch (const Exception &ex)
|
||||
{
|
||||
Console::Error::WriteLine(ex.GetMessage());
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
auto importer = std::unique_ptr<IParkImporter>(ParkImporter::Create(sourcePath));
|
||||
importer->Load(sourcePath);
|
||||
importer->Import();
|
||||
}
|
||||
else
|
||||
catch (const Exception &ex)
|
||||
{
|
||||
if (sourceFileType == FILE_EXTENSION_SC6)
|
||||
{
|
||||
scenario_load_and_play_from_path(sourcePath);
|
||||
}
|
||||
if (sourceFileType == FILE_EXTENSION_SV6)
|
||||
{
|
||||
game_load_save(sourcePath);
|
||||
}
|
||||
Console::Error::WriteLine(ex.GetMessage());
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
|
||||
SDL_RWops* rw = SDL_RWFromFile(destinationPath, "wb+");
|
||||
if (rw != NULL) {
|
||||
if (sourceFileType == FILE_EXTENSION_SC4 ||
|
||||
sourceFileType == FILE_EXTENSION_SC6)
|
||||
{
|
||||
// We are converting a scenario, so reset the park
|
||||
scenario_begin();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto exporter = std::make_unique<S6Exporter>();
|
||||
|
||||
// HACK remove the main window so it saves the park with the
|
||||
// correct initial view
|
||||
window_close_by_class(WC_MAIN_WINDOW);
|
||||
|
||||
exporter->Export();
|
||||
if (destinationFileType == FILE_EXTENSION_SC6)
|
||||
{
|
||||
scenario_save(rw, 0x80000002);
|
||||
exporter->SaveScenario(destinationPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
scenario_save(rw, 0x80000001);
|
||||
exporter->SaveGame(destinationPath);
|
||||
}
|
||||
SDL_RWclose(rw);
|
||||
Console::WriteLine("Conversion successful!");
|
||||
}
|
||||
else
|
||||
catch (const Exception &ex)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to write destination file.");
|
||||
Console::Error::WriteLine(ex.GetMessage());
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
|
||||
Console::WriteLine("Conversion successful!");
|
||||
return EXITCODE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
enum
|
||||
{
|
||||
FILE_MODE_OPEN,
|
||||
FILE_MODE_WRITE
|
||||
FILE_MODE_WRITE,
|
||||
FILE_MODE_APPEND,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -61,6 +62,11 @@ public:
|
|||
_canRead = true;
|
||||
_canWrite = true;
|
||||
break;
|
||||
case FILE_MODE_APPEND:
|
||||
mode = "a";
|
||||
_canRead = false;
|
||||
_canWrite = true;
|
||||
break;
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,12 @@ MemoryStream::~MemoryStream()
|
|||
_data = nullptr;
|
||||
}
|
||||
|
||||
void * MemoryStream::GetData() const
|
||||
const void * MemoryStream::GetData() const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
void * MemoryStream::GetDataCopy() const
|
||||
{
|
||||
return Memory::Duplicate(_data, _dataSize);
|
||||
}
|
||||
|
@ -173,7 +178,9 @@ void MemoryStream::EnsureCapacity(size_t capacity)
|
|||
newCapacity *= 2;
|
||||
}
|
||||
|
||||
uint64 position = GetPosition();
|
||||
_dataCapacity = newCapacity;
|
||||
Memory::Reallocate(_data, _dataCapacity);
|
||||
_data = Memory::Reallocate(_data, _dataCapacity);
|
||||
_position = (void *)((uintptr_t)_data + (uintptr_t)position);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@ public:
|
|||
MemoryStream(const void * data, size_t dataSize);
|
||||
virtual ~MemoryStream();
|
||||
|
||||
void * GetData() const;
|
||||
const void * GetData() const;
|
||||
void * GetDataCopy() const;
|
||||
void * TakeData();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -168,7 +168,6 @@ sint32 game_do_command_p(sint32 command, sint32 *eax, sint32 *ebx, sint32 *ecx,
|
|||
void game_load_or_quit_no_save_prompt();
|
||||
bool game_load_sv6_path(const char * path);
|
||||
bool game_load_sv6(SDL_RWops* rw);
|
||||
sint32 game_load_network(SDL_RWops* rw);
|
||||
bool game_load_save(const utf8 *path);
|
||||
void game_load_init();
|
||||
void game_pause_toggle(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp);
|
||||
|
|
|
@ -16,13 +16,14 @@
|
|||
|
||||
#ifndef DISABLE_NETWORK
|
||||
|
||||
#include "NetworkKey.h"
|
||||
#include "../diagnostic.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <vector>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "../core/IStream.hpp"
|
||||
#include "../diagnostic.h"
|
||||
#include "NetworkKey.h"
|
||||
|
||||
#define KEY_TYPE EVP_PKEY_RSA
|
||||
|
||||
|
@ -90,10 +91,11 @@ bool NetworkKey::Generate()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetworkKey::LoadPrivate(SDL_RWops * file)
|
||||
bool NetworkKey::LoadPrivate(IStream * stream)
|
||||
{
|
||||
assert(file != nullptr);
|
||||
size_t size = (size_t)file->size(file);
|
||||
Guard::ArgumentNotNull(stream);
|
||||
|
||||
size_t size = (size_t)stream->GetLength();
|
||||
if (size == (size_t)-1)
|
||||
{
|
||||
log_error("unknown size, refusing to load key");
|
||||
|
@ -105,7 +107,7 @@ bool NetworkKey::LoadPrivate(SDL_RWops * file)
|
|||
return false;
|
||||
}
|
||||
char * priv_key = new char[size];
|
||||
file->read(file, priv_key, 1, size);
|
||||
stream->Read(priv_key, size);
|
||||
BIO * bio = BIO_new_mem_buf(priv_key, (sint32)size);
|
||||
if (bio == nullptr)
|
||||
{
|
||||
|
@ -134,10 +136,11 @@ bool NetworkKey::LoadPrivate(SDL_RWops * file)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetworkKey::LoadPublic(SDL_RWops * file)
|
||||
bool NetworkKey::LoadPublic(IStream * stream)
|
||||
{
|
||||
assert(file != nullptr);
|
||||
size_t size = (size_t)file->size(file);
|
||||
Guard::ArgumentNotNull(stream);
|
||||
|
||||
size_t size = (size_t)stream->GetLength();
|
||||
if (size == (size_t)-1)
|
||||
{
|
||||
log_error("unknown size, refusing to load key");
|
||||
|
@ -149,7 +152,7 @@ bool NetworkKey::LoadPublic(SDL_RWops * file)
|
|||
return false;
|
||||
}
|
||||
char * pub_key = new char[size];
|
||||
file->read(file, pub_key, 1, size);
|
||||
stream->Read(pub_key, size);
|
||||
BIO * bio = BIO_new_mem_buf(pub_key, (sint32)size);
|
||||
if (bio == nullptr)
|
||||
{
|
||||
|
@ -171,7 +174,7 @@ bool NetworkKey::LoadPublic(SDL_RWops * file)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetworkKey::SavePrivate(SDL_RWops *file)
|
||||
bool NetworkKey::SavePrivate(IStream * stream)
|
||||
{
|
||||
if (_key == nullptr)
|
||||
{
|
||||
|
@ -208,7 +211,7 @@ bool NetworkKey::SavePrivate(SDL_RWops *file)
|
|||
sint32 keylen = BIO_pending(bio);
|
||||
char * pem_key = new char[keylen];
|
||||
BIO_read(bio, pem_key, keylen);
|
||||
file->write(file, pem_key, keylen, 1);
|
||||
stream->Write(pem_key, keylen);
|
||||
log_verbose("saving key of length %u", keylen);
|
||||
BIO_free_all(bio);
|
||||
delete [] pem_key;
|
||||
|
@ -219,7 +222,7 @@ bool NetworkKey::SavePrivate(SDL_RWops *file)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetworkKey::SavePublic(SDL_RWops *file)
|
||||
bool NetworkKey::SavePublic(IStream * stream)
|
||||
{
|
||||
if (_key == nullptr)
|
||||
{
|
||||
|
@ -250,7 +253,7 @@ bool NetworkKey::SavePublic(SDL_RWops *file)
|
|||
sint32 keylen = BIO_pending(bio);
|
||||
char * pem_key = new char[keylen];
|
||||
BIO_read(bio, pem_key, keylen);
|
||||
file->write(file, pem_key, keylen, 1);
|
||||
stream->Write(pem_key, keylen);
|
||||
BIO_free_all(bio);
|
||||
delete [] pem_key;
|
||||
|
||||
|
|
|
@ -21,22 +21,23 @@
|
|||
|
||||
#include "../common.h"
|
||||
|
||||
#include <SDL_rwops.h>
|
||||
#include <string>
|
||||
|
||||
typedef struct evp_pkey_st EVP_PKEY;
|
||||
typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
|
||||
|
||||
interface IStream;
|
||||
|
||||
class NetworkKey final
|
||||
{
|
||||
public:
|
||||
NetworkKey();
|
||||
~NetworkKey();
|
||||
bool Generate();
|
||||
bool LoadPrivate(SDL_RWops * file);
|
||||
bool LoadPublic(SDL_RWops * file);
|
||||
bool SavePrivate(SDL_RWops * file);
|
||||
bool SavePublic(SDL_RWops * file);
|
||||
bool LoadPrivate(IStream * stream);
|
||||
bool LoadPublic(IStream * stream);
|
||||
bool SavePrivate(IStream * stream);
|
||||
bool SavePublic(IStream * stream);
|
||||
std::string PublicKeyString();
|
||||
std::string PublicKeyHash();
|
||||
void Unload();
|
||||
|
|
|
@ -66,6 +66,10 @@
|
|||
|
||||
constexpr uint32 CONNECT_TIMEOUT_MS = 3000;
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
static bool _wsaInitialised = false;
|
||||
#endif
|
||||
|
||||
class TcpSocket;
|
||||
|
||||
class SocketException : public Exception
|
||||
|
@ -431,7 +435,7 @@ private:
|
|||
explicit TcpSocket(SOCKET socket)
|
||||
{
|
||||
_socket = socket;
|
||||
_status = SOCKET_STATUS_CONNECTED;
|
||||
_status = SOCKET_STATUS_CONNECTED;
|
||||
}
|
||||
|
||||
void CloseSocket()
|
||||
|
@ -492,4 +496,48 @@ ITcpSocket * CreateTcpSocket()
|
|||
return new TcpSocket();
|
||||
}
|
||||
|
||||
bool InitialiseWSA()
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
if (!_wsaInitialised)
|
||||
{
|
||||
log_verbose("Initialising WSA");
|
||||
WSADATA wsa_data;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0)
|
||||
{
|
||||
log_error("Unable to initialise winsock.");
|
||||
return false;
|
||||
}
|
||||
_wsaInitialised = true;
|
||||
}
|
||||
return _wsaInitialised;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void DisposeWSA()
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
if (_wsaInitialised)
|
||||
{
|
||||
WSACleanup();
|
||||
_wsaInitialised = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace Convert
|
||||
{
|
||||
uint16 HostToNetwork(uint16 value)
|
||||
{
|
||||
return htons(value);
|
||||
}
|
||||
|
||||
uint16 NetworkToHost(uint16 value)
|
||||
{
|
||||
return ntohs(value);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -62,3 +62,12 @@ public:
|
|||
};
|
||||
|
||||
ITcpSocket * CreateTcpSocket();
|
||||
|
||||
bool InitialiseWSA();
|
||||
void DisposeWSA();
|
||||
|
||||
namespace Convert
|
||||
{
|
||||
uint16 HostToNetwork(uint16 value);
|
||||
uint16 NetworkToHost(uint16 value);
|
||||
}
|
||||
|
|
|
@ -16,19 +16,12 @@
|
|||
|
||||
#include <SDL_platform.h>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
// winsock2 must be included before windows.h
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "../core/Guard.hpp"
|
||||
#include "../OpenRCT2.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../util/sawyercoding.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "../util/sawyercoding.h"
|
||||
}
|
||||
|
||||
#include "network.h"
|
||||
|
@ -45,13 +38,16 @@ sint32 _pickup_peep_old_x = SPRITE_LOCATION_NULL;
|
|||
#include <string>
|
||||
|
||||
#include "../core/Console.hpp"
|
||||
#include "../core/FileStream.hpp"
|
||||
#include "../core/Json.hpp"
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/MemoryStream.h"
|
||||
#include "../core/Path.hpp"
|
||||
#include "../core/String.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../object/ObjectManager.h"
|
||||
#include "../object/ObjectRepository.h"
|
||||
#include "../ParkImporter.h"
|
||||
#include "../rct2/S6Exporter.h"
|
||||
|
||||
extern "C" {
|
||||
|
@ -130,17 +126,9 @@ Network::~Network()
|
|||
|
||||
bool Network::Init()
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
if (!wsa_initialized) {
|
||||
log_verbose("Initialising WSA");
|
||||
WSADATA wsa_data;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) {
|
||||
log_error("Unable to initialise winsock.");
|
||||
return false;
|
||||
}
|
||||
wsa_initialized = true;
|
||||
if (!InitialiseWSA()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
status = NETWORK_STATUS_READY;
|
||||
|
||||
|
@ -183,12 +171,7 @@ void Network::Close()
|
|||
player_list.clear();
|
||||
group_list.clear();
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
if (wsa_initialized) {
|
||||
WSACleanup();
|
||||
wsa_initialized = false;
|
||||
}
|
||||
#endif
|
||||
DisposeWSA();
|
||||
|
||||
CloseChatLog();
|
||||
gfx_invalidate_screen();
|
||||
|
@ -229,36 +212,47 @@ bool Network::BeginClient(const char* host, uint16 port)
|
|||
return false;
|
||||
}
|
||||
|
||||
SDL_RWops *privkey = SDL_RWFromFile(keyPath, "wb+");
|
||||
if (privkey == nullptr) {
|
||||
try
|
||||
{
|
||||
auto fs = FileStream(keyPath, FILE_MODE_WRITE);
|
||||
_key.SavePrivate(&fs);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
log_error("Unable to save private key at %s.", keyPath);
|
||||
return false;
|
||||
}
|
||||
_key.SavePrivate(privkey);
|
||||
SDL_RWclose(privkey);
|
||||
|
||||
const std::string hash = _key.PublicKeyHash();
|
||||
const utf8 *publicKeyHash = hash.c_str();
|
||||
network_get_public_key_path(keyPath, sizeof(keyPath), gConfigNetwork.player_name, publicKeyHash);
|
||||
Console::WriteLine("Key generated, saving public bits as %s", keyPath);
|
||||
SDL_RWops *pubkey = SDL_RWFromFile(keyPath, "wb+");
|
||||
if (pubkey == nullptr) {
|
||||
|
||||
try
|
||||
{
|
||||
auto fs = FileStream(keyPath, FILE_MODE_WRITE);
|
||||
_key.SavePublic(&fs);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
log_error("Unable to save public key at %s.", keyPath);
|
||||
return false;
|
||||
}
|
||||
_key.SavePublic(pubkey);
|
||||
SDL_RWclose(pubkey);
|
||||
} else {
|
||||
log_verbose("Loading key from %s", keyPath);
|
||||
SDL_RWops *privkey = SDL_RWFromFile(keyPath, "rb");
|
||||
if (privkey == nullptr) {
|
||||
// LoadPrivate returns validity of loaded key
|
||||
bool ok = false;
|
||||
try
|
||||
{
|
||||
log_verbose("Loading key from %s", keyPath);
|
||||
auto fs = FileStream(keyPath, FILE_MODE_OPEN);
|
||||
ok = _key.LoadPrivate(&fs);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
log_error("Unable to read private key from %s.", keyPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// LoadPrivate returns validity of loaded key
|
||||
bool ok = _key.LoadPrivate(privkey);
|
||||
SDL_RWclose(privkey);
|
||||
// Don't store private key in memory when it's not in use.
|
||||
_key.Unload();
|
||||
return ok;
|
||||
|
@ -813,10 +807,11 @@ void Network::AppendChatLog(const utf8 *text)
|
|||
utf8 directory[MAX_PATH];
|
||||
Path::GetDirectory(directory, sizeof(directory), chatLogPath);
|
||||
if (platform_ensure_directory_exists(directory)) {
|
||||
_chatLogStream = SDL_RWFromFile(chatLogPath, "a");
|
||||
if (_chatLogStream != nullptr) {
|
||||
utf8 buffer[256];
|
||||
try
|
||||
{
|
||||
_chatLogStream = new FileStream(chatLogPath, FILE_MODE_APPEND);
|
||||
|
||||
utf8 buffer[256];
|
||||
time_t timer;
|
||||
struct tm * tmInfo;
|
||||
time(&timer);
|
||||
|
@ -827,8 +822,12 @@ void Network::AppendChatLog(const utf8 *text)
|
|||
utf8_remove_formatting(buffer, false);
|
||||
String::Append(buffer, sizeof(buffer), PLATFORM_NEWLINE);
|
||||
|
||||
SDL_RWwrite(_chatLogStream, buffer, strlen(buffer), 1);
|
||||
SDL_RWclose(_chatLogStream);
|
||||
_chatLogStream->Write(buffer, strlen(buffer));
|
||||
delete _chatLogStream;
|
||||
_chatLogStream = nullptr;
|
||||
}
|
||||
catch (const Exception &)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -916,14 +915,6 @@ void Network::Server_Send_AUTH(NetworkConnection& connection)
|
|||
|
||||
void Network::Server_Send_MAP(NetworkConnection* connection)
|
||||
{
|
||||
FILE* temp = tmpfile();
|
||||
if (!temp) {
|
||||
log_warning("Failed to create temporary file to save map.");
|
||||
return;
|
||||
}
|
||||
SDL_RWops* rw = SDL_RWFromFP(temp, SDL_TRUE);
|
||||
size_t out_size;
|
||||
uint8 *header;
|
||||
std::vector<const ObjectRepositoryItem *> objects;
|
||||
if (connection) {
|
||||
objects = connection->RequestedObjects;
|
||||
|
@ -933,8 +924,9 @@ void Network::Server_Send_MAP(NetworkConnection* connection)
|
|||
IObjectManager * objManager = GetObjectManager();
|
||||
objects = objManager->GetPackableObjects();
|
||||
}
|
||||
header = save_for_network(rw, out_size, objects);
|
||||
SDL_RWclose(rw);
|
||||
|
||||
size_t out_size;
|
||||
uint8 * header = save_for_network(out_size, objects);
|
||||
if (header == nullptr) {
|
||||
if (connection) {
|
||||
connection->SetLastDisconnectReason(STR_MULTIPLAYER_CONNECTION_CLOSED);
|
||||
|
@ -957,22 +949,24 @@ void Network::Server_Send_MAP(NetworkConnection* connection)
|
|||
free(header);
|
||||
}
|
||||
|
||||
uint8 * Network::save_for_network(SDL_RWops *rw_buffer, size_t &out_size, const std::vector<const ObjectRepositoryItem *> &objects) const
|
||||
uint8 * Network::save_for_network(size_t &out_size, const std::vector<const ObjectRepositoryItem *> &objects) const
|
||||
{
|
||||
uint8 * header = nullptr;
|
||||
out_size = 0;
|
||||
bool RLEState = gUseRLE;
|
||||
gUseRLE = false;
|
||||
scenario_save_network(rw_buffer, objects);
|
||||
gUseRLE = RLEState;
|
||||
sint32 size = (sint32)SDL_RWtell(rw_buffer);
|
||||
std::vector<uint8> buffer(size);
|
||||
SDL_RWseek(rw_buffer, 0, RW_SEEK_SET);
|
||||
if (SDL_RWread(rw_buffer, &buffer[0], size, 1) == 0) {
|
||||
log_warning("Failed to read temporary map file into memory.");
|
||||
|
||||
auto ms = MemoryStream();
|
||||
if (!SaveMap(&ms, objects)) {
|
||||
log_warning("Failed to export map.");
|
||||
return nullptr;
|
||||
}
|
||||
uint8 *compressed = util_zlib_deflate(&buffer[0], size, &out_size);
|
||||
gUseRLE = RLEState;
|
||||
|
||||
const void * data = ms.GetData();
|
||||
sint32 size = ms.GetLength();
|
||||
|
||||
uint8 *compressed = util_zlib_deflate((const uint8 *)data, size, &out_size);
|
||||
if (compressed != NULL)
|
||||
{
|
||||
header = (uint8 *)_strdup("open2_sv6_zlib");
|
||||
|
@ -993,7 +987,7 @@ uint8 * Network::save_for_network(SDL_RWops *rw_buffer, size_t &out_size, const
|
|||
log_error("Failed to allocate %u bytes.", size);
|
||||
} else {
|
||||
out_size = size;
|
||||
memcpy(header, &buffer[0], size);
|
||||
memcpy(header, data, size);
|
||||
}
|
||||
}
|
||||
return header;
|
||||
|
@ -1381,15 +1375,23 @@ void Network::Client_Handle_TOKEN(NetworkConnection& connection, NetworkPacket&
|
|||
log_error("Key file (%s) was not found. Restart client to re-generate it.", keyPath);
|
||||
return;
|
||||
}
|
||||
SDL_RWops *privkey = SDL_RWFromFile(keyPath, "rb");
|
||||
bool ok = _key.LoadPrivate(privkey);
|
||||
SDL_RWclose(privkey);
|
||||
if (!ok) {
|
||||
|
||||
try
|
||||
{
|
||||
auto fs = FileStream(keyPath, FILE_MODE_OPEN);
|
||||
if (!_key.LoadPrivate(&fs))
|
||||
{
|
||||
throw Exception();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
log_error("Failed to load key %s", keyPath);
|
||||
connection.SetLastDisconnectReason(STR_MULTIPLAYER_VERIFICATION_FAILURE);
|
||||
connection.Socket->Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 challenge_size;
|
||||
packet >> challenge_size;
|
||||
const char *challenge = (const char *)packet.Read(challenge_size);
|
||||
|
@ -1398,7 +1400,7 @@ void Network::Client_Handle_TOKEN(NetworkConnection& connection, NetworkPacket&
|
|||
const std::string pubkey = _key.PublicKeyString();
|
||||
_challenge.resize(challenge_size);
|
||||
memcpy(_challenge.data(), challenge, challenge_size);
|
||||
ok = _key.Sign(_challenge.data(), _challenge.size(), &signature, &sigsize);
|
||||
bool ok = _key.Sign(_challenge.data(), _challenge.size(), &signature, &sigsize);
|
||||
if (!ok) {
|
||||
log_error("Failed to sign server's challenge.");
|
||||
connection.SetLastDisconnectReason(STR_MULTIPLAYER_VERIFICATION_FAILURE);
|
||||
|
@ -1552,26 +1554,45 @@ void Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& p
|
|||
if (pubkey == nullptr) {
|
||||
connection.AuthStatus = NETWORK_AUTH_VERIFICATIONFAILURE;
|
||||
} else {
|
||||
const char *signature = (const char *)packet.Read(sigsize);
|
||||
SDL_RWops *pubkey_rw = SDL_RWFromConstMem(pubkey, (sint32)strlen(pubkey));
|
||||
if (signature == nullptr || pubkey_rw == nullptr) {
|
||||
connection.AuthStatus = NETWORK_AUTH_VERIFICATIONFAILURE;
|
||||
log_verbose("Signature verification failed, invalid data!");
|
||||
} else {
|
||||
connection.Key.LoadPublic(pubkey_rw);
|
||||
SDL_RWclose(pubkey_rw);
|
||||
try
|
||||
{
|
||||
const char *signature = (const char *)packet.Read(sigsize);
|
||||
if (signature == nullptr)
|
||||
{
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
auto ms = MemoryStream(pubkey, strlen(pubkey));
|
||||
if (!connection.Key.LoadPublic(&ms))
|
||||
{
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
bool verified = connection.Key.Verify(connection.Challenge.data(), connection.Challenge.size(), signature, sigsize);
|
||||
const std::string hash = connection.Key.PublicKeyHash();
|
||||
if (verified) {
|
||||
connection.AuthStatus = NETWORK_AUTH_VERIFIED;
|
||||
if (verified)
|
||||
{
|
||||
log_verbose("Signature verification ok. Hash %s", hash.c_str());
|
||||
} else {
|
||||
if (gConfigNetwork.known_keys_only && _userManager.GetUserByHash(hash) == nullptr)
|
||||
{
|
||||
log_verbose("Hash %s, not known", hash.c_str());
|
||||
connection.AuthStatus = NETWORK_AUTH_UNKNOWN_KEY_DISALLOWED;
|
||||
}
|
||||
else
|
||||
{
|
||||
connection.AuthStatus = NETWORK_AUTH_VERIFIED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
connection.AuthStatus = NETWORK_AUTH_VERIFICATIONFAILURE;
|
||||
log_verbose("Signature verification failed!");
|
||||
}
|
||||
if (gConfigNetwork.known_keys_only && _userManager.GetUserByHash(hash) == nullptr) {
|
||||
connection.AuthStatus = NETWORK_AUTH_UNKNOWN_KEY_DISALLOWED;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
connection.AuthStatus = NETWORK_AUTH_VERIFICATIONFAILURE;
|
||||
log_verbose("Signature verification failed, invalid data!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1649,8 +1670,10 @@ void Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pa
|
|||
} else {
|
||||
log_verbose("Assuming received map is in plain sv6 format");
|
||||
}
|
||||
SDL_RWops* rw = SDL_RWFromMem(data, (sint32)data_size);
|
||||
if (game_load_network(rw)) {
|
||||
|
||||
auto ms = MemoryStream(data, data_size);
|
||||
if (LoadMap(&ms))
|
||||
{
|
||||
game_load_init();
|
||||
game_command_queue.clear();
|
||||
server_tick = gCurrentTicks;
|
||||
|
@ -1667,7 +1690,6 @@ void Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pa
|
|||
//Something went wrong, game is not loaded. Return to main screen.
|
||||
game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 1, 0);
|
||||
}
|
||||
SDL_RWclose(rw);
|
||||
if (has_to_free)
|
||||
{
|
||||
free(data);
|
||||
|
@ -1675,6 +1697,99 @@ void Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pa
|
|||
}
|
||||
}
|
||||
|
||||
bool Network::LoadMap(IStream * stream)
|
||||
{
|
||||
bool result = false;
|
||||
try
|
||||
{
|
||||
auto importer = std::unique_ptr<IParkImporter>(ParkImporter::CreateS6());
|
||||
importer->LoadFromStream(stream, false);
|
||||
importer->Import();
|
||||
|
||||
sprite_position_tween_reset();
|
||||
|
||||
// Read checksum
|
||||
uint32 checksum = stream->ReadValue<uint32>();
|
||||
UNUSED(checksum);
|
||||
|
||||
// Read other data not in normal save files
|
||||
stream->Read(gSpriteSpatialIndex, 0x10001 * sizeof(uint16));
|
||||
gGamePaused = stream->ReadValue<uint32>();
|
||||
_guestGenerationProbability = stream->ReadValue<uint32>();
|
||||
_suggestedGuestMaximum = stream->ReadValue<uint32>();
|
||||
gCheatsSandboxMode = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsDisableClearanceChecks = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsDisableSupportLimits = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsDisableTrainLengthLimit = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsEnableChainLiftOnAllTrack = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsShowAllOperatingModes = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsShowVehiclesFromOtherTrackTypes = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsFastLiftHill = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsDisableBrakesFailure = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsDisableAllBreakdowns = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsUnlockAllPrices = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsBuildInPauseMode = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsIgnoreRideIntensity = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsDisableVandalism = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsDisableLittering = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsNeverendingMarketing = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsFreezeClimate = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsDisablePlantAging = stream->ReadValue<uint8>() != 0;
|
||||
gCheatsAllowArbitraryRideTypeChanges = stream->ReadValue<uint8>() != 0;
|
||||
|
||||
gLastAutoSaveUpdate = AUTOSAVE_PAUSE;
|
||||
result = true;
|
||||
}
|
||||
catch (const Exception &)
|
||||
{
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Network::SaveMap(IStream * stream, const std::vector<const ObjectRepositoryItem *> &objects) const
|
||||
{
|
||||
bool result = false;
|
||||
viewport_set_saved_view();
|
||||
try
|
||||
{
|
||||
auto s6exporter = std::make_unique<S6Exporter>();
|
||||
s6exporter->ExportObjectsList = objects;
|
||||
s6exporter->Export();
|
||||
s6exporter->SaveGame(stream);
|
||||
|
||||
// Write other data not in normal save files
|
||||
stream->Write(gSpriteSpatialIndex, 0x10001 * sizeof(uint16));
|
||||
stream->WriteValue<uint32>(gGamePaused);
|
||||
stream->WriteValue<uint32>(_guestGenerationProbability);
|
||||
stream->WriteValue<uint32>(_suggestedGuestMaximum);
|
||||
stream->WriteValue<uint8>(gCheatsSandboxMode);
|
||||
stream->WriteValue<uint8>(gCheatsDisableClearanceChecks);
|
||||
stream->WriteValue<uint8>(gCheatsDisableSupportLimits);
|
||||
stream->WriteValue<uint8>(gCheatsDisableTrainLengthLimit);
|
||||
stream->WriteValue<uint8>(gCheatsEnableChainLiftOnAllTrack);
|
||||
stream->WriteValue<uint8>(gCheatsShowAllOperatingModes);
|
||||
stream->WriteValue<uint8>(gCheatsShowVehiclesFromOtherTrackTypes);
|
||||
stream->WriteValue<uint8>(gCheatsFastLiftHill);
|
||||
stream->WriteValue<uint8>(gCheatsDisableBrakesFailure);
|
||||
stream->WriteValue<uint8>(gCheatsDisableAllBreakdowns);
|
||||
stream->WriteValue<uint8>(gCheatsUnlockAllPrices);
|
||||
stream->WriteValue<uint8>(gCheatsBuildInPauseMode);
|
||||
stream->WriteValue<uint8>(gCheatsIgnoreRideIntensity);
|
||||
stream->WriteValue<uint8>(gCheatsDisableVandalism);
|
||||
stream->WriteValue<uint8>(gCheatsDisableLittering);
|
||||
stream->WriteValue<uint8>(gCheatsNeverendingMarketing);
|
||||
stream->WriteValue<uint8>(gCheatsFreezeClimate);
|
||||
stream->WriteValue<uint8>(gCheatsDisablePlantAging);
|
||||
stream->WriteValue<uint8>(gCheatsAllowArbitraryRideTypeChanges);
|
||||
|
||||
result = true;
|
||||
}
|
||||
catch (const Exception &)
|
||||
{
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Network::Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet)
|
||||
{
|
||||
const char* text = packet.ReadString();
|
||||
|
@ -1955,19 +2070,6 @@ void Network::Client_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacke
|
|||
network_chat_show_server_greeting();
|
||||
}
|
||||
|
||||
namespace Convert
|
||||
{
|
||||
uint16 HostToNetwork(uint16 value)
|
||||
{
|
||||
return htons(value);
|
||||
}
|
||||
|
||||
uint16 NetworkToHost(uint16 value)
|
||||
{
|
||||
return ntohs(value);
|
||||
}
|
||||
}
|
||||
|
||||
sint32 network_init()
|
||||
{
|
||||
return gNetwork.Init();
|
||||
|
@ -2456,8 +2558,16 @@ void network_send_password(const char* password)
|
|||
log_error("Private key %s missing! Restart the game to generate it.", keyPath);
|
||||
return;
|
||||
}
|
||||
SDL_RWops *privkey = SDL_RWFromFile(keyPath, "rb");
|
||||
gNetwork._key.LoadPrivate(privkey);
|
||||
try
|
||||
{
|
||||
auto fs = FileStream(keyPath, FILE_MODE_OPEN);
|
||||
gNetwork._key.LoadPrivate(&fs);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
log_error("Error reading private key from %s.", keyPath);
|
||||
return;
|
||||
}
|
||||
const std::string pubkey = gNetwork._key.PublicKeyString();
|
||||
size_t sigsize;
|
||||
char *signature;
|
||||
|
|
|
@ -67,7 +67,6 @@ extern "C" {
|
|||
#include <vector>
|
||||
#include <map>
|
||||
#include <openssl/evp.h>
|
||||
#include <SDL.h>
|
||||
#include "../core/Json.hpp"
|
||||
#include "../core/Nullable.hpp"
|
||||
#include "NetworkConnection.h"
|
||||
|
@ -174,6 +173,9 @@ private:
|
|||
std::string GenerateAdvertiseKey();
|
||||
void SetupDefaultGroups();
|
||||
|
||||
bool LoadMap(IStream * stream);
|
||||
bool SaveMap(IStream * stream, const std::vector<const ObjectRepositoryItem *> &objects) const;
|
||||
|
||||
struct GameCommand
|
||||
{
|
||||
GameCommand(uint32 t, uint32* args, uint8 p, uint8 cb) {
|
||||
|
@ -211,7 +213,7 @@ private:
|
|||
INetworkServerAdvertiser * _advertiser = nullptr;
|
||||
uint32 server_connect_time = 0;
|
||||
uint8 default_group = 0;
|
||||
SDL_RWops *_chatLogStream = nullptr;
|
||||
IStream * _chatLogStream = nullptr;
|
||||
std::string _chatLogPath;
|
||||
uint32 game_commands_processed_this_tick = 0;
|
||||
|
||||
|
@ -245,15 +247,9 @@ private:
|
|||
void Client_Handle_OBJECTS(NetworkConnection& connection, NetworkPacket& packet);
|
||||
void Server_Handle_OBJECTS(NetworkConnection& connection, NetworkPacket& packet);
|
||||
|
||||
uint8 * save_for_network(SDL_RWops *buffer, size_t &out_size, const std::vector<const ObjectRepositoryItem *> &objects) const;
|
||||
uint8 * save_for_network(size_t &out_size, const std::vector<const ObjectRepositoryItem *> &objects) const;
|
||||
};
|
||||
|
||||
namespace Convert
|
||||
{
|
||||
uint16 HostToNetwork(uint16 value);
|
||||
uint16 NetworkToHost(uint16 value);
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
#else /* DISABLE_NETWORK */
|
||||
#define NETWORK_STREAM_ID "Multiplayer disabled"
|
||||
|
|
|
@ -107,7 +107,6 @@ assert_struct_size(rct_object_filters, 3);
|
|||
extern const rct_object_entry_group object_entry_groups[];
|
||||
|
||||
void object_list_load();
|
||||
bool object_read_and_load_entries(SDL_RWops* rw);
|
||||
bool object_load_entries(rct_object_entry* entries);
|
||||
bool object_saved_packed(SDL_RWops* rw, const rct_object_entry * entry);
|
||||
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
#include "../core/FileStream.hpp"
|
||||
#include "../core/Memory.hpp"
|
||||
#include "../core/MemoryStream.h"
|
||||
#include "../core/String.hpp"
|
||||
#include "../core/Path.hpp"
|
||||
#include "../core/String.hpp"
|
||||
#include "../rct12/SawyerChunkReader.h"
|
||||
#include "BannerObject.h"
|
||||
#include "EntranceObject.h"
|
||||
#include "FootpathItemObject.h"
|
||||
|
@ -102,64 +103,40 @@ namespace ObjectFactory
|
|||
}
|
||||
}
|
||||
|
||||
static MemoryStream * GetDecodedChunkStream(IReadObjectContext * context, SDL_RWops * file)
|
||||
{
|
||||
size_t bufferSize = 0x600000;
|
||||
void * buffer = Memory::Allocate<void>(bufferSize);
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
log_error("Unable to allocate data buffer.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bufferSize = sawyercoding_read_chunk_with_size(file, (uint8 *)buffer, bufferSize);
|
||||
if (bufferSize == SIZE_MAX)
|
||||
{
|
||||
context->LogError(OBJECT_ERROR_BAD_ENCODING, "Unable to decode chunk.");
|
||||
Memory::Free(buffer);
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = Memory::Reallocate(buffer, bufferSize);
|
||||
return new MemoryStream(buffer, bufferSize, MEMORY_ACCESS::READ | MEMORY_ACCESS::OWNER);
|
||||
}
|
||||
}
|
||||
|
||||
Object * CreateObjectFromLegacyFile(const utf8 * path)
|
||||
{
|
||||
log_verbose("CreateObjectFromLegacyFile(\"%s\")", path);
|
||||
|
||||
Object * result = nullptr;
|
||||
|
||||
SDL_RWops * file = SDL_RWFromFile(path, "rb");
|
||||
if (file != nullptr)
|
||||
try
|
||||
{
|
||||
rct_object_entry entry;
|
||||
if (SDL_RWread(file, &entry, sizeof(entry), 1) == 1)
|
||||
auto fs = FileStream(path, FILE_MODE_OPEN);
|
||||
auto chunkReader = SawyerChunkReader(&fs);
|
||||
|
||||
rct_object_entry entry = fs.ReadValue<rct_object_entry>();
|
||||
result = CreateObject(entry);
|
||||
|
||||
utf8 objectName[9] = { 0 };
|
||||
object_entry_get_name_fixed(objectName, sizeof(objectName), &entry);
|
||||
log_verbose(" entry: { 0x%08X, \"%s\", 0x%08X }", entry.flags, objectName, entry.checksum);
|
||||
|
||||
auto chunk = chunkReader.ReadChunk();
|
||||
log_verbose(" size: %zu", chunk->GetLength());
|
||||
|
||||
auto chunkStream = MemoryStream(chunk->GetData(), chunk->GetLength());
|
||||
auto readContext = ReadObjectContext(objectName);
|
||||
ReadObjectLegacy(result, &readContext, &chunkStream);
|
||||
if (readContext.WasError())
|
||||
{
|
||||
result = CreateObject(entry);
|
||||
if (result != nullptr)
|
||||
{
|
||||
utf8 objectName[9] = { 0 };
|
||||
Memory::Copy(objectName, entry.name, 8);
|
||||
|
||||
auto readContext = ReadObjectContext(objectName);
|
||||
auto chunkStream = GetDecodedChunkStream(&readContext, file);
|
||||
if (chunkStream != nullptr)
|
||||
{
|
||||
ReadObjectLegacy(result, &readContext, chunkStream);
|
||||
delete chunkStream;
|
||||
}
|
||||
|
||||
if (readContext.WasError())
|
||||
{
|
||||
Console::Error::WriteLine("Error reading object: '%s'", path);
|
||||
|
||||
delete result;
|
||||
result = nullptr;
|
||||
}
|
||||
}
|
||||
throw Exception("Object has errors");
|
||||
}
|
||||
SDL_RWclose(file);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open or read '%s'", path);
|
||||
|
||||
delete result;
|
||||
result = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -190,8 +167,7 @@ namespace ObjectFactory
|
|||
|
||||
Object * CreateObject(const rct_object_entry &entry)
|
||||
{
|
||||
Object * result = nullptr;
|
||||
|
||||
Object * result;
|
||||
uint8 objectType = entry.flags & 0x0F;
|
||||
switch (objectType) {
|
||||
case OBJECT_TYPE_RIDE:
|
||||
|
@ -227,8 +203,9 @@ namespace ObjectFactory
|
|||
case OBJECT_TYPE_SCENARIO_TEXT:
|
||||
result = new StexObject(entry);
|
||||
break;
|
||||
default:
|
||||
throw Exception("Invalid object type");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,20 +127,6 @@ void object_create_identifier_name(char* string_buffer, size_t size, const rct_o
|
|||
snprintf(string_buffer, size, "%.8s/%4X%4X", object->name, object->flags, object->checksum);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA0C6
|
||||
*/
|
||||
bool object_read_and_load_entries(SDL_RWops* rw)
|
||||
{
|
||||
// Read all the object entries
|
||||
rct_object_entry *entries = malloc(OBJECT_ENTRY_COUNT * sizeof(rct_object_entry));
|
||||
sawyercoding_read_chunk_with_size(rw, (uint8*)entries, OBJECT_ENTRY_COUNT * sizeof(rct_object_entry));
|
||||
bool result = object_load_entries(entries);
|
||||
free(entries);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006A9DA2
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "crash.h"
|
||||
|
||||
#ifdef USE_BREAKPAD
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
|
@ -28,13 +29,16 @@
|
|||
#error Breakpad support not implemented yet for this platform
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#include "../localisation/language.h"
|
||||
#include "../scenario/scenario.h"
|
||||
#include "platform.h"
|
||||
}
|
||||
|
||||
#include "../core/Console.hpp"
|
||||
#include "../core/Exception.hpp"
|
||||
#include "../rct2/S6Exporter.h"
|
||||
|
||||
#define WSZ(x) L"" x
|
||||
|
||||
|
@ -86,21 +90,25 @@ static bool OnCrash(const wchar_t * dumpPath,
|
|||
wprintf(L"Version: %s\n", WSZ(OPENRCT2_VERSION));
|
||||
wprintf(L"Commit: %s\n", _wszCommitSha1Short);
|
||||
|
||||
utf8 * saveFilePathUTF8 = widechar_to_utf8(saveFilePath);
|
||||
SDL_RWops * rw = SDL_RWFromFile(saveFilePathUTF8, "wb+");
|
||||
free(saveFilePathUTF8);
|
||||
|
||||
bool savedGameDumped = false;
|
||||
if (rw != NULL) {
|
||||
scenario_save(rw, 0x80000000);
|
||||
utf8 * saveFilePathUTF8 = widechar_to_utf8(saveFilePath);
|
||||
try
|
||||
{
|
||||
auto exporter = std::make_unique<S6Exporter>();
|
||||
exporter->Export();
|
||||
exporter->SaveGame(saveFilePathUTF8);
|
||||
savedGameDumped = true;
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
catch (const Exception &)
|
||||
{
|
||||
}
|
||||
free(saveFilePathUTF8);
|
||||
|
||||
if (gOpenRCT2SilentBreakpad)
|
||||
{
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
constexpr const wchar_t * MessageFormat = L"A crash has occurred and a dump was created at\n%s.\n\nPlease file an issue with OpenRCT2 on GitHub, and provide the dump and saved game there.\n\nVersion: %s\nCommit: %s";
|
||||
wchar_t message[MAX_PATH * 2];
|
||||
swprintf_s(message,
|
||||
|
|
|
@ -396,61 +396,6 @@ uint32 S6Exporter::GetLoanHash(money32 initialCash, money32 bankLoan, uint32 max
|
|||
return value;
|
||||
}
|
||||
|
||||
// Save game state without modifying any of the state for multiplayer
|
||||
sint32 scenario_save_network(SDL_RWops * rw, const std::vector<const ObjectRepositoryItem *> &objects)
|
||||
{
|
||||
viewport_set_saved_view();
|
||||
|
||||
bool result = false;
|
||||
auto s6exporter = new S6Exporter();
|
||||
try
|
||||
{
|
||||
auto rwStream = FileStream(rw, FILE_MODE_WRITE);
|
||||
|
||||
s6exporter->ExportObjectsList = objects;
|
||||
s6exporter->Export();
|
||||
s6exporter->SaveGame(&rwStream);
|
||||
result = true;
|
||||
}
|
||||
catch (const 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;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
enum {
|
||||
|
|
|
@ -30,8 +30,6 @@ extern "C"
|
|||
interface IStream;
|
||||
struct ObjectRepositoryItem;
|
||||
|
||||
sint32 scenario_save_network(SDL_RWops* rw, const std::vector<const ObjectRepositoryItem *> &objects);
|
||||
|
||||
/**
|
||||
* Class to export RollerCoaster Tycoon 2 scenarios (*.SC6) and saved games (*.SV6).
|
||||
*/
|
||||
|
|
|
@ -486,42 +486,6 @@ extern "C"
|
|||
return result;
|
||||
}
|
||||
|
||||
bool scenario_load_rw(SDL_RWops * rw)
|
||||
{
|
||||
bool result = false;
|
||||
auto stream = FileStream(rw, FILE_MODE_OPEN);
|
||||
auto s6Importer = new S6Importer();
|
||||
try
|
||||
{
|
||||
s6Importer->LoadFromStream(&stream, true);
|
||||
s6Importer->Import();
|
||||
|
||||
game_fix_save_vars();
|
||||
sprite_position_tween_reset();
|
||||
result = true;
|
||||
}
|
||||
catch (ObjectLoadException)
|
||||
{
|
||||
gErrorType = ERROR_TYPE_FILE_LOAD;
|
||||
gErrorStringId = STR_GAME_SAVE_FAILED;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
gErrorType = ERROR_TYPE_FILE_LOAD;
|
||||
gErrorStringId = STR_GAME_SAVE_FAILED;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
gErrorType = ERROR_TYPE_FILE_LOAD;
|
||||
gErrorStringId = STR_FILE_CONTAINS_INVALID_DATA;
|
||||
}
|
||||
delete s6Importer;
|
||||
|
||||
gScreenAge = 0;
|
||||
gLastAutoSaveUpdate = AUTOSAVE_PAUSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00676053
|
||||
|
@ -561,63 +525,4 @@ extern "C"
|
|||
gLastAutoSaveUpdate = AUTOSAVE_PAUSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
sint32 game_load_network(SDL_RWops* rw)
|
||||
{
|
||||
bool result = false;
|
||||
auto stream = FileStream(rw, FILE_MODE_OPEN);
|
||||
auto s6Importer = new S6Importer();
|
||||
try
|
||||
{
|
||||
s6Importer->LoadFromStream(&stream, false);
|
||||
s6Importer->Import();
|
||||
|
||||
sprite_position_tween_reset();
|
||||
result = true;
|
||||
}
|
||||
catch (const ObjectLoadException &)
|
||||
{
|
||||
}
|
||||
catch (const Exception &)
|
||||
{
|
||||
}
|
||||
delete s6Importer;
|
||||
|
||||
if (!result)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read checksum
|
||||
uint32 checksum;
|
||||
SDL_RWread(rw, &checksum, sizeof(uint32), 1);
|
||||
|
||||
// Read other data not in normal save files
|
||||
SDL_RWread(rw, gSpriteSpatialIndex, 0x10001 * sizeof(uint16), 1);
|
||||
gGamePaused = SDL_ReadLE32(rw);
|
||||
_guestGenerationProbability = SDL_ReadLE32(rw);
|
||||
_suggestedGuestMaximum = SDL_ReadLE32(rw);
|
||||
gCheatsSandboxMode = SDL_ReadU8(rw) != 0;
|
||||
gCheatsDisableClearanceChecks = SDL_ReadU8(rw) != 0;
|
||||
gCheatsDisableSupportLimits = SDL_ReadU8(rw) != 0;
|
||||
gCheatsDisableTrainLengthLimit = SDL_ReadU8(rw) != 0;
|
||||
gCheatsEnableChainLiftOnAllTrack = SDL_ReadU8(rw) != 0;
|
||||
gCheatsShowAllOperatingModes = SDL_ReadU8(rw) != 0;
|
||||
gCheatsShowVehiclesFromOtherTrackTypes = SDL_ReadU8(rw) != 0;
|
||||
gCheatsFastLiftHill = SDL_ReadU8(rw) != 0;
|
||||
gCheatsDisableBrakesFailure = SDL_ReadU8(rw) != 0;
|
||||
gCheatsDisableAllBreakdowns = SDL_ReadU8(rw) != 0;
|
||||
gCheatsUnlockAllPrices = SDL_ReadU8(rw) != 0;
|
||||
gCheatsBuildInPauseMode = SDL_ReadU8(rw) != 0;
|
||||
gCheatsIgnoreRideIntensity = SDL_ReadU8(rw) != 0;
|
||||
gCheatsDisableVandalism = SDL_ReadU8(rw) != 0;
|
||||
gCheatsDisableLittering = SDL_ReadU8(rw) != 0;
|
||||
gCheatsNeverendingMarketing = SDL_ReadU8(rw) != 0;
|
||||
gCheatsFreezeClimate = SDL_ReadU8(rw) != 0;
|
||||
gCheatsDisablePlantAging = SDL_ReadU8(rw) != 0;
|
||||
gCheatsAllowArbitraryRideTypeChanges = SDL_ReadU8(rw) != 0;
|
||||
|
||||
gLastAutoSaveUpdate = AUTOSAVE_PAUSE;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -376,7 +376,6 @@ extern uint32 gLastAutoSaveUpdate;
|
|||
|
||||
extern const char *_scenarioFileName;
|
||||
|
||||
bool scenario_load_rw(SDL_RWops * rw);
|
||||
sint32 scenario_load(const char *path);
|
||||
sint32 scenario_load_and_play_from_path(const char *path);
|
||||
void scenario_begin();
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#pragma endregion
|
||||
|
||||
#include <vector>
|
||||
#include <SDL.h>
|
||||
#include "../common.h"
|
||||
#include "../core/Collections.hpp"
|
||||
#include "../core/Console.hpp"
|
||||
|
@ -39,7 +38,7 @@
|
|||
static std::vector<utf8 *> GetSaves(const utf8 * path);
|
||||
static std::vector<utf8 *> GetSaves(IZipArchive * zip);
|
||||
static std::vector<TitleCommand> LegacyScriptRead(utf8 * script, size_t scriptLength, std::vector<utf8 *> saves);
|
||||
static void LegacyScriptGetLine(SDL_RWops * file, char * parts);
|
||||
static void LegacyScriptGetLine(IStream * stream, char * parts);
|
||||
static void * ReadScriptFile(const utf8 * path, size_t * outSize);
|
||||
static utf8 * LegacyScriptWrite(TitleSequence * seq);
|
||||
|
||||
|
@ -392,10 +391,11 @@ static std::vector<utf8 *> GetSaves(IZipArchive * zip)
|
|||
static std::vector<TitleCommand> LegacyScriptRead(utf8 * script, size_t scriptLength, std::vector<utf8 *> saves)
|
||||
{
|
||||
std::vector<TitleCommand> commands;
|
||||
SDL_RWops * file = SDL_RWFromMem(script, (sint32)scriptLength);
|
||||
do {
|
||||
auto fs = MemoryStream(script, scriptLength);
|
||||
do
|
||||
{
|
||||
char parts[3 * 128], *token, *part1, *part2;
|
||||
LegacyScriptGetLine(file, parts);
|
||||
LegacyScriptGetLine(&fs, parts);
|
||||
|
||||
token = &parts[0 * 128];
|
||||
part1 = &parts[1 * 128];
|
||||
|
@ -466,13 +466,12 @@ static std::vector<TitleCommand> LegacyScriptRead(utf8 * script, size_t scriptLe
|
|||
{
|
||||
commands.push_back(command);
|
||||
}
|
||||
} while (SDL_RWtell(file) < (sint32)scriptLength);
|
||||
SDL_RWclose(file);
|
||||
|
||||
}
|
||||
while (fs.GetPosition() < scriptLength);
|
||||
return commands;
|
||||
}
|
||||
|
||||
static void LegacyScriptGetLine(SDL_RWops * file, char * parts)
|
||||
static void LegacyScriptGetLine(IStream * stream, char * parts)
|
||||
{
|
||||
for (sint32 i = 0; i < 3; i++)
|
||||
{
|
||||
|
@ -486,7 +485,7 @@ static void LegacyScriptGetLine(SDL_RWops * file, char * parts)
|
|||
for (; part < 3;)
|
||||
{
|
||||
sint32 c = 0;
|
||||
if (SDL_RWread(file, &c, 1, 1) != 1)
|
||||
if (stream->TryRead(&c, 1) != 1)
|
||||
{
|
||||
c = EOF;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
#include "../common.h"
|
||||
|
||||
struct SDL_RWops;
|
||||
|
||||
typedef struct TitleCommand
|
||||
{
|
||||
uint8 Type;
|
||||
|
|
|
@ -495,7 +495,7 @@ uint8 *util_zlib_inflate(uint8 *data, size_t data_in_size, size_t *data_out_size
|
|||
* @return Returns a pointer to memory holding compressed data or NULL on failure.
|
||||
* @note It is caller's responsibility to free() the returned pointer once done with it.
|
||||
*/
|
||||
uint8 *util_zlib_deflate(uint8 *data, size_t data_in_size, size_t *data_out_size)
|
||||
uint8 *util_zlib_deflate(const uint8 *data, size_t data_in_size, size_t *data_out_size)
|
||||
{
|
||||
sint32 ret = Z_OK;
|
||||
uLongf out_size = (uLongf)*data_out_size;
|
||||
|
|
|
@ -53,7 +53,7 @@ bool str_is_null_or_empty(const char *str);
|
|||
void util_srand(sint32 source);
|
||||
uint32 util_rand();
|
||||
|
||||
uint8 *util_zlib_deflate(uint8 *data, size_t data_in_size, size_t *data_out_size);
|
||||
uint8 *util_zlib_deflate(const uint8 *data, size_t data_in_size, size_t *data_out_size);
|
||||
uint8 *util_zlib_inflate(uint8 *data, size_t data_in_size, size_t *data_out_size);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue