add timeout for persistent games

This commit is contained in:
Martin Michelsen
2023-12-13 20:52:35 -08:00
parent 3551b9abc3
commit 974269187b
7 changed files with 96 additions and 23 deletions
+36 -1
View File
@@ -31,12 +31,21 @@ Lobby::Lobby(shared_ptr<ServerState> s, uint32_t id)
block(0),
leader_id(0),
max_clients(12),
enabled_flags(0) {
enabled_flags(0),
idle_timeout_usecs(0),
idle_timeout_event(
event_new(s->base.get(), -1, EV_TIMEOUT | EV_PERSIST, &Lobby::dispatch_on_idle_timeout, this),
event_free) {
this->log.info("Created");
for (size_t x = 0; x < 12; x++) {
this->next_item_id[x] = 0x00010000 + 0x00200000 * x;
}
}
Lobby::~Lobby() {
this->log.info("Deleted");
}
shared_ptr<ServerState> Lobby::require_server_state() const {
auto s = this->server_state.lock();
if (!s) {
@@ -369,6 +378,12 @@ void Lobby::add_client(shared_ptr<Client> c, ssize_t required_client_id) {
send_ep3_update_game_metadata(this->shared_from_this());
}
}
// There is a player in the lobby, so it is no longer idle
if (event_pending(this->idle_timeout_event.get(), EV_TIMEOUT, nullptr)) {
event_del(this->idle_timeout_event.get());
this->log.info("Idle timeout cancelled");
}
}
void Lobby::remove_client(shared_ptr<Client> c) {
@@ -409,6 +424,14 @@ void Lobby::remove_client(shared_ptr<Client> c) {
send_ep3_update_game_metadata(this->shared_from_this());
}
}
// If the lobby is persistent but has an idle timeout, make it expire after
// the specified time
if ((this->count_clients() == 0) && this->check_flag(Flag::PERSISTENT) && (this->idle_timeout_usecs > 0)) {
auto tv = usecs_to_timeval(this->idle_timeout_usecs);
event_add(this->idle_timeout_event.get(), &tv);
this->log.info("Idle timeout scheduled");
}
}
void Lobby::move_client_to_lobby(
@@ -551,3 +574,15 @@ QuestIndex::IncludeCondition Lobby::quest_include_condition() const {
return is_enabled ? QuestIndex::IncludeState::AVAILABLE : QuestIndex::IncludeState::DISABLED;
};
}
void Lobby::dispatch_on_idle_timeout(evutil_socket_t, short, void* ctx) {
auto l = reinterpret_cast<Lobby*>(ctx)->shared_from_this();
if (l->count_clients() == 0) {
l->log.info("Idle timeout expired");
auto s = l->require_server_state();
s->remove_lobby(l);
} else {
l->log.error("Idle timeout occurred, but clients are present in lobby");
event_del(l->idle_timeout_event.get());
}
}