working main menu
This commit is contained in:
@@ -17,6 +17,8 @@ class EnetServer : private NonCopyable {
|
|||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
|
bool IsClosed() const;
|
||||||
|
|
||||||
void CloseConnection(std::uint16_t a_PeerId);
|
void CloseConnection(std::uint16_t a_PeerId);
|
||||||
|
|
||||||
EnetConnection* GetConnection(std::uint16_t a_PeerId);
|
EnetConnection* GetConnection(std::uint16_t a_PeerId);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Nazara/Core/EnttWorld.hpp>
|
#include <Nazara/Core/EnttWorld.hpp>
|
||||||
#include <atomic>
|
|
||||||
#include <blitz/network/EnetClient.h>
|
#include <blitz/network/EnetClient.h>
|
||||||
#include <blitz/protocol/PacketHandler.h>
|
#include <blitz/protocol/PacketHandler.h>
|
||||||
|
|
||||||
@@ -18,6 +17,9 @@ class Client : private NonCopyable {
|
|||||||
|
|
||||||
bool IsConnected();
|
bool IsConnected();
|
||||||
|
|
||||||
|
NazaraSignal(OnClientReady);
|
||||||
|
NazaraSignal(OnClientDisconnect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EnttWorld m_World;
|
EnttWorld m_World;
|
||||||
std::unique_ptr<network::EnetClient> m_NetworkClient;
|
std::unique_ptr<network::EnetClient> m_NetworkClient;
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class PlayerJoinHandler : public protocol::PacketHandler {
|
|||||||
|
|
||||||
NazaraSlot(network::EnetConnection, OnPlayerJoin, m_Slot);
|
NazaraSlot(network::EnetConnection, OnPlayerJoin, m_Slot);
|
||||||
|
|
||||||
|
NazaraSignal(OnLocalPlayerReady);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Handle(const protocol::data::PlayerJoin&);
|
void Handle(const protocol::data::PlayerJoin&);
|
||||||
};
|
};
|
||||||
|
|||||||
62
include/client/states/ConnectingState.h
Normal file
62
include/client/states/ConnectingState.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Nazara/Network/IpAddress.hpp>
|
||||||
|
#include <Nazara/Widgets/ButtonWidget.hpp>
|
||||||
|
#include <Nazara/Widgets/LabelWidget.hpp>
|
||||||
|
#include <client/Client.h>
|
||||||
|
#include <client/states/AbstractState.h>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace blitz {
|
||||||
|
|
||||||
|
namespace server {
|
||||||
|
class Server;
|
||||||
|
} // namespace server
|
||||||
|
|
||||||
|
namespace client {
|
||||||
|
|
||||||
|
class ConnectingState : public AbstractState {
|
||||||
|
public:
|
||||||
|
ConnectingState(std::shared_ptr<StateData> a_StateData, std::shared_ptr<AbstractState> a_PreviousState,
|
||||||
|
const std::string& a_Address, std::uint16_t a_Port, bool a_IntegratedServer = false);
|
||||||
|
~ConnectingState();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ResolvingData {
|
||||||
|
bool m_HasResult = false;
|
||||||
|
Nz::Result<std::vector<Nz::IpAddress>, std::string /*error*/> m_Result = Nz::Err("");
|
||||||
|
std::string m_ServerName;
|
||||||
|
std::uint16_t m_Port;
|
||||||
|
};
|
||||||
|
|
||||||
|
ResolvingData m_ResolvingData;
|
||||||
|
bool m_IsConnected = false;
|
||||||
|
std::queue<Nz::IpAddress> m_Addresses;
|
||||||
|
Nz::MillisecondClock m_TimeoutClock;
|
||||||
|
|
||||||
|
Nz::ButtonWidget* m_BackButton;
|
||||||
|
Nz::LabelWidget* m_StatusText;
|
||||||
|
std::shared_ptr<AbstractState> m_NextState;
|
||||||
|
std::shared_ptr<AbstractState> m_PreviousState;
|
||||||
|
|
||||||
|
std::unique_ptr<Client> m_Client;
|
||||||
|
std::unique_ptr<server::Server> m_Server;
|
||||||
|
|
||||||
|
void LayoutWidgets() override;
|
||||||
|
bool Update(Nz::StateMachine& fsm, Nz::Time elapsedTime) override;
|
||||||
|
|
||||||
|
void TryResolve();
|
||||||
|
void TryConnect(const Nz::IpAddress& a_ServerAddress);
|
||||||
|
void TryNextAddress();
|
||||||
|
|
||||||
|
void OnBackPressed();
|
||||||
|
|
||||||
|
void OnConnect();
|
||||||
|
void OnConnectFailed();
|
||||||
|
|
||||||
|
NazaraSlot(Client, OnClientReady, m_ClientReady);
|
||||||
|
NazaraSlot(Client, OnClientDisconnect, m_ClientDisconnect);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace client
|
||||||
|
} // namespace blitz
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Nazara/Widgets/TextAreaWidget.hpp>
|
||||||
#include <Nazara/Widgets/ButtonWidget.hpp>
|
#include <Nazara/Widgets/ButtonWidget.hpp>
|
||||||
#include <client/states/AbstractState.h>
|
#include <client/states/AbstractState.h>
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ class CreateServerState : public AbstractState {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Nz::ButtonWidget* m_CreateServerButton;
|
Nz::ButtonWidget* m_CreateServerButton;
|
||||||
|
Nz::TextAreaWidget* m_InputPort;
|
||||||
Nz::ButtonWidget* m_BackButton;
|
Nz::ButtonWidget* m_BackButton;
|
||||||
std::shared_ptr<AbstractState> m_NextState;
|
std::shared_ptr<AbstractState> m_NextState;
|
||||||
std::shared_ptr<AbstractState> m_PreviousState;
|
std::shared_ptr<AbstractState> m_PreviousState;
|
||||||
|
|||||||
27
include/client/states/GameState.h
Normal file
27
include/client/states/GameState.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <client/states/AbstractState.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace blitz {
|
||||||
|
|
||||||
|
namespace server {
|
||||||
|
class Server;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace client {
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
class GameState : public AbstractState {
|
||||||
|
public:
|
||||||
|
GameState(std::shared_ptr<StateData> a_StateData, std::unique_ptr<Client>&& a_Client, std::unique_ptr<server::Server>&& a_Server);
|
||||||
|
~GameState();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Client> m_Client;
|
||||||
|
std::unique_ptr<server::Server> m_Server;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace client
|
||||||
|
} // namespace blitz
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Nazara/Widgets/ButtonWidget.hpp>
|
#include <Nazara/Widgets/ButtonWidget.hpp>
|
||||||
|
#include <Nazara/Widgets/TextAreaWidget.hpp>
|
||||||
#include <client/states/AbstractState.h>
|
#include <client/states/AbstractState.h>
|
||||||
|
|
||||||
namespace blitz {
|
namespace blitz {
|
||||||
@@ -12,6 +13,7 @@ class JoinServerState : public AbstractState {
|
|||||||
~JoinServerState();
|
~JoinServerState();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Nz::TextAreaWidget* m_InputAddress;
|
||||||
Nz::ButtonWidget* m_JoinServerButton;
|
Nz::ButtonWidget* m_JoinServerButton;
|
||||||
Nz::ButtonWidget* m_BackButton;
|
Nz::ButtonWidget* m_BackButton;
|
||||||
std::shared_ptr<AbstractState> m_NextState;
|
std::shared_ptr<AbstractState> m_NextState;
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ class Server {
|
|||||||
|
|
||||||
network::EnetConnection* GetConnection(std::uint16_t a_PeerId);
|
network::EnetConnection* GetConnection(std::uint16_t a_PeerId);
|
||||||
|
|
||||||
|
bool IsClosed() const;
|
||||||
|
|
||||||
void CloseConnection(std::uint16_t a_PeerId);
|
void CloseConnection(std::uint16_t a_PeerId);
|
||||||
|
|
||||||
void CloseServer();
|
void CloseServer();
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ namespace server {
|
|||||||
|
|
||||||
class Server;
|
class Server;
|
||||||
|
|
||||||
class DisconectSystem {
|
class DisconnectSystem {
|
||||||
public:
|
public:
|
||||||
DisconectSystem(entt::registry&, EnttWorld& a_World, Server& a_Server);
|
DisconnectSystem(entt::registry&, EnttWorld& a_World, Server& a_Server);
|
||||||
|
|
||||||
void Update(Nz::Time elapsedTime);
|
void Update(Nz::Time elapsedTime);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace blitz {
|
|||||||
namespace network {
|
namespace network {
|
||||||
|
|
||||||
EnetClient::EnetClient(const Nz::IpAddress& address) : m_Running(true) {
|
EnetClient::EnetClient(const Nz::IpAddress& address) : m_Running(true) {
|
||||||
m_Host.Create(Nz::IpAddress::LoopbackIpV4, 1);
|
m_Host.Create(address.GetProtocol() == Nz::NetProtocol::IPv4 ? Nz::IpAddress::LoopbackIpV4 : Nz::IpAddress::LoopbackIpV6, 1);
|
||||||
m_Peer = m_Host.Connect(address);
|
m_Peer = m_Host.Connect(address);
|
||||||
m_Thread = std::jthread(&EnetClient::WorkerThread, this);
|
m_Thread = std::jthread(&EnetClient::WorkerThread, this);
|
||||||
m_Connection.SetPeer(m_Peer);
|
m_Connection.SetPeer(m_Peer);
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ void EnetServer::Update() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (m_Host.CheckEvents(&event));
|
} while (m_Host.CheckEvents(&event));
|
||||||
|
} else if (service < 0) {
|
||||||
|
m_Running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,5 +104,9 @@ void EnetServer::Destroy() {
|
|||||||
m_Host.Destroy();
|
m_Host.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EnetServer::IsClosed() const {
|
||||||
|
return !m_Running;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace network
|
} // namespace network
|
||||||
} // namespace blitz
|
} // namespace blitz
|
||||||
|
|||||||
@@ -18,9 +18,14 @@ Client::~Client() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::BindHandlers() {
|
void Client::BindHandlers() {
|
||||||
|
m_NetworkClient->OnDisconnect.Connect([this]() { OnClientDisconnect(); });
|
||||||
|
m_NetworkClient->OnDisconnectTimeout.Connect([this]() { OnClientDisconnect(); });
|
||||||
|
|
||||||
m_Handlers.push_back(std::make_unique<KeepAliveHandler>(m_NetworkClient->GetConnection(), m_World));
|
m_Handlers.push_back(std::make_unique<KeepAliveHandler>(m_NetworkClient->GetConnection(), m_World));
|
||||||
m_Handlers.push_back(std::make_unique<LoggingSuccessHandler>(m_NetworkClient->GetConnection(), m_World));
|
m_Handlers.push_back(std::make_unique<LoggingSuccessHandler>(m_NetworkClient->GetConnection(), m_World));
|
||||||
m_Handlers.push_back(std::make_unique<PlayerJoinHandler>(m_NetworkClient->GetConnection(), m_World));
|
auto playerJoin = std::make_unique<PlayerJoinHandler>(m_NetworkClient->GetConnection(), m_World);
|
||||||
|
playerJoin->OnLocalPlayerReady.Connect([this]() { OnClientReady(); });
|
||||||
|
m_Handlers.push_back(std::move(playerJoin));
|
||||||
m_Handlers.push_back(std::make_unique<PlayerLeaveHandler>(m_NetworkClient->GetConnection(), m_World));
|
m_Handlers.push_back(std::make_unique<PlayerLeaveHandler>(m_NetworkClient->GetConnection(), m_World));
|
||||||
m_Handlers.push_back(std::make_unique<PlayerListHandler>(m_NetworkClient->GetConnection(), m_World));
|
m_Handlers.push_back(std::make_unique<PlayerListHandler>(m_NetworkClient->GetConnection(), m_World));
|
||||||
}
|
}
|
||||||
@@ -38,6 +43,7 @@ void Client::Connect(const Nz::IpAddress& a_Ip) {
|
|||||||
void Client::Disconnect() {
|
void Client::Disconnect() {
|
||||||
if (!m_NetworkClient)
|
if (!m_NetworkClient)
|
||||||
return;
|
return;
|
||||||
|
m_NetworkClient->GetConnection().SendDisconnect({});
|
||||||
m_NetworkClient->Disconnect();
|
m_NetworkClient->Disconnect();
|
||||||
UnbindHandlers();
|
UnbindHandlers();
|
||||||
m_NetworkClient.reset(nullptr);
|
m_NetworkClient.reset(nullptr);
|
||||||
@@ -51,6 +57,7 @@ bool Client::IsConnected() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::Login() {
|
void Client::Login() {
|
||||||
|
srand(time(0));
|
||||||
if (!m_NetworkClient || !m_NetworkClient->GetConnection().IsConnected())
|
if (!m_NetworkClient || !m_NetworkClient->GetConnection().IsConnected())
|
||||||
return;
|
return;
|
||||||
m_NetworkClient->GetConnection().SendPlayerLogin({"Player_" + std::to_string(rand() % 100)});
|
m_NetworkClient->GetConnection().SendPlayerLogin({"Player_" + std::to_string(rand() % 100)});
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ void PlayerJoinHandler::Handle(const protocol::data::PlayerJoin& a_PlayerJoin) {
|
|||||||
world->GetRegistry().emplace<PlayerInfoComponent>(localPlayer, a_PlayerJoin.m_Player);
|
world->GetRegistry().emplace<PlayerInfoComponent>(localPlayer, a_PlayerJoin.m_Player);
|
||||||
|
|
||||||
// we are now into the game so we can begin to load the world for example
|
// we are now into the game so we can begin to load the world for example
|
||||||
|
OnLocalPlayerReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerJoinHandler::~PlayerJoinHandler() {}
|
PlayerJoinHandler::~PlayerJoinHandler() {}
|
||||||
|
|||||||
189
src/client/states/ConnectingState.cpp
Normal file
189
src/client/states/ConnectingState.cpp
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
#include "client/states/GameState.h"
|
||||||
|
#include <client/states/ConnectingState.h>
|
||||||
|
|
||||||
|
#include <Nazara/Core/ApplicationBase.hpp>
|
||||||
|
#include <Nazara/Core/Clock.hpp>
|
||||||
|
#include <Nazara/Core/EntitySystemAppComponent.hpp>
|
||||||
|
#include <Nazara/Core/EnttWorld.hpp>
|
||||||
|
#include <Nazara/Core/StateMachine.hpp>
|
||||||
|
#include <Nazara/Core/Time.hpp>
|
||||||
|
#include <Nazara/Network/Algorithm.hpp>
|
||||||
|
#include <Nazara/Network/IpAddress.hpp>
|
||||||
|
#include <Nazara/TextRenderer.hpp>
|
||||||
|
#include <Nazara/TextRenderer/SimpleTextDrawer.hpp>
|
||||||
|
#include <blitz/common/Format.h>
|
||||||
|
#include <blitz/common/Log.h>
|
||||||
|
#include <client/Client.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <server/Server.h>
|
||||||
|
|
||||||
|
namespace blitz {
|
||||||
|
namespace client {
|
||||||
|
|
||||||
|
static const int ConnectTimeout = 5;
|
||||||
|
|
||||||
|
ConnectingState::ConnectingState(std::shared_ptr<StateData> a_StateData, std::shared_ptr<AbstractState> a_PreviousState,
|
||||||
|
const std::string& a_Address, std::uint16_t a_Port, bool a_Server) :
|
||||||
|
AbstractState(std::move(a_StateData)),
|
||||||
|
m_PreviousState(std::move(a_PreviousState)),
|
||||||
|
m_Client(std::make_unique<Client>(*GetStateData().m_World)) {
|
||||||
|
m_ResolvingData.m_Port = a_Port;
|
||||||
|
m_ResolvingData.m_ServerName = a_Address;
|
||||||
|
|
||||||
|
Nz::SimpleTextDrawer textDrawer;
|
||||||
|
textDrawer.SetTextColor({0.0, 0.0, 0.0, 1.0});
|
||||||
|
textDrawer.SetCharacterSize(75);
|
||||||
|
m_BackButton = CreateWidget<Nz::ButtonWidget>();
|
||||||
|
textDrawer.SetText("Back");
|
||||||
|
m_BackButton->UpdateText(textDrawer);
|
||||||
|
m_BackButton->Resize(m_BackButton->GetPreferredSize());
|
||||||
|
m_BackButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnBackPressed(); });
|
||||||
|
|
||||||
|
m_StatusText = CreateWidget<Nz::LabelWidget>();
|
||||||
|
m_StatusText->UpdateText(Nz::SimpleTextDrawer::Draw("Connecting ...", 80));
|
||||||
|
|
||||||
|
if (a_Server) {
|
||||||
|
auto& app = GetStateData().m_App;
|
||||||
|
auto& ecs = app->GetComponent<Nz::EntitySystemAppComponent>();
|
||||||
|
|
||||||
|
// create server
|
||||||
|
Nz::EnttWorld& world = ecs.AddWorld<Nz::EnttWorld>();
|
||||||
|
m_Server = std::make_unique<server::Server>(a_Port, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ClientReady.Connect(m_Client->OnClientReady, [this]() { OnConnect(); });
|
||||||
|
m_ClientDisconnect.Connect(m_Client->OnClientDisconnect, [this]() { TryNextAddress(); });
|
||||||
|
|
||||||
|
TryResolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectingState::~ConnectingState() {}
|
||||||
|
|
||||||
|
bool ConnectingState::Update(Nz::StateMachine& fsm, Nz::Time elapsedTime) {
|
||||||
|
if (m_NextState)
|
||||||
|
fsm.ChangeState(std::move(m_NextState));
|
||||||
|
|
||||||
|
if (m_Server && m_Server->IsClosed())
|
||||||
|
OnConnectFailed();
|
||||||
|
|
||||||
|
if (m_ResolvingData.m_HasResult) {
|
||||||
|
if (m_ResolvingData.m_Result) {
|
||||||
|
// Register resolved addresses as next addresses
|
||||||
|
const auto& addresses = m_ResolvingData.m_Result.GetValue();
|
||||||
|
for (auto resultIt = addresses.rbegin(); resultIt != addresses.rend(); ++resultIt)
|
||||||
|
m_Addresses.emplace(*resultIt);
|
||||||
|
TryConnect(m_Addresses.front());
|
||||||
|
} else {
|
||||||
|
OnConnectFailed();
|
||||||
|
}
|
||||||
|
m_ResolvingData.m_HasResult = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Nz::MillisecondClock clock;
|
||||||
|
static int progress = -1;
|
||||||
|
|
||||||
|
if (m_Client && clock.RestartIfOver(Nz::Time::Milliseconds(500))) {
|
||||||
|
progress++;
|
||||||
|
progress %= 4;
|
||||||
|
std::string textStr = "Connecting ";
|
||||||
|
for (int i = 0; i < progress; i++) {
|
||||||
|
textStr += ".";
|
||||||
|
}
|
||||||
|
m_StatusText->UpdateText(Nz::SimpleTextDrawer::Draw(textStr, 80));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_Addresses.empty() && m_TimeoutClock.RestartIfOver(Nz::Time::Seconds(ConnectTimeout))) {
|
||||||
|
TryNextAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_IsConnected) {
|
||||||
|
fsm.ResetState(std::make_shared<GameState>(GetStateDataPtr(), std::move(m_Client), std::move(m_Server)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectingState::TryConnect(const Nz::IpAddress& a_ServerAddress) {
|
||||||
|
if (!m_Client)
|
||||||
|
return;
|
||||||
|
LogD("Trying to connect to " + a_ServerAddress.ToString() + " ...");
|
||||||
|
m_TimeoutClock.Restart();
|
||||||
|
m_Client->Connect(a_ServerAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectingState::TryNextAddress() {
|
||||||
|
m_Client->Disconnect();
|
||||||
|
m_Addresses.pop();
|
||||||
|
if (m_Addresses.empty())
|
||||||
|
OnConnectFailed();
|
||||||
|
else
|
||||||
|
TryConnect(m_Addresses.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectingState::TryResolve() {
|
||||||
|
Nz::ResolveError resolveError;
|
||||||
|
auto serverAddresses = Nz::IpAddress::ResolveHostname(
|
||||||
|
Nz::NetProtocol::Any, m_ResolvingData.m_ServerName, std::to_string(m_ResolvingData.m_Port), &resolveError);
|
||||||
|
if (serverAddresses.empty()) {
|
||||||
|
m_ResolvingData.m_Result = Nz::Err(Nz::ErrorToString(resolveError));
|
||||||
|
LogD("Failed to resolve " + m_ResolvingData.m_ServerName + " !");
|
||||||
|
} else {
|
||||||
|
std::vector<Nz::IpAddress> addresses;
|
||||||
|
addresses.reserve(serverAddresses.size());
|
||||||
|
for (auto hostnameInfo : serverAddresses) {
|
||||||
|
hostnameInfo.address.SetPort(m_ResolvingData.m_Port);
|
||||||
|
addresses.push_back(hostnameInfo.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ResolvingData.m_Result = std::move(addresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ResolvingData.m_HasResult = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectingState::LayoutWidgets() {
|
||||||
|
Nz::Vector2f canvasSize = GetStateData().m_Canvas->GetSize();
|
||||||
|
Nz::Vector2f center = canvasSize / 2.f;
|
||||||
|
|
||||||
|
constexpr float padding = 10.f;
|
||||||
|
|
||||||
|
std::array<Nz::BaseWidget*, 2> widgets = {m_StatusText, m_BackButton};
|
||||||
|
|
||||||
|
float maxWidth = 0.f;
|
||||||
|
float totalSize = padding * (widgets.size() - 1);
|
||||||
|
for (Nz::BaseWidget* widget : widgets) {
|
||||||
|
Nz::Vector2f size = widget->GetSize();
|
||||||
|
|
||||||
|
maxWidth = std::max(maxWidth, size.x);
|
||||||
|
totalSize += size.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::Vector2f cursor = center;
|
||||||
|
cursor.y += totalSize / 2.f;
|
||||||
|
|
||||||
|
for (Nz::BaseWidget* widget : widgets) {
|
||||||
|
widget->Resize({maxWidth, widget->GetHeight()});
|
||||||
|
widget->SetPosition({0.f, cursor.y - widget->GetSize().y, 0.f});
|
||||||
|
widget->CenterHorizontal();
|
||||||
|
cursor.y -= widget->GetSize().y + padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectingState::OnBackPressed() {
|
||||||
|
m_NextState = std::move(m_PreviousState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectingState::OnConnect() {
|
||||||
|
m_IsConnected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectingState::OnConnectFailed() {
|
||||||
|
m_StatusText->UpdateText(Nz::SimpleTextDrawer::Draw("Connection failed !", 80));
|
||||||
|
m_StatusText->CenterHorizontal();
|
||||||
|
m_Server.reset(nullptr);
|
||||||
|
m_Client.reset(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace client
|
||||||
|
} // namespace blitz
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
|
#include <Nazara/Core/Color.hpp>
|
||||||
|
#include <Nazara/Network/IpAddress.hpp>
|
||||||
|
#include <Nazara/Widgets/TextAreaWidget.hpp>
|
||||||
#include <client/states/CreateServerState.h>
|
#include <client/states/CreateServerState.h>
|
||||||
|
|
||||||
#include <Nazara/Core/StateMachine.hpp>
|
#include <Nazara/Core/StateMachine.hpp>
|
||||||
#include <Nazara/TextRenderer.hpp>
|
#include <Nazara/TextRenderer.hpp>
|
||||||
|
#include <client/Client.h>
|
||||||
|
#include <client/states/ConnectingState.h>
|
||||||
|
#include <server/Server.h>
|
||||||
|
|
||||||
namespace blitz {
|
namespace blitz {
|
||||||
namespace client {
|
namespace client {
|
||||||
@@ -18,6 +24,18 @@ CreateServerState::CreateServerState(std::shared_ptr<StateData> a_StateData, std
|
|||||||
m_CreateServerButton->Resize(m_CreateServerButton->GetPreferredSize());
|
m_CreateServerButton->Resize(m_CreateServerButton->GetPreferredSize());
|
||||||
m_CreateServerButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnCreateServerPressed(); });
|
m_CreateServerButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnCreateServerPressed(); });
|
||||||
|
|
||||||
|
m_InputPort = CreateWidget<Nz::TextAreaWidget>();
|
||||||
|
m_InputPort->SetBackgroundColor(Nz::Color::White());
|
||||||
|
m_InputPort->EnableBackground(true);
|
||||||
|
m_InputPort->EnableMultiline(false);
|
||||||
|
m_InputPort->SetTextColor(Nz::Color::Black());
|
||||||
|
m_InputPort->SetCharacterFilter([](Nz::UInt32 character) {
|
||||||
|
if (character < U'0' || character > U'9')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
m_BackButton = CreateWidget<Nz::ButtonWidget>();
|
m_BackButton = CreateWidget<Nz::ButtonWidget>();
|
||||||
textDrawer.SetText("Back");
|
textDrawer.SetText("Back");
|
||||||
m_BackButton->UpdateText(textDrawer);
|
m_BackButton->UpdateText(textDrawer);
|
||||||
@@ -40,7 +58,7 @@ void CreateServerState::LayoutWidgets() {
|
|||||||
|
|
||||||
constexpr float padding = 10.f;
|
constexpr float padding = 10.f;
|
||||||
|
|
||||||
std::array<Nz::BaseWidget*, 2> widgets = {m_CreateServerButton, m_BackButton};
|
std::array<Nz::BaseWidget*, 3> widgets = {m_InputPort, m_CreateServerButton, m_BackButton};
|
||||||
|
|
||||||
float maxWidth = 0.f;
|
float maxWidth = 0.f;
|
||||||
float totalSize = padding * (widgets.size() - 1);
|
float totalSize = padding * (widgets.size() - 1);
|
||||||
@@ -62,7 +80,24 @@ void CreateServerState::LayoutWidgets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateServerState::OnCreateServerPressed() {}
|
void CreateServerState::OnCreateServerPressed() {
|
||||||
|
std::string serverPort = m_InputPort->GetText();
|
||||||
|
if (serverPort.empty()) {
|
||||||
|
// UpdateStatus("Error: blank server port", Nz::Color::Red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long rawPort = std::stoi(serverPort);
|
||||||
|
if (rawPort <= 0 || rawPort > 0xFFFF) {
|
||||||
|
// UpdateStatus("Error: " + serverPort + " is not a valid port", Nz::Color::Red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::IpAddress address = Nz::IpAddress::LoopbackIpV4;
|
||||||
|
address.SetPort(rawPort);
|
||||||
|
|
||||||
|
m_NextState = std::make_shared<ConnectingState>(GetStateDataPtr(), shared_from_this(), "localhost", rawPort, true);
|
||||||
|
}
|
||||||
|
|
||||||
void CreateServerState::OnBackPressed() {
|
void CreateServerState::OnBackPressed() {
|
||||||
m_NextState = std::move(m_PreviousState);
|
m_NextState = std::move(m_PreviousState);
|
||||||
|
|||||||
16
src/client/states/GameState.cpp
Normal file
16
src/client/states/GameState.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <client/states/GameState.h>
|
||||||
|
|
||||||
|
#include <client/Client.h>
|
||||||
|
#include <server/Server.h>
|
||||||
|
|
||||||
|
namespace blitz {
|
||||||
|
namespace client {
|
||||||
|
|
||||||
|
GameState::GameState(
|
||||||
|
std::shared_ptr<StateData> a_StateData, std::unique_ptr<Client>&& a_Client, std::unique_ptr<server::Server>&& a_Server) :
|
||||||
|
AbstractState(a_StateData), m_Client(std::move(a_Client)), m_Server(std::move(a_Server)) {}
|
||||||
|
|
||||||
|
GameState::~GameState() {}
|
||||||
|
|
||||||
|
} // namespace client
|
||||||
|
} // namespace blitz
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#include <Nazara/Network/Enums.hpp>
|
||||||
|
#include <Nazara/Network/IpAddress.hpp>
|
||||||
|
#include <client/states/ConnectingState.h>
|
||||||
#include <client/states/JoinServerState.h>
|
#include <client/states/JoinServerState.h>
|
||||||
|
|
||||||
#include <Nazara/Core/StateMachine.hpp>
|
#include <Nazara/Core/StateMachine.hpp>
|
||||||
@@ -12,6 +15,13 @@ JoinServerState::JoinServerState(std::shared_ptr<StateData> a_StateData, std::sh
|
|||||||
textDrawer.SetTextColor({0.0, 0.0, 0.0, 1.0});
|
textDrawer.SetTextColor({0.0, 0.0, 0.0, 1.0});
|
||||||
textDrawer.SetCharacterSize(75);
|
textDrawer.SetCharacterSize(75);
|
||||||
|
|
||||||
|
m_InputAddress = CreateWidget<Nz::TextAreaWidget>();
|
||||||
|
m_InputAddress->SetBackgroundColor(Nz::Color::White());
|
||||||
|
m_InputAddress->EnableBackground(true);
|
||||||
|
m_InputAddress->EnableMultiline(false);
|
||||||
|
m_InputAddress->SetTextColor(Nz::Color::Black());
|
||||||
|
m_InputAddress->SetText("localhost");
|
||||||
|
|
||||||
m_JoinServerButton = CreateWidget<Nz::ButtonWidget>();
|
m_JoinServerButton = CreateWidget<Nz::ButtonWidget>();
|
||||||
textDrawer.SetText("Join Server");
|
textDrawer.SetText("Join Server");
|
||||||
m_JoinServerButton->UpdateText(textDrawer);
|
m_JoinServerButton->UpdateText(textDrawer);
|
||||||
@@ -40,7 +50,7 @@ void JoinServerState::LayoutWidgets() {
|
|||||||
|
|
||||||
constexpr float padding = 10.f;
|
constexpr float padding = 10.f;
|
||||||
|
|
||||||
std::array<Nz::BaseWidget*, 2> widgets = {m_JoinServerButton, m_BackButton};
|
std::array<Nz::BaseWidget*, 3> widgets = {m_InputAddress, m_JoinServerButton, m_BackButton};
|
||||||
|
|
||||||
float maxWidth = 0.f;
|
float maxWidth = 0.f;
|
||||||
float totalSize = padding * (widgets.size() - 1);
|
float totalSize = padding * (widgets.size() - 1);
|
||||||
@@ -62,7 +72,21 @@ void JoinServerState::LayoutWidgets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoinServerState::OnJoinServerPressed() {}
|
void JoinServerState::OnJoinServerPressed() {
|
||||||
|
std::string address = m_InputAddress->GetText();
|
||||||
|
auto separator = address.find(':');
|
||||||
|
std::string name = address.substr(0, separator);
|
||||||
|
std::uint16_t port = 25565;
|
||||||
|
if (separator != std::string::npos) {
|
||||||
|
try {
|
||||||
|
std::string rawPort = address.substr(separator + 1, std::string::npos);
|
||||||
|
port = std::stoi(rawPort);
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_NextState = std::make_shared<ConnectingState>(GetStateDataPtr(), shared_from_this(), name, port, false);
|
||||||
|
}
|
||||||
|
|
||||||
void JoinServerState::OnBackPressed() {
|
void JoinServerState::OnBackPressed() {
|
||||||
m_NextState = std::move(m_PreviousState);
|
m_NextState = std::move(m_PreviousState);
|
||||||
|
|||||||
@@ -13,8 +13,6 @@
|
|||||||
namespace blitz {
|
namespace blitz {
|
||||||
namespace server {
|
namespace server {
|
||||||
|
|
||||||
#define RegisterHandler(Handler) session.m_Handlers.push_back(std::make_unique<Handler>(*session.m_Connection, m_World))
|
|
||||||
|
|
||||||
Server::Server(std::uint16_t a_Port, Nz::EnttWorld& a_World) : m_World({a_World}), m_NetworkServer(a_Port) {
|
Server::Server(std::uint16_t a_Port, Nz::EnttWorld& a_World) : m_World({a_World}), m_NetworkServer(a_Port) {
|
||||||
RegisterSystems();
|
RegisterSystems();
|
||||||
m_NetworkServer.OnClientConnect.Connect(this, &Server::HandleConnect);
|
m_NetworkServer.OnClientConnect.Connect(this, &Server::HandleConnect);
|
||||||
@@ -22,7 +20,14 @@ Server::Server(std::uint16_t a_Port, Nz::EnttWorld& a_World) : m_World({a_World}
|
|||||||
m_NetworkServer.OnClientDisconnectTimeout.Connect(this, &Server::HandleDisconnect);
|
m_NetworkServer.OnClientDisconnectTimeout.Connect(this, &Server::HandleDisconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server() {}
|
Server::~Server() {
|
||||||
|
CloseServer();
|
||||||
|
|
||||||
|
AtomicEnttWorld world = m_World;
|
||||||
|
world->RemoveSystem<KeepAliveSystem>();
|
||||||
|
world->RemoveSystem<DisconnectSystem>();
|
||||||
|
world->RemoveSystem<RemovePlayersSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
void Server::HandleConnect(network::EnetConnection& a_Connection) {
|
void Server::HandleConnect(network::EnetConnection& a_Connection) {
|
||||||
Session newSession;
|
Session newSession;
|
||||||
@@ -50,7 +55,7 @@ void Server::CreateEntity(network::EnetConnection& a_Connection) {
|
|||||||
void Server::RegisterSystems() {
|
void Server::RegisterSystems() {
|
||||||
AtomicEnttWorld world = m_World;
|
AtomicEnttWorld world = m_World;
|
||||||
world->AddSystem<KeepAliveSystem>(m_World);
|
world->AddSystem<KeepAliveSystem>(m_World);
|
||||||
world->AddSystem<DisconectSystem>(m_World, *this);
|
world->AddSystem<DisconnectSystem>(m_World, *this);
|
||||||
world->AddSystem<RemovePlayersSystem>(m_World);
|
world->AddSystem<RemovePlayersSystem>(m_World);
|
||||||
|
|
||||||
auto counter = world->CreateEntity();
|
auto counter = world->CreateEntity();
|
||||||
@@ -58,8 +63,8 @@ void Server::RegisterSystems() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Server::RegisterHandlers(Session& session) {
|
void Server::RegisterHandlers(Session& session) {
|
||||||
RegisterHandler(KeepAliveHandler);
|
session.m_Handlers.push_back(std::make_unique<KeepAliveHandler>(*session.m_Connection, m_World));
|
||||||
RegisterHandler(PlayerLoginHandler);
|
session.m_Handlers.push_back(std::make_unique<PlayerLoginHandler>(*session.m_Connection, m_World));
|
||||||
}
|
}
|
||||||
|
|
||||||
network::EnetConnection* Server::GetConnection(std::uint16_t a_PeerId) {
|
network::EnetConnection* Server::GetConnection(std::uint16_t a_PeerId) {
|
||||||
@@ -81,5 +86,9 @@ void Server::CloseServer() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Server::IsClosed() const {
|
||||||
|
return m_NetworkServer.IsClosed();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
} // namespace blitz
|
} // namespace blitz
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
namespace blitz {
|
namespace blitz {
|
||||||
namespace server {
|
namespace server {
|
||||||
|
|
||||||
DisconectSystem::DisconectSystem(entt::registry&, EnttWorld& a_World, Server& a_Server) : m_World(a_World), m_Server(a_Server) {}
|
DisconnectSystem::DisconnectSystem(entt::registry&, EnttWorld& a_World, Server& a_Server) : m_World(a_World), m_Server(a_Server) {}
|
||||||
|
|
||||||
void DisconectSystem::Update(Nz::Time elapsedTime) {
|
void DisconnectSystem::Update(Nz::Time elapsedTime) {
|
||||||
AtomicEnttWorld world = m_World;
|
AtomicEnttWorld world = m_World;
|
||||||
|
|
||||||
entt::registry& registry = world->GetRegistry();
|
entt::registry& registry = world->GetRegistry();
|
||||||
|
|||||||
Reference in New Issue
Block a user