From 7a373c3f1fb8ea9dbef7690154bbe332fc386eca Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Mon, 18 Oct 2010 23:41:41 +0000 Subject: bullet ActionInterface for controlable entities, KeepAlive flag and g_keepalive --- src/core/entity.cc | 92 ++++++++++++++++++++++++++++++++--------------- src/core/entity.h | 53 ++++++++++++++++++++++----- src/core/gameserver.cc | 45 +++++++++++++++++------ src/core/physics.h | 2 +- src/game/base/cargopod.cc | 3 ++ src/game/base/game.cc | 5 ++- src/game/base/game.h | 3 ++ src/game/base/ship.cc | 80 ++++++++++++++++++++++------------------- 8 files changed, 196 insertions(+), 87 deletions(-) diff --git a/src/core/entity.cc b/src/core/entity.cc index a1db040..1438466 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -520,7 +520,7 @@ void Entity::reset() entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(entity_mass, entity_motionstate, entity_collision_shape, inertia); entity_body = new btRigidBody(*entity_body_info); - //entity_body->setActivationState(ISLAND_SLEEPING); + entity_body->setActivationState(ISLAND_SLEEPING); if (zone()) zone()->physics()->addRigidBody(entity_body); @@ -540,12 +540,16 @@ EntityDynamic::EntityDynamic() : Entity() { entity_state = Normal; entity_timer = 0; + entity_keepalive_time = 0.0f; + entity_keepalive_timeout = 0.0f; } EntityDynamic::EntityDynamic(std::istream & is) : Entity(is) { entity_state = Normal; entity_timer = 0; + entity_keepalive_time = 0.0f; + entity_keepalive_timeout = 0.0f; } EntityDynamic::~EntityDynamic() @@ -560,6 +564,16 @@ void EntityDynamic::set_state(int state) } } +void EntityDynamic::set_keepalive_time(float time) +{ + entity_keepalive_time = time; +} + +void EntityDynamic::set_keepalive_timeout(float timeout) +{ + entity_keepalive_timeout = timeout; +} + void EntityDynamic::reset() { Entity::reset(); @@ -577,7 +591,6 @@ void EntityDynamic::frame(float seconds) return; // transfer bullet state to entity state - // FIXME disable physics when docked if (entity_body) { // this makes sure an update is sent if speed goes to 0 in the next step if (entity_speed > 0) { @@ -672,6 +685,27 @@ void EntityDynamic::receive_server_update(std::istream &is) } } +/*----- EntityControlable::ActionInterface ------------------------- */ + +EntityControlable::ActionInterface::ActionInterface(EntityControlable *entity) +{ + actioninterface_entity = entity; +} + +EntityControlable::ActionInterface::~ActionInterface() +{ + actioninterface_entity = 0; +} + +void EntityControlable::ActionInterface::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) +{ + actioninterface_entity->action(deltaTimeStep); +} + +void EntityControlable::ActionInterface::debugDraw(btIDebugDraw* debugDrawer) +{ +} + /*----- EntityControlable ------------------------------------------ */ EntityControlable::EntityControlable() : EntityDynamic() @@ -688,7 +722,7 @@ EntityControlable::EntityControlable() : EntityDynamic() entity_owner = 0; - entity_vehicle = 0; + entity_actioninterface = 0; } EntityControlable::EntityControlable(std::istream & is) : @@ -706,7 +740,7 @@ EntityControlable::EntityControlable(std::istream & is) : entity_owner = 0; - entity_vehicle = 0; + entity_actioninterface = 0; } @@ -800,14 +834,6 @@ void EntityControlable::receive_server_update(std::istream &is) entity_movement /= 100.0f; } -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) @@ -892,11 +918,9 @@ void EntityControlable::set_zone(Zone *zone) if (entity_zone) { entity_zone->remove(this); - if (vehicle() && entity_zone->physics()) { - entity_zone->physics()->removeAction(entity_vehicle); + if (body() && entity_zone->physics()) { + entity_zone->physics()->removeAction(entity_actioninterface); entity_zone->physics()->removeRigidBody(body()); - delete entity_vehicle; - entity_vehicle = 0; } } @@ -909,10 +933,9 @@ void EntityControlable::set_zone(Zone *zone) if (entity_zone) { entity_zone->add(this); - if (body() && entity_zone->physics()) { - entity_vehicle = new btRaycastVehicle(entity_vehicletuning, body(), entity_zone->raycaster()); + if (body() && entity_zone->physics()) { entity_zone->physics()->addRigidBody(body()); - entity_zone->physics()->addAction(entity_vehicle); + entity_zone->physics()->addAction(entity_actioninterface); reset(); } } @@ -945,20 +968,19 @@ void EntityControlable::reset() entity_body_info = new btRigidBody::btRigidBodyConstructionInfo(entity_mass, entity_motionstate, entity_collision_shape, inertia); entity_body = new btRigidBody(*entity_body_info); entity_body->setActivationState(DISABLE_DEACTIVATION); - } - - entity_body->setWorldTransform(t); - if (zone()) { - if (!entity_vehicle) { - entity_vehicle = new btRaycastVehicle(entity_vehicletuning, body(), entity_zone->raycaster()); + + entity_actioninterface = new ActionInterface(this); + + if (zone()) { entity_zone->physics()->addRigidBody(body()); - entity_zone->physics()->addAction(entity_vehicle); - } + entity_zone->physics()->addAction(entity_actioninterface); - // transfer entity location to motion state - zone()->physics()->synchronizeSingleMotionState(entity_body); + // transfer entity location to motion state + zone()->physics()->synchronizeSingleMotionState(entity_body); + } } + entity_body->setWorldTransform(t); if ((entity_state == Docked) || (entity_state == Destroyed) || (!visible())){ entity_body->activate(false); } else { @@ -968,6 +990,18 @@ void EntityControlable::reset() set_dirty(); } +// bullet physics frame (runs at bullet framerate) +void EntityControlable::action(btScalar seconds) +{ +} + +// osirion game frame (runs at osirion server framerate) +void EntityControlable::frame(float seconds) +{ + EntityDynamic::frame(seconds); +} + + /*----- EntityGlobe ------------------------------------------------ */ EntityGlobe::EntityGlobe() : Entity() diff --git a/src/core/entity.h b/src/core/entity.h index 057ffb2..f6ee1d7 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -41,8 +41,10 @@ class Entity : public Label friend class Extension; public: - /// Entity flags - enum Flags {Static = 1, Solid = 2, Bright = 4, Dockable = 8, ShowOnMap = 16}; + /** + * @brief entity flags + */ + enum Flags {Static = 1, Solid = 2, Bright = 4, Dockable = 8, ShowOnMap = 16, KeepAlive = 32}; /// Entity type constants enum Type {Default = 0, Dynamic = 1, Controlable = 2, Globe = 3}; @@ -492,7 +494,17 @@ public: return entity_timer; } -/*----- mutators -------------------------------------------------- */ + /// time when the entity was last alive + inline const float keepalive_time() const { + return entity_keepalive_time; + } + + /// keepalive timeout + inline const float keepalive_timeout() const { + return entity_keepalive_timeout; + } + + /*----- mutators -------------------------------------------------- */ /// mass of the entity inline void set_mass(const float mass) { @@ -528,6 +540,12 @@ public: /// set event state virtual void set_state(int state); + + /// set the time when the entity was last alive, in game time seconds + void set_keepalive_time(float time); + + /// set the timeout after which the entitie is deleted, in seconds + void set_keepalive_timeout(float timeout); /// runs one game frame for the entity /** @@ -542,6 +560,8 @@ public: virtual void reset(); protected: + float entity_keepalive_time; + float entity_keepalive_timeout; float entity_timer; int entity_state; }; @@ -551,6 +571,20 @@ class EntityControlable : public EntityDynamic { friend class Player; public: + /// bullet action interface class + class ActionInterface: public btActionInterface { + public: + ActionInterface(EntityControlable *entity); + virtual ~ActionInterface(); + + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep); + + virtual void debugDraw(btIDebugDraw* debugDrawer); + + private: + EntityControlable *actioninterface_entity; + }; + /// server-side constructor, create a controlable entity EntityControlable(); @@ -581,9 +615,9 @@ public: return entity_movement; } - /// physics vehicle container - inline btRaycastVehicle *vehicle() { - return entity_vehicle; + /// physics action + inline ActionInterface *actioninterface() { + return entity_actioninterface; } /*----- serializers ----------------------------------------------- */ @@ -655,6 +689,10 @@ public: float entity_thrust; protected: + + /// physics action interface callback + virtual void action (btScalar seconds); + /* target_ variables can be set by the client */ /** @@ -688,8 +726,7 @@ protected: float entity_movement; - btRaycastVehicle::btVehicleTuning entity_vehicletuning; - btRaycastVehicle *entity_vehicle; + ActionInterface *entity_actioninterface; private: // owner of the entity diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index 597de33..e6c44d0 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -15,6 +15,7 @@ #include "core/loader.h" #include "core/parser.h" #include "core/physics.h" +#include "core/range.h" #include "core/netserver.h" #include "filesystem/filesystem.h" #include "sys/sys.h" @@ -564,8 +565,7 @@ void GameServer::frame(unsigned long timestamp) } // view is to be deleted - if (view->destroyed()) - { + if (view->destroyed()) { if (control) { // player is docked at deleted entity if (control->state() == Entity::Docked) { @@ -590,15 +590,42 @@ void GameServer::frame(unsigned long timestamp) } // mark all entities as updated + const float keepalive_distance_squared = range::fxdistance * range::fxdistance; + for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end();) { - Entity *entity = (*it).second; + + // perform a keep-alive pass + if ((*it).second->flag_is_set(Entity::KeepAlive) && ((*it).second->type() == Entity::Dynamic) && (*it).second->zone()) { + + bool keepalive = false; + EntityDynamic *entity = static_cast((*it).second); + + for (Zone::Content::const_iterator zit = entity->zone()->content().begin(); zit != entity->zone()->content().end(); zit++) { + + if (( (*zit)->type() == Entity::Controlable) && ( (*zit) != entity)) { + + const EntityControlable *other = static_cast(*zit); + if (other->owner() && (other->state() != Entity::Docked) && (math::distancesquared(entity->location(), other->location()) < keepalive_distance_squared)) { + keepalive = true; + } + } + + } + + if (keepalive) { + entity->set_keepalive_time(time() + entity->keepalive_timeout()); + } else if ((entity->keepalive_time() > 0.0f) && (entity->keepalive_time() < time())) { + entity->die(); + } + } - if (entity->entity_destroyed) { - delete entity; - (*it).second = entity = 0; + // delete the entity if necessary + if ((*it).second->entity_destroyed) { + delete (*it).second; + (*it).second = 0; Entity::registry().erase(it++); } else { - entity->clear_updates(); + (*it).second->clear_updates(); ++it; } } @@ -607,10 +634,6 @@ void GameServer::frame(unsigned long timestamp) application()->notify_zonechange(); localplayer()->set_zonechange(false); } - - /*if (!Cvar::sv_dedicated->value()) { - update_clientstate(); - }*/ } void GameServer::save_config() diff --git a/src/core/physics.h b/src/core/physics.h index 071ad33..ecceb67 100644 --- a/src/core/physics.h +++ b/src/core/physics.h @@ -15,7 +15,7 @@ #include "BulletCollision/CollisionShapes/btTriangleMesh.h" #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/Gimpact/btGImpactShape.h" -#include "BulletDynamics/Vehicle/btRaycastVehicle.h" +#include "BulletDynamics/Dynamics/btActionInterface.h" namespace core { diff --git a/src/game/base/cargopod.cc b/src/game/base/cargopod.cc index efdfe33..6581b75 100644 --- a/src/game/base/cargopod.cc +++ b/src/game/base/cargopod.cc @@ -15,6 +15,9 @@ CargoPod::CargoPod() : EntityDynamic() entity_moduletypeid = cargopod_enttype; set_name("Cargo pod"); set_label("cargopod"); + + set_flag(core::Entity::KeepAlive); + set_keepalive_timeout(Game::g_keepalive ? Game::g_keepalive->value() : 0); // FIXME hardcoded modelname set_modelname("maps/cargo/pod"); diff --git a/src/game/base/game.cc b/src/game/base/game.cc index 346208b..ebf09ce 100644 --- a/src/game/base/game.cc +++ b/src/game/base/game.cc @@ -55,6 +55,7 @@ core::Cvar *Game::g_impulseacceleration = 0; core::Cvar *Game::g_jumppointrange = 0; core::Cvar *Game::g_devel = 0; core::Cvar *Game::g_damping = 0; +core::Cvar *Game::g_keepalive; core::Module *factory() { @@ -802,6 +803,9 @@ Game::Game() : core::Module("Project::OSiRiON", true) g_damping = core::Cvar::get("g_damping", "0.1", core::Cvar::Archive); g_damping->set_info("[float] physics damping factor (0-1)"); + + g_keepalive = core::Cvar::get("g_keepalive", "300", core::Cvar::Archive); + g_keepalive->set_info("[float] amount of time dynamic objects are kept alive, in seconds"); } Game::~Game() @@ -1372,7 +1376,6 @@ bool Game::load_defaults() void Game::frame(float seconds) { - if (!running()) return; } diff --git a/src/game/base/game.h b/src/game/base/game.h index c229a18..07df62d 100644 --- a/src/game/base/game.h +++ b/src/game/base/game.h @@ -83,6 +83,9 @@ public: /// physics variable: default damping factor of space static core::Cvar *g_damping; + + /// game variable: amount of time dynamic objects are kept alive when there are no players + static core::Cvar *g_keepalive; private: diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 44676c4..9f04e43 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -519,10 +519,7 @@ void Ship::frame(float seconds) entity_thrust = target_thrust; } math::clamp(entity_thrust, 0.0f, 1.0f); - actual_thrust = entity_thrust + current_target_afterburner * 0.15f; - if ((entity_state == core::Entity::ImpulseInitiate) || (entity_state == core::Entity::Impulse)) { - actual_thrust = 1.0f; - } + // update strafe control target if (current_target_strafe < target_strafe) { @@ -546,25 +543,6 @@ void Ship::frame(float seconds) current_target_vstrafe = target_vstrafe; } - // update roll control target - if (current_target_roll < target_roll) { - current_target_roll += direction_reaction * seconds; - if (current_target_roll > target_roll) - current_target_roll = target_roll; - } else if (current_target_roll > target_roll) { - current_target_roll -= direction_reaction * seconds; - if (current_target_roll < target_roll) - current_target_roll = target_roll; - } - math::clamp(current_target_roll, -1.0f, 1.0f); - - if (fabs(current_target_roll) > MIN_DELTA) { - float roll_offset = seconds * current_target_roll; - get_axis().change_roll(actual_turnspeed * roll_offset); - } else { - current_target_roll = 0.0f; - } - // update direction control target if (current_target_direction < target_direction) { current_target_direction += direction_reaction * seconds; @@ -578,13 +556,6 @@ void Ship::frame(float seconds) } } - if (fabs(current_target_direction) > MIN_DELTA) { - math::clamp(current_target_direction, -1.0f, 1.0f); - target_axis.change_direction(actual_turnspeed * current_target_direction); - } else { - current_target_direction = 0.0f; - } - // update pitch control target if (current_target_pitch < target_pitch) { current_target_pitch += direction_reaction * seconds; @@ -596,13 +567,17 @@ void Ship::frame(float seconds) current_target_pitch = target_pitch; } - if (fabs(current_target_pitch) > MIN_DELTA) { - math::clamp(current_target_pitch, -1.0f, 1.0f); - target_axis.change_pitch(actual_turnspeed * current_target_pitch); - } else { - current_target_pitch = 0.0f; + // update roll control target + if (current_target_roll < target_roll) { + current_target_roll += direction_reaction * seconds; + if (current_target_roll > target_roll) + current_target_roll = target_roll; + } else if (current_target_roll > target_roll) { + current_target_roll -= direction_reaction * seconds; + if (current_target_roll < target_roll) + current_target_roll = target_roll; } - + /* // -- BULLET @@ -628,10 +603,35 @@ void Ship::frame(float seconds) EntityDynamic::frame(seconds); */ + + // apply direction rotation to target axis + if (fabs(current_target_direction) > MIN_DELTA) { + math::clamp(current_target_direction, -1.0f, 1.0f); + target_axis.change_direction(actual_turnspeed * current_target_direction); + } else { + current_target_direction = 0.0f; + } + + // apply pitch rotation to target axis + if (fabs(current_target_pitch) > MIN_DELTA) { + math::clamp(current_target_pitch, -1.0f, 1.0f); + target_axis.change_pitch(actual_turnspeed * current_target_pitch); + } else { + current_target_pitch = 0.0f; + } + + // apply roll rotation to axis + if (fabs(current_target_roll) > MIN_DELTA) { + math::clamp(current_target_roll, -1.0f, 1.0f); + get_axis().change_roll(actual_turnspeed * current_target_roll * seconds); + } else { + current_target_roll = 0.0f; + } + + // update axis float cosangle; // cosine of an angle float angle; // angle in radians - // update axis n.assign(math::crossproduct(axis().forward(), target_axis.forward())); if (!(n.length() < MIN_DELTA)) { n.normalize(); @@ -642,6 +642,12 @@ void Ship::frame(float seconds) } // update speed + if ((entity_state == core::Entity::ImpulseInitiate) || (entity_state == core::Entity::Impulse)) { + actual_thrust = 1.0f; + } else { + actual_thrust = entity_thrust + current_target_afterburner * 0.15f; + } + const float max = actual_thrust * actual_maxspeed; if (entity_speed < max) { entity_speed += actual_acceleration * seconds; -- cgit v1.2.3