summaryrefslogtreecommitdiffhomepage
path: root/Starserver
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2022-04-07 00:24:56 +0200
committerAki <please@ignore.pl>2022-04-07 00:24:56 +0200
commitd8c1d5b840acc183e2cef112ebc6760952583f87 (patch)
treefc855d24ec6314c49f5aef61e722a60552e093d7 /Starserver
parent7d00261f6b3bf7da2b9371796848883dc3b40392 (diff)
downloadstarshatter-d8c1d5b840acc183e2cef112ebc6760952583f87.zip
starshatter-d8c1d5b840acc183e2cef112ebc6760952583f87.tar.gz
starshatter-d8c1d5b840acc183e2cef112ebc6760952583f87.tar.bz2
Moved server exclusive files to own module
Diffstat (limited to 'Starserver')
-rw-r--r--Starserver/CMakeLists.txt4
-rw-r--r--Starserver/NetAdminChat.cpp120
-rw-r--r--Starserver/NetAdminChat.h32
-rw-r--r--Starserver/NetAdminServer.cpp784
-rw-r--r--Starserver/NetAdminServer.h90
-rw-r--r--Starserver/NetFileServlet.cpp117
-rw-r--r--Starserver/NetFileServlet.h49
-rw-r--r--Starserver/StarServer.cpp309
-rw-r--r--Starserver/StarServer.h54
9 files changed, 1559 insertions, 0 deletions
diff --git a/Starserver/CMakeLists.txt b/Starserver/CMakeLists.txt
index 3142ce2..779b494 100644
--- a/Starserver/CMakeLists.txt
+++ b/Starserver/CMakeLists.txt
@@ -2,6 +2,10 @@ project(Starserver)
add_executable(
Starserver
Main.cpp
+ NetAdminChat.cpp
+ NetAdminServer.cpp
+ NetFileServlet.cpp
+ StarServer.cpp
)
target_include_directories(
Starserver
diff --git a/Starserver/NetAdminChat.cpp b/Starserver/NetAdminChat.cpp
new file mode 100644
index 0000000..359173a
--- /dev/null
+++ b/Starserver/NetAdminChat.cpp
@@ -0,0 +1,120 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ HTTP Servlet Engine for Multiplayer Admin
+*/
+
+
+#include "NetAdminChat.h"
+#include "NetLobbyServer.h"
+#include "NetServerConfig.h"
+#include "NetUser.h"
+#include "NetChat.h"
+#include "NetUtil.h"
+
+#include "HttpServlet.h"
+#include "NetLayer.h"
+#include "FormatUtil.h"
+
+// +-------------------------------------------------------------------+
+
+NetAdminChat::NetAdminChat()
+{ }
+
+// +-------------------------------------------------------------------+
+
+bool
+NetAdminChat::DoGet(HttpRequest& request, HttpResponse& response)
+{
+ if (CheckUser(request, response)) {
+ NetLobbyServer* lobby = NetLobbyServer::GetInstance();
+
+ if (lobby) {
+ Text msg = request.GetParam("msg");
+ Text act = request.GetParam("action");
+
+ if (msg.length()) {
+ lobby->AddChat(user, msg);
+
+ if (user)
+ NetUtil::SendChat(0xffff, user->Name(), msg);
+ }
+
+ else if (act.length()) {
+ if (act == "clear")
+ lobby->ClearChat();
+
+ else if (act == "save")
+ lobby->SaveChat();
+ }
+ }
+
+ response.SetStatus(HttpResponse::SC_OK);
+ response.AddHeader("MIME-Version", "1.0");
+ response.AddHeader("Content-Type", "text/html");
+ response.AddHeader("Cache-Control", "no-cache");
+ response.AddHeader("Expires", "-1");
+
+ response.SetContent(GetHead("Chat") +
+ GetTitleBar(GetStatLine(),
+ "onLoad=\"self.focus();document.chatForm.msg.focus();\"") +
+ GetContent() +
+ GetBodyClose());
+ }
+
+ return true;
+}
+
+// +-------------------------------------------------------------------+
+
+Text
+NetAdminChat::GetContent()
+{
+ Text content = "<div style=\"overflow-y:scroll; height:240px; padding-right:4pt; padding-left:4pt; padding-bottom:4pt; padding-top:4pt; margin:4pt;\">\n";
+
+ int nchat = 0;
+ NetLobbyServer* lobby = NetLobbyServer::GetInstance();
+ if (lobby) {
+ content += "\n<table width=\"90%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n";
+
+ ListIter<NetChatEntry> iter = lobby->GetChat();
+ while (++iter) {
+ NetChatEntry* c = iter.value();
+
+ content += " <tr><td nowrap width=\"130\" class=\"tiny\">";
+ content += FormatTimeString(c->GetTime());
+ content += "</td><td nowrap width=\"80\" class=\"tiny\">";
+ content += c->GetUser();
+ content += "</td><td class=\"tiny\">";
+ content += c->GetMessage();
+ content += "</td></tr>\n";
+ }
+
+ content += "</table>\n\n";
+ }
+
+ content += "</div>\n<div class=\"content\">\n\
+<form name=\"chatForm\" method=\"post\"action=\"/chat\">\n\
+<table border=\"0\">\n\
+ <tr>\n\
+ <td valign=\"middle\">&nbsp;&nbsp;<input type=\"text\" name=\"msg\" size=\"80\"></td>\n\
+ <td valign=\"middle\">&nbsp;&nbsp;<input type=\"submit\" value=\"Send\"></td>\n\
+ </tr>\n\
+ <tr>\n\
+ <td colspan=\"2\" valign=\"middle\" class=\"std\">&nbsp;&nbsp;<a href=\"/chat\">Refresh</a>\
+&nbsp;&nbsp;&#183;&nbsp;&nbsp;<a href=\"/chat?action=save\">Save</a>&nbsp;&nbsp;&#183;&nbsp;&nbsp;<a href=\"/chat?action=clear\">Clear</a></td>\n\
+ </tr>\n\
+</table>\n\
+</form>\n\
+</div>\n\n";
+
+ content += GetCopyright();
+ return content;
+}
diff --git a/Starserver/NetAdminChat.h b/Starserver/NetAdminChat.h
new file mode 100644
index 0000000..2ce1fba
--- /dev/null
+++ b/Starserver/NetAdminChat.h
@@ -0,0 +1,32 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ HTTP Servlet Engine for Multiplayer Admin
+*/
+
+
+#ifndef NetAdminChat_h
+#define NetAdminChat_h
+
+#include "NetAdminServer.h"
+
+// +-------------------------------------------------------------------+
+
+class NetAdminChat : public NetAdminServlet
+{
+public:
+ NetAdminChat();
+ virtual ~NetAdminChat() { }
+
+ virtual bool DoGet(HttpRequest& request, HttpResponse& response);
+ virtual Text GetContent();
+};
+
+#endif // NetAdminChat_h \ No newline at end of file
diff --git a/Starserver/NetAdminServer.cpp b/Starserver/NetAdminServer.cpp
new file mode 100644
index 0000000..7e82801
--- /dev/null
+++ b/Starserver/NetAdminServer.cpp
@@ -0,0 +1,784 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ HTTP Servlet Engine for Multiplayer Admin
+*/
+
+
+#include "NetAdminServer.h"
+#include "NetLobbyServer.h"
+#include "NetServerConfig.h"
+#include "NetClientConfig.h"
+#include "NetAdminChat.h"
+#include "NetUser.h"
+#include "NetChat.h"
+
+#include "HttpServlet.h"
+#include "NetLayer.h"
+
+#include "DataLoader.h"
+#include "FormatUtil.h"
+#include "MachineInfo.h"
+#include "VersionInfo.h"
+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+
+class NetAdminLogin : public NetAdminServlet
+{
+public:
+ NetAdminLogin() { }
+ virtual ~NetAdminLogin() { }
+
+ virtual bool DoGet(HttpRequest& request, HttpResponse& response) {
+ NetServerConfig* config = NetServerConfig::GetInstance();
+
+ Text admin_name = "system";
+ Text admin_pass = "manager";
+
+ if (config) {
+ admin_name = config->GetAdminName();
+ admin_pass = config->GetAdminPass();
+ }
+
+ Text name = request.GetParam("user");
+ Text pass = request.GetParam("pass");
+
+ Sleep(500);
+
+ if (CheckUser(request, response)) {
+ response.SetStatus(HttpResponse::SC_TEMPORARY_REDIRECT);
+ response.SetHeader("MIME-Version", "1.0");
+ response.SetHeader("Content-Type", "text/html");
+ response.SetHeader("Cache-Control", "no-cache");
+ response.SetHeader("Expires", "-1");
+ response.SetHeader("Location", "/home");
+
+ response.SetContent(GetHead("Login") +
+ "<body><br>You are already logged in.<br>" +
+ GetBodyClose());
+ }
+
+ else if (name == admin_name && pass == admin_pass) {
+ user = new NetUser(name);
+ user->SetAddress(request.GetClientAddr());
+
+ if (session)
+ user->SetSessionID(session->GetID());
+
+ admin->AddUser(user);
+
+ response.SetStatus(HttpResponse::SC_TEMPORARY_REDIRECT);
+ response.SetHeader("MIME-Version", "1.0");
+ response.SetHeader("Content-Type", "text/html");
+ response.SetHeader("Cache-Control", "no-cache");
+ response.SetHeader("Expires", "-1");
+ response.SetHeader("Location", "/home");
+
+ response.SetContent(GetHead("Login") +
+ "<body><br>You have successfully logged in.<br>" +
+ GetBodyClose());
+ }
+
+ else {
+ response.SetStatus(HttpResponse::SC_OK);
+ response.SetHeader("MIME-Version", "1.0");
+ response.SetHeader("Content-Type", "text/html");
+ response.SetHeader("Cache-Control", "no-cache");
+ response.SetHeader("Expires", "-1");
+
+ response.SetContent(GetHead("Login") +
+ GetTitleBar(0, "onLoad=\"self.focus();document.loginForm.user.focus();\"") +
+ GetContent() +
+ GetBodyClose());
+ }
+
+ return true;
+ }
+
+ virtual Text GetContent() { Text content =
+ " <table border=\"0\" cellspacing=\"0\" cellpadding=\"4\" align=\"left\" width =\"100%\">\n\
+ <tr>\n\
+ <td width=\"100\">&nbsp;&nbsp;</td>\n\
+ <td valign=\"top\" align=\"left\" width=\"400\"><br><br>\n\
+ <span class=\"subhead\">Welcome to the Starshatter Server!</span><br><br>\n\
+ <span class=\"std\">Login to access the server <b>";
+
+ NetServerConfig* config = NetServerConfig::GetInstance();
+ if (config)
+ content += config->Name();
+ else
+ content += "server";
+
+ content += "</b></span><br>\n\
+ <form name=\"loginForm\" method=\"get\" action=\"/login\">\n\
+ <table border=\"0\" cellspacing=\"0\" cellpadding=\"4\" width=\"100\">\n\
+ <tr>\n\
+ <td align=\"left\" valign=\"middle\" width=\"80\"><span class=\"std\">Username:</span></td>\n\
+ <td align=\"left\" valign=\"middle\"><input type=\"text\" name=\"user\" size=\"25\"></td>\n\
+ </tr>\n\
+ <tr>\n\
+ <td align=\"left\" valign=\"middle\" width=\"80\"><span class=\"std\">Password:</span></td>\n\
+ <td align=\"left\" valign=\"middle\"><input type=\"password\" name=\"pass\" size=\"25\"></td>\n\
+ </tr>\n\
+ <tr>\n\
+ <td>&nbsp;</td>\n\
+ <td align=\"right\"><input type=\"submit\" value=\"Login\"></td>\n\
+ </tr>\n\
+ </table>\n\
+ </form>\n\
+ <td>&nbsp;</td>\n\
+ </tr>\n\
+</table>\n";
+
+ return content;
+ }
+};
+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+
+class NetAdminFile : public NetAdminServlet
+{
+public:
+ NetAdminFile() { }
+ virtual ~NetAdminFile() { }
+
+ virtual bool DoGet(HttpRequest& request, HttpResponse& response) {
+ if (!CheckUser(request, response))
+ return true;
+
+ Text content;
+ Text path = request.GetParam("path");
+ Text name = request.GetParam("name");
+
+ if (name.length()) {
+ BYTE* buffer = 0;
+ DataLoader* loader = DataLoader::GetLoader();
+
+ if (loader) {
+ bool use_file_system = loader->IsFileSystemEnabled();
+
+ loader->UseFileSystem(true);
+ loader->SetDataPath(path);
+ int len = loader->LoadBuffer(name, buffer);
+
+ if (len) {
+ content = Text((const char*) buffer, len);
+ }
+
+ loader->ReleaseBuffer(buffer);
+ loader->SetDataPath(0);
+ loader->UseFileSystem(use_file_system);
+ }
+ }
+
+ response.SetStatus(HttpResponse::SC_OK);
+ response.AddHeader("MIME-Version", "1.0");
+ response.AddHeader("Cache-Control", "no-cache");
+ response.AddHeader("Expires", "-1");
+ response.AddHeader("Content-Type", "text/plain");
+ response.SetContent(content);
+
+ return true;
+ }
+};
+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+
+class NetAdminUserList : public NetAdminServlet
+{
+public:
+ NetAdminUserList() { }
+ virtual ~NetAdminUserList() { }
+
+ virtual bool DoGet(HttpRequest& request, HttpResponse& response) {
+ if (CheckUser(request, response)) {
+ response.SetStatus(HttpResponse::SC_OK);
+ response.SetHeader("MIME-Version", "1.0");
+ response.SetHeader("Content-Type", "text/html");
+ response.SetHeader("Cache-Control", "no-cache");
+ response.SetHeader("Expires", "-1");
+
+ response.SetContent(GetHead("User List") +
+ GetTitleBar() +
+ GetContent() +
+ GetBodyClose());
+ }
+
+ return true;
+ }
+
+ virtual Text GetContent() {
+ Text content =
+ "<script LANGUAGE=\"JavaScript\">\n\
+<!--\n\
+function doConfirm() {\n\
+return confirm(\"Are you sure you want to ban this player?\");\n\
+}\n\
+// -->\n\
+</script>\n\
+<div class=\"content\">\n\
+<table border=\"0\" width=\"95%\">\n\
+ <tr class=\"heading\">\n\
+ <td nowrap valign=\"middle\" align=\"left\">\n\
+ <span class=\"heading\">&nbsp;User List</span>\n\
+ </td>\n\
+ </tr>\n\
+</table>\n\n";
+
+ content +=
+ " <table border=\"0\" width=\"95%\" class=\"std\">\n\
+ <tr>\n\
+ <td nowrap width=\"1%\">&nbsp;</td>\n\
+ <td nowrap width=\"20%\" valign=\"middle\" align=\"left\"><b>Name</b></td>\n\
+ <td nowrap width=\"10%\" valign=\"middle\" align=\"left\"><b>Address</b></td>\n\
+ <td nowrap width=\"10%\" valign=\"middle\" align=\"center\"><b>Is Host</b></td>\n\
+ <td nowrap width=\"20%\" valign=\"middle\" align=\"left\"><b>Squadron</b></td>\n\
+ <td nowrap width=\"20%\" valign=\"middle\" align=\"center\"><b>Stats</b></td>\n\
+ <td nowrap width=\"19%\" valign=\"middle\" align=\"center\"><b>Ban</b></td>\n\
+ <td></td>\n\
+</tr>\n";
+
+ NetLobbyServer* lobby = NetLobbyServer::GetInstance();
+
+ if (lobby) {
+ ListIter<NetUser> u_iter = lobby->GetUsers();
+ while (++u_iter) {
+ NetUser* u = u_iter.value();
+ NetAddr a = u->GetAddress();
+
+ char addr_dotted[32];
+ char addr_hex[16];
+ char user_stats[16];
+
+ sprintf_s(addr_dotted, "%d.%d.%d.%d", a.B1(), a.B2(), a.B3(), a.B4());
+ sprintf_s(addr_hex, "%08x", a.IPAddr());
+ sprintf_s(user_stats, "%d / %d / %d", u->Missions(), u->Kills(), u->Losses());
+
+ content += "<tr>\n<td nowrap width=\"1%\">&nbsp;</td>\n\
+ <td nowrap valign=\"middle\" align=\"left\">";
+ content += u->Name();
+ content += "</td><td nowrap valign=\"middle\" align=\"left\">";
+ content += addr_dotted;
+ content += "</td><td nowrap valign=\"middle\" align=\"center\">";
+ content += u->IsHost() ? "*" : "&nbsp;";
+ content += "</td><td nowrap valign=\"middle\" align=\"left\">";
+ content += u->Squadron();
+ content += "</td><td nowrap valign=\"middle\" align=\"center\">";
+ content += user_stats;
+ content += "</td><td nowrap valign=\"middle\" align=\"center\">";
+ content += "<a onclick=\"return doConfirm()\" href=\"/ban?name=";
+ content += HttpRequest::EncodeParam(u->Name());
+ content += "&addr=";
+ content += addr_hex;
+ content += "\">BAN</a></td></tr>\n";
+ }
+ }
+
+ content += " </table>\n\n";
+
+ content += "</div>\n\n";
+ content += GetCopyright();
+ return content;
+ }
+};
+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+
+class NetAdminBanUser : public NetAdminServlet
+{
+public:
+ NetAdminBanUser() { }
+ virtual ~NetAdminBanUser() { }
+
+ virtual bool DoGet(HttpRequest& request, HttpResponse& response) {
+ if (CheckUser(request, response)) {
+ Text name = request.GetParam("name");
+ bool completed = false;
+
+ NetLobbyServer* lobby = NetLobbyServer::GetInstance();
+
+ if (lobby) {
+ ListIter<NetUser> u_iter = lobby->GetUsers();
+ while (++u_iter && !completed) {
+ NetUser* u = u_iter.value();
+
+ if (u->Name() == name) {
+ NetLobbyServer* nls = NetLobbyServer::GetInstance();
+
+ if (nls) {
+ nls->BanUser(u);
+ completed = true;
+ }
+ }
+ }
+ }
+
+ response.SetStatus(HttpResponse::SC_TEMPORARY_REDIRECT);
+ response.SetHeader("MIME-Version", "1.0");
+ response.SetHeader("Content-Type", "text/html");
+ response.SetHeader("Cache-Control", "no-cache");
+ response.SetHeader("Expires", "-1");
+ response.SetHeader("Location", "/users");
+
+ response.SetContent(GetHead("User List") +
+ GetTitleBar() +
+ "<div class=\"content\">User Banned.<br></div>" +
+ GetBodyClose());
+ }
+
+ return true;
+ }
+};
+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+
+static NetAdminServer* net_Admin_server = 0;
+
+NetAdminServer*
+NetAdminServer::GetInstance(WORD port)
+{
+ if (!net_Admin_server && port > 0)
+ net_Admin_server = new NetAdminServer(port);
+
+ return net_Admin_server;
+}
+
+NetAdminServer::NetAdminServer(WORD port)
+: HttpServletExec(port)
+{
+ http_server_name = Text("Starshatter NetAdminServer ") + versionInfo;
+}
+
+NetAdminServer::~NetAdminServer()
+{
+ if (net_Admin_server == this)
+ net_Admin_server = 0;
+}
+
+// +--------------------------------------------------------------------+
+
+HttpServlet*
+NetAdminServer::GetServlet(HttpRequest& request)
+{
+ Text path = request.URI();
+ path.setSensitive(false);
+
+ if (path.indexOf("/login") == 0)
+ return new NetAdminLogin;
+
+ if (path.indexOf("/chat") == 0)
+ return new NetAdminChat;
+
+ if (path.indexOf("/file") == 0)
+ return new NetAdminFile;
+
+ if (path.indexOf("/user") == 0)
+ return new NetAdminUserList;
+
+ if (path.indexOf("/ban") == 0)
+ return new NetAdminBanUser;
+
+ return new NetAdminServlet;
+}
+
+// +-------------------------------------------------------------------+
+
+void
+NetAdminServer::AddChat(NetUser* user, const char* msg)
+{
+ if (user && msg && *msg) {
+ NetLobbyServer* lobby = NetLobbyServer::GetInstance();
+
+ if (lobby)
+ lobby->AddChat(user, msg);
+ }
+}
+
+ListIter<NetChatEntry>
+NetAdminServer::GetChat()
+{
+ NetLobbyServer* lobby = NetLobbyServer::GetInstance();
+
+ if (lobby)
+ return lobby->GetChat();
+
+ static List<NetChatEntry> idle_chatter;
+ return idle_chatter;
+}
+
+// +-------------------------------------------------------------------+
+
+void
+NetAdminServer::AddUser(NetUser* user)
+{
+ if (user && !admin_users.contains(user))
+ admin_users.append(user);
+}
+
+void
+NetAdminServer::DelUser(NetUser* user)
+{
+ if (user) {
+ admin_users.remove(user);
+ delete user;
+ }
+}
+
+int
+NetAdminServer::NumUsers()
+{
+ return admin_users.size();
+}
+
+
+List<NetUser>&
+NetAdminServer::GetUsers()
+{
+ return admin_users;
+}
+
+bool
+NetAdminServer::HasHost()
+{
+ bool result = false;
+
+ NetLobbyServer* lobby = NetLobbyServer::GetInstance();
+
+ if (lobby)
+ result = lobby->HasHost();
+
+ return result;
+}
+
+NetUser*
+NetAdminServer::FindUserBySession(Text id)
+{
+ ListIter<NetUser> iter = admin_users;
+ while (++iter) {
+ NetUser* u = iter.value();
+ if (u->GetSessionID() == id)
+ return u;
+ }
+
+ return 0;
+}
+
+void
+NetAdminServer::DoSyncedCheck()
+{
+ ListIter<NetUser> iter = admin_users;
+ while (++iter) {
+ NetUser* u = iter.value();
+
+ bool found = false;
+
+ ListIter<HttpSession> s_iter = sessions;
+ while (++s_iter && !found) {
+ HttpSession* s = s_iter.value();
+
+ if (s->GetID() == u->GetSessionID())
+ found = true;
+ }
+
+ if (!found)
+ delete iter.removeItem();
+ }
+}
+
+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+// +-------------------------------------------------------------------+
+
+NetAdminServlet::NetAdminServlet()
+{
+ admin = NetAdminServer::GetInstance();
+ user = 0;
+}
+
+// +-------------------------------------------------------------------+
+
+bool
+NetAdminServlet::DoGet(HttpRequest& request, HttpResponse& response)
+{
+ if (CheckUser(request, response)) {
+
+ if (request.URI() == "/home")
+ response.SetStatus(HttpResponse::SC_OK);
+ else
+ response.SetStatus(HttpResponse::SC_TEMPORARY_REDIRECT);
+
+ response.SetHeader("MIME-Version", "1.0");
+ response.SetHeader("Content-Type", "text/html");
+ response.SetHeader("Cache-Control", "no-cache");
+ response.SetHeader("Expires", "-1");
+ response.SetHeader("Location", "/home");
+
+ response.SetContent(GetHead() +
+ GetTitleBar(GetStatLine()) +
+ GetContent() +
+ GetBodyClose());
+ }
+
+ return true;
+}
+
+// +-------------------------------------------------------------------+
+
+bool
+NetAdminServlet::CheckUser(HttpRequest& request, HttpResponse& response)
+{
+ if (!user) {
+ if (session)
+ user = admin->FindUserBySession(session->GetID());
+
+ if (!user) {
+ response.SetStatus(HttpResponse::SC_TEMPORARY_REDIRECT);
+ response.SetHeader("MIME-Version", "1.0");
+ response.SetHeader("Content-Type", "text/plain");
+ response.SetHeader("Cache-Control", "no-cache");
+ response.SetHeader("Expires", "-1");
+ response.SetHeader("Location", "/login");
+ response.SetContent("You are not logged in.");
+ }
+ }
+
+ return user != 0;
+}
+
+// +-------------------------------------------------------------------+
+
+Text
+NetAdminServlet::GetCSS()
+{
+ return
+
+ "body { font-family:arial,helvetica,sans-serif; color:black; background-color:white }\n\
+a:link { text-decoration:none; font-weight:normal; font-size:10pt; color:black }\n\
+a:visited { text-decoration:none; font-weight:normal; font-size:10pt; color:black }\n\
+a:hover { text-decoration:underline; font-weight:normal; font-size:10pt; color:black }\n\
+.std { font-size:10pt }\n\
+.tiny { font-size:8pt }\n\
+.heading { font-size:14pt; font-weight:bold; background-color:#99BBEE }\n\
+.subhead { font-size:11pt; font-weight:bold }\n\
+.status { font-size:10pt; color:white }\n\
+.content { padding-right: 4pt; padding-left: 4pt; padding-bottom: 4pt; padding-top: 4pt; margin: 4pt; }\n\
+.copy { font-size:8pt; }\n\
+.top-bar { color: white; background-color: #336699 }\n\
+.top-line { color: yellow; background-color: black }\n\
+.topbarbig { line-height:24px; color:white; font-size:18px; font-weight:bold; }\n\
+.topbarsmall { line-height:18px; color:white; font-size:14px; }\n";
+}
+
+Text
+NetAdminServlet::GetHead(const char* title)
+{
+ Text head = "<html>\n<head>\n<title>Starshatter Server";
+
+ if (title && *title) {
+ head += " - ";
+ head += title;
+ }
+
+ head += "</title>\n<style type=\"text/css\" media=\"screen\">\n";
+ head += GetCSS();
+ head += "</style>\n</head>\n";
+
+ return head;
+}
+
+Text
+NetAdminServlet::GetBody()
+{
+ return GetTitleBar(GetStatLine()) +
+ GetContent() +
+ GetBodyClose();
+}
+
+Text
+NetAdminServlet::GetTitleBar(const char* statline, const char* onload)
+{
+ Text bar = "<body ";
+
+ if (onload && *onload)
+ bar += onload;
+
+ bar += " leftmargin=\"0\" topmargin=\"0\" marginwidth=\"0\" marginheight=\"0\">\n\
+<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\" class=\"top-bar\">\n\
+ <tr height=\"50\">\n\
+ <td>&nbsp;</td>\n\
+ <td valign=\"middle\" align=\"left\">\n\
+ <span class=\"topbarsmall\">Administration Console</span><br>\n";
+
+ if (statline) {
+ bar += "<a href=\"/home\">";
+ }
+
+ bar += "<span class=\"topbarbig\">Starshatter Server ";
+ bar += versionInfo;
+ bar += "</span>";
+
+ if (statline) {
+ bar += "</a>";
+ }
+
+ bar += "\n\
+ </td>\n\
+ </tr>\n\
+ <tr class=\"top-line\">\n\
+ <td colspan=\"2\">";
+
+ if (statline && *statline)
+ bar += statline;
+ else
+ bar += "&nbsp;";
+
+ bar += "</td>\n\
+ </tr>\n\
+</table>\n\n";
+
+ return bar;
+}
+
+Text
+NetAdminServlet::GetStatLine()
+{
+ NetServerConfig* config = NetServerConfig::GetInstance();
+
+ Text line =
+ " <table width=\"100%\" cellspacing=\"0\" cellpadding=\"2\" border=\"0\">\n\
+ <tr>\n\
+ <td nowrap width=\"33%\" class=\"top-line\" align=\"left\">\n\
+ <span class=\"status\">&nbsp;&nbsp;Connected to <b>";
+
+ char buffer[256];
+ sprintf_s(buffer, "%s:%d", config->Name().data(), config->GetAdminPort());
+ line += buffer;
+
+ line += "</b></span>\n\
+ </td>\n\
+ <td nowrap width=\"34%\" class=\"top-line\" align=\"center\">\n\
+ <span class=\"status\">Server Mode: <b>";
+
+ NetLobbyServer* lobby = NetLobbyServer::GetInstance();
+ if (lobby) {
+ switch (lobby->GetStatus()) {
+ default:
+ case NetServerInfo::OFFLINE: line += "Offline"; break;
+ case NetServerInfo::LOBBY: line += "Lobby"; break;
+ case NetServerInfo::BRIEFING: line += "Briefing"; break;
+ case NetServerInfo::ACTIVE: line += "Active"; break;
+ case NetServerInfo::DEBRIEFING: line += "Debriefing"; break;
+ case NetServerInfo::PERSISTENT: line += "PERSISTENT"; break;
+ }
+ }
+ else {
+ line += "Unknown";
+ }
+
+ line += "</b></span>\n\
+ </td>\n\
+ <td nowrap width=\"33%\" class=\"top-line\" align=\"right\">\n\
+ <span class=\"status\">";
+
+ line += FormatTimeString();
+
+ line += "&nbsp;&nbsp;</span>\n\
+ </td>\n\
+ </tr>\n\
+ </table>\n";
+
+ return line;
+}
+
+Text
+NetAdminServlet::GetContent()
+{
+ Text content =
+ "<script LANGUAGE=\"JavaScript\">\n\
+<!--\n\
+function doConfirm() {\n\
+return confirm(\"Are you sure you want to do this?\");\n\
+}\n\
+// -->\n\
+</script>\n\
+<div class=\"content\">\n\
+<table border=\"0\" width=\"95%\">\n\
+ <tr class=\"heading\">\n\
+ <td nowrap valign=\"middle\" align=\"left\">\n\
+ <span class=\"heading\">&nbsp;Game Admin Functions</span>\n\
+ </td>\n\
+ </tr>\n\
+</table>\n\n\
+<table border=\"0\" width=\"95%\">\n\
+ <tr>\n\
+ <td nowrap width=\"1%\">&nbsp;</td>\n\
+ <td nowrap width=\"33%\" valign=\"middle\" align=\"left\">\n\
+ <a href=\"/chat\">Lobby Chat</a>\n\
+ </td>\n\
+ <td nowrap width=\"33%\" valign=\"middle\" align=\"left\">\n\
+ <a href=\"/home\">Mission List</a>\n\
+ </td>\n\
+ <td></td>\n\
+ </tr>\n\
+ <tr>\n\
+ <td nowrap width=\"1%\">&nbsp;</td>\n\
+ <td nowrap width=\"33%\" valign=\"middle\" align=\"left\">\n\
+ <a href=\"/file?name=errlog.txt\">View Error Log</a>\n\
+ </td>\n\
+ <td nowrap width=\"33%\" valign=\"middle\" align=\"left\">\n\
+ <a href=\"/users\">Player List</a>\n\
+ </td>\n\
+ <td></td>\n\
+ </tr>\n\
+ <tr>\n\
+ <td nowrap width=\"1%\">&nbsp;</td>\n\
+ <td nowrap width=\"33%\" valign=\"middle\" align=\"left\">\n\
+ <a href=\"/file?name=serverlog.txt\">View Server Log</a>\n\
+ </td>\n\
+ <td nowrap width=\"33%\" valign=\"middle\" align=\"left\">\n\
+ <a href=\"/home\">Ban List</a>\n\
+ </td>\n\
+ <td></td>\n\
+ </tr>\n\
+ <tr>\n\
+ <td nowrap width=\"1%\">&nbsp;</td>\n\
+ <td nowrap width=\"33%\" valign=\"middle\" align=\"left\"></td>\n\
+ <td nowrap width=\"33%\" valign=\"middle\" align=\"left\"></td>\n\
+ <td></td>\n\
+</tr>\n\
+</table>\n\n";
+
+ content += "</div>\n\n";
+ content += GetCopyright();
+ return content;
+}
+
+Text
+NetAdminServlet::GetBodyClose()
+{
+ return "\n\n</body>\n</html>\n";
+}
+
+Text
+NetAdminServlet::GetCopyright()
+{
+ return "<br><span class=\"copy\">&nbsp;&nbsp;&nbsp;&nbsp;Copyright &copy; 1997-2004 Destroyer Studios. All rights reserved.</span><br>";
+}
diff --git a/Starserver/NetAdminServer.h b/Starserver/NetAdminServer.h
new file mode 100644
index 0000000..804d482
--- /dev/null
+++ b/Starserver/NetAdminServer.h
@@ -0,0 +1,90 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ HTTP Servlet Engine for Multiplayer Admin
+*/
+
+
+#ifndef NetAdminServer_h
+#define NetAdminServer_h
+
+#include "HttpServletExec.h"
+#include "HttpServlet.h"
+
+// +-------------------------------------------------------------------+
+
+class Mission;
+class MissionElement;
+class NetChatEntry;
+class NetUser;
+
+// +-------------------------------------------------------------------+
+
+class NetAdminServer : public HttpServletExec
+{
+public:
+ virtual ~NetAdminServer();
+
+ int operator == (const NetAdminServer& s) const { return this == &s; }
+
+ virtual HttpServlet* GetServlet(HttpRequest& request);
+
+ virtual void AddUser(NetUser* user);
+ virtual void DelUser(NetUser* user);
+ virtual int NumUsers();
+ virtual bool HasHost();
+ virtual List<NetUser>& GetUsers();
+
+ virtual NetUser* FindUserBySession(Text id);
+
+ virtual void AddChat(NetUser* user, const char* msg);
+ ListIter<NetChatEntry> GetChat();
+ DWORD GetStartTime() const { return start_time; }
+
+ virtual void GameOn() { }
+ virtual void GameOff() { }
+
+ // singleton locator:
+ static NetAdminServer* GetInstance(WORD port=0);
+
+protected:
+ NetAdminServer(WORD port);
+ virtual void DoSyncedCheck();
+
+ DWORD start_time;
+ List<NetUser> admin_users;
+};
+
+// +-------------------------------------------------------------------+
+
+class NetAdminServlet : public HttpServlet
+{
+public:
+ NetAdminServlet();
+ virtual ~NetAdminServlet() { }
+
+ virtual bool DoGet(HttpRequest& request, HttpResponse& response);
+ virtual bool CheckUser(HttpRequest& request, HttpResponse& response);
+
+ virtual Text GetCSS();
+ virtual Text GetHead(const char* title=0);
+ virtual Text GetBody();
+ virtual Text GetTitleBar(const char* statline=0, const char* onload=0);
+ virtual Text GetStatLine();
+ virtual Text GetCopyright();
+ virtual Text GetContent();
+ virtual Text GetBodyClose();
+
+protected:
+ NetAdminServer* admin;
+ NetUser* user;
+};
+
+#endif // NetAdminServer_h \ No newline at end of file
diff --git a/Starserver/NetFileServlet.cpp b/Starserver/NetFileServlet.cpp
new file mode 100644
index 0000000..6b23d9d
--- /dev/null
+++ b/Starserver/NetFileServlet.cpp
@@ -0,0 +1,117 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ HTTP Servlet for File Transfer
+*/
+
+
+#include "NetFileServlet.h"
+#include "NetAdminServer.h"
+#include "NetLayer.h"
+
+#include "DataLoader.h"
+
+// +-------------------------------------------------------------------+
+
+bool
+NetFileServlet::DoGet(HttpRequest& request, HttpResponse& response)
+{
+ if (!CheckUser(request, response))
+ return true;
+
+ Text content;
+ Text path = request.GetParam("path");
+ Text name = request.GetParam("name");
+
+ if (name.length()) {
+ BYTE* buffer = 0;
+ DataLoader* loader = DataLoader::GetLoader();
+
+ if (loader) {
+ loader->SetDataPath(path);
+ int len = loader->LoadBuffer(name, buffer);
+
+ if (len) {
+ content = Text((const char*) buffer, len);
+ }
+
+ loader->ReleaseBuffer(buffer);
+ loader->SetDataPath(0);
+ }
+ }
+
+ response.SetStatus(HttpResponse::SC_OK);
+ response.AddHeader("MIME-Version", "1.0");
+ response.AddHeader("Cache-Control", "no-cache");
+ response.AddHeader("Expires", "-1");
+ response.AddHeader("Content-Type", "text/plain");
+ response.SetContent(content);
+
+ return true;
+}
+
+// +-------------------------------------------------------------------+
+
+bool
+NetWebServlet::DoGet(HttpRequest& request, HttpResponse& response)
+{
+ Text content;
+ Text name = request.URI();
+ bool found = false;
+
+ if (name.length() > 4) {
+ char filename[256];
+ strcpy_s(filename, name.data() + 1); // skip leading '/'
+
+ FILE* f;
+ ::fopen_s(&f, filename, "rb");
+
+ if (f) {
+ ::fseek(f, 0, SEEK_END);
+ int len = ftell(f);
+ ::fseek(f, 0, SEEK_SET);
+
+ BYTE* buf = new BYTE[len];
+
+ ::fread(buf, len, 1, f);
+ ::fclose(f);
+
+ content = Text((const char*) buf, len);
+ delete [] buf;
+
+ found = true;
+ ::Print("weblog: 200 OK %s %d bytes\n", name.data(), len);
+ }
+ else {
+ ::Print("weblog: 404 Not Found %s\n", name.data());
+ }
+ }
+
+ if (found) {
+ Text content_type = "text/plain";
+
+ if (name.contains(".gif"))
+ content_type = "image/gif";
+ else if (name.contains(".jpg"))
+ content_type = "image/jpeg";
+ else if (name.contains(".htm"))
+ content_type = "text/html";
+
+ response.SetStatus(HttpResponse::SC_OK);
+ response.AddHeader("MIME-Version", "1.0");
+ response.AddHeader("Content-Type", content_type);
+ response.SetContent(content);
+ }
+ else {
+ response.SetStatus(HttpResponse::SC_NOT_FOUND);
+ }
+
+ return true;
+}
diff --git a/Starserver/NetFileServlet.h b/Starserver/NetFileServlet.h
new file mode 100644
index 0000000..7de3443
--- /dev/null
+++ b/Starserver/NetFileServlet.h
@@ -0,0 +1,49 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ HTTP Servlet for File Transfer
+*/
+
+
+#ifndef NetFileServlet_h
+#define NetFileServlet_h
+
+#include "Types.h"
+#include "NetAdminServer.h"
+#include "NetUser.h"
+
+// +-------------------------------------------------------------------+
+
+class Campaign;
+class File;
+
+// +-------------------------------------------------------------------+
+
+class NetFileServlet : public NetAdminServlet
+{
+public:
+ NetFileServlet() { }
+ virtual ~NetFileServlet() { }
+
+ virtual bool DoGet(HttpRequest& request, HttpResponse& response);
+};
+
+// +-------------------------------------------------------------------+
+
+class NetWebServlet : public NetAdminServlet
+{
+public:
+ NetWebServlet() { }
+ virtual ~NetWebServlet() { }
+
+ virtual bool DoGet(HttpRequest& request, HttpResponse& response);
+};
+
+#endif // NetFileServlet_h \ No newline at end of file
diff --git a/Starserver/StarServer.cpp b/Starserver/StarServer.cpp
new file mode 100644
index 0000000..8d76f38
--- /dev/null
+++ b/Starserver/StarServer.cpp
@@ -0,0 +1,309 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+
+ AUTHOR: John DiCamillo
+
+*/
+
+#include "StarServer.h"
+
+#include <stdlib.h>
+
+#include <chrono>
+#include <iostream>
+#include <thread>
+
+#include "Campaign.h"
+#include "Clock.h"
+#include "CombatRoster.h"
+#include "DataLoader.h"
+#include "Drive.h"
+#include "Explosion.h"
+#include "FlightDeck.h"
+#include "Galaxy.h"
+#include "Game.h"
+#include "ModConfig.h"
+#include "NetAdminServer.h"
+#include "NetGame.cpp"
+#include "NetLobby.h"
+#include "NetLobbyServer.h"
+#include "NetServerConfig.h"
+#include "RadioTraffic.h"
+#include "Random.h"
+#include "Ship.h"
+#include "Shot.h"
+#include "Sim.h"
+#include "SystemDesign.h"
+#include "Types.h"
+#include "Utils.h"
+#include "WeaponDesign.h"
+
+
+StarServer* StarServer::instance {nullptr};
+
+
+StarServer*
+StarServer::GetInstance()
+{
+ return instance;
+}
+
+
+StarServer::StarServer() :
+ world {nullptr},
+ current_mission {nullptr},
+ admin_server {nullptr},
+ lobby_server {nullptr}
+{
+ if (instance != nullptr)
+ throw "StarServer may have only one instance";
+ instance = this;
+
+ DataLoader::Initialize();
+ auto loader = DataLoader::GetLoader();
+ if (!loader) throw "Could not get DataLoader instance";
+
+ int loadstat = loader->EnableDatafile("shatter.dat");
+ if (loadstat != DataLoader::DATAFILE_OK) {
+ if (loadstat == DataLoader::DATAFILE_INVALID) {
+ throw "The file 'shatter.dat' appears to have been damaged.";
+ }
+ else {
+ throw "Starshatter cannot open the file 'shatter.dat'. Please check current directory.";
+ }
+ }
+
+ if (loader->FindFile("start.dat"))
+ loader->EnableDatafile("start.dat");
+
+ loader->EnableMedia(false);
+}
+
+
+StarServer::~StarServer()
+{
+ delete admin_server;
+ delete lobby_server;
+
+ admin_server = nullptr;
+ lobby_server = nullptr;
+
+ // delete all the ships and stuff
+ // BEFORE getting rid of the system
+ // and weapons catalogs!
+ if (world) delete world;
+ world = nullptr;
+
+ Drive::Close();
+ Explosion::Close();
+ FlightDeck::Close();
+ Campaign::Close();
+ CombatRoster::Close();
+ Galaxy::Close();
+ RadioTraffic::Close();
+ Ship::Close();
+ WeaponDesign::Close();
+ SystemDesign::Close();
+ DataLoader::Close();
+ NetServerConfig::Close();
+ ModConfig::Close();
+
+ if (instance == this)
+ instance = nullptr;
+}
+
+
+bool
+StarServer::Init(HINSTANCE hi, HINSTANCE hpi, LPSTR cmdline, int nCmdShow)
+{
+ if (auto loader = DataLoader::GetLoader())
+ loader->UseFileSystem(false);
+ return Game::Init(hi, hpi, cmdline, nCmdShow);
+}
+
+
+bool
+StarServer::InitGame()
+{
+ if (!Game::InitGame())
+ return false;
+
+ RandomInit();
+ ModConfig::Initialize();
+ NetServerConfig::Initialize();
+ SystemDesign::Initialize("sys.def");
+ WeaponDesign::Initialize("wep.def");
+ Ship::Initialize();
+ Galaxy::Initialize();
+ CombatRoster::Initialize();
+ Campaign::Initialize();
+
+ Drive::Initialize();
+ Explosion::Initialize();
+ FlightDeck::Initialize();
+ Ship::Initialize();
+ Shot::Initialize();
+ RadioTraffic::Initialize();
+
+ NetServerConfig* server_config = NetServerConfig::GetInstance();
+ if (!server_config)
+ return false;
+
+ ::Print("\n\n\nStarshatter Server Init\n");
+ ::Print("-----------------------\n");
+ ::Print("Server Name: %s\n", (const char*) server_config->Name());
+ ::Print("Server Type: %d\n", server_config->GetGameType());
+
+ if (server_config->GetMission().length() > 0)
+ ::Print("Server Mission: %s\n", (const char*) server_config->GetMission());
+
+ ::Print("Lobby Server Port: %d\n", server_config->GetLobbyPort());
+ ::Print("Admin Server Port: %d\n", server_config->GetAdminPort());
+ ::Print("-----------------------\n");
+
+ NetLobbyServer* nls = new NetLobbyServer;
+ NetAdminServer* nas = NetAdminServer::GetInstance(server_config->GetAdminPort());
+ nas->SetServerName(server_config->Name());
+
+ lobby_server = nls;
+ admin_server = nas;
+
+ std::cout << "Started server listening on port " << server_config->GetLobbyPort() << std::endl;
+
+ return true;
+}
+
+
+void
+StarServer::SetGameMode(int m)
+{
+ if (game_mode == m)
+ return;
+
+ if (m == LOAD_MODE) {
+ Print(" game_mode = LOAD_MODE\n");
+ paused = true;
+ }
+
+ else if (m == PLAY_MODE) {
+ Print(" game_mode = PLAY_MODE\n");
+
+ if (!world) {
+ CreateWorld();
+ InstantiateMission();
+ }
+
+ // stand alone server should wait for players to connect
+ // before unpausing the simulation...
+ Clock::GetInstance()->SetTimeCompression(1.0);
+ Pause(true);
+ }
+
+ else if (m == MENU_MODE) {
+ Print(" game_mode = MENU_MODE\n");
+ paused = true;
+
+ if (auto sim = dynamic_cast<Sim*>(world))
+ sim->UnloadMission();
+ }
+
+ game_mode = m;
+}
+
+
+void
+StarServer::CreateWorld()
+{
+ RadioTraffic::Initialize();
+
+ // create world
+ if (!world) {
+ world = new Sim(nullptr);
+ Print(" World Created.\n");
+ }
+}
+
+
+void
+StarServer::InstantiateMission()
+{
+ current_mission = nullptr;
+
+ if (Campaign::GetCampaign()) {
+ current_mission = Campaign::GetCampaign()->GetMission();
+ }
+
+ if (auto sim = dynamic_cast<Sim*>(world)) {
+ sim->UnloadMission();
+
+ if (current_mission) {
+ sim->LoadMission(current_mission);
+ sim->ExecMission();
+ sim->SetTestMode(false);
+
+ Print(" Mission Instantiated.\n");
+ std::cout << "Loaded mission: " << current_mission->Name() << std::endl;
+ }
+
+ else {
+ Print(" *** WARNING: StarServer::InstantiateMission() - no mission selected ***\n");
+ }
+ }
+}
+
+
+void
+StarServer::UpdateWorld()
+{
+ Galaxy* galaxy = Galaxy::GetInstance();
+ if (galaxy) galaxy->ExecFrame();
+
+ Campaign* campaign = Campaign::GetCampaign();
+ if (campaign) campaign->ExecFrame();
+
+ if (paused) {
+ if (world)
+ world->ExecFrame(0);
+ }
+
+ else {
+ Drive::StartFrame();
+
+ if (world)
+ world->ExecFrame(Clock::GetInstance()->Delta());
+ }
+}
+
+
+void
+StarServer::GameState()
+{
+ if (lobby_server) {
+ lobby_server->ExecFrame();
+
+ if (lobby_server->GetStatus() == NetServerInfo::PERSISTENT)
+ paused = NetGame::NumPlayers() < 1;
+ }
+
+ if (game_mode == MENU_MODE) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(30));
+ }
+ else if (game_mode == LOAD_MODE) {
+ CreateWorld();
+ InstantiateMission();
+
+ SetGameMode(PLAY_MODE);
+ }
+ else if (game_mode == PLAY_MODE) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+}
+
+
+bool
+StarServer::Server() const
+{
+ return true;
+}
diff --git a/Starserver/StarServer.h b/Starserver/StarServer.h
new file mode 100644
index 0000000..0bcab06
--- /dev/null
+++ b/Starserver/StarServer.h
@@ -0,0 +1,54 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+
+ AUTHOR: John DiCamillo
+
+*/
+
+#ifndef StarServer_h
+#define StarServer_h
+
+#include "Game.h"
+#include "NetLobbyServer.h"
+#include "NetServer.h"
+#include "Mission.h"
+#include "Types.h"
+#include "Universe.h"
+
+
+class StarServer : public Game
+{
+public:
+ static StarServer* GetInstance();
+
+ StarServer();
+ virtual ~StarServer();
+
+ virtual bool Init(HINSTANCE hi, HINSTANCE hpi, LPSTR cmdline, int nCmdShow);
+ virtual bool InitGame();
+
+ virtual void UpdateWorld();
+ virtual void GameState();
+
+ bool Server() const override;
+ void SetGameMode(int mode) override;
+
+ void CreateWorld();
+
+protected:
+ virtual void InstantiateMission();
+
+ Universe* world;
+ Mission* current_mission;
+
+ NetServer* admin_server;
+ NetLobbyServer* lobby_server;
+
+private:
+ static StarServer* instance;
+};
+
+
+#endif // StarServer_h