diff --git a/src/activeobject.h b/src/activeobject.h index c46ae61b2..7a5952f18 100644 --- a/src/activeobject.h +++ b/src/activeobject.h @@ -62,6 +62,7 @@ public: virtual u8 getType() const = 0; + virtual aabb3f* getCollisionBox() = 0; protected: u16 m_id; // 0 is invalid, "no id" }; diff --git a/src/collision.cpp b/src/collision.cpp index d131c7a20..78597ac68 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -22,8 +22,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map.h" #include "nodedef.h" #include "gamedef.h" +#include "environment.h" #include "log.h" #include +#include // Helper function: // Checks for collision of a moving aabbox with a static aabbox @@ -183,11 +185,14 @@ bool wouldCollideWithCeiling( } -collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, +collisionMoveResult collisionMoveSimple(Environment* env, f32 pos_max_d, const aabb3f &box_0, f32 stepheight, f32 dtime, v3f &pos_f, v3f &speed_f, v3f &accel_f) { + Map * map = &env->getMap(); + IGameDef * gamedef = env->getGameDef(); + TimeTaker tt("collisionMoveSimple"); collisionMoveResult result; @@ -252,6 +257,27 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, assert(cboxes.size() == is_unloaded.size()); assert(cboxes.size() == is_step_up.size()); + { + TimeTaker tt3("collisionMoveSimple collect object boxes"); + + /* add object boxes to cboxes */ + core::list objects = env->getActiveObjects(); + + for (core::list::Iterator iter = objects.begin(); + iter != objects.end(); iter++) + { + aabb3f* object_collisionbox = (*iter)->getCollisionBox(); + //TODO do we need to check if it's really near enough? + if (object_collisionbox != NULL) + { + cboxes.push_back(*object_collisionbox); + is_unloaded.push_back(false); + is_step_up.push_back(false); + } + } + } //tt3 + + /* Collision detection */ @@ -277,7 +303,8 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, loopcount++; if(loopcount >= 100) { - infostream<<"collisionMoveSimple: WARNING: Loop count exceeded, aborting to avoid infiniite loop"< -class Map; -class IGameDef; +class Environment; struct collisionMoveResult { @@ -42,13 +41,13 @@ struct collisionMoveResult }; // Moves using a single iteration; speed should not exceed pos_max_d/dtime -collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, +collisionMoveResult collisionMoveSimple(Environment* env, f32 pos_max_d, const aabb3f &box_0, f32 stepheight, f32 dtime, v3f &pos_f, v3f &speed_f, v3f &accel_f); // Moves using as many iterations as needed -collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef, +collisionMoveResult collisionMovePrecise(Environment* env, f32 pos_max_d, const aabb3f &box_0, f32 stepheight, f32 dtime, v3f &pos_f, v3f &speed_f, v3f &accel_f); diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 3e330028a..b9afd8199 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1701,6 +1701,7 @@ private: int m_anim_num_frames; float m_anim_framelength; float m_anim_timer; + aabb3f m_collisionbox; public: LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env): @@ -1879,8 +1880,7 @@ public: v3f p_pos = m_position; v3f p_velocity = m_velocity; v3f p_acceleration = m_acceleration; - IGameDef *gamedef = env->getGameDef(); - moveresult = collisionMovePrecise(&env->getMap(), gamedef, + moveresult = collisionMovePrecise(env, pos_max_d, box, stepheight, dtime, p_pos, p_velocity, p_acceleration); // Apply results @@ -2047,6 +2047,21 @@ public: updateTexturePos(); } } + + aabb3f* getCollisionBox() { + if (m_prop->physical) { + //update collision box + m_collisionbox.MinEdge = m_prop->collisionbox.MinEdge * BS; + m_collisionbox.MaxEdge = m_prop->collisionbox.MaxEdge * BS; + + m_collisionbox.MinEdge += m_position; + m_collisionbox.MaxEdge += m_position; + + return &m_collisionbox; + } + + return NULL; + } }; // Prototype @@ -2070,6 +2085,7 @@ private: LocalPlayer *m_local_player; float m_damage_visual_timer; bool m_dead; + aabb3f m_collisionbox; public: PlayerCAO(IGameDef *gamedef, ClientEnvironment *env): @@ -2116,6 +2132,17 @@ public: } } + aabb3f* getCollisionBox() { + //update collision box + m_collisionbox.MinEdge = m_selection_box.MinEdge; + m_collisionbox.MaxEdge = m_selection_box.MaxEdge; + + m_collisionbox.MinEdge += m_position; + m_collisionbox.MaxEdge += m_position; + + return &m_collisionbox; + } + ~PlayerCAO() { if(m_node) diff --git a/src/content_sao.cpp b/src/content_sao.cpp index cb6be2f2c..e8290a8db 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -165,8 +165,7 @@ void ItemSAO::step(float dtime, bool send_recommended) v3f pos_f_old = pos_f; v3f accel_f = v3f(0,0,0); f32 stepheight = 0; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, + moveresult = collisionMoveSimple(m_env, pos_max_d, box, stepheight, dtime, pos_f, m_speed_f, accel_f); @@ -409,8 +408,7 @@ void RatSAO::step(float dtime, bool send_recommended) v3f pos_f_old = pos_f; v3f accel_f = v3f(0,0,0); f32 stepheight = 0; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, + moveresult = collisionMoveSimple(m_env, pos_max_d, box, stepheight, dtime, pos_f, m_speed_f, accel_f); m_touching_ground = moveresult.touching_ground; @@ -660,8 +658,7 @@ void Oerkki1SAO::step(float dtime, bool send_recommended) v3f pos_f_old = pos_f; v3f accel_f = v3f(0,0,0); f32 stepheight = 0; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMovePrecise(&m_env->getMap(), gamedef, + moveresult = collisionMovePrecise(m_env, pos_max_d, box, stepheight, dtime, pos_f, m_speed_f, accel_f); m_touching_ground = moveresult.touching_ground; @@ -910,8 +907,7 @@ void FireflySAO::step(float dtime, bool send_recommended) v3f pos_f_old = pos_f; v3f accel_f = v3f(0,0,0); f32 stepheight = 0; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, + moveresult = collisionMoveSimple(m_env, pos_max_d, box, stepheight, dtime, pos_f, m_speed_f, accel_f); m_touching_ground = moveresult.touching_ground; @@ -1634,8 +1630,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) v3f p_pos = m_base_position; v3f p_velocity = m_velocity; v3f p_acceleration = m_acceleration; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMovePrecise(&m_env->getMap(), gamedef, + moveresult = collisionMovePrecise(m_env, pos_max_d, box, stepheight, dtime, p_pos, p_velocity, p_acceleration); // Apply results @@ -1844,3 +1839,18 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) m_messages_out.push_back(aom); } +aabb3f* LuaEntitySAO::getCollisionBox() { + if (m_prop->physical) { + //update collision box + m_collisionbox.MinEdge = m_prop->collisionbox.MinEdge * BS; + m_collisionbox.MaxEdge = m_prop->collisionbox.MaxEdge * BS; + + m_collisionbox.MinEdge += m_base_position; + m_collisionbox.MaxEdge += m_base_position; + + return &m_collisionbox; + } + + return NULL; +} + diff --git a/src/content_sao.h b/src/content_sao.h index f0c9cea90..6ff2a04fe 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -32,6 +32,7 @@ public: static ServerActiveObject* create(ServerEnvironment *env, v3f pos, const std::string &data); void step(float dtime, bool send_recommended); + inline aabb3f* getCollisionBox() { return NULL; } private: float m_timer1; float m_age; @@ -51,6 +52,7 @@ public: ItemStack createItemStack(); void punch(ServerActiveObject *puncher, float time_from_last_punch); float getMinimumSavedMovement(){ return 0.1*BS; } + inline aabb3f* getCollisionBox() { return NULL; } private: std::string m_itemstring; bool m_itemstring_changed; @@ -71,6 +73,7 @@ public: std::string getClientInitializationData(); std::string getStaticData(); void punch(ServerActiveObject *puncher, float time_from_last_punch); + inline aabb3f* getCollisionBox() { return NULL; } private: bool m_is_active; IntervalLimiter m_inactive_interval; @@ -97,6 +100,7 @@ public: std::string getStaticData(); void punch(ServerActiveObject *puncher, float time_from_last_punch); bool isPeaceful(){return false;} + inline aabb3f* getCollisionBox() { return NULL; } private: void doDamage(u16 d); @@ -125,6 +129,7 @@ public: void step(float dtime, bool send_recommended); std::string getClientInitializationData(); std::string getStaticData(); + inline aabb3f* getCollisionBox() { return NULL; } private: bool m_is_active; IntervalLimiter m_inactive_interval; @@ -155,6 +160,7 @@ public: void step(float dtime, bool send_recommended); void punch(ServerActiveObject *puncher, float time_from_last_punch); bool isPeaceful(); + inline aabb3f* getCollisionBox() { return NULL; } private: void sendPosition(); void setPropertyDefaults(); @@ -222,6 +228,7 @@ public: void setSprite(v2s16 p, int num_frames, float framelength, bool select_horiz_by_yawpitch); std::string getName(); + aabb3f* getCollisionBox(); private: void sendPosition(bool do_interpolate, bool is_movement_end); @@ -238,6 +245,7 @@ private: v3f m_last_sent_velocity; float m_last_sent_position_timer; float m_last_sent_move_precision; + aabb3f m_collisionbox; }; #endif diff --git a/src/environment.cpp b/src/environment.cpp index 6f1d8ff55..f74299d6c 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -920,7 +920,7 @@ void ServerEnvironment::step(float dtime) v3f playerpos = player->getPosition(); // Move - player->move(dtime, *m_map, 100*BS); + player->move(dtime, this, 100*BS); /* Add footsteps to grass @@ -1803,6 +1803,22 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) } } +//get a list of all active objects +core::list ServerEnvironment::getActiveObjects() { + core::list retval; + + if (m_active_objects.size() > 0 ) + { + for (core::map::Iterator iter=m_active_objects.getIterator(); + iter.atEnd()==false; iter++) { + + retval.push_back(iter.getNode()->getValue()); + } + } + + return retval; +} + #ifndef SERVER @@ -1963,7 +1979,7 @@ void ClientEnvironment::step(float dtime) Move the lplayer. This also does collision detection. */ - lplayer->move(dtime_part, *m_map, position_max_increment, + lplayer->move(dtime_part, this, position_max_increment, &player_collisions); } } @@ -2034,7 +2050,7 @@ void ClientEnvironment::step(float dtime) if(player->isLocal() == false) { // Move - player->move(dtime, *m_map, 100*BS); + player->move(dtime, this, 100*BS); } @@ -2311,6 +2327,21 @@ ClientEnvEvent ClientEnvironment::getClientEvent() return m_client_event_queue.pop_front(); } +//get a list of all active objects +core::list ClientEnvironment::getActiveObjects() { + core::list retval; + + if (m_active_objects.size() > 0 ) + { + for (core::map::Iterator iter=m_active_objects.getIterator(); + iter.atEnd()==false; iter++) + { + retval.push_back(iter.getNode()->getValue()); + } + } + return retval; +} + #endif // #ifndef SERVER diff --git a/src/environment.h b/src/environment.h index 89c9fd676..e8338e37b 100644 --- a/src/environment.h +++ b/src/environment.h @@ -87,6 +87,9 @@ public: return m_time_of_day; } + virtual IGameDef *getGameDef() = 0; + virtual core::list getActiveObjects() = 0; + protected: // peer_ids in here should be unique, except that there may be many 0s core::list m_players; @@ -280,6 +283,8 @@ public: // This makes stuff happen void step(f32 dtime); + //get a list of all active objects + core::list getActiveObjects(); private: /* @@ -462,6 +467,9 @@ public: // Get event from queue. CEE_NONE is returned if queue is empty. ClientEnvEvent getClientEvent(); + + //get a list of all active objects + core::list getActiveObjects(); private: ClientMap *m_map; scene::ISceneManager *m_smgr; diff --git a/src/player.cpp b/src/player.cpp index 1aedf4a63..61cc2de7e 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -199,9 +199,10 @@ LocalPlayer::~LocalPlayer() { } -void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, +void LocalPlayer::move(f32 dtime, Environment* env, f32 pos_max_d, core::list *collision_info) { + Map& map = env->getMap(); INodeDefManager *nodemgr = m_gamedef->ndef(); v3f position = getPosition(); @@ -312,7 +313,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, v3f accel_f = v3f(0,0,0); - collisionMoveResult result = collisionMoveSimple(&map, m_gamedef, + collisionMoveResult result = collisionMoveSimple(env, pos_max_d, playerbox, player_stepheight, dtime, position, m_speed, accel_f); @@ -420,9 +421,9 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, } } -void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d) +void LocalPlayer::move(f32 dtime,Environment* env, f32 pos_max_d) { - move(dtime, map, pos_max_d, NULL); + move(dtime, env, pos_max_d, NULL); } void LocalPlayer::applyControl(float dtime) diff --git a/src/player.h b/src/player.h index d62fb6111..69db8ac51 100644 --- a/src/player.h +++ b/src/player.h @@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., class Map; class IGameDef; struct CollisionInfo; +class Environment; class Player { @@ -42,7 +43,7 @@ public: void resetInventory(); //void move(f32 dtime, Map &map); - virtual void move(f32 dtime, Map &map, f32 pos_max_d) = 0; + virtual void move(f32 dtime, Environment* env, f32 pos_max_d) = 0; v3f getSpeed() { @@ -231,9 +232,9 @@ public: return true; } - void move(f32 dtime, Map &map, f32 pos_max_d, + void move(f32 dtime, Environment* env, f32 pos_max_d, core::list *collision_info); - void move(f32 dtime, Map &map, f32 pos_max_d); + void move(f32 dtime, Environment* env, f32 pos_max_d); void applyControl(float dtime); diff --git a/src/serverremoteplayer.cpp b/src/serverremoteplayer.cpp index 728ffe026..6663d22f8 100644 --- a/src/serverremoteplayer.cpp +++ b/src/serverremoteplayer.cpp @@ -262,9 +262,20 @@ void ServerRemotePlayer::setHP(s16 hp_) m_messages_out.push_back(aom); } } + s16 ServerRemotePlayer::getHP() { return hp; } +aabb3f* ServerRemotePlayer::getCollisionBox() { + m_collisionbox.MinEdge = aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.).MinEdge; + m_collisionbox.MaxEdge = aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.).MaxEdge; + + m_collisionbox.MinEdge += m_position; + m_collisionbox.MaxEdge += m_position; + + return &m_collisionbox; +} + diff --git a/src/serverremoteplayer.h b/src/serverremoteplayer.h index 94926c824..6de36eebc 100644 --- a/src/serverremoteplayer.h +++ b/src/serverremoteplayer.h @@ -40,7 +40,7 @@ public: virtual bool isLocal() const { return false; } - virtual void move(f32 dtime, Map &map, f32 pos_max_d) + virtual void move(f32 dtime, Environment* env, f32 pos_max_d) { } @@ -93,9 +93,10 @@ public: bool m_is_in_environment; // Incremented by step(), read and reset by Server float m_time_from_last_punch; - + aabb3f* getCollisionBox(); private: bool m_position_not_sent; + aabb3f m_collisionbox; }; #endif