diff options
| author | Stijn Buys <ingar@osirion.org> | 2008-09-27 17:16:15 +0000 | 
|---|---|---|
| committer | Stijn Buys <ingar@osirion.org> | 2008-09-27 17:16:15 +0000 | 
| commit | ca0c1d3e6f8b5fa4eb2e0a86fcf47b12fb600786 (patch) | |
| tree | 5d72e330f11350065806e83cc8712693241b9aad | |
| parent | 29984680d6e0e52efec489497b1796e056164442 (diff) | |
mission targets, texture unloading, private messages
38 files changed, 751 insertions, 374 deletions
| @@ -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];  }; | 
