mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 11:03:00 +01:00
map load on join
This commit is contained in:
59
src/game.c
59
src/game.c
@@ -780,6 +780,63 @@ int game_load_sv6(SDL_RWops* rw)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Load game state for multiplayer
|
||||
int game_load_network(SDL_RWops* rw)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4;
|
||||
rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
|
||||
|
||||
// Read first chunk
|
||||
sawyercoding_read_chunk(rw, (uint8*)s6Header);
|
||||
if (s6Header->type == S6_TYPE_SAVEDGAME) {
|
||||
// Read packed objects
|
||||
if (s6Header->num_packed_objects > 0) {
|
||||
j = 0;
|
||||
for (i = 0; i < s6Header->num_packed_objects; i++)
|
||||
j += object_load_packed(rw);
|
||||
if (j > 0)
|
||||
object_list_load();
|
||||
}
|
||||
}
|
||||
|
||||
uint8 load_success = object_read_and_load_entries(rw);
|
||||
|
||||
// Read flags (16 bytes)
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR);
|
||||
|
||||
// Read map elements
|
||||
memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element));
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS);
|
||||
|
||||
// Read game data, including sprites
|
||||
sawyercoding_read_chunk(rw, (uint8*)0x010E63B8);
|
||||
|
||||
// Read checksum
|
||||
uint32 checksum;
|
||||
SDL_RWread(rw, &checksum, sizeof(uint32), 1);
|
||||
|
||||
if (!load_success){
|
||||
set_load_objects_fail_reason();
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5){
|
||||
RCT2_GLOBAL(0x14241BC, uint32) = 2;
|
||||
//call 0x0040705E Sets cursor position and something else. Calls maybe wind func 8 probably pointless
|
||||
RCT2_GLOBAL(0x14241BC, uint32) = 0;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_5;
|
||||
}
|
||||
|
||||
return 0;//This never gets called
|
||||
}
|
||||
|
||||
// The rest is the same as in scenario load and play
|
||||
reset_loaded_objects();
|
||||
map_update_tile_pointers();
|
||||
reset_0x69EBE4();
|
||||
openrct2_reset_object_tween_locations();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00675E1B
|
||||
@@ -860,8 +917,6 @@ void game_load_init()
|
||||
gGameSpeed = 1;
|
||||
|
||||
scenario_set_filename((char*)0x0135936C);
|
||||
|
||||
RCT2_GLOBAL(0x01388698, uint16) = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -127,6 +127,7 @@ void game_reduce_game_speed();
|
||||
|
||||
void game_load_or_quit_no_save_prompt();
|
||||
int game_load_sv6(SDL_RWops* rw);
|
||||
int game_load_network(SDL_RWops* rw);
|
||||
int game_load_save(const char *path);
|
||||
void game_load_init();
|
||||
void game_pause_toggle(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
|
||||
@@ -492,12 +492,12 @@ void Network::Client_Send_AUTH(const char* gameversion, const char* name, const
|
||||
server_connection.QueuePacket(std::move(packet));
|
||||
}
|
||||
|
||||
void Network::Server_Send_MAP()
|
||||
void Network::Server_Send_MAP(NetworkConnection* connection)
|
||||
{
|
||||
int buffersize = 0x600000;
|
||||
std::vector<uint8> buffer(buffersize);
|
||||
SDL_RWops* rw = SDL_RWFromMem(&buffer[0], buffersize);
|
||||
scenario_save(rw, 0);
|
||||
scenario_save_network(rw);
|
||||
int size = (int)SDL_RWtell(rw);
|
||||
int chunksize = 1000;
|
||||
for (int i = 0; i < size; i += chunksize) {
|
||||
@@ -505,7 +505,11 @@ void Network::Server_Send_MAP()
|
||||
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
|
||||
*packet << (uint32)NETWORK_COMMAND_MAP << (uint32)size << (uint32)i;
|
||||
packet->Write(&buffer[i], datasize);
|
||||
SendPacketToClients(*packet);
|
||||
if (connection) {
|
||||
connection->QueuePacket(std::move(packet));
|
||||
} else {
|
||||
SendPacketToClients(*packet);
|
||||
}
|
||||
}
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
@@ -744,6 +748,7 @@ int Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& pa
|
||||
sprintf(&text[2], "%s has joined the game", player->name);
|
||||
chat_history_add(text);
|
||||
gNetwork.Server_Send_CHAT(text);
|
||||
Server_Send_MAP(&connection);
|
||||
}
|
||||
}
|
||||
std::unique_ptr<NetworkPacket> responsepacket = std::move(NetworkPacket::Allocate());
|
||||
@@ -774,7 +779,7 @@ int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pac
|
||||
memcpy(&chunk_buffer[offset], (void*)packet.Read(chunksize), chunksize);
|
||||
if (offset + chunksize == size) {
|
||||
SDL_RWops* rw = SDL_RWFromMem(&chunk_buffer[0], size);
|
||||
if (game_load_sv6(rw)) {
|
||||
if (game_load_network(rw)) {
|
||||
game_load_init();
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) & 1)
|
||||
pause_toggle();
|
||||
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
bool CheckSRAND(uint32 tick, uint32 srand0);
|
||||
|
||||
void Client_Send_AUTH(const char* gameversion, const char* name, const char* password);
|
||||
void Server_Send_MAP();
|
||||
void Server_Send_MAP(NetworkConnection* connection = nullptr);
|
||||
void Client_Send_CHAT(const char* text);
|
||||
void Server_Send_CHAT(const char* text);
|
||||
void Client_Send_GAMECMD(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp, uint8 callback);
|
||||
|
||||
@@ -979,6 +979,72 @@ int scenario_save(SDL_RWops* rw, int flags)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Save game state without modifying any of the state for multiplayer
|
||||
int scenario_save_network(SDL_RWops* rw)
|
||||
{
|
||||
rct_window *w;
|
||||
rct_viewport *viewport;
|
||||
int viewX, viewY, viewZoom, viewRotation;
|
||||
|
||||
/*map_reorganise_elements();
|
||||
reset_0x69EBE4();
|
||||
sprite_clear_all_unused();
|
||||
sub_677552();
|
||||
sub_674BCF();*/
|
||||
|
||||
// Set saved view
|
||||
w = window_get_main();
|
||||
if (w != NULL) {
|
||||
viewport = w->viewport;
|
||||
|
||||
viewX = viewport->view_width / 2 + viewport->view_x;
|
||||
viewY = viewport->view_height / 2 + viewport->view_y;
|
||||
viewZoom = viewport->zoom;
|
||||
viewRotation = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8);
|
||||
} else {
|
||||
viewX = 0;
|
||||
viewY = 0;
|
||||
viewZoom = 0;
|
||||
viewRotation = 0;
|
||||
}
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, uint16) = viewX;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, uint16) = viewY;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, uint16) = viewZoom | (viewRotation << 8);
|
||||
|
||||
// Prepare S6
|
||||
rct_s6_data *s6 = malloc(sizeof(rct_s6_data));
|
||||
s6->header.type = S6_TYPE_SAVEDGAME;
|
||||
s6->header.num_packed_objects = scenario_get_num_packed_objects_to_write();
|
||||
s6->header.version = S6_RCT2_VERSION;
|
||||
s6->header.magic_number = S6_MAGIC_NUMBER;
|
||||
|
||||
memcpy(&s6->info, (rct_s6_info*)0x0141F570, sizeof(rct_s6_info));
|
||||
|
||||
for (int i = 0; i < 721; i++) {
|
||||
uint32 chunkPtr = RCT2_ADDRESS(0x009ACFA4, uint32)[i];
|
||||
rct_object_entry_extended *entry = &(RCT2_ADDRESS(0x00F3F03C, rct_object_entry_extended)[i]);
|
||||
|
||||
if (RCT2_ADDRESS(0x009ACFA4, uint32)[i] == 0xFFFFFFFF) {
|
||||
memset(&s6->objects[i], 0xFF, sizeof(rct_object_entry));
|
||||
} else {
|
||||
s6->objects[i] = *((rct_object_entry*)entry);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&s6->elapsed_months, (void*)0x00F663A8, 16);
|
||||
memcpy(s6->map_elements, (void*)0x00F663B8, 0x180000);
|
||||
memcpy(&s6->dword_010E63B8, (void*)0x010E63B8, 0x2E8570);
|
||||
|
||||
scenario_fix_ghosts(s6);
|
||||
scenario_save_s6(rw, s6);
|
||||
|
||||
free(s6);
|
||||
|
||||
gfx_invalidate_screen();
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6)
|
||||
{
|
||||
char *buffer;
|
||||
|
||||
@@ -427,6 +427,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);
|
||||
bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6);
|
||||
void scenario_set_filename(const char *value);
|
||||
void scenario_failure();
|
||||
|
||||
Reference in New Issue
Block a user