コード例 #1
0
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);
}
コード例 #2
0
ファイル: net_server.c プロジェクト: Nekrofage/DoomRPi
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);
}
コード例 #3
0
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;
}
コード例 #4
0
ファイル: net_server.c プロジェクト: Nekrofage/DoomRPi
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;
}
コード例 #5
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);
}
コード例 #6
0
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;
}
コード例 #7
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);
}
コード例 #8
0
void NET_CL_LaunchGame(void)
{
    NET_Conn_NewReliable(&client_connection, NET_PACKET_TYPE_LAUNCH);
}