Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-05-14 21:07:10 +0000
committerStijn Buys <ingar@osirion.org>2008-05-14 21:07:10 +0000
commita185c11f2397c0296a4b62cc266b4fa00a63c1e2 (patch)
tree186da4cdee2d9cd46fb2415567da1c441c7431ef /src
parent599adb817e19d9be3502e501dc904c7255cd616c (diff)
console, camera & interpolation
Diffstat (limited to 'src')
-rw-r--r--src/client/camera.cc129
-rw-r--r--src/client/chat.cc51
-rw-r--r--src/client/client.cc16
-rw-r--r--src/client/console.cc536
-rw-r--r--src/client/console.h84
-rw-r--r--src/client/input.cc20
-rw-r--r--src/client/view.cc10
-rw-r--r--src/core/application.cc26
-rw-r--r--src/core/application.h4
-rw-r--r--src/core/cvar.cc1
-rw-r--r--src/core/cvar.h2
-rw-r--r--src/core/gameconnection.cc4
-rw-r--r--src/core/gameinterface.cc207
-rw-r--r--src/core/gameinterface.h4
-rw-r--r--src/core/gameserver.cc10
-rw-r--r--src/core/gameserver.h1
-rw-r--r--src/core/netconnection.cc14
-rw-r--r--src/game/game.cc2
-rw-r--r--src/math/functions.cc10
-rw-r--r--src/render/draw.cc4
-rw-r--r--src/server/console.cc75
-rw-r--r--src/server/console.h13
-rw-r--r--src/server/server.cc5
-rw-r--r--src/sys/consoleinterface.cc129
-rw-r--r--src/sys/consoleinterface.h39
-rw-r--r--src/sys/sys.cc16
-rw-r--r--src/sys/sys.h4
27 files changed, 808 insertions, 608 deletions
diff --git a/src/client/camera.cc b/src/client/camera.cc
index 29310fc..21bf930 100644
--- a/src/client/camera.cc
+++ b/src/client/camera.cc
@@ -28,6 +28,7 @@ math::Vector3f target;
math::Vector3f eye;
math::Axis axis;
+const float MIN_DELTA = 10e-10;
// current camera mode
Mode mode;
@@ -86,10 +87,18 @@ void set_mode(Mode newmode) {
target_pitch = 0.0f;
distance = 0.4f;
+ axis.clear();
+
switch(newmode) {
case Track:
// switch camera to Track mode
mode = Track;
+ if (core::localcontrol()) {
+ if (core::localcontrol()->state())
+ axis.assign(core::localcontrol()->state()->axis());
+ else
+ axis.assign(core::localcontrol()->axis());
+ }
break;
case Free:
@@ -148,7 +157,7 @@ void next_mode()
void draw(float seconds)
{
math::Matrix4f matrix;
-
+ math::Axis target_axis;
float d = 0;
if (!core::localcontrol()) {
@@ -165,37 +174,102 @@ void draw(float seconds)
distance = 20.0f;
} else {
-
if (mode == Overview)
set_mode(Track);
if (core::localcontrol()->state()) {
target.assign(core::localcontrol()->state()->location());
- axis.assign(core::localcontrol()->state()->axis());
+ target_axis.assign(core::localcontrol()->state()->axis());
} else {
target.assign(core::localcontrol()->location());
- axis.assign(core::localcontrol()->axis());
+ target_axis.assign(core::localcontrol()->axis());
}
-
+
if (mode == Track) {
- if (core::localcontrol()->state() && core::localcontrol()->model()) {
- target -= (core::localcontrol()->model()->maxbbox().x + 0.15f) * core::localcontrol()->state()->axis().forward();
-
- target += (core::localcontrol()->model()->maxbbox().z + 0.3f ) *
- core::localcontrol()->state()->axis().up();
+ float cosangle;
+ float angle;
+ float side;
+ float u;
+ const float cam_speed = seconds * 4 ;
+
+ math::Vector3f n;
+ math::Vector3f p;
+
+ // camera axis: pitch
+
+ // project target_axis.up() into the plane with axis->left() normal
+ n = axis.left();
+ p = target_axis.up();
+ u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
+ p = target_axis.up() + u * n;
+
+ side = axis.forward().x * p.x +
+ axis.forward().y * p.y +
+ axis.forward().z * p.z;
+
+ if ((fabs(side) - MIN_DELTA > 0)) {
+
+ cosangle = math::dotproduct(p, axis.up());
+ if (fabs(cosangle) + MIN_DELTA < 1 ) {
+ angle = acos(cosangle) * 180.0f / M_PI;
+ angle = math::sgnf(side) * angle * cam_speed;
+ axis.change_pitch(-angle);
+ }
}
- // make the camera swing while turning
- target_direction = core::localcontrol()->target_direction;
- target_pitch = core::localcontrol()->target_pitch;
+ // camera axis: direction
+
+ // project target_axis.forward() into the plane with axis.up() normal
+ n = axis.up();
+ p = target_axis.forward();
+ u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
+ p = target_axis.forward() + u * n;
+
+ side = axis.left().x * p.x +
+ axis.left().y * p.y +
+ axis.left().z * p.z;
+
+ if ((fabs(side) - MIN_DELTA > 0)) {
+
+ cosangle = math::dotproduct(p, axis.forward());
+ if (fabs(cosangle) + MIN_DELTA < 1 ) {
+ angle = acos(cosangle) * 180.0f / M_PI;
+ angle = math::sgnf(side) * angle * cam_speed;
+ axis.change_direction(angle);
+ }
+ }
- yaw_target = - 30 * target_direction;
- pitch_target = - 30 * target_pitch;
- //pitch_target = pitch_track - 30 * target_pitch;
+ // camera axis: roll
+
+ // project target_axis.up() into the plane with axis.forward() normal
+ n = axis.forward();
+ p = target_axis.up();
+ u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
+ p = target_axis.up() + u * n;
+
+ side = axis.left().x * p.x +
+ axis.left().y * p.y +
+ axis.left().z * p.z;
+
+ if ((fabs(side) - MIN_DELTA > 0)) {
+
+ cosangle = math::dotproduct(p, axis.up());
+ if (fabs(cosangle) + MIN_DELTA < 1 ) {
+ angle = acos(cosangle) * 180.0f / M_PI;
+ angle = math::sgnf(side) * angle * cam_speed;
+ axis.change_roll(angle);
+ }
+ }
distance = 0.0f;
+ if (core::localcontrol()->model()) {
+ target -= (core::localcontrol()->model()->maxbbox().x + 0.1f) * axis.forward();
+ target += (core::localcontrol()->model()->maxbbox().z + 0.1f ) * axis.up();
+ }
+
} else if (mode == Free) {
+ axis.assign(target_axis);
yaw_target = yaw_current - 90 * target_direction;
pitch_target = pitch_current - 90 * target_pitch;
@@ -205,26 +279,25 @@ void draw(float seconds)
} else {
distance = 1.0f;
}
-
- } else if (mode == Cockpit) {
- if (core::localcontrol()->state() && core::localcontrol()->model())
- target += (core::localcontrol()->model()->maxbbox().x+0.05) *
- core::localcontrol()->state()->axis().forward();
-
- distance = 0.0f;
- }
-
- if (mode != Cockpit) {
// adjust direction
d = degrees180f(yaw_current - yaw_target);
yaw_current = degrees360f( yaw_current - d * seconds);
axis.change_direction(yaw_current);
- // adjust pitch target
+ // adjust pitch
d = degrees180f(pitch_current - pitch_target);
- pitch_current = degrees360f(pitch_current - d *seconds);
+ pitch_current = degrees360f(pitch_current - d * seconds);
axis.change_pitch(pitch_current);
+
+ } else if (mode == Cockpit) {
+ axis.assign(target_axis);
+
+ if (core::localcontrol()->state() && core::localcontrol()->model())
+ target += (core::localcontrol()->model()->maxbbox().x+0.05) *
+ core::localcontrol()->state()->axis().forward();
+
+ distance = 0.0f;
}
}
diff --git a/src/client/chat.cc b/src/client/chat.cc
index 1953390..9171387 100644
--- a/src/client/chat.cc
+++ b/src/client/chat.cc
@@ -4,6 +4,7 @@
the terms and conditions of the GNU General Public License version 2
*/
+#include "auxiliary/functions.h"
#include "core/core.h"
#include "client/chat.h"
#include "client/console.h"
@@ -71,24 +72,54 @@ void draw()
{
using namespace render;
- if (console::visible() || !visible())
+ if (console()->visible() || !visible())
return;
- size_t width = (size_t) (video::width / Text::fontwidth()) - 7;
- size_t draw_pos = 0;
- while (input_pos - draw_pos > width)
- draw_pos += 2;
+ size_t width = (size_t) (video::width / Text::fontwidth()) - 8;
+ float y = video::height*8/10;
+ Text::draw(4, y, "^BSay^F:^B ");
- // draw the chat input
- float y = video::height * 8.0 / 10.0;
+ std::string firstpart((*history_pos).substr(0, input_pos));
+ size_t draw_width = 0;
+ const char *c = firstpart.c_str();
- Text::draw(4 , y, "^Bsay^F:^B");
- Text::draw(4+Text::fontwidth()*5 , y, (*history_pos).substr(draw_pos, width));
+ while (*c) {
+ if (aux::is_color_code(c)) {
+ c++;
+ } else {
+ draw_width++;
+ }
+ c++;
+ }
+
+ c = firstpart.c_str();
+ while (*c && draw_width > width - 2) {
+ if (aux::is_color_code(c)) {
+ c++;
+ Text::setcolor(*c);
+ } else {
+ draw_width--;
+ }
+ c++;
+ }
+
+ if (*c) {
+ Text::draw(4+5*Text::fontwidth(), y, c);
+ }
+
+ if (input_pos < (*history_pos).size()) {
+ // FIXME limit to width
+ if (input_pos > 1 && aux::is_color_code((*history_pos).c_str() + input_pos -1)) {
+ Text::setcolor((*history_pos)[input_pos]);
+ }
+ c = (*history_pos).c_str() + input_pos;
+ Text::draw(4+Text::fontwidth()*(draw_width+5), y, c);
+ }
// draw cursor
if ((core::application()->time() - ::floorf(core::application()->time())) < 0.5f) {
std::string cursor("^B_");
- Text::draw(4+Text::fontwidth()*(input_pos - draw_pos+5), y, cursor);
+ Text::draw(4+Text::fontwidth()*(draw_width+5), y , cursor);
}
}
diff --git a/src/client/client.cc b/src/client/client.cc
index 97c0128..85dec27 100644
--- a/src/client/client.cc
+++ b/src/client/client.cc
@@ -25,6 +25,7 @@ namespace client
core::Cvar *cl_framerate = 0;
//--- private definition ------------------------------------------
+
/// client application implementation
class Client : public core::Application
{
@@ -49,10 +50,8 @@ Client app;
void func_r_restart(std::stringstream &args)
{
video::shutdown();
- console::flush();
if (!video::init()) {
- console::flush();
app.quit(1);
}
}
@@ -87,6 +86,7 @@ void Client::init(int count, char **arguments)
// initialize core
core::Cvar::sv_dedicated = core::Cvar::set("sv_private", "0");
core::Application::init(count, arguments);
+ Console::init();
// client variables
core::Cvar *cvar = 0;
@@ -104,12 +104,10 @@ void Client::init(int count, char **arguments)
// Initialize the video subsystem
if (!video::init()) {
- console::flush();
quit(1);
}
// initialize console
- console::init();
chat::init();
// initialize input
@@ -128,6 +126,9 @@ void Client::run()
Uint32 client_framerate = (Uint32)(1000/120);
Uint32 elapsed = 0;
+ console()->flush();
+ console()->clear_notify();
+
while (true) {
Uint32 chrono = SDL_GetTicks();
@@ -155,24 +156,19 @@ void Client::run()
void Client::shutdown()
{
con_print << "^BShutting down client..." << std::endl;
- console::flush();
// remove engine functions
core::Func::remove("r_restart");
chat::shutdown();
- console::shutdown();
- console::flush();
+ Console::shutdown();
input::shutdown();
- console::flush();
video::shutdown();
- console::flush();
core::Application::shutdown();
- console::flush();
quit(0);
}
diff --git a/src/client/console.cc b/src/client/console.cc
index 4c65581..f692db4 100644
--- a/src/client/console.cc
+++ b/src/client/console.cc
@@ -4,12 +4,12 @@
the terms and conditions of the GNU General Public License version 2
*/
+#include "client/console.h"
#include "auxiliary/functions.h"
#include "core/core.h"
#include "filesystem/filesystem.h"
#include "render/render.h"
#include "render/textures.h"
-#include "client/console.h"
#include "client/video.h"
#include "client/keyboard.h"
@@ -19,116 +19,225 @@
namespace client {
-namespace console {
+Console client_console;
-//--- private definition ------------------------------------------
+Console *console() {
+ return &client_console;
+}
+//--- engine functions --------------------------------------------
-/// private client console implementation
-class Console : public sys::ConsoleInterface {
-public:
- /// stream to send normal messages too
- virtual std::ostream & messagestream();
+void func_con_toggle(std::string const &args)
+{
+
+ console()->toggle();
+}
- /// stream to send warning messages too
- virtual std::ostream & warningstream();
+//--- public ------------------------------------------------------
- /// stream to send error messages too
- virtual std::ostream & errorstream();
-
- /// stream to send debug messages too
- virtual std::ostream & debugstream();
+void Console::init()
+{
+ con_print << "^BInitializing console..." << std::endl;
- /// flush buffered messages
- virtual void flush();
+ core::Func *func = core::Func::add("con_toggle", (core::FuncPtr) func_con_toggle);
+ func->set_info("toggle console on or off");
+ console()->load_history();
+}
+
+void Console::shutdown()
+{
+ con_print << "^BShutting down console..." << std::endl;
- /// console text buffer
- std::stringstream buffer;
-};
+ console()->save_history();
-// private client console object
-Console console;
+ // remove engine functions
+ core::Func::remove("con_toggle");
+}
+
+//--- Console -----------------------------------------------------
+
+Console::Console()
+{
+ clear();
+}
-// console text data
-std::deque<std::string> text;
+Console::~Console()
+{
+ history.clear();
+}
-// input history
-std::deque<std::string> history;
-std::deque<std::string>::reverse_iterator history_pos;
-size_t input_pos = 0;
+void Console::clear()
+{
+ console_visible = false;
+ console_scroll = 0;
+ history.clear();
+ history.push_back("");
+ history_pos = history.rbegin();
+ input_pos = 0;
-// console visibility
-bool console_visible = false;
-size_t console_scroll = 0;
+ clear_notify();
-// notifications
-size_t notify_pos = 0;
-std::string notify_text[MAXNOTIFYLINES];
-float notify_time[MAXNOTIFYLINES];
+}
-//--- engine functions --------------------------------------------
+void Console::draw() {
+ if (visible())
+ draw_console();
+ else
+ draw_notify();
+}
-void func_con_toggle(std::string const &args)
+void Console::toggle()
{
+ console_visible = !console_visible;
- std::istringstream argstream(args);
- int i;
+ if (console_visible) {
+ console_scroll = 0;
+ input_pos = 0;
+
+ history_pos = history.rbegin();
+ (*history_pos).clear();
- if (argstream >> i) {
- if (i) console_visible = false; else console_visible = true;
+ SDL_WM_GrabInput(SDL_GRAB_OFF);
+ SDL_ShowCursor(SDL_ENABLE);
+ } else {
+ SDL_WM_GrabInput(SDL_GRAB_ON);
+ SDL_ShowCursor(SDL_DISABLE);
+ clear_notify();
}
- toggle();
+
+ setkeyboardmode(visible());
}
-//--- public ------------------------------------------------------
-
-void clear_notify()
+void Console::keypressed(int key)
{
- for (size_t i=0; i < MAXNOTIFYLINES; i++) {
- notify_text[i].clear();
- notify_time[i] = 0;
+ std::deque<std::string>::reverse_iterator upit;
+
+ switch( key ) {
+ case SDLK_TAB:
+ core::CommandBuffer::complete( (*history_pos), input_pos);
+ break;
+ case SDLK_RETURN:
+ 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;
+ }
+ break;
+ case SDLK_UP:
+ upit = history_pos;
+ ++upit;
+ if (upit != history.rend()) {
+ history_pos = upit;
+ input_pos = (*history_pos).size();
+ }
+ break;
+ case SDLK_DOWN:
+ if (history_pos != history.rbegin()) {
+ --history_pos;
+ input_pos = (*history_pos).size();
+ }
+ break;
+ case SDLK_HOME:
+ input_pos = 0;
+ break;
+ case SDLK_END:
+ input_pos = (*history_pos).size();
+ break;
+ case SDLK_LEFT:
+ if (input_pos > 0)
+ input_pos--;
+ break;
+ case SDLK_RIGHT:
+ if (input_pos < (*history_pos).size())
+ input_pos++;
+ break;
+ case SDLK_BACKSPACE:
+ if ((*history_pos).size() && input_pos) {
+ (*history_pos).erase(input_pos-1, 1);
+ input_pos--;
+ }
+ break;
+ case SDLK_PAGEUP:
+ console_scroll +=5;
+ if (console_scroll > consoleinterface_text.size()) console_scroll = consoleinterface_text.size();
+ break;
+ case SDLK_PAGEDOWN:
+ if (console_scroll > 5) console_scroll -=5;
+ else console_scroll = 0;
+ break;
+ default:
+ if ((key >= 32 ) && (key <175)) {
+ if (input_pos == (*history_pos).size())
+ (*history_pos) += (char)key;
+ else
+ (*history_pos).insert(input_pos, 1, (char)key);
+ input_pos++;
+ }
+ break;
}
+
+
}
-void init()
+void Console::save_history()
{
- con_print << "^BInitializing console..." << std::endl;
-
- console_visible = false;
-
- // add engine functions
- core::Func *func = core::Func::add("con_toggle", (core::FuncPtr) func_con_toggle);
- func->set_info("toggle console on or off");
- clear_notify();
- text.clear();
- console_scroll = 0;
+ if (history.size() <= 1)
+ return;
- history.clear();
- history.push_back("");
- history_pos = history.rbegin();
- input_pos = 0;
+ std::string filename(filesystem::writedir);
+ filename.append("history.txt");
+ std::ofstream ofs(filename.c_str());
- load_history();
+ if (!ofs.is_open()) {
+ con_warn << "Could not write " << filename << std::endl;
+ return;
+ }
+ std::deque<std::string>::iterator it;
+ size_t l = 1;
+ for (it = history.begin(); it != history.end(); it++) {
+ if (l < history.size())
+ ofs << (*it) << std::endl;
+ l++;
+ }
+
+ ofs.close();
}
-void shutdown()
+void Console::load_history()
{
- con_print << "^BShutting down console..." << std::endl;
-
- save_history();
+ std::string filename(filesystem::writedir);
+ filename.append("history.txt");
+ std::ifstream ifs(filename.c_str(), std::ifstream::in);
- // remove engine functions
- //core::Func::remove("con_toggle");
-
- text.clear();
- console_scroll = 0;
+ if (!ifs.is_open()) {
+ con_warn << "Could not read " << filename << std::endl;
+ return;
+ }
history.clear();
+ char line[MAXCMDSIZE];
+ while (ifs.getline(line, MAXCMDSIZE-1)) {
+ history.push_back(line);
+ }
+
+ ifs.close();
+
+ history.push_back("");
+ history_pos = history.rbegin();
input_pos = 0;
}
-void draw_notify()
+void Console::draw_notify()
{
using namespace render;
@@ -150,6 +259,7 @@ void draw_notify()
const char *c = linedata.c_str();
char pen = 'N';
+ char wordpen = 'N';
while (*c) {
@@ -170,7 +280,7 @@ void draw_notify()
h += Text::fontheight();
line.clear();
line += '^';
- line += pen;
+ line += wordpen;
line_length = 0;
}
}
@@ -180,6 +290,7 @@ void draw_notify()
word.clear();
word_length = 0;
+ wordpen = pen;
// new line
if (*c == '\n' ) {
@@ -205,7 +316,7 @@ void draw_notify()
h += Text::fontheight();
line.clear();
line += '^';
- line += pen;
+ line += wordpen;
line_length = 0;
}
@@ -214,6 +325,7 @@ void draw_notify()
word.clear();
word_length = 0;
+ wordpen = pen;
}
}
@@ -225,7 +337,7 @@ void draw_notify()
}
}
-void draw_console()
+void Console::draw_console()
{
using namespace render;
@@ -251,17 +363,17 @@ void draw_console()
gl::color(0.0f, 1.0f, 0.0f, 0.5f);
Text::draw(video::width-Text::fontwidth()*(version.size()+1), video::height*con_height-Text::fontheight()-4, version);
- // draw the console text
- if (console_scroll > text.size())
- console_scroll = text.size();
+ // draw the console consoleinterface_text
+ if (console_scroll > consoleinterface_text.size())
+ console_scroll = consoleinterface_text.size();
size_t height = (size_t) (video::height * con_height / Text::fontheight()) -1;
size_t width = (size_t) ((video::width-8) / Text::fontwidth());
- size_t bottom = text.size() - console_scroll;
+ size_t bottom = consoleinterface_text.size() - console_scroll;
size_t current_line = 0;
std::deque<std::string> lines;
- for (std::deque<std::string>::iterator it = text.begin(); it != text.end() && current_line < bottom; it++) {
+ for (std::deque<std::string>::iterator it = consoleinterface_text.begin(); it != consoleinterface_text.end() && current_line < bottom; it++) {
if (current_line >= bottom - height) {
std::string linedata(*it);
linedata += '\n';
@@ -274,6 +386,7 @@ void draw_console()
const char *c = linedata.c_str();
char pen = 'N';
+ char wordpen = 'N';
while (*c) {
@@ -293,7 +406,7 @@ void draw_console()
lines.push_back(line);
line.clear();
line += '^';
- line += pen;
+ line += wordpen;
line_length = 0;
}
}
@@ -303,6 +416,7 @@ void draw_console()
word.clear();
word_length = 0;
+ wordpen = pen;
// new line
if (*c == '\n' ) {
@@ -326,7 +440,7 @@ void draw_console()
lines.push_back(line);
line.clear();
line += '^';
- line += pen;
+ line += wordpen;
line_length = 0;
}
@@ -335,6 +449,7 @@ void draw_console()
word.clear();
word_length = 0;
+ wordpen = pen;
}
}
@@ -354,233 +469,86 @@ void draw_console()
// draw the console input
- size_t draw_pos = 0;
y = video::height*con_height - Text::fontheight() - 4;
-
- while (input_pos - draw_pos > width)
- draw_pos += 2;
-
Text::draw(4, y, "^B>");
- Text::draw(4+Text::fontwidth(), y , (*history_pos).substr(draw_pos, width-1));
- // draw cursor
- if ((core::application()->time() - ::floorf(core::application()->time())) < 0.5f) {
- std::string cursor("^B_");
- Text::draw(4+Text::fontwidth()*(input_pos-draw_pos+1), y , cursor);
- }
-
-}
-
-void draw(){
- if (visible())
- draw_console();
- else
- draw_notify();
-}
+ std::string firstpart((*history_pos).substr(0, input_pos));
+ size_t draw_width = 0;
+ const char *c = firstpart.c_str();
-void flush()
-{
- char line[MAXCMDSIZE];
- while(console.buffer.getline(line, MAXCMDSIZE-1)) {
- while (text.size() >= MAXCONLINES) {
- text.pop_front();
+ while (*c) {
+ if (aux::is_color_code(c)) {
+ c++;
+ } else {
+ draw_width++;
}
- text.push_back(std::string(line));
-
- // save notification
- notify_text[notify_pos] = line;
- notify_time[notify_pos] = core::application()->time();
- notify_pos = (notify_pos+1) % MAXNOTIFYLINES;
-
- // print to stdout
- std::cout << line << std::endl;
+ c++;
}
-
- console.buffer.clear();
-}
-
-void toggle()
-{
- console_visible = !console_visible;
-
- if (console_visible) {
- console_scroll = 0;
- input_pos = 0;
- history_pos = history.rbegin();
- (*history_pos).clear();
-
- SDL_WM_GrabInput(SDL_GRAB_OFF);
- SDL_ShowCursor(SDL_ENABLE);
- } else {
- SDL_WM_GrabInput(SDL_GRAB_ON);
- SDL_ShowCursor(SDL_DISABLE);
- clear_notify();
+ c = firstpart.c_str();
+ while (*c && draw_width > width - 2) {
+ if (aux::is_color_code(c)) {
+ c++;
+ Text::setcolor(*c);
+ } else {
+ draw_width--;
+ }
+ c++;
}
-
- setkeyboardmode(console::visible());
-}
-
-void keypressed(int key)
-{
- std::deque<std::string>::reverse_iterator upit;
-
- switch( key ) {
- case SDLK_TAB:
- core::CommandBuffer::complete( (*history_pos), input_pos);
- break;
- case SDLK_RETURN:
- 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);
+ if (*c) {
+ Text::draw(4+Text::fontwidth(), y, c);
+ }
- history.push_back("");
- history_pos = history.rbegin();
- input_pos = 0;
- }
- break;
- case SDLK_UP:
- upit = history_pos;
- ++upit;
- if (upit != history.rend()) {
- history_pos = upit;
- input_pos = (*history_pos).size();
- }
- break;
- case SDLK_DOWN:
- if (history_pos != history.rbegin()) {
- --history_pos;
- input_pos = (*history_pos).size();
+ if (input_pos < (*history_pos).size()) {
+ // FIXME limit to width
+ if (input_pos > 1 && aux::is_color_code((*history_pos).c_str() + input_pos -1)) {
+ Text::setcolor((*history_pos)[input_pos]);
}
- break;
- case SDLK_HOME:
- input_pos = 0;
- break;
- case SDLK_END:
- input_pos = (*history_pos).size();
- break;
- case SDLK_LEFT:
- if (input_pos > 0)
- input_pos--;
- break;
- case SDLK_RIGHT:
- if (input_pos < (*history_pos).size())
- input_pos++;
- break;
- case SDLK_BACKSPACE:
- if ((*history_pos).size() && input_pos) {
- (*history_pos).erase(input_pos-1, 1);
- input_pos--;
- }
- break;
- case SDLK_PAGEUP:
- console_scroll +=5;
- if (console_scroll > text.size()) console_scroll = text.size();
- break;
- case SDLK_PAGEDOWN:
- if (console_scroll > 5) console_scroll -=5;
- else console_scroll = 0;
- break;
- default:
- if ((key >= 32 ) && (key <175)) {
- if (input_pos == (*history_pos).size())
- (*history_pos) += (char)key;
- else
- (*history_pos).insert(input_pos, 1, (char)key);
- input_pos++;
- }
- break;
+ c = (*history_pos).c_str() + input_pos;
+ Text::draw(4+Text::fontwidth()*(draw_width+1), y, c);
}
-
-}
-
-bool visible()
-{
- return console_visible;
-}
-
-void save_history()
-{
-
- if (history.size() <= 1)
- return;
-
- std::string filename(filesystem::writedir);
- filename.append("history.txt");
- std::ofstream ofs(filename.c_str());
-
- if (!ofs.is_open()) {
- con_warn << "Could not write " << filename << std::endl;
- return;
- }
- std::deque<std::string>::iterator it;
- size_t l = 1;
- for (it = history.begin(); it != history.end(); it++) {
- if (l < history.size())
- ofs << (*it) << std::endl;
- l++;
+ // draw cursor
+ if ((core::application()->time() - ::floorf(core::application()->time())) < 0.5f) {
+ std::string cursor("^B_");
+ Text::draw(4+Text::fontwidth()*(draw_width+1), y , cursor);
}
- ofs.close();
}
-void load_history()
-{
- std::string filename(filesystem::writedir);
- filename.append("history.txt");
- std::ifstream ifs(filename.c_str(), std::ifstream::in);
- if (!ifs.is_open()) {
- con_warn << "Could not read " << filename << std::endl;
- return;
- }
-
- history.clear();
- char line[MAXCMDSIZE];
- while (ifs.getline(line, MAXCMDSIZE-1)) {
- history.push_back(line);
+void Console::clear_notify()
+{
+ for (size_t i=0; i < MAXNOTIFYLINES; i++) {
+ notify_text[i].clear();
+ notify_time[i] = 0;
}
-
- ifs.close();
-
- history.push_back("");
- history_pos = history.rbegin();
- input_pos = 0;
+ notify_pos = 0;
}
-//--- private -----------------------------------------------------
void Console::flush()
{
- console::flush();
-}
+ char line[MAXCMDSIZE];
-std::ostream & Console::messagestream()
-{
- return (buffer << "^N");
-}
+ while(consoleinterface_buffer.getline(line, MAXCMDSIZE-1)) {
-std::ostream & Console::warningstream()
-{
- return (buffer << "^W");
-}
+ while (consoleinterface_text.size() >= sys::MAXCONLINES) {
+ consoleinterface_text.pop_front();
+ }
+ consoleinterface_text.push_back(std::string(line));
-std::ostream & Console::errorstream()
-{
- return (buffer << "^R");
-}
+ // save notification
+ notify_text[notify_pos] = line;
+ notify_time[notify_pos] = core::application()->time();
+ notify_pos = (notify_pos+1) % MAXNOTIFYLINES;
-std::ostream & Console::debugstream()
-{
- return (buffer << "^D");
+ // print to stdout
+ print_ansi(line);
+ std::cout << std::endl;
+ }
+
+ consoleinterface_buffer.clear();
}
-} // namespace console
-
} // namespace client
diff --git a/src/client/console.h b/src/client/console.h
index dc831b7..2f8d6a0 100644
--- a/src/client/console.h
+++ b/src/client/console.h
@@ -9,54 +9,70 @@
#include "sys/consoleinterface.h"
-#include <sstream>
-#include <deque>
+namespace client {
-const size_t MAXCONLINES = 2048;
-const size_t MAXHISTOLINES = 512;
const size_t MAXNOTIFYLINES = 3;
+const size_t MAXHISTOLINES = 512;
-namespace client {
+/// client console implementation
+class Console : public sys::ConsoleInterface {
+public:
+ Console();
+ virtual ~Console();
-/// the client console
-namespace console {
+ virtual void flush();
-/// initialize client console
-/** Adds the engine functions for the client console
- */
-void init();
+ void draw_console();
-/// shutdown the client console
-/** Removes the engine functions for the client console
- */
-void shutdown();
+ void draw_notify();
-/// flush buffer messages and print to stdout
-void flush();
-
-/// draw the console
-void draw();
+ /// clear notifications
+ void clear_notify();
-/// toggle the console on or off
-void toggle();
+ /// draw client notifications or console text
+ void draw();
-/// handle keyboard input
-void keypressed(int key);
+ /// toggle the console on or off
+ void toggle();
-/// true of the console is visible
-bool visible();
+ /// handle keyboard input
+ void keypressed(int key);
-/// load input history
-void load_history();
+ /// true of the console is visible
+ inline bool visible() { return console_visible; }
-/// save input history
-void save_history();
+ /// load input history
+ void load_history();
-extern size_t notify_pos;
-extern std::string notify_text[MAXNOTIFYLINES];
-extern float notify_time[MAXNOTIFYLINES];
+ /// save input history
+ void save_history();
-}
+ /// clear console
+ void clear();
+
+ /// initialize client console
+ static void init();
+
+ /// shutdown the client console
+ static void shutdown();
+
+private:
+ // notifications
+ size_t notify_pos;
+ std::string notify_text[MAXNOTIFYLINES];
+ float notify_time[MAXNOTIFYLINES];
+
+ // input history
+ std::deque<std::string> history;
+ std::deque<std::string>::reverse_iterator history_pos;
+ size_t input_pos;
+
+ bool console_visible;
+ size_t console_scroll;
+
+};
+
+Console *console();
}
diff --git a/src/client/input.cc b/src/client/input.cc
index f40591c..22db6bc 100644
--- a/src/client/input.cc
+++ b/src/client/input.cc
@@ -221,31 +221,31 @@ void frame(float seconds)
mouse_y = event.motion.y;
break;
case SDL_MOUSEBUTTONDOWN:
- if (!console::visible() && core::application()->connected() && core::localcontrol())
+ if (!console()->visible() && core::application()->connected() && core::localcontrol())
mousebuttonpressed(event.button);
break;
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_PRINT) {
video::screenshot();
- } else if (!chat::visible() && !console::visible() &&
+ } else if (!chat::visible() && !console()->visible() &&
core::application()->connected() && core::localcontrol())
// send key events to the game world
keyreleased(event.key.keysym);
break;
case SDL_KEYDOWN:
- if (chat::visible() && !console::visible() && (event.key.keysym.sym == SDLK_ESCAPE)) {
+ if (chat::visible() && !console()->visible() && (event.key.keysym.sym == SDLK_ESCAPE)) {
chat::toggle();
} else if (event.key.keysym.sym == '`' || event.key.keysym.sym == '~' || (event.key.keysym.sym == SDLK_ESCAPE)) {
//last_control = 0;
- console::toggle();
+ console()->toggle();
- if (console::visible() && chat::visible())
+ if (console()->visible() && chat::visible())
chat::toggle();
- } else if (console::visible()) {
+ } else if (console()->visible()) {
// send key events to the console
- console::keypressed(translate_keysym(event.key.keysym));
+ console()->keypressed(translate_keysym(event.key.keysym));
} else if (chat::visible()) {
if(event.key.keysym.sym == SDLK_ESCAPE) {
@@ -270,7 +270,7 @@ void frame(float seconds)
}
- if (!console::visible() && core::application()->connected() && core::localcontrol()) {
+ if (!console()->visible() && core::application()->connected() && core::localcontrol()) {
if (cl_mousecontrol->value()) {
// the mouse will not react if it is in the deadzone
@@ -302,8 +302,8 @@ void frame(float seconds)
}
if ((camera::mode == camera::Track) || (camera::mode == camera::Cockpit)) {
- local_direction = mouse_direction;
- local_pitch = mouse_pitch;
+ local_direction = mouse_direction * math::absf(mouse_direction);
+ local_pitch = mouse_pitch * math::absf(mouse_pitch);
} else if (camera::mode == camera::Free) {
// squared values to smoothen camera movement
camera::set_direction( -mouse_direction * math::absf(mouse_direction));
diff --git a/src/client/view.cc b/src/client/view.cc
index 63c373e..e2c8687 100644
--- a/src/client/view.cc
+++ b/src/client/view.cc
@@ -128,7 +128,7 @@ void draw_status()
{
using namespace render;
- if (console::visible())
+ if (console()->visible())
return;
// print the status in the upper left corner
@@ -171,7 +171,7 @@ void draw_status()
void draw_cursor()
{
- if (!core::localcontrol() || console::visible())
+ if (!core::localcontrol() || console()->visible())
return;
float crosshair_size = 48.0f;
@@ -222,7 +222,7 @@ void frame(float seconds)
fps = 9999;
// flush console messages
- console::flush();
+ console()->flush();
// Clear the color and depth buffers.
gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -234,7 +234,7 @@ void frame(float seconds)
gl::loadidentity();
// FIXME width must always be one
- const float frustumsize = 0.5f;
+ const float frustumsize = 0.25f;
gl::frustum(-frustumsize*video::aspect, frustumsize*video::aspect, -frustumsize, frustumsize, 1.0f, 1024.0f);
gl::matrixmode(GL_MODELVIEW); // map world to screen coordinates
@@ -263,7 +263,7 @@ void frame(float seconds)
// draw text elements
Text::setfont("bitmaps/fonts/console", 12, 18);
- console::draw();
+ console()->draw();
chat::draw();
Text::setfont("bitmaps/fonts/gui", 16, 24);
diff --git a/src/core/application.cc b/src/core/application.cc
index 79f4a28..67bb952 100644
--- a/src/core/application.cc
+++ b/src/core/application.cc
@@ -100,10 +100,10 @@ Application::Application()
application_game = 0;
#ifndef _WIN32
- //sys::signal(SIGHUP, signal_handler);
- //sys::signal(SIGINT, signal_handler);
- //sys::signal(SIGQUIT, signal_handler);
- //sys::signal(SIGTERM, signal_handler);
+ sys::signal(SIGHUP, signal_handler);
+ sys::signal(SIGINT, signal_handler);
+ sys::signal(SIGQUIT, signal_handler);
+ sys::signal(SIGTERM, signal_handler);
#endif
}
@@ -117,7 +117,7 @@ void Application::init(int count, char **arguments)
{
con_debug << "Debug messages enabled\n";
con_print << "^BInitializing core...\n";
-
+
filesystem::init();
CommandBuffer::init();
@@ -157,6 +157,14 @@ void Application::init(int count, char **arguments)
Cvar::net_framerate->set_info("[int] network framerate in frames/sec");
#ifdef _WIN32
+ Cvar::con_ansi = Cvar::get("con_ansi", "0", Cvar::Archive);
+#else
+ Cvar::con_ansi = Cvar::get("con_ansi", "1", Cvar::Archive);
+#endif
+ Cvar::con_ansi->set_info("[bool] console ANSI colors");
+ sys::ConsoleInterface::instance()->set_ansi(Cvar::con_ansi->value());
+
+#ifdef _WIN32
// Initialize win32 socket library
WSADATA wsa_data;
WORD wsa_version = MAKEWORD(2, 0);
@@ -217,6 +225,8 @@ void Application::shutdown()
void Application::quit(int status)
{
+ console()->flush();
+
sys::quit(status);
}
@@ -264,6 +274,8 @@ void Application::disconnect()
void Application::frame(float seconds)
{
+ console()->flush();
+
// execute commands in the buffer
CommandBuffer::exec();
@@ -278,9 +290,11 @@ void Application::frame(float seconds)
// run a game interface frame
application_game->frame(seconds);
-
+
if (!application_game->running())
disconnect();
+
+ console()->flush();
}
void Application::save_config()
diff --git a/src/core/application.h b/src/core/application.h
index 01f34cf..bec53d9 100644
--- a/src/core/application.h
+++ b/src/core/application.h
@@ -7,6 +7,7 @@
#ifndef __INCLUDED_CORE_APPLICATION_H__
#define __INCLUDED_CORE_APPLICATION_H__
+#include "sys/sys.h"
#include "core/commandbuffer.h"
#include "core/netserver.h"
#include "core/netconnection.h"
@@ -86,6 +87,9 @@ inline Application *application() { return Application::instance(); }
/// pointer to the current GameInterface
inline GameInterface *game() { return Application::instance()->game(); }
+/// pointer to the console
+inline sys::ConsoleInterface *console() { return sys::ConsoleInterface::instance(); };
+
} // namespace core
#endif // __INCLUDED_CORE_APPLICATION_H__
diff --git a/src/core/cvar.cc b/src/core/cvar.cc
index 7593ac3..f8ea746 100644
--- a/src/core/cvar.cc
+++ b/src/core/cvar.cc
@@ -17,6 +17,7 @@
namespace core
{
+Cvar *Cvar::con_ansi = 0;
Cvar *Cvar::sv_dedicated = 0;
Cvar *Cvar::sv_private = 0;
Cvar *Cvar::sv_framerate = 0;
diff --git a/src/core/cvar.h b/src/core/cvar.h
index 4125d3c..69fcae1 100644
--- a/src/core/cvar.h
+++ b/src/core/cvar.h
@@ -113,6 +113,8 @@ public:
static Cvar *sv_private; // client with private server
static Cvar *sv_framerate; // server framerate
+ static Cvar *con_ansi; // console ANSI colors
+
static Cvar *net_host; // network server ip (default binds to all interfaces)
static Cvar *net_port; // network port
static Cvar *net_maxclients;// maximum number of connected clients
diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc
index 1d022c5..6090a52 100644
--- a/src/core/gameconnection.cc
+++ b/src/core/gameconnection.cc
@@ -88,9 +88,7 @@ void GameConnection::frame(float seconds)
return;
}
- if (!Cvar::sv_dedicated->value()) {
- update_clientstate(seconds);
- }
+ update_clientstate(seconds);
connection_network->frame(seconds);
diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc
index 1f4a5cd..f50c1cc 100644
--- a/src/core/gameinterface.cc
+++ b/src/core/gameinterface.cc
@@ -18,6 +18,8 @@
namespace core
{
+const float MIN_DELTA = 10e-10;
+
void func_list_model(std::string const &args)
{
model::Model::list();
@@ -97,12 +99,10 @@ void GameInterface::clear()
game_clientframetime = 0;
}
-void GameInterface::reset_clientstate(float servertime)
+void GameInterface::reset_clientstate(float timestamp, float prevtimestamp)
{
- game_previousframetime = game_serverframetime;
- game_clientframetime = game_serverframetime;
-
- game_serverframetime = servertime;
+ game_previousframetime = prevtimestamp;
+ game_serverframetime = timestamp;
std::map<unsigned int, core::Entity *>::iterator it;
for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) {
@@ -112,121 +112,130 @@ void GameInterface::reset_clientstate(float servertime)
if (entity->state() && !(entity->flags() & core::Entity::Static))
entity->state()->assign(entity);
}
-}
-
-void GameInterface::update_clientstate(float seconds)
-{
- game_clientframetime += seconds;
- if (game_clientframetime > game_serverframetime)
+ if ( game_clientframetime < game_previousframetime)
+ game_clientframetime = game_previousframetime;
+ else if ( game_clientframetime > game_serverframetime)
game_clientframetime = game_serverframetime;
- std::map<unsigned int, Entity *>::iterator it;
- for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) {
+}
+
- Entity *entity = (*it).second;
+void GameInterface::update_entity_clientstate(Entity *entity)
+{
+ if (!entity->state()) {
+ entity->entity_clientstate = new core::ClientState(entity);
+ entity->entity_clientstate->assign(entity);
+ }
- // update client state
- if (!entity->state()) {
- entity->entity_clientstate = new core::ClientState(entity);
- }
+ if (!(entity->flags() & core::Entity::Static))
+ return;
+
+ if (game_clientframetime < game_serverframetime) {
if (!(entity->flags() & core::Entity::Static)) {
-
+
// clientstate location
entity->state()->state_location = entity->state()->previouslocation() +
- (entity->location() - entity->state()->previouslocation()) * core::game()->timeoffset();
-
- if (core::game()->clientframetime() < core::game()->serverframetime()) {
-
- // http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/
- float cosangle;
- float angle;
- float side;
- float u;
-
- math::Vector3f n;
- math::Vector3f p;
-
- // clientstate axis: pitch
-
- // project entity->axis().up() into the plane with entity->state()->axis()->left() normal
- n = entity->state()->axis().left();
- p = entity->axis().up();
- u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
- p = entity->axis().up() + u * n;
-
- side = entity->state()->axis().forward().x * p.x +
- entity->state()->axis().forward().y * p.y +
- entity->state()->axis().forward().z * p.z;
-
- if (fabs(side) > 0.00005f) {
- cosangle = math::dotproduct(p, entity->state()->axis().up());
-
- if (fabs(cosangle) < 0.99995f) {
- angle = acos(cosangle) * 180.0f / M_PI;
- angle = math::sgnf(side) * angle * seconds /
- (core::game()->serverframetime() - core::game()->clientframetime());
-
- entity->state()->state_axis.change_pitch(-angle);
- }
+ (entity->location() - entity->state()->previouslocation()) * timeoffset();
+
+ // http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/
+ float cosangle;
+ float angle;
+ float side;
+ float u;
+ float l;
+
+ math::Vector3f n;
+ math::Vector3f p;
+
+ entity->state()->state_axis.assign(entity->state()->previousaxis());
+ // clientstate axis: pitch
+
+ // project entity->axis().up() into the plane with entity->state()->axis()->left() normal
+ n = entity->state()->axis().left();
+ p = entity->axis().up();
+ u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
+ p = entity->axis().up() + u * n;
+
+ side = entity->state()->axis().forward().x * p.x +
+ entity->state()->axis().forward().y * p.y +
+ entity->state()->axis().forward().z * p.z;
+
+ l = p.length();
+ if ((fabs(side) - MIN_DELTA > 0)) {
+ cosangle = math::dotproduct(p, entity->state()->axis().up());
+ if (fabs(cosangle) + MIN_DELTA < 1 ) {
+ angle = acos(cosangle) * 180.0f / M_PI;
+ angle = math::sgnf(side) * angle * timeoffset();
+ entity->state()->state_axis.change_pitch(-angle);
}
-
- // clientstate axis: direction
-
- // project entity->axis().forward() into the plane with entity->state()->axis().up() normal
- n = entity->state()->axis().up();
- p = entity->axis().forward();
- u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
- p = entity->axis().forward() + u * n;
-
- side = entity->state()->axis().left().x * p.x +
- entity->state()->axis().left().y * p.y +
- entity->state()->axis().left().z * p.z;
-
- if (fabs(side) > 0.00005f) {
- cosangle = math::dotproduct(p, entity->state()->axis().forward());
- if (fabs(cosangle) < 0.99995f) {
- angle = acos(cosangle) * 180.0f / M_PI;
- angle = math::sgnf(side) * angle * seconds /
- (core::game()->serverframetime() - core::game()->clientframetime());
-
- entity->state()->state_axis.change_direction(angle);
- }
+ }
+
+ // clientstate axis: direction
+
+ // project entity->axis().forward() into the plane with entity->state()->axis().up() normal
+ n = entity->state()->axis().up();
+ p = entity->axis().forward();
+ u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
+ p = entity->axis().forward() + u * n;
+
+ side = entity->state()->axis().left().x * p.x +
+ entity->state()->axis().left().y * p.y +
+ entity->state()->axis().left().z * p.z;
+
+ l = p.length();
+ if ((fabs(side) - MIN_DELTA > 0)) {
+ cosangle = math::dotproduct(p, entity->state()->axis().forward());
+ if (fabs(cosangle) + MIN_DELTA < 1 ) {
+ angle = acos(cosangle) * 180.0f / M_PI;
+ angle = math::sgnf(side) * angle * timeoffset();
+ entity->state()->state_axis.change_direction(angle);
}
-
- // clientstate axis: roll
-
- // project entity->axis().up() into the plane with entity->state()->axis().forward() normal
- n = entity->state()->axis().forward();
- p = entity->axis().up();
- u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
- p = entity->axis().up() + u * n;
-
- side = entity->state()->axis().left().x * p.x +
- entity->state()->axis().left().y * p.y +
- entity->state()->axis().left().z * p.z;
-
- if (fabs(side) > 0.00005f) {
- cosangle = math::dotproduct(p, entity->state()->axis().up());
+ }
+
+ // clientstate axis: roll
+
+ // project entity->axis().up() into the plane with entity->state()->axis().forward() normal
+ n = entity->state()->axis().forward();
+ p = entity->axis().up();
+ u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
+ p = entity->axis().up() + u * n;
+
+ side = entity->state()->axis().left().x * p.x +
+ entity->state()->axis().left().y * p.y +
+ entity->state()->axis().left().z * p.z;
+
+ l = p.length();
+ if ((fabs(side) - MIN_DELTA > 0)) {
+ cosangle = math::dotproduct(p, entity->state()->axis().up());
+ if (fabs(cosangle) + MIN_DELTA < 1 ) {
angle = acos(cosangle) * 180.0f / M_PI;
- if (fabs(cosangle) < 0.99995f) {
- angle = math::sgnf(side) * angle * seconds /
- (core::game()->serverframetime() - core::game()->clientframetime());
-
- entity->state()->state_axis.change_roll(angle);
- }
+ angle = math::sgnf(side) * angle * timeoffset();
+ entity->state()->state_axis.change_roll(angle);
}
-
}
- }
+ }
+
+ } else {
+ entity->state()->assign(entity);
+ }
+}
+void GameInterface::update_clientstate(float seconds)
+{
+ std::map<unsigned int, core::Entity *>::iterator it;
+ for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) {
+ update_entity_clientstate((*it).second);
}
}
float GameInterface::timeoffset() {
+ if (game_clientframetime > game_serverframetime)
+ return 1;
+
float d = game_serverframetime - game_previousframetime;
if (d <= 0)
return 0;
diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h
index 0edcb1b..19c6886 100644
--- a/src/core/gameinterface.h
+++ b/src/core/gameinterface.h
@@ -52,11 +52,13 @@ public:
void clear();
/// reset the client state
- void reset_clientstate(float servertime);
+ void reset_clientstate(float timestamp, float prevtimestamp);
/// update the client state timers
void update_clientstate(float seconds);
+ void update_entity_clientstate(Entity *entity);
+
/*----- virtual mutators ------------------------------------------ */
/// run one game time frame
diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc
index 11a8b13..fb828e2 100644
--- a/src/core/gameserver.cc
+++ b/src/core/gameserver.cc
@@ -34,6 +34,7 @@ GameServer::GameServer() : GameInterface()
server_instance = this;
server_network = 0;
server_time = 0;
+ server_previoustime = 0;
server_frametime = 0.0f;
server_maxplayerid = 1;
@@ -278,7 +279,7 @@ void GameServer::frame(float seconds)
// copy the previous entity state to the client state
if (!Cvar::sv_dedicated->value()) {
- reset_clientstate(server_time);
+ reset_clientstate(server_time, server_previoustime);
}
// run a time frame on each entity
@@ -308,7 +309,7 @@ void GameServer::frame(float seconds)
// start server frame
std::ostringstream framehdr;
framehdr.str("");
- framehdr << "frame " << server_time << "\n";
+ framehdr << "frame " << server_time << " " << server_previoustime << "\n";
server_network->broadcast(framehdr.str());
std::map<unsigned int, Entity *>::iterator it;
@@ -377,7 +378,12 @@ void GameServer::frame(float seconds)
}
}
+ if (!Cvar::sv_dedicated->value()) {
+ update_clientstate(0);
+ }
+
server_frametime = 0;
+ server_previoustime = server_time;
}
diff --git a/src/core/gameserver.h b/src/core/gameserver.h
index 4fb9c47..bcd9cc3 100644
--- a/src/core/gameserver.h
+++ b/src/core/gameserver.h
@@ -76,6 +76,7 @@ private:
unsigned int server_maxplayerid;
float server_frametime;
float server_time;
+ float server_previoustime;
};
inline GameServer *server() { return GameServer::instance(); }
diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc
index 2bcd6dc..22614d2 100644
--- a/src/core/netconnection.cc
+++ b/src/core/netconnection.cc
@@ -307,9 +307,9 @@ void NetConnection::parse_incoming_message(const std::string & message)
} else if (command == "ping") {
} else if (command == "frame") {
- float timestamp;
- if (msgstream >> timestamp) {
- game()->reset_clientstate(timestamp);
+ float timestamp, prevtimestamp;
+ if ((msgstream >> timestamp) && (msgstream >> prevtimestamp)) {
+ game()->reset_clientstate(timestamp, prevtimestamp);
}
} else if (command == "die") {
@@ -329,16 +329,16 @@ void NetConnection::parse_incoming_message(const std::string & message)
switch (type)
{
case Entity::Default:
- new Entity(msgstream);
+ game()->update_entity_clientstate(new Entity(msgstream));
break;
case Entity::Dynamic:
- new EntityDynamic(msgstream);
+ game()->update_entity_clientstate(new EntityDynamic(msgstream));
break;
case Entity::Controlable:
- new EntityControlable(msgstream);
+ game()->update_entity_clientstate(new EntityControlable(msgstream));
break;
case Entity::Globe:
- new EntityGlobe(msgstream);
+ game()->update_entity_clientstate(new EntityGlobe(msgstream));
break;
default:
con_warn << "Create for unknown entity type " << type << std::endl;
diff --git a/src/game/game.cc b/src/game/game.cc
index d2e5242..aa78e41 100644
--- a/src/game/game.cc
+++ b/src/game/game.cc
@@ -96,7 +96,7 @@ void func_buy(core::Player *player, std::string const &args)
player->player_control = new Ship(player, shipmodel);
player->control()->entity_color = player->color();
- core::server()->broadcast("^N" + player->name() + " ^Bpurchased " + aux::article(shipmodel->name()));
+ core::server()->broadcast("^B" + player->name() + " ^Bpurchased " + aux::article(shipmodel->name()));
player->player_dirty = true;
} else {
core::server()->send(player, "Usage: buy <" + helpstr + "^N>");
diff --git a/src/math/functions.cc b/src/math/functions.cc
index e048659..40f0f4e 100644
--- a/src/math/functions.cc
+++ b/src/math/functions.cc
@@ -9,6 +9,8 @@
namespace math
{
+const float DELTA = 10e-10;
+
float min(float a, float b)
{
return (a < b ? a : b);
@@ -42,9 +44,9 @@ unsigned randomi(const unsigned int max)
float degrees180f(float angle)
{
float r = angle;
- while (r < -180.0f)
+ while (r - DELTA < -180.0f)
r += 360.0f;
- while (r > 180.0f)
+ while (r + DELTA > 180.0f)
r -= 360.0f;
return r;
}
@@ -52,9 +54,9 @@ float degrees180f(float angle)
float degrees360f(float angle)
{
float r = angle;
- while (r < 0.0f)
+ while (r - DELTA < 0)
r += 360.0f;
- while (r > 360.0f)
+ while (r + DELTA > 360.0f)
r -= 360.0f;
return r;
}
diff --git a/src/render/draw.cc b/src/render/draw.cc
index 7c35bf3..9292460 100644
--- a/src/render/draw.cc
+++ b/src/render/draw.cc
@@ -431,7 +431,7 @@ void draw_pass_model_fx()
t = (core::application()->time() + entity->state()->fuzz() - (*lit)->offset()) * (*lit)->frequency();
if (!(*lit)->strobe() || (( t - floorf(t)) <= (*lit)->time())) {
- math::Vector3f location = entity->state()->location() + (entity->axis() * (*lit)->location());
+ math::Vector3f location = entity->state()->location() + (entity->state()->axis() * (*lit)->location());
float light_size = 0.0625 * (*lit)->radius();
if ((*lit)->render_texture != flare_texture) {
@@ -482,7 +482,7 @@ void draw_pass_model_fx()
t = 0.75f + t/2;
for(std::list<model::Engine*>::iterator eit = entity->model()->model_engine.begin(); eit != entity->model()->model_engine.end(); eit++) {
- math::Vector3f location = entity->state()->location() + (entity->axis() * (*eit)->location());
+ math::Vector3f location = entity->state()->location() + (entity->state()->axis() * (*eit)->location());
float engine_size = 0.0625 * (*eit)->radius() * t;
math::Color color(1.0f, 0.0f, 0.0f, 0.9f * u);
diff --git a/src/server/console.cc b/src/server/console.cc
index b5d0aaf..4b7992e 100644
--- a/src/server/console.cc
+++ b/src/server/console.cc
@@ -11,86 +11,21 @@
namespace server {
-namespace console {
+Console server_console;
-//--- private definition ------------------------------------------
-
-/// server console implementation
-class Console : public sys::ConsoleInterface {
-public:
- /// stream to send normal messages too
- virtual std::ostream & messagestream();
-
- /// stream to send warning messages too
- virtual std::ostream & warningstream();
-
- /// stream to send warning messages too
- virtual std::ostream & errorstream();
-
- /// stream to send debug messages too
- virtual std::ostream & debugstream();
-
- /// flush does nothing in this implementation
- virtual void flush();
-
- unsigned long ping;
-
-};
-
-// private console object
-Console console;
-
-//--- engine functions --------------------------------------------
-
-extern "C" void func_con_ping(std::stringstream &args)
+Console *console()
{
- con_print << "Ping!" << std::endl;
- console.ping++;
+ return (&server_console);
}
-
-//--- public ------------------------------------------------------
-
-void init()
+void Console::init()
{
con_print << "Initializing console..." << std::endl;
-
- // register our engine functions
- core::Func::add("con_ping", (core::FuncPtr) func_con_ping);
}
-void shutdown()
+void Console::shutdown()
{
con_print << "Shutting down console..." << std::endl;
-
- // unregister our engine functions
- core::Func::remove("con_ping");
-}
-
-//--- private -----------------------------------------------------
-
-void Console::flush()
-{
}
-std::ostream & Console::messagestream()
-{
- return std::cout;
-}
-
-std::ostream & Console::warningstream()
-{
- return std::cerr;
}
-std::ostream & Console::errorstream()
-{
- return std::cerr;
-}
-
-std::ostream & Console::debugstream()
-{
- return std::cout;
-}
-
-} // namespace console
-} // namespace server
diff --git a/src/server/console.h b/src/server/console.h
index 1d94ba6..d894bf1 100644
--- a/src/server/console.h
+++ b/src/server/console.h
@@ -11,15 +11,16 @@
namespace server {
-namespace console {
+class Console : public sys::ConsoleInterface {
+public:
+ static void init();
-void init();
+ static void shutdown();
+};
-void shutdown();
+Console *console();
-} // namespace console
-
-} // namespace server
+}
#endif // __INCLUDED_SERVER_CONSOLE_H__
diff --git a/src/server/server.cc b/src/server/server.cc
index 1c95ee8..ee54352 100644
--- a/src/server/server.cc
+++ b/src/server/server.cc
@@ -33,6 +33,7 @@ public:
virtual void quit(int status);
};
+
Server app;
//--- public ------------------------------------------------------
@@ -60,7 +61,7 @@ void Server::init(int count, char **arguments)
core::Cvar::sv_private = core::Cvar::set("sv_dedicated", "1", core::Cvar::ReadOnly);
core::Application::init(count, arguments);
- console::init();
+ Console::init();
// the command line is in the buffer, execute it
core::CommandBuffer::exec();
@@ -103,7 +104,7 @@ void Server::shutdown()
con_debug << " bytes sent " << 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;
- console::shutdown();
+ Console::shutdown();
core::Application::shutdown();
diff --git a/src/sys/consoleinterface.cc b/src/sys/consoleinterface.cc
index f80939d..a300ea1 100644
--- a/src/sys/consoleinterface.cc
+++ b/src/sys/consoleinterface.cc
@@ -17,11 +17,15 @@ ConsoleInterface *ConsoleInterface::consoleinterface_instance = 0;
ConsoleInterface::ConsoleInterface()
{
+ consoleinterface_ansi = true;
if (consoleinterface_instance) {
std::cerr << "multiple sys::ConsoleInterface instances!" << std::endl;
sys::quit(2);
}
+
consoleinterface_instance = this;
+ consoleinterface_text.clear();
+ consoleinterface_buffer.clear();
}
ConsoleInterface::~ConsoleInterface()
@@ -34,4 +38,129 @@ ConsoleInterface *ConsoleInterface::instance()
return consoleinterface_instance;
}
+std::ostream & ConsoleInterface::messagestream()
+{
+ flush();
+ return (consoleinterface_buffer << "^N");
+}
+
+std::ostream & ConsoleInterface::warningstream()
+{
+ flush();
+ return (consoleinterface_buffer << "^W");
+}
+
+std::ostream & ConsoleInterface::errorstream()
+{
+ flush();
+ return (consoleinterface_buffer << "^R");
+}
+
+std::ostream & ConsoleInterface::debugstream()
+{
+ flush();
+ return (consoleinterface_buffer << "^D");
+}
+
+void ConsoleInterface::flush()
+{
+ char line[MAXCMDSIZE];
+
+ while(consoleinterface_buffer.getline(line, MAXCMDSIZE-1)) {
+
+ while (consoleinterface_text.size() >= MAXCONLINES) {
+ consoleinterface_text.pop_front();
+ }
+ consoleinterface_text.push_back(std::string(line));
+
+ // print to stdout
+ print_ansi(line);
+ std::cout << std::endl;
+ }
+
+ consoleinterface_buffer.clear();
+}
+
+void ConsoleInterface::print_ansi(const char *line)
+{
+ if (consoleinterface_ansi)
+ std::cout << "\033[0;39m";
+
+ const char *c = line;
+ while (*c) {
+
+ if ((*c == '^')) {
+ bool is_code = true;
+ int bold = 0;
+ int color = 39;
+
+ switch (*(c+1)) {
+ case '0': // black
+ color = 0;
+ bold = 1;
+ break;
+ case '1': // red
+ color = 31;
+ break;
+ case '2': // green
+ color = 32;
+ break;
+ case '3': // yellow
+ bold = 1;
+ color = 33;
+ break;
+ case '4': // blue
+ color = 34;
+ break;
+ case '5': // cyan
+ color = 36;
+ break;
+ case '6': // magenta
+ color = 35;
+ break;
+ case '7': // white is mapped to foreground color
+ bold = 1;
+ color = 39;
+ break;
+
+ case 'N': // normal
+ bold = 0;
+ color = 39;
+ break;
+ case 'B': // bold
+ bold = 1;
+ color = 39;
+ break;
+ case 'D': // debug
+ bold = 0;
+ color = 39;
+ break;
+ case 'R': // error
+ bold = 0;
+ color = 31;
+ break;
+ case 'W': // warning
+ bold = 1;
+ color = 33;
+ break;
+ case 'F': // fancy
+ bold = 0;
+ color = 32;
+ break;
+ default:
+ is_code = false;
+ }
+ if (is_code) {
+ c++;
+ if (consoleinterface_ansi)
+ std::cout << "\033[" << bold << ";" << color << "m";
+ } else
+ std::cout << *c;
+ } else {
+ std::cout << *c;
+ }
+ c++;
+ }
+}
+
} // namespace sys
diff --git a/src/sys/consoleinterface.h b/src/sys/consoleinterface.h
index 33dc5b5..f874182 100644
--- a/src/sys/consoleinterface.h
+++ b/src/sys/consoleinterface.h
@@ -7,11 +7,11 @@
#ifndef __INCLUDED_SYS_CONSOLEINTERFACE_H__
#define __INCLUDED_SYS_CONSOLEINTERFACE_H__
-// project headers
-#include "sys/sys.h"
-
-// C++ headers
#include <iostream>
+#include <sstream>
+#include <deque>
+
+#include "sys/sys.h"
/// global define to send a message to the system console
#define con_print sys::ConsoleInterface::instance()->messagestream()
@@ -30,6 +30,8 @@
namespace sys
{
+const size_t MAXCONLINES = 2048;
+
/// interface for the client and server Console classes
class ConsoleInterface
{
@@ -40,27 +42,38 @@ public:
/// default destructor
virtual ~ConsoleInterface();
- /// stream to send normal messages too
- virtual std::ostream & messagestream() = 0;
+ /// stream to send normal messages to
+ std::ostream & messagestream();
- /// stream to send warning messages too
- virtual std::ostream & warningstream() = 0;
+ /// stream to send warning messages to
+ std::ostream & warningstream();
- /// stream to send error messages too
- virtual std::ostream & errorstream() = 0;
+ /// stream to send error messages to
+ std::ostream & errorstream();
- /// stream to send debug messages too
- virtual std::ostream & debugstream() = 0;
+ /// stream to send debug messages to
+ std::ostream & debugstream();
/// flush buffered messages
- virtual void flush() = 0;
+ virtual void flush();
+
+ /// turn ANSI color codes on or off
+ inline void set_ansi(bool ansi) { consoleinterface_ansi = ansi; }
/// a pointer to the current console instance
static ConsoleInterface *instance();
+protected:
+ std::deque<std::string> consoleinterface_text;
+ std::stringstream consoleinterface_buffer;
+
+ /// print a string to stdout with ansi color codes
+ void print_ansi(const char *line);
+
private:
/// console singleton
static ConsoleInterface *consoleinterface_instance;
+ bool consoleinterface_ansi;
};
} // namespace sys
diff --git a/src/sys/sys.cc b/src/sys/sys.cc
index 4c3f38f..4cb820d 100644
--- a/src/sys/sys.cc
+++ b/src/sys/sys.cc
@@ -20,25 +20,25 @@
#endif
#include <stdlib.h>
+#include <string>
#include "sys/sys.h"
namespace sys {
-void mkdir(const char *path)
+void mkdir(std::string const &path)
{
#ifdef _WIN32
- mkdir(path);
+ string p(path);
+ for (size_t i = 0; i < p.lenght(); i++)
+ if (p[i] == '/') p[i] = '\\';
+ ::mkdir(p.cstr());
#else
- ::mkdir(path, 0777);
+
+ ::mkdir(path.c_str(), 0777);
#endif
}
-void mkdir(const std::string &path)
-{
- mkdir(path.c_str());
-}
-
void signal(int signum, signalfunc handler)
{
#ifndef _WIN32
diff --git a/src/sys/sys.h b/src/sys/sys.h
index 178fe60..e455b82 100644
--- a/src/sys/sys.h
+++ b/src/sys/sys.h
@@ -22,9 +22,7 @@ namespace sys
typedef void (* signalfunc)(int signum);
/// create a directory
-void mkdir(const char *path);
-
-void mkdir(const std::string &path);
+void mkdir(std::string const &path);
/// intercept OS signals
void signal(int signum, signalfunc handler);