Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'Start Server' menu #23

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/base/tl/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class string_base : private ALLOCATOR
public:
string_base() { reset(); }
string_base(const char *other_str) { copy(other_str, str_length(other_str)); }
string_base(const char *other_str, int length) { copy(other_str, length); }
string_base(const char *other_str, int length) { copy(other_str, length); str[length] = 0; }
string_base(const string_base &other) { reset(); copy(other); }
~string_base() { free(); }

Expand Down
2 changes: 1 addition & 1 deletion src/base/vmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class vector2_base
union { T y,v; };

vector2_base() {}
vector2_base(float nx, float ny)
vector2_base(T nx, T ny)
{
x = nx;
y = ny;
Expand Down
12 changes: 11 additions & 1 deletion src/game/client/components/menus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,15 @@ int CMenus::RenderMenubar(CUIRect r)
NewPage = PAGE_FAVORITES;
}

Box.VSplitLeft(4.0f*5, 0, &Box);
Box.VSplitLeft(10.0f, 0, &Box);
Box.VSplitLeft(100.0f, &Button, &Box);
static int s_ServerButton=0;
if(DoButton_MenuTab(&s_ServerButton, Localize("Server"), m_ActivePage==PAGE_SERVER, &Button, CUI::CORNER_T))
{
NewPage = PAGE_SERVER;
}

Box.VSplitLeft(10.0f, 0, &Box);
Box.VSplitLeft(100.0f, &Button, &Box);
static int s_DemosButton=0;
if(DoButton_MenuTab(&s_DemosButton, Localize("Demos"), m_ActivePage==PAGE_DEMOS, &Button, CUI::CORNER_T))
Expand Down Expand Up @@ -840,6 +848,8 @@ int CMenus::Render()
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_LAN)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_SERVER)
ServerCreatorProcess(MainView);
else if(g_Config.m_UiPage == PAGE_DEMOS)
RenderDemoList(MainView);
else if(g_Config.m_UiPage == PAGE_FAVORITES)
Expand Down
5 changes: 5 additions & 0 deletions src/game/client/components/menus.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class CMenus : public CComponent
PAGE_INTERNET,
PAGE_LAN,
PAGE_FAVORITES,
PAGE_SERVER,
PAGE_DEMOS,
PAGE_SETTINGS,
PAGE_SYSTEM,
Expand Down Expand Up @@ -244,6 +245,10 @@ class CMenus : public CComponent
void RenderDemoPlayer(CUIRect MainView);
void RenderDemoList(CUIRect MainView);

// found in menus_server.cpp
void ServerCreatorInit();
void ServerCreatorProcess(CUIRect MainView);

// found in menus_ingame.cpp
void RenderGame(CUIRect MainView);
void RenderPlayers(CUIRect MainView);
Expand Down
238 changes: 238 additions & 0 deletions src/game/client/components/menus_server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@


#include <base/math.h>

#include <engine/demo.h>
#include <engine/keys.h>
#include <engine/graphics.h>
#include <engine/textrender.h>
#include <engine/storage.h>

#include <game/client/render.h>
#include <game/client/gameclient.h>
#include <game/localization.h>

#include <game/client/ui.h>

#include <game/generated/client_data.h>
#include <engine/shared/config.h>

#include "menus.h"

#if defined(WIN32)
#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <process.h>

static HANDLE serverProcess = -1;
#else
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#endif

static sorted_array<string> s_maplist;
static bool atexitRegistered = false;

static int MapScan(const char *pName, int IsDir, int DirType, void *pUser)
{
sorted_array<string> *maplist = (sorted_array<string> *)pUser;
int l = str_length(pName);
if(l < 4 || IsDir || str_comp(pName+l-4, ".map") != 0)
return 0;
maplist->add(string(pName, l - 4));
return 0;
}

void CMenus::ServerCreatorInit()
{
if( s_maplist.size() == 0 )
{
Storage()->ListDirectory(IStorage::TYPE_ALL, "maps", MapScan, &s_maplist);
}
}

static void StopServer()
{
#if defined(WIN32)
if( serverProcess != -1 )
TerminateProcess(serverProcess, 0);
serverProcess = -1;
#elif defined(__ANDROID__)
system("$SECURE_STORAGE_DIR/busybox killall ninslash_srv");
#else
system("killall ninslash_srv ninslash_srv_d");
#endif
}

static void StartServer(const char *type, const char *map, int bots)
{
char aBuf[4096];
str_format(aBuf, sizeof(aBuf),
"sv_port 8303\n"
"sv_name \"%s\"\n"
"sv_gametype %s\n"
"sv_map %s\n"
"sv_maprotation %s\n"
"sv_preferredteamsize %d\n"
"sv_scorelimit 0\n"
"sv_randomweapons 1\n"
"sv_vanillapickups 1\n"
"sv_weapondrops 1\n",
type, type, map, map, bots);

FILE *ff = fopen("server.cfg", "wb");
if( !ff )
return;
fwrite(aBuf, str_length(aBuf), 1, ff);
fclose(ff);

#if defined(WIN32)
serverProcess = (HANDLE) _spawnl(_P_NOWAIT, "ninslash_srv.exe", "ninslash_srv.exe", "-f", "server.cfg", NULL);
#elif defined(__ANDROID__)
system("$SECURE_STORAGE_DIR/ninslash_srv -f server.cfg >/dev/null 2>&1 &");
#else
system("./ninslash_srv_d -f server.cfg || ./ninslash_srv -f server.cfg &");
#endif

if( !atexitRegistered )
atexit(&StopServer);
atexitRegistered = true;
}

static bool ServerStatus()
{
#if defined(WIN32)
return serverProcess != -1;
#elif defined(__ANDROID__)
int status = system("$SECURE_STORAGE_DIR/busybox sh -c 'ps | grep ninslash_srv'");
return WEXITSTATUS(status) == 0;
#else
int status = system("ps | grep ninslash_srv");
return WEXITSTATUS(status) == 0;
#endif
}

void CMenus::ServerCreatorProcess(CUIRect MainView)
{
static int s_map = 0;
static int s_bots = 5;

static int64 LastUpdateTime = 0;
static bool ServerRunning = false;
static bool ServerStarting = false;

bool ServerStarted = false;

ServerCreatorInit();

// background
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 20.0f);
MainView.Margin(20.0f, &MainView);

MainView.HSplitTop(10, 0, &MainView);
CUIRect MsgBox = MainView;
UI()->DoLabelScaled(&MsgBox, Localize("Local server"), 20.0f, 0);

if (time_get() / time_freq() > LastUpdateTime + 2)
{
LastUpdateTime = time_get() / time_freq();
ServerRunning = ServerStatus();
if (ServerRunning && ServerStarting)
ServerStarted = true;
ServerStarting = false;
}

MainView.HSplitTop(30, 0, &MainView);
MsgBox = MainView;
UI()->DoLabelScaled(&MsgBox, ServerStarting ? Localize("Server is starting") :
ServerRunning ? Localize("Server is running") :
Localize("Server stopped"), 20.0f, 0);

MainView.HSplitTop(50, 0, &MainView);

CUIRect Button;

MainView.VSplitLeft(50, 0, &Button);
Button.h = 30;
Button.w = 200;
static int s_StopServerButton = 0;
if( ServerRunning && DoButton_Menu(&s_StopServerButton, Localize("Stop server"), 0, &Button))
{
StopServer();
LastUpdateTime = time_get() / time_freq() - 2;
}

static int s_StartDmServerButton = 0;
if( !ServerRunning && !ServerStarting && DoButton_Menu(&s_StartDmServerButton, Localize("Start DM server"), 0, &Button))
{
StartServer("dm", s_maplist[s_map].cstr(), s_bots);
LastUpdateTime = time_get() / time_freq(); // We do not actually ping the server, just wait 3 seconds
ServerStarting = true;
}

MainView.VSplitLeft(300, 0, &Button);
Button.h = 30;
Button.w = 200;
static int s_StartInfServerButton = 0;
if( !ServerRunning && !ServerStarting && DoButton_Menu(&s_StartInfServerButton, Localize("Start INF server"), 0, &Button) )
{
StartServer("inf", s_maplist[s_map].cstr(), s_bots);
LastUpdateTime = time_get() / time_freq(); // We do not actually ping the server, just wait 3 seconds
ServerStarting = true;
}

MainView.VSplitLeft(550, 0, &Button);
Button.h = 30;
Button.w = 200;
static int s_StartCtfServerButton = 0;
if( !ServerRunning && !ServerStarting && DoButton_Menu(&s_StartCtfServerButton, Localize("Start CTF server"), 0, &Button) )
{
StartServer("ctf", s_maplist[s_map].cstr(), s_bots);
LastUpdateTime = time_get() / time_freq(); // We do not actually ping the server, just wait 3 seconds
ServerStarting = true;
}

static int s_JoinServerButton = 0;
if(ServerStarted || (ServerRunning && DoButton_Menu(&s_JoinServerButton, Localize("Join server"), 0, &Button)))
{
strcpy(g_Config.m_UiServerAddress, "127.0.0.1");
Client()->Connect(g_Config.m_UiServerAddress);
}

MainView.HSplitTop(60, 0, &MainView);

MainView.VSplitLeft(50, 0, &MsgBox);
MsgBox.w = 100;

char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Bots"), s_bots);
UI()->DoLabelScaled(&MsgBox, aBuf, 20.0f, -1);

MainView.VSplitLeft(150, 0, &Button);
Button.h = 30;
Button.w = 500;

s_bots = (int)(DoScrollbarH(&s_bots, &Button, s_bots/15.0f)*15.0f+0.1f);

MainView.HSplitTop(60, 0, &MainView);

static float s_ScrollValue = 0.0f;
UiDoListboxStart(&s_ScrollValue, &MainView, 50.0f, Localize("Map"), "", s_maplist.size(), 1, s_map, s_ScrollValue);

for(int i = 0; i < s_maplist.size(); ++i)
{
CListboxItem Item = UiDoListboxNextItem(&s_maplist[i], s_map == i);
if(Item.m_Visible)
{
CUIRect Label;
//Item.m_Rect.Margin(5.0f, &Item.m_Rect);
Item.m_Rect.HSplitTop(10.0f, &Item.m_Rect, &Label);
UI()->DoLabelScaled(&Label, s_maplist[i].cstr(), 20.0f, 0);
}
}

s_map = UiDoListboxEnd(&s_ScrollValue, 0);
}