Compare commits

..

13 Commits

Author SHA1 Message Date
9147787fd2 allow communication between clients 2025-04-17 18:50:00 -05:00
24ab4a2f49 return to while 2025-04-17 18:40:18 -05:00
5c32a86674 onEvent return true 2025-04-17 18:32:55 -05:00
a728dc2c15 test 2025-04-17 18:28:35 -05:00
fa4bbbde0c handleEvents 2025-04-17 17:54:47 -05:00
799438ba3e build 2025-04-17 17:49:45 -05:00
30d80fa0de dependencies 2025-04-17 17:48:31 -05:00
4f36ce3086 spellcheck 2025-04-17 17:46:47 -05:00
9e62a5847c start server 2025-04-17 17:44:51 -05:00
c39b27b0d0 build 2025-04-17 17:32:18 -05:00
a79f40c66c build 2025-04-17 17:28:47 -05:00
a1e9401aaa refactor 2025-04-17 14:58:22 -05:00
f36f6ae125 work on ClientModule, add ChatServer 2025-04-17 14:16:57 -05:00
31 changed files with 619 additions and 90 deletions

View File

@@ -58,6 +58,7 @@
''; '';
}; };
Print = pkgs.stdenvNoCC.mkDerivation { Print = pkgs.stdenvNoCC.mkDerivation {
name = "Print"; name = "Print";
@@ -168,7 +169,6 @@
$imgui/*.cpp \ $imgui/*.cpp \
-DRENDERER_OPENGL \ -DRENDERER_OPENGL \
-DWINDOW_GLFW \ -DWINDOW_GLFW \
-DGUIMODULE \
-DTESTIMGUI_DYNAMIC \ -DTESTIMGUI_DYNAMIC \
-fpic -shared \ -fpic -shared \
-I src -I include -I $imgui -I . \ -I src -I include -I $imgui -I . \
@@ -214,4 +214,85 @@
''; '';
}; };
ChatServer = pkgs.stdenvNoCC.mkDerivation {
name = "ChatServer";
src = ./.;
nativeBuildInputs = with pkgs; [
clang
];
buildInputs = with pkgs; [
gamenetworkingsockets
];
buildPhase = ''
clang++ \
modules/examples/ChatServer/src/*.cpp \
modules/ServerModule/src/*.cpp \
-fpic -shared \
-I ${pkgs.gamenetworkingsockets}/include/GameNetworkingSockets \
-I src -I include -I . \
-lGameNetworkingSockets \
-DCHATSERVER_DYNAMIC \
-Wall \
-o $name
'';
installPhase = ''
mkdir -p $out/bin
cp $name $out/bin
'';
};
ChatClient = pkgs.stdenvNoCC.mkDerivation {
name = "ChatClient";
src = ./.;
imgui = inputs.imgui;
nativeBuildInputs = with pkgs; [
clang
];
buildInputs = with pkgs; [
gamenetworkingsockets
glfw
glew
];
buildPhase = ''
clang++ \
modules/examples/ChatClient/src/*.cpp \
modules/ClientModule/src/*.cpp \
-I ${pkgs.gamenetworkingsockets}/include/GameNetworkingSockets \
-lGameNetworkingSockets \
-DCHATCLIENT_DYNAMIC \
modules/WindowModule/src/*.cpp \
modules/ImguiModule/src/*.cpp \
$imgui/backends/imgui_impl_glfw.cpp \
$imgui/backends/imgui_impl_opengl3.cpp \
$imgui/misc/cpp/*.cpp \
$imgui/*.cpp \
-DRENDERER_OPENGL \
-DWINDOW_GLFW \
-fpic -shared \
-I src -I include -I $imgui -I . \
-lGL -lglfw -lGLEW \
-Wall \
-o $name
'';
installPhase = ''
mkdir -p $out/bin
cp $name $out/bin
'';
};
} }

View File

@@ -90,6 +90,7 @@
''; '';
}; };
WindowModule = pkgs.stdenvNoCC.mkDerivation { WindowModule = pkgs.stdenvNoCC.mkDerivation {
name = "WindowModule"; name = "WindowModule";

View File

@@ -60,13 +60,13 @@ namespace Archimedes {
unsigned int getEventType(std::string event) { return eventTypes[event]; } unsigned int getEventType(std::string event) { return eventTypes[event]; }
void addEventType(std::string type) { void registerEvent(std::string type) {
//only add each type once //only add each type once
if(eventTypes.find(type) == eventTypes.end()) if(eventTypes.find(type) == eventTypes.end())
eventTypes[type] = nextEventType++; eventTypes[type] = nextEventType++;
} }
void removeEventType(std::string type) { void unregisterEvent(std::string type) {
//only erase registered types //only erase registered types
auto it = eventTypes.find(type); auto it = eventTypes.find(type);
if(it != eventTypes.end()) if(it != eventTypes.end())
@@ -140,7 +140,7 @@ namespace Archimedes {
void* h = m->getHandle(); void* h = m->getHandle();
for(auto it = runOrder.begin(); it != runOrder.end(); it++) { for(auto it = runOrder.begin(); it != runOrder.end(); it++) {
if(*it == m->getName()) { if(*it == static_cast<std::string>(*m)) {
std::cout << "Module \"" << *it << "\" is already loaded!\n"; std::cout << "Module \"" << *it << "\" is already loaded!\n";
delete m; delete m;
if(h) { if(h) {
@@ -150,7 +150,7 @@ namespace Archimedes {
} }
} }
modules[m->getName()] = m; modules[*m] = m;
for(auto it = runOrder.begin(); it != runOrder.end(); it++) { for(auto it = runOrder.begin(); it != runOrder.end(); it++) {
@@ -164,7 +164,7 @@ namespace Archimedes {
} }
//insert temporarily to avoid circular dependencies //insert temporarily to avoid circular dependencies
runOrder.insert(roInsert, m->getName()); runOrder.insert(roInsert, *m);
bool skip = false; bool skip = false;
for(auto it : m->deps) { for(auto it : m->deps) {
@@ -185,9 +185,9 @@ namespace Archimedes {
} }
//reinsert once final order has been reached //reinsert once final order has been reached
runOrder.remove(m->getName()); runOrder.remove(*m);
runOrder.insert(roInsert, m->getName()); runOrder.insert(roInsert, *m);
return m; return m;
} }

View File

@@ -19,13 +19,15 @@ namespace Archimedes {
Module(App* a, void* h) : app(a), handle(h) {} Module(App* a, void* h) : app(a), handle(h) {}
Module() : app(nullptr), handle(nullptr) {}
virtual ~Module() {} virtual ~Module() {}
virtual void run() {} virtual void run() {}
virtual bool onEvent(const Event& e) { return false; } virtual bool onEvent(const Event& e) { return false; }
virtual void onLoad() {}; virtual void onLoad() {};
std::string getName() const { return name; } operator std::string() const { return name; }
void* getHandle() { return handle; } void* getHandle() { return handle; }
//std::any getData(std::string s) { return data[s.c_str()]; }; //std::any getData(std::string s) { return data[s.c_str()]; };

View File

@@ -14,7 +14,12 @@ namespace CMEvent {
DataRecievedEvent(ISteamNetworkingMessage* m) : msg(m) {} DataRecievedEvent(ISteamNetworkingMessage* m) : msg(m) {}
operator std::string() const { return "DataRecievedEvent"; } ~DataRecievedEvent() {
if(msg)
msg->Release();
}
operator std::string() const { return "CMEvent::DataRecievedEvent"; }
ISteamNetworkingMessage* msg; ISteamNetworkingMessage* msg;
@@ -28,7 +33,7 @@ namespace CMEvent {
DataSentEvent(ISteamNetworkingMessage* m) : msg(m) {} DataSentEvent(ISteamNetworkingMessage* m) : msg(m) {}
operator std::string() const { return "DataSentEvent"; } operator std::string() const { return "CMEvent::DataSentEvent"; }
ISteamNetworkingMessage* msg; ISteamNetworkingMessage* msg;
}; };
@@ -41,7 +46,7 @@ namespace CMEvent {
ConnectionStatusChangedEvent(SteamNetConnectionStatusChangedCallback_t* i) : info(i) {} ConnectionStatusChangedEvent(SteamNetConnectionStatusChangedCallback_t* i) : info(i) {}
operator std::string() const { return "ConnectionStatusChangedEvent"; } operator std::string() const { return "CMEvent::ConnectionStatusChangedEvent"; }
SteamNetConnectionStatusChangedCallback_t* info; SteamNetConnectionStatusChangedCallback_t* info;
}; };

View File

@@ -5,17 +5,136 @@ ClientModule::ClientModule(Archimedes::App* a, void* h) : Archimedes::Module(a,
} }
ClientModule::~ClientModule() { ClientModule::~ClientModule() {
GameNetworkingSockets_Kill(); if(app) {
app->unregisterEvent(CMEvent::DataRecievedEvent());
app->unregisterEvent(CMEvent::DataSentEvent());
app->unregisterEvent(CMEvent::ConnectionStatusChangedEvent());
GameNetworkingSockets_Kill();
}
} }
void ClientModule::onLoad() { void ClientModule::onLoad() {
app->registerEvent(CMEvent::DataSentEvent());
app->registerEvent(CMEvent::DataRecievedEvent());
app->registerEvent(CMEvent::ConnectionStatusChangedEvent());
SteamDatagramErrMsg errMsg; SteamDatagramErrMsg errMsg;
if ( !GameNetworkingSockets_Init( nullptr, errMsg ) ) { if ( !GameNetworkingSockets_Init( nullptr, errMsg ) ) {
//FatalError( "GameNetworkingSockets_Init failed. %s", errMsg ); //FatalError( "GameNetworkingSockets_Init failed. %s", errMsg );
std::cerr << "GameNetworkingSockets_Init() Failed: " << errMsg << std::endl; std::cerr << "GameNetworkingSockets_Init() Failed: " << errMsg << std::endl;
} }
//g_logTimeZero = SteamNetworkingUtils()->GetLocalTimestamp();
//SteamNetworkingUtils()->SetDebugOutputFunction( k_ESteamNetworkingSocketsDebugOutputType_Msg, DebugOutput ); //SteamNetworkingUtils()->SetDebugOutputFunction( k_ESteamNetworkingSocketsDebugOutputType_Msg, DebugOutput );
interface = SteamNetworkingSockets();
}
void ClientModule::startClient(SteamNetworkingIPAddr& serverAddr) {
if(!running) {
// Start connecting
char szAddr[ SteamNetworkingIPAddr::k_cchMaxString ];
serverAddr.ToString( szAddr, sizeof(szAddr), true );
std::cerr << "Connecting to chat server at " << szAddr << std::endl;
SteamNetworkingConfigValue_t opt;
opt.SetPtr( k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, (void*)SteamNetConnectionStatusChangedCallback );
connection = interface->ConnectByIPAddress( serverAddr, 1, &opt );
if ( connection == k_HSteamNetConnection_Invalid )
std::cerr << "Failed to create connection\n";
running = true;
}
}
void ClientModule::stopClient() { running = false; }
void ClientModule::run() {
if(running) {
pollIncomingData();
PollConnectionStateChanges();
}
}
bool ClientModule::onEvent(const Archimedes::Event& event) {
unsigned int type = app->getEventType(event);
if(eventsToHandle & CMEventEnum::ConnectionStatusChanged && type == app->getEventType(CMEvent::ConnectionStatusChangedEvent())) {
CMEvent::ConnectionStatusChangedEvent& e = (CMEvent::ConnectionStatusChangedEvent&) event;
switch(e.info->m_info.m_eState) {
case k_ESteamNetworkingConnectionState_None:
// NOTE: We will get callbacks here when we destroy connections. You can ignore these.
break;
case k_ESteamNetworkingConnectionState_ClosedByPeer:
case k_ESteamNetworkingConnectionState_ProblemDetectedLocally:
{
// Ignore if they were not previously connected. (If they disconnected
// before we accepted the connection.)
if ( e.info->m_eOldState == k_ESteamNetworkingConnectionState_Connected )
{
}
else
{
assert( e.info->m_eOldState == k_ESteamNetworkingConnectionState_Connecting );
}
// Clean up the connection. This is important!
// The connection is "closed" in the network sense, but
// it has not been destroyed. We must close it on our end, too
// to finish up. The reason information do not matter in this case,
// and we cannot linger because it's already closed on the other end,
// so we just pass 0's.
//
// OnDisconnect
interface->CloseConnection( e.info->m_hConn, 0, nullptr, false );
connection = k_HSteamNetConnection_Invalid;
break;
}
case k_ESteamNetworkingConnectionState_Connecting:
{
break;
}
case k_ESteamNetworkingConnectionState_Connected:
//OnConnect
break;
default:
// Silences -Wswitch
break;
}
return true;
} else if(eventsToHandle & CMEventEnum::DataRecieved && type == app->getEventType(CMEvent::DataRecievedEvent())) {
return true;
} else if(eventsToHandle & CMEventEnum::DataSent && type == app->getEventType(CMEvent::DataSentEvent())) {
return true;
}
return false;
}
void ClientModule::pollIncomingData() {
while(running) {
ISteamNetworkingMessage *pIncomingMsg = nullptr;
int numMsgs = interface->ReceiveMessagesOnConnection( connection, &pIncomingMsg, 1 );
if ( numMsgs == 0 )
break;
if ( numMsgs < 0 )
std::cerr << "Error checking for messages" << std::endl;
assert( numMsgs == 1 && pIncomingMsg );
assert( pIncomingMsg->m_conn == connection );
app->emitEvent(new CMEvent::DataRecievedEvent(pIncomingMsg));
}
} }

View File

@@ -3,16 +3,68 @@
#include <steam/steamnetworkingsockets.h> #include <steam/steamnetworkingsockets.h>
#include <steam/isteamnetworkingutils.h> #include <steam/isteamnetworkingutils.h>
#include "ClientEvents.h"
class ClientModule : public Archimedes::Module { class ClientModule : public Archimedes::Module {
public: public:
ClientModule(Archimedes::App*, void*); ClientModule(Archimedes::App*, void*);
ClientModule() { name = "ClientModule"; }
~ClientModule(); ~ClientModule();
void onLoad(); void onLoad();
void run(); void run();
bool onEvent(const Archimedes::Event&);
void startClient(SteamNetworkingIPAddr&);
void stopClient();
void sendReliable(const void* data, uint32 byteCount) {
interface->SendMessageToConnection(connection, data, byteCount, k_nSteamNetworkingSend_Reliable, nullptr);
}
bool isRunning() const { return running; }
bool isConnected() const { return connection != k_HSteamNetConnection_Invalid; }
void pollIncomingData();
void shouldHandleEvents(unsigned int events) { eventsToHandle = events; }
enum CMEventEnum {
None = 0,
ConnectionStatusChanged = 1 << 0,
DataRecieved = 1 << 1,
DataSent = 1 << 2
};
private: private:
unsigned int eventsToHandle = CMEventEnum::ConnectionStatusChanged | CMEventEnum::DataSent | CMEventEnum::DataRecieved;
bool running = false;
ISteamNetworkingSockets* interface;
HSteamNetConnection connection;
inline static ClientModule* callbackInstance = nullptr;
static void SteamNetConnectionStatusChangedCallback( SteamNetConnectionStatusChangedCallback_t *pInfo ) {
callbackInstance->OnSteamNetConnectionStatusChanged( pInfo );
}
void OnSteamNetConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t *pInfo ) {
app->emitEvent(new CMEvent::ConnectionStatusChangedEvent(pInfo));
}
void PollConnectionStateChanges() {
callbackInstance = this;
interface->RunCallbacks();
}
}; };
#ifdef CLIENTMODULE_DYNAMIC #ifdef CLIENTMODULE_DYNAMIC

View File

@@ -14,22 +14,26 @@ ImguiModule::ImguiModule(Archimedes::App* a, void* h = nullptr) : Archimedes::Mo
name = "ImguiModule"; name = "ImguiModule";
WindowModule* wm = new WindowModule(a, h); WindowModule* wm = new WindowModule(a, h);
deps[wm->getName()] = wm; deps[*wm] = wm;
} }
ImguiModule::~ImguiModule() { ImguiModule::~ImguiModule() {
WindowModule* wm = (WindowModule*) moduleInstances["WindowModule"]; if(app) {
wm->getRenderer()->getCmdList().erase(rcmd_it); WindowModule* wm; { wm = (WindowModule*) moduleInstances[WindowModule()]; }
ImGui_ImplOpenGL3_Shutdown(); wm->getRenderer()->getCmdList().erase(rcmd_it);
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext(); ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
} }
void ImguiModule::onLoad() { void ImguiModule::onLoad() {
WindowModule* wm = (WindowModule*) moduleInstances["WindowModule"];
WindowModule* wm; { wm = (WindowModule*) moduleInstances[WindowModule()]; }
if(!wm) { if(!wm) {
std::cout << "No WindowModule for ImguiModule!\n"; std::cout << "No WindowModule for ImguiModule!\n";
std::abort(); std::abort();

View File

@@ -12,6 +12,8 @@ class ImguiModule : public Archimedes::Module {
public: public:
ImguiModule(Archimedes::App*, void*); ImguiModule(Archimedes::App*, void*);
ImguiModule() { name = "ImguiModule"; }
~ImguiModule(); ~ImguiModule();
void onLoad(); void onLoad();

View File

@@ -7,16 +7,17 @@ MainGUI::MainGUI(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
name = "MainGUI"; name = "MainGUI";
ImguiModule* im = new ImguiModule(a, h); ImguiModule* im = new ImguiModule(a, h);
deps[im->getName()] = im; deps[*im] = im;
} }
MainGUI::~MainGUI() { MainGUI::~MainGUI() {
if(app) {}
} }
void MainGUI::onLoad() { void MainGUI::onLoad() {
ImguiModule* im = (ImguiModule*) moduleInstances["ImguiModule"]; ImguiModule* im; { im = (ImguiModule*) moduleInstances[ImguiModule()]; }
if(!im) { if(!im) {
std::cout << "No ImguiModule for MainGUI!\n"; std::cout << "No ImguiModule for MainGUI!\n";

View File

@@ -5,6 +5,8 @@ class MainGUI : public Archimedes::Module {
public: public:
MainGUI(Archimedes::App*, void*); MainGUI(Archimedes::App*, void*);
MainGUI() { name = "MainGUI"; }
~MainGUI(); ~MainGUI();
void onLoad(); void onLoad();

View File

@@ -8,15 +8,17 @@ Ollama::Ollama(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
name = "Ollama"; name = "Ollama";
ImguiModule* im = new ImguiModule(a, h); ImguiModule* im = new ImguiModule(a, h);
deps[im->getName()] = im; deps[*im] = im;
} }
Ollama::~Ollama() { Ollama::~Ollama() {
if(curl) { if(app) {
curl_easy_cleanup(curl); if(curl) {
curl = nullptr; curl_easy_cleanup(curl);
curl = nullptr;
}
curl_global_cleanup();
} }
curl_global_cleanup();
} }
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::ostream* userp) static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::ostream* userp)
@@ -27,7 +29,7 @@ static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::ostr
void Ollama::onLoad() { void Ollama::onLoad() {
ImguiModule* im = (ImguiModule*) moduleInstances["ImguiModule"]; ImguiModule* im; { im = (ImguiModule*) moduleInstances[ImguiModule()]; }
if(!im) { if(!im) {
std::cout << "No ImguiModule for Ollama!\n"; std::cout << "No ImguiModule for Ollama!\n";
@@ -109,7 +111,7 @@ void Ollama::run() {
if(code != CURLE_OK) { if(code != CURLE_OK) {
std::cerr << "curl_easy_perform() failed!: " << curl_easy_strerror(code) << std::endl; std::cerr << "curl_easy_perform() failed!: " << curl_easy_strerror(code) << std::endl;
app->stopModule(getName()); app->stopModule(name);
return; return;
} else { } else {
jsonObj = nlohmann::json::parse(response); jsonObj = nlohmann::json::parse(response);

View File

@@ -8,6 +8,7 @@ class Ollama : public Archimedes::Module {
public: public:
Ollama(Archimedes::App*, void*); Ollama(Archimedes::App*, void*);
Ollama() { name = "Ollama"; }
~Ollama(); ~Ollama();
void onLoad(); void onLoad();

View File

@@ -19,7 +19,7 @@ namespace SMEvent {
DataRecievedEvent(ISteamNetworkingMessage* m) : msg(m) {} DataRecievedEvent(ISteamNetworkingMessage* m) : msg(m) {}
operator std::string() const { return "DataRecievedEvent"; } operator std::string() const { return "SMEvent::DataRecievedEvent"; }
ISteamNetworkingMessage* msg; ISteamNetworkingMessage* msg;
@@ -38,7 +38,7 @@ namespace SMEvent {
DataSentEvent(ISteamNetworkingMessage* m) : msg(m) {} DataSentEvent(ISteamNetworkingMessage* m) : msg(m) {}
operator std::string() const { return "DataSentEvent"; } operator std::string() const { return "SMEvent::DataSentEvent"; }
ISteamNetworkingMessage* msg; ISteamNetworkingMessage* msg;
}; };
@@ -51,7 +51,7 @@ namespace SMEvent {
ConnectionStatusChangedEvent(SteamNetConnectionStatusChangedCallback_t* i) : info(i) {} ConnectionStatusChangedEvent(SteamNetConnectionStatusChangedCallback_t* i) : info(i) {}
operator std::string() const { return "ConnectionStatusChangedEvent"; } operator std::string() const { return "SMEvent::ConnectionStatusChangedEvent"; }
SteamNetConnectionStatusChangedCallback_t* info; SteamNetConnectionStatusChangedCallback_t* info;
}; };

View File

@@ -5,18 +5,20 @@ ServerModule::ServerModule(Archimedes::App* a, void* h) : Archimedes::Module(a,
} }
ServerModule::~ServerModule() { ServerModule::~ServerModule() {
app->removeEventType(SMEvent::DataRecievedEvent()); if(app) {
app->removeEventType(SMEvent::DataSentEvent()); app->unregisterEvent(SMEvent::DataRecievedEvent());
app->removeEventType(SMEvent::ConnectionStatusChangedEvent()); app->unregisterEvent(SMEvent::DataSentEvent());
app->unregisterEvent(SMEvent::ConnectionStatusChangedEvent());
GameNetworkingSockets_Kill(); GameNetworkingSockets_Kill();
}
} }
void ServerModule::onLoad() { void ServerModule::onLoad() {
app->addEventType(SMEvent::DataRecievedEvent()); app->registerEvent(SMEvent::DataRecievedEvent());
app->addEventType(SMEvent::DataSentEvent()); app->registerEvent(SMEvent::DataSentEvent());
app->addEventType(SMEvent::ConnectionStatusChangedEvent()); app->registerEvent(SMEvent::ConnectionStatusChangedEvent());
SteamDatagramErrMsg errMsg; SteamDatagramErrMsg errMsg;
@@ -28,26 +30,38 @@ void ServerModule::onLoad() {
interface = SteamNetworkingSockets(); interface = SteamNetworkingSockets();
SteamNetworkingIPAddr serverLocalAddr; }
serverLocalAddr.Clear();
serverLocalAddr.m_port = port;
SteamNetworkingConfigValue_t opt;
opt.SetPtr(k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, (void*)SteamNetConnectionStatusChangedCallback);
listenSock = interface->CreateListenSocketIP( serverLocalAddr, 1, &opt ); void ServerModule::startServer(int p) {
if ( listenSock == k_HSteamListenSocket_Invalid ) if(!running) {
std::cerr << "Failed to listen on port " << port << std::endl; port = p;
pollGroup = interface->CreatePollGroup();
if ( pollGroup == k_HSteamNetPollGroup_Invalid ) SteamNetworkingIPAddr serverLocalAddr;
std::cerr << "Failed to listen on port " << port << std::endl; serverLocalAddr.Clear();
//Printf( "Server listening on port %d\n", port ); serverLocalAddr.m_port = port;
SteamNetworkingConfigValue_t opt;
opt.SetPtr(k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, (void*)SteamNetConnectionStatusChangedCallback);
listenSock = interface->CreateListenSocketIP( serverLocalAddr, 1, &opt );
if ( listenSock == k_HSteamListenSocket_Invalid )
std::cerr << "Failed to listen on port " << port << std::endl;
pollGroup = interface->CreatePollGroup();
if ( pollGroup == k_HSteamNetPollGroup_Invalid )
std::cerr << "Failed to listen on port " << port << std::endl;
std::cerr << "Server listening on port " << port << std::endl;
running = true;
}
}
void ServerModule::stopServer() {
running = false;
} }
void ServerModule::run() { void ServerModule::run() {
if(running) { if(running) {
pollIncomingData(); pollIncomingData();
PollConnectionStateChanges(); PollConnectionStateChanges();
PollLocalUserInput();
} else if(port >= 0) { } else if(port >= 0) {
interface->CloseListenSocket(listenSock); interface->CloseListenSocket(listenSock);
@@ -56,18 +70,16 @@ void ServerModule::run() {
interface->DestroyPollGroup(pollGroup); interface->DestroyPollGroup(pollGroup);
pollGroup = k_HSteamNetPollGroup_Invalid; pollGroup = k_HSteamNetPollGroup_Invalid;
app->stopModule(getName()); port = -1;
port = -1; //just in case
} }
} }
void ServerModule::OnSteamNetConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t *pInfo ) {
app->emitEvent(new SMEvent::ConnectionStatusChangedEvent(pInfo));
}
bool ServerModule::onEvent(const Archimedes::Event& event) { bool ServerModule::onEvent(const Archimedes::Event& event) {
if(eventsToHandle & SMEventEnum::ConnectionStatusChanged && app->getEventType(event) == app->getEventType("ConnectionStatusChangedEvent")) { unsigned int type = app->getEventType(event);
if(eventsToHandle & SMEventEnum::ConnectionStatusChanged && type == app->getEventType(SMEvent::ConnectionStatusChangedEvent())) {
SMEvent::ConnectionStatusChangedEvent& e = (SMEvent::ConnectionStatusChangedEvent&) event; SMEvent::ConnectionStatusChangedEvent& e = (SMEvent::ConnectionStatusChangedEvent&) event;
@@ -93,18 +105,18 @@ bool ServerModule::onEvent(const Archimedes::Event& event) {
// Select appropriate log messages // Select appropriate log messages
//const char *pszDebugLogAction; //const char *pszDebugLogAction;
if ( e.info->m_info.m_eState == k_ESteamNetworkingConnectionState_ProblemDetectedLocally ) /*if ( e.info->m_info.m_eState == k_ESteamNetworkingConnectionState_ProblemDetectedLocally )
{ {
//pszDebugLogAction = "problem detected locally"; pszDebugLogAction = "problem detected locally";
//sprintf( temp, "Alas, %s hath fallen into shadow. (%s)", itClient->second.name.c_str(), e.info->m_info.m_szEndDebug ); sprintf( temp, "Alas, %s hath fallen into shadow. (%s)", itClient->second.name.c_str(), e.info->m_info.m_szEndDebug );
} }
else else
{ {
// Note that here we could check the reason code to see if // Note that here we could check the reason code to see if
// it was a "usual" connection or an "unusual" one. // it was a "usual" connection or an "unusual" one.
//pszDebugLogAction = "closed by peer"; (void)pszDebugLogAction; pszDebugLogAction = "closed by peer"; (void)pszDebugLogAction;
//sprintf( temp, "%s hath departed", itClient->second.name.c_str() ); sprintf( temp, "%s hath departed", itClient->second.name.c_str() );
} }*/
// Spew something to our own log. Note that because we put their nick // Spew something to our own log. Note that because we put their nick
// as the connection description, it will show up, along with their // as the connection description, it will show up, along with their
@@ -154,6 +166,7 @@ bool ServerModule::onEvent(const Archimedes::Event& event) {
//Printf( "Can't accept connection. (It was already closed?)" ); //Printf( "Can't accept connection. (It was already closed?)" );
break; break;
} }
std::cerr << "Connection Accepted!\n";
// Assign the poll group // Assign the poll group
if ( !interface->SetConnectionPollGroup( e.info->m_hConn, pollGroup ) ) if ( !interface->SetConnectionPollGroup( e.info->m_hConn, pollGroup ) )
@@ -180,9 +193,9 @@ bool ServerModule::onEvent(const Archimedes::Event& event) {
} }
return true; return true;
} else if(eventsToHandle & SMEventEnum::DataRecieved && app->getEventType(event) == app->getEventType("DataRecievedEvent")) { } else if(eventsToHandle & SMEventEnum::DataRecieved && type == app->getEventType(SMEvent::DataRecievedEvent())) {
return true; return true;
} else if(eventsToHandle & SMEventEnum::DataSent && app->getEventType(event) == app->getEventType("DataSentEvent")) { } else if(eventsToHandle & SMEventEnum::DataSent && type == app->getEventType(SMEvent::DataSentEvent())) {
return true; return true;
} }

View File

@@ -1,3 +1,6 @@
#ifndef SERVERMODULE_H
#define SERVERMODULE_H
#include "Archimedes.h" #include "Archimedes.h"
#include <steam/steamnetworkingsockets.h> #include <steam/steamnetworkingsockets.h>
@@ -9,6 +12,9 @@ class ServerModule : public Archimedes::Module {
public: public:
ServerModule(Archimedes::App*, void*); ServerModule(Archimedes::App*, void*);
ServerModule() { name = "ServerModule"; }
~ServerModule(); ~ServerModule();
void onLoad(); void onLoad();
bool onEvent(const Archimedes::Event&); bool onEvent(const Archimedes::Event&);
@@ -24,9 +30,17 @@ class ServerModule : public Archimedes::Module {
DataSent = 1 << 2 DataSent = 1 << 2
}; };
bool isRunning() const { return running; }
void shouldHandleEvents(unsigned int events) { eventsToHandle = events; } void shouldHandleEvents(unsigned int events) { eventsToHandle = events; }
void sendData() {} void sendReliable(HSteamNetConnection client, const void* data, uint32 byteCount) {
interface->SendMessageToConnection(client, data, byteCount, k_nSteamNetworkingSend_Reliable, nullptr);
}
std::map<HSteamNetConnection, unsigned int> getClients() const { return clients; }
void pollIncomingData(); void pollIncomingData();
private: private:
@@ -48,16 +62,21 @@ class ServerModule : public Archimedes::Module {
callbackInstance->OnSteamNetConnectionStatusChanged( pInfo ); callbackInstance->OnSteamNetConnectionStatusChanged( pInfo );
} }
void OnSteamNetConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t *pInfo ); void OnSteamNetConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t *pInfo ) {
app->emitEvent(new SMEvent::ConnectionStatusChangedEvent(pInfo));
}
std::map<HSteamNetConnection, unsigned int> clients; std::map<HSteamNetConnection, unsigned int> clients;
void PollConnectionStateChanges(); void PollConnectionStateChanges() {
void PollLocalUserInput(); callbackInstance = this;
interface->RunCallbacks();
}
}; };
#ifdef SERVERMODULE_DYNAMIC #ifdef SERVERMODULE_DYNAMIC
#define MODULE_TYPE ServerModule #define MODULE_TYPE ServerModule
#include "endModule.h" #include "endModule.h"
#endif #endif
#endif

View File

@@ -13,16 +13,16 @@ Terminal::Terminal(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
name = "Terminal"; name = "Terminal";
ImguiModule* im = new ImguiModule(a, h); ImguiModule* im = new ImguiModule(a, h);
deps[im->getName()] = im; deps[*im] = im;
} }
Terminal::~Terminal() { Terminal::~Terminal() {
if(app) {}
} }
void Terminal::onLoad() { void Terminal::onLoad() {
ImguiModule* im = (ImguiModule*) moduleInstances["ImguiModule"]; ImguiModule* im; { im = (ImguiModule*) moduleInstances[ImguiModule()]; }
if(!im) { if(!im) {
std::cout << "No ImguiModule for Terminal!\n"; std::cout << "No ImguiModule for Terminal!\n";
@@ -67,7 +67,7 @@ void Terminal::run() {
rc = read(master, opArr, 150); rc = read(master, opArr, 150);
if(rc < 0) { if(rc < 0) {
//error on read //error on read
app->stopModule(getName()); app->stopModule(name);
} else { } else {
if(input == "clear") output = ""; if(input == "clear") output = "";
output += opArr; output += opArr;

View File

@@ -5,6 +5,7 @@ class Terminal : public Archimedes::Module {
public: public:
Terminal(Archimedes::App*, void*); Terminal(Archimedes::App*, void*);
Terminal() { name = "Terminal"; }
~Terminal(); ~Terminal();
void onLoad(); void onLoad();

View File

@@ -1,12 +1,14 @@
#include "WindowModule.h" #include "WindowModule.h"
WindowModule::~WindowModule() { WindowModule::~WindowModule() {
if(renderer) { if(app) {
renderer->getCmdList().clear(); if(renderer) {
delete renderer; renderer->getCmdList().clear();
} delete renderer;
if(window) { }
delete window; if(window) {
delete window;
}
} }
} }

View File

@@ -9,10 +9,11 @@
class WindowModule : public Archimedes::Module { class WindowModule : public Archimedes::Module {
public: public:
WindowModule(Archimedes::App* a, void* h = nullptr) : Archimedes::Module(a, h) { WindowModule(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
name = "WindowModule"; name = "WindowModule";
} }
WindowModule() { name = "WindowModule"; }
~WindowModule(); ~WindowModule();

View File

@@ -0,0 +1,96 @@
#include "ChatClient.h"
ChatClient::ChatClient(Archimedes::App* a, void* h) : Module(a, h) {
name = "ChatClient";
ClientModule* cm = new ClientModule(a, h);
deps[*cm] = cm;
cm->shouldHandleEvents(ClientModule::CMEventEnum::ConnectionStatusChanged | ClientModule::CMEventEnum::DataSent);
ImguiModule* im = new ImguiModule(a, h);
deps[*im] = im;
}
void ChatClient::onLoad() {
}
void ChatClient::run() {
static ClientModule* cm; { cm = (ClientModule*) moduleInstances[ClientModule()]; }
if(open) {
static std::string s, addr;
ImGui::Begin("ChatClient Module", &open);
ImGui::InputText("Server Address: ", &addr);
if(cm->isRunning() && cm->isConnected()) {
if(ImGui::Button("Disconnect") && cm->isRunning()) {
cm->stopClient();
}
} else {
if(ImGui::Button("Connect") && !cm->isRunning()) {
static SteamNetworkingIPAddr serverAddr;
serverAddr.ParseString(addr.c_str());
cm->startClient(serverAddr);
}
}
ImGui::Text("%s", messages.c_str());
ImGui::InputText("Message: ", &s);
ImGui::SameLine();
if(ImGui::Button("send")) {
cm->sendReliable(s.c_str(), (uint32) s.length());
}
ImGui::End();
} else {
app->stopModule(name);
}
}
bool ChatClient::onEvent(const Archimedes::Event& event) {
unsigned int type = app->getEventType(event);
/*if(type == app->getEventType("DataSentEvent")) {
//we did this?
return true;
} else */
if(type == app->getEventType(CMEvent::DataRecievedEvent())) {
CMEvent::DataRecievedEvent& e = (CMEvent::DataRecievedEvent&) event;
static std::string s; s = std::string((const char*)e.msg->m_pData, e.msg->m_cbSize);
std::cerr << "Client Recieved: " << s << std::endl;
messages += "\n\n" + s;
return true;
}
/*else if(type == app->getEventType("ConnectionStatusChangedEvent")) {
//CMEvent::ConnectionStatusChangedEvent& e = (CMEvent::ConnectionStatusChangedEvent&) event;
return false;
}*/
return false;
}

View File

@@ -0,0 +1,33 @@
#include "Archimedes.h"
#include "modules/ClientModule/src/ClientModule.h"
#include "modules/ImguiModule/src/ImguiModule.h"
class ChatClient : public Archimedes::Module {
public:
ChatClient(Archimedes::App* a, void* h);
ChatClient() { name = "ChatClient"; }
~ChatClient() {
if(app) {}
}
void onLoad();
void run();
bool onEvent(const Archimedes::Event&);
private:
std::string messages = "";
bool open = true;
};
#ifdef CHATCLIENT_DYNAMIC
#define MODULE_TYPE ChatClient
#include "endModule.h"
#endif

View File

@@ -0,0 +1,49 @@
#include "ChatServer.h"
void ChatServer::onLoad() {
ServerModule* sm = (ServerModule*) moduleInstances[ServerModule()];
sm->startServer(9932);
}
//void ChatServer::run() {}
bool ChatServer::onEvent(const Archimedes::Event& event) {
unsigned int type = app->getEventType(event);
/*if(type == app->getEventType("DataSentEvent")) {
//we did this?
return true;
} else */
if(type == app->getEventType(SMEvent::DataRecievedEvent())) {
static ServerModule* sm; { sm = (ServerModule*) moduleInstances[ServerModule()]; }
SMEvent::DataRecievedEvent& e = (SMEvent::DataRecievedEvent&) event;
static std::string s; s = std::string((const char*)e.msg->m_pData, e.msg->m_cbSize);
std::cerr << "Server Recieved: " << s << std::endl;
for(auto& it : sm->getClients()) {
if(it.first != e.msg->m_conn)
sm->sendReliable(it.first, s.c_str(), s.length());
else
sm->sendReliable(e.msg->m_conn, "\nMessage sent\n", strlen("\nMessage sent\n"));
}
return true;
} /*else if(type == app->getEventType("ConnectionStatusChangedEvent")) {
//SMEvent::ConnectionStatusChangedEvent& e = (SMEvent::ConnectionStatusChangedEvent&) event;
return false;
}*/
return false;
}

View File

@@ -0,0 +1,34 @@
#include "Archimedes.h"
#include "modules/ServerModule/src/ServerModule.h"
class ChatServer : public Archimedes::Module {
public:
ChatServer(Archimedes::App* a, void* h) : Module(a, h) {
name = "ChatServer";
ServerModule* sm = new ServerModule(a, h);
deps[*sm] = sm;
sm->shouldHandleEvents(ServerModule::SMEventEnum::ConnectionStatusChanged | ServerModule::SMEventEnum::DataSent);
}
ChatServer() { name = "ChatServer"; }
~ChatServer() {
if(app) {}
}
void onLoad();
//void run();
bool onEvent(const Archimedes::Event&);
};
#ifdef CHATSERVER_DYNAMIC
#define MODULE_TYPE ChatServer
#include "endModule.h"
#endif

View File

@@ -5,7 +5,8 @@
DependsOnPrintStatic::DependsOnPrintStatic(Archimedes::App* a, void* h) : Module(a, h) { DependsOnPrintStatic::DependsOnPrintStatic(Archimedes::App* a, void* h) : Module(a, h) {
name = "DependsOnPrintStatic"; name = "DependsOnPrintStatic";
deps["Print"] = new Print(a, h); Print* p = new Print(a, h);
deps[*p] = p;
} }
DependsOnPrintStatic::~DependsOnPrintStatic() { DependsOnPrintStatic::~DependsOnPrintStatic() {

View File

@@ -5,7 +5,9 @@ Print::Print(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
} }
Print::~Print() { Print::~Print() {
std::cout << "Print Destroyed!\n"; if(app) {
std::cout << "Print Destroyed!\n";
}
} }
void Print::run() { void Print::run() {

View File

@@ -4,6 +4,7 @@ class Print : public Archimedes::Module {
public: public:
Print(Archimedes::App*, void*); Print(Archimedes::App*, void*);
Print() { name = "Print"; }
~Print(); ~Print();
void run(); void run();
}; };

View File

@@ -6,7 +6,7 @@ TestImgui::TestImgui(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
name = "TestImgui"; name = "TestImgui";
ImguiModule* im = new ImguiModule(a, h); ImguiModule* im = new ImguiModule(a, h);
deps[im->getName()] = im; deps[*im] = im;
} }
TestImgui::~TestImgui() { TestImgui::~TestImgui() {
@@ -30,7 +30,7 @@ void TestImgui::run() {
if(demo) if(demo)
ImGui::ShowDemoWindow(&this->demo); ImGui::ShowDemoWindow(&this->demo);
else else
app->stopModule(getName()); app->stopModule(name);
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();

View File

@@ -5,6 +5,8 @@ class TestImgui : public Archimedes::Module {
public: public:
TestImgui(Archimedes::App*, void*); TestImgui(Archimedes::App*, void*);
TestImgui() { name = "TestImgui"; }
~TestImgui(); ~TestImgui();
void onLoad(); void onLoad();

View File

@@ -4,6 +4,7 @@ class TestMenu : public Archimedes::Module {
public: public:
TestMenu(Archimedes::App*, void*); TestMenu(Archimedes::App*, void*);
TestMenu() { name = "TestMenu"; }
~TestMenu(); ~TestMenu();
void run(); void run();
void onLoad() {} void onLoad() {}

View File

@@ -13,6 +13,8 @@ void MinimalApp::run() {
modules[m]->run(); modules[m]->run();
} }
handleEvents();
for(std::string m : toClose) { for(std::string m : toClose) {
unload(m); unload(m);
} }