diff options
author | Stijn Buys <ingar@osirion.org> | 2008-07-28 19:37:31 +0000 |
---|---|---|
committer | Stijn Buys <ingar@osirion.org> | 2008-07-28 19:37:31 +0000 |
commit | d389a31f9816b55d8c7685ec24b9ab814252d693 (patch) | |
tree | 9b2577692e543fa6c59fcda508f92c3eb839ac7a | |
parent | 17408276791033e8122819185abf3bcb01740105 (diff) |
zone support
40 files changed, 885 insertions, 395 deletions
diff --git a/doc/STORYLINE b/doc/STORYLINE index 966feb6..33f532b 100644 --- a/doc/STORYLINE +++ b/doc/STORYLINE @@ -9,16 +9,15 @@ PLACES Borderworlds: -System? - Planet Seymour - Regula mining operation - - asteroid field - +Ghant System Planet Ghant Alexandria outpost Battleship custodian + Planet Seymour + Regula mining operation + + asteroid field Central worlds: @@ -34,8 +33,8 @@ laughed it the mere idea, but in these outskirts of the galaxy chocolate was a hard to find commodity. And fresh milk? You'd have to have almost criminal connections to find it. fortunatly I had, and I did. These were times for celebration. I had spend the loan I managed to get -from the local planetairy bank on a small transort ship and just finished -my first cargo shipment of <insert silly ore here> from the Regula mining +from the local planetairy bank on a small transort ship and I had just +finished my first day of <insert silly ore here> transport from the Regula mining operation to Alexandria outpost. Not the glorious life I had gotten used to on the central planets, but at least a decent one with its small pleasures once in a while, like the cup of chocolate milk. The hundred credits I payed @@ -56,7 +55,7 @@ We shared a few memories of distant times but it didn't take hime very long to c to the point. Brent was the business type. "The rising star of the Regula mining operations, -overseeing all shipments og <fancy ore> in the Orion sector", to quote his words. +overseeing all shipments of <fancy ore> in the Ghant system", to quote his words. His phrases like "A smart man could make a fortune" sounded rather hollow to me, but he did have a point. 500 runs to Regula to pay the loan for the ship. Another 1500 more to get myself a ship big enough to hold a small cabin with all the @@ -73,7 +72,9 @@ All it misses is a pair of blasters to shoot the mosquitos from the windshield. That would have added another 50 runs to the price. - +The first two runs went smooth. Nothing unexpected. Pick up supplies at Alexandria, +fly all the way to the Regula mining operation station, exchange the supplies +for a shipment of <insert silly ore name here> and head back. Cali Prime @@ -2,16 +2,15 @@ TODO milestone 1: fix turning (needs more testing) - fix camera frustum clip fix cl_prediction milestone 2: + zones targetting system server-client event system, hit-once lightweight entities explosion events weapon fire events - zones - + milestone 3: gui @@ -25,18 +24,9 @@ filesystem: model: engine flare key (ok) split map loader from model (ok) + model fragments (ok) - load vertices into VertexData - support map classes (e.g. func_rotate), requires class VertexData - - rework textures/shaders - on .map load, convert 'common/entity' to a flag - rename 'entity' to 'primairy' - add 'common/primairy_dark', ''common/secondairy', 'common/secondairy_dark' and convert to flags - sort triangles by flags - render by flag - use quads array and quad flag? - + support model parts (e.g. func rotate) core: connection to remote game (ok) read/write configuration file (ok) @@ -46,11 +36,11 @@ core: globe entity (ok) refactor 'say', it should not be a game function (ok) execute config files (ok) + support entity secondairy color (ok) zones (breaks network proto) game module loading/unloading (breaks network proto, server must send module type) - support entity secondairy color (breaks network proto) - + toggle func to toggle a bool cvar network: @@ -67,7 +57,8 @@ network: group/clan chat (requires groups) rcon authentication, rcon command, servers must be able to disable rcon - fix lag/client prediction + fix lag/client interpolation + rename cl_prediction to cl_interpolation detect and disconnect clients behaving badly client: @@ -78,7 +69,9 @@ client: better crosshair bitmaps (ok) keyboard repeat (ok) fix tracking camera (ok) - + + fix camera frustum clip (size issue, postponed) + shift/ctrl/alt modifier key binds render: @@ -88,8 +81,6 @@ render: texture registry (ok) add small camera light (ok) - text quads render pipe? (see model quads) - - text can't be a in quadpipe -> gui layers test/fix? lighting without sun in world.ini sun light strenght @@ -107,6 +98,8 @@ game: implement player credits entity health/shield/armor gui concept artwork + docking + jumpgates, requires zones win32 port: network not functional (ok) @@ -114,4 +107,4 @@ win32 port: screenshots are broken (ok) sound is broken (ok) - directory creation + directory creation is broken diff --git a/osirion.kdevelop b/osirion.kdevelop index c65b0a6..d40c050 100644 --- a/osirion.kdevelop +++ b/osirion.kdevelop @@ -21,7 +21,7 @@ </general> <kdevautoproject> <general> - <activetarget>src/model/libmodel.la</activetarget> + <activetarget>src/core/libcore.la</activetarget> <useconfiguration>debug</useconfiguration> </general> <run> diff --git a/src/audio/audio.cc b/src/audio/audio.cc index 3be1aa5..3ad640d 100644 --- a/src/audio/audio.cc +++ b/src/audio/audio.cc @@ -39,7 +39,7 @@ void init() Sources::init(); - con_debug << " audio device ^B" << alcGetString(audio_device, ALC_DEFAULT_DEVICE_SPECIFIER) << std::endl; + //con_debug << " audio device ^B" << alcGetString(audio_device, ALC_DEFAULT_DEVICE_SPECIFIER) << std::endl; // the "no sound" sound load("ui/nosnd"); diff --git a/src/audio/wav.cc b/src/audio/wav.cc index 5d118c6..178f199 100644 --- a/src/audio/wav.cc +++ b/src/audio/wav.cc @@ -109,7 +109,7 @@ PCM *Wav::load(std::string const & name) con_warn << "Error reading " << filename << ": file truncated!" << std::endl; } - con_print << " " << filename << " " << pcm->samplerate()<< "Hz " << pcm->bitspersample() << "bit " << + con_debug << " " << filename << " " << pcm->samplerate()<< "Hz " << pcm->bitspersample() << "bit " << pcm->channels() << " chan " << pcm->size() << " bytes" << std::endl; filesystem::close(wav_file); diff --git a/src/client/input.cc b/src/client/input.cc index 6306fc8..d26c3ba 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -4,6 +4,7 @@ the terms and conditions of the GNU General Public License version 2 */ +#include "auxiliary/functions.h" #include "audio/audio.h" #include "core/core.h" #include "client/client.h" @@ -128,6 +129,7 @@ void func_list_keys(std::string const &args) std::stringstream argstr(args); std::string keyname; if (argstr >> keyname) { + aux::lowercase(keyname); keyboard->list_bind(keyname); } else { keyboard->list_keys(); @@ -143,6 +145,7 @@ void func_list_binds(std::string const &args) std::stringstream argstr(args); std::string keyname; if (argstr >> keyname) { + aux::lowercase(keyname); keyboard->list_bind(keyname); } else { keyboard->list_binds(); @@ -158,6 +161,7 @@ void func_bind(std::string const &args) std::stringstream argstr(args); std::string keyname; if (argstr >> keyname) { + aux::lowercase(keyname); if (args.size() > keyname.size()+1) { keyboard->bind(keyname, args.substr(keyname.size()+1)); } else { diff --git a/src/client/keyboard.cc b/src/client/keyboard.cc index d8b14b3..5870e06 100644 --- a/src/client/keyboard.cc +++ b/src/client/keyboard.cc @@ -329,7 +329,7 @@ Key *Keyboard::find(unsigned int keysym) void Keyboard::bind(std::string const &name, const std::string str) { - Key *key = find(aux::lowercase(name)); + Key *key = find(name); if (key) { key->assign(Key::None, str.c_str()); } else { diff --git a/src/client/targets.cc b/src/client/targets.cc index a39943f..666ea6a 100644 --- a/src/client/targets.cc +++ b/src/client/targets.cc @@ -67,8 +67,14 @@ void select_target(core::Entity *entity) void select_target(unsigned int id) { - // FIXME validate - core::Entity * entity = core::Entity::find(id); + if (!core::localcontrol()) + return; + core::Zone *zone = core::localcontrol()->zone(); + if (!zone) + return; + + core::Entity *entity = zone->find_entity(id); + if (entity) select_target(entity); } @@ -77,45 +83,49 @@ void func_target_next(std::string const &args) { if (!core::localcontrol()) return; + core::Zone *zone = core::localcontrol()->zone(); + if (!zone) + return; - if (!core::Entity::registry.size()) { + if (!zone->content().size()) { current_target = 0; current_target_id = 0; return; } - std::map<unsigned int, core::Entity *>::iterator it = core::Entity::registry.begin(); + core::Zone::Content::iterator it = zone->content().begin(); if (!current_target_id) { // first entity - it = core::Entity::registry.begin(); - while (!is_legal_target((*it).second) && it != core::Entity::registry.end()) + it = zone->content().begin(); + while (!is_legal_target((*it)) && it != zone->content().end()) it++; } else { // current entity - it = core::Entity::registry.find(current_target_id); + while (it != zone->content().end() && ((*it)->id() != current_target_id)) + ++it; // next legal entity - if (it != core::Entity::registry.end()) + if (it != zone->content().end()) it++; - if (it == core::Entity::registry.end()) { - it = core::Entity::registry.begin(); + if (it == zone->content().end()) { + it = zone->content().begin(); } - while (!is_legal_target((*it).second)) { + while (!is_legal_target((*it))) { it++; - if (it == core::Entity::registry.end()) - it = core::Entity::registry.begin(); + if (it == zone->content().end()) + it = zone->content().begin(); - if ((*it).first == current_target_id) { - current_target = (*it).second; + if ((*it)->id() == current_target_id) { + current_target = (*it); return; } } } - if (it != core::Entity::registry.end()) { - select_target((*it).second); + if (it != zone->content().end()) { + select_target((*it)); } else { current_target = 0; current_target_id = 0; @@ -127,45 +137,47 @@ void func_target_prev(std::string const &args) { if (!core::localcontrol()) return; + core::Zone *zone = core::localcontrol()->zone(); + if (!zone) + return; - if (!core::Entity::registry.size()) { + if (!zone->content().size()) { current_target = 0; current_target_id = 0; return; } - std::map<unsigned int, core::Entity *>::reverse_iterator rit = core::Entity::registry.rbegin(); + core::Zone::Content::reverse_iterator rit = zone->content().rbegin(); if (!current_target_id) { // last entity - rit = core::Entity::registry.rbegin(); - while (!is_legal_target((*rit).second) && rit != core::Entity::registry.rend()) + rit = zone->content().rbegin(); + while (!is_legal_target((*rit)) && rit != zone->content().rend()) rit++; } else { // current entity - while (rit != core::Entity::registry.rend() && ((*rit).first != current_target_id)) + while (rit != zone->content().rend() && ((*rit)->id() != current_target_id)) ++rit; // previous legal entity - if (rit != core::Entity::registry.rend()) + if (rit != zone->content().rend()) ++rit; - if (rit == core::Entity::registry.rend()) { - rit = core::Entity::registry.rbegin(); + if (rit == zone->content().rend()) { + rit = zone->content().rbegin(); } - while (!is_legal_target((*rit).second)) { + while (!is_legal_target((*rit))) { ++rit; - if (rit == core::Entity::registry.rend()) - rit = core::Entity::registry.rbegin(); + if (rit == zone->content().rend()) + rit = zone->content().rbegin(); - if ((*rit).first == current_target_id) { - current_target = (*rit).second; + if ((*rit)->id() == current_target_id) { + current_target = (*rit); return; } } } - if (rit != core::Entity::registry.rend()) { - select_target((*rit).second); - + if (rit != zone->content().rend()) { + select_target((*rit)); } else { current_target = 0; current_target_id = 0; @@ -260,6 +272,9 @@ void render_entity_sound(core::Entity *entity) // render client targets void frame() { + core::Zone *zone = core::localplayer()->zone(); + if (!zone) + return; /* Notes http://en.wikipedia.org/wiki/Line-plane_intersection @@ -283,8 +298,8 @@ void frame() cursor -= render::Camera::axis().up() * y; math::Vector3f center = render::Camera::eye() + (render::Camera::axis().forward() * (render::Camera::frustum_front() +0.01f)); - for (core::Entity::Registry::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { - core::Entity *entity = (*it).second; + for (core::Zone::Content::iterator it=zone->content().begin(); it != zone->content().end(); it++) { + core::Entity *entity = (*it); // render entity sound render_entity_sound(entity); diff --git a/src/client/view.cc b/src/client/view.cc index eda5cf8..75c4989 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -92,15 +92,13 @@ void draw_status() { using namespace render; - // print the status in the upper left corner std::stringstream status; - if (core::game()) { int minutes = (int) floorf(core::game()->clientframetime() / 60.0f); int seconds = (int) floorf( core::game()->clientframetime() - (float) minutes* 60.0f); status << "^Ntime ^B" << std::setfill(' ') << std::setw(3) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; - Text::draw(video::width-Text::fontwidth()*11-4, 4+Text::fontheight(), status); + Text::draw(video::width-Text::fontwidth()*11-4, 4, status); } // print stats if desired @@ -113,7 +111,8 @@ void draw_status() } stats << "^Ntx ^B"<< std::setw(5) << (core::Stats::network_bytes_sent >> 10) << "\n"; stats << "^Nrx ^B"<< std::setw(5) << (core::Stats::network_bytes_received >> 10) << "\n"; - Text::draw(video::width-Text::fontwidth()*11-4, 4 + Text::fontheight()*3, stats); + + Text::draw(video::width-Text::fontwidth()*11-4, 4 + Text::fontheight()*2, stats); } // draw a basic HUD @@ -136,6 +135,10 @@ void draw_status() Text::draw(4, video::height - Text::fontheight()*2 -4, location); } + if (core::localplayer()->zone()) { + Text::draw(video::width - 4-Text::fontwidth()*24, video::height - Text::fontheight()*3 -4, core::localplayer()->zone()->name()); + } + core::Entity *entity = targets::current(); if (entity) { std::stringstream target; @@ -345,6 +348,8 @@ void frame(float seconds) // Clear the color and depth buffers. gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + render::Stats::clear(); + if (core::application()->connected() && core::game()->serverframetime()) { render::draw(seconds); // draw the world targets::frame(); diff --git a/src/core/Makefile.am b/src/core/Makefile.am index fb32450..6c2c41e 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -1,9 +1,9 @@ METASOURCES = AUTO INCLUDES = -I$(top_srcdir)/src -libcore_la_SOURCES = application.cc commandbuffer.cc clientstate.cc core.cc cvar.cc entity.cc \ - func.cc gameconnection.cc gameinterface.cc gameserver.cc module.cc netclient.cc \ - netconnection.cc netserver.cc player.cc stats.cc +libcore_la_SOURCES = application.cc clientstate.cc commandbuffer.cc core.cc \ + cvar.cc entity.cc func.cc gameconnection.cc gameinterface.cc gameserver.cc \ + module.cc netclient.cc netconnection.cc netserver.cc player.cc stats.cc zone.cc libcore_la_LDFLAGS = -avoid-version -no-undefined libcore_la_LIBADD = $(top_builddir)/src/model/libmodel.la \ $(top_builddir)/src/filesystem/libfilesystem.la $(top_builddir)/src/math/libmath.la $(top_builddir)/src/sys/libsys.la \ diff --git a/src/core/application.cc b/src/core/application.cc index 8234b8f..4d1ef86 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -349,9 +349,7 @@ void Application::save_config() ofs << "# this file is automaticly generated" << std::endl; - Cvar::iterator it; - for (it = Cvar::registry.begin(); it != Cvar::registry.end(); it++) { - + for (Cvar::Registry::iterator it = Cvar::registry().begin(); it != Cvar::registry().end(); it++) { if (((*it).second->flags() & Cvar::Archive) == Cvar::Archive) ofs << "set " << (*it).first << " " << (*it).second->str() << std::endl; } diff --git a/src/core/commandbuffer.cc b/src/core/commandbuffer.cc index 80e7e36..c111e17 100644 --- a/src/core/commandbuffer.cc +++ b/src/core/commandbuffer.cc @@ -17,6 +17,7 @@ #include "core/gameconnection.h" #include "core/func.h" #include "core/cvar.h" +#include "core/zone.h" namespace core { @@ -51,31 +52,83 @@ void func_list_ent(std::string const &args) Entity::list(); } +void func_list_zone(std::string const &args) +{ + std::istringstream argstream(args); + std::string zonelabel; + if (argstream >> zonelabel) { + aux::lowercase(zonelabel); + Zone::list_zone(zonelabel); + } else { + Zone::list(); + } +} + void func_set(std::string const &args) { std::istringstream argstream(args); std::string varname; - if (!(argstream >> varname)) + if (!(argstream >> varname)) { + con_print << "Variable name expected!" << std::endl; return; + } aux::to_lowercase(varname); std::string value; if (!(argstream >> value)) { + Cvar *cvar = Cvar::find(varname); + if (cvar) { + con_print << " " << varname << " " << cvar->str() << " ^N" << cvar->info() << "\n"; + } return; } char c; while (argstream.get(c)) value += c; + Cvar *cvar = Cvar::set(varname.c_str(), value.c_str(), Cvar::Archive); + if (cvar->flags() && Cvar::Info) { + localplayer()->player_dirty = true; + } + + con_debug << " " << cvar->name() << " " << cvar->str() << "\n"; +} + +void func_toggle(std::string const &args) +{ + std::istringstream argstream(args); + std::string varname; + if (!(argstream >> varname)) { + con_print << "Variable name expected!" << std::endl; + return; + } - con_print << " " << cvar->name() << " " << cvar->str() << "\n"; + aux::to_lowercase(varname); + + Cvar *cvar = Cvar::find(varname); + if (!cvar) { + con_print << "Unknown variable '" << varname << "'\n"; + return; + } + + float valueone = 1.0f; + if (!(argstream >> valueone)) { + valueone = 1.0f; + } + + if (cvar->value()) { + (*cvar) = 0.0f; + } else { + (*cvar) = valueone; + } if (cvar->flags() && Cvar::Info) { localplayer()->player_dirty = true; } - return; + + con_debug << " " << cvar->name() << " " << cvar->str() << "\n"; } void func_exec(std::string const &args) @@ -104,9 +157,15 @@ void CommandBuffer::init() func = Func::add("list_var", (FuncPtr)func_list_var); func->set_info("list variables"); + func = Func::add("list_zone", (FuncPtr)func_list_zone); + func->set_info("list zones"); + func = Func::add("set", (FuncPtr)func_set); func->set_info("[variable] [str] set variable value"); + func = Func::add("toggle", (FuncPtr)func_toggle); + func->set_info("[variable] toggle a variable"); + func = Func::add("print", func_print); func->set_info("[str] print a message on the console"); @@ -122,9 +181,11 @@ void CommandBuffer::shutdown() //con_debug << "Shutting down command buffer...\n"; Func::remove("set"); + Func::remove("toggle"); Func::remove("list_var"); Func::remove("list_func"); Func::remove("list_ent"); + Func::remove("list_zone"); Func::remove("print"); Func::remove("print_file"); Func::remove("exec"); @@ -220,8 +281,7 @@ void CommandBuffer::complete(std::string &input, size_t &pos) aux::to_lowercase(partial); // search function registry for matches - std::map<std::string, Func *>::iterator f; - for (f = Func::registry.begin(); f != Func::registry.end(); f++) { + for (Func::Registry::iterator f = Func::registry().begin(); f != Func::registry().end(); f++) { if (partial == (*f).first.substr(0, partial.size())) { match.push_back((*f).first); //con_print << " " << (*f).first << "\n"; @@ -229,8 +289,7 @@ void CommandBuffer::complete(std::string &input, size_t &pos) } // search cvar registry for matches - std::map<std::string, Cvar *>::iterator c; - for (c = Cvar::registry.begin(); c != Cvar::registry.end(); c++) { + for (Cvar::Registry::iterator c = Cvar::registry().begin(); c != Cvar::registry().end(); c++) { if (partial == (*c).first.substr(0, partial.size())) { match.push_back((*c).first); //con_print << " " << (*c).first << "\n"; diff --git a/src/core/core.h b/src/core/core.h index a3e13e4..a3c9005 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -17,6 +17,7 @@ #include "core/gameinterface.h" #include "core/module.h" #include "core/player.h" +#include "core/zone.h" /// core contains the basic functionality of the engine namespace core diff --git a/src/core/cvar.cc b/src/core/cvar.cc index 772144f..45f04f3 100644 --- a/src/core/cvar.cc +++ b/src/core/cvar.cc @@ -33,7 +33,7 @@ Cvar *Cvar::net_framerate = 0; Cvar *Cvar::rconpassword = 0; -std::map<std::string, Cvar*> Cvar::registry; +Cvar::Registry Cvar::cvar_registry; Cvar::Cvar(const char *name, unsigned int flags) { @@ -85,7 +85,7 @@ Cvar* Cvar::get(const char *name, const char *value, unsigned int flags) } else { //con_debug << "get " << name << " " << value << std::endl; c = new Cvar(name, flags); - registry[std::string(name)] = c; + cvar_registry[std::string(name)] = c; (*c) = value; } c->cvar_flags |= flags; @@ -100,7 +100,7 @@ Cvar* Cvar::get(const char *name, float value, unsigned int flags) } else { //con_debug << "get " << name << " " << value << std::endl; c = new Cvar(name, flags); - registry[std::string(name)] = c; + cvar_registry[std::string(name)] = c; (*c) = value; } c->cvar_flags |= flags; @@ -112,7 +112,7 @@ Cvar* Cvar::set(const char *name, const char *value, unsigned int flags) Cvar *c = find(name); if (!c) { c = new Cvar(name, flags); - registry[std::string(name)] = c; + cvar_registry[std::string(name)] = c; } (*c) = value; c->cvar_flags = flags; @@ -126,7 +126,7 @@ Cvar* Cvar::set(const char *name, float value, unsigned int flags) Cvar *c = find(name); if (!c) { c = new Cvar(name, flags); - registry[std::string(name)] = c; + cvar_registry[std::string(name)] = c; } (*c) = value; c->cvar_flags = flags; @@ -140,7 +140,7 @@ void Cvar::unset(std::string const &name) Cvar *c = find(name); if (c) { con_debug << "unset " << name << std::endl; - registry.erase(name); + cvar_registry.erase(name); delete c; } } @@ -152,8 +152,8 @@ void Cvar::unset(const char *name) Cvar *Cvar::find(std::string const &name) { - std::map<std::string, Cvar*>::iterator it = registry.find(name); - if (it == registry.end()) + Registry::iterator it = cvar_registry.find(name); + if (it == cvar_registry.end()) return 0; else return (*it).second; @@ -168,8 +168,8 @@ void Cvar::list() { con_print << "Flags: A=Archive G=Game R=ReadOnly" << std::endl; - std::map<std::string, Cvar*>::iterator it; - for (it = registry.begin(); it != registry.end(); it++) { + Registry::iterator it; + for (it = cvar_registry.begin(); it != cvar_registry.end(); it++) { std::string typeindicator; if (((*it).second->flags() & Archive) == Archive) typeindicator += 'A'; @@ -189,7 +189,7 @@ void Cvar::list() con_print << " " << typeindicator << " " << (*it).first << " " << (*it).second->str() << " ^N" << (*it).second->info() << std::endl; } - con_print << registry.size() << " registered variables" << std::endl; + con_print << cvar_registry.size() << " registered variables" << std::endl; } } diff --git a/src/core/cvar.h b/src/core/cvar.h index 7aab5d3..b8e406c 100644 --- a/src/core/cvar.h +++ b/src/core/cvar.h @@ -61,6 +61,9 @@ public: Cvar &operator=(float other); /* ---- Static functions for the Cvar registry -------------------- */ + + /// type definition for the Cvar registry + typedef std::map<std::string, Cvar*> Registry; /// get a cvar value from the registry /** If the a cvar with the given name already exists in the registry, @@ -104,10 +107,7 @@ public: static void list(); /// the Cvar registry - static std::map<std::string, Cvar*> registry; - - /// an iterator for the Cvar registry - typedef std::map<std::string, Cvar*>::iterator iterator; + static inline Registry & registry() { return cvar_registry; } static Cvar *sv_dedicated; // dedicated server static Cvar *sv_private; // client with private server @@ -133,6 +133,8 @@ private: unsigned int cvar_flags; float cvar_value; + static Registry cvar_registry; + }; } diff --git a/src/core/entity.cc b/src/core/entity.cc index c45825b..20e34ee 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -19,17 +19,17 @@ using math::Vector3f; /* ---- Static functions for the Entity registry ------------------- */ -std::map<unsigned int, Entity *> Entity::registry; +Entity::Registry Entity::entity_registry; void Entity::add(Entity *ent) { Registry::iterator it; unsigned int id = 1; - for (it = registry.begin(); it != registry.end() && id == (*it).second->id(); it++) { + for (it = entity_registry.begin(); it != entity_registry.end() && id == (*it).second->id(); it++) { id++; } ent->entity_id = id; - registry[id] = ent; + entity_registry[id] = ent; } void Entity::add(Entity *ent, unsigned int id) @@ -39,33 +39,33 @@ void Entity::add(Entity *ent, unsigned int id) return; } ent->entity_id = id; - registry[id] = ent; + entity_registry[id] = ent; } Entity *Entity::find(unsigned int id) { - std::map<unsigned int, Entity *>::iterator it = registry.find(id); - if (it == registry.end()) + Registry::iterator it = entity_registry.find(id); + if (it == entity_registry.end()) return 0; else return (*it).second; } -void Entity::remove(unsigned int id) +void Entity::erase(unsigned int id) { - std::map<unsigned int, Entity *>::iterator it = registry.find(id); - if (it != registry.end()) { + Registry::iterator it = entity_registry.find(id); + if (it != entity_registry.end()) { delete((*it).second); - registry.erase(it); + entity_registry.erase(it); } else { - con_warn << "Could not remove entity " << id << "!\n"; + con_warn << "Could not erase entity " << id << "!\n"; } } void Entity::list() { - std::map<unsigned int, Entity *>::iterator it; - for (it = registry.begin(); it != registry.end(); it++) { + Registry::iterator it; + for (it = entity_registry.begin(); it != entity_registry.end(); it++) { std::string typeindicator; Entity *entity = (*it).second; con_print << " id " << std::setw(4) << entity->id() @@ -73,7 +73,7 @@ void Entity::list() << ":" << std::setw(4) << entity->moduletype() << " " << entity->label() << std::endl; } - con_print << registry.size() << " registered entities" << std::endl; + con_print << entity_registry.size() << " registered entities" << std::endl; } /*----- Entity ----------------------------------------------------- */ @@ -101,11 +101,15 @@ Entity::Entity(unsigned int flags) : entity_clientstate = 0; + entity_zone = 0; + add(this); } Entity::Entity(std::istream & is) { + entity_zone = 0; + // type is already determined unsigned int s; std::string n; @@ -113,6 +117,13 @@ Entity::Entity(std::istream & is) is >> entity_id; is >> entity_moduletypeid; is >> entity_flags; + is >> s; + + set_zone(Zone::find(s)); + if (entity_zone && !s) { + con_warn << "Received entity " << entity_id << " for unknown zone " << s << "!" << std::endl; + } + is >> entity_location; is >> entity_color; is >> entity_color_second; @@ -162,6 +173,29 @@ Entity::~Entity() { if (entity_clientstate) delete entity_clientstate; + + if (entity_zone) + entity_zone->remove(this); +} + +void Entity::die() +{ + entity_destroyed = true; +} + +void Entity::set_zone(Zone *zone) +{ + if (entity_zone == zone) + return; + + if (entity_zone) + entity_zone->remove(this); + + entity_zone = zone; + entity_dirty = true; + + if (entity_zone) + entity_zone->add(this); } void Entity::serialize(std::ostream & os) const @@ -170,6 +204,7 @@ void Entity::serialize(std::ostream & os) const << entity_id << " " << entity_moduletypeid << " " << entity_flags << " " + << (entity_zone ? entity_zone->id() : 0) << " " << entity_location << " " << entity_color << " " << entity_color_second << " " @@ -186,7 +221,7 @@ void Entity::serialize_client_update(std::ostream & os) const { } -void Entity::recieve_client_update(std::istream &is) +void Entity::receive_client_update(std::istream &is) { } @@ -194,7 +229,7 @@ void Entity::serialize_server_update(std::ostream & os) const { } -void Entity::recieve_server_update(std::istream &is) +void Entity::receive_server_update(std::istream &is) { } @@ -244,42 +279,58 @@ void EntityDynamic::serialize_client_update(std::ostream & os) const { } -void EntityDynamic::recieve_client_update(std::istream &is) +void EntityDynamic::receive_client_update(std::istream &is) { } void EntityDynamic::serialize_server_update(std::ostream & os) const { + os << (entity_zone ? entity_zone->id() : 0) << " "; os << entity_location << " "; os << entity_axis.forward() << " "; os << entity_axis.left() << " "; os << entity_speed; } -void EntityDynamic::recieve_server_update(std::istream &is) +void EntityDynamic::receive_server_update(std::istream &is) { + unsigned int zone_id; + is >> zone_id; is >> entity_location; // axis up vector is the crossproduct of forward and left is >> entity_axis[0]; is >> entity_axis[1]; entity_axis[2] = math::crossproduct(entity_axis.forward(), entity_axis.left()); is >> entity_speed; + + + if (!zone_id) { + if (entity_zone) { + entity_zone->remove(this); + entity_zone = 0; + } + } else { + if (zone_id != entity_zone->id()) { + set_zone(Zone::find(zone_id)); + } + } } /*----- EntityControlable ------------------------------------------ */ -EntityControlable::EntityControlable(Player *player, unsigned int flags) : +EntityControlable::EntityControlable(Player *owner, unsigned int flags) : EntityDynamic(flags) { - entity_owner = player; - if (entity_owner) - entity_owner->add_asset(this); entity_thrust = 0; target_direction = 0.0f; target_thrust = 0.0f; target_pitch = 0.0f; target_roll = 0.0f; + + entity_owner = 0; + if (owner) + owner->add_asset(this); } EntityControlable::EntityControlable(std::istream & is) : @@ -305,7 +356,7 @@ void EntityControlable::serialize(std::ostream & os) const { EntityDynamic::serialize(os); os << " " << entity_thrust; - os << " " << entity_owner->id(); + os << " " << ( entity_owner ? entity_owner->id() : 0); } void EntityControlable::serialize_client_update(std::ostream & os) const @@ -318,9 +369,9 @@ void EntityControlable::serialize_client_update(std::ostream & os) const } -void EntityControlable::recieve_client_update(std::istream &is) +void EntityControlable::receive_client_update(std::istream &is) { - EntityDynamic::recieve_client_update(is); + EntityDynamic::receive_client_update(is); is >> target_direction; is >> target_pitch; is >> target_thrust; @@ -333,9 +384,9 @@ void EntityControlable::serialize_server_update(std::ostream & os) const os << " " << entity_thrust; } -void EntityControlable::recieve_server_update(std::istream &is) +void EntityControlable::receive_server_update(std::istream &is) { - EntityDynamic::recieve_server_update(is); + EntityDynamic::receive_server_update(is); is >> entity_thrust; } diff --git a/src/core/entity.h b/src/core/entity.h index d6000b9..ca2d029 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -25,6 +25,7 @@ class EntityControlable; #include "core/clientstate.h" #include "core/player.h" +#include "core/zone.h" namespace core { @@ -48,7 +49,7 @@ public: /// create a new entity and add it to the registry Entity(unsigned int flags = 0); - /// create an entity froms stream data + /// create an entity from stream data Entity(std::istream & is); /// destroy an entity @@ -83,6 +84,9 @@ public: /// pointer to the model, is used client-side inline model::Model * model() { return entity_model; } + /// pointer to the zone the entity belongs to + inline Zone *zone() const { return entity_zone; } + /// dirty flag inline bool dirty() const { return entity_dirty; } @@ -117,13 +121,13 @@ public: /*----- mutators -------------------------------------------------- */ /// receive a client-to-server update from a stream - virtual void recieve_client_update(std::istream &is); + virtual void receive_client_update(std::istream &is); /// receive a server-to-client update from a stream - virtual void recieve_server_update(std::istream &is); + virtual void receive_server_update(std::istream &is); /// mark the entity as destroyed - inline void die() { entity_destroyed = true; } + void die(); /// runs one game frame for the entity /** @@ -131,23 +135,30 @@ public: */ virtual void frame(float seconds); + /// set the zone the entity is currently in + /** + * this fuction removes the entity from its previous zone + * and removes it to the new one, if it is not 0 + */ + virtual void set_zone(Zone *zone); + /*----- static ---------------------------------------------------- */ /// type definition for the entity registry typedef std::map<unsigned int, Entity*> Registry; - /// the entity registry - static Registry registry; - /// find an entity in the registry static Entity *find(unsigned int id); - /// remove one entity from the registry and deletes it - static void remove(unsigned int entity_id); + /// erase an entity from the registry and delete it + static void erase(unsigned int entity_id); /// list the entity registry static void list(); + /// the entity registry + static inline Registry & registry() { return entity_registry; } + /* entity_ variables can be set by the module */ math::Vector3f entity_location; math::Axis entity_axis; @@ -172,15 +183,23 @@ public: ClientState *entity_clientstate; +protected: + // the zone the entity belongs to + Zone *entity_zone; + private: - /// add an entity to the registry + // add an entity to the registry static void add(Entity *ent); - /// add an entity with id to the registry - void add(Entity *ent, unsigned int id); + // add an entity to the registry + static void add(Entity *ent, unsigned int it); - /// the id is set by add() + // the id is set by add() unsigned int entity_id; + + + // the entity registry + static Registry entity_registry; }; @@ -216,10 +235,10 @@ public: /*----- mutators -------------------------------------------------- */ /// receive a client-to-server update from a stream - virtual void recieve_client_update(std::istream &is); + virtual void receive_client_update(std::istream &is); /// receive a server-to-client update from a stream - virtual void recieve_server_update(std::istream &is); + virtual void receive_server_update(std::istream &is); /// runs one game frame for the entity /** @@ -235,9 +254,11 @@ public: /// an entity that can be controlled by a player class EntityControlable : public EntityDynamic { + friend class Player; + public: /// create a controlable entity - EntityControlable(Player *player, unsigned int flags = 0); + EntityControlable(Player *owner, unsigned int flags = 0); /// create a controlable entity from stream data EntityControlable(std::istream & is); @@ -269,10 +290,10 @@ public: /*----- mutators -------------------------------------------------- */ /// receive a client-to-server update from a stream - virtual void recieve_client_update(std::istream &is); + virtual void receive_client_update(std::istream &is); /// receive a server-to-client update from a stream - virtual void recieve_server_update(std::istream &is); + virtual void receive_server_update(std::istream &is); /// set the target thrust void set_thrust(float thrust); @@ -293,9 +314,6 @@ public: */ virtual void frame(float seconds); - /* entity_ variables can be set by the module */ - /// owner of the entity - Player *entity_owner; /// current thrust float entity_thrust; @@ -314,6 +332,11 @@ public: /** target_roll must be in the [-1, 1] range */ float target_roll; + +private: + // owner of the entity + Player *entity_owner; + }; /// a Globe entity diff --git a/src/core/func.cc b/src/core/func.cc index ad25426..edebc8a 100644 --- a/src/core/func.cc +++ b/src/core/func.cc @@ -16,15 +16,15 @@ namespace core /* ---- Static functions for the Func registry -------------------- */ -std::map<std::string, Func*> Func::registry; +Func::Registry Func::func_registry; Func * Func::add(const char *name, FuncPtr functionptr, unsigned int flags) { Func *func = 0; - std::map<std::string, Func*>::iterator it = registry.find(name); - if (it == registry.end()) { + Registry::iterator it = func_registry.find(name); + if (it == func_registry.end()) { func = new Func(name, (void *)functionptr, flags & ~Func::Game); - registry[std::string(name)] = func; + func_registry[std::string(name)] = func; //con_debug << "Function '" << name << "' registered." << std::endl; } else { con_warn << "Function '" << name << "' already registered!" << std::endl; @@ -36,10 +36,10 @@ Func * Func::add(const char *name, FuncPtr functionptr, unsigned int flags) Func *Func::add(const char *name, GameFuncPtr gamefunctionptr, unsigned int flags) { Func *func = 0; - std::map<std::string, Func*>::iterator it = registry.find(name); - if (it == registry.end()) { + Registry::iterator it = func_registry.find(name); + if (it == func_registry.end()) { func = new Func(name, (void *)gamefunctionptr, flags | Func::Game); - registry[std::string(name)] = func; + func_registry[std::string(name)] = func; //con_debug << "Function '" << name << "' registered." << std::endl; } else { con_warn << "Function '" << name << "' already registered!" << std::endl; @@ -50,20 +50,20 @@ Func *Func::add(const char *name, GameFuncPtr gamefunctionptr, unsigned int flag void Func::remove(const char *name) { - std::map<std::string, Func *>::iterator it = registry.find(std::string(name)); - if (it != registry.end()) { + std::map<std::string, Func *>::iterator it = func_registry.find(std::string(name)); + if (it != func_registry.end()) { delete (*it).second; - registry.erase(it); + func_registry.erase(it); //con_debug << "Function '" << name << "' unregistered." << std::endl; } } void Func::remove(const std::string &name) { - std::map<std::string, Func *>::iterator it = registry.find(name); - if (it != registry.end()) { + std::map<std::string, Func *>::iterator it = func_registry.find(name); + if (it != func_registry.end()) { delete (*it).second; - registry.erase(it); + func_registry.erase(it); //con_debug << "Function '" << name << "' unregistered." << std::endl; } @@ -71,8 +71,8 @@ void Func::remove(const std::string &name) Func *Func::find(const std::string &name) { - std::map<std::string, Func *>::iterator it = registry.find(name); - if (it == registry.end()) + std::map<std::string, Func *>::iterator it = func_registry.find(name); + if (it == func_registry.end()) return 0; else return (*it).second; @@ -80,10 +80,10 @@ Func *Func::find(const std::string &name) void Func::list() { - std::map<std::string, Func*>::iterator it; + Registry::iterator it; con_print << "Flags: G=Game S=Shared" << std::endl; - for (it = registry.begin(); it != registry.end(); it++) { + for (it = func_registry.begin(); it != func_registry.end(); it++) { std::string typeindicator; if (((*it).second->flags() & Game) == Game) typeindicator += 'G'; @@ -96,7 +96,7 @@ void Func::list() con_print << " " << typeindicator << " " << (*it).second->name() << " " << (*it).second->info() << std::endl; } - con_print << registry.size() << " registered functions" << std::endl; + con_print << func_registry.size() << " registered functions" << std::endl; } /* ---- Func ------------------------------------------------------ */ diff --git a/src/core/func.h b/src/core/func.h index d72e583..7c5635f 100644 --- a/src/core/func.h +++ b/src/core/func.h @@ -58,6 +58,9 @@ public: /* ---- Static functions for the Func registry -------------------- */ + /// type definition + typedef std::map<std::string, Func*> Registry; + /// add a function to the registry static Func *add(const char *name, FuncPtr functionptr, unsigned int flags=0); @@ -77,13 +80,15 @@ public: static void list(); /// the function registry - static std::map<std::string, Func*> registry; + static inline Registry & registry() { return func_registry; } private: std::string func_name; std::string func_info; unsigned int func_flags; void *func_ptr; + + static Registry func_registry; }; } diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index be4d288..7833bf5 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -12,6 +12,7 @@ #include "core/func.h" #include "core/gameinterface.h" #include "core/player.h" +#include "core/zone.h" #include "model/model.h" #include "sys/sys.h" @@ -52,12 +53,12 @@ GameInterface::GameInterface() game_localplayer.update_info(); } - core::Func::add("list_model", (core::FuncPtr) func_list_model); + Func::add("list_model", (FuncPtr) func_list_model); } GameInterface::~GameInterface() { - core::Func::remove("list_model"); + Func::remove("list_model"); game_localplayer.clear(); @@ -70,24 +71,30 @@ void GameInterface::clear() //con_debug << "Clearing game data\n"; // remove all entities - for (std::map<unsigned int, Entity*>::iterator it = Entity::registry.begin(); it != Entity::registry.end(); it++) { + for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { delete (*it).second; } - Entity::registry.clear(); + Entity::registry().clear(); + + // remove all zones + for (Zone::Registry::iterator it = Zone::registry().begin(); it != Zone::registry().end(); it++) { + delete (*it).second; + } + Zone::registry().clear(); // remove all game functions - for (std::map<std::string, Func*>::iterator it = Func::registry.begin(); it != Func::registry.end(); it++) { + for (Func::Registry::iterator it = Func::registry().begin(); it != Func::registry().end(); it++) { if ( ((*it).second->flags() & Func::Game) == Func::Game) { delete (*it).second; - Func::registry.erase(it); + Func::registry().erase(it); } } // remove all game cvars - for (std::map<std::string, Cvar*>::iterator it = Cvar::registry.begin(); it != Cvar::registry.end(); it++) { + for (Cvar::Registry::iterator it = Cvar::registry().begin(); it != Cvar::registry().end(); it++) { if ( ((*it).second->flags() & Cvar::Game) == Cvar::Game) { delete (*it).second; - Cvar::registry.erase(it); + Cvar::registry().erase(it); } } @@ -104,12 +111,11 @@ void GameInterface::reset_clientstate(float timestamp, float prevtimestamp) game_previousframetime = prevtimestamp; game_serverframetime = timestamp; - std::map<unsigned int, core::Entity *>::iterator it; - for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { - core::Entity *entity = (*it).second; + Entity *entity = (*it).second; - if (entity->state() && !(entity->flags() & core::Entity::Static)) + if (entity->state() && !(entity->flags() & Entity::Static)) entity->state()->assign(entity); } @@ -124,7 +130,7 @@ void GameInterface::reset_clientstate(float timestamp, float prevtimestamp) void GameInterface::update_entity_clientstate(Entity *entity) { if (!entity->state()) { - entity->entity_clientstate = new core::ClientState(entity); + entity->entity_clientstate = new ClientState(entity); entity->entity_clientstate->assign(entity); } @@ -134,7 +140,7 @@ void GameInterface::update_entity_clientstate(Entity *entity) return; } - if (!(entity->flags() & core::Entity::Static)) { + if (!(entity->flags() & Entity::Static)) { // clientstate location entity->state()->state_location = entity->state()->previouslocation() + @@ -156,7 +162,7 @@ void GameInterface::update_entity_clientstate(Entity *entity) if (angle > MIN_DELTA) entity->state()->state_axis.rotate(n, -angle); } - + /* n.assign(math::crossproduct( entity->state()->axis().left(), entity->axis().left())); if (!(n.length() < MIN_DELTA)) { n.normalize(); @@ -174,7 +180,7 @@ void GameInterface::update_entity_clientstate(Entity *entity) if (angle > MIN_DELTA) entity->state()->state_axis.rotate(n, -angle); } - + */ } else { entity->state()->state_axis.assign(entity->axis()); } @@ -188,8 +194,7 @@ void GameInterface::update_clientstate(float seconds) { game_clientframetime += seconds; - std::map<unsigned int, core::Entity *>::iterator it; - for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { update_entity_clientstate((*it).second); } } diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index afdc269..db8852a 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -188,10 +188,10 @@ GameServer::~GameServer() server_network = 0; } - if (!Cvar::sv_dedicated->value()) - player_disconnect(localplayer()); - if (server_module) { + if (server_module->running() && !Cvar::sv_dedicated->value()) + player_disconnect(localplayer()); + server_module->shutdown(); if (server_module != Module::preload()) @@ -480,6 +480,9 @@ void GameServer::player_disconnect(Player *player) message.append("^B disconnects."); broadcast(message, player); + // clear all player assets + player->clear_assets(); + // notify the game module server_module->player_disconnect(player); @@ -533,8 +536,7 @@ void GameServer::frame(float seconds) } // run a time frame on each entity - std::map<unsigned int, Entity *>::iterator it; - for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { + for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); it++) { Entity *entity = (*it).second; if ((entity->type() == Entity::Controlable) || (entity->type() == Entity::Dynamic)) { @@ -562,8 +564,7 @@ void GameServer::frame(float seconds) server_network->broadcast_frame(server_time, server_previoustime); // send changes in the world - std::map<unsigned int, Entity *>::iterator it; - for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { + for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); it++) { Entity *entity = (*it).second; @@ -573,7 +574,7 @@ void GameServer::frame(float seconds) server_network->broadcast_entity_delete(entity); } - core::Entity::remove(entity->id()); + core::Entity::erase(entity->id()); } else if (entity->entity_created) { @@ -597,12 +598,12 @@ void GameServer::frame(float seconds) } else { // local update stub - std::map<unsigned int, Entity *>::iterator it; - for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { + for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); it++) { Entity *entity = (*it).second; if (entity->entity_destroyed) { - core::Entity::remove(entity->id()); + Entity::erase(entity->id()); + } else if (entity->entity_created) { entity->entity_created = false; diff --git a/src/core/net.h b/src/core/net.h index 177aa14..c80b979 100644 --- a/src/core/net.h +++ b/src/core/net.h @@ -11,7 +11,7 @@ namespace core { /// network protocol version -const unsigned int PROTOCOLVERSION = 2; +const unsigned int PROTOCOLVERSION = 3; /// 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 1bda423..db8e3a2 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -394,6 +394,7 @@ void NetConnection::send_say(std::string const &text) * frame * sup * pif + * zone */ void NetConnection::parse_incoming_message(const std::string & message) { @@ -453,9 +454,9 @@ void NetConnection::parse_incoming_message(const std::string & message) //con_debug << "Received die entity id " << id << std::endl; Entity *e = Entity::find(id); if (localcontrol() == e) - localplayer()->player_control = 0; + localplayer()->set_control(0); if (e) - Entity::remove(id); + Entity::erase(id); } } else if (command == "ent") { @@ -481,9 +482,25 @@ void NetConnection::parse_incoming_message(const std::string & message) break; } } + } else if (command.compare("zone") == 0) { + unsigned int id; + std::string label; + if (msgstream >> id) { + con_debug << "Received create zone " << id << std::endl; + Zone * zone = Zone::find(id); + + // create the zone if necessary + if (!zone) { + zone = new Zone(msgstream); + Zone::add(zone, id); + } else { + zone->receive_server_update(msgstream); + } + } + } else if (command == "pif") { //con_debug << "Received update player info" << std::endl; - connection()->localplayer()->recieve_server_update(msgstream); + connection()->localplayer()->receive_server_update(msgstream); } else if (command == "sup") { if (connection_state == Connected) @@ -497,7 +514,7 @@ void NetConnection::parse_incoming_message(const std::string & message) con_warn << "Update for unknown entity " << id << std::endl; } else { // FIXME check of the received update matches the actual entity - entity->recieve_server_update(msgstream); + entity->receive_server_update(msgstream); } } } diff --git a/src/core/netserver.cc b/src/core/netserver.cc index 2e50efd..10fd554 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -29,6 +29,7 @@ #include "core/func.h" #include "core/core.h" #include "core/stats.h" +#include "core/zone.h" #ifdef _WIN32 typedef int socklen_t; @@ -53,15 +54,6 @@ NetServer::NetServer(std::string const host, unsigned int const port) return; } - /* - // set socket options - socklen_t yes = 1; - if (::setsockopt(netserver_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(socklen_t)) == -1) { - con_error << "Network can't set socket options!" << std::endl; - //perror("setsockopt"); - return; - } - */ // Get the local adress to bind to netserver_addr.sin_family = AF_INET; @@ -103,7 +95,7 @@ NetServer::~NetServer() std::string netmsg("disconnect\n"); // delete all clients - std::list<NetClient *>:: iterator it; + Clients:: iterator it; for (it = clients.begin(); it != clients.end(); it++) { // notify the game server @@ -133,7 +125,7 @@ void NetServer::abort() { // remove disconnected clients void NetServer::reap() { - for (std::list<NetClient *>:: iterator it = clients.begin(); it != clients.end(); it++) { + for (Clients:: iterator it = clients.begin(); it != clients.end(); it++) { NetClient *client = *it; if (client->client_timeout + NETTIMEOUT < application()->time()) { @@ -169,7 +161,7 @@ void NetServer::reap() void NetServer::transmit() { - for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { + for (Clients::iterator it = clients.begin(); it != clients.end(); it++) { (*it)->transmit(fd()); } } @@ -220,7 +212,7 @@ void NetServer::receive() // get messages from clients bool msg_received = false; - for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end() && !msg_received; it++) { + for (Clients::iterator it = clients.begin(); it != clients.end() && !msg_received; it++) { NetClient *client = *it; if ((client->host() == client_host) && (client->port() == (int) client_port)) { @@ -282,25 +274,24 @@ NetClient * NetServer::client_connect(std::string const host, int const port) void NetServer::client_initialize(NetClient *client) { // send welcome message - std::ostringstream netmsg; - netmsg.str(""); - netmsg << "msg info ^B" << Cvar::sv_name->str() << "\n"; - client->send_raw(netmsg.str()); + std::string welcome("^B"); + welcome.append(Cvar::sv_name->str()); + send_message(client, "info", welcome); client->transmit(fd()); + // send zones + for (Zone::Registry::iterator it = Zone::registry().begin(); it != Zone::registry().end(); it++) { + send_zone_update(client, (*it).second); + } + // send entities - std::map<unsigned int, Entity *>::iterator it; - for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { - netmsg.str(""); - netmsg << "ent "; - (*it).second->serialize(netmsg); - netmsg << "\n"; - client->send_raw(netmsg.str()); + for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { + send_entity_create(client, (*it).second); } // send connect completed - netmsg.str("connect\n"); - client->send_raw(netmsg.str()); + std::string connect("connect\n"); + client->send_raw(connect); client->transmit(fd()); // set client state to pending @@ -310,7 +301,7 @@ void NetServer::client_initialize(NetClient *client) { // find the client corresponding to a player NetClient *NetServer::find_client(Player const *player) { - for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { + for (Clients::iterator it = clients.begin(); it != clients.end(); it++) { if ((*it)->player() == player) { return (*it); } @@ -331,6 +322,7 @@ NetClient *NetServer::find_client(Player const *player) * msg <channel> <text> * supported message channels are "info" "public" "rcon" and "snd" * "snd" is a special channel to transmit sound events + * zone <id> <zone create/update data> */ // broadcast a "msg <channel>" message to all clients @@ -345,7 +337,7 @@ void NetServer::broadcast_message(const char *channel, std::string const & messa msg.append(message); msg += '\n'; - for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { + for (Clients::iterator it = clients.begin(); it != clients.end(); it++) { if (((*it)->player() && (*it)->player() != ignore_player) && ((*it)->state() == NetClient::Connected)) { (*it)->send_raw(msg); } @@ -382,7 +374,7 @@ void NetServer::broadcast_frame(float timestamp, float previoustimestamp) std::ostringstream msg(""); msg << "frame " << timestamp << " " << previoustimestamp << "\n"; - for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { + for (Clients::iterator it = clients.begin(); it != clients.end(); it++) { if ((*it)->state() == NetClient::Connected) { (*it)->send_raw(msg.str()); } @@ -395,7 +387,7 @@ void NetServer::broadcast_entity_delete(Entity *entity) std::ostringstream msg(""); msg << "die " << entity->id() << '\n'; - for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { + for (Clients::iterator it = clients.begin(); it != clients.end(); it++) { if ((*it)->state() == NetClient::Connected) { (*it)->send_raw(msg.str()); } @@ -410,13 +402,33 @@ void NetServer::broadcast_entity_create(Entity *entity) entity->serialize(msg); msg << '\n'; - for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { + for (Clients::iterator it = clients.begin(); it != clients.end(); it++) { if ((*it)->state() == NetClient::Connected) { (*it)->send_raw(msg.str()); } } } +// send a "ent" create entity message to all clients +void NetServer::send_entity_create(NetClient *client, Entity *entity) +{ + std::ostringstream msg; + msg << "ent "; + entity->serialize(msg); + msg << '\n'; + client->send_raw(msg.str()); +} + +// send a "zone" update zone message to a client +void NetServer::send_zone_update(NetClient *client, Zone *zone) +{ + std::ostringstream msg; + msg << "zone "; + zone->serialize_server_update(msg); + msg << '\n'; + client->send_raw(msg.str()); +} + // broadcast a "sup" server update entity message to all clients void NetServer::broadcast_entity_update(Entity *entity) { @@ -425,7 +437,7 @@ void NetServer::broadcast_entity_update(Entity *entity) entity->serialize_server_update(msg); msg << '\n'; - for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { + for (Clients::iterator it = clients.begin(); it != clients.end(); it++) { if ((*it)->state() == NetClient::Connected) { (*it)->send_raw(msg.str()); } @@ -435,7 +447,7 @@ void NetServer::broadcast_entity_update(Entity *entity) // broadcast a "pif" update player information if necessary void NetServer::broadcast_player_update() { - for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { + for (Clients::iterator it = clients.begin(); it != clients.end(); it++) { NetClient *client = *it; if (client->player()->dirty()) { @@ -525,7 +537,7 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me // client connection is completed on the first pif if (command == "pif") { std::string oldname(client->player()->name()); - client->player()->recieve_client_update(msgstream); + client->player()->receive_client_update(msgstream); if (client->state() == NetClient::Pending) { @@ -582,7 +594,7 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me } entitycontrolable->entity_dirty = true; - entitycontrolable->recieve_client_update(msgstream); + entitycontrolable->receive_client_update(msgstream); } return; } diff --git a/src/core/netserver.h b/src/core/netserver.h index d76676f..2340a5d 100644 --- a/src/core/netserver.h +++ b/src/core/netserver.h @@ -27,6 +27,8 @@ namespace core class NetServer { public: + typedef std::list<NetClient *> Clients; + NetServer(std::string const host, unsigned int const port); ~NetServer(); @@ -70,6 +72,12 @@ public: /// broadcast a create entity event void broadcast_entity_create(Entity *entity); + /// send a create entity event to a single player + void send_entity_create(NetClient *client, Entity *entity); + + /// send a zone update event to a single player + void send_zone_update(NetClient *client, Zone *zone); + /// broadcast a update entity event void broadcast_entity_update(Entity *entity); @@ -108,7 +116,7 @@ private: char recbuf[FRAMESIZE]; - std::list<NetClient *> clients; + Clients clients; }; } diff --git a/src/core/player.cc b/src/core/player.cc index 18dabed..9f531ed 100644 --- a/src/core/player.cc +++ b/src/core/player.cc @@ -26,6 +26,7 @@ Player::~Player() void Player::clear() { player_id = 0; + player_zone = 0; player_name.clear(); player_dirty = false; player_rcon = false; @@ -34,16 +35,21 @@ void Player::clear() clear_assets(); } -void Player::clear_assets() +void Player::set_control(EntityControlable *entitycontrolable) { - // clear assets - for (std::list<EntityControlable*>::iterator asset = assets.begin(); asset != assets.end(); asset++) { - (*asset)->entity_owner = 0; - (*asset)->die(); + player_control = entitycontrolable; + + if (entitycontrolable) { + player_zone = entitycontrolable->zone(); } - assets.clear(); - player_control = 0; + player_dirty = true; +} + +void Player::set_zone(Zone *zone) +{ + player_zone = zone; + player_dirty = true; } void Player::update_info() @@ -76,7 +82,7 @@ void Player::serialize_client_update(std::ostream & os) os << " " << player_color << " " << player_color_second << " \"" << player_name << "\""; } -void Player::recieve_client_update(std::istream &is) +void Player::receive_client_update(std::istream &is) { is >> player_color; is >> player_color_second; @@ -93,24 +99,41 @@ void Player::recieve_client_update(std::istream &is) void Player::serialize_server_update(std::ostream & os) const { + unsigned int zone; + if (player_zone) + zone = player_zone->id(); + else + zone = 0; + unsigned int co; if (player_control) co = player_control->id(); else co = 0; + - os << player_id << " " << co << " " << player_color << " \"" << player_name << "\""; + os << player_id << " " << zone << " " << co << " " << player_color << " \"" << player_name << "\""; } -void Player::recieve_server_update(std::istream &is) +void Player::receive_server_update(std::istream &is) { is >> player_id; + + unsigned int zone = 0; + is >> zone; + if (zone) { + player_zone = Zone::find(zone); + } else { + player_zone = 0; + } + unsigned int co = 0; is >> co; if (co) { Entity *e = Entity::find(co); if (e && e->type() == Entity::Controlable) { player_control = (EntityControlable *) e; + player_zone = player_control->zone(); } else { player_control = 0; con_warn << "control set to unknown entity " << co << "\n"; @@ -135,15 +158,24 @@ void Player::add_asset(EntityControlable *entity) { entity->entity_owner = this; assets.push_back(entity); + con_debug << " adding asset " << entity->id() << " to player " << id() << std::endl; } void Player::remove_asset(EntityControlable *entity) { + if (!entity) + return; + for (std::list<EntityControlable*>::iterator asset = assets.begin(); asset != assets.end(); asset++) { - if ((*asset) == entity) { + if (((*asset) == entity) && (entity->owner() == this)) { + //con_debug << " removing asset " << (*asset)->id() << " from player " << id() << std::endl; + + if ((*asset) == player_control) + player_control = 0; (*asset)->entity_owner = 0; (*asset)->die(); assets.erase(asset); + player_dirty = true; return; } } @@ -152,15 +184,38 @@ void Player::remove_asset(EntityControlable *entity) void Player::remove_asset(unsigned int id) { + if (!id) + return; + for (std::list<EntityControlable*>::iterator asset = assets.begin(); asset != assets.end(); asset++) { - if ((*asset)->id() == id) { + if ( ((*asset)->id() == id) && ((*asset)->owner() == this) ) { + //con_debug << " removing asset " << (*asset)->id() << " from player " << this->id() << std::endl; + + if ((*asset) == player_control) + player_control = 0; + (*asset)->entity_owner = 0; (*asset)->die(); assets.erase(asset); + player_dirty = true; return; } } con_warn << "Could not remove asset " << id << " from player " << this->id() << "\n"; } +void Player::clear_assets() +{ + // clear assets + for (std::list<EntityControlable*>::iterator asset = assets.begin(); asset != assets.end(); asset++) { + //con_debug << " removing asset " << (*asset)->id() << " from player " << id() << std::endl; + + (*asset)->entity_owner = 0; + (*asset)->die(); + } + assets.clear(); + + player_control = 0; +} + } diff --git a/src/core/player.h b/src/core/player.h index e37c577..cdcdbd1 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -13,6 +13,7 @@ class Player; } #include "core/entity.h" +#include "core/zone.h" #include "math/mathlib.h" #include <string> @@ -44,6 +45,17 @@ public: /// the entity the Player is currently controling inline EntityControlable *control() const { return player_control; } + /// set the entity the player is currenty controlling + /** This will automaticly set zone() to the zone the entity is in + */ + void set_control(EntityControlable *entitycontrolable); + + /// the zone the player is currently in + inline Zone *zone() const { return player_zone; } + + /// set the zone the player is currently in + void set_zone(Zone *zone); + /// player primary color inline math::Color const & color() const { return player_color; } @@ -59,13 +71,13 @@ public: void serialize_server_update(std::ostream & os) const; /// receive player info from a stream - void recieve_server_update(std::istream &is); + void receive_server_update(std::istream &is); /// serialize player info to a stream void serialize_client_update(std::ostream & os); /// receive player info from a stream - void recieve_client_update(std::istream &is); + void receive_client_update(std::istream &is); /// clear all the data void clear(); @@ -108,12 +120,14 @@ public: /// player is muted by admin bool player_mute; - /// the entity the Player is currently controling - EntityControlable *player_control; + std::list<EntityControlable *> assets; - std::list<EntityControlable*> assets; +private: + // the entity the Player is currently controling + EntityControlable *player_control; - + // the zone the player is currently in + Zone *player_zone; }; } diff --git a/src/filesystem/inifile.cc b/src/filesystem/inifile.cc index 0cc690f..47baebf 100644 --- a/src/filesystem/inifile.cc +++ b/src/filesystem/inifile.cc @@ -187,6 +187,39 @@ bool IniFile::got_key_color(const char * keylabel, math::Color & color) { } } +bool IniFile::got_key_bool(const char * keylabel, bool & b) +{ + if (last_read_was_key && (key_current.compare(keylabel) == 0 )) { + std::istringstream is(value_current); + + unsigned int i; + if (is >> i) { + if (i) b = true; else b = false; + return true; + } + + std::string val(value_current); + aux::trim(val); + aux::lowercase(val); + + if (val.compare("yes") == 0) { + b = true; + return true; + } else if (val.compare("true") == 0) { + b = true; + return true; + } else if (val.compare("no") == 0) { + b = false; + return true; + } else if (val.compare("false") == 0) { + b = false; + return true; + } + } + + return false; +} + void IniFile::close() { inifile_ifs.close(); diff --git a/src/filesystem/inifile.h b/src/filesystem/inifile.h index f5c903d..3efcfc4 100644 --- a/src/filesystem/inifile.h +++ b/src/filesystem/inifile.h @@ -73,6 +73,8 @@ public: bool got_key_vector3f(const char * keylabel, math::Vector3f & v); + bool got_key_bool(const char * keylabel, bool & b); + inline unsigned int line() const { return line_number; diff --git a/src/game/game.cc b/src/game/game.cc index 2d21be8..efca1be 100644 --- a/src/game/game.cc +++ b/src/game/game.cc @@ -20,7 +20,11 @@ namespace game { -ShipModel *default_shipmodel; +Game *this_game = 0; + +ShipModel *default_shipmodel = 0; +core::Zone *default_zone = 0; + /*----- engine game functions ------------------------------------- */ /// list the ship model registry @@ -35,8 +39,11 @@ void func_join(core::Player *player, std::string const &args) if (player->control()) return; - player->player_control = new Ship(player, default_shipmodel); - player->control()->entity_color = player->color(); + player->set_zone(default_zone); + Ship *ship = new Ship(player, default_shipmodel); + ship->set_zone(default_zone); + player->set_control(ship); + core::server()->send_sound(player, "game/buy-ship"); std::string message("^B"); @@ -50,7 +57,7 @@ void func_join(core::Player *player, std::string const &args) /// a player joins the spectators void func_spectate(core::Player *player, std::string const &args) { - if (!player->player_control) + if (!player->control()) return; std::string message("^B"); @@ -59,12 +66,8 @@ void func_spectate(core::Player *player, std::string const &args) core::server()->broadcast(message); if (player->control()) { - // player has only ship for now - player->player_control->die(); - player->player_control = 0; + player->remove_asset(player->control()); } - - player->player_dirty = true; } /// a player buys a ship @@ -92,17 +95,16 @@ void func_buy(core::Player *player, std::string const &args) if (shipmodel) { // player has only ship for now if (player->control()) { - player->player_control->die(); - player->player_control = 0; + player->remove_asset(player->control()); } - player->player_control = new Ship(player, shipmodel); - player->control()->entity_color = player->color(); - player->control()->entity_color_second = player->color_second(); - + Ship * ship = new Ship(player, shipmodel); + ship->set_zone(default_zone); + player->set_control(ship); + core::server()->broadcast("^B" + player->name() + " ^Bpurchased " + aux::article(shipmodel->name())); core::server()->send_sound(player, "game/buy-ship"); - player->player_dirty = true; + } else { core::server()->send(player, "Usage: buy [^B" + helpstr + "^N]"); } @@ -131,10 +133,49 @@ void func_hail(core::Player *player, std::string const &args) core::server()->send_sound(targetplayer, "com/hail"); } +/// a player actives the jumpdrive on his ship +void func_jump(core::Player *player, std::string const &args) +{ + if (!player->control()) + return; + + if (!player->control()->moduletype() == ship_enttype) + return; + + Ship * ship = static_cast<Ship *>(player->control()); + + if (!ship->jumpdrive()) { + core::server()->send(player, "Your ship is not equiped with a jumpdrive"); + return; + } + + std::string target; + std::istringstream is(args); + if (!(is >> target)) { + core::server()->send(player, "Usage: jump [system]"); + return; + } + + core::Zone *zone = core::Zone::find_zone(target); + if (!zone) { + core::server()->send(player, "Unknown system '" + target + '\''); + return; + } + + if (zone == player->control()->zone()) + return; + + core::server()->send(player, "Jumping to '" + zone->name() + '\''); + + player->control()->set_zone(zone); + player->set_zone(zone); +} + /*----- Game ------------------------------------------------------ */ Game::Game() : core::Module("Project::OSiRiON") { + this_game = this; } Game::~Game() @@ -143,23 +184,130 @@ Game::~Game() void Game::init() { - using math::Vector3f; - using math::Color; - module_running = false; ShipModel::clear(); - // setup the game world + if (!load_world()) { + abort(); + return; + } + + if (!load_ships()) { + abort(); + return; + } + + // add engine game functions + core::Func *func = 0; + func = core::Func::add("buy", (core::GameFuncPtr) func_buy); + func->set_info("buy a ship"); + func = core::Func::add("jump", (core::GameFuncPtr) func_jump); + func->set_info("make a hyperspace jump"); + func = core::Func::add("join", (core::GameFuncPtr) func_join); + func->set_info("join the game"); + func = core::Func::add("hail", (core::GameFuncPtr) func_hail); + func->set_info("send a standard hail"); + func = core::Func::add("spectate", (core::GameFuncPtr) func_spectate); + func->set_info("leave the game and spectate"); + + // add engine core functions + func = core::Func::add("list_ship", (core::FuncPtr) func_list_ship); + func->set_info("list ship statistics"); + + // set game variables + core::Cvar::set("g_impulsespeed", "10.0f", core::Cvar::Game); + + // indicate the module is ready to run frames + module_running = true; +} + +void Game::shutdown() +{ + // game functions are automaticly removed + + // remove engine core functions + core::Func::remove("list_ship"); + + ShipModel::clear(); + module_running = false; +} + +bool Game::load_world() +{ + std::string inifilename("world"); + filesystem::IniFile worldini; - worldini.open("world"); + worldini.open(inifilename); if (!worldini.is_open()) { - con_error << "Could not open ini/world.ini!" << std::endl; - abort(); - return; + con_error << "Could not open " << worldini.name() << std::endl; + return false; + } + + core::Zone *zone = 0; + std::string label; + + while (worldini.getline()) { + + if (worldini.got_section()) { + + if (worldini.got_section("world")) { + continue; + } else { + con_warn << worldini.name() << " unknown section '" << worldini.section() << "' at line " << worldini.line() << std::endl; + } + + } else if (worldini.section().compare("world") == 0 ) { + if (worldini.got_key_string("zone", label)) { + aux::trim(label); + aux::lowercase(label); + zone = new core::Zone(label); + core::Zone::add(zone); + } + } + } + worldini.close(); + + if (!core::Zone::registry().size()) { + con_error << "No zones found!" << std::endl; + return false; + } + + con_debug << " " << worldini.name() << " " << core::Zone::registry().size() << " zones" << std::endl; + + for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { + if (!load_zone((*it).second)) { + return false; + } + } + + if (!default_zone) { + con_error << "No default zone found!" << std::endl; + return false; + } + + return true; +} + +bool Game::load_zone(core::Zone *zone) +{ + using math::Vector3f; + using math::Color; + + std::string inifilename("zones/"); + inifilename.append(zone->label()); + + filesystem::IniFile zoneini; + zoneini.open(inifilename); + + if (!zoneini.is_open()) { + con_error << "Could not open " << zoneini.name() << std::endl; + return false; } + size_t count = 0; + Planet *planet = 0; Star *star = 0; core::Entity *entity = 0; @@ -168,41 +316,61 @@ void Game::init() float pitch; float roll; - while (worldini.getline()) { - if (worldini.got_key()) { - if (worldini.section().compare("star") == 0) { - if (worldini.got_key_string("label", star->entity_label)) + bool b; + + std::string strval; + + // set th default sky + zone->set_sky("sky"); + + while (zoneini.getline()) { + if (zoneini.got_key()) { + if (zoneini.section().compare("zone") == 0) { + if (zoneini.got_key_string("name", strval)) { + zone->set_name(strval); + continue; + } else if (zoneini.got_key_string("sky", strval)) { + zone->set_sky(strval); + continue; + } else if (zoneini.got_key_bool("default", b)) { + if (b) default_zone = zone; continue; - else if (worldini.got_key_string("name", star->entity_name)) + } else { + 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", star->entity_label)) continue; - else if (worldini.got_key_vector3f("location", star->entity_location )) + else if (zoneini.got_key_string("name", star->entity_name)) continue; - else if (worldini.got_key_color("color", star->entity_color)) + else if (zoneini.got_key_vector3f("location", star->entity_location )) continue; - else if (worldini.got_key_angle("radius", star->entity_radius)) + else if (zoneini.got_key_color("color", star->entity_color)) + continue; + else if (zoneini.got_key_angle("radius", star->entity_radius)) continue; else - con_warn << worldini.name() << " unknown key '" << worldini.key() << "' at line " << worldini.line() << std::endl; + con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; - } else if (worldini.section().compare("planet") == 0) { - if (worldini.got_key_string("label", planet->entity_label)) + } else if (zoneini.section().compare("planet") == 0) { + if (zoneini.got_key_string("label", planet->entity_label)) continue; - else if (worldini.got_key_string("name", planet->entity_name)) + else if (zoneini.got_key_string("name", planet->entity_name)) continue; - else if (worldini.got_key_string("texture", planet->entity_texture)) + else if (zoneini.got_key_string("texture", planet->entity_texture)) continue; - else if (worldini.got_key_vector3f("location", planet->entity_location )) + else if (zoneini.got_key_vector3f("location", planet->entity_location )) continue; - else if (worldini.got_key_color("color", planet->entity_color)) + else if (zoneini.got_key_color("color", planet->entity_color)) continue; - else if (worldini.got_key_angle("radius", planet->entity_radius)) + else if (zoneini.got_key_angle("radius", planet->entity_radius)) continue; else - con_warn << worldini.name() << " unknown key '" << worldini.key() << "' at line " << worldini.line() << std::endl; + con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; - } else if (worldini.section().compare("entity") == 0) { + } else if (zoneini.section().compare("entity") == 0) { std::string shapename; - if (worldini.got_key_string("shape", 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) { @@ -212,65 +380,83 @@ void Game::init() } else if (shapename.compare("sphere") == 0) { entity->entity_shape = core::Entity::Sphere; } else { - con_warn << worldini.name() << " unknown shape '" << shapename << "' at line " << worldini.line() << std::endl; + con_warn << zoneini.name() << " unknown shape '" << shapename << "' at line " << zoneini.line() << std::endl; } continue; - } else if (worldini.got_key_string("label", entity->entity_label)) { + } else if (zoneini.got_key_string("label", entity->entity_label)) { continue; - } else if (worldini.got_key_string("name", entity->entity_name)) { + } else if (zoneini.got_key_string("name", entity->entity_name)) { continue; - } else if (worldini.got_key_string("model", entity->entity_modelname)) { + } else if (zoneini.got_key_string("model", entity->entity_modelname)) { continue; - } else if (worldini.got_key_angle("direction", direction)) { + } else if (zoneini.got_key_angle("direction", direction)) { entity->axis().change_direction(direction); continue; - } else if (worldini.got_key_angle("pitch", pitch)) { + } else if (zoneini.got_key_angle("pitch", pitch)) { entity->axis().change_pitch(pitch); continue; - } else if (worldini.got_key_angle("roll", roll)) { + } else if (zoneini.got_key_angle("roll", roll)) { entity->axis().change_roll(roll); continue; - } else if (worldini.got_key_angle("radius", entity->entity_radius)) { + } else if (zoneini.got_key_angle("radius", entity->entity_radius)) { continue; - } else if (worldini.got_key_vector3f("location", entity->entity_location)) { + } else if (zoneini.got_key_vector3f("location", entity->entity_location)) { continue; - } else if (worldini.got_key_color("color", entity->entity_color)) { + } else if (zoneini.got_key_color("color", entity->entity_color)) { continue; - } else if (worldini.got_key_color("colorsecond", entity->entity_color_second)) { + } else if (zoneini.got_key_color("colorsecond", entity->entity_color_second)) { continue; } else { - con_warn << worldini.name() << " unknown key '" << worldini.key() << "' at line " << worldini.line() << std::endl; + con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; } } - } else if (worldini.got_section("star")) { + } else if (zoneini.got_section("zone")) { + continue; + + } else if (zoneini.got_section("star")) { star = new Star(); + star->set_zone(zone); + count ++; - } else if (worldini.got_section("planet")) { + } else if (zoneini.got_section("planet")) { planet = new Planet(); + planet->set_zone(zone); + count ++; - } else if (worldini.got_section("entity")) { + } else if (zoneini.got_section("entity")) { entity = new core::Entity(); entity->entity_flags += core::Entity::Static; + entity->set_zone(zone); + count ++; - } else if (worldini.got_section()) { - con_warn << worldini.name() << " unknown section '" << worldini.section() << "' at line " << worldini.line() << std::endl; + } else if (zoneini.got_section()) { + con_warn << zoneini.name() << " unknown section '" << zoneini.section() << "' at line " << zoneini.line() << std::endl; } } - worldini.close(); + zoneini.close(); + + con_debug << " " << zoneini.name() << " " << zone->content().size() << " entities" << std::endl; + + return true; +} + +// read ship model specifications +bool Game::load_ships() +{ + using math::Vector3f; + using math::Color; + + default_shipmodel = 0; - // read ship model specifications - // note: - // do not reuse the previous IniFile instance, some gcc versions do not like it filesystem::IniFile shipsini; shipsini.open("ships"); if (!shipsini.is_open()) { con_error << "Could not open ini/ships.ini!" << std::endl; - abort(); - return; + return false; } ShipModel *shipmodel = 0; - default_shipmodel = 0; + bool b; while (shipsini.getline()) { if (shipsini.got_key()) { @@ -282,8 +468,10 @@ void Game::init() continue; } else if (shipsini.got_key_string("model", shipmodel->shipmodel_modelname)) { continue; - } else if (shipsini.got_key("default")) { - default_shipmodel = shipmodel; + } else if (shipsini.got_key_bool("default", b)) { + if (b) default_shipmodel = shipmodel; + continue; + } else if (shipsini.got_key_bool("jumpdrive", shipmodel->shipmodel_jumpdrive)) { continue; } else if (shipsini.got_key_float("acceleration", shipmodel->shipmodel_acceleration)) { continue; @@ -307,43 +495,14 @@ void Game::init() } shipsini.close(); + con_debug << " " << shipsini.name() << " " << ShipModel::registry.size() << " ship models" << std::endl; + if (!default_shipmodel) { - con_error << "No default ship model in ini/ships.ini!\n"; - abort(); - return; + con_error << "No default ship model found!\n"; + return false; } - // add engine game functions - core::Func *func = 0; - func = core::Func::add("buy", (core::GameFuncPtr) func_buy); - func->set_info("buy a ship"); - func = core::Func::add("join", (core::GameFuncPtr) func_join); - func->set_info("join the game"); - func = core::Func::add("hail", (core::GameFuncPtr) func_hail); - func->set_info("send a standard hail"); - func = core::Func::add("spectate", (core::GameFuncPtr) func_spectate); - func->set_info("leave the game and spectate"); - - // add engine core functions - func = core::Func::add("list_ship", (core::FuncPtr) func_list_ship); - func->set_info("list ship statistics"); - - // set game variables - core::Cvar::set("g_impulsespeed", "10.0f", core::Cvar::Game); - - // indicate the module is ready to run frames - module_running = true; -} - -void Game::shutdown() -{ - // game functions are automaticly removed - - // remove engine core functions - core::Func::remove("list_ship"); - - ShipModel::clear(); - module_running = false; + return true; } void Game::frame(float seconds) @@ -355,16 +514,13 @@ void Game::frame(float seconds) void Game::player_connect(core::Player *player) { std::string args; + player->set_zone(default_zone); func_spectate(player, args); } void Game::player_disconnect(core::Player *player) { - if (player->control()) { - // player has only one ship for now - player->control()->die(); - player->player_control = 0; - } + player->remove_asset(player->control()); } } // namespace game diff --git a/src/game/game.h b/src/game/game.h index 89889a0..a715edd 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -47,6 +47,13 @@ public: /// is called when a player disconnects void player_disconnect(core::Player *player); + +private: + bool load_world(); + + bool load_zone(core::Zone *zone); + + bool load_ships(); }; } diff --git a/src/game/ship.cc b/src/game/ship.cc index 66d8b52..f61c9bd 100644 --- a/src/game/ship.cc +++ b/src/game/ship.cc @@ -23,19 +23,23 @@ Ship::Ship(core::Player *owner, ShipModel *shipmodel) : entity_modelname = "ships/" + shipmodel->modelname(); entity_name = shipmodel->name() + ": <^B" + owner->name() + "^N>"; entity_label = shipmodel->label(); - ship_shipmodel = shipmodel; entity_moduletypeid = ship_enttype; current_target_direction = 0.0f; current_target_pitch = 0.0f;; - current_target_roll = 0.0f;; + current_target_roll = 0.0f; + + entity_color = owner->color(); + entity_color_second = owner->color_second(); + + ship_shipmodel = shipmodel; + ship_jumpdrive = shipmodel->shipmodel_jumpdrive; } Ship::~Ship() { - if (entity_owner) - entity_owner->remove_asset(this); + } void Ship::frame(float seconds) diff --git a/src/game/ship.h b/src/game/ship.h index 9e978bb..bca0857 100644 --- a/src/game/ship.h +++ b/src/game/ship.h @@ -24,12 +24,17 @@ public: /// update the ship state virtual void frame(float seconds); + /// true if the ship is equiped with a jumpdrive + inline bool jumpdrive() const { return ship_jumpdrive; } + private: ShipModel *ship_shipmodel; float current_target_direction; float current_target_pitch; float current_target_roll; + + bool ship_jumpdrive; }; } diff --git a/src/game/shipmodel.cc b/src/game/shipmodel.cc index aa0c2c9..6a226f4 100644 --- a/src/game/shipmodel.cc +++ b/src/game/shipmodel.cc @@ -19,6 +19,7 @@ ShipModel::ShipModel() shipmodel_maxspeed = 3.0f; shipmodel_turnspeed = 0.1f; + shipmodel_jumpdrive = false; } ShipModel::~ShipModel() diff --git a/src/game/shipmodel.h b/src/game/shipmodel.h index 686d736..a29f860 100644 --- a/src/game/shipmodel.h +++ b/src/game/shipmodel.h @@ -44,6 +44,9 @@ public: std::string shipmodel_name; std::string shipmodel_modelname; + /// indicates of this model can be equiped with a jump drive + bool shipmodel_jumpdrive; + static ShipModel *find(const std::string label); /// the ship model registry diff --git a/src/model/map.cc b/src/model/map.cc index ad569eb..c68bb1d 100644 --- a/src/model/map.cc +++ b/src/model/map.cc @@ -912,7 +912,7 @@ Model * Map::load(std::string const &name) */ mapfile.load_fragments(model); - con_print << " " << mapfile.name() << " " << + con_debug << " " << mapfile.name() << " " << model->model_tris_count << "/" << model->model_tris_detail_count << " tris/detail " << model->model_quad_count << "/" << model->model_quad_detail_count << " quads/detail " << model->fragments().size() << " frags " <<std::endl; diff --git a/src/render/draw.cc b/src/render/draw.cc index 2e72529..b26b8ce 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -41,6 +41,7 @@ math::Vector3f v7(-1, -1, -1); const float drawdistance = 128.0f; const float drawfxdistance = 64.0f; +core::Zone *zone = 0; float angle = 0; @@ -367,10 +368,8 @@ void pass_prepare(float seconds) glGetDoublev(GL_MODELVIEW, gl_model_matrix); glGetIntegerv(GL_VIEWPORT, gl_viewport); - std::map<unsigned int, core::Entity *>::iterator it; - for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { - - core::Entity *entity = (*it).second; + for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { + core::Entity *entity = (*it); // load entity models and light flare textures if (!entity->model() && entity->modelname().size()) { @@ -503,9 +502,8 @@ void pass_prepare(float seconds) /* Draw entities without model */ void draw_pass_default() { - std::map<unsigned int, core::Entity *>::iterator it; - for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { - core::Entity *entity = (*it).second; + for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { + core::Entity *entity = (*it); // draw entities without model if (!entity->model()) { @@ -590,10 +588,9 @@ void draw_pass_default() /* draw model geometry fragments */ void draw_pass_model_fragments() { - std::map<unsigned int, core::Entity *>::iterator it; - for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { + core::Entity *entity = (*it); - core::Entity *entity = (*it).second; if (entity->model() && entity->state()->visible()) { gl::push(); gl::translate(entity->state()->location()); @@ -619,8 +616,8 @@ void draw_pass_model_fx(float elapsed) gl::begin(gl::Quads); - for (std::map<unsigned int, core::Entity *>::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { - core::Entity *entity = (*it).second; + for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { + core::Entity *entity = (*it); if (entity->model() && entity->state()->detailvisible()) { @@ -822,10 +819,10 @@ void draw_pass_model_corona() if (!(r_radius && r_radius->value())) return; - for (std::map<unsigned int, core::Entity *>::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { - core::Entity *entity = (*it).second; + for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { + core::Entity *entity = (*it); - if (entity->model() && entity->state() && entity->state()->visible()) { + if (entity->model() && entity->state()->visible()) { gl::push(); gl::translate(entity->state()->location()); math::Color color = entity->color(); @@ -844,9 +841,20 @@ void draw_pass_sky() if (!(r_sky && r_sky->value())) return; - size_t sky_texture = Textures::load("textures/env/sky"); - Textures::bind(sky_texture); + if (!core::localplayer()->zone()) + return; + + if (!core::localplayer()->zone()->sky_texture() && core::localplayer()->zone()->sky().size()) { + std::string texture_name("textures/env/"); + texture_name.append(core::localplayer()->zone()->sky()); + core::localplayer()->zone()->set_sky_texture(Textures::load(texture_name)); + + if (!core::localplayer()->zone()->sky_texture()) + core::localplayer()->zone()->set_sky(""); + } + + Textures::bind(core::localplayer()->zone()->sky_texture()); gl::enable(GL_TEXTURE_2D); gl::push(); @@ -901,7 +909,9 @@ void draw_pass_spacegrid() void draw(float seconds) { - Stats::clear(); + zone = core::localplayer()->zone(); + if (!zone) + return; // used for animations angle += 180.0f * seconds; diff --git a/src/render/render.cc b/src/render/render.cc index cb0d4dd..dd5703a 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -108,8 +108,9 @@ void shutdown() con_print << "^BShutting down renderer..." << std::endl; // clear entity models, this will force a reload - for (std::map<unsigned int, core::Entity *>::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + for (core::Entity::Registry::iterator it = core::Entity::registry().begin(); it != core::Entity::registry().end(); it++) { core::Entity *entity = (*it).second; + if (entity->model()) entity->entity_model = 0; } diff --git a/src/render/text.cc b/src/render/text.cc index f5c221f..c64e331 100644 --- a/src/render/text.cc +++ b/src/render/text.cc @@ -32,13 +32,13 @@ void Text::init() base_color[7] = new math::Color(1, 1, 1); for (size_t i=0; i< 26; i++) { - core_color[i] = new math::Color(.7, .7, .7); + core_color[i] = new math::Color(.75, .75, .75); } // N - normal color - core_color[(size_t)('N'-'A')]->assign(.7, .7, .7); + core_color[(size_t)('N'-'A')]->assign(.75, .75, .75); // D - Debug color - core_color[(size_t)('D'-'A')]->assign(.6, .6, .6); + core_color[(size_t)('D'-'A')]->assign(.5, .5, .5); // B - bold color core_color[(size_t)('B'-'A')]->assign(1, 1, 1); // W - warning color diff --git a/src/render/tga.cc b/src/render/tga.cc index fb4301b..fb65910 100644 --- a/src/render/tga.cc +++ b/src/render/tga.cc @@ -97,9 +97,6 @@ Image *TGA::load(const char *filename) // byte 17 - image descriptor byte unsigned int tga_descriptor = header[17]; - con_debug << " " << filename << " " - << tga_width << "x" << tga_height << "x" << tga_depth << "bpp" << std::endl; - // read the image id if there is one if (tga_idlength) tga_file->skip(tga_idlength); @@ -214,6 +211,8 @@ Image *TGA::load(const char *filename) con_warn << filename << ": descriptor bit 4 (left-right) set!" << std::endl; } + con_debug << " " << filename << " " << tga_width << "x" << tga_height << "x" << tga_depth << "bpp" << std::endl; + return image; } |