}
virtual u8 getType() const = 0;
-
+ virtual bool getCollisionBox(aabb3f *toset) = 0;
protected:
u16 m_id; // 0 is invalid, "no id"
};
#include "nodedef.h"
#include "gamedef.h"
#include "log.h"
+#include "environment.h"
+#include "serverobject.h"
#include <vector>
+#include <set>
#include "util/timetaker.h"
#include "main.h" // g_profiler
#include "profiler.h"
}
-collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
+collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
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();
//TimeTaker tt("collisionMoveSimple");
ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG);
std::vector<aabb3f> cboxes;
std::vector<bool> is_unloaded;
std::vector<bool> is_step_up;
+ std::vector<bool> is_object;
std::vector<int> bouncy_values;
std::vector<v3s16> node_positions;
{
is_step_up.push_back(false);
bouncy_values.push_back(n_bouncy_value);
node_positions.push_back(p);
+ is_object.push_back(false);
}
}
catch(InvalidPositionException &e)
is_step_up.push_back(false);
bouncy_values.push_back(0);
node_positions.push_back(p);
+ is_object.push_back(false);
}
}
} // tt2
+ {
+ ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
+ //TimeTaker tt3("collisionMoveSimple collect object boxes");
+
+ /* add object boxes to cboxes */
+
+
+ std::list<ActiveObject*> objects;
+#ifndef SERVER
+ ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
+ if (c_env != 0)
+ {
+ f32 distance = speed_f.getLength();
+ std::vector<DistanceSortedActiveObject> clientobjects;
+ c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects);
+ for (int i=0; i < clientobjects.size(); i++)
+ {
+ objects.push_back((ActiveObject*)clientobjects[i].obj);
+ }
+ }
+ else
+#endif
+ {
+ ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
+ if (s_env != 0)
+ {
+ f32 distance = speed_f.getLength();
+ std::set<u16> s_objects = s_env->getObjectsInsideRadius(pos_f,distance * 1.5);
+ for (std::set<u16>::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++)
+ {
+ ServerActiveObject *current = s_env->getActiveObject(*iter);
+ objects.push_back((ActiveObject*)current);
+ }
+ }
+ }
+
+ for (std::list<ActiveObject*>::const_iterator iter = objects.begin();iter != objects.end(); ++iter)
+ {
+ ActiveObject *object = *iter;
+
+ if (object != NULL)
+ {
+ aabb3f object_collisionbox;
+ if (object->getCollisionBox(&object_collisionbox))
+ {
+ cboxes.push_back(object_collisionbox);
+ is_unloaded.push_back(false);
+ is_step_up.push_back(false);
+ bouncy_values.push_back(0);
+ node_positions.push_back(v3s16(0,0,0));
+ is_object.push_back(true);
+ }
+ }
+ }
+ } //tt3
+
assert(cboxes.size() == is_unloaded.size());
assert(cboxes.size() == is_step_up.size());
assert(cboxes.size() == bouncy_values.size());
assert(cboxes.size() == node_positions.size());
+ assert(cboxes.size() == is_object.size());
/*
Collision detection
is_collision = false;
CollisionInfo info;
- info.type = COLLISION_NODE;
+ if (is_object[nearest_boxindex]) {
+ info.type = COLLISION_OBJECT;
+ }
+ else
+ info.type = COLLISION_NODE;
info.node_p = node_positions[nearest_boxindex];
info.bouncy = bouncy;
info.old_speed = speed_f;
class Map;
class IGameDef;
+class Environment;
enum CollisionType
{
- COLLISION_NODE
+ COLLISION_NODE,
+ COLLISION_OBJECT,
};
struct CollisionInfo
};
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
-collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
+collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
f32 pos_max_d, const aabb3f &box_0,
f32 stepheight, f32 dtime,
v3f &pos_f, v3f &speed_f, v3f &accel_f);
void processMessage(const std::string &data);
+ bool getCollisionBox(aabb3f *toset) { return false; }
private:
scene::IMeshSceneNode *m_node;
v3f m_position;
std::string infoText()
{return m_infotext;}
+ bool getCollisionBox(aabb3f *toset) { return false; }
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
ClientActiveObject::registerType(getType(), create);
}
+ bool getCollisionBox(aabb3f *toset) {
+ if (m_prop.physical) {
+ aabb3f retval;
+ //update collision box
+ toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
+ toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
+
+ toset->MinEdge += m_position;
+ toset->MaxEdge += m_position;
+
+ return true;
+ }
+
+ return false;
+ }
+
void initialize(const std::string &data)
{
infostream<<"GenericCAO: Got init data"<<std::endl;
v3f p_pos = m_position;
v3f p_velocity = m_velocity;
v3f p_acceleration = m_acceleration;
- IGameDef *gamedef = env->getGameDef();
- moveresult = collisionMoveSimple(&env->getMap(), gamedef,
+ moveresult = collisionMoveSimple(env,env->getGameDef(),
pos_max_d, box, stepheight, dtime,
p_pos, p_velocity, p_acceleration);
// Apply results
infostream<<"DummyLoadSAO step"<<std::endl;
}
+ bool getCollisionBox(aabb3f *toset) {
+ return false;
+ }
+
private:
};
}
}
+ bool getCollisionBox(aabb3f *toset) {
+ return false;
+ }
+
private:
float m_timer1;
float m_age;
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,m_env->getGameDef(),
pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f);
return 0;
}
+ bool getCollisionBox(aabb3f *toset) {
+ return false;
+ }
+
private:
std::string m_itemstring;
v3f p_pos = m_base_position;
v3f p_velocity = m_velocity;
v3f p_acceleration = m_acceleration;
- IGameDef *gamedef = m_env->getGameDef();
- moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
+ moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
pos_max_d, box, stepheight, dtime,
p_pos, p_velocity, p_acceleration);
// Apply results
m_messages_out.push_back(aom);
}
+bool LuaEntitySAO::getCollisionBox(aabb3f *toset) {
+ if (m_prop.physical)
+ {
+ //update collision box
+ toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
+ toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
+
+ toset->MinEdge += m_base_position;
+ toset->MaxEdge += m_base_position;
+
+ return true;
+ }
+
+ return false;
+}
+
/*
PlayerSAO
*/
return gob_cmd_set_properties(m_prop);
}
+bool PlayerSAO::getCollisionBox(aabb3f *toset) {
+ //player collision handling is already done clientside no need to do it twice
+ return false;
+}
void setSprite(v2s16 p, int num_frames, float framelength,
bool select_horiz_by_yawpitch);
std::string getName();
+ bool getCollisionBox(aabb3f *toset);
private:
std::string getPropertyPacket();
void sendPosition(bool do_interpolate, bool is_movement_end);
m_is_singleplayer = is_singleplayer;
}
+ bool getCollisionBox(aabb3f *toset);
+
private:
std::string getPropertyPacket();
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);
}
}
#include "gamedef.h"
#include "nodedef.h"
#include "settings.h"
+#include "environment.h"
#include "map.h"
#include "util/numeric.h"
{
}
-void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
+void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
std::list<CollisionInfo> *collision_info)
{
+ Map *map = &env->getMap();
INodeDefManager *nodemgr = m_gamedef->ndef();
v3f position = getPosition();
if(in_liquid)
{
v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
- in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
- liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity;
+ in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
+ liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
}
// If not in liquid, the threshold of going in is at lower y
else
{
v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
- in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
- liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity;
+ in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
+ liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
}
}
catch(InvalidPositionException &e)
*/
try{
v3s16 pp = floatToInt(position + v3f(0,0,0), BS);
- in_liquid_stable = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
+ in_liquid_stable = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
}
catch(InvalidPositionException &e)
{
try {
v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
- is_climbing = ((nodemgr->get(map.getNode(pp).getContent()).climbable ||
- nodemgr->get(map.getNode(pp2).getContent()).climbable) && !free_move);
+ is_climbing = ((nodemgr->get(map->getNode(pp).getContent()).climbable ||
+ nodemgr->get(map->getNode(pp2).getContent()).climbable) && !free_move);
}
catch(InvalidPositionException &e)
{
v3f accel_f = v3f(0,0,0);
- collisionMoveResult result = collisionMoveSimple(&map, m_gamedef,
+ collisionMoveResult result = collisionMoveSimple(env, m_gamedef,
pos_max_d, playerbox, player_stepheight, dtime,
position, m_speed, accel_f);
*/
v3s16 current_node = floatToInt(position - v3f(0,BS/2,0), BS);
if(m_sneak_node_exists &&
- nodemgr->get(map.getNodeNoEx(m_old_node_below)).name == "air" &&
+ nodemgr->get(map->getNodeNoEx(m_old_node_below)).name == "air" &&
m_old_node_below_type != "air")
{
// Old node appears to have been removed; that is,
m_need_to_get_new_sneak_node = false;
m_sneak_node_exists = false;
}
- else if(nodemgr->get(map.getNodeNoEx(current_node)).name != "air")
+ else if(nodemgr->get(map->getNodeNoEx(current_node)).name != "air")
{
// We are on something, so make sure to recalculate the sneak
// node.
try{
// The node to be sneaked on has to be walkable
- if(nodemgr->get(map.getNode(p)).walkable == false)
+ if(nodemgr->get(map->getNode(p)).walkable == false)
continue;
// And the node above it has to be nonwalkable
- if(nodemgr->get(map.getNode(p+v3s16(0,1,0))).walkable == true)
+ if(nodemgr->get(map->getNode(p+v3s16(0,1,0))).walkable == true)
continue;
}
catch(InvalidPositionException &e)
{
camera_barely_in_ceiling = false;
v3s16 camera_np = floatToInt(getEyePosition(), BS);
- MapNode n = map.getNodeNoEx(camera_np);
+ MapNode n = map->getNodeNoEx(camera_np);
if(n.getContent() != CONTENT_IGNORE){
if(nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2){
camera_barely_in_ceiling = true;
Update the node last under the player
*/
m_old_node_below = floatToInt(position - v3f(0,BS/2,0), BS);
- m_old_node_below_type = nodemgr->get(map.getNodeNoEx(m_old_node_below)).name;
+ m_old_node_below_type = nodemgr->get(map->getNodeNoEx(m_old_node_below)).name;
/*
Check properties of the node on which the player is standing
*/
- const ContentFeatures &f = nodemgr->get(map.getNodeNoEx(getStandingNodePos()));
+ const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos()));
// Determine if jumping is possible
m_can_jump = touching_ground && !in_liquid;
if(itemgroup_get(f.groups, "disable_jump"))
m_can_jump = false;
}
-void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
+void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d)
{
- move(dtime, map, pos_max_d, NULL);
+ move(dtime, env, pos_max_d, NULL);
}
void LocalPlayer::applyControl(float dtime)
#include "player.h"
#include <list>
+class ClientEnvironment;
+
class LocalPlayer : public Player
{
public:
v3f overridePosition;
- void move(f32 dtime, Map &map, f32 pos_max_d,
+ void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
std::list<CollisionInfo> *collision_info);
- void move(f32 dtime, Map &map, f32 pos_max_d);
+ void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d);
void applyControl(float dtime);
v3f p_pos = m_pos*BS;
v3f p_velocity = m_velocity*BS;
v3f p_acceleration = m_acceleration*BS;
- collisionMoveSimple(&env.getClientMap(), m_gamedef,
+ collisionMoveSimple(&env, m_gamedef,
BS*0.5, box,
0, dtime,
p_pos, p_velocity, p_acceleration);