Exemplo n.º 1
0
void NET_SV_Shutdown(void)
{
    int i;
    boolean running;
    int start_time;

    if (!server_initialized)
    {
        return;
    }
    
    fprintf(stderr, "SV: Shutting down server...\n");

    // Disconnect all clients
    
    for (i=0; i<MAXNETNODES; ++i)
    {
        if (clients[i].active)
        {
            NET_SV_DisconnectClient(&clients[i]);
        }
    }

    // Wait for all clients to finish disconnecting

    start_time = I_GetTimeMS();
    running = true;

    while (running)
    {
        // Check if any clients are still not finished

        running = false;

        for (i=0; i<MAXNETNODES; ++i)
        {
            if (clients[i].active)
            {
                running = true;
            }
        }

        // Timed out?

        if (I_GetTimeMS() - start_time > 5000)
        {
            running = false;
            fprintf(stderr, "SV: Timed out waiting for clients to disconnect.\n");
        }

        // Run the client code in case this is a loopback client.

        NET_CL_Run();
        NET_SV_Run();

        // Don't hog the CPU

        I_Sleep(1);
    }
}
Exemplo n.º 2
0
static net_packet_t *BlockForPacket(net_addr_t *addr, unsigned int packet_type,
                                    unsigned int timeout_ms)
{
    net_packet_t *packet;
    net_addr_t *packet_src;
    unsigned int read_packet_type;
    unsigned int start_time;

    start_time = I_GetTimeMS();

    while (I_GetTimeMS() < start_time + timeout_ms)
    {
        if (!NET_RecvPacket(query_context, &packet_src, &packet))
        {
            I_Sleep(20);
            continue;
        }

        if (packet_src == addr
         && NET_ReadInt16(packet, &read_packet_type)
         && packet_type == read_packet_type)
        {
            return packet;
        }

        NET_FreePacket(packet);
    }

    // Timeout - no response.

    return NULL;
}
static void NET_CL_SendResendRequest(int start, int end)
{
    net_packet_t *packet;
    unsigned int nowtime;
    int i;

    //printf("CL: Send resend %i-%i\n", start, end);
    
    packet = NET_NewPacket(64);
    NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND);
    NET_WriteInt32(packet, start);
    NET_WriteInt8(packet, end - start + 1);
    NET_Conn_SendPacket(&client_connection, packet);
    NET_FreePacket(packet);

    nowtime = I_GetTimeMS();

    // Save the time we sent the resend request

    for (i=start; i<=end; ++i)
    {
        int index;

        index = i - recvwindow_start;

        if (index < 0 || index >= BACKUPTICS)
            continue;

        recvwindow[index].resend_time = nowtime;
    }
}
void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic)
{
    net_ticdiff_t diff;
    net_server_send_t *sendobj;
    int starttic, endtic;
    
    // Calculate the difference to the last ticcmd

    NET_TiccmdDiff(&last_ticcmd, ticcmd, &diff);
    
    // Store in the send queue

    sendobj = &send_queue[maketic % BACKUPTICS];
    sendobj->active = true;
    sendobj->seq = maketic;
    sendobj->time = I_GetTimeMS();
    sendobj->cmd = diff;

    last_ticcmd = *ticcmd;

    // Send to server.

    starttic = maketic - extratics;
    endtic = maketic;

    if (starttic < 0)
        starttic = 0;
    
    NET_CL_SendTics(starttic, endtic);
}
Exemplo n.º 5
0
static void UpdateMasterServer(void)
{
    unsigned int now;

    now = I_GetTimeMS();

    // The address of the master server can change. Periodically
    // re-resolve the master server to update.

    if (now - master_resolve_time > MASTER_RESOLVE_PERIOD * 1000)
    {
        net_addr_t *new_addr;
        printf("Re-resolve master server\n");

        new_addr = NET_Query_ResolveMaster(server_context);

        // Has the master server changed address?

        if (new_addr != NULL && new_addr != master_server)
        {
            NET_FreeAddress(master_server);
            master_server = new_addr;
        }

        master_resolve_time = now;
    }

    // Possibly refresh our registration with the master server.

    if (now - master_refresh_time > MASTER_REFRESH_PERIOD * 1000)
    {
        NET_Query_AddToMaster(master_server);
        master_refresh_time = now;
    }
}
Exemplo n.º 6
0
void NET_SV_RegisterWithMaster(void)
{
    //!
    // When running a server, don't register with the global master server.
    // Implies -server.
    //
    // @category net
    //

    if (!M_CheckParm("-privateserver"))
    {
        master_server = NET_Query_ResolveMaster(server_context);
    }
    else
    {
        master_server = NULL;
    }

    // Send request.

    if (master_server != NULL)
    {
        NET_Query_AddToMaster(master_server);
        master_refresh_time = I_GetTimeMS();
        master_resolve_time = master_refresh_time;
    }
}
Exemplo n.º 7
0
static void CheckTargetTimeouts(void)
{
    unsigned int i;
    unsigned int now;

    now = I_GetTimeMS();

    for (i = 0; i < num_targets; ++i)
    {
        /*
        printf("target %i: state %i, queries %i, query time %i\n",
               i, targets[i].state, targets[i].query_attempts,
               now - targets[i].query_time);
        */

        // We declare a target to be "no response" when we've sent
        // multiple query packets to it (QUERY_MAX_ATTEMPTS) and
        // received no response to any of them.

        if (targets[i].state == QUERY_TARGET_QUERIED
         && targets[i].query_attempts >= QUERY_MAX_ATTEMPTS
         && now - targets[i].query_time > QUERY_TIMEOUT_SECS * 1000)
        {
            targets[i].state = QUERY_TARGET_NO_RESPONSE;

            if (targets[i].type == QUERY_TARGET_MASTER)
            {
                fprintf(stderr, "NET_MasterQuery: no response "
                                "from master server.\n");
            }
        }
    }
}
Exemplo n.º 8
0
static int D_GetAdjustedTime(void)
{
    int time_ms;

    time_ms = I_GetTimeMS();
    time_ms += (offsetms / FRACUNIT);

    return (time_ms * TICRATE) / 1000;
}
Exemplo n.º 9
0
static void SendOneQuery(void)
{
    unsigned int now;
    unsigned int i;

    now = I_GetTimeMS();

    // Rate limit - only send one query every 50ms.

    if (now - last_query_time < 50)
    {
        return;
    }

    for (i = 0; i < num_targets; ++i)
    {
        // Not queried yet?
        // Or last query timed out without a response?

        if (targets[i].state == QUERY_TARGET_QUEUED
         || (targets[i].state == QUERY_TARGET_QUERIED
             && now - targets[i].query_time > QUERY_TIMEOUT_SECS * 1000))
        {
            break;
        }
    }

    if (i >= num_targets)
    {
        return;
    }

    // Found a target to query.  Send a query; how to do this depends on
    // the target type.

    switch (targets[i].type)
    {
        case QUERY_TARGET_SERVER:
            NET_Query_SendQuery(targets[i].addr);
            break;

        case QUERY_TARGET_BROADCAST:
            NET_Query_SendQuery(NULL);
            break;

        case QUERY_TARGET_MASTER:
            NET_Query_SendMasterQuery(targets[i].addr);
            break;
    }

    //printf("Queried %s\n", NET_AddrToString(targets[i].addr));
    targets[i].state = QUERY_TARGET_QUERIED;
    targets[i].query_time = now;
    ++targets[i].query_attempts;

    last_query_time = now;
}
Exemplo n.º 10
0
void NET_SV_CheckDeadlock(net_client_t *client)
{
    int nowtime;
    int i;

    // Don't expect game data from clients.

    if (client->drone)
    {
        return;
    }

    nowtime = I_GetTimeMS();

    // If we haven't received anything for a long time, it may be a deadlock.

    if (nowtime - client->last_gamedata_time > 1000)
    {
        NET_Log("server: no gamedata from %s since %d - deadlock?",
                NET_AddrToString(client->addr),
                client->last_gamedata_time);

        // Search the receive window for the first tic we are expecting
        // from this player.

        for (i=0; i<BACKUPTICS; ++i)
        {
            if (!recvwindow[client->player_number][i].active)
            {
                NET_Log("server: deadlock: sending resend request for %d-%d",
                        recvwindow_start + i, recvwindow_start + i + 5);

                // Found a tic we haven't received.  Send a resend request.

                NET_SV_SendResendRequest(client,
                                         recvwindow_start + i,
                                         recvwindow_start + i + 5);

                client->last_gamedata_time = nowtime;
                break;
            }
        }

        // If we sent a resend request to break the deadlock, also trigger a
        // resend of any tics we have sitting in the send queue, in case the
        // client is blocked waiting on tics from us that have been lost.
        // This fixes deadlock with some older clients which do not send
        // resends to break deadlock.
        if (i < BACKUPTICS && client->sendseq > client->acknowledged)
        {
            NET_Log("server: also resending tics %d-%d to break deadlock",
                    client->acknowledged, client->sendseq - 1);
            NET_SV_SendTics(client, client->acknowledged, client->sendseq - 1);
        }
    }
}
Exemplo n.º 11
0
boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet, 
                        unsigned int *packet_type)
{
    conn->keepalive_recv_time = I_GetTimeMS();

    // Is this a reliable packet?

    if (*packet_type & NET_RELIABLE_PACKET)
    {
        if (NET_Conn_ReliablePacket(conn, packet)) 
        {
            // Invalid packet: eat it.

            return true;
        }

        // Remove the reliable bit

        *packet_type &= ~NET_RELIABLE_PACKET;
    }
    
    switch (*packet_type)
    {
        case NET_PACKET_TYPE_ACK:
            NET_Conn_ParseACK(conn, packet);
            break;
        case NET_PACKET_TYPE_DISCONNECT:
            NET_Conn_ParseDisconnect(conn, packet);
            break;
        case NET_PACKET_TYPE_DISCONNECT_ACK:
            NET_Conn_ParseDisconnectACK(conn, packet);
            break;
        case NET_PACKET_TYPE_KEEPALIVE:
            // No special action needed.
            break;
        case NET_PACKET_TYPE_REJECTED:
            NET_Conn_ParseReject(conn, packet);
            break;
        case NET_PACKET_TYPE_RELIABLE_ACK:
            NET_Conn_ParseReliableACK(conn, packet);
            break;
        default:
            // Not a common packet

            return false;
    }

    // We found a packet that we found interesting, and ate it.

    return true;
}
void NET_CL_Disconnect(void)
{
    int start_time;

    if (!net_client_connected)
    {
        return;
    }
    
    NET_Conn_Disconnect(&client_connection);

    start_time = I_GetTimeMS();

    while (client_connection.state != NET_CONN_STATE_DISCONNECTED
        && client_connection.state != NET_CONN_STATE_DISCONNECTED_SLEEP)
    {
        if (I_GetTimeMS() - start_time > 5000)
        {
            // time out after 5 seconds
            
            client_state = NET_CONN_STATE_DISCONNECTED;

            fprintf(stderr, "NET_CL_Disconnect: Timeout while disconnecting from server\n");
            break;
        }

        NET_CL_Run();
        NET_SV_Run();

        I_Sleep(1);
    }

    // Finished sending disconnect packets, etc.

    NET_CL_Shutdown();
}
Exemplo n.º 13
0
//
// haleyjd 20140904: [SVE]
// Choco's sound engine won't tolerate the main loop running at full blast 
// and turns into chop city. We must give up a non-trivial amount of CPU
// time on a consistent basis.
//
static boolean FE_CapFrameRate(void)
{
    float frameMillis = 1000.0f / frontend_fpslimit;
    int   curTics = I_GetTimeMS();
    float elapsed = (float)(curTics - frontend_ticcount);
    
    if(elapsed < frameMillis)
    {
        if(frameMillis - elapsed > 3.0f)
            I_Sleep(2);
        return true;
    }

    return false;
}
Exemplo n.º 14
0
static int GetAdjustedTime(void)
{
    int time_ms;

    time_ms = I_GetTimeMS();

    if (net_cl_new_sync)
    {
        // Use the adjustments from net_client.c only if we are
        // using the new sync mode.

        time_ms += (offsetms / FRACUNIT);
    }

    return (time_ms * TICRATE) / 1000;
}
Exemplo n.º 15
0
static void NET_Conn_ParseDisconnect(net_connection_t *conn, net_packet_t *packet)
{
    net_packet_t *reply;

    // Other end wants to disconnect
    // Send a DISCONNECT_ACK reply.
    
    reply = NET_NewPacket(10);
    NET_WriteInt16(reply, NET_PACKET_TYPE_DISCONNECT_ACK);
    NET_Conn_SendPacket(conn, reply);
    NET_FreePacket(reply);

    conn->last_send_time = I_GetTimeMS();
    
    conn->state = NET_CONN_STATE_DISCONNECTED_SLEEP;
    conn->disconnect_reason = NET_DISCONNECT_REMOTE;
}
Exemplo n.º 16
0
static void NET_SV_InitNewClient(net_client_t *client, 
                                 net_addr_t *addr,
                                 char *player_name)
{
    client->active = true;
    client->connect_time = I_GetTimeMS();
    NET_Conn_InitServer(&client->connection, addr);
    client->addr = addr;
    client->last_send_time = -1;
    client->name = strdup(player_name);

    // init the ticcmd send queue

    client->sendseq = 0;
    client->acknowledged = 0;
    client->drone = false;

    client->last_gamedata_time = 0;

    memset(client->sendqueue, 0xff, sizeof(client->sendqueue));
}
Exemplo n.º 17
0
static void NET_SV_SendResendRequest(net_client_t *client, int start, int end)
{
    net_packet_t *packet;
    net_client_recv_t *recvobj;
    int i;
    unsigned int nowtime;
    int index;

    NET_Log("server: send resend to %s for tics %d-%d",
            NET_AddrToString(client->addr), start, end);

    packet = NET_NewPacket(20);

    NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND);
    NET_WriteInt32(packet, start);
    NET_WriteInt8(packet, end - start + 1);

    NET_Conn_SendPacket(&client->connection, packet);
    NET_FreePacket(packet);

    // Store the time we send the resend request

    nowtime = I_GetTimeMS();

    for (i=start; i<=end; ++i)
    {
        index = i - recvwindow_start;

        if (index >= BACKUPTICS)
        {
            // Outside the range

            continue;
        }
        
        recvobj = &recvwindow[index][client->player_number];

        recvobj->resend_time = nowtime;
    }
}
Exemplo n.º 18
0
void NET_SV_CheckDeadlock(net_client_t *client)
{
    int nowtime;
    int i;

    // Don't expect game data from clients.

    if (client->drone)
    {
        return;
    }

    nowtime = I_GetTimeMS();

    // If we haven't received anything for a long time, it may be a deadlock.

    if (nowtime - client->last_gamedata_time > 1000)
    {
        // Search the receive window for the first tic we are expecting
        // from this player.

        for (i=0; i<BACKUPTICS; ++i)
        {
            if (!recvwindow[client->player_number][i].active)
            {
                //printf("Possible deadlock: Sending resend request\n");

                // Found a tic we haven't received.  Send a resend request.

                NET_SV_SendResendRequest(client,
                                         recvwindow_start + i,
                                         recvwindow_start + i + 5);

                client->last_gamedata_time = nowtime;
                break;
            }
        }
    }
}
Exemplo n.º 19
0
static void NET_SV_InitNewClient(net_client_t *client, net_addr_t *addr,
                                 net_protocol_t protocol)
{
    client->active = true;
    client->connect_time = I_GetTimeMS();
    NET_Conn_InitServer(&client->connection, addr, protocol);
    client->addr = addr;
    NET_ReferenceAddress(addr);
    client->last_send_time = -1;

    // init the ticcmd send queue

    client->sendseq = 0;
    client->acknowledged = 0;
    client->drone = false;
    client->ready = false;

    client->last_gamedata_time = 0;

    memset(client->sendqueue, 0xff, sizeof(client->sendqueue));

    NET_Log("server: initialized new client from %s", NET_AddrToString(addr));
}
static void NET_CL_ParseGameData(net_packet_t *packet)
{
    net_server_recv_t *recvobj;
    unsigned int seq, num_tics;
    unsigned int nowtime;
    int resend_start, resend_end;
    size_t i;
    int index;
    
    // Read header
    
    if (!NET_ReadInt8(packet, &seq)
     || !NET_ReadInt8(packet, &num_tics))
    {
        return;
    }

    nowtime = I_GetTimeMS();

    // Whatever happens, we now need to send an acknowledgement of our
    // current receive point.

    if (!need_to_acknowledge)
    {
        need_to_acknowledge = true;
        gamedata_recv_time = nowtime;
    }

    // Expand byte value into the full tic number

    seq = NET_CL_ExpandTicNum(seq);

    for (i=0; i<num_tics; ++i)
    {
        net_full_ticcmd_t cmd;

        index = seq - recvwindow_start + i;

        if (!NET_ReadFullTiccmd(packet, &cmd, lowres_turn))
        {
            return;
        }

        if (index < 0 || index >= BACKUPTICS)
        {
            // Out of range of the recv window

            continue;
        }

        // Store in the receive window
        
        recvobj = &recvwindow[index];

        recvobj->active = true;
        recvobj->cmd = cmd;
    }

    // Has this been received out of sequence, ie. have we not received
    // all tics before the first tic in this packet?  If so, send a 
    // resend request.

    //printf("CL: %p: %i\n", client, seq);

    resend_end = seq - recvwindow_start;

    if (resend_end <= 0)
        return;

    if (resend_end >= BACKUPTICS)
        resend_end = BACKUPTICS - 1;

    index = resend_end - 1;
    resend_start = resend_end;
    
    while (index >= 0)
    {
        recvobj = &recvwindow[index];

        if (recvobj->active)
        {
            // ended our run of unreceived tics

            break;
        }

        if (recvobj->resend_time != 0)
        {
            // Already sent a resend request for this tic

            break;
        }

        resend_start = index;
        --index;
    }

    // Possibly send a resend request

    if (resend_start < resend_end)
    {
        NET_CL_SendResendRequest(recvwindow_start + resend_start, 
                                 recvwindow_start + resend_end - 1);
    }
}
Exemplo n.º 21
0
static void NET_Query_ParseResponse(net_addr_t *addr, net_packet_t *packet,
                                    net_query_callback_t callback,
                                    void *user_data)
{
    unsigned int packet_type;
    net_querydata_t querydata;
    query_target_t *target;

    // Read the header

    if (!NET_ReadInt16(packet, &packet_type)
     || packet_type != NET_PACKET_TYPE_QUERY_RESPONSE)
    {
        return;
    }

    // Read query data

    if (!NET_ReadQueryData(packet, &querydata))
    {
        return;
    }

    // Find the target that responded.

    target = GetTargetForAddr(addr, false);

    // If the target is not found, it may be because we are doing
    // a LAN broadcast search, in which case we need to create a
    // target for the new responder.

    if (target == NULL)
    {
        query_target_t *broadcast_target;

        broadcast_target = GetTargetForAddr(NULL, false);

        // Not in broadcast mode, unexpected response that came out
        // of nowhere. Ignore.

        if (broadcast_target == NULL
         || broadcast_target->state != QUERY_TARGET_QUERIED)
        {
            return;
        }

        // Create new target.

        target = GetTargetForAddr(addr, true);
        target->state = QUERY_TARGET_QUERIED;
        target->query_time = broadcast_target->query_time;
    }

    if (target->state != QUERY_TARGET_RESPONDED)
    {
        target->state = QUERY_TARGET_RESPONDED;
        memcpy(&target->data, &querydata, sizeof(net_querydata_t));

        // Calculate RTT.

        target->ping_time = I_GetTimeMS() - target->query_time;

        // Invoke callback to signal that we have a new address.

        callback(addr, &target->data, target->ping_time, user_data);
    }
}
Exemplo n.º 22
0
static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client)
{
    net_client_recv_t *recvobj;
    unsigned int seq;
    unsigned int ackseq;
    unsigned int num_tics;
    unsigned int nowtime;
    size_t i;
    int player;
    int resend_start, resend_end;
    int index;

    if (server_state != SERVER_IN_GAME)
    {
        return;
    }

    if (client->drone)
    {
        // Drones do not contribute any game data.
        return;
    }

    player = client->player_number;

    // Read header

    if (!NET_ReadInt8(packet, &ackseq)
     || !NET_ReadInt8(packet, &seq)
     || !NET_ReadInt8(packet, &num_tics))
    {
        return;
    }

    // Get the current time

    nowtime = I_GetTimeMS();

    // Expand 8-bit values to the full sequence number

    ackseq = NET_SV_ExpandTicNum(ackseq);
    seq = NET_SV_ExpandTicNum(seq);

    // Sanity checks

    for (i=0; i<num_tics; ++i)
    {
        net_ticdiff_t diff;
        signed int latency;

        if (!NET_ReadSInt16(packet, &latency)
         || !NET_ReadTiccmdDiff(packet, &diff, sv_settings.lowres_turn))
        {
            return;
        }

        index = seq + i - recvwindow_start;

        if (index < 0 || index >= BACKUPTICS)
        {
            // Not in range of the recv window

            continue;
        }

        recvobj = &recvwindow[index][player];
        recvobj->active = true;
        recvobj->diff = diff;
        recvobj->latency = latency;

        client->last_gamedata_time = nowtime;
    }

    // Higher acknowledgement point?

    if (ackseq > client->acknowledged)
    {
        client->acknowledged = ackseq;
    }

    // Has this been received out of sequence, ie. have we not received
    // all tics before the first tic in this packet?  If so, send a 
    // resend request.

    //printf("SV: %p: %i\n", client, seq);

    resend_end = seq - recvwindow_start;

    if (resend_end <= 0)
        return;

    if (resend_end >= BACKUPTICS)
        resend_end = BACKUPTICS - 1;

    index = resend_end - 1;
    resend_start = resend_end;
    
    while (index >= 0)
    {
        recvobj = &recvwindow[index][player];

        if (recvobj->active)
        {
            // ended our run of unreceived tics

            break;
        }

        if (recvobj->resend_time != 0)
        {
            // Already sent a resend request for this tic

            break;
        }

        resend_start = index;
        --index;
    }

    // Possibly send a resend request

    if (resend_start < resend_end)
    {
            /*
        printf("missed %i-%i before %i, send resend\n",
                        recvwindow_start + resend_start,
                        recvwindow_start + resend_end - 1,
                        seq);
                        */
        NET_SV_SendResendRequest(client, 
                                 recvwindow_start + resend_start, 
                                 recvwindow_start + resend_end - 1);
    }
}
Exemplo n.º 23
0
static void NET_SV_CheckResends(net_client_t *client)
{
    int i;
    int player;
    int resend_start, resend_end;
    unsigned int nowtime;

    nowtime = I_GetTimeMS();

    player = client->player_number;
    resend_start = -1;
    resend_end = -1;

    for (i=0; i<BACKUPTICS; ++i)
    {
        net_client_recv_t *recvobj;
        boolean need_resend;

        recvobj = &recvwindow[i][player];

        // if need_resend is true, this tic needs another retransmit
        // request (300ms timeout)

        need_resend = !recvobj->active
                   && recvobj->resend_time != 0
                   && nowtime > recvobj->resend_time + 300;

        if (need_resend)
        {
            // Start a new run of resend tics?
 
            if (resend_start < 0)
            {
                resend_start = i;
            }
            
            resend_end = i;
        }
        else
        {
            if (resend_start >= 0)
            {
                // End of a run of resend tics

                //printf("SV: resend request timed out: %i-%i\n", resend_start, resend_end);
                NET_SV_SendResendRequest(client, 
                                         recvwindow_start + resend_start,
                                         recvwindow_start + resend_end);

                resend_start = -1;
            }
        }
    }

    if (resend_start >= 0)
    {
        NET_SV_SendResendRequest(client, 
                                 recvwindow_start + resend_start,
                                 recvwindow_start + resend_end);
    }
}
Exemplo n.º 24
0
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;
}
Exemplo n.º 25
0
static void HU_DrawHUD(void)
{
    const int           health = MAX(0, plr->health);
    const weapontype_t  pendingweapon = plr->pendingweapon;
    const weapontype_t  readyweapon = plr->readyweapon;
    int                 ammotype = weaponinfo[readyweapon].ammo;
    int                 ammo = plr->ammo[ammotype];
    const int           armor = plr->armorpoints;
    int                 health_x = HUD_HEALTH_X;
    int                 keys = 0;
    int                 i = 0;
    byte                *tinttab;
    const int           invulnerability = plr->powers[pw_invulnerability];
    static dboolean     healthanim;
    patch_t             *patch;
    const dboolean      gamepaused = (menuactive || paused || consoleactive);
    const int           currenttime = I_GetTimeMS();

    tinttab = (!health || (health <= HUD_HEALTH_MIN && healthanim) || health > HUD_HEALTH_MIN ? tinttab66 :
        tinttab25);

    patch = (((readyweapon == wp_fist && pendingweapon == wp_nochange) || pendingweapon == wp_fist)
        && plr->powers[pw_strength] ? berserkpatch : healthpatch);

    if (patch)
    {
        if ((plr->cheats & CF_GODMODE) || invulnerability > STARTFLASHING || (invulnerability & 8))
            godhudfunc(health_x, HUD_HEALTH_Y - (SHORT(patch->height) - 17), patch, tinttab);
        else
            hudfunc(health_x, HUD_HEALTH_Y - (SHORT(patch->height) - 17), patch, tinttab);

        health_x += SHORT(patch->width) + 8;
    }

    if (healthhighlight > currenttime)
    {
        DrawHUDNumber(&health_x, HUD_HEALTH_Y + hudnumoffset, MAX((minuspatch ? health_min : 0),
            plr->health), tinttab, V_DrawHighlightedHUDNumberPatch);

        if (!emptytallpercent)
            V_DrawHighlightedHUDNumberPatch(health_x, HUD_HEALTH_Y + hudnumoffset, tallpercent, tinttab);
    }
    else
    {
        DrawHUDNumber(&health_x, HUD_HEALTH_Y + hudnumoffset, MAX((minuspatch ? health_min : 0), plr->health),
            tinttab, hudnumfunc);

        if (!emptytallpercent)
            hudnumfunc(health_x, HUD_HEALTH_Y + hudnumoffset, tallpercent, tinttab);
    }

    if (!gamepaused)
    {
        static int  healthwait;

        if (health <= HUD_HEALTH_MIN)
        {
            if (healthwait < currenttime)
            {
                healthanim = !healthanim;
                healthwait = currenttime + HUD_HEALTH_WAIT * health / HUD_HEALTH_MIN + 115;
            }
        }
        else
        {
            healthanim = false;
            healthwait = 0;
        }
    }

    if (pendingweapon != wp_nochange)
    {
        ammotype = weaponinfo[pendingweapon].ammo;
        ammo = plr->ammo[ammotype];
    }

    if (health && ammo && ammotype != am_noammo)
    {
        int             ammo_x = HUD_AMMO_X + ammopic[ammotype].x;
        static dboolean ammoanim;

        tinttab = ((ammo <= HUD_AMMO_MIN && ammoanim) || ammo > HUD_AMMO_MIN ? tinttab66 : tinttab25);

        if ((patch = ammopic[ammotype].patch))
        {
            hudfunc(ammo_x, HUD_AMMO_Y + ammopic[ammotype].y, patch, tinttab);
            ammo_x += SHORT(patch->width) + 8;
        }

        if (ammohighlight > currenttime)
            DrawHUDNumber(&ammo_x, HUD_AMMO_Y + hudnumoffset, ammo, tinttab,
                V_DrawHighlightedHUDNumberPatch);
        else
            DrawHUDNumber(&ammo_x, HUD_AMMO_Y + hudnumoffset, ammo, tinttab, hudnumfunc);

        if (!gamepaused)
        {
            static int  ammowait;

            if (ammo <= HUD_AMMO_MIN)
            {
                if (ammowait < currenttime)
                {
                    ammoanim = !ammoanim;
                    ammowait = currenttime + HUD_AMMO_WAIT * ammo / HUD_AMMO_MIN + 115;
                }
            }
            else
            {
                ammoanim = false;
                ammowait = 0;
            }
        }
    }

    while (i < NUMCARDS)
        if (plr->cards[i++] > 0)
            keys++;

    if (keys || plr->neededcardflash)
    {
        int             keypic_x = HUD_KEYS_X - 20 * (keys - 1);
        static int      keywait;
        static dboolean showkey;

        if (!armor)
            keypic_x += 114;
        else
        {
            if (emptytallpercent)
                keypic_x += tallpercentwidth;

            if (armor < 10)
                keypic_x += 26;
            else if (armor < 100)
                keypic_x += 12;
        }

        if (plr->neededcardflash)
        {
            if ((patch = keypic[plr->neededcard].patch))
            {
                if (!gamepaused && keywait < currenttime)
                {
                    showkey = !showkey;
                    keywait = currenttime + HUD_KEY_WAIT;
                    plr->neededcardflash--;
                }

                if (showkey)
                    hudfunc(keypic_x - SHORT(patch->width) - 6, HUD_KEYS_Y, patch, tinttab66);
            }
        }
        else
        {
            showkey = false;
            keywait = 0;
        }

        for (i = 0; i < NUMCARDS; i++)
            if (plr->cards[i] > 0 && (patch = keypic[i].patch))
                hudfunc(keypic_x + (SHORT(patch->width) + 6) * (cardsfound - plr->cards[i]), HUD_KEYS_Y,
                    patch, tinttab66);
    }

    if (armor)
    {
        int armor_x = HUD_ARMOR_X;

        if ((patch = (plr->armortype == GREENARMOR ? greenarmorpatch : bluearmorpatch)))
        {
            armor_x -= SHORT(patch->width);
            hudfunc(armor_x, HUD_ARMOR_Y - (SHORT(patch->height) - 16), patch, tinttab66);
            armor_x -= 7;
        }

        if (armorhighlight > currenttime)
        {
            if (emptytallpercent)
            {
                armor_x -= HUDNumberWidth(armor);
                DrawHUDNumber(&armor_x, HUD_ARMOR_Y + hudnumoffset, armor, tinttab66,
                    V_DrawHighlightedHUDNumberPatch);
            }
            else
            {
                armor_x -= tallpercentwidth;
                V_DrawHighlightedHUDNumberPatch(armor_x, HUD_ARMOR_Y + hudnumoffset, tallpercent, tinttab66);
                armor_x -= HUDNumberWidth(armor);
                DrawHUDNumber(&armor_x, HUD_ARMOR_Y + hudnumoffset, armor, tinttab66,
                    V_DrawHighlightedHUDNumberPatch);
            }
        }
        else if (emptytallpercent)
        {
            armor_x -= HUDNumberWidth(armor);
            DrawHUDNumber(&armor_x, HUD_ARMOR_Y + hudnumoffset, armor, tinttab66, hudnumfunc);
        }
        else
        {
            armor_x -= tallpercentwidth;
            hudnumfunc(armor_x, HUD_ARMOR_Y + hudnumoffset, tallpercent, tinttab66);
            armor_x -= HUDNumberWidth(armor);
            DrawHUDNumber(&armor_x, HUD_ARMOR_Y + hudnumoffset, armor, tinttab66, hudnumfunc);
        }
    }
}
Exemplo n.º 26
0
static void HU_DrawAltHUD(void)
{
    int health = MAX(health_min, plr->health);
    int armor = plr->armorpoints;
    int color2 = (health <= 20 ? red : (health >= 100 ? green : white));
    int color1 = color2 + (color2 == green ? coloroffset : 0);
    int keys = 0;
    int i = 0;
    int powerup = 0;
    int powerupbar = 0;
    int max;

    DrawAltHUDNumber(ALTHUD_LEFT_X + 35 - AltHUDNumberWidth(ABS(health)), ALTHUD_Y + 12, health);
    health = MAX(0, plr->health) * 200 / maxhealth;

    if (health > 100)
    {
        fillrectfunc(0, ALTHUD_LEFT_X + 60, ALTHUD_Y + 13, 101, 8, color1);
        fillrectfunc(0, ALTHUD_LEFT_X + 60, ALTHUD_Y + 13, MAX(1, health - 100) + (health == 200), 8, color2);
        althudfunc(ALTHUD_LEFT_X + 40, ALTHUD_Y + 1, altleftpatch, WHITE, white);
        althudfunc(ALTHUD_LEFT_X + 60, ALTHUD_Y + 13, altendpatch, WHITE, color2);
        althudfunc(ALTHUD_LEFT_X + 60 + 98, ALTHUD_Y + 13, altmarkpatch, WHITE, color1);
        althudfunc(ALTHUD_LEFT_X + 60 + health - 100 - (health < 200) - 2, ALTHUD_Y + 10, altmark2patch,
            WHITE, color2);
    }
    else
    {
        fillrectfunc(0, ALTHUD_LEFT_X + 60, ALTHUD_Y + 13, MAX(1, health) + (health == 100), 8, color1);
        althudfunc(ALTHUD_LEFT_X + 40, ALTHUD_Y + 1, altleftpatch, WHITE, white);
        althudfunc(ALTHUD_LEFT_X + 60, ALTHUD_Y + 13, altendpatch, WHITE, color1);
        althudfunc(ALTHUD_LEFT_X + 60 + MAX(1, health) - (health < 100) - 2, ALTHUD_Y + 13, altmarkpatch,
            WHITE, color1);
    }

    if (armor)
    {
        color2 = (plr->armortype == GREENARMOR ? gray : lightgray);
        color1 = color2 + coloroffset;
        althudfunc(ALTHUD_LEFT_X + 43, ALTHUD_Y, altarmpatch, WHITE, color2);
        DrawAltHUDNumber2(ALTHUD_LEFT_X + 35 - AltHUDNumber2Width(armor), ALTHUD_Y, armor, color2);
        armor = armor * 200 / max_armor;

        if (armor > 100)
        {
            fillrectfunc(0, ALTHUD_LEFT_X + 60, ALTHUD_Y + 2, 100 + 1, 4, color1);
            fillrectfunc(0, ALTHUD_LEFT_X + 60, ALTHUD_Y + 2, armor - 100 + (armor == 200), 4, color2);
        }
        else
            fillrectfunc(0, ALTHUD_LEFT_X + 60, ALTHUD_Y + 2, armor + (armor == 100), 4, color1);
    }
    else
        althudfunc(ALTHUD_LEFT_X + 43, ALTHUD_Y, altarmpatch, WHITE, darkgray);

    if (health)
    {
        const weapontype_t  pendingweapon = plr->pendingweapon;
        const weapontype_t  weapon = (pendingweapon != wp_nochange ? pendingweapon : plr->readyweapon);
        const ammotype_t    ammotype = weaponinfo[weapon].ammo;

        if (ammotype != am_noammo)
        {
            int ammo = plr->ammo[ammotype];

            DrawAltHUDNumber(ALTHUD_RIGHT_X + 101 - AltHUDNumberWidth(ammo), ALTHUD_Y - 1, ammo);
            ammo = 100 * ammo / plr->maxammo[ammotype];
            color1 = (ammo <= 15 ? yellow : white);
            fillrectfunc(0, ALTHUD_RIGHT_X + 100 - ammo, ALTHUD_Y + 13, ammo + 1, 8, color1);
            althudfunc(ALTHUD_RIGHT_X, ALTHUD_Y + 13, altrightpatch, WHITE, white);
            althudfunc(ALTHUD_RIGHT_X + 100, ALTHUD_Y + 13, altendpatch, WHITE, color1);
            althudfunc(ALTHUD_RIGHT_X + 100 - ammo - 2, ALTHUD_Y + 13, altmarkpatch, WHITE, color1);
        }

        if (weapon != wp_fist)
            althudfunc(ALTHUD_RIGHT_X + 107, ALTHUD_Y - 15, altweapon[weapon], WHITE, white);
    }

    while (i < NUMCARDS)
        if (plr->cards[i++] > 0)
            keys++;

    if (keys || plr->neededcardflash)
    {
        static int      keywait;
        static dboolean showkey;

        if (plr->neededcardflash)
        {
            if (!(menuactive || paused || consoleactive))
            {
                int currenttime = I_GetTimeMS();

                if (keywait < currenttime)
                {
                    showkey = !showkey;
                    keywait = currenttime + HUD_KEY_WAIT;
                    plr->neededcardflash--;
                }
            }

            if (showkey)
            {
                altkeypic_t altkeypic = altkeypics[plr->neededcard];

                althudfunc(ALTHUD_RIGHT_X + 11 * cardsfound, ALTHUD_Y, altkeypic.patch, WHITE,
                    altkeypic.color);
            }
        }
        else
        {
            showkey = false;
            keywait = 0;
        }

        for (i = 0; i < NUMCARDS; i++)
        {
            int card = plr->cards[i];

            if (card > 0)
            {
                altkeypic_t    altkeypic = altkeypics[i];

                althudfunc(ALTHUD_RIGHT_X + 11 * (card - 1), ALTHUD_Y, altkeypic.patch, WHITE,
                    altkeypic.color);
            }
        }
    }

    if ((powerup = plr->powers[pw_invulnerability]))
    {
        max = INVULNTICS;
        powerupbar = (powerup == -1 ? max : powerup);
    }

    if ((powerup = plr->powers[pw_invisibility]) && (!powerupbar || (powerup >= 0 && powerup < powerupbar)))
    {
        max = INVISTICS;
        powerupbar = (powerup == -1 ? max : powerup);
    }

    if ((powerup = plr->powers[pw_ironfeet]) && (!powerupbar || (powerup >= 0 && powerup < powerupbar)))
    {
        max = IRONTICS;
        powerupbar = (powerup == -1 ? max : powerup);
    }

    if ((powerup = plr->powers[pw_infrared]) && (!powerupbar || (powerup >= 0 && powerup < powerupbar)))
    {
        max = INFRATICS;
        powerupbar = (powerup == -1 ? max : powerup);
    }

    if ((powerup = plr->powers[pw_strength]) && plr->readyweapon == wp_fist && !powerupbar)
    {
        max = STARTFLASHING + 1;
        powerupbar = STARTFLASHING + 1;
    }

    if (powerupbar > STARTFLASHING || (powerupbar & 8))
    {
        fillrectfunc(0, ALTHUD_RIGHT_X, ALTHUD_Y + 26, 101, 2, darkgray);
        fillrectfunc(0, ALTHUD_RIGHT_X, ALTHUD_Y + 26, powerupbar * 101 / max, 2, gray);
    }
}
boolean NET_CL_Connect(net_addr_t *addr)
{
    int start_time;
    int last_send_time;

    server_addr = addr;

    // Are we recording a demo? Possibly set lowres turn mode

    if (M_CheckParm("-record") > 0 && M_CheckParm("-longtics") == 0)
    {
        lowres_turn = true;
    }

    // Read checksums of our WAD directory and dehacked information

    W_Checksum(net_local_wad_md5sum);
    DEH_Checksum(net_local_deh_md5sum);

    // Are we playing with the Freedoom IWAD?

    net_local_is_freedoom = W_CheckNumForName("FREEDOOM") >= 0;

    // create a new network I/O context and add just the
    // necessary module

    client_context = NET_NewContext();
    
    // initialize module for client mode

    if (!addr->module->InitClient())
    {
        return false;
    }

    NET_AddModule(client_context, addr->module);

    net_client_connected = true;
    net_client_received_wait_data = false;

    // Initialize connection

    NET_Conn_InitClient(&client_connection, addr);

    // try to connect
 
    start_time = I_GetTimeMS();
    last_send_time = -1;

    while (client_connection.state == NET_CONN_STATE_CONNECTING)
    {
        int nowtime = I_GetTimeMS();

        // Send a SYN packet every second.

        if (nowtime - last_send_time > 1000 || last_send_time < 0)
        {
            NET_CL_SendSYN();
            last_send_time = nowtime;
        }
 
        // time out after 5 seconds 

        if (nowtime - start_time > 5000)
        {
            break;
        }

        // run client code

        NET_CL_Run();
        
        // run the server, just incase we are doing a loopback
        // connect

        NET_SV_Run();

        // Don't hog the CPU

        I_Sleep(1);
    }

    if (client_connection.state == NET_CONN_STATE_CONNECTED)
    {
        // connected ok!

        client_state = CLIENT_STATE_WAITING_START;

        return true;
    }
    else
    {
        // failed to connect

        NET_CL_Shutdown();
        
        return false;
    }
}
Exemplo n.º 28
0
static void NET_SV_RunClient(net_client_t *client)
{
    // Run common code

    NET_Conn_Run(&client->connection);
    
    if (client->connection.state == NET_CONN_STATE_DISCONNECTED
     && client->connection.disconnect_reason == NET_DISCONNECT_TIMEOUT)
    {
        NET_SV_BroadcastMessage("Client '%s' timed out and disconnected",
                                client->name);
    }
    
    // Is this client disconnected?

    if (client->connection.state == NET_CONN_STATE_DISCONNECTED)
    {
        // deactivate and free back 

        client->active = false;
        free(client->name);
        NET_FreeAddress(client->addr);

        // Are there any clients left connected?  If not, return the
        // server to the waiting-for-players state.
        //
	// Disconnect any drones still connected.

        if (NET_SV_NumPlayers() <= 0)
        {
            NET_SV_GameEnded();
        }
    }
    
    if (!ClientConnected(client))
    {
        // client has not yet finished connecting

        return;
    }

    if (server_state == SERVER_WAITING_START)
    {
        // Waiting for the game to start

        // Send information once every second

        if (client->last_send_time < 0 
         || I_GetTimeMS() - client->last_send_time > 1000)
        {
            NET_SV_SendWaitingData(client);
            client->last_send_time = I_GetTimeMS();
        }
    }

    if (server_state == SERVER_IN_GAME)
    {
        NET_SV_PumpSendQueue(client);
        NET_SV_CheckDeadlock(client);
    }
}
static void NET_CL_ExpandFullTiccmd(net_full_ticcmd_t *cmd, unsigned int seq)
{
    int latency;
    fixed_t adjustment;
    int i;

    // Update average_latency

    if (seq == send_queue[seq % BACKUPTICS].seq)
    {
        latency = I_GetTimeMS() - send_queue[seq % BACKUPTICS].time;
    }
    else if (seq > send_queue[seq % BACKUPTICS].seq)
    {
        // We have received the ticcmd from the server before we have
        // even sent ours

        latency = 0;
    }
    else
    {
        latency = -1;
    }

    if (latency >= 0)
    {
        if (seq <= 20)
        {
            average_latency = latency * FRACUNIT;
        }
        else
        {
            // Low level filter

            average_latency = (fixed_t)((average_latency * 0.9)
                            + (latency * FRACUNIT * 0.1));
        }
    }

    //printf("latency: %i\tremote:%i\n", average_latency / FRACUNIT, 
    //                                   cmd->latency);

    // Possibly adjust offsetms in d_net.c, try to make players all have
    // the same lag.  Don't adjust in the first few tics of play, as 
    // we don't have an accurate value for average_latency yet.

    if (seq > TICRATE)
    {
        adjustment = (cmd->latency * FRACUNIT) - average_latency;

        // Only adjust very slightly; the cumulative effect over 
        // multiple tics will sort it out.

        adjustment = adjustment / 100;

        offsetms += adjustment;
    }

    // Expand tic diffs for all players
    
    for (i=0; i<MAXPLAYERS; ++i)
    {
        if (i == consoleplayer && !drone)
        {
            continue;
        }
        
        if (playeringame[i] && !cmd->playeringame[i])
        {
            NET_CL_PlayerQuitGame(&players[i]);
        }
        
        playeringame[i] = cmd->playeringame[i];

        if (playeringame[i])
        {
            net_ticdiff_t *diff;
            ticcmd_t ticcmd;

            diff = &cmd->cmds[i];

            // Use the ticcmd diff to patch the previous ticcmd to
            // the new ticcmd

            NET_TiccmdPatch(&recvwindow_cmd_base[i], diff, &ticcmd);

            // Save in d_net.c structures

            netcmds[i][nettics[i] % BACKUPTICS] = ticcmd;
            ++nettics[i];

            // Store a copy for next time

            recvwindow_cmd_base[i] = ticcmd;
        }
    }
}
static void NET_CL_CheckResends(void)
{
    int i;
    int resend_start, resend_end;
    unsigned int nowtime;

    nowtime = I_GetTimeMS();

    resend_start = -1;
    resend_end = -1;

    for (i=0; i<BACKUPTICS; ++i)
    {
        net_server_recv_t *recvobj;
        boolean need_resend;

        recvobj = &recvwindow[i];

        // if need_resend is true, this tic needs another retransmit
        // request (300ms timeout)

        need_resend = !recvobj->active
                   && recvobj->resend_time != 0
                   && nowtime > recvobj->resend_time + 300;

        if (need_resend)
        {
            // Start a new run of resend tics?
 
            if (resend_start < 0)
            {
                resend_start = i;
            }
            
            resend_end = i;
        }
        else
        {
            if (resend_start >= 0)
            {
                // End of a run of resend tics

                //printf("CL: resend request timed out: %i-%i\n", resend_start, resend_end);
                NET_CL_SendResendRequest(recvwindow_start + resend_start,
                                         recvwindow_start + resend_end);

                resend_start = -1;
            }
        }
    }

    if (resend_start >= 0)
    {
        //printf("CL: resend request timed out: %i-%i\n", resend_start, resend_end);
        NET_CL_SendResendRequest(recvwindow_start + resend_start,
                                 recvwindow_start + resend_end);
    }

    // We have received some data from the server and not acknowledged
    // it yet.  Normally this gets acknowledged when we send our game
    // data, but if the client is a drone we need to do this.

    if (need_to_acknowledge && nowtime - gamedata_recv_time > 200)
    {
        NET_CL_SendGameDataACK();
    }
}