Example #1
0
void Client::sevt_login(ServerEvent& evt) {
    ScopeMutex lock(mtx);

    const Resources::LoadedPaks& paks = resources.get_loaded_paks();
    GPakHash gph;
    for (Resources::LoadedPaks::const_iterator it = paks.begin(); it != paks.end(); it++) {
        const Resources::LoadedPak& pak = *it;
        memset(&gph, 0, GPakHashLen);
        strncpy(gph.pak_name, pak.pak_short_name.c_str(), NameLength - 1);
        strncpy(gph.pak_hash, pak.pak_hash.c_str(), 64);
        gph.to_net();
        stacked_send_data(evt.c, 0, GPSPakSyncHash, NetFlagsReliable, GPakHashLen, &gph);
    }
    stacked_send_data(evt.c, 0, GPSPakSyncHashFinished, NetFlagsReliable, 0, 0);
    flush_stacked_send_data(evt.c, 0);
}
Example #2
0
void Client::idle() throw (Exception) {
    /* process net io */
    bool queue_empty = true;
    do {
        ServerEvent evt;
        {
            Scope<Mutex> lock(mtx);
            if (server_events.empty()) {
                break;
            }
            evt = server_events.front();
            server_events.pop();
            queue_empty = server_events.empty();
        }
        switch (evt.event) {
            case EventTypeStatus:
            {
                std::string msg(evt.data, evt.sz);
                subsystem << msg << std::endl;
                break;
            }

            case EventTypeAccessDenied:
            {
                stop_thread();
                exception_msg.assign(evt.data, evt.sz);
                throw_exception = true;
                break;
            }

            case EventTypeLogin:
            {
                sevt_login(evt);
                break;
            }

            case EventTypeLogout:
            {
                stop_thread();
                logged_in = false;
                conn = 0;
                exception_msg.assign(evt.data, evt.sz);
                throw_exception = true;
                break;
            }

            case EventTypeData:
                sevt_data(evt);
                break;
        }
        if (evt.data) {
            delete[] evt.data;
        }
    } while (!queue_empty && !throw_exception);

    /* have to throw an exception? */
    if (throw_exception) {
        throw ClientException(exception_msg);
    }

    /* interpolate movements */
    get_now(now);
    ns_t diff = diff_ns(last, now);

    last = now;

    if (tournament) {
        tournament->update_states(diff);
        if (conn) {
            tournament->set_ping_time(conn->ping_time);
            Tournament::StateResponses& responses = tournament->get_state_responses();
            size_t sz = responses.size();
            {
                Scope<Mutex> lock(mtx);
                for (size_t i = 0; i < sz; i++) {
                    StateResponse *resp = responses[i];
                    if (resp->action == GPCTextMessage) {
                        std::string msg(reinterpret_cast<const char *>(resp->data), resp->len);
                        add_text_msg(msg);
                    } else {
                        stacked_send_data(conn, factory.get_tournament_id(), resp->action, 0, resp->len, resp->data);
                    }
                }
                flush_stacked_send_data(conn, 0);
            }
        }
        tournament->delete_responses();

        /* send player position (unreliable) */
        updatecnt += diff;
        bool player_force = false;
        if (me && me->force_broadcast) {
            player_force = true;
            me->force_broadcast = false;
            me->state.client_server_state.flags |= PlayerClientServerFlagForceBroadcast;
        }
        if (updatecnt >= UpdatePeriod || force_send || player_force) {
            updatecnt = 0;
            if (conn && me && tournament->is_ready()) {
                GPlayerClientServerState state;
                state = me->state.client_server_state;
                state.to_net();
                {
                    Scope<Mutex> lock(mtx);
                    send_data(conn, factory.get_tournament_id(), GPSUpdatePlayerClientServerState, 0, GPlayerClientServerStateLen, &state);
                }
                me->state.client_server_state.flags &= ~PlayerClientServerFlagForceBroadcast;
            }
        }
    }

    /* interpolate messages */
    for (TextMessages::iterator it = text_messages.begin();
        it != text_messages.end(); it++)
    {
        TextMessage *cmsg = *it;
        cmsg->duration += (diff / 1000000.0f);
        if (cmsg->duration > text_message_duration) {
            cmsg->delete_me = true;
        }
    }
    text_messages.erase(std::remove_if(text_messages.begin(),
        text_messages.end(), erase_element<TextMessage>),
        text_messages.end());

    /* player in options or in chatbox? */
    if (me) {
        if (get_stack_count()) {
            me->state.client_server_state.flags |= PlayerClientServerFlagWriting;
        } else {
            me->state.client_server_state.flags &= ~PlayerClientServerFlagWriting;
        }
    }

    /* draw map */
    if (tournament) {
        tournament->draw();
    }

    /* draw messages */
    Font *font = resources.get_font("normal");
    int view_height = subsystem.get_view_height();
    int font_height = font->get_font_height();
    int y = view_height - font_height - 5;
    for (TextMessages::reverse_iterator it = text_messages.rbegin();
        it != text_messages.rend(); it++)
    {
        TextMessage *cmsg = *it;
        float alpha = 1.0f;
        if (cmsg->duration > text_message_fade_out_at) {
            alpha = static_cast<float>((text_message_duration - cmsg->duration) / (text_message_duration - text_message_fade_out_at));
        }

        subsystem.set_color(0.75f, 0.75f, 1.0f, alpha);
        subsystem.draw_text(font, 5, y, cmsg->text);
        alpha *= 0.9f;
        y -= font_height;
    }
    subsystem.reset_color();

    /* draw file transfer status */
    if (fhnd) {
        Font *big = resources.get_font("big");
        int percent = 100 - static_cast<int>(100.0f / static_cast<float>(total_xfer_sz) * remaining_xfer_sz);
        sprintf(buffer, "transferring %s (%d%%)", xfer_filename.c_str(), percent);
        int tw = big->get_text_width(buffer);
        subsystem.draw_text(big, subsystem.get_view_width() / 2 - tw / 2, view_height - 30, buffer);
    }
}