From 89de2efebc22b3754c18ede10dc07bfc397fc2d0 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 2 Jul 2008 19:18:44 +0000 Subject: initial server ncurses console --- ROADMAP | 11 ++-- TODO | 19 ++++--- configure.in | 55 +++++++++++++++++- osirion.kdevelop.pcs | Bin 760202 -> 764410 bytes osirion.kdevses | 8 +-- src/Makefile.am | 2 +- src/auxiliary/functions.h | 2 +- src/client/input.cc | 3 + src/core/application.cc | 23 +++++--- src/core/commandbuffer.cc | 1 + src/core/core.cc | 2 +- src/core/cvar.cc | 2 + src/core/cvar.h | 3 + src/core/gameserver.cc | 4 ++ src/core/netconnection.cc | 2 +- src/core/netserver.cc | 15 ++++- src/core/netserver.h | 3 + src/core/player.cc | 1 + src/core/player.h | 13 +++-- src/server/console.cc | 132 +++++++++++++++++++++++++++++++++++++++++++- src/server/console.h | 22 +++++++- src/server/server.cc | 15 ++--- src/sys/consoleinterface.cc | 4 ++ src/sys/consoleinterface.h | 3 + 24 files changed, 294 insertions(+), 51 deletions(-) diff --git a/ROADMAP b/ROADMAP index 655d5fa..d57baac 100644 --- a/ROADMAP +++ b/ROADMAP @@ -1,6 +1,6 @@ ROADMAP -* MILESTONE 1 - version 0.1 +* MILESTONE 1 - version 0.0.1 Description: The game takes place in a simple solar system with one star, @@ -20,20 +20,21 @@ Requires: Camera handling Keyboard bindings -* MILESTONE 2 - version 0.2 +* MILESTONE 2 - version 0.0.2 Description: Players can shoot at each other. They can crash into the star or the planet. Player ships explode on destruction. Requires: + Targetting Events: explosions, weapons fire Model weapon support Turret and cannon models Particle systems clip brushes and collision detection -* MILESTONE 3 - version 0.3 +* MILESTONE 3 - version 0.0.3 Description: Players can dock at the space station and buy a ship or purchase @@ -43,11 +44,13 @@ Requires: Docking Docking GUI -* MILESTONE 4 - version 0.4 +* MILESTONE 4 - version 0.0.4 * MILESTONE 5 +.. + * Release 1.0 Requires: diff --git a/TODO b/TODO index a46b22e..6059c24 100644 --- a/TODO +++ b/TODO @@ -1,30 +1,30 @@ TODO -(ok) done -(--) postponed - milestone 1: console text color and wrapping (ok) - entity axis interpolation (usable for now) - camera tracking mode (usable for now) - camera frustum clip (--) + keyboard binds (ok) + + fix turning + fix camera rotation + fix camera frustum clip - keyboard binds + better crosshair bitmaps milestone 2: + targetting system server-client event system, hit-once lightweight entities explosion events weapons fire events - filesystem: write a filesystem based on streams write handlers for zip model: + engine flare key (ok) + support map classes (e.g. func_rotate), requires class VertexData split map loader from model, load vertices into VertexData - engine flare key core: connection to remote game (ok) @@ -82,3 +82,4 @@ win32 port: sound is broken directory creation + diff --git a/configure.in b/configure.in index 0b42aa7..1628c75 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,16 @@ AC_INIT(configure.in) +dnl ---------------------------------------------------------------- +dnl append SVN revision to the version number +OSIRIONVERSION='0.0.1' +SVNREVISION=`svnversion $srcdir` + +if test ! -z "$SVNREVISION"; then + OSIRIONVERSION="${OSIRIONVERSION}_${SVNREVISION}" +fi + AM_CONFIG_HEADER(src/config.h) -AM_INIT_AUTOMAKE(osirion, 0.1) +AM_INIT_AUTOMAKE(osirion, $OSIRIONVERSION) AC_LANG_CPLUSPLUS AC_PROG_CXX @@ -62,6 +71,9 @@ AC_DEFUN([KDE_FIND_PATH], fi ]) +dnl ---------------------------------------------------------------- +dnl HOST dependend variables +dnl AC_MSG_CHECKING([host type]) case "$host" in *-*-mingw*) @@ -85,6 +97,9 @@ AC_SUBST(HOST_LIBS) AC_SUBST(ICON_CLIENT) AC_SUBST(ICON_SERVER) +dnl ---------------------------------------------------------------- +dnl enable compiler warnings or not +dnl AC_MSG_CHECKING(whether to abort on compiler warnings) WARN_CFLAGS="" AC_ARG_ENABLE(warn, @@ -97,7 +112,9 @@ AC_ARG_ENABLE(warn, ) AC_SUBST(WARN_CFLAGS) - +dnl ---------------------------------------------------------------- +dnl enable DEBUG messages or not +dnl AC_MSG_CHECKING(whether to include debug messages) AC_ARG_ENABLE(debug_messages, AC_HELP_STRING( @@ -108,10 +125,41 @@ AC_ARG_ENABLE(debug_messages, AC_DEFINE_UNQUOTED(HAVE_DEBUG_MESSAGES, 1, [Defines if debug information is enabled]) ) +dnl ---------------------------------------------------------------- +dnl check for ncurses +dnl + +HAVE_CURSES=no + +AC_ARG_WITH(ncurses, + AC_HELP_STRING([--without-ncurses], + [don't include ncurses support] + ) +) + +if test "x${with_ncurses}" != "xno"; then + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $CURSES_CFLAGS" + + AC_CHECK_HEADER(ncurses.h, + HAVE_CURSES=yes + AC_DEFINE(HAVE_CURSES, 1, [Define this if you have ncurses]) + CURSES_LIBS="$NCURSES_LIBS -lncurses", + HAVE_CURSES=no + ) + + CPPFLAGS="$save_CPPFLAGS" +fi +AC_SUBST(CURSES_CFLAGS) +AC_SUBST(CURSES_LIBS) + +dnl ---------------------------------------------------------------- +dnl build client and erer or dedicated server only +dnl BUILD_CLIENT=no AC_ARG_WITH(client, - AC_HELP_STRING([--without-client], [build the dedicated server only]) + AC_HELP_STRING([--without-client], [do not build the client application]) ) AC_MSG_CHECKING(whether to build client) @@ -229,6 +277,7 @@ Configuration summary: platform ........... $host flags .............. $CXXFLAGS libraries .......... $HOST_LIBS + ncurses ............ $HAVE_CURSES build client ....... $BUILD_CLIENT opengl ............. $GL_LIBS openal ............. $AL_LIBS diff --git a/osirion.kdevelop.pcs b/osirion.kdevelop.pcs index 000958d..7d39b5d 100644 Binary files a/osirion.kdevelop.pcs and b/osirion.kdevelop.pcs differ diff --git a/osirion.kdevses b/osirion.kdevses index c284b2a..975ddcf 100644 --- a/osirion.kdevses +++ b/osirion.kdevses @@ -2,11 +2,11 @@ - - + + - - + + diff --git a/src/Makefile.am b/src/Makefile.am index 3fad1fd..b192682 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,7 +25,7 @@ osiriond_LDADD = $(top_builddir)/src/auxiliary/libauxiliary.la \ $(top_builddir)/src/core/libcore.la $(top_builddir)/src/filesystem/libfilesystem.la \ $(top_builddir)/src/game/libgame.la \ $(top_builddir)/src/model/libmodel.la $(top_builddir)/src/server/libserver.la \ - $(top_builddir)/src/math/libmath.la $(top_builddir)/src/sys/libsys.la $(HOST_LIBS) $(ICON_SERVER) + $(top_builddir)/src/math/libmath.la $(top_builddir)/src/sys/libsys.la $(HOST_LIBS) $(ICON_SERVER) $(CURSES_LIBS) # client osirion_SOURCES = osirion.cc diff --git a/src/auxiliary/functions.h b/src/auxiliary/functions.h index ceab0de..e8704d4 100644 --- a/src/auxiliary/functions.h +++ b/src/auxiliary/functions.h @@ -1,5 +1,5 @@ /* - aux/functions.cc + aux/functions.h This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ diff --git a/src/client/input.cc b/src/client/input.cc index d3feefe..6a62fa5 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -65,6 +65,9 @@ void func_screenshot(std::string const & args) void func_ui_control(std::string const &args) { + if (!core::localcontrol()) + return; + if (cl_mousecontrol->value() > 0) { (*cl_mousecontrol) = 0.0f; } else { diff --git a/src/core/application.cc b/src/core/application.cc index 738a071..cd6d278 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -61,9 +61,9 @@ void func_disconnect(std::string const &args) // --------------- signal_handler ----------------------------------- +#ifndef _WIN32 extern "C" void signal_handler(int signum) { -#ifndef _WIN32 switch (signum) { case SIGHUP: case SIGINT: @@ -78,13 +78,18 @@ extern "C" void signal_handler(int signum) application()->quit(1); } break; +#ifdef HAVE_CURSES + case SIGWINCH: + sys::ConsoleInterface::instance()->resize(); + break; +#endif default: std::cerr << "Received signal " << signum << ", terminated...\n"; application()->quit(1); break; } -#endif } +#endif // --------------- Application ----------------------------- @@ -106,6 +111,9 @@ Application::Application() sys::signal(SIGINT, signal_handler); sys::signal(SIGQUIT, signal_handler); sys::signal(SIGTERM, signal_handler); +#ifdef HAVE_CURSES + sys::signal(SIGWINCH, signal_handler); +#endif #endif } @@ -165,6 +173,10 @@ void Application::init(int count, char **arguments) Cvar::net_framerate = Cvar::get("net_framerate", "25"); Cvar::net_framerate->set_info("[int] network framerate in frames/sec"); + // passwords + Cvar::rconpassword = Cvar::get("rconpassword", "", Cvar::Archive); + Cvar::rconpassword->set_info("[string] password for remote console access"); + #ifdef _WIN32 Cvar::con_ansi = Cvar::get("con_ansi", "0", Cvar::Archive); #else @@ -185,7 +197,7 @@ void Application::init(int count, char **arguments) // register our engine functions Func *func = 0; func = Func::add("help", func_help); - func->set_info("dummy help function"); + func->set_info("help function"); func = Func::add("quit", func_quit); func->set_info("exit the application"); @@ -212,7 +224,6 @@ void Application::shutdown() save_config(); // remove our engine functions - Func::remove("print"); Func::remove("help"); Func::remove("quit"); @@ -280,8 +291,6 @@ void Application::disconnect() void Application::frame(float seconds) { - console()->flush(); - // execute commands in the buffer CommandBuffer::exec(); @@ -299,8 +308,6 @@ void Application::frame(float seconds) if (!application_game->running()) disconnect(); - - console()->flush(); } void Application::save_config() diff --git a/src/core/commandbuffer.cc b/src/core/commandbuffer.cc index 0d02e6b..b34b04b 100644 --- a/src/core/commandbuffer.cc +++ b/src/core/commandbuffer.cc @@ -93,6 +93,7 @@ std::stringstream CommandBuffer::cmdbuf(std::stringstream::in | std::stringstrea void CommandBuffer::init() { //con_debug << "Initializing command buffer...\n"; + Func *func = 0; func = Func::add("list_ent", (FuncPtr)func_list_ent); func->set_info("list entities"); diff --git a/src/core/core.cc b/src/core/core.cc index c77087e..0f68ab3 100644 --- a/src/core/core.cc +++ b/src/core/core.cc @@ -12,7 +12,7 @@ namespace core { std::string core_name("The Osirion Project"); -std::string core_version("0.1"); +std::string core_version(VERSION); const std::string &name() { diff --git a/src/core/cvar.cc b/src/core/cvar.cc index 9d90afd..772144f 100644 --- a/src/core/cvar.cc +++ b/src/core/cvar.cc @@ -31,6 +31,8 @@ Cvar *Cvar::net_maxclients = 0; Cvar *Cvar::net_timeout = 0; Cvar *Cvar::net_framerate = 0; +Cvar *Cvar::rconpassword = 0; + std::map Cvar::registry; Cvar::Cvar(const char *name, unsigned int flags) diff --git a/src/core/cvar.h b/src/core/cvar.h index 620096b..7aab5d3 100644 --- a/src/core/cvar.h +++ b/src/core/cvar.h @@ -123,6 +123,9 @@ public: static Cvar *net_maxclients;// maximum number of connected clients static Cvar *net_timeout; // network timeout in seconds static Cvar *net_framerate; // client network send framerate + + static Cvar *rconpassword; // rcon password + private: std::string cvar_name; std::string cvar_info; diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index 3bcc4fe..cddddff 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -298,6 +298,10 @@ void GameServer::exec(Player *player, std::string const & cmdline) void GameServer::player_connect(Player *player) { + if (Cvar::sv_dedicated->value() && (player == localplayer())) { + return; + } + player->player_id = server_maxplayerid++; std::string message("^B"); diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index fc2e5d0..b89887c 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -348,7 +348,7 @@ void NetConnection::parse_incoming_message(const std::string & message) // FIXME - separate sender nickname if (message.size() > 11) { application()->notify_message(message.substr(11)); - application()->notify_sound("com/chat.wav"); + application()->notify_sound("com/chat"); } } else if (level == "snd") { diff --git a/src/core/netserver.cc b/src/core/netserver.cc index b604f47..2859006 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -126,6 +126,10 @@ NetServer::~NetServer() } } +void NetServer::abort() { + netserver_error = true; +} + // remove disconnected clients void NetServer::reap() { @@ -185,9 +189,14 @@ void NetServer::receive() int nb = select(fd()+1, &readset, NULL, NULL, &timeout); if (nb == -1) { +#ifndef _WIN32 + // ncurses needs SIGWINCH catched + if (errno == EINTR) { + return; + } +#endif con_error << "Network error on select()" << std::endl; - //perror("select"); - abort(); + this->abort(); return; } @@ -200,7 +209,7 @@ void NetServer::receive() ssize_t bytes_received = ::recvfrom(fd(), recbuf, FRAMESIZE-1, 0, (struct sockaddr *)&client_addr, &client_addr_len); if (bytes_received == -1) { con_error << "Network error on recvfrom()!" << std::endl; - abort(); + this->abort(); return; } else { //con_debug << "Incoming data '" << recbuf << "'"<< bytes_received << " bytes" << std::endl; diff --git a/src/core/netserver.h b/src/core/netserver.h index 5850b29..a83229c 100644 --- a/src/core/netserver.h +++ b/src/core/netserver.h @@ -64,6 +64,9 @@ public: std::list clients; protected: + /// set the error state + void abort(); + /// called when a new client connects NetClient *client_connect(std::string const host, int const port); diff --git a/src/core/player.cc b/src/core/player.cc index 71ac8de..97b6944 100644 --- a/src/core/player.cc +++ b/src/core/player.cc @@ -28,6 +28,7 @@ void Player::clear() player_id = 0; player_name.clear(); player_dirty = false; + player_rcon = false; clear_assets(); } diff --git a/src/core/player.h b/src/core/player.h index 08abac2..b8dd100 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -25,7 +25,9 @@ namespace core class Player { public: + /// default constructor Player(); + /// default destructor ~Player(); /*----- inspectors ------------------------------------------------ */ @@ -79,19 +81,22 @@ public: /* -- should actually not be public --*/ - // dirty state + /// dirty state bool player_dirty; - // id of the player + /// indicates rcon access + bool player_rcon; + + /// id of the player int player_id; // name of the player std::string player_name; - // color + /// player color math::Color player_color; - // the entity the Player is currently controling + /// the entity the Player is currently controling EntityControlable *player_control; std::list assets; diff --git a/src/server/console.cc b/src/server/console.cc index 4b7992e..ea82dff 100644 --- a/src/server/console.cc +++ b/src/server/console.cc @@ -4,28 +4,158 @@ the terms and conditions of the GNU General Public License version 2 */ +#include + #include "server/console.h" #include "core/core.h" +#include "sys/consoleinterface.h" -#include +#ifdef HAVE_CURSES +#include +#endif namespace server { +bool console_initialized = false; +bool console_updated = false; + 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(0); // disable cursor + + console_initialized = true; + console_updated = true; +#endif // HAVE_CURSES + con_print << "Initializing console..." << std::endl; + +#ifdef HAVE_CURSES + server_console.console_lastrefresh = 1; + server_console.draw(); +#endif // HAVE_CURSES } void Console::shutdown() { con_print << "Shutting down console..." << std::endl; + +#ifdef HAVE_CURSES + server_console.draw(); + endwin(); + console_initialized = false; +#endif +} + +#ifdef HAVE_CURSES +void Console::resize() +{ + if (!console_initialized) + return; + + endwin(); + refresh(); + + console_updated = true; +} + +void Console::flush() +{ + char line[MAXCMDSIZE]; + + while(consoleinterface_buffer.getline(line, MAXCMDSIZE-1)) { + + while (consoleinterface_text.size() >= sys::MAXCONLINES) { + consoleinterface_text.pop_front(); + } + consoleinterface_text.push_back(std::string(line)); + console_updated = true; + } + + consoleinterface_buffer.clear(); +} + +void Console::draw_background() +{ + bkgdset(' '); + clear(); + + // draw version string + std::string versionstr("The Osirion Project "); + versionstr.append(core::version()); + mvaddstr(0, stdwin->_maxx - 1 - versionstr.size(), versionstr.c_str()); +} + +void Console::draw_text() +{ + int w = stdwin->_maxx; + int h = stdwin->_maxy; + + if ((w < 3) || (h < 3)) + return; + + int y = h-1; + + // draw console text + std::deque::reverse_iterator rit = consoleinterface_text.rbegin(); + while (rit != consoleinterface_text.rend() && y > 0) { + mvaddnstr(y, 0, (*rit).c_str(), w); + ++rit; + y--; + } +} + +void Console::draw() +{ + flush(); + + if (console_lastrefresh < 0.1) { + return; + } + + if (console_initialized && console_updated && stdwin->_maxx && stdwin->_maxy) { + + draw_background(); + draw_text(); + wrefresh(stdwin); + + console_updated = false; + console_lastrefresh = 0; + } + +} + +void Console::frame(float seconds) +{ + if (!console_initialized) + return; + + console_lastrefresh += seconds; + + int key = wgetch(stdwin); + while (key != ERR) { + key = wgetch(stdwin); + } + + draw(); } +#endif // HAVE_CURSES } diff --git a/src/server/console.h b/src/server/console.h index d894bf1..6a42ba5 100644 --- a/src/server/console.h +++ b/src/server/console.h @@ -13,9 +13,29 @@ namespace server { class Console : public sys::ConsoleInterface { public: + /// initialize the server console static void init(); - + /// shutdown the server console static void shutdown(); + +#ifdef HAVE_CURSES + /// flush buffered messages + virtual void flush(); + /// resize the console + virtual void resize(); + /// run one console frame + void frame(float seconds); +protected: + /// draw the ncurses console + void draw(); + /// clear and draw background (ncurses) + void draw_background(); + /// draw the console text (ncurses) + void draw_text(); + +private: + float console_lastrefresh; +#endif }; Console *console(); diff --git a/src/server/server.cc b/src/server/server.cc index 27cdf9b..fce2181 100644 --- a/src/server/server.cc +++ b/src/server/server.cc @@ -83,17 +83,11 @@ void Server::run() while(connected()) { timer.mark(); frame(elapsed); +#ifdef HAVE_CURSES + console()->frame(elapsed); +#endif elapsed = timer.elapsed(); - - /* - if (elapsed < server_framerate) { - sys::sleep(server_framerate - elapsed); - - elapsed = server_framerate; - } - */ } - } void Server::shutdown() @@ -113,9 +107,10 @@ void Server::shutdown() 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; - Console::shutdown(); core::Application::shutdown(); + + Console::shutdown(); quit(0); } diff --git a/src/sys/consoleinterface.cc b/src/sys/consoleinterface.cc index eaecdea..8b734ff 100644 --- a/src/sys/consoleinterface.cc +++ b/src/sys/consoleinterface.cc @@ -81,6 +81,10 @@ void ConsoleInterface::flush() consoleinterface_buffer.clear(); } +void ConsoleInterface::resize() +{ +} + void ConsoleInterface::print_ansi(const char *line) { if (consoleinterface_ansi) diff --git a/src/sys/consoleinterface.h b/src/sys/consoleinterface.h index f874182..6475676 100644 --- a/src/sys/consoleinterface.h +++ b/src/sys/consoleinterface.h @@ -57,6 +57,9 @@ public: /// flush buffered messages virtual void flush(); + /// resize the console (ncurses stub) + virtual void resize(); + /// turn ANSI color codes on or off inline void set_ansi(bool ansi) { consoleinterface_ansi = ansi; } -- cgit v1.2.3