mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-01 17:38:41 +00:00
Added object <-> object collision handling (player + luaentity support only)
This commit is contained in:
parent
f34f75291b
commit
ffe6025f61
12 changed files with 157 additions and 32 deletions
|
@ -62,6 +62,7 @@ public:
|
|||
|
||||
virtual u8 getType() const = 0;
|
||||
|
||||
virtual aabb3f* getCollisionBox() = 0;
|
||||
protected:
|
||||
u16 m_id; // 0 is invalid, "no id"
|
||||
};
|
||||
|
|
|
@ -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 <vector>
|
||||
#include <list>
|
||||
|
||||
// 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<ActiveObject*> objects = env->getActiveObjects();
|
||||
|
||||
for (core::list<ActiveObject*>::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"<<std::endl;
|
||||
infostream<<"collisionMoveSimple: WARNING: Loop count exceeded, "
|
||||
"aborting to avoid infiniite loop"<<std::endl;
|
||||
dtime = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -422,7 +449,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
|||
return result;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -470,7 +497,7 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
|||
dtime_downcount = 0;
|
||||
}
|
||||
|
||||
collisionMoveResult result = collisionMoveSimple(map, gamedef,
|
||||
collisionMoveResult result = collisionMoveSimple(env,
|
||||
pos_max_d, box_0, stepheight, dtime_part,
|
||||
pos_f, speed_f, accel_f);
|
||||
|
||||
|
|
|
@ -23,8 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "common_irrlicht.h"
|
||||
#include <vector>
|
||||
|
||||
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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<ActiveObject*> ServerEnvironment::getActiveObjects() {
|
||||
core::list<ActiveObject*> retval;
|
||||
|
||||
if (m_active_objects.size() > 0 )
|
||||
{
|
||||
for (core::map<u16, ServerActiveObject*>::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<ActiveObject*> ClientEnvironment::getActiveObjects() {
|
||||
core::list<ActiveObject*> retval;
|
||||
|
||||
if (m_active_objects.size() > 0 )
|
||||
{
|
||||
for (core::map<u16, ClientActiveObject*>::Iterator iter=m_active_objects.getIterator();
|
||||
iter.atEnd()==false; iter++)
|
||||
{
|
||||
retval.push_back(iter.getNode()->getValue());
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif // #ifndef SERVER
|
||||
|
||||
|
||||
|
|
|
@ -87,6 +87,9 @@ public:
|
|||
return m_time_of_day;
|
||||
}
|
||||
|
||||
virtual IGameDef *getGameDef() = 0;
|
||||
virtual core::list<ActiveObject*> getActiveObjects() = 0;
|
||||
|
||||
protected:
|
||||
// peer_ids in here should be unique, except that there may be many 0s
|
||||
core::list<Player*> m_players;
|
||||
|
@ -280,6 +283,8 @@ public:
|
|||
// This makes stuff happen
|
||||
void step(f32 dtime);
|
||||
|
||||
//get a list of all active objects
|
||||
core::list<ActiveObject*> 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<ActiveObject*> getActiveObjects();
|
||||
private:
|
||||
ClientMap *m_map;
|
||||
scene::ISceneManager *m_smgr;
|
||||
|
|
|
@ -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<CollisionInfo> *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)
|
||||
|
|
|
@ -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<CollisionInfo> *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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue