Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/TODO3
-rw-r--r--osirion.kdevelop2
-rw-r--r--src/auxiliary/functions.cc9
-rw-r--r--src/auxiliary/functions.h3
-rw-r--r--src/client/client.cc55
-rw-r--r--src/client/client.h5
-rw-r--r--src/client/targets.cc4
-rw-r--r--src/client/view.cc58
-rw-r--r--src/client/view.h5
-rw-r--r--src/core/Makefile.am3
-rw-r--r--src/core/application.cc29
-rw-r--r--src/core/application.h6
-rw-r--r--src/core/commandbuffer.cc24
-rw-r--r--src/core/core.h1
-rw-r--r--src/core/gameconnection.cc10
-rw-r--r--src/core/gameconnection.h3
-rw-r--r--src/core/gameinterface.cc44
-rw-r--r--src/core/gameinterface.h11
-rw-r--r--src/core/gameserver.cc196
-rw-r--r--src/core/gameserver.h37
-rw-r--r--src/core/message.h23
-rw-r--r--src/core/net.h2
-rw-r--r--src/core/netconnection.cc91
-rw-r--r--src/core/netconnection.h3
-rw-r--r--src/core/netserver.cc11
-rw-r--r--src/core/player.cc28
-rw-r--r--src/core/player.h9
-rw-r--r--src/game/game.cc197
-rw-r--r--src/game/game.h12
-rw-r--r--src/game/jumppoint.cc4
-rw-r--r--src/game/racetrack.cc13
-rw-r--r--src/game/ship.cc59
-rw-r--r--src/game/ship.h4
-rw-r--r--src/render/camera.cc18
-rw-r--r--src/render/render.cc57
-rw-r--r--src/render/render.h8
-rw-r--r--src/render/textures.cc67
-rw-r--r--src/render/textures.h11
38 files changed, 751 insertions, 374 deletions
diff --git a/doc/TODO b/doc/TODO
index 7bdcc98..b851d74 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -123,6 +123,9 @@ game:
docking
jumpgates (required docking)
+data:
+ rename skies (lindblade1, lindblade2, ...)
+
win32 port:
network (ok)
texture loading (ok)
diff --git a/osirion.kdevelop b/osirion.kdevelop
index c94d33e..d40c050 100644
--- a/osirion.kdevelop
+++ b/osirion.kdevelop
@@ -21,7 +21,7 @@
</general>
<kdevautoproject>
<general>
- <activetarget>src/server/libserver.la</activetarget>
+ <activetarget>src/core/libcore.la</activetarget>
<useconfiguration>debug</useconfiguration>
</general>
<run>
diff --git a/src/auxiliary/functions.cc b/src/auxiliary/functions.cc
index 860524a..8cefbc5 100644
--- a/src/auxiliary/functions.cc
+++ b/src/auxiliary/functions.cc
@@ -165,4 +165,13 @@ void to_label(std::string &text)
}
}
+void strip_quotes(std::string &text)
+{
+ for (size_t pos = 0; pos < text.size(); pos++) {
+ if (text[pos] == '"') {
+ text[pos] = '\'';
+ }
+ }
+}
+
}
diff --git a/src/auxiliary/functions.h b/src/auxiliary/functions.h
index fccb4dc..d5b590d 100644
--- a/src/auxiliary/functions.h
+++ b/src/auxiliary/functions.h
@@ -55,6 +55,9 @@ const std::string text_strip_lowercase(const std::string &text);
/// trim leading ad trailing spaces from a string
void trim(std::string &text);
+/// replaces double quotes by single quotes
+void strip_quotes(std::string &text);
+
/// convert a string to a valid label string
/** trim leading and trealing spaces, convert remaining spaces to underscores, and make lowercase
* remove any non-alphanumeric character
diff --git a/src/client/client.cc b/src/client/client.cc
index 7ba61d6..a8d4ca8 100644
--- a/src/client/client.cc
+++ b/src/client/client.cc
@@ -19,6 +19,8 @@
#include "client/input.h"
#include "client/view.h"
#include "core/core.h"
+#include "core/zone.h"
+#include "render/render.h"
namespace client
{
@@ -181,6 +183,8 @@ void Client::shutdown()
{
con_print << "^BShutting down client..." << std::endl;
+ if (connected()) disconnect();
+
core::Func::remove("r_restart");
core::Func::remove("snd_restart");
@@ -210,34 +214,49 @@ void Client::notify_remove_sound(size_t source)
audio::Sources::remove(source);
}
-void Client::notify_message(std::string const & message)
+void Client::notify_message(core::Message::Channel const channel, std::string const message)
{
- con_print << message << std::endl;
+
+ switch(channel) {
+
+ case core::Message::Info: // Info message
+ break;
+
+ case core::Message::Local: // Chat message in the local zone
+ break;
+
+ case core::Message::RCon: // RCon message
+ break;
+
+ case core::Message::Public: // Public chat message
+ audio::play("com/chat");
+ break;
+
+ case core::Message::Private: // Private chat message
+ audio::play("com/priv");
+ break;
+
+ default:
+ break;
+ }
+
+ con_print << message << std::endl;
console()->notify(message);
}
void Client::notify_zoneclear(core::Zone *zone)
{
- // FIXME unload zone textures
- /*
if (!zone)
return;
- for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content.end(); i++) {
- core:: Entity *entity = (*it);
-
- if (entity->type() == core::Entity::Globe) {
- core::EntityGlobe *globe = static_cast<core::EntityGlobe *>(entity);
- if (globe->render_texture)
- render::Textures::unload(render_texture);
-
- }
+ view::clear_zone(zone);
+}
- if (zone->sky_texture()) {
- render::Textures::unload(zone->sky_texture());
- zone->set_sky_texture(0);
- }
- */
+void Client::notify_disconnect()
+{
+ // FIXME unload sounds
+
+ render::unload();
}
} // namespace client
diff --git a/src/client/client.h b/src/client/client.h
index 664bbb4..6da5c5f 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -32,13 +32,16 @@ public:
virtual void notify_sound(const char * name);
/// text notifications from the core
- virtual void notify_message(std::string const & message);
+ virtual void notify_message(core::Message::Channel const channel, std::string const message);
/// remove sound source notification
virtual void notify_remove_sound(size_t source);
/// clear zone notification
virtual void notify_zoneclear(core::Zone *zone);
+
+ /// disconnect notification
+ virtual void notify_disconnect();
};
diff --git a/src/client/targets.cc b/src/client/targets.cc
index a18392f..4764245 100644
--- a/src/client/targets.cc
+++ b/src/client/targets.cc
@@ -42,7 +42,9 @@ bool is_legal_target(core::Entity *entity)
{
if (entity->serverside()) {
return false;
- } else if (entity->id() == core::localcontrol()->id()) {
+ } else if (entity == core::localplayer()->mission_target()) {
+ return true;
+ } else if (entity == core::localcontrol()) {
return false;
} else if (entity->state()->distance() < 0.001f) {
return false;
diff --git a/src/client/view.cc b/src/client/view.cc
index 8cf1af9..bbf9088 100644
--- a/src/client/view.cc
+++ b/src/client/view.cc
@@ -18,13 +18,8 @@
#include "client/input.h"
#include "client/targets.h"
#include "client/video.h"
-#include "render/draw.h"
#include "render/render.h"
-#include "render/textures.h"
-#include "render/camera.h"
#include "core/core.h"
-#include "core/stats.h"
-#include "core/zone.h"
#include "math/mathlib.h"
#include "sys/sys.h"
@@ -38,6 +33,7 @@ core::Cvar *draw_keypress = 0;
core::Cvar *ui_pointercolor = 0;
core::Cvar *ui_pointerhovercolor =0;
+
namespace view
{
@@ -50,6 +46,8 @@ float net_counter_time[net_counter_size];
size_t net_counter_traffic[net_counter_size];
size_t net_counter_index;
+core::Zone *current_zone = 0;
+
void init()
{
draw_stats = core::Cvar::get("draw_stats", "0", core::Cvar::Archive);
@@ -84,6 +82,26 @@ void shutdown()
targets::shutdown();
}
+void clear_zone(core::Zone *zone)
+{
+ for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) {
+ core:: Entity *entity = (*it);
+
+ if (entity->type() == core::Entity::Globe) {
+ core::EntityGlobe *globe = static_cast<core::EntityGlobe *>(entity);
+ if (globe->render_texture) {
+ render::Textures::unload(globe->render_texture);
+ globe->render_texture = 0;
+ }
+ }
+ }
+
+ if (zone->sky_texture()) {
+ render::Textures::unload(zone->sky_texture());
+ zone->set_sky_texture(0);
+ }
+}
+
void draw_loader()
{
using namespace render;
@@ -219,10 +237,12 @@ void draw_entity_offscreen_target(core::Entity *entity, bool is_active_target)
glVertex3f(cx, cy-r+2, 0);
render::gl::end();
- if (entity->type() == core::Entity::Controlable) {
- render::gl::color(0, 1, 0, 1);
+ if (entity == core::localplayer()->mission_target()) {
+ render::gl::color(1, 0.5f, 1, 1); // FIXME mission color
+ } else if (entity->type() == core::Entity::Controlable) {
+ render::gl::color(0, 1, 0, 1); // FIXME allegiance color
} else {
- render::gl::color(1, 1, 1, 1);
+ render::gl::color(1, 1, 1, 1); // FIXME neutral color
}
render::gl::begin(render::gl::LineLoop);
@@ -279,11 +299,14 @@ void draw_entity_target(core::Entity *entity, bool is_active_target)
glVertex3f(cx, cy-r+2, 0);
render::gl::end();
- if (entity->type() == core::Entity::Controlable) {
- render::gl::color(0, 1, 0, 1);
+ if (entity == core::localplayer()->mission_target()) {
+ render::gl::color(1, 0.5f, 1, 1); // FIXME mission color
+ } else if (entity->type() == core::Entity::Controlable) {
+ render::gl::color(0, 1, 0, 1); // FIXME allegiance color
} else {
- render::gl::color(1, 1, 1, 1);
+ render::gl::color(1, 1, 1, 1); // FIXME neutral color
}
+
// outer square0
render::gl::begin(render::gl::LineLoop);
glVertex3f(cx+r, cy, 0);
@@ -391,7 +414,9 @@ void draw_status()
core::Entity *entity = (*it);
if (targets::is_legal_target(entity)) {
- if (entity == targets::current()) {
+ if (entity == core::localplayer()->mission_target()) {
+ draw_entity_target(entity, true);
+ } else if (entity == targets::current()) {
draw_entity_target(entity, true);
} else if (entity->type() == core::Entity::Controlable) {
draw_entity_target(entity, false);
@@ -716,11 +741,20 @@ void frame(float seconds)
render::Stats::clear();
if (core::application()->connected() && core::game()->serverframetime()) {
+
+ if (core::localplayer()->zone() != current_zone) {
+ if (current_zone)
+ clear_zone(current_zone);
+ current_zone = core::localplayer()->zone();
+ }
+
render::draw(seconds); // draw the world
targets::draw(); // validate current target, render sound
if (targets::current()) // draw target docks etc
draw_entity_world_target(targets::current());
+ } else {
+ current_zone = 0;
}
// switch to orthographic projection to draw the GUI
diff --git a/src/client/view.h b/src/client/view.h
index d9e44ab..1f81597 100644
--- a/src/client/view.h
+++ b/src/client/view.h
@@ -6,6 +6,8 @@
#ifndef __INCLUDED_CLIENT_VIEW_H__
#define __INCLUDED_CLIENT_VIEW_H__
+#include "core/zone.h"
+
namespace client
{
@@ -24,6 +26,9 @@ namespace view
/// reset OpenGL state
void reset();
+ /// clear client-side assets of a zone
+ void clear_zone(core::Zone *zone);
+
} // namespace view
} // namespace client
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 802234e..8c44d13 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -12,6 +12,5 @@ libcore_la_LIBADD = $(top_builddir)/src/model/libmodel.la \
noinst_LTLIBRARIES = libcore.la
noinst_HEADERS = application.h clientstate.h commandbuffer.h core.h cvar.h \
- entity.h func.h gameconnection.h gameinterface.h gameserver.h module.h net.h \
+ entity.h func.h gameconnection.h gameinterface.h gameserver.h message.h module.h net.h \
netclient.h netconnection.h netserver.h player.h range.h stats.h timer.h
-
diff --git a/src/core/application.cc b/src/core/application.cc
index 21d5e50..6207a0d 100644
--- a/src/core/application.cc
+++ b/src/core/application.cc
@@ -70,6 +70,16 @@ void func_say(std::string const &args)
}
}
+void func_msg(std::string const &args)
+{
+ if (connection()) {
+ connection()->private_message(args);
+ } else if (server()) {
+ server()->private_message(localplayer(), args);
+ } else {
+ con_print << "Not connected." << std::endl;
+ }
+}
// --------------- signal_handler -----------------------------------
#ifndef _WIN32
@@ -222,6 +232,9 @@ void Application::init(int count, char **arguments)
func = Func::add("say",func_say);
func->set_info("say [text] say something on the public chat");
+
+ func = Func::add("msg",func_msg);
+ func->set_info("msg [player] [text] send a private message to another player");
}
void Application::shutdown()
@@ -299,6 +312,7 @@ void Application::connect(std::string const &host)
void Application::disconnect()
{
if(application_game) {
+ notify_disconnect();
delete application_game;
application_game = 0;
con_print << "^BDisconnected.\n";
@@ -446,6 +460,11 @@ void Application::load_commandline(int count, char **arguments)
cmd() << '\n';
}
+void Application::notify_message(Message::Channel const channel, std::string const message)
+{
+ con_print << message << std::endl;
+}
+
void Application::notify_sound(const char *name)
{
// the default implementation does nothing.
@@ -458,15 +477,17 @@ void Application::notify_remove_sound(size_t source)
// Dedicated servers don't need sounds
}
-void Application::notify_message(std::string const & message)
+void Application::notify_zoneclear(Zone *zone)
{
- con_print << message << std::endl;
+ // the default implementation does nothing.
+ // The client uses this to clear old zones
}
-void Application::notify_zoneclear(Zone *zone)
+void Application::notify_disconnect()
{
// the default implementation does nothing.
- // The client uses this to clear old zones
+ // The client uses this to clear game data
+
}
}
diff --git a/src/core/application.h b/src/core/application.h
index ef89e70..0dfa652 100644
--- a/src/core/application.h
+++ b/src/core/application.h
@@ -9,6 +9,7 @@
#include "sys/sys.h"
#include "core/commandbuffer.h"
+#include "core/message.h"
#include "core/netserver.h"
#include "core/netconnection.h"
#include "core/gameinterface.h"
@@ -62,7 +63,7 @@ public:
virtual void notify_sound(const char * name);
/// text notifications from the core to the application
- virtual void notify_message(std::string const & message);
+ virtual void notify_message(Message::Channel const channel, std::string const message);
/// remove sound source notification
virtual void notify_remove_sound(size_t source);
@@ -70,6 +71,9 @@ public:
/// zone clear notification
virtual void notify_zoneclear(Zone *zone);
+ /// disconnect notification
+ virtual void notify_disconnect();
+
/*----- static --------------------------------------------------- */
/// a pointer to the current application instance
diff --git a/src/core/commandbuffer.cc b/src/core/commandbuffer.cc
index c111e17..5ed3787 100644
--- a/src/core/commandbuffer.cc
+++ b/src/core/commandbuffer.cc
@@ -64,6 +64,11 @@ void func_list_zone(std::string const &args)
}
}
+void func_list_model(std::string const &args)
+{
+ model::Model::list();
+}
+
void func_set(std::string const &args)
{
std::istringstream argstream(args);
@@ -160,6 +165,9 @@ void CommandBuffer::init()
func = Func::add("list_zone", (FuncPtr)func_list_zone);
func->set_info("list zones");
+ Func::add("list_model", (FuncPtr) func_list_model);
+ func->set_info("list models");
+
func = Func::add("set", (FuncPtr)func_set);
func->set_info("[variable] [str] set variable value");
@@ -185,6 +193,7 @@ void CommandBuffer::shutdown()
Func::remove("list_var");
Func::remove("list_func");
Func::remove("list_ent");
+ Func::remove("list_model");
Func::remove("list_zone");
Func::remove("print");
Func::remove("print_file");
@@ -205,6 +214,10 @@ void CommandBuffer::exec(std::string const &cmdline)
aux::to_lowercase(command);
//con_debug << "Executing '" << cmdline << "'\n";
+ if ((command[0] == '\\') || (command[0] == '/')) {
+ command.erase(0, 1);
+ }
+
// is it a function
Func *f = Func::find(command);
if (f) {
@@ -248,10 +261,15 @@ void CommandBuffer::exec(std::string const &cmdline)
}
// this gets forwarded to the server
- if (connection())
- connection()->forward(cmdline);
- else
+ if (connection()) {
+ if ((cmdline[0] == '\\') || (cmdline[0] == '/')) {
+ connection()->forward(cmdline.substr(1, cmdline.size()-1));
+ } else {
+ connection()->forward(cmdline);
+ }
+ } else {
con_print << "Unknown command '" << command << "^N'\n";
+ }
}
void CommandBuffer::exec()
diff --git a/src/core/core.h b/src/core/core.h
index feca5fd..80f6d54 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -18,6 +18,7 @@
#include "core/module.h"
#include "core/player.h"
#include "core/range.h"
+#include "core/stats.h"
#include "core/zone.h"
/// core contains the basic functionality of the engine
diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc
index ef998e6..114931c 100644
--- a/src/core/gameconnection.cc
+++ b/src/core/gameconnection.cc
@@ -57,6 +57,8 @@ GameConnection::GameConnection(std::string const &connectionstr)
return;
}
+ game_players.push_back(localplayer());
+
connection_running = true;
}
@@ -91,6 +93,14 @@ void GameConnection::say(std::string const &args)
connection_network->send_say(args);
}
+void GameConnection::private_message(std::string const &args)
+{
+ if (!connection_network->connected())
+ return;
+
+ connection_network->send_private_message(args);
+}
+
void GameConnection::frame(float seconds)
{
if (!running())
diff --git a/src/core/gameconnection.h b/src/core/gameconnection.h
index d0da18e..ecf50f2 100644
--- a/src/core/gameconnection.h
+++ b/src/core/gameconnection.h
@@ -39,6 +39,9 @@ public:
/// localplayer sends a chat message to the public channel
void say(std::string const &args);
+ /// localplayer sends a private message to another player
+ void private_message(std::string const &args);
+
/*----- static ---------------------------------------------------- */
/// return the current game connection
diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc
index 70224b0..17623f2 100644
--- a/src/core/gameinterface.cc
+++ b/src/core/gameinterface.cc
@@ -4,9 +4,11 @@
the terms of the GNU General Public License version 2
*/
-#include <stdlib.h>
+#include <cstdlib>
#include <iostream>
+#include <iomanip>
+#include "auxiliary/functions.h"
#include "core/application.h"
#include "core/cvar.h"
#include "core/func.h"
@@ -19,13 +21,13 @@
namespace core
{
-const float MIN_DELTA = 10e-10;
-
-void func_list_model(std::string const &args)
+void func_list_players(std::string const &args)
{
- model::Model::list();
+ game()->list_players();
}
+const float MIN_DELTA = 10e-10;
+
Player GameInterface::game_localplayer;
EntityControlable *localcontrol()
@@ -52,13 +54,14 @@ GameInterface::GameInterface()
game_localplayer.player_name.assign("Player");
game_localplayer.update_info();
}
-
- Func::add("list_model", (FuncPtr) func_list_model);
+
+ Func *func = Func::add("list_players", func_list_players);
+ func->set_info("get the local list of connected players");
}
GameInterface::~GameInterface()
{
- Func::remove("list_model");
+ Func::remove("list_players");
game_localplayer.clear();
@@ -105,6 +108,16 @@ void GameInterface::clear()
// remove all models
model::Model::clear();
+ // clear player list
+ for (Players::iterator it = game_players.begin(); it != game_players.end(); it++) {
+ Player *player = (*it);
+ if (player != localplayer()) {
+ delete player;
+ }
+ }
+
+ game_players.clear();
+
game_previousframetime = 0;
game_serverframetime = 0;
game_clientframetime = 0;
@@ -220,4 +233,19 @@ float GameInterface::timeoffset() {
return t/d;
}
+void GameInterface::list_players()
+{
+ using namespace std;
+ stringstream msgstr;
+ int count = 0;
+
+ for (Players::iterator it = game_players.begin(); it != game_players.end(); it++) {
+ msgstr.str("");
+ con_print << setw(3) << (*it)->id() << aux::pad_left((*it)->name(), 24) << std::endl;
+ count++;
+ }
+
+ con_print << count << " connected " << aux::plural("player", count) << std::endl;
+}
+
}
diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h
index ef51545..69cd588 100644
--- a/src/core/gameinterface.h
+++ b/src/core/gameinterface.h
@@ -22,6 +22,9 @@ public:
/// destroy the game
virtual ~GameInterface();
+ /// type definition for the Players collection
+ typedef std::list<Player *> Players;
+
/*----- inspectors ---------------------------------------------- */
/// return the local player
@@ -41,6 +44,11 @@ public:
inline float timestep() const { return game_timestep; }
+ inline Players & players() { return game_players; }
+
+ /// show a list of connected players
+ void list_players();
+
/*----- virtual inspectors --------------------------------------- */
/// returns true if the game server can run a time frime
@@ -68,6 +76,9 @@ public:
protected:
/// the local player
static Player game_localplayer;
+
+ /// all the players
+ Players game_players;
float game_serverframetime;
float game_previousframetime;
diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc
index 14f97bb..f251b75 100644
--- a/src/core/gameserver.cc
+++ b/src/core/gameserver.cc
@@ -4,17 +4,17 @@
the terms of the GNU General Public License version 2
*/
-#include <iomanip>
#include <fstream>
+#include <iomanip>
#include "auxiliary/functions.h"
-#include "sys/sys.h"
#include "core/application.h"
#include "core/cvar.h"
#include "core/func.h"
#include "core/gameserver.h"
#include "core/netserver.h"
#include "filesystem/filesystem.h"
+#include "sys/sys.h"
namespace core
{
@@ -174,8 +174,6 @@ GameServer::GameServer() : GameInterface()
func = Func::add("who", func_who, Func::Shared);
func->set_info("get a list of connected players");
- server_players.clear();
-
if (!Cvar::sv_dedicated->value()) {
player_connect(localplayer());
}
@@ -218,8 +216,6 @@ GameServer::~GameServer()
Func::remove("who");
server_instance = 0;
-
- server_players.clear();
}
void GameServer::abort()
@@ -227,21 +223,6 @@ void GameServer::abort()
server_running = false;
}
-void GameServer::list_players()
-{
- using namespace std;
- stringstream msgstr;
- int count = 0;
-
- for (Players::iterator it = server_players.begin(); it != server_players.end(); it++) {
- msgstr.str("");
- con_print << setw(3) << (*it)->id() << aux::pad_left((*it)->name(), 24) << std::endl;
- count++;
- }
-
- con_print << count << " connected " << aux::plural("player", count) << std::endl;
-}
-
void GameServer::showtime()
{
using namespace std;
@@ -265,7 +246,7 @@ Player *GameServer::find_player(std::string const search)
std::istringstream searchstr(search);
int id = 0;
if (searchstr >> id) {
- for (std::list<Player *>:: iterator it = server_players.begin(); it != server_players.end(); it++) {
+ for (std::list<Player *>:: iterator it = game_players.begin(); it != game_players.end(); it++) {
if ((*it)->id() == id) {
return (*it);
}
@@ -275,7 +256,7 @@ Player *GameServer::find_player(std::string const search)
if (search.size() <3)
return 0;
- for (std::list<Player *>:: iterator it = server_players.begin(); it != server_players.end(); it++) {
+ for (std::list<Player *>:: iterator it = game_players.begin(); it != game_players.end(); it++) {
if (aux::text_strip_lowercase((*it)->name()).find(lowercase(search)) != std::string::npos)
return (*it);
}
@@ -298,14 +279,35 @@ void GameServer::say(Player *player, std::string const &message)
notification.append("^F:^B ");
notification.append(message);
- // send to application
- application()->notify_message(notification);
- application()->notify_sound("com/chat");
-
- // broadcast to remote clients
- if (server_network) {
- server_network->broadcast_message("public", notification);
+ broadcast_message(Message::Public, notification);
+}
+
+void GameServer::private_message(Player *player, std::string const &args)
+{
+ if (!args.size())
+ return;
+
+ if (player->mute()) {
+ send(player, "^BYou have been muted.");
+ return;
+ }
+
+ std::string target;
+ std::stringstream argstr(args);
+ if (!(argstr >> target)) {
+ return;
}
+
+ core::Player *targetplayer = core::server()->find_player(target);
+ if (!targetplayer) {
+ send(player, "^BPlayer " + target + "^B not found.");
+ return;
+ }
+
+
+ std::string message(args.substr(target.size()));
+ send_message(Message::Private, player, "^FTo ^B" + targetplayer->name() + "^F:" + message);
+ send_message(Message::Private, targetplayer, "^FFrom ^B" + player->name() + "^F:" + message);
}
// FIXME kicked by
@@ -327,44 +329,114 @@ void GameServer::kick(Player *player, std::string const &reason)
}
// broadcast an "info" message to all players
-void GameServer::broadcast(std::string const & message, Player *ignore_player)
+void GameServer::broadcast(std::string const message, Player *ignore_player)
{
if (!message.size())
return;
- // send to application
- if (ignore_player != game()->localplayer())
- application()->notify_message(message);
-
- // broadcast to remote clients
- if (server_network) {
- server_network->broadcast_message("info", message, ignore_player);
- }
+ broadcast_message(Message::Info, message, ignore_player);
}
// send and "info" message to a single player
-void GameServer::send(Player *player, std::string message)
+void GameServer::send(Player *player, std::string const message)
+{
+ send_message(Message::Info, player, message);
+}
+
+// send an rcon message to a single player
+void GameServer::send_rcon(Player *player, std::string const message)
+{
+ send_message(Message::RCon, player, message);
+}
+
+void GameServer::send_message(Message::Channel const channel, Player *player, std::string const message)
{
if (!message.size())
return;
- // send to application
if (player == localplayer()) {
- application()->notify_message(message);
+ application()->notify_message(channel, message);
return;
+ } else {
+ if (server_network) {
+ std::string msg_channel;
+ switch(channel) {
+ case core::Message::Info: // Info message
+ msg_channel.assign("info");
+ break;
+
+ case core::Message::Local: // Chat message in the local zone
+ msg_channel.assign("local");
+ break;
+
+ case core::Message::Public: // Public chat message
+ msg_channel.assign("public");
+ break;
+
+ case core::Message::Private: // Private chat message
+ msg_channel.assign("private");
+ break;
+
+ case core::Message::RCon: // RCon message
+ msg_channel.assign("rcon");
+ break;
+
+ default:
+ con_warn << "message on unknown channel " << channel << "!" << std::endl;
+ return;
+ break;
+ }
+
+ NetClient *client = server_network->find_client(player);
+ if (client) {
+ server_network->send_message(client, msg_channel.c_str(), message);
+ }
+ }
}
+}
+
+// broadcast a message on a specified channel to all players
+void GameServer::broadcast_message(Message::Channel const channel, std::string const message, Player *ignore_player)
+{
+ if (!message.size())
+ return;
- // send to remote clients
+ // send to application
+ if (ignore_player != game()->localplayer())
+ application()->notify_message(channel, message);
+
+ // broadcast to remote clients
if (server_network) {
- NetClient *client = server_network->find_client(player);
- if (client) {
- server_network->send_message(client, "info", message);
+ std::string msg_channel;
+ switch(channel) {
+ case core::Message::Info: // Info message
+ msg_channel.assign("info");
+ break;
+
+ case core::Message::Local: // Chat message in the local zone
+ msg_channel.assign("local");
+ break;
+
+ case core::Message::RCon: // RCon message
+ msg_channel.assign("rcon");
+ break;
+
+ case core::Message::Public: // Public chat message
+ msg_channel.assign("public");
+ break;
+
+ default:
+ con_warn << "message on unknown channel " << channel << "!" << std::endl;
+ return;
+ break;
}
+
+ server_network->broadcast_message(msg_channel.c_str(), message);
}
}
// broadcast a sound event to all players
-void GameServer::broadcast_sound(std::string const & sound, Player *ignore_player)
+void GameServer::broadcast_sound(std::string const sound, Player *ignore_player)
{
if (!sound.size())
return;
@@ -381,7 +453,7 @@ void GameServer::broadcast_sound(std::string const & sound, Player *ignore_playe
}
// send a sound event to a single player
-void GameServer::send_sound(Player *player, std::string sound)
+void GameServer::send_sound(Player *player, std::string const sound)
{
if (!sound.size())
return;
@@ -401,24 +473,6 @@ void GameServer::send_sound(Player *player, std::string sound)
}
}
-// send an rcon message to a single player
-void GameServer::send_rcon(Player *player, std::string message)
-{
- // send to application
- if (player == localplayer()) {
- con_print << message << std::endl;
- return;
- }
-
- // send to remote clients
- if (server_network) {
- NetClient *client = server_network->find_client(player);
- if (client) {
- server_network->send_message(client, "rcon", message);
- }
- }
-}
-
// execute a command for a remote player
void GameServer::exec(Player *player, std::string const & cmdline)
{
@@ -478,7 +532,7 @@ void GameServer::player_connect(Player *player)
server_module->player_connect(player);
// manage player list
- server_players.push_back(player);
+ game_players.push_back(player);
}
void GameServer::player_disconnect(Player *player)
@@ -495,12 +549,12 @@ void GameServer::player_disconnect(Player *player)
server_module->player_disconnect(player);
// manage player list
- std::list<Player *>:: iterator it = server_players.begin();
- while (((*it)->id() != player->id()) && (it != server_players.end())) {
+ std::list<Player *>:: iterator it = game_players.begin();
+ while (((*it)->id() != player->id()) && (it != game_players.end())) {
it++;
}
- if (it != server_players.end()) {
- server_players.erase(it);
+ if (it != game_players.end()) {
+ game_players.erase(it);
}
}
diff --git a/src/core/gameserver.h b/src/core/gameserver.h
index 1f6d8cc..b25f1a0 100644
--- a/src/core/gameserver.h
+++ b/src/core/gameserver.h
@@ -8,6 +8,7 @@
#define __INCLUDED_CORE_GAMESERVER_H__
#include "core/gameinterface.h"
+#include "core/message.h"
#include "core/module.h"
#include "core/netserver.h"
@@ -21,8 +22,6 @@ namespace core
class GameServer : public GameInterface
{
public:
- typedef std::list<Player *> Players;
-
GameServer();
~GameServer();
@@ -34,9 +33,6 @@ public:
/// returns true if the game server can not run a time frime
inline bool error() { return !server_running; }
- /// show a list of connected players
- void list_players();
-
/// show the current time
void showtime();
@@ -57,23 +53,32 @@ public:
/// a player sends a chat message to the public channel
void say(Player *player, std::string const &args);
+ /// a player sends a private message to another player
+ void private_message(Player *player, std::string const &args);
+
/// kick a player from the server
void kick(Player *player, std::string const &reason);
- /// broadcast a message to all players
- void broadcast(std::string const & message, Player *ignore_player = 0);
+ /// broadcast an Info message to all players
+ void broadcast(std::string const message, Player *ignore_player = 0);
+
+ /// broadcast a message to all players on a specified channel
+ void broadcast_message(Message::Channel const channel, std::string const message, Player *ignore_player = 0);
+
+ /// send an Info message to a single player
+ void send(Player *player, std::string const message);
- /// send a message to a single player
- void send(Player *player, std::string message);
+ /// send a RCon message to a single player
+ void send_rcon(Player *player, std::string const message);
+
+ /// send a message on the specific channel to the specified Player
+ void send_message(Message::Channel const channel, Player *player, std::string const message);
/// broadcast a sound to all players
- void broadcast_sound(std::string const & sound, Player *ignore_player = 0);
+ void broadcast_sound(std::string const sound, Player *ignore_player = 0);
/// send a sound to a single player
- void send_sound(Player *player, std::string sound);
-
- /// send a rcon message to a single player
- void send_rcon(Player *player, std::string message);
+ void send_sound(Player *player, std::string const sound);
/// a player sends a command to the game server
void exec(Player *player, std::string const &cmdline);
@@ -81,8 +86,6 @@ public:
/// find the first player who's id or name matches the search string
Player *find_player(std::string const search);
- inline Players & players() { return server_players; }
-
/*----- static ---------------------------------------------------- */
/// return the current game server
@@ -104,8 +107,6 @@ private:
float server_frametime;
float server_time;
float server_previoustime;
-
- Players server_players;
};
inline GameServer *server() { return GameServer::instance(); }
diff --git a/src/core/message.h b/src/core/message.h
new file mode 100644
index 0000000..53d24be
--- /dev/null
+++ b/src/core/message.h
@@ -0,0 +1,23 @@
+/*
+ core/message.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_CORE_MESSAGE_H__
+#define __INCLUDED_CORE_MESSAGE_H__
+
+namespace core
+{
+
+class Message {
+
+public:
+ /// indicates the type of message
+ enum Channel {Info=0, Public=1, Local=2, Private=3, RCon=4 };
+};
+
+}
+
+#endif // __INCLUDED_CORE_MESSAGE_H__
+
diff --git a/src/core/net.h b/src/core/net.h
index f3f976b..4909136 100644
--- a/src/core/net.h
+++ b/src/core/net.h
@@ -11,7 +11,7 @@ namespace core
{
/// network protocol version
-const unsigned int PROTOCOLVERSION = 9;
+const unsigned int PROTOCOLVERSION = 10;
/// maximum lenght of a (compressed) network message block
const unsigned int FRAMESIZE = 1152;
diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc
index ed1a91b..9268447 100644
--- a/src/core/netconnection.cc
+++ b/src/core/netconnection.cc
@@ -328,6 +328,7 @@ void NetConnection::send_raw(std::string const &msg)
* cup <id> <entity data>
* cmd <text>
* say <text>
+ * priv <text>
*/
// send a "connect" message to the server
@@ -380,6 +381,15 @@ void NetConnection::send_say(std::string const &text)
this->send_raw(msg);
}
+// send a "priv" private message to the server
+void NetConnection::send_private_message(std::string const &text)
+{
+ std::string msg("priv ");
+ msg.append(text);
+ msg += '\n';
+ this->send_raw(msg);
+}
+
// parse incoming client messages
/**
* The following incoming messages are parsed;
@@ -388,13 +398,14 @@ void NetConnection::send_say(std::string const &text)
* disconnect
* msg info <text>
* msg public <name> <text>
+ * msg private <name> <text>
* msg rcon <text>
* msg snd <soundname>
- * die
- * ent
+ * die <id>
+ * ent <id>
* frame
- * sup
- * pif
+ * sup <id>
+ * pif <id>
* zone
*/
void NetConnection::parse_incoming_message(const std::string & message)
@@ -409,19 +420,22 @@ void NetConnection::parse_incoming_message(const std::string & message)
if (msgstream >> level) {
if (level =="info") {
if (message.size() > 9) {
- application()->notify_message(message.substr(9));
+ application()->notify_message(Message::Info, message.substr(9));
}
} else if (level =="rcon") {
if (message.size() > 9) {
- con_print << message.substr(9) << std::endl;
+ application()->notify_message(Message::RCon, message.substr(9));
}
} else if (level == "public") {
// FIXME - separate sender nickname
if (message.size() > 11) {
- application()->notify_message(message.substr(11));
- application()->notify_sound("com/chat");
+ application()->notify_message(Message::Public, message.substr(11));
}
-
+ } else if (level == "private") {
+ // FIXME - separate sender nickname
+ if (message.size() > 12) {
+ application()->notify_message(Message::Private, message.substr(12));
+ }
} else if (level == "snd") {
if (message.size() > 8) {
application()->notify_sound(message.substr(8).c_str());
@@ -527,29 +541,50 @@ void NetConnection::parse_incoming_message(const std::string & message)
} else if (command == "pif") {
//con_debug << "Received update player info" << std::endl;
-
- Zone *oldzone = connection()->localplayer()->zone();
- connection()->localplayer()->receive_server_update(msgstream);
-
- //con_debug << "zone " << ( connection()->localplayer()->zone() ? connection()->localplayer()->zone()->id() : 0) << std::endl;
- if (connection()->localplayer()->zonechange() && oldzone && (oldzone != connection()->localplayer()->zone())) {
-
- // notify the applciation to clear none-core zone assets (textures etc)
- application()->notify_zoneclear(oldzone);
-
- // delete all entities in the old zone
- for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); ) {
- Entity *entity = (*it).second;
+ int player_id;
+ if (!(msgstream >> player_id)) {
+ con_warn << "Received illegal update player info for player!" << std::endl;
+ return;
+ }
- if ((entity->zone() == oldzone)) {
- delete entity;
- Entity::registry().erase(it++);
- } else {
- ++it;
+ if (!player_id) {
+ Zone *oldzone = connection()->localplayer()->zone();
+ connection()->localplayer()->receive_server_update(msgstream);
+
+ //con_debug << "zone " << ( connection()->localplayer()->zone() ? connection()->localplayer()->zone()->id() : 0) << std::endl;
+
+ if (connection()->localplayer()->zonechange() && oldzone && (oldzone != connection()->localplayer()->zone())) {
+
+ // notify the applciation to clear none-core zone assets (textures etc)
+ application()->notify_zoneclear(oldzone);
+
+ // delete all entities in the old zone
+ for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); ) {
+ Entity *entity = (*it).second;
+
+ if ((entity->zone() == oldzone)) {
+ delete entity;
+ Entity::registry().erase(it++);
+ } else {
+ ++it;
+ }
+ }
+ oldzone->content().clear();
+ }
+ } else {
+ // FIXME find player
+ Player *player = 0;
+ for (GameInterface::Players::iterator it = game()->players().begin(); it != game()->players().end() && !player; it++) {
+ if( (*it)->id() == player_id) {
+ player = (*it);
}
}
- oldzone->content().clear();
+ if (!player) {
+ player = new Player();
+ game()->players().push_back(player);
+ }
+ player->receive_server_update(msgstream);
}
} else if (command == "sup") {
diff --git a/src/core/netconnection.h b/src/core/netconnection.h
index da683f5..cb04ce2 100644
--- a/src/core/netconnection.h
+++ b/src/core/netconnection.h
@@ -62,6 +62,9 @@ public:
/// send a chat message
void send_say(std::string const &text);
+ /// send a private message
+ void send_private_message(std::string const &text);
+
/// send a command line to the remote server
void send_command(std::string const &cmdline);
diff --git a/src/core/netserver.cc b/src/core/netserver.cc
index 93d4682..e1bd41a 100644
--- a/src/core/netserver.cc
+++ b/src/core/netserver.cc
@@ -514,7 +514,7 @@ void NetServer::send_zone_update(NetClient *client, Zone *zone)
void NetServer::send_player_update(NetClient *client)
{
std::ostringstream msg;
- msg << "pif ";
+ msg << "pif 0 ";
client->player()->serialize_server_update(msg);
msg << '\n';
client->send_raw(msg.str());
@@ -531,6 +531,7 @@ void NetServer::send_player_update(NetClient *client)
* pif
* ping
* say <text>
+ * priv <player> <text>
*
*/
void NetServer::parse_incoming_message(NetClient *client, const std::string & message)
@@ -653,6 +654,14 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me
}
return;
}
+
+ // priv
+ if (command == "priv") {
+ if (message.size() > command.size()+1) {
+ server()->private_message(client->player(), message.substr(command.size()+1));
+ }
+ return;
+ }
}
diff --git a/src/core/player.cc b/src/core/player.cc
index 1a610ca..26ea070 100644
--- a/src/core/player.cc
+++ b/src/core/player.cc
@@ -6,6 +6,7 @@
#include <sstream>
+#include "auxiliary/functions.h"
#include "sys/sys.h"
#include "core/player.h"
#include "core/cvar.h"
@@ -33,6 +34,7 @@ void Player::clear()
player_zonechange = false;
player_rcon = false;
player_mute = false;
+ player_mission_target = 0;
clear_assets();
player_control = 0;
@@ -56,12 +58,23 @@ void Player::set_zone(Zone *zone)
}
}
+void Player::set_mission_target(Entity *new_mission_target)
+{
+ if (new_mission_target != player_mission_target) {
+ player_mission_target = new_mission_target;
+ player_dirty = true;
+ }
+}
+
void Player::update_info()
{
Cvar *cl_name = Cvar::find("cl_name");
if (cl_name) {
- if (cl_name->str().size())
+ if (cl_name->str().size()) {
player_name = cl_name->str();
+ aux::strip_quotes(player_name);
+ (*cl_name) = player_name;
+ }
}
Cvar *cl_color = Cvar::find("cl_color");
@@ -105,8 +118,9 @@ void Player::serialize_server_update(std::ostream & os) const
{
unsigned int zo = (zone() ? zone()->id() : 0);
unsigned int co = (player_control ? player_control->id() : 0);
+ unsigned int mission = (player_mission_target ? player_mission_target->id() : 0);
- os << player_id << " " << zo << " " << co << " " << player_color << " \"" << player_name << "\"";
+ os << player_id << " " << zo << " " << co << " " << mission << " " << player_color << " \"" << player_name << "\"";
}
void Player::receive_server_update(std::istream &is)
@@ -131,6 +145,16 @@ void Player::receive_server_update(std::istream &is)
player_control = 0;
}
+ unsigned int mission = 0;
+ is >> mission;
+ if (mission) {
+ player_mission_target = Entity::find(mission);
+ if (!player_mission_target) {
+ con_warn << "mission target set to unknown entity " << co << "\n";
+ }
+ } else {
+ player_mission_target = 0;
+ }
is >> player_color;
std::string n;
diff --git a/src/core/player.h b/src/core/player.h
index 7bf533c..aa31a35 100644
--- a/src/core/player.h
+++ b/src/core/player.h
@@ -67,6 +67,9 @@ public:
/// player has been muted by admin or console
inline bool mute() const { return player_mute; }
+ /// mission target
+ inline Entity *mission_target() { return player_mission_target; }
+
/*----- mutators -------------------------------------------------- */
/// serialize player info to a stream
@@ -99,6 +102,8 @@ public:
/// update player info from client variables
void update_info();
+ void set_mission_target(Entity *new_mission_target);
+
/* -- should actually not be public --*/
/// dirty state
@@ -131,10 +136,12 @@ private:
// the entity the Player is currently controling
EntityControlable *player_control;
+ Entity *player_mission_target;
+
// the zone the player is currently in
Zone *player_zone;
-
+ float player_credits;
};
}
diff --git a/src/game/game.cc b/src/game/game.cc
index 0502ece..4d66cbe 100644
--- a/src/game/game.cc
+++ b/src/game/game.cc
@@ -224,6 +224,9 @@ void Game::init()
g_strafespeed = core::Cvar::get("g_strafespeed", "0.003", core::Cvar::Game | core::Cvar::Archive);
g_strafespeed->set_info("[float] strafe speed");
+ g_jumppointrange = core::Cvar::get("g_jumppointrange", "512", core::Cvar::Game | core::Cvar::Archive);
+ g_jumppointrange->set_info("[float] jumppoint range");
+
g_devel = core::Cvar::get("g_devel", "0", core::Cvar::Archive);
g_devel->set_info("[bool] enable or disable developer mode");
@@ -305,6 +308,65 @@ bool Game::load_world()
return true;
}
+bool Game::got_entity_key(filesystem::IniFile &inifile, core::Entity *entity)
+{
+ std::string shapename;
+ std::string strval;
+ float direction;
+ float pitch;
+ float roll;
+
+ if (inifile.got_key_string("shape", shapename)) {
+
+ if (shapename.compare("axis") == 0) {
+ entity->entity_shape = core::Entity::Axis;
+ return true;
+ } else if (shapename.compare("cube") == 0) {
+ entity->entity_shape = core::Entity::Cube;
+ return true;
+ } else if (shapename.compare("diamond") == 0) {
+ entity->entity_shape = core::Entity::Diamond;
+ return true;
+ } else if (shapename.compare("sphere") == 0) {
+ entity->entity_shape = core::Entity::Sphere;
+ return true;
+ } else {
+ con_warn << inifile.name() << " unknown shape '" << shapename << "' at line " << inifile.line() << std::endl;
+ return false;
+ }
+
+ } else if (inifile.got_key_string("label", strval)) {
+ aux::to_label(strval);
+ entity->entity_label.assign(strval);
+ return true;
+ } else if (inifile.got_key_string("name", strval)) {
+ aux::strip_quotes(strval);
+ entity->entity_name.assign(strval);
+ return true;
+ } else if (inifile.got_key_string("model", entity->entity_modelname)) {
+ return true;
+ } else if (inifile.got_key_angle("direction", direction)) {
+ entity->axis().change_direction(direction);
+ return true;
+ } else if (inifile.got_key_angle("pitch", pitch)) {
+ entity->axis().change_pitch(pitch);
+ return true;
+ } else if (inifile.got_key_angle("roll", roll)) {
+ entity->axis().change_roll(roll);
+ return true;
+ } else if (inifile.got_key_angle("radius", entity->entity_radius)) {
+ return true;
+ } else if (inifile.got_key_vector3f("location", entity->entity_location)) {
+ return true;
+ } else if (inifile.got_key_color("color", entity->entity_color)) {
+ return true;
+ } else if (inifile.got_key_color("colorsecond", entity->entity_color_second)) {
+ return true;
+ }
+
+ return false;
+}
+
bool Game::load_zone(core::Zone *zone)
{
using math::Vector3f;
@@ -331,10 +393,6 @@ bool Game::load_zone(core::Zone *zone)
CheckPoint *checkpoint = 0;
core::Entity *entity = 0;
- float direction;
- float pitch;
- float roll;
-
bool b;
std::string strval;
@@ -346,6 +404,7 @@ bool Game::load_zone(core::Zone *zone)
if (zoneini.got_key()) {
if (zoneini.section().compare("zone") == 0) {
if (zoneini.got_key_string("name", strval)) {
+ aux::strip_quotes(strval);
zone->set_name(strval);
continue;
} else if (zoneini.got_key_string("sky", strval)) {
@@ -358,77 +417,32 @@ bool Game::load_zone(core::Zone *zone)
con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl;
}
} else if (zoneini.section().compare("star") == 0) {
-
- if (zoneini.got_key_string("label", strval)) {
- aux::to_label(strval);
- star->entity_label.assign(strval);
- continue;
- } else if (zoneini.got_key_string("name", star->entity_name)) {
- continue;
- } else if (zoneini.got_key_vector3f("location", star->entity_location )) {
- continue;
- } else if (zoneini.got_key_color("color", star->entity_color)) {
- continue;
- } else if (zoneini.got_key_angle("radius", star->entity_radius)) {
- continue;
- } else if (zoneini.got_key_angle("direction", direction)) {
- star->axis().change_direction(direction);
+ if (got_entity_key(zoneini, star)) {
continue;
} else if (zoneini.got_key_string("texture", star->entity_texture)) {
continue;
- } else if (zoneini.got_key_angle("pitch", pitch)) {
- star->axis().change_pitch(pitch);
- continue;
} else {
con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl;
}
} else if (zoneini.section().compare("navpoint") == 0) {
- if (zoneini.got_key_string("label", strval)) {
- aux::to_label(strval);
- navpoint->entity_label.assign(strval);
- continue;
- } else if (zoneini.got_key_string("name", navpoint->entity_name)) {
- continue;
- } else if (zoneini.got_key_vector3f("location", navpoint->entity_location )) {
+ if (got_entity_key(zoneini, navpoint)) {
continue;
} else {
con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl;
}
} else if (zoneini.section().compare("jumppoint") == 0) {
- if (zoneini.got_key_string("label", strval)) {
- aux::to_label(strval);
- jumppoint->entity_label.assign(strval);
- continue;
- } else if (zoneini.got_key_string("name", jumppoint->entity_name)) {
+ if (got_entity_key(zoneini, jumppoint)) {
continue;
} else if (zoneini.got_key_string("target", jumppoint->jumppoint_targetlabel)) {
continue;
- } else if (zoneini.got_key_vector3f("location", jumppoint->entity_location )) {
- continue;
} else {
con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl;
}
} else if (zoneini.section().compare("planet") == 0) {
- if (zoneini.got_key_string("label", strval)) {
- aux::to_label(strval);
- planet->entity_label.assign(strval);
- continue;
- } else if (zoneini.got_key_string("name", planet->entity_name)) {
+ if (got_entity_key(zoneini, planet)) {
continue;
} else if (zoneini.got_key_string("texture", planet->entity_texture)) {
continue;
- } else if (zoneini.got_key_vector3f("location", planet->entity_location )) {
- continue;
- } else if (zoneini.got_key_color("color", planet->entity_color)) {
- continue;
- } else if (zoneini.got_key_angle("radius", planet->entity_radius)) {
- continue;
- } else if (zoneini.got_key_angle("direction", direction)) {
- planet->axis().change_direction(direction);
- continue;
- } else if (zoneini.got_key_angle("pitch", pitch)) {
- planet->axis().change_pitch(pitch);
- continue;
} else if (zoneini.got_key_float("rotationspeed", planet->entity_rotationspeed)) {
continue;
} else {
@@ -436,88 +450,21 @@ bool Game::load_zone(core::Zone *zone)
}
} else if (zoneini.section().compare("racetrack") == 0) {
- if (zoneini.got_key_string("label", strval)) {
- aux::to_label(strval);
- racetrack->entity_label.assign(strval);
- continue;
- } else if (zoneini.got_key_string("name", racetrack->entity_name)) {
- continue;
- } else if (zoneini.got_key_vector3f("location", racetrack->entity_location )) {
- continue;
- } else if (zoneini.got_key_color("color", racetrack->entity_color)) {
- continue;
- } else if (zoneini.got_key_angle("direction", direction)) {
- racetrack->axis().change_direction(direction);
- continue;
- } else if (zoneini.got_key_angle("pitch", pitch)) {
- racetrack->axis().change_pitch(pitch);
- continue;
- } else if (zoneini.got_key_string("model", racetrack->entity_modelname)) {
+ if (got_entity_key(zoneini, racetrack)) {
continue;
} else {
con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl;
}
} else if (zoneini.section().compare("checkpoint") == 0) {
- if (zoneini.got_key_string("label", strval)) {
- aux::to_label(strval);
- checkpoint->entity_label.assign(strval);
- continue;
- } else if (zoneini.got_key_string("name", checkpoint->entity_name)) {
- continue;
- } else if (zoneini.got_key_vector3f("location", checkpoint->entity_location )) {
- continue;
- } else if (zoneini.got_key_angle("direction", direction)) {
- checkpoint->axis().change_direction(direction);
- continue;
- } else if (zoneini.got_key_angle("pitch", pitch)) {
- checkpoint->axis().change_pitch(pitch);
- continue;
- } else if (zoneini.got_key_string("model", checkpoint->entity_modelname)) {
+ if (got_entity_key(zoneini, checkpoint)) {
continue;
} else {
con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl;
}
} else if (zoneini.section().compare("entity") == 0) {
- std::string shapename;
- if (zoneini.got_key_string("shape", shapename)) {
- if (shapename.compare("axis") == 0) {
- entity->entity_shape = core::Entity::Axis;
- } else if (shapename.compare("cube") == 0) {
- entity->entity_shape = core::Entity::Cube;
- } else if (shapename.compare("diamond") == 0) {
- entity->entity_shape = core::Entity::Diamond;
- } else if (shapename.compare("sphere") == 0) {
- entity->entity_shape = core::Entity::Sphere;
- } else {
- con_warn << zoneini.name() << " unknown shape '" << shapename << "' at line " << zoneini.line() << std::endl;
- }
- continue;
- } else if (zoneini.got_key_string("label", strval)) {
- aux::to_label(strval);
- entity->entity_label.assign(strval);
- continue;
- } else if (zoneini.got_key_string("name", entity->entity_name)) {
- continue;
- } else if (zoneini.got_key_string("model", entity->entity_modelname)) {
- continue;
- } else if (zoneini.got_key_angle("direction", direction)) {
- entity->axis().change_direction(direction);
- continue;
- } else if (zoneini.got_key_angle("pitch", pitch)) {
- entity->axis().change_pitch(pitch);
- continue;
- } else if (zoneini.got_key_angle("roll", roll)) {
- entity->axis().change_roll(roll);
- continue;
- } else if (zoneini.got_key_angle("radius", entity->entity_radius)) {
- continue;
- } else if (zoneini.got_key_vector3f("location", entity->entity_location)) {
- continue;
- } else if (zoneini.got_key_color("color", entity->entity_color)) {
- continue;
- } else if (zoneini.got_key_color("colorsecond", entity->entity_color_second)) {
+ if (got_entity_key(zoneini, entity)) {
continue;
} else {
con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl;
@@ -576,6 +523,8 @@ bool Game::load_zone(core::Zone *zone)
bool Game::validate_zone(core::Zone *zone)
{
+ con_debug << " validating " << zone->name() << std::endl;
+
for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) {
core::Entity *entity = (*it);
@@ -614,7 +563,7 @@ bool Game::validate_zone(core::Zone *zone)
jumppoint->jumppoint_target = static_cast<JumpPoint *>(targetentity);
- con_debug << " Jump point " << zone->label() << ":" << jumppoint->label() << " with target " << jumppoint->targetlabel() << std::endl;
+ //con_debug << " Jumppoint " << zone->label() << ":" << jumppoint->label() << " with target " << jumppoint->targetlabel() << std::endl;
}
}
diff --git a/src/game/game.h b/src/game/game.h
index c7ec040..3b65da1 100644
--- a/src/game/game.h
+++ b/src/game/game.h
@@ -7,16 +7,15 @@
#ifndef __INCLUDED_GAME_H__
#define __INCLUDED_GAME_H__
-// project headers
+#include <vector>
+#include <string>
+
+#include "filesystem/inifile.h"
#include "game/ship.h"
#include "game/star.h"
#include "core/core.h"
#include "sys/sys.h"
-// C++ headers
-#include <vector>
-#include <string>
-
/// the game-specific engine
/** The main game functions.
*/
@@ -55,10 +54,13 @@ public:
core::Cvar *g_impulsespeed;
core::Cvar *g_impulseacceleration;
core::Cvar *g_strafespeed;
+ core::Cvar *g_jumppointrange;
core::Cvar *g_devel;
private:
+ bool got_entity_key(filesystem::IniFile &inifile, core::Entity *entity);
+
bool load_world();
bool load_zone(core::Zone *zone);
diff --git a/src/game/jumppoint.cc b/src/game/jumppoint.cc
index a5f9b1a..d2c6bc1 100644
--- a/src/game/jumppoint.cc
+++ b/src/game/jumppoint.cc
@@ -13,13 +13,13 @@ namespace game
JumpPoint::JumpPoint() : core::Entity(core::Entity::Static)
{
entity_shape = core::Entity::Diamond;
- entity_color.assign(0.8f, 0.0f, 0.0f, 1.0f);
+ entity_color.assign(0.0f, 0.8f, 0.8f, 1.0f);
entity_color_second.assign(0.6f, 1.0f);
entity_radius = 0.25f;
entity_moduletypeid = jumppoint_enttype;
jumppoint_target = 0;
- entity_serverside = true;
+ entity_serverside = false;
}
JumpPoint::~JumpPoint()
diff --git a/src/game/racetrack.cc b/src/game/racetrack.cc
index 897a839..cfacb82 100644
--- a/src/game/racetrack.cc
+++ b/src/game/racetrack.cc
@@ -56,6 +56,9 @@ void RaceTrack::add_checkpoint(CheckPoint *checkpoint)
void RaceTrack::reset()
{
+ if (track_player) {
+ track_player->set_mission_target(0);
+ }
track_player = 0;
track_racestart = 0;
track_checkpointtime = 0;
@@ -64,8 +67,7 @@ void RaceTrack::reset()
(*cpit)->set_eventstate(core::Entity::NoPower);
}
- entity_eventstate |= core::Entity::NoPower;
- entity_dirty = true;
+ set_eventstate(core::Entity::NoPower);
}
void RaceTrack::frame(float seconds)
@@ -93,6 +95,7 @@ void RaceTrack::frame(float seconds)
message.append(track_player->name());
message.append(" ^Bactivated the race! Race starts in 5...");
core::server()->broadcast(message);
+ track_player->set_mission_target(this);
return;
}
}
@@ -149,6 +152,7 @@ void RaceTrack::frame(float seconds)
track_checkpointtime = core::server()->time() + 15.0f;
track_checkpoint = track_checkpoints.begin();
(*track_checkpoint)->set_eventstate(core::Entity::Normal);
+ track_player->set_mission_target((*track_checkpoint));
}
}
@@ -175,16 +179,13 @@ void RaceTrack::frame(float seconds)
(*track_checkpoint)->set_eventstate(core::Entity::NoPower);
track_checkpoint++;
(*track_checkpoint)->set_eventstate(core::Entity::Normal);
+ track_player->set_mission_target((*track_checkpoint));
} else {
std::stringstream msgstr;
msgstr << "^BRace completed in " << core::server()->time() - track_racestart << " seconds!";
core::server()->broadcast(msgstr.str());
- track_player = 0;
- track_racestart = 0;
- track_checkpointtime = 0;
-
reset();
}
}
diff --git a/src/game/ship.cc b/src/game/ship.cc
index 0dde90e..1828172 100644
--- a/src/game/ship.cc
+++ b/src/game/ship.cc
@@ -118,7 +118,7 @@ void Ship::jump(std::string const &args)
return;
}
- core::server()->send(owner(), "Jumping to '" + jumptargetzone->name() + '\'');
+ core::server()->send(owner(), "Jumping to the " + jumptargetzone->name());
set_zone(jumptargetzone);
if (owner()->control() == (EntityControlable*) this)
owner()->set_zone(jumptargetzone);
@@ -145,6 +145,10 @@ void Ship::jump(std::string const &args)
return;
}
+ if (!find_closest_jumppoint()) {
+ return;
+ }
+
entity_eventstate = core::Entity::JumpInitiate;
if (Game::instance()->g_devel->value()) {
entity_timer = 0;
@@ -157,6 +161,39 @@ void Ship::jump(std::string const &args)
}
}
+JumpPoint * Ship::find_closest_jumppoint()
+{
+ // find closest jumppoint
+ float d = -1;
+ JumpPoint *jumppoint = 0;
+ for (core::Zone::Content::iterator it = zone()->content().begin(); it != zone()->content().end(); it++) {
+ core::Entity *entity = (*it);
+ if (entity->moduletype() == jumppoint_enttype) {
+ JumpPoint *te = static_cast<JumpPoint *>(entity);
+ float d1 = math::distance(location(), te->location());
+ if ((d < 0) || (d1 < d)) {
+ d = d1;
+ jumppoint = te;
+ }
+ }
+ }
+
+ if (jumppoint && jumppoint->target()) {
+ if (Game::instance()->g_jumppointrange->value() < d) {
+ core::server()->send(owner(), "Jumppoint out of range!");
+ return 0;
+ } else {
+ core::server()->send(owner(), "Jumping to the " + jumppoint->target()->zone()->name());
+ return jumppoint;
+ }
+ } else {
+ core::server()->send(owner(), "No jumppoints found!");
+ return 0;
+ }
+
+ return 0;
+}
+
void Ship::frame(float seconds)
{
const float direction_change_speed = 2;
@@ -184,29 +221,15 @@ void Ship::frame(float seconds)
entity_timer -= 1.0f;
if (entity_timer <= 0) {
- // find closest jumppoint
- float d = -1;
- JumpPoint *jumppoint = 0;
- for (core::Zone::Content::iterator it = zone()->content().begin(); it != zone()->content().end(); it++) {
- core::Entity *entity = (*it);
- if (entity->moduletype() == jumppoint_enttype) {
- JumpPoint *te = static_cast<JumpPoint *>(entity);
- float d1 = math::distance(location(), te->location());
- if ((d < 0) || (d1 < d1)) {
- d = d1;
- jumppoint = te;
- }
- }
- }
- if (jumppoint && jumppoint->target()) {
- core::server()->send(owner(), "Jumping to '" + jumppoint->target()->zone()->name() + '\'');
+ JumpPoint *jumppoint = find_closest_jumppoint();
+
+ if (jumppoint) {
set_zone(jumppoint->target()->zone());
if (owner()->control() == (EntityControlable*) this)
owner()->set_zone(jumppoint->target()->zone());
entity_eventstate = core::Entity::Jump;
entity_location.assign(jumppoint->target()->location() + location() - jumppoint->location());
} else {
- core::server()->send(owner(), "Jump failed!");
entity_eventstate = core::Entity::Normal;
}
ship_jumpdrive_timer = 0;
diff --git a/src/game/ship.h b/src/game/ship.h
index 568997c..3a62a9d 100644
--- a/src/game/ship.h
+++ b/src/game/ship.h
@@ -49,7 +49,9 @@ private:
bool ship_jumpdrive;
float ship_jumpdrive_timer;
- float ship_impulsedrive_timer;
+ float ship_impulsedrive_timer;
+
+ JumpPoint * find_closest_jumppoint();
};
}
diff --git a/src/render/camera.cc b/src/render/camera.cc
index e708b71..53d27f7 100644
--- a/src/render/camera.cc
+++ b/src/render/camera.cc
@@ -138,19 +138,22 @@ void Camera::view_next()
case Free:
// switch camera to Track mode
set_mode(Track);
- core::application()->notify_message(std::string("view: track"));
+ con_print << "view: track" << std::endl;
+ //core::application()->notify_message(core::Message::Info, std::string("view: track"));
break;
case Track:
// switch camera to Cockpit mode
set_mode(Cockpit);
- core::application()->notify_message(std::string("view: cockpit"));
+ con_print << "view: cockpit" << std::endl;
+ //core::application()->notify_message(core::Message::Info, std::string("view: cockpit"));
break;
case Cockpit:
// switch camera to Free mode
set_mode(Free);
- core::application()->notify_message(std::string("view: free"));
+ con_print << "view: free" << std::endl;
+ //core::application()->notify_message(core::Message::Info, std::string("view: free"));
break;
default:
@@ -170,19 +173,22 @@ void Camera::view_previous()
case Cockpit:
// switch camera to Track mode
set_mode(Track);
- core::application()->notify_message(std::string("view: track"));
+ con_print << "view: track" << std::endl;
+ //core::application()->notify_message(std::string("view: track"));
break;
case Free:
// switch camera to Cockpit mode
set_mode(Cockpit);
- core::application()->notify_message(std::string("view: cockpit"));
+ con_print << "view: cockpit" << std::endl;
+ //core::application()->notify_message(std::string("view: cockpit"));
break;
case Track:
// switch camera to Free mode
set_mode(Free);
- core::application()->notify_message(std::string("view: free"));
+ con_print << "view: free" << std::endl;
+ //core::application()->notify_message(std::string("view: free"));
break;
default:
diff --git a/src/render/render.cc b/src/render/render.cc
index e91be23..8fce251 100644
--- a/src/render/render.cc
+++ b/src/render/render.cc
@@ -22,8 +22,6 @@
namespace render {
-GLuint textures[32];
-
core::Cvar *r_arraysize = 0;
core::Cvar *r_bbox = 0;
core::Cvar *r_grid = 0;
@@ -32,31 +30,11 @@ core::Cvar *r_sky = 0;
core::Cvar *r_wireframe = 0;
using model::VertexArray;
-
VertexArray *vertexarray = 0;
-bool texture(const char *filename, size_t id)
+void func_list_textures(std::string const &args)
{
- Image *image = TGA::load(filename);
- if (!image)
- return false;
-
- glGenTextures(1, &textures[id]);
- glBindTexture(GL_TEXTURE_2D, textures[id]);
-
- int texture_type;
- if (image->channels() == 4)
- texture_type = GL_RGBA;
- else
- texture_type = GL_RGB;
-
- gluBuild2DMipmaps(GL_TEXTURE_2D, image->channels(),
- image->width(), image->height(), texture_type, GL_UNSIGNED_BYTE, image->data());
-
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);
-
- return true;
+ Textures::list();
}
void init()
@@ -101,12 +79,13 @@ void init()
Text::init();
Dust::init();
+
+ core::Func *func = core::Func::add("list_textures", func_list_textures);
+ func->set_info("list loaded textures");
}
-void shutdown()
+void clear()
{
- con_print << "^BShutting down renderer..." << std::endl;
-
// clear zone sky textures
for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) {
core::Zone *zone = (*it).second;
@@ -132,6 +111,30 @@ void shutdown()
// clear vertex array
delete vertexarray;
vertexarray = 0;
+}
+
+void unload()
+{
+ clear();
+
+ Textures::shutdown();
+ Textures::init();
+ size_t mb = (size_t) r_arraysize->value();
+ if (mb < 4 * sizeof(float))
+ mb = 4 * sizeof(float);
+ if (mb > 256)
+ mb = 256;
+ (*r_arraysize) = (float) mb;
+ vertexarray = new VertexArray(mb);
+
+}
+void shutdown()
+{
+ con_print << "^BShutting down renderer..." << std::endl;
+
+ core::Func::remove("list_textures");
+
+ clear();
Text::shutdown();
diff --git a/src/render/render.h b/src/render/render.h
index 2a8952e..5d8d12f 100644
--- a/src/render/render.h
+++ b/src/render/render.h
@@ -12,8 +12,13 @@
#include "render/camera.h"
#include "render/draw.h"
+#include "render/dust.h"
#include "render/gl.h"
+#include "render/jpgfile.h"
+#include "render/pngfile.h"
+#include "render/image.h"
#include "render/text.h"
+#include "render/textures.h"
#include "render/tga.h"
namespace render {
@@ -24,6 +29,9 @@ namespace render {
/// shutdown the render subsystem
void shutdown();
+ /// unload render data
+ void unload();
+
extern core::Cvar *r_arraysize;
extern core::Cvar *r_bbox;
extern core::Cvar *r_grid;
diff --git a/src/render/textures.cc b/src/render/textures.cc
index a041c32..b6b7f05 100644
--- a/src/render/textures.cc
+++ b/src/render/textures.cc
@@ -19,14 +19,18 @@ namespace render
{
std::map<std::string, size_t> Textures::registry;
-size_t Textures::index = 0;
GLuint Textures::textures[MAXTEXTURES];
void Textures::init()
{
- clear();
con_print << "^BLoading textures..." << std::endl;
+ if (registry.size()) {
+ clear();
+ } else {
+ memset(textures,0, sizeof(textures));
+ }
+
// "no texture" bitmap
load("textures/common/notex");
@@ -51,14 +55,54 @@ void Textures::shutdown()
clear();
}
+void Textures::list()
+{
+ for (iterator it = registry.begin(); it != registry.end(); it++) {
+ con_print << " " << (*it).first << " " << (*it).second << std::endl;
+ }
+ con_print << registry.size() << " loaded textures" << std::endl;
+}
+
void Textures::clear()
{
- if (index)
- glDeleteTextures(index, textures);
+ for (size_t i=0; i < MAXTEXTURES; i++) {
+ if (textures[i]) {
+ glDeleteTextures(1, &textures[i]);
+ }
+ }
registry.clear();
memset(textures,0, sizeof(textures));
- index = 0;
+}
+
+void Textures::unload(std::string name)
+{
+ iterator it = registry.find(name);
+ if (it != registry.end()) {
+ con_debug << " unloading " << (*it).first << std::endl;
+ size_t id = (*it).second;
+ if (textures[id]) {
+ glDeleteTextures(1, &textures[id]);
+ }
+ registry.erase(it);
+
+ }
+}
+
+void Textures::unload(size_t id)
+{
+ // find in map
+ for (iterator it = registry.begin(); it != registry.end(); it++) {
+ if ((*it).second == id) {
+ con_debug << " unloading " << (*it).first << std::endl;
+ size_t id = (*it).second;
+ if (textures[id]) {
+ glDeleteTextures(1, &textures[id]);
+ }
+ registry.erase(it);
+ break;
+ }
+ }
}
size_t Textures::load(std::string name, bool filter)
@@ -68,7 +112,12 @@ size_t Textures::load(std::string name, bool filter)
if (it != registry.end())
return (*it).second;
- if (index == MAXTEXTURES) {
+ // find first available texture
+ size_t id = 0;
+ while ((id < MAXTEXTURES) && (textures[id])) {
+ id++;
+ }
+ if (id == MAXTEXTURES) {
con_error << "Texture limit " << MAXTEXTURES << " exceeded!" << std::endl;
registry[name] = 0;
return 0;
@@ -105,8 +154,6 @@ size_t Textures::load(std::string name, bool filter)
return 0;
}
- size_t id = index;
-
glGenTextures(1, &textures[id]);
glBindTexture(GL_TEXTURE_2D, textures[id]);
@@ -123,7 +170,6 @@ size_t Textures::load(std::string name, bool filter)
// add to the registry
registry[name] = id;
- index++;
// delete image data
delete image;
@@ -157,7 +203,7 @@ size_t Textures::bind(std::string name, bool filter)
size_t Textures::bind(size_t texture, bool filter)
{
size_t id = texture;
- if (texture >= index)
+ if (!textures[id])
id = 0;
glBindTexture(GL_TEXTURE_2D, textures[id]);
@@ -175,4 +221,5 @@ void Textures::set_filter(bool filter)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
}
+
}
diff --git a/src/render/textures.h b/src/render/textures.h
index 43e312d..aa47bfa 100644
--- a/src/render/textures.h
+++ b/src/render/textures.h
@@ -43,15 +43,22 @@ public:
/// find the texture index for a given name
static size_t find(std::string name);
+ /// unload a texture
+ static void unload(size_t id);
+
+ /// unload a texture
+ static void unload(std::string name);
+
+ /// list loaded textures
+ static void list();
+
private:
static void clear();
-
static void set_filter(bool filter);
typedef std::map<std::string, size_t>::iterator iterator;
static std::map<std::string, size_t> registry;
- static size_t index;
static GLuint textures[MAXTEXTURES];
};