void NET_CL_StartGame(net_gamesettings_t *settings) { net_packet_t *packet; // Start from a ticcmd of all zeros memset(&last_ticcmd, 0, sizeof(ticcmd_t)); // Send packet packet = NET_Conn_NewReliable(&client_connection, NET_PACKET_TYPE_GAMESTART); NET_WriteSettings(packet, settings); }
static void NET_SV_SendConsoleMessage(net_client_t *client, char *s, ...) { char buf[1024]; va_list args; net_packet_t *packet; va_start(args, s); vsnprintf(buf, sizeof(buf), s, args); va_end(args); packet = NET_Conn_NewReliable(&client->connection, NET_PACKET_TYPE_CONSOLE_MESSAGE); NET_WriteString(packet, buf); }
static void NET_SV_ParseLaunch(net_packet_t *packet, net_client_t *client) { net_packet_t *launchpacket; int num_players; unsigned int i; NET_Log("server: processing launch packet"); // Only the controller can launch the game. if (client != NET_SV_Controller()) { NET_Log("server: error: this client isn't the controller, %d != %d", client, NET_SV_Controller()); return; } // Can only launch when we are in the waiting state. if (server_state != SERVER_WAITING_LAUNCH) { NET_Log("server: error: not in waiting launch state, state=%d", server_state); return; } // Forward launch on to all clients. NET_Log("server: sending launch to all clients"); NET_SV_AssignPlayers(); num_players = NET_SV_NumPlayers(); for (i=0; i<MAXNETNODES; ++i) { if (!ClientConnected(&clients[i])) continue; launchpacket = NET_Conn_NewReliable(&clients[i].connection, NET_PACKET_TYPE_LAUNCH); NET_WriteInt8(launchpacket, num_players); } // Now in launch state. server_state = SERVER_WAITING_START; }
static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client) { net_gamesettings_t settings; net_packet_t *startpacket; int nowtime; int i; if (client != NET_SV_Controller()) { // Only the controller can start a new game return; } if (!NET_ReadSettings(packet, &settings)) { // Malformed packet return; } // Check the game settings are valid if (!NET_ValidGameSettings(sv_gamemode, sv_gamemission, &settings)) { return; } if (server_state != SERVER_WAITING_START) { // Can only start a game if we are in the waiting start state. return; } // Assign player numbers NET_SV_AssignPlayers(); // Check if anyone is recording a demo and set lowres_turn if so. settings.lowres_turn = false; for (i=0; i<MAXPLAYERS; ++i) { if (sv_players[i] != NULL && sv_players[i]->recording_lowres) { settings.lowres_turn = true; } } nowtime = I_GetTimeMS(); // Send start packets to each connected node for (i=0; i<MAXNETNODES; ++i) { if (!ClientConnected(&clients[i])) continue; clients[i].last_gamedata_time = nowtime; startpacket = NET_Conn_NewReliable(&clients[i].connection, NET_PACKET_TYPE_GAMESTART); NET_WriteInt8(startpacket, NET_SV_NumPlayers()); NET_WriteInt8(startpacket, clients[i].player_number); NET_WriteSettings(startpacket, &settings); } // Change server state server_state = SERVER_IN_GAME; sv_settings = settings; memset(recvwindow, 0, sizeof(recvwindow)); recvwindow_start = 0; }
void NET_CL_StartGame(void) { net_packet_t *packet; net_gamesettings_t settings; int i; // Fill in game settings structure with appropriate parameters // for the new game settings.deathmatch = deathmatch; settings.episode = startepisode; settings.map = startmap; settings.skill = startskill; settings.loadgame = startloadgame; settings.gameversion = gameversion; settings.nomonsters = nomonsters; settings.fast_monsters = fastparm; settings.respawn_monsters = respawnparm; settings.timelimit = timelimit; //! // @category net // // Use original game sync code. // if (M_CheckParm("-oldsync") > 0) settings.new_sync = 0; else settings.new_sync = 1; //! // @category net // @arg <n> // // Send n extra tics in every packet as insurance against dropped // packets. // i = M_CheckParm("-extratics"); if (i > 0) settings.extratics = atoi(myargv[i+1]); else settings.extratics = 1; //! // @category net // @arg <n> // // Reduce the resolution of the game by a factor of n, reducing // the amount of network bandwidth needed. // i = M_CheckParm("-dup"); if (i > 0) settings.ticdup = atoi(myargv[i+1]); else settings.ticdup = 1; // Start from a ticcmd of all zeros memset(&last_ticcmd, 0, sizeof(ticcmd_t)); // Send packet packet = NET_Conn_NewReliable(&client_connection, NET_PACKET_TYPE_GAMESTART); NET_WriteSettings(packet, &settings); }
static void StartGame(void) { net_packet_t *startpacket; unsigned int i; int nowtime; // Assign player numbers NET_SV_AssignPlayers(); // Check if anyone is recording a demo and set lowres_turn if so. sv_settings.lowres_turn = false; for (i = 0; i < NET_MAXPLAYERS; ++i) { if (sv_players[i] != NULL && sv_players[i]->recording_lowres) { sv_settings.lowres_turn = true; } } sv_settings.num_players = NET_SV_NumPlayers(); // Copy player classes: for (i = 0; i < NET_MAXPLAYERS; ++i) { if (sv_players[i] != NULL) { sv_settings.player_classes[i] = sv_players[i]->player_class; } else { sv_settings.player_classes[i] = 0; } } nowtime = I_GetTimeMS(); // Send start packets to each connected node for (i = 0; i < MAXNETNODES; ++i) { if (!ClientConnected(&clients[i])) continue; clients[i].last_gamedata_time = nowtime; startpacket = NET_Conn_NewReliable(&clients[i].connection, NET_PACKET_TYPE_GAMESTART); sv_settings.consoleplayer = clients[i].player_number; NET_WriteSettings(startpacket, &sv_settings); } // Change server state server_state = SERVER_IN_GAME; memset(recvwindow, 0, sizeof(recvwindow)); recvwindow_start = 0; }
static void NET_SV_ParseSYN(net_packet_t *packet, net_client_t *client, net_addr_t *addr) { unsigned int magic; net_connect_data_t data; net_packet_t *reply; net_protocol_t protocol; char *player_name; char *client_version; int num_players; int i; NET_Log("server: processing SYN packet"); // Read the magic number and check it is the expected one. if (!NET_ReadInt32(packet, &magic)) { NET_Log("server: error: no magic number for SYN"); return; } switch (magic) { case NET_MAGIC_NUMBER: break; case NET_OLD_MAGIC_NUMBER: NET_Log("server: error: client using old magic number: %d", magic); NET_SV_SendReject(addr, "You are using an old client version that is not supported by " "this server. This server is running " PACKAGE_STRING "."); return; default: NET_Log("server: error: wrong magic number: %d", magic); return; } // Read the client version string. We actually now only use this when // sending a reject message, as we only reject if we can't negotiate a // common protocol (below). client_version = NET_ReadString(packet); if (client_version == NULL) { NET_Log("server: error: no version from client"); return; } // Read the client's list of accepted protocols. Net play between forks // of Chocolate Doom is accepted provided that they can negotiate a // common accepted protocol. protocol = NET_ReadProtocolList(packet); if (protocol == NET_PROTOCOL_UNKNOWN) { char reject_msg[256]; M_snprintf(reject_msg, sizeof(reject_msg), "Version mismatch: server version is: " PACKAGE_STRING "; " "client is: %s. No common compatible protocol could be " "negotiated.", client_version); NET_SV_SendReject(addr, reject_msg); NET_Log("server: error: no common protocol"); return; } // Read connect data, and check that the game mode/mission are valid // and the max_players value is in a sensible range. if (!NET_ReadConnectData(packet, &data)) { NET_Log("server: error: failed to read connect data"); return; } if (!D_ValidGameMode(data.gamemission, data.gamemode) || data.max_players > NET_MAXPLAYERS) { NET_Log("server: error: invalid connect data, max_players=%d, " "gamemission=%d, gamemode=%d", data.max_players, data.gamemission, data.gamemode); return; } // Read the player's name player_name = NET_ReadString(packet); if (player_name == NULL) { NET_Log("server: error: failed to read player name"); return; } // At this point we have received a valid SYN. // Not accepting new connections? if (server_state != SERVER_WAITING_LAUNCH) { NET_Log("server: error: not in waiting launch state, server_state=%d", server_state); NET_SV_SendReject(addr, "Server is not currently accepting connections"); return; } // Before accepting a new client, check that there is a slot free. NET_SV_AssignPlayers(); num_players = NET_SV_NumPlayers(); if ((!data.drone && num_players >= NET_SV_MaxPlayers()) || NET_SV_NumClients() >= MAXNETNODES) { NET_Log("server: no more players, num_players=%d, max=%d", num_players, NET_SV_MaxPlayers()); NET_SV_SendReject(addr, "Server is full!"); return; } // TODO: Add server option to allow rejecting clients which set // lowres_turn. This is potentially desirable as the presence of such // clients affects turning resolution. // Adopt the game mode and mission of the first connecting client: if (num_players == 0 && !data.drone) { sv_gamemode = data.gamemode; sv_gamemission = data.gamemission; NET_Log("server: new game, mode=%d, mission=%d", sv_gamemode, sv_gamemission); } // Check the connecting client is playing the same game as all // the other clients if (data.gamemode != sv_gamemode || data.gamemission != sv_gamemission) { char msg[128]; NET_Log("server: wrong mode/mission, %d != %d || %d != %d", data.gamemode, sv_gamemode, data.gamemission, sv_gamemission); M_snprintf(msg, sizeof(msg), "Game mismatch: server is %s (%s), client is %s (%s)", D_GameMissionString(sv_gamemission), D_GameModeString(sv_gamemode), D_GameMissionString(data.gamemission), D_GameModeString(data.gamemode)); NET_SV_SendReject(addr, msg); return; } // Allocate a client slot if there isn't one already if (client == NULL) { // find a slot, or return if none found for (i=0; i<MAXNETNODES; ++i) { if (!clients[i].active) { client = &clients[i]; break; } } if (client == NULL) { return; } } else { // If this is a recently-disconnected client, deactivate // to allow immediate reconnection if (client->connection.state == NET_CONN_STATE_DISCONNECTED) { client->active = false; } } // Client already connected? if (client->active) { NET_Log("server: client is already initialized (duplicate SYN?)"); return; } // Activate, initialize connection NET_SV_InitNewClient(client, addr, protocol); // Save the SHA1 checksums and other details. memcpy(client->wad_sha1sum, data.wad_sha1sum, sizeof(sha1_digest_t)); memcpy(client->deh_sha1sum, data.deh_sha1sum, sizeof(sha1_digest_t)); client->is_freedoom = data.is_freedoom; client->max_players = data.max_players; client->name = M_StringDuplicate(player_name); client->recording_lowres = data.lowres_turn; client->drone = data.drone; client->player_class = data.player_class; // Send a reply back to the client, indicating a successful connection // and specifying the protocol that will be used for communications. reply = NET_Conn_NewReliable(&client->connection, NET_PACKET_TYPE_SYN); NET_WriteString(reply, PACKAGE_STRING); NET_WriteProtocol(reply, protocol); }
void NET_CL_LaunchGame(void) { NET_Conn_NewReliable(&client_connection, NET_PACKET_TYPE_LAUNCH); }