diff options
| author | Stijn Buys <ingar@osirion.org> | 2008-11-08 13:53:28 +0000 | 
|---|---|---|
| committer | Stijn Buys <ingar@osirion.org> | 2008-11-08 13:53:28 +0000 | 
| commit | 016d769e2b353d28b40f9c045f8e6d004d83bec1 (patch) | |
| tree | b797be0fc03d146427af2601762e6460cf880084 /src/dedicated | |
| parent | dbb28ef3422bf2442e15d75fd52180cfb9b40102 (diff) | |
renaming server namespace to dedicated
Diffstat (limited to 'src/dedicated')
| -rw-r--r-- | src/dedicated/Makefile.am | 7 | ||||
| -rw-r--r-- | src/dedicated/console.cc | 485 | ||||
| -rw-r--r-- | src/dedicated/console.h | 66 | ||||
| -rw-r--r-- | src/dedicated/server.cc | 123 | ||||
| -rw-r--r-- | src/dedicated/server.h | 19 | 
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__ + | 
