/* core/entity.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2. */ #include #include #include "sys/sys.h" #include "core/entity.h" #include "core/cvar.h" namespace core { using math::Color; using math::Vector3f; /* ---- Static functions for the Entity registry ------------------- */ Entity::Registry Entity::entity_registry; void Entity::add(Entity *ent) { Registry::iterator it; unsigned int id = 1; for (it = entity_registry.begin(); it != entity_registry.end() && id == (*it).second->id(); it++) { id++; } ent->entity_id = id; entity_registry[id] = ent; } void Entity::add(Entity *ent, unsigned int id) { if (find(id)) { con_warn << "Duplicate entity " << id << "!\n"; return; } ent->entity_id = id; entity_registry[id] = ent; } Entity *Entity::find(unsigned int id) { Registry::iterator it = entity_registry.find(id); if (it == entity_registry.end()) return 0; else return (*it).second; } void Entity::erase(unsigned int id) { Registry::iterator it = entity_registry.find(id); if (it != entity_registry.end()) { delete((*it).second); entity_registry.erase(it); } else { con_warn << "Could not erase entity " << id << "!\n"; } } void Entity::list() { 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() << " type " << std::setw(4) << entity->type() << ":" << std::setw(4) << entity->moduletype() << " " << entity->label() << std::endl; } con_print << entity_registry.size() << " registered entities" << std::endl; } /*----- Entity ----------------------------------------------------- */ Entity::Entity(unsigned int flags) : entity_location(0.0f, 0.0f, 0.0f), entity_color(1.0f, 1.0f, 1.0f, 1.0f), entity_color_second(1.0f, 1.0f, 1.0f, 1.0f) { entity_id = 0; entity_flags = flags; entity_moduletypeid = 0; entity_radius = 0.5f; entity_shape = Diamond; entity_created = true; entity_destroyed = false; entity_dirty = false; entity_model = 0; entity_modelname.clear(); entity_label.clear(); entity_name.clear(); 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; 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; is >> s; // shape entity_shape = (Shape) s; is >> entity_radius; is >> entity_axis[0]; is >> entity_axis[1]; entity_axis[2] = math::crossproduct(entity_axis.forward(), entity_axis.left()); char c; // read label while ( (is.get(c)) && (c != '"')); while ( (is.get(c)) && (c != '"')) n += c; entity_label = n; n.clear(); // read name while ( (is.get(c)) && (c != '"')); while ( (is.get(c)) && (c != '"')) n += c; entity_name = n; n.clear(); // read model name while ( (is.get(c)) && (c != '"')); while ( (is.get(c)) && (c != '"')) n += c; entity_modelname = n; entity_model = 0; // this will be resolved later entity_created = true; entity_destroyed = false; entity_dirty = false; // this entity is created clientside entity_clientstate = 0; add(this, entity_id); } 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 { os << type() << " " << entity_id << " " << entity_moduletypeid << " " << entity_flags << " " << (entity_zone ? entity_zone->id() : 0) << " " << entity_location << " " << entity_color << " " << entity_color_second << " " << entity_shape << " " << entity_radius << " " << entity_axis.forward() << " " << entity_axis.left() << " " << "\"" << entity_label << "\" " << "\"" << entity_name << "\" " << "\"" << entity_modelname << "\""; } void Entity::serialize_client_update(std::ostream & os) const { } void Entity::receive_client_update(std::istream &is) { } void Entity::serialize_server_update(std::ostream & os) const { } void Entity::receive_server_update(std::istream &is) { } void Entity::frame(float seconds) { } /* ---- EntityDynamic ---------------------------------------------- */ EntityDynamic::EntityDynamic(unsigned int flags) : Entity(flags) { entity_speed = 0.0f; } EntityDynamic::EntityDynamic(std::istream & is) : Entity(is) { is >> entity_speed; } EntityDynamic::~EntityDynamic() { } void EntityDynamic::frame(float seconds) { if ((flags() & Static) == Static) return; if (entity_speed == 0) return; entity_location += entity_axis.forward() * entity_speed * seconds; entity_dirty = true; } void EntityDynamic::serialize(std::ostream & os) const { Entity::serialize(os); os << " " << entity_speed; } void EntityDynamic::serialize_client_update(std::ostream & os) const { } 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::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 *owner, unsigned int flags) : EntityDynamic(flags) { entity_thrust = 0; entity_autolevel = false; 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) : EntityDynamic(is) { unsigned int o; entity_thrust = 0; entity_autolevel = false; target_direction = 0.0f; target_thrust = 0.0f; target_pitch = 0.0f; target_roll = 0.0f; is >> entity_thrust; is >> o; // FIXME resolve owner entity_owner = 0; } EntityControlable::~EntityControlable() { if (entity_owner) entity_owner->remove_asset(this); } void EntityControlable::serialize(std::ostream & os) const { EntityDynamic::serialize(os); os << " " << entity_thrust; os << " " << ( entity_owner ? entity_owner->id() : 0); } void EntityControlable::serialize_client_update(std::ostream & os) const { EntityDynamic::serialize_client_update(os); os << " " << target_direction; os << " " << target_pitch; os << " " << target_thrust; os << " " << target_roll; os << " " << (autolevel() ? 1 : 0); } void EntityControlable::receive_client_update(std::istream &is) { EntityDynamic::receive_client_update(is); is >> target_direction; is >> target_pitch; is >> target_thrust; is >> target_roll; unsigned int b = 0; is >> b; if (b) entity_autolevel = true; else entity_autolevel = true; } void EntityControlable::serialize_server_update(std::ostream & os) const { EntityDynamic::serialize_server_update(os); os << " " << entity_thrust; } void EntityControlable::receive_server_update(std::istream &is) { EntityDynamic::receive_server_update(is); is >> entity_thrust; } void EntityControlable::frame(float seconds) { //entity_direction = target_direction; //entity_thrust = target_thrust; //entity_dirty = true; EntityDynamic::frame(seconds); } void EntityControlable::set_thrust(float thrust) { if ((flags() & Static) == Static) return; if (thrust != target_thrust) { target_thrust = thrust; entity_dirty = true; } } void EntityControlable::set_autolevel(bool autolevel) { if (entity_autolevel != autolevel) { entity_autolevel = autolevel; entity_dirty = true; } } void EntityControlable::set_direction(float direction) { if ((flags() & Static) == Static) return; if (target_direction != direction) { target_direction = direction; entity_dirty = true; } } void EntityControlable::set_pitch(float pitch) { if ((flags() & Static) == Static) return; if (target_pitch != pitch) { target_pitch = pitch; entity_dirty = true; } } void EntityControlable::set_roll(float roll) { if ((flags() & Static) == Static) return; if (target_roll != roll) { target_roll = roll; entity_dirty = true; } } /*----- EntityGlobe ------------------------------------------------ */ EntityGlobe::EntityGlobe(unsigned int flags) : Entity(flags) { render_texture = 0; entity_shape = Sphere; } EntityGlobe::EntityGlobe(std::istream & is) : Entity(is) { render_texture = 0; entity_shape = Sphere; std::string n; char c; while ( (is.get(c)) && (c != '"')); while ( (is.get(c)) && (c != '"')) n += c; entity_texture = n; n.clear(); } EntityGlobe::~EntityGlobe() { } void EntityGlobe::serialize(std::ostream & os) const { Entity::serialize(os); os << " \"" << entity_texture << "\""; } }