Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-11-08 13:53:28 +0000
committerStijn Buys <ingar@osirion.org>2008-11-08 13:53:28 +0000
commit016d769e2b353d28b40f9c045f8e6d004d83bec1 (patch)
treeb797be0fc03d146427af2601762e6460cf880084 /src/dedicated
parentdbb28ef3422bf2442e15d75fd52180cfb9b40102 (diff)
renaming server namespace to dedicated
Diffstat (limited to 'src/dedicated')
-rw-r--r--src/dedicated/Makefile.am7
-rw-r--r--src/dedicated/console.cc485
-rw-r--r--src/dedicated/console.h66
-rw-r--r--src/dedicated/server.cc123
-rw-r--r--src/dedicated/server.h19
5 files changed, 700 insertions, 0 deletions
diff --git a/src/dedicated/Makefile.am b/src/dedicated/Makefile.am
new file mode 100644
index 0000000..bc2f741
--- /dev/null
+++ b/src/dedicated/Makefile.am
@@ -0,0 +1,7 @@
+METASOURCES = AUTO
+libserver_la_SOURCES = console.cc server.cc
+noinst_HEADERS = console.h server.h
+noinst_LTLIBRARIES = libserver.la
+INCLUDES = -I$(top_srcdir)/src
+libserver_la_LDFLAGS = -avoid-version -no-undefined
+libserver_la_LIBADD = $(top_builddir)/src/core/libcore.la
diff --git a/src/dedicated/console.cc b/src/dedicated/console.cc
new file mode 100644
index 0000000..9fdad4f
--- /dev/null
+++ b/src/dedicated/console.cc
@@ -0,0 +1,485 @@
+/*
+ server/console.cc
+ This file is part of the Osirion project and is distributed under
+ the terms and conditions of the GNU General Public License version 2
+*/
+
+#include <iostream>
+#include <queue>
+#include <string>
+#include <sstream>
+#include <iomanip>
+#include <cmath>
+
+#include "server/console.h"
+#include "core/core.h"
+#include "sys/consoleinterface.h"
+#include "auxiliary/functions.h"
+
+#ifdef HAVE_CURSES
+#include <ncurses.h>
+#endif
+
+namespace server {
+
+bool console_initialized = false;
+bool console_updated = false;
+
+const size_t MAXHISTOLINES = 512;
+float prev_time = 0;
+Console server_console;
+
+#ifdef HAVE_CURSES
+WINDOW *stdwin;
+#endif
+
+Console *console()
+{
+ return (&server_console);
+}
+
+void Console::init()
+{
+#ifdef HAVE_CURSES
+ stdwin = initscr(); // initialize the ncurses window
+ cbreak(); // disable input line buffering
+ noecho(); // don't show typed characters
+ keypad(stdwin, TRUE); // enable special keys
+ nodelay(stdwin, TRUE); // non-blocking input
+ curs_set(1); // enable cursor
+
+ if (has_colors() == TRUE) {
+ start_color();
+ // this is ncurses-specific
+ use_default_colors();
+ // COLOR_PAIR(0) is terminal default
+ init_pair(1, COLOR_RED, -1);
+ init_pair(2, COLOR_GREEN, -1);
+ init_pair(3, COLOR_YELLOW, -1);
+ init_pair(4, COLOR_BLUE, -1);
+ init_pair(5, COLOR_CYAN, -1);
+ init_pair(6, COLOR_MAGENTA, -1);
+ init_pair(7, COLOR_WHITE, -1);
+ init_pair(8, -1, -1);
+ }
+ console_initialized = true;
+ console_updated = true;
+
+#endif // HAVE_CURSES
+
+ con_print << "^BInitializing console..." << std::endl;
+
+#ifdef HAVE_CURSES
+ server_console.history.clear();
+ server_console.history.push_back("");
+ server_console.history_pos = server_console.history.rbegin();
+ server_console.input_pos = 0;
+ server_console.console_scroll = 0;
+ server_console.draw();
+#endif // HAVE_CURSES
+}
+
+void Console::shutdown()
+{
+ con_print << "^BShutting down console..." << std::endl;
+
+#ifdef HAVE_CURSES
+ server_console.draw();
+ endwin();
+ console_initialized = false;
+
+ server_console.dump();
+#endif
+}
+
+Console::Console()
+{
+}
+
+Console::~Console()
+{
+}
+
+#ifdef HAVE_CURSES
+void Console::dump()
+{
+ // dump console content
+ for (Queue::iterator it = log().begin(); it != log().end(); it++) {
+ sys::ConsoleInterface::print((*it));
+ }
+}
+
+void Console::resize()
+{
+ if (!console_initialized)
+ return;
+
+ endwin();
+ refresh();
+
+ draw();
+}
+
+void Console::print(const std::string & text)
+{
+ console_updated = true;
+}
+
+void Console::set_color(const char *color_code)
+{
+ if (!has_colors())
+ return;
+
+ int color = 0;
+ bool bold = false;
+
+ if (aux::is_base_color_code(color_code)) {
+ // base colors
+ // Default=0, Red=1, Green=2, Yellow=3, Blue=4, Cyan=5, Magenta=6, White=7
+
+ color = *(color_code+1) - '0';
+ if (color == 3 || color == 7)
+ bold = true;
+ else
+ bold = false;
+
+ } else if (aux::is_core_color_code(color_code)) {
+
+ switch (*(color_code+1)) {
+ case 'N': // normal color
+ case 'D': // debug color
+ color = 0;
+ break;
+ case 'B': // bold color
+ color = 0;
+ bold = true;
+ break;
+ case 'W': // warning color
+ color = 3;
+ bold = true;
+ break;
+ case 'R': // error color
+ color = 1;
+ bold = true;
+ break;
+ case 'F': // fancy color
+ color = 2;
+ bold = true;
+ break;
+ }
+ }
+
+ color_set(color, NULL);
+ if (bold)
+ attron(A_BOLD);
+ else
+ attroff(A_BOLD);
+
+}
+
+void Console::draw_background()
+{
+ color_set(0, NULL);
+ attroff(A_BOLD);
+
+ bkgdset(' ');
+ clear();
+
+ // draw version string
+ color_set(2, NULL);
+ std::string versionstr("The Osirion Project ");
+ versionstr.append(core::version());
+ int y = stdwin->_maxx - 1 - versionstr.size();
+ if (y < 0)
+ y = 0;
+ mvaddnstr(0, y, versionstr.c_str(), stdwin->_maxx - 1);
+}
+
+void Console::draw_status()
+{
+ if (core::game()) {
+ attroff(A_BOLD);
+ color_set(2, NULL);
+ int minutes = (int) floorf(core::game()->time() / 60.0f);
+ int seconds = (int) floorf( core::game()->time() - (float) minutes* 60.0f);
+ std::stringstream status;
+ status << "time " << std::setfill(' ') << std::setw(3) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds;
+ mvaddnstr(0, 2, status.str().c_str(), status.str().size());
+ }
+}
+void Console::draw_text()
+{
+ int w = stdwin->_maxx;
+ int h = stdwin->_maxy;
+
+ if ((w < 3) || (h < 3))
+ return;
+
+ Queue lines;
+
+ int height = stdwin->_maxy - 1;
+ int width = stdwin->_maxx - 1;
+ int bottom = (int) log().size() - console_scroll;
+ int current_line = 0;
+
+ // parse console text, wrap long lines
+ for (Queue::iterator it = log().begin(); it != log().end() && current_line < bottom; it++) {
+ if (current_line >= bottom - height) {
+ std::string linedata(*it);
+ linedata += '\n';
+
+ std::string word;
+ int word_length = 0;
+
+ std::string line;
+ int line_length = 0;
+
+ const char *c = linedata.c_str();
+ char pen = 'N';
+ char wordpen = 'N';
+
+ while (*c) {
+
+ // color code
+ if (aux::is_color_code(c)) {
+ c++;
+ pen = *c;
+ word += '^';
+ word += pen;
+ }
+
+ // new word, wrap if necessary
+ else if ((*c == '\n' ) || ( *c == ' ')) {
+
+ if (line_length + word_length > width) {
+ if (line.size()) {
+ lines.push_back(line);
+ line.clear();
+ line += '^';
+ line += wordpen;
+ line_length = 0;
+ }
+ }
+
+ line.append(word);
+ line_length += word_length;
+
+ word.clear();
+ word_length = 0;
+ wordpen = pen;
+
+ // new line
+ if (*c == '\n' ) {
+ lines.push_back(line);
+ line.clear();
+ line_length = 0;
+ // new word
+ } else if (*c == ' ' ) {
+ line += ' ';
+ line_length++;
+ }
+ }
+
+ // new character
+ else {
+ word += *c;
+ word_length++;
+
+ if (word_length == width) {
+ if (line.size()) {
+ lines.push_back(line);
+ line.clear();
+ line += '^';
+ line += wordpen;
+ line_length = 0;
+ }
+
+ line.append(word);
+ line_length = word_length;
+
+ word.clear();
+ word_length = 0;
+ wordpen = pen;
+ }
+ }
+
+ c++;
+ }
+
+ }
+ current_line++;
+ }
+
+ int y = stdwin->_maxy - 1;
+ color_set(0, NULL);
+ attroff(A_BOLD);
+
+ for (Queue::reverse_iterator rit = lines.rbegin(); (y > 0) && (rit != lines.rend()); ++rit) {
+
+ const char *c = (*rit).c_str();
+ int x = 0;
+
+ while (*c) {
+ if (aux::is_color_code(c)) {
+ set_color(c);
+ c++;
+ } else {
+ mvaddnstr(y, x, c, 1);
+ x++;
+ }
+ c++;
+ }
+ y--;
+ }
+}
+
+void Console::draw_input()
+{
+ color_set(0, NULL);
+ attron(A_BOLD);
+ // draw input text
+ mvaddstr(stdwin->_maxy, 0, ">");
+ mvaddstr(stdwin->_maxy, 1, (*history_pos).c_str());
+ // fill the remainder with spaces
+ for (int i=1 + (*history_pos).size(); i < stdwin->_maxx; i++)
+ addch(' ');
+}
+
+void Console::draw()
+{
+ if (!console_initialized)
+ return;
+
+ draw_background();
+ draw_status();
+ draw_text();
+ draw_input();
+ move(stdwin->_maxy, 1 + input_pos);
+ wrefresh(stdwin);
+
+ console_updated = false;
+}
+
+void Console::frame()
+{
+ const size_t scroll_offset = 3;
+ History::reverse_iterator upit;
+
+ if (!console_initialized)
+ return;
+
+ bool input_updated = false;
+
+ int key = wgetch(stdwin);
+ while (key != ERR) {
+ if (key == KEY_BACKSPACE || key == 8 || key == 127) {
+ if ((*history_pos).size() && input_pos) {
+ (*history_pos).erase(input_pos-1, 1);
+ input_pos--;
+ input_updated = true;
+ }
+ break;
+ } else if (key == KEY_STAB || key ==9) {
+ core::CommandBuffer::complete( (*history_pos), input_pos);
+ input_updated = true;
+ break;
+ } else if (key == KEY_LEFT) {
+ if (input_pos > 0) {
+ input_pos--;
+ }
+ input_updated = true;
+ break;
+ } else if (key == KEY_RIGHT) {
+ if (input_pos < (*history_pos).size()) {
+ input_pos++;
+ }
+ input_updated = true;
+ break;
+ } else if (key == KEY_HOME) {
+ input_pos = 0;
+ input_updated = true;
+ break;
+ } else if (key == KEY_END) {
+ input_pos = (*history_pos).size();
+ input_updated = true;
+ break;
+ } else if (key == KEY_UP) {
+ upit = history_pos;
+ ++upit;
+ if (upit != history.rend()) {
+ history_pos = upit;
+ input_pos = (*history_pos).size();
+ input_updated = true;
+ }
+ break;
+ } else if (key == KEY_DOWN) {
+ if (history_pos != history.rbegin()) {
+ --history_pos;
+ input_pos = (*history_pos).size();
+ input_updated = true;
+ }
+ break;
+ } else if (key == KEY_ENTER || key == '\n') {
+ if ((*history_pos).size()) {
+ // store input into history
+ while (history.size() >= MAXHISTOLINES) {
+ history.pop_front();
+ }
+
+ core::cmd() << (*history_pos) << std::endl;
+ con_print << "^B>" << (*history_pos) << std::endl;
+ (*history.rbegin()) = (*history_pos);
+
+ history.push_back("");
+ history_pos = history.rbegin();
+ input_pos = 0;
+ console_updated = true;
+ }
+ break;
+ } else if (key == KEY_PPAGE) {
+ console_scroll += scroll_offset;
+ if (console_scroll > log().size())
+ console_scroll = log().size();
+ console_updated = true;
+ break;
+ } else if (key == KEY_NPAGE) {
+ if (console_scroll > scroll_offset)
+ console_scroll -= scroll_offset;
+ else
+ console_scroll = 0;
+ console_updated = true;
+ break;
+ } else if ((key >= 32) && (key < 127) && ((*history_pos).size() < MAXCMDSIZE)) {
+ if (input_pos == (*history_pos).size()) {
+ (*history_pos) += (char)key;
+ } else {
+ (*history_pos).insert(input_pos, 1, (char)key);
+ }
+ input_pos++;
+ input_updated = true;
+ }
+ key = wgetch(stdwin);
+ }
+
+ if (console_updated) {
+ draw();
+ } else {
+ if (input_updated) {
+ draw_input();
+ }
+ if (roundf(core::application()->time()) != prev_time) {
+ draw_status();
+ prev_time = roundf(core::application()->time());
+ input_updated = true;
+ }
+ if (input_updated) {
+ // move the cursor to input position
+ move(stdwin->_maxy, 1 + input_pos);
+ wrefresh(stdwin);
+ }
+ }
+}
+#endif // HAVE_CURSES
+
+}
+
diff --git a/src/dedicated/console.h b/src/dedicated/console.h
new file mode 100644
index 0000000..13db3fc
--- /dev/null
+++ b/src/dedicated/console.h
@@ -0,0 +1,66 @@
+/*
+ server/console.h
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#ifndef __INCLUDED_SERVER_CONSOLE_H__
+#define __INCLUDED_SERVER_CONSOLE_H__
+
+#include "sys/consoleinterface.h"
+
+namespace server {
+
+class Console : public sys::ConsoleInterface {
+public:
+ Console();
+ ~Console();
+
+ /// initialize the server console
+ static void init();
+ /// shutdown the server console
+ static void shutdown();
+
+#ifdef HAVE_CURSES
+ /// resize the console
+ virtual void resize();
+ /// run one console frame
+ void frame();
+
+protected:
+ /// draw the ncurses console
+ void draw();
+ /// clear and draw background (ncurses)
+ void draw_background();
+ /// draw status
+ void draw_status();
+ /// draw the console text (ncurses)
+ void draw_text();
+ /// draw the console input (ncurses)
+ void draw_input();
+ /// dump console content to cout
+ void dump();
+ /// print one line of text (do nothing)
+ virtual void print(const std::string & text);
+
+private:
+ typedef std::deque<std::string> History;
+
+ /// set ncurses drawing color
+ void set_color(const char *color_code);
+
+ // input history
+ History history;
+ History::reverse_iterator history_pos;
+
+ size_t input_pos;
+ size_t console_scroll;
+#endif
+};
+
+Console *console();
+
+}
+
+#endif // __INCLUDED_SERVER_CONSOLE_H__
+
diff --git a/src/dedicated/server.cc b/src/dedicated/server.cc
new file mode 100644
index 0000000..a4424a0
--- /dev/null
+++ b/src/dedicated/server.cc
@@ -0,0 +1,123 @@
+/*
+ server/server.cc
+ This file is part of the Osirion project and is distributed under
+ the terms and conditions of the GNU General Public License version 2
+*/
+
+#include <iostream>
+#include <iomanip>
+
+#include "core/core.h"
+#include "core/stats.h"
+#include "core/timer.h"
+#include "server/console.h"
+#include "server/server.h"
+
+namespace server {
+
+//--- private definition ------------------------------------------
+
+/// server Application implementation
+class Server : public core::Application {
+public:
+ /// initialize the server Application
+ virtual void init(int count, char **arguments);
+
+ /// run the server Application
+ virtual void run();
+
+ /// shutdown the server Application
+ virtual void shutdown();
+
+ /// quit the server Application
+ virtual void quit(int status);
+};
+
+
+Server app;
+
+//--- public ------------------------------------------------------
+
+/// the server main loop
+void main(int count, char **arguments)
+{
+ std::cout << core::name() << " " << core::version() << std::endl;
+
+ for (int i =0; i < count; i++)
+ std::cout << arguments[i] << " ";
+ std::cout << std::endl;
+
+ app.init(count, arguments);
+ app.run();
+ app.shutdown();
+}
+
+//--- private -----------------------------------------------------
+
+void Server::init(int count, char **arguments)
+{
+ con_print << "^BInitializing server..." << std::endl;
+
+ core::Cvar::set("sv_dedicated", "1", core::Cvar::ReadOnly);
+
+ core::Application::init(count, arguments);
+
+ Console::init();
+
+ // the command line is in the buffer, execute it
+ core::CommandBuffer::exec();
+
+ std::string empty;
+ core::Application::connect(empty);
+}
+
+void Server::run()
+{
+ float server_framerate = 1.0f / 25.0f;
+
+ if (core::Cvar::sv_framerate->value())
+ server_framerate = 1.0f / core::Cvar::sv_framerate->value();
+
+ core::Timer timer;
+ timer.mark();
+
+ while(connected()) {
+ frame(timer.timestamp());
+#ifdef HAVE_CURSES
+ console()->frame();
+#endif
+ }
+}
+
+void Server::shutdown()
+{
+ con_print << "^BShutting down server..." << std::endl;
+
+ float ratio = 0;
+ if (core::Stats::network_uncompressed_bytes_sent > 0)
+ ratio = 100.0f - floorf((float)core::Stats::network_bytes_sent /
+ (float) core::Stats::network_uncompressed_bytes_sent * 100.0f);
+
+ int minutes = (int) floorf(time() / 60.0f);
+ int seconds = (int) floorf(time() - (float) minutes* 60.0f);
+
+ con_debug << "Statistics:" << std::endl;
+ con_debug << " uptime " << std::setfill(' ') << std::setw(3) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds << std::endl;
+ con_debug << " bytes sent " << std::setfill(' ') << std::setw(6) << core::Stats::network_bytes_sent / 1024 << " Kb" << std::endl;
+ con_debug << " bytes received " << std::setw(6) << core::Stats::network_bytes_received / 1024 << " Kb" << std::endl;
+ con_debug << " compression " << std::setw(6) << ratio << " %" << std::endl;
+
+ core::Application::shutdown();
+
+ Console::shutdown();
+
+ quit(0);
+}
+
+void Server::quit(int status)
+{
+ core::Application::quit(status);
+}
+
+} // namespace server
+
diff --git a/src/dedicated/server.h b/src/dedicated/server.h
new file mode 100644
index 0000000..4691e91
--- /dev/null
+++ b/src/dedicated/server.h
@@ -0,0 +1,19 @@
+/*
+ server/server.h
+ This file is part of the Osirion project and is distributed under
+ the terms and conditions of the GNU General Public License version 2
+*/
+
+#ifndef __INCLUDED_SERVER_H__
+#define __INCLUDED_SERVER_H__
+
+/// contains classes and functions to run a dedicated server
+namespace server {
+
+/// the server main loop
+void main(int count, char **arguments);
+
+} // namespace server
+
+#endif // __INCLUDED_SERVER_H__
+