Skip to content

Commit

Permalink
changes in a server and client...
Browse files Browse the repository at this point in the history
  • Loading branch information
UtoECat committed Jan 22, 2024
1 parent 81a5384 commit 5df5e5d
Show file tree
Hide file tree
Showing 4 changed files with 434 additions and 151 deletions.
49 changes: 49 additions & 0 deletions base/event.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* This file is a part of Pixelbox - Infinite 2D sandbox game
* Evenst for objservers/subscribers patterns
* Copyright (C) 2023-2024 UtoECat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once
#include <functional>
#include <utility>

namespace pb {

// subject for "Observers"
template <typename F, typename... Args>
class Subject {
protected:
using function_type = std::function<F(Args...)>;
std::vector<function_type> handlers;
public:
Subject() {};
Subject(const Subject&) = default;
Subject(Subject&&) = default;
Subject& operator=(const Subject&) = default;
Subject& operator=(Subject&&) = default;
void subscribe(const function_type& f) { handlers.emplace_back(f); }
void subscribe(function_type&& f) { handlers.emplace_back(std::move(f)); }
void notify_all(Args&&... args) {
for (auto& f : handlers) {
f(std::forward<Args>(args)...);
}
}
};

};


141 changes: 141 additions & 0 deletions engine/network.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* This file is a part of Pixelbox - Infinite 2D sandbox game
* Enet wrapper!
* Copyright (C) 2023-2024 UtoECat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once
#include "engine/network.hpp"

#include <base.hpp>
#include <functional>
#include <memory>
#include <set>
#include <stdexcept>
#include <string>

#include "enet.h"

/**
* @description ENet Wrapper
*/
namespace pb {

void ENetBase::on_event_recv(ENetEvent& ev) {
auto conn = ENetConnection(ev.peer);
switch (ev.type) {
case ENET_EVENT_TYPE_CONNECT:
enet_peer_set_data(ev.peer, new ConnectionData());
h_connect.notify_all(*this, conn);
break;
case ENET_EVENT_TYPE_DISCONNECT:
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
try {
h_disconnect.notify_all(*this, conn);
} catch (std::exception& e) {
std::cerr << "Exception in disconnect handler : " << e.what() << std::endl;
} catch (...) {
std::cerr << "Unknown exception in disconnect handler" << std::endl;
}
{
auto v = (ConnectionData*)enet_peer_get_data(ev.peer);
if (v) delete v;
enet_peer_set_data(ev.peer, nullptr);
}
break;
case ENET_EVENT_TYPE_RECEIVE:
try {
h_recieve.notify_all(*this, conn, ev.channelID,
std::string_view((const char*)enet_packet_get_data(ev.packet), enet_packet_get_length(ev.packet)));
} catch (std::exception& e) {
std::cerr << "Exception in message handler : " << e.what() << std::endl;
}
enet_packet_destroy(ev.packet); // hehe
break;
case ENET_EVENT_TYPE_NONE:
break;
}
}

void ENetBase::destroy() {
/** request disconnection */
foreach ([](ENetPeer* peer) {
enet_peer_timeout(peer, 2000, 1000, 5000);
enet_peer_disconnect(peer, -1); // shutdown
})
;

flush();

int attempts = host->peerCount * 8; // process as much as *8 events
int dummies = host->peerCount;

ENetEvent ev;
while (dummies > 0 && attempts > 0 && enet_host_service(host, &ev, 5000)) {
switch (ev.type) {
case ENET_EVENT_TYPE_CONNECT:
enet_peer_reset(ev.peer); // ignore and kill
break;
case ENET_EVENT_TYPE_DISCONNECT:
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
dummies--;
on_event_recv(ev); // default behaviour
break;
case ENET_EVENT_TYPE_RECEIVE:
enet_packet_destroy(ev.packet); // we don't care
break;
case ENET_EVENT_TYPE_NONE:
break;
}
}

force_destroy(); // shutdown now!
};

bool ENetClient::connect(const char* ip, unsigned short port) {
ProtocolInfo info;
info.ip = NULL;
info.port = port;
create_client();
server = nullptr;

if (!host) {
std::cerr << "ENetClient: can't create client host! (weird)" << std::endl;
return false; // :(
}

// connect
const ENetAddress addr = info.getAddress();
server = enet_host_connect(host, &addr, info.nchannels, 0);
if (!server) {
std::cerr << "ENetClient : can't create peer!" << std::endl;
goto err;
}

// process events
ENetEvent event;
if (enet_host_service(host, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
on_event_recv(event); // do init
return true;
}

std::cerr << "ENetClient : can't connect to the server!" << std::endl;
err:
force_destroy();
return false;
}

}; // namespace pb
Loading

0 comments on commit 5df5e5d

Please sign in to comment.