From bb49e2b2a9bb4aefe76182be725e998bf9495976 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Sat, 25 Aug 2018 00:42:10 +0200 Subject: [PATCH] added sending level file (and level template) for network games As the level to play may not exist on the receiving side (but only on the sending side -- the client who initiates the network game), this change adds sending the level file (and the level template, if needed) to all receiving network clients, so all clients always play the exact same level (and do not have to worry about having the same level sets). --- src/files.c | 57 ++++++++++++++++++--- src/files.h | 1 + src/game.c | 1 + src/netserv.c | 11 ++++ src/netserv.h | 1 + src/network.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++---- src/network.h | 1 + 7 files changed, 193 insertions(+), 17 deletions(-) diff --git a/src/files.c b/src/files.c index bc996816..bb1ce497 100644 --- a/src/files.c +++ b/src/files.c @@ -2287,6 +2287,17 @@ static void setLevelFileInfo(struct LevelFileInfo *level_file_info, int nr) determineLevelFileInfo_Filetype(level_file_info); } +static void copyLevelFileInfo(struct LevelFileInfo *lfi_from, + struct LevelFileInfo *lfi_to) +{ + lfi_to->nr = lfi_from->nr; + lfi_to->type = lfi_from->type; + lfi_to->packed = lfi_from->packed; + + setString(&lfi_to->basename, lfi_from->basename); + setString(&lfi_to->filename, lfi_from->filename); +} + /* ------------------------------------------------------------------------- */ /* functions for loading R'n'D level */ /* ------------------------------------------------------------------------- */ @@ -6582,6 +6593,16 @@ static void LoadLevel_InitNativeEngines(struct LevelInfo *level) CopyNativeLevel_RND_to_Native(level); } +static void LoadLevelTemplate_LoadAndInit() +{ + LoadLevelFromFileInfo(&level_template, &level_template.file_info, FALSE); + + LoadLevel_InitVersion(&level_template); + LoadLevel_InitElements(&level_template); + + ActivateLevelTemplate(); +} + void LoadLevelTemplate(int nr) { if (!fileExists(getGlobalLevelTemplateFilename())) @@ -6593,22 +6614,27 @@ void LoadLevelTemplate(int nr) setLevelFileInfo(&level_template.file_info, nr); - LoadLevelFromFileInfo(&level_template, &level_template.file_info, FALSE); + LoadLevelTemplate_LoadAndInit(); +} - LoadLevel_InitVersion(&level_template); - LoadLevel_InitElements(&level_template); +static void LoadLevelTemplateFromNetwork(struct LevelFileInfo *lfi_network_template) +{ + copyLevelFileInfo(lfi_network_template, &level_template.file_info); - ActivateLevelTemplate(); + LoadLevelTemplate_LoadAndInit(); } -void LoadLevel(int nr) +static void LoadLevel_LoadAndInit(struct LevelFileInfo *lfi_network_template) { - setLevelFileInfo(&level.file_info, nr); - LoadLevelFromFileInfo(&level, &level.file_info, FALSE); if (level.use_custom_template) - LoadLevelTemplate(-1); + { + if (lfi_network_template != NULL) + LoadLevelTemplateFromNetwork(lfi_network_template); + else + LoadLevelTemplate(-1); + } LoadLevel_InitVersion(&level); LoadLevel_InitElements(&level); @@ -6617,6 +6643,13 @@ void LoadLevel(int nr) LoadLevel_InitNativeEngines(&level); } +void LoadLevel(int nr) +{ + setLevelFileInfo(&level.file_info, nr); + + LoadLevel_LoadAndInit(NULL); +} + void LoadLevelInfoOnly(int nr) { setLevelFileInfo(&level.file_info, nr); @@ -6624,6 +6657,14 @@ void LoadLevelInfoOnly(int nr) LoadLevelFromFileInfo(&level, &level.file_info, TRUE); } +void LoadLevelFromNetwork(struct LevelFileInfo *lfi_network_level, + struct LevelFileInfo *lfi_network_template) +{ + copyLevelFileInfo(lfi_network_level, &level.file_info); + + LoadLevel_LoadAndInit(lfi_network_template); +} + static int SaveLevel_VERS(FILE *file, struct LevelInfo *level) { int chunk_size = 0; diff --git a/src/files.h b/src/files.h index 4579f881..f823e1f2 100644 --- a/src/files.h +++ b/src/files.h @@ -37,6 +37,7 @@ void LoadLevelFromFilename(struct LevelInfo *, char *); void LoadLevel(int); void LoadLevelTemplate(int); void LoadLevelInfoOnly(int); +void LoadLevelFromNetwork(struct LevelFileInfo *, struct LevelFileInfo *); void SaveLevel(int); void SaveLevelTemplate(); void SaveNativeLevel(struct LevelInfo *); diff --git a/src/game.c b/src/game.c index 125e1666..380614c4 100644 --- a/src/game.c +++ b/src/game.c @@ -11228,6 +11228,7 @@ void StartGameActions(boolean init_network_game, boolean record_tape, if (init_network_game) { + SendToServer_LevelFile(); SendToServer_StartPlaying(); return; diff --git a/src/netserv.c b/src/netserv.c index 0a3661e1..eef7aa11 100644 --- a/src/netserv.c +++ b/src/netserv.c @@ -809,6 +809,13 @@ static void Handle_OP_BROADCAST_MESSAGE(struct NetworkServerPlayerInfo *player) SendNetworkBufferToAllButOne(write_buffer, player); } +static void Handle_OP_LEVEL_FILE(struct NetworkServerPlayerInfo *player) +{ + copyNetworkBufferForWriting(read_buffer, write_buffer, player->number); + + SendNetworkBufferToAllButOne(write_buffer, player); +} + void ExitNetworkServer(int exit_value) { Error(ERR_NETWORK_SERVER, "exiting network server"); @@ -1007,6 +1014,10 @@ void NetworkServer(int port, int serveronly) Handle_OP_BROADCAST_MESSAGE(player); break; + case OP_LEVEL_FILE: + Handle_OP_LEVEL_FILE(player); + break; + default: if (options.verbose) Error(ERR_NETWORK_SERVER, diff --git a/src/netserv.h b/src/netserv.h index d69deca7..baebb99c 100644 --- a/src/netserv.h +++ b/src/netserv.h @@ -33,6 +33,7 @@ #define OP_STOP_PLAYING 11 #define OP_MOVE_PLAYER 12 #define OP_BROADCAST_MESSAGE 13 +#define OP_LEVEL_FILE 14 #define MAX_BUFFER_SIZE 4096 diff --git a/src/network.c b/src/network.c index 72851746..bfe53c37 100644 --- a/src/network.c +++ b/src/network.c @@ -37,6 +37,15 @@ static struct NetworkClientPlayerInfo first_player = NULL }; +struct NetworkLevelFileInfo +{ + char *leveldir_identifier; + struct LevelFileInfo file_info; + struct LevelFileInfo tmpl_info; + boolean use_network_level_files; + boolean use_custom_template; +}; + /* server stuff */ static TCPsocket sfd; /* TCP server socket */ @@ -50,6 +59,8 @@ static boolean stop_network_game = FALSE; static boolean stop_network_client = FALSE; static char stop_network_client_message[MAX_OUTPUT_LINESIZE + 1]; +static struct NetworkLevelFileInfo network_level; + static void DrawNetworkTextExt(char *message, int font_nr, boolean initialize) { static int xpos = 0, ypos = 0; @@ -376,6 +387,44 @@ void SendToServer_NrWanted(int nr_wanted) SendNetworkBufferToServer(write_buffer); } +void SendToServer_LevelFile() +{ + initNetworkBufferForWriting(write_buffer, OP_LEVEL_FILE, 0); + + putNetworkBufferString( write_buffer, leveldir_current->identifier); + putNetworkBuffer16BitInteger(write_buffer, level.file_info.nr); + putNetworkBuffer8BitInteger( write_buffer, level.file_info.type); + putNetworkBuffer8BitInteger( write_buffer, level.file_info.packed); + putNetworkBufferString( write_buffer, level.file_info.basename); + putNetworkBufferFile( write_buffer, level.file_info.filename); + putNetworkBuffer8BitInteger( write_buffer, level.use_custom_template); + + if (level.use_custom_template) + { + putNetworkBufferString(write_buffer, level_template.file_info.basename); + putNetworkBufferFile( write_buffer, level_template.file_info.filename); + } + + SendNetworkBufferToServer(write_buffer); + + setString(&network_level.leveldir_identifier, leveldir_current->identifier); + + /* the sending client does not use network level files (but the real ones) */ + network_level.use_network_level_files = FALSE; + +#if 0 + printf("::: '%s'\n", leveldir_current->identifier); + printf("::: '%d'\n", level.file_info.nr); + printf("::: '%d'\n", level.file_info.type); + printf("::: '%d'\n", level.file_info.packed); + printf("::: '%s'\n", level.file_info.basename); + printf("::: '%s'\n", level.file_info.filename); + + if (level.use_custom_template) + printf("::: '%s'\n", level_template.file_info.filename); +#endif +} + void SendToServer_StartPlaying() { unsigned int new_random_seed = InitRND(level.random_seed); @@ -621,10 +670,7 @@ static void Handle_OP_START_PLAYING() int new_level_nr = getNetworkBuffer16BitInteger(read_buffer); unsigned int new_random_seed = getNetworkBuffer32BitInteger(read_buffer); - LevelDirTree *new_leveldir = - getTreeInfoFromIdentifier(leveldir_first, new_leveldir_identifier); - - if (new_leveldir == NULL) + if (!strEqual(new_leveldir_identifier, network_level.leveldir_identifier)) { Error(ERR_WARN, "no such level identifier: '%s'", new_leveldir_identifier); @@ -636,14 +682,24 @@ static void Handle_OP_START_PLAYING() printf("OP_START_PLAYING: %d\n", player_nr); Error(ERR_NETWORK_CLIENT, "client %d starts game [level %d from level identifier '%s']\n", - player_nr, new_level_nr, new_leveldir->identifier); + player_nr, new_level_nr, new_leveldir_identifier); + + LevelDirTree *new_leveldir = + getTreeInfoFromIdentifier(leveldir_first, new_leveldir_identifier); - leveldir_current = new_leveldir; - level_nr = new_level_nr; + if (new_leveldir != NULL) + { + leveldir_current = new_leveldir; + level_nr = new_level_nr; + } TapeErase(); - LoadTape(level_nr); - LoadLevel(level_nr); + + if (network_level.use_network_level_files) + LoadLevelFromNetwork(&network_level.file_info, + &network_level.tmpl_info); + else + LoadLevel(level_nr); StartGameActions(FALSE, setup.autorecord, new_random_seed); } @@ -746,6 +802,66 @@ static void Handle_OP_BROADCAST_MESSAGE() Error(ERR_NETWORK_CLIENT, "client %d sends message", player_nr); } +static void Handle_OP_LEVEL_FILE() +{ + int player_nr = getNetworkBuffer8BitInteger(read_buffer); + char *leveldir_identifier; + char *network_level_dir; + struct LevelFileInfo *file_info = &network_level.file_info; + struct LevelFileInfo *tmpl_info = &network_level.tmpl_info; + boolean use_custom_template; + + setString(&network_level.leveldir_identifier, NULL); + setString(&network_level.file_info.basename, NULL); + setString(&network_level.file_info.filename, NULL); + setString(&network_level.tmpl_info.basename, NULL); + setString(&network_level.tmpl_info.filename, NULL); + + printf("OP_LEVEL_FILE: %d\n", player_nr); + + leveldir_identifier = getStringCopy(getNetworkBufferString(read_buffer)); + network_level_dir = getNetworkLevelDir(leveldir_identifier); + + file_info->nr = getNetworkBuffer16BitInteger(read_buffer); + file_info->type = getNetworkBuffer8BitInteger(read_buffer); + file_info->packed = getNetworkBuffer8BitInteger(read_buffer); + file_info->basename = getStringCopy(getNetworkBufferString(read_buffer)); + file_info->filename = getPath2(network_level_dir, file_info->basename); + + InitNetworkLevelDirectory(leveldir_identifier); + + getNetworkBufferFile(read_buffer, file_info->filename); + + use_custom_template = getNetworkBuffer8BitInteger(read_buffer); + if (use_custom_template) + { + *tmpl_info = *file_info; + + tmpl_info->basename = getStringCopy(getNetworkBufferString(read_buffer)); + tmpl_info->filename = getPath2(network_level_dir, tmpl_info->basename); + + getNetworkBufferFile(read_buffer, tmpl_info->filename); + } + + network_level.leveldir_identifier = leveldir_identifier; + network_level.use_custom_template = use_custom_template; + + /* the receiving client(s) use(s) the transferred network level files */ + network_level.use_network_level_files = TRUE; + +#if 0 + printf("::: '%s'\n", leveldir_identifier); + printf("::: '%d'\n", file_info->nr); + printf("::: '%d'\n", file_info->type); + printf("::: '%d'\n", file_info->packed); + printf("::: '%s'\n", file_info->basename); + printf("::: '%s'\n", file_info->filename); + + if (use_custom_template) + printf("::: '%s'\n", tmpl_info->filename); +#endif +} + static void HandleNetworkingMessage() { stop_network_game = FALSE; @@ -804,6 +920,10 @@ static void HandleNetworkingMessage() Handle_OP_BROADCAST_MESSAGE(); break; + case OP_LEVEL_FILE: + Handle_OP_LEVEL_FILE(); + break; + default: if (options.verbose) Error(ERR_NETWORK_CLIENT, diff --git a/src/network.h b/src/network.h index c682105c..22a826c6 100644 --- a/src/network.h +++ b/src/network.h @@ -23,6 +23,7 @@ boolean ConnectToServer(char *, int); void SendToServer_PlayerName(char *); void SendToServer_ProtocolVersion(void); void SendToServer_NrWanted(int); +void SendToServer_LevelFile(void); void SendToServer_StartPlaying(void); void SendToServer_PausePlaying(void); void SendToServer_ContinuePlaying(void); -- 2.34.1