mirror of
https://github.com/moparisthebest/minetest
synced 2024-11-15 13:55:11 -05:00
implemented rats in new system to verify that it works
This commit is contained in:
parent
08bbf96877
commit
5a4d8ffad3
@ -24,6 +24,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
ClientActiveObject
|
||||||
|
*/
|
||||||
|
|
||||||
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
|
||||||
|
|
||||||
ClientActiveObject::ClientActiveObject(u16 id):
|
ClientActiveObject::ClientActiveObject(u16 id):
|
||||||
@ -231,8 +235,9 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr)
|
|||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
//buf->getMaterial().setTexture(0, NULL);
|
//buf->getMaterial().setTexture(0, NULL);
|
||||||
|
// Initialize with the stick texture
|
||||||
buf->getMaterial().setTexture
|
buf->getMaterial().setTexture
|
||||||
(0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
|
(0, driver->getTexture(porting::getDataPath("stick.png").c_str()));
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
@ -313,19 +318,12 @@ void ItemCAO::processMessage(const std::string &data)
|
|||||||
{
|
{
|
||||||
dstream<<"ItemCAO: Got message"<<std::endl;
|
dstream<<"ItemCAO: Got message"<<std::endl;
|
||||||
std::istringstream is(data, std::ios::binary);
|
std::istringstream is(data, std::ios::binary);
|
||||||
char buf[4];
|
|
||||||
// command
|
// command
|
||||||
is.read(buf, 1);
|
u8 cmd = readU8(is);
|
||||||
u8 cmd = buf[0];
|
|
||||||
if(cmd == 0)
|
if(cmd == 0)
|
||||||
{
|
{
|
||||||
// pos
|
// pos
|
||||||
is.read(buf, 4);
|
m_position = readV3F1000(is);
|
||||||
m_position.X = (float)readS32((u8*)buf)/1000.0;
|
|
||||||
is.read(buf, 4);
|
|
||||||
m_position.Y = (float)readS32((u8*)buf)/1000.0;
|
|
||||||
is.read(buf, 4);
|
|
||||||
m_position.Z = (float)readS32((u8*)buf)/1000.0;
|
|
||||||
updateNodePos();
|
updateNodePos();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,20 +334,13 @@ void ItemCAO::initialize(const std::string &data)
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::istringstream is(data, std::ios::binary);
|
std::istringstream is(data, std::ios::binary);
|
||||||
char buf[4];
|
|
||||||
// version
|
// version
|
||||||
is.read(buf, 1);
|
u8 version = readU8(is);
|
||||||
u8 version = buf[0];
|
|
||||||
// check version
|
// check version
|
||||||
if(version != 0)
|
if(version != 0)
|
||||||
return;
|
return;
|
||||||
// pos
|
// pos
|
||||||
is.read(buf, 4);
|
m_position = readV3F1000(is);
|
||||||
m_position.X = (float)readS32((u8*)buf)/1000.0;
|
|
||||||
is.read(buf, 4);
|
|
||||||
m_position.Y = (float)readS32((u8*)buf)/1000.0;
|
|
||||||
is.read(buf, 4);
|
|
||||||
m_position.Z = (float)readS32((u8*)buf)/1000.0;
|
|
||||||
// inventorystring
|
// inventorystring
|
||||||
m_inventorystring = deSerializeString(is);
|
m_inventorystring = deSerializeString(is);
|
||||||
}
|
}
|
||||||
@ -400,4 +391,164 @@ void ItemCAO::initialize(const std::string &data)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
RatCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
RatCAO proto_RatCAO;
|
||||||
|
|
||||||
|
RatCAO::RatCAO():
|
||||||
|
ClientActiveObject(0),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0))
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
RatCAO::~RatCAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientActiveObject* RatCAO::create()
|
||||||
|
{
|
||||||
|
return new RatCAO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::addToScene(scene::ISceneManager *smgr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
//buf->getMaterial().setTexture(0, NULL);
|
||||||
|
buf->getMaterial().setTexture
|
||||||
|
(0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u16 mc = mesh->getMeshBufferCount();
|
||||||
|
for(u16 j=0; j<mc; j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||||
|
u16 vc = buf->getVertexCount();
|
||||||
|
for(u16 i=0; i<vc; i++)
|
||||||
|
{
|
||||||
|
vertices[i].Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 RatCAO::getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position, BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//m_node->setPosition(m_position);
|
||||||
|
m_node->setPosition(pos_translator.vect_show);
|
||||||
|
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = 180.0 - m_yaw;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"RatCAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == 0)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatCAO::initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"RatCAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +35,63 @@ Some planning
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
SmoothTranslator
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct SmoothTranslator
|
||||||
|
{
|
||||||
|
v3f vect_old;
|
||||||
|
f32 anim_counter;
|
||||||
|
f32 anim_time;
|
||||||
|
f32 anim_time_counter;
|
||||||
|
v3f vect_show;
|
||||||
|
v3f vect_aim;
|
||||||
|
|
||||||
|
SmoothTranslator():
|
||||||
|
vect_old(0,0,0),
|
||||||
|
anim_counter(0),
|
||||||
|
anim_time(0),
|
||||||
|
anim_time_counter(0),
|
||||||
|
vect_show(0,0,0),
|
||||||
|
vect_aim(0,0,0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void init(v3f vect)
|
||||||
|
{
|
||||||
|
vect_old = vect;
|
||||||
|
vect_show = vect;
|
||||||
|
vect_aim = vect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(v3f vect_new)
|
||||||
|
{
|
||||||
|
vect_old = vect_show;
|
||||||
|
vect_aim = vect_new;
|
||||||
|
if(anim_time < 0.001 || anim_time > 1.0)
|
||||||
|
anim_time = anim_time_counter;
|
||||||
|
else
|
||||||
|
anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
|
||||||
|
anim_time_counter = 0;
|
||||||
|
anim_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void translate(f32 dtime)
|
||||||
|
{
|
||||||
|
anim_time_counter = anim_time_counter + dtime;
|
||||||
|
anim_counter = anim_counter + dtime;
|
||||||
|
v3f vect_move = vect_aim - vect_old;
|
||||||
|
f32 moveratio = 1.0;
|
||||||
|
if(anim_time > 0.001)
|
||||||
|
moveratio = anim_time_counter / anim_time;
|
||||||
|
// Move a bit less than should, to avoid oscillation
|
||||||
|
moveratio = moveratio * 0.8;
|
||||||
|
if(moveratio > 1.5)
|
||||||
|
moveratio = 1.5;
|
||||||
|
vect_show = vect_old + vect_move * moveratio;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ClientEnvironment;
|
class ClientEnvironment;
|
||||||
|
|
||||||
class ClientActiveObject : public ActiveObject
|
class ClientActiveObject : public ActiveObject
|
||||||
@ -168,5 +225,47 @@ private:
|
|||||||
std::string m_inventorystring;
|
std::string m_inventorystring;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
RatCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RatCAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RatCAO();
|
||||||
|
virtual ~RatCAO();
|
||||||
|
|
||||||
|
u8 getType() const
|
||||||
|
{
|
||||||
|
return ACTIVEOBJECT_TYPE_RAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create();
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr);
|
||||||
|
void removeFromScene();
|
||||||
|
void updateLight(u8 light_at_pos);
|
||||||
|
v3s16 getLightPosition();
|
||||||
|
void updateNodePos();
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env);
|
||||||
|
|
||||||
|
void processMessage(const std::string &data);
|
||||||
|
|
||||||
|
void initialize(const std::string &data);
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
v3f getPosition()
|
||||||
|
{return m_position;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
float m_yaw;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
184
src/collision.cpp
Normal file
184
src/collision.cpp
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "collision.h"
|
||||||
|
#include "mapblock.h"
|
||||||
|
#include "map.h"
|
||||||
|
|
||||||
|
collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
|
||||||
|
const core::aabbox3d<f32> &box_0,
|
||||||
|
f32 dtime, v3f &pos_f, v3f &speed_f)
|
||||||
|
{
|
||||||
|
collisionMoveResult result;
|
||||||
|
|
||||||
|
v3f oldpos_f = pos_f;
|
||||||
|
v3s16 oldpos_i = floatToInt(oldpos_f, BS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate new position
|
||||||
|
*/
|
||||||
|
pos_f += speed_f * dtime;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Collision detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
// position in nodes
|
||||||
|
v3s16 pos_i = floatToInt(pos_f, BS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Collision uncertainty radius
|
||||||
|
Make it a bit larger than the maximum distance of movement
|
||||||
|
*/
|
||||||
|
f32 d = pos_max_d * 1.1;
|
||||||
|
// A fairly large value in here makes moving smoother
|
||||||
|
//f32 d = 0.15*BS;
|
||||||
|
|
||||||
|
// This should always apply, otherwise there are glitches
|
||||||
|
assert(d > pos_max_d);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate collision box
|
||||||
|
*/
|
||||||
|
core::aabbox3d<f32> box = box_0;
|
||||||
|
box.MaxEdge += pos_f;
|
||||||
|
box.MinEdge += pos_f;
|
||||||
|
core::aabbox3d<f32> oldbox = box_0;
|
||||||
|
oldbox.MaxEdge += oldpos_f;
|
||||||
|
oldbox.MinEdge += oldpos_f;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the object lies on a walkable node, this is set to true.
|
||||||
|
*/
|
||||||
|
result.touching_ground = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Go through every node around the object
|
||||||
|
*/
|
||||||
|
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
||||||
|
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
||||||
|
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
// Object collides into walkable nodes
|
||||||
|
if(content_walkable(map->getNode(v3s16(x,y,z)).d) == false)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
// Doing nothing here will block the object from
|
||||||
|
// walking over map borders
|
||||||
|
}
|
||||||
|
|
||||||
|
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
See if the object is touching ground.
|
||||||
|
|
||||||
|
Object touches ground if object's minimum Y is near node's
|
||||||
|
maximum Y and object's X-Z-area overlaps with the node's
|
||||||
|
X-Z-area.
|
||||||
|
|
||||||
|
Use 0.15*BS so that it is easier to get on a node.
|
||||||
|
*/
|
||||||
|
if(
|
||||||
|
//fabs(nodebox.MaxEdge.Y-box.MinEdge.Y) < d
|
||||||
|
fabs(nodebox.MaxEdge.Y-box.MinEdge.Y) < 0.15*BS
|
||||||
|
&& nodebox.MaxEdge.X-d > box.MinEdge.X
|
||||||
|
&& nodebox.MinEdge.X+d < box.MaxEdge.X
|
||||||
|
&& nodebox.MaxEdge.Z-d > box.MinEdge.Z
|
||||||
|
&& nodebox.MinEdge.Z+d < box.MaxEdge.Z
|
||||||
|
){
|
||||||
|
result.touching_ground = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If object doesn't intersect with node, ignore node.
|
||||||
|
if(box.intersectsWithBox(nodebox) == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Go through every axis
|
||||||
|
*/
|
||||||
|
v3f dirs[3] = {
|
||||||
|
v3f(0,0,1), // back-front
|
||||||
|
v3f(0,1,0), // top-bottom
|
||||||
|
v3f(1,0,0), // right-left
|
||||||
|
};
|
||||||
|
for(u16 i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Calculate values along the axis
|
||||||
|
*/
|
||||||
|
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]);
|
||||||
|
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]);
|
||||||
|
f32 objectmax = box.MaxEdge.dotProduct(dirs[i]);
|
||||||
|
f32 objectmin = box.MinEdge.dotProduct(dirs[i]);
|
||||||
|
f32 objectmax_old = oldbox.MaxEdge.dotProduct(dirs[i]);
|
||||||
|
f32 objectmin_old = oldbox.MinEdge.dotProduct(dirs[i]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check collision for the axis.
|
||||||
|
Collision happens when object is going through a surface.
|
||||||
|
*/
|
||||||
|
bool negative_axis_collides =
|
||||||
|
(nodemax > objectmin && nodemax <= objectmin_old + d
|
||||||
|
&& speed_f.dotProduct(dirs[i]) < 0);
|
||||||
|
bool positive_axis_collides =
|
||||||
|
(nodemin < objectmax && nodemin >= objectmax_old - d
|
||||||
|
&& speed_f.dotProduct(dirs[i]) > 0);
|
||||||
|
bool main_axis_collides =
|
||||||
|
negative_axis_collides || positive_axis_collides;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check overlap of object and node in other axes
|
||||||
|
*/
|
||||||
|
bool other_axes_overlap = true;
|
||||||
|
for(u16 j=0; j<3; j++)
|
||||||
|
{
|
||||||
|
if(j == i)
|
||||||
|
continue;
|
||||||
|
f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]);
|
||||||
|
f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]);
|
||||||
|
f32 objectmax = box.MaxEdge.dotProduct(dirs[j]);
|
||||||
|
f32 objectmin = box.MinEdge.dotProduct(dirs[j]);
|
||||||
|
if(!(nodemax - d > objectmin && nodemin + d < objectmax))
|
||||||
|
{
|
||||||
|
other_axes_overlap = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If this is a collision, revert the pos_f in the main
|
||||||
|
direction.
|
||||||
|
*/
|
||||||
|
if(other_axes_overlap && main_axis_collides)
|
||||||
|
{
|
||||||
|
speed_f -= speed_f.dotProduct(dirs[i]) * dirs[i];
|
||||||
|
pos_f -= pos_f.dotProduct(dirs[i]) * dirs[i];
|
||||||
|
pos_f += oldpos_f.dotProduct(dirs[i]) * dirs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // xyz
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
43
src/collision.h
Normal file
43
src/collision.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COLLISION_HEADER
|
||||||
|
#define COLLISION_HEADER
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
|
||||||
|
class Map;
|
||||||
|
|
||||||
|
struct collisionMoveResult
|
||||||
|
{
|
||||||
|
bool touching_ground;
|
||||||
|
|
||||||
|
collisionMoveResult():
|
||||||
|
touching_ground(false)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
|
||||||
|
const core::aabbox3d<f32> &box_0,
|
||||||
|
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||||
|
//{return collisionMoveResult();}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -189,7 +189,8 @@ u32 Environment::getDayNightRatio()
|
|||||||
ServerEnvironment::ServerEnvironment(ServerMap *map, Server *server):
|
ServerEnvironment::ServerEnvironment(ServerMap *map, Server *server):
|
||||||
m_map(map),
|
m_map(map),
|
||||||
m_server(server),
|
m_server(server),
|
||||||
m_random_spawn_timer(3)
|
m_random_spawn_timer(3),
|
||||||
|
m_send_recommended_timer(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,19 +423,25 @@ void ServerEnvironment::step(float dtime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(g_settings.getBool("enable_experimental"))
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Step active objects
|
Step active objects
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
bool send_recommended = false;
|
||||||
|
m_send_recommended_timer += dtime;
|
||||||
|
if(m_send_recommended_timer > 0.2)
|
||||||
|
{
|
||||||
|
m_send_recommended_timer = 0;
|
||||||
|
send_recommended = true;
|
||||||
|
}
|
||||||
|
|
||||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||||
i = m_active_objects.getIterator();
|
i = m_active_objects.getIterator();
|
||||||
i.atEnd()==false; i++)
|
i.atEnd()==false; i++)
|
||||||
{
|
{
|
||||||
ServerActiveObject* obj = i.getNode()->getValue();
|
ServerActiveObject* obj = i.getNode()->getValue();
|
||||||
// Step object, putting messages directly to the queue
|
// Step object, putting messages directly to the queue
|
||||||
obj->step(dtime, m_active_object_messages);
|
obj->step(dtime, m_active_object_messages, send_recommended);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -460,6 +467,19 @@ void ServerEnvironment::step(float dtime)
|
|||||||
// If not m_removed, don't remove.
|
// If not m_removed, don't remove.
|
||||||
if(obj->m_removed == false)
|
if(obj->m_removed == false)
|
||||||
continue;
|
continue;
|
||||||
|
// Delete static data from block
|
||||||
|
if(obj->m_static_exists)
|
||||||
|
{
|
||||||
|
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
|
||||||
|
if(block)
|
||||||
|
{
|
||||||
|
block->m_static_objects.remove(id);
|
||||||
|
block->setChangedFlag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If m_known_by_count > 0, don't actually remove.
|
||||||
|
if(obj->m_known_by_count > 0)
|
||||||
|
continue;
|
||||||
// Delete
|
// Delete
|
||||||
delete obj;
|
delete obj;
|
||||||
// Id to be removed from m_active_objects
|
// Id to be removed from m_active_objects
|
||||||
@ -633,6 +653,9 @@ void ServerEnvironment::step(float dtime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(g_settings.getBool("enable_experimental"))
|
||||||
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TEST CODE
|
TEST CODE
|
||||||
*/
|
*/
|
||||||
@ -668,7 +691,8 @@ void ServerEnvironment::step(float dtime)
|
|||||||
|
|
||||||
//TestSAO *obj = new TestSAO(this, 0, pos);
|
//TestSAO *obj = new TestSAO(this, 0, pos);
|
||||||
//ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
|
//ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
|
||||||
//addActiveObject(obj);
|
ServerActiveObject *obj = new RatSAO(this, 0, pos);
|
||||||
|
addActiveObject(obj);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1082,6 +1106,7 @@ void ClientEnvironment::step(float dtime)
|
|||||||
/*
|
/*
|
||||||
Step active objects
|
Step active objects
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for(core::map<u16, ClientActiveObject*>::Iterator
|
for(core::map<u16, ClientActiveObject*>::Iterator
|
||||||
i = m_active_objects.getIterator();
|
i = m_active_objects.getIterator();
|
||||||
i.atEnd()==false; i++)
|
i.atEnd()==false; i++)
|
||||||
|
@ -153,6 +153,7 @@ private:
|
|||||||
core::map<u16, ServerActiveObject*> m_active_objects;
|
core::map<u16, ServerActiveObject*> m_active_objects;
|
||||||
Queue<ActiveObjectMessage> m_active_object_messages;
|
Queue<ActiveObjectMessage> m_active_object_messages;
|
||||||
float m_random_spawn_timer;
|
float m_random_spawn_timer;
|
||||||
|
float m_send_recommended_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "serverobject.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
InventoryItem
|
InventoryItem
|
||||||
@ -90,6 +91,19 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Create an ItemSAO
|
||||||
|
*/
|
||||||
|
// Get item string
|
||||||
|
std::ostringstream os(std::ios_base::binary);
|
||||||
|
serialize(os);
|
||||||
|
// Create object
|
||||||
|
ServerActiveObject *obj = new ItemSAO(env, 0, pos, os.str());
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MaterialItem
|
MaterialItem
|
||||||
*/
|
*/
|
||||||
@ -124,6 +138,48 @@ InventoryItem *MaterialItem::createCookResult()
|
|||||||
CraftItem
|
CraftItem
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef SERVER
|
||||||
|
video::ITexture * CraftItem::getImage()
|
||||||
|
{
|
||||||
|
if(g_texturesource == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
if(m_subname == "Stick")
|
||||||
|
name = "stick.png";
|
||||||
|
else if(m_subname == "lump_of_coal")
|
||||||
|
name = "lump_of_coal.png";
|
||||||
|
else if(m_subname == "lump_of_iron")
|
||||||
|
name = "lump_of_iron.png";
|
||||||
|
else if(m_subname == "steel_ingot")
|
||||||
|
name = "steel_ingot.png";
|
||||||
|
else if(m_subname == "rat")
|
||||||
|
name = "rat.png";
|
||||||
|
else
|
||||||
|
name = "cloud.png";
|
||||||
|
|
||||||
|
// Get such a texture
|
||||||
|
//return g_irrlicht->getTexture(name);
|
||||||
|
return g_texturesource->getTextureRaw(name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos)
|
||||||
|
{
|
||||||
|
// Special cases
|
||||||
|
if(m_subname == "rat")
|
||||||
|
{
|
||||||
|
ServerActiveObject *obj = new RatSAO(env, id, pos);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
// Default
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return InventoryItem::createSAO(env, id, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CraftItem::isCookable()
|
bool CraftItem::isCookable()
|
||||||
{
|
{
|
||||||
if(m_subname == "lump_of_iron")
|
if(m_subname == "lump_of_iron")
|
||||||
@ -144,6 +200,7 @@ InventoryItem *CraftItem::createCookResult()
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
MapBlockObjectItem
|
MapBlockObjectItem
|
||||||
|
TODO: Remove
|
||||||
*/
|
*/
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
video::ITexture * MapBlockObjectItem::getImage()
|
video::ITexture * MapBlockObjectItem::getImage()
|
||||||
|
@ -35,6 +35,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#define QUANTITY_ITEM_MAX_COUNT 99
|
#define QUANTITY_ITEM_MAX_COUNT 99
|
||||||
|
|
||||||
|
class ServerActiveObject;
|
||||||
|
class ServerEnvironment;
|
||||||
|
|
||||||
class InventoryItem
|
class InventoryItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -54,6 +57,12 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
// Shall return a text to show in the GUI
|
// Shall return a text to show in the GUI
|
||||||
virtual std::string getText() { return ""; }
|
virtual std::string getText() { return ""; }
|
||||||
|
// Creates an object from the item, to be placed in the world.
|
||||||
|
virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Quantity methods
|
||||||
|
*/
|
||||||
|
|
||||||
// Shall return true if the item can be add()ed to the other
|
// Shall return true if the item can be add()ed to the other
|
||||||
virtual bool addableTo(InventoryItem *other)
|
virtual bool addableTo(InventoryItem *other)
|
||||||
@ -61,9 +70,6 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Quantity methods
|
|
||||||
*/
|
|
||||||
u16 getCount()
|
u16 getCount()
|
||||||
{
|
{
|
||||||
return m_count;
|
return m_count;
|
||||||
@ -175,6 +181,7 @@ private:
|
|||||||
u8 m_content;
|
u8 m_content;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//TODO: Remove
|
||||||
class MapBlockObjectItem : public InventoryItem
|
class MapBlockObjectItem : public InventoryItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -262,28 +269,7 @@ public:
|
|||||||
return new CraftItem(m_subname, m_count);
|
return new CraftItem(m_subname, m_count);
|
||||||
}
|
}
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
video::ITexture * getImage()
|
video::ITexture * getImage();
|
||||||
{
|
|
||||||
if(g_texturesource == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
if(m_subname == "Stick")
|
|
||||||
name = "stick.png";
|
|
||||||
else if(m_subname == "lump_of_coal")
|
|
||||||
name = "lump_of_coal.png";
|
|
||||||
else if(m_subname == "lump_of_iron")
|
|
||||||
name = "lump_of_iron.png";
|
|
||||||
else if(m_subname == "steel_ingot")
|
|
||||||
name = "steel_ingot.png";
|
|
||||||
else
|
|
||||||
name = "cloud.png";
|
|
||||||
|
|
||||||
// Get such a texture
|
|
||||||
//return g_irrlicht->getTexture(name);
|
|
||||||
return g_texturesource->getTextureRaw(name);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
std::string getText()
|
std::string getText()
|
||||||
{
|
{
|
||||||
@ -291,6 +277,9 @@ public:
|
|||||||
os<<m_count;
|
os<<m_count;
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
|
||||||
|
|
||||||
virtual bool addableTo(InventoryItem *other)
|
virtual bool addableTo(InventoryItem *other)
|
||||||
{
|
{
|
||||||
if(std::string(other->getName()) != "CraftItem")
|
if(std::string(other->getName()) != "CraftItem")
|
||||||
|
@ -1295,7 +1295,7 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
|
|||||||
if(dummy == false)
|
if(dummy == false)
|
||||||
reallocate();
|
reallocate();
|
||||||
|
|
||||||
m_spawn_timer = -10000;
|
//m_spawn_timer = -10000;
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
m_mesh_expired = false;
|
m_mesh_expired = false;
|
||||||
@ -1688,6 +1688,7 @@ void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
|
|||||||
*/
|
*/
|
||||||
m_objects.step(dtime, server, daynight_ratio);
|
m_objects.step(dtime, server, daynight_ratio);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
Spawn some objects at random.
|
Spawn some objects at random.
|
||||||
|
|
||||||
@ -1724,6 +1725,7 @@ void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
setChangedFlag();
|
setChangedFlag();
|
||||||
}
|
}
|
||||||
|
@ -729,10 +729,11 @@ private:
|
|||||||
// Whether day and night lighting differs
|
// Whether day and night lighting differs
|
||||||
bool m_day_night_differs;
|
bool m_day_night_differs;
|
||||||
|
|
||||||
|
// TODO: Remove this
|
||||||
MapBlockObjectList m_objects;
|
MapBlockObjectList m_objects;
|
||||||
|
|
||||||
// Object spawning stuff
|
// Object spawning stuff
|
||||||
float m_spawn_timer;
|
//float m_spawn_timer;
|
||||||
|
|
||||||
#ifndef SERVER // Only on client
|
#ifndef SERVER // Only on client
|
||||||
/*
|
/*
|
||||||
|
@ -2046,29 +2046,27 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip if object has been removed
|
||||||
|
if(obj->m_removed)
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create the inventory item
|
Create the inventory item
|
||||||
*/
|
*/
|
||||||
InventoryItem *item = NULL;
|
InventoryItem *item = obj->createPickedUpItem();
|
||||||
// If it is an item-object, take the item from it
|
|
||||||
if(obj->getType() == ACTIVEOBJECT_TYPE_ITEM
|
|
||||||
&& obj->m_removed == false)
|
|
||||||
{
|
|
||||||
item = ((ItemSAO*)obj)->createInventoryItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(item)
|
if(item)
|
||||||
{
|
{
|
||||||
// Add to inventory and send inventory
|
// Add to inventory and send inventory
|
||||||
ilist->addItem(item);
|
ilist->addItem(item);
|
||||||
SendInventory(player->peer_id);
|
SendInventory(player->peer_id);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove object from environment
|
// Remove object from environment
|
||||||
obj->m_removed = true;
|
obj->m_removed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(command == TOSERVER_GROUND_ACTION)
|
else if(command == TOSERVER_GROUND_ACTION)
|
||||||
{
|
{
|
||||||
if(datasize < 17)
|
if(datasize < 17)
|
||||||
@ -2448,15 +2446,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
pos.Z += BS*0.2*(float)myrand_range(-1000,1000)/1000.0;
|
pos.Z += BS*0.2*(float)myrand_range(-1000,1000)/1000.0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create an ItemSAO
|
Create the object
|
||||||
*/
|
*/
|
||||||
// Get item string
|
ServerActiveObject *obj = item->createSAO(&m_env, 0, pos);
|
||||||
std::ostringstream os(std::ios_base::binary);
|
|
||||||
item->serialize(os);
|
|
||||||
dout_server<<"Item string is \""<<os.str()<<"\""<<std::endl;
|
|
||||||
// Create object
|
|
||||||
ServerActiveObject *obj = new ItemSAO
|
|
||||||
(&m_env, 0, pos, os.str());
|
|
||||||
|
|
||||||
if(obj == NULL)
|
if(obj == NULL)
|
||||||
{
|
{
|
||||||
@ -2471,6 +2463,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
|
|
||||||
dout_server<<"Placed object"<<std::endl;
|
dout_server<<"Placed object"<<std::endl;
|
||||||
|
|
||||||
|
// If item has count<=1, delete it
|
||||||
|
if(item->getCount() <= 1)
|
||||||
|
{
|
||||||
InventoryList *ilist = player->inventory.getList("main");
|
InventoryList *ilist = player->inventory.getList("main");
|
||||||
if(g_settings.getBool("creative_mode") == false && ilist)
|
if(g_settings.getBool("creative_mode") == false && ilist)
|
||||||
{
|
{
|
||||||
@ -2480,6 +2475,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
SendInventory(peer_id);
|
SendInventory(peer_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Else decrement it
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item->remove(1);
|
||||||
|
// Send inventory
|
||||||
|
SendInventory(peer_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // action == 1
|
} // action == 1
|
||||||
|
@ -91,7 +91,8 @@ ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
|||||||
return new TestSAO(env, id, pos);
|
return new TestSAO(env, id, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
|
void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||||
|
bool send_recommended)
|
||||||
{
|
{
|
||||||
m_age += dtime;
|
m_age += dtime;
|
||||||
if(m_age > 10)
|
if(m_age > 10)
|
||||||
@ -104,6 +105,9 @@ void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
|
|||||||
if(m_base_position.Y > 8*BS)
|
if(m_base_position.Y > 8*BS)
|
||||||
m_base_position.Y = 2*BS;
|
m_base_position.Y = 2*BS;
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
m_timer1 -= dtime;
|
m_timer1 -= dtime;
|
||||||
if(m_timer1 < 0.0)
|
if(m_timer1 < 0.0)
|
||||||
{
|
{
|
||||||
@ -137,7 +141,8 @@ ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
|
|||||||
const std::string inventorystring):
|
const std::string inventorystring):
|
||||||
ServerActiveObject(env, id, pos),
|
ServerActiveObject(env, id, pos),
|
||||||
m_inventorystring(inventorystring),
|
m_inventorystring(inventorystring),
|
||||||
m_speed_f(0,0,0)
|
m_speed_f(0,0,0),
|
||||||
|
m_last_sent_position(0,0,0)
|
||||||
{
|
{
|
||||||
dstream<<"Server: ItemSAO created with inventorystring=\""
|
dstream<<"Server: ItemSAO created with inventorystring=\""
|
||||||
<<m_inventorystring<<"\""<<std::endl;
|
<<m_inventorystring<<"\""<<std::endl;
|
||||||
@ -161,7 +166,8 @@ ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
|||||||
return new ItemSAO(env, id, pos, inventorystring);
|
return new ItemSAO(env, id, pos, inventorystring);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
|
void ItemSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||||
|
bool send_recommended)
|
||||||
{
|
{
|
||||||
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
|
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
|
||||||
collisionMoveResult moveresult;
|
collisionMoveResult moveresult;
|
||||||
@ -177,9 +183,13 @@ void ItemSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
|
|||||||
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
||||||
box, dtime, pos_f, m_speed_f);
|
box, dtime, pos_f, m_speed_f);
|
||||||
|
|
||||||
if(pos_f.getDistanceFrom(pos_f_old) > 0.01*BS)
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
{
|
{
|
||||||
setBasePosition(pos_f);
|
setBasePosition(pos_f);
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
std::ostringstream os(std::ios::binary);
|
std::ostringstream os(std::ios::binary);
|
||||||
char buf[6];
|
char buf[6];
|
||||||
@ -250,4 +260,180 @@ InventoryItem * ItemSAO::createInventoryItem()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
RatSAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0));
|
||||||
|
|
||||||
|
RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
|
||||||
|
ServerActiveObject(env, id, pos),
|
||||||
|
m_speed_f(0,0,0)
|
||||||
|
{
|
||||||
|
dstream<<"Server: RatSAO created"<<std::endl;
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_oldpos = v3f(0,0,0);
|
||||||
|
m_last_sent_position = v3f(0,0,0);
|
||||||
|
m_yaw = 0;
|
||||||
|
m_counter1 = 0;
|
||||||
|
m_counter2 = 0;
|
||||||
|
m_age = 0;
|
||||||
|
m_touching_ground = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
char buf[1];
|
||||||
|
// read version
|
||||||
|
is.read(buf, 1);
|
||||||
|
u8 version = buf[0];
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
return new RatSAO(env, id, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RatSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||||
|
bool send_recommended)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The AI
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_age += dtime;
|
||||||
|
if(m_age > 60)
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply gravity
|
||||||
|
m_speed_f.Y -= dtime*9.81*BS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move around if some player is close
|
||||||
|
*/
|
||||||
|
bool player_is_close = false;
|
||||||
|
// Check connected players
|
||||||
|
core::list<Player*> players = m_env->getPlayers(true);
|
||||||
|
core::list<Player*>::Iterator i;
|
||||||
|
for(i = players.begin();
|
||||||
|
i != players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
|
||||||
|
{
|
||||||
|
player_is_close = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(player_is_close == false)
|
||||||
|
{
|
||||||
|
m_speed_f.X = 0;
|
||||||
|
m_speed_f.Z = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Move around
|
||||||
|
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||||
|
f32 speed = 2*BS;
|
||||||
|
m_speed_f.X = speed * dir.X;
|
||||||
|
m_speed_f.Z = speed * dir.Z;
|
||||||
|
|
||||||
|
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
|
||||||
|
< dtime*speed/2)
|
||||||
|
{
|
||||||
|
m_counter1 -= dtime;
|
||||||
|
if(m_counter1 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter1 += 1.0;
|
||||||
|
m_speed_f.Y = 5.0*BS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
m_counter2 -= dtime;
|
||||||
|
if(m_counter2 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter2 += (float)(myrand()%100)/100*3.0;
|
||||||
|
m_yaw += ((float)(myrand()%200)-100)/100*180;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_oldpos = m_base_position;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move it, with collision detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
// Maximum movement without glitches
|
||||||
|
f32 pos_max_d = BS*0.25;
|
||||||
|
// Limit speed
|
||||||
|
if(m_speed_f.getLength()*dtime > pos_max_d)
|
||||||
|
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||||
|
v3f pos_f = getBasePosition();
|
||||||
|
v3f pos_f_old = pos_f;
|
||||||
|
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
||||||
|
box, dtime, pos_f, m_speed_f);
|
||||||
|
m_touching_ground = moveresult.touching_ground;
|
||||||
|
|
||||||
|
setBasePosition(pos_f);
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
// yaw
|
||||||
|
writeF1000(os, m_yaw);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
messages.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RatSAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RatSAO::getStaticData()
|
||||||
|
{
|
||||||
|
dstream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryItem* RatSAO::createPickedUpItem()
|
||||||
|
{
|
||||||
|
std::istringstream is("CraftItem rat 1", std::ios_base::binary);
|
||||||
|
InventoryItem *item = InventoryItem::deSerialize(is);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,6 +40,38 @@ Some planning
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
class IntervalLimiter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IntervalLimiter():
|
||||||
|
m_accumulator(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
dtime: time from last call to this method
|
||||||
|
wanted_interval: interval wanted
|
||||||
|
return value:
|
||||||
|
true: action should be skipped
|
||||||
|
false: action should be done and dtime has been set
|
||||||
|
*/
|
||||||
|
bool step(float &dtime, float wanted_interval)
|
||||||
|
{
|
||||||
|
accumulator += dtime;
|
||||||
|
if(accumulator < wanted_interval)
|
||||||
|
{
|
||||||
|
dtime = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
accumulator -= wanted-interval;
|
||||||
|
dtime = wanted_interval;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
float m_accumulator;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class ServerEnvironment;
|
class ServerEnvironment;
|
||||||
class InventoryItem;
|
class InventoryItem;
|
||||||
|
|
||||||
@ -67,8 +99,15 @@ public:
|
|||||||
/*
|
/*
|
||||||
Step object in time.
|
Step object in time.
|
||||||
Messages added to messages are sent to client over network.
|
Messages added to messages are sent to client over network.
|
||||||
|
|
||||||
|
send_recommended:
|
||||||
|
True at around 5 times a second, same for all objects.
|
||||||
|
This is used to let objects send most of the data at the
|
||||||
|
same time so that the data can be combined in a single
|
||||||
|
packet.
|
||||||
*/
|
*/
|
||||||
virtual void step(float dtime, Queue<ActiveObjectMessage> &messages){}
|
virtual void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||||
|
bool send_recommended){}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The return value of this is passed to the client-side object
|
The return value of this is passed to the client-side object
|
||||||
@ -83,6 +122,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual std::string getStaticData(){return "";}
|
virtual std::string getStaticData(){return "";}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Item that the player gets when this object is picked up.
|
||||||
|
If NULL, object cannot be picked up.
|
||||||
|
*/
|
||||||
|
virtual InventoryItem* createPickedUpItem(){return NULL;}
|
||||||
|
|
||||||
// Number of players which know about this object
|
// Number of players which know about this object
|
||||||
u16 m_known_by_count;
|
u16 m_known_by_count;
|
||||||
/*
|
/*
|
||||||
@ -129,7 +174,8 @@ public:
|
|||||||
{return ACTIVEOBJECT_TYPE_TEST;}
|
{return ACTIVEOBJECT_TYPE_TEST;}
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
const std::string &data);
|
const std::string &data);
|
||||||
void step(float dtime, Queue<ActiveObjectMessage> &messages);
|
void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||||
|
bool send_recommended);
|
||||||
private:
|
private:
|
||||||
float m_timer1;
|
float m_timer1;
|
||||||
float m_age;
|
float m_age;
|
||||||
@ -144,13 +190,40 @@ public:
|
|||||||
{return ACTIVEOBJECT_TYPE_ITEM;}
|
{return ACTIVEOBJECT_TYPE_ITEM;}
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
const std::string &data);
|
const std::string &data);
|
||||||
void step(float dtime, Queue<ActiveObjectMessage> &messages);
|
void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||||
|
bool send_recommended);
|
||||||
std::string getClientInitializationData();
|
std::string getClientInitializationData();
|
||||||
std::string getStaticData();
|
std::string getStaticData();
|
||||||
InventoryItem* createInventoryItem();
|
InventoryItem* createInventoryItem();
|
||||||
|
InventoryItem* createPickedUpItem(){return createInventoryItem();}
|
||||||
private:
|
private:
|
||||||
std::string m_inventorystring;
|
std::string m_inventorystring;
|
||||||
v3f m_speed_f;
|
v3f m_speed_f;
|
||||||
|
v3f m_last_sent_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RatSAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RatSAO(ServerEnvironment *env, u16 id, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_RAT;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||||
|
bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
InventoryItem* createPickedUpItem();
|
||||||
|
private:
|
||||||
|
v3f m_speed_f;
|
||||||
|
v3f m_oldpos;
|
||||||
|
v3f m_last_sent_position;
|
||||||
|
float m_yaw;
|
||||||
|
float m_counter1;
|
||||||
|
float m_counter2;
|
||||||
|
float m_age;
|
||||||
|
bool m_touching_ground;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -95,8 +95,6 @@ inline u8 readU8(u8 *data)
|
|||||||
return (data[0]<<0);
|
return (data[0]<<0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signed variants of the above
|
|
||||||
|
|
||||||
inline void writeS32(u8 *data, s32 i){
|
inline void writeS32(u8 *data, s32 i){
|
||||||
writeU32(data, (u32)i);
|
writeU32(data, (u32)i);
|
||||||
}
|
}
|
||||||
@ -104,6 +102,13 @@ inline s32 readS32(u8 *data){
|
|||||||
return (s32)readU32(data);
|
return (s32)readU32(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void writeF1000(u8 *data, f32 i){
|
||||||
|
writeS32(data, i*1000);
|
||||||
|
}
|
||||||
|
inline f32 readF1000(u8 *data){
|
||||||
|
return (f32)readS32(data)/1000.;
|
||||||
|
}
|
||||||
|
|
||||||
inline void writeS16(u8 *data, s16 i){
|
inline void writeS16(u8 *data, s16 i){
|
||||||
writeU16(data, (u16)i);
|
writeU16(data, (u16)i);
|
||||||
}
|
}
|
||||||
@ -117,7 +122,6 @@ inline void writeV3S32(u8 *data, v3s32 p)
|
|||||||
writeS32(&data[4], p.Y);
|
writeS32(&data[4], p.Y);
|
||||||
writeS32(&data[8], p.Z);
|
writeS32(&data[8], p.Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline v3s32 readV3S32(u8 *data)
|
inline v3s32 readV3S32(u8 *data)
|
||||||
{
|
{
|
||||||
v3s32 p;
|
v3s32 p;
|
||||||
@ -127,6 +131,21 @@ inline v3s32 readV3S32(u8 *data)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void writeV3F1000(u8 *data, v3f p)
|
||||||
|
{
|
||||||
|
writeF1000(&data[0], p.X);
|
||||||
|
writeF1000(&data[4], p.Y);
|
||||||
|
writeF1000(&data[8], p.Z);
|
||||||
|
}
|
||||||
|
inline v3f readV3F1000(u8 *data)
|
||||||
|
{
|
||||||
|
v3f p;
|
||||||
|
p.X = (float)readF1000(&data[0]);
|
||||||
|
p.Y = (float)readF1000(&data[4]);
|
||||||
|
p.Z = (float)readF1000(&data[8]);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
inline void writeV2S16(u8 *data, v2s16 p)
|
inline void writeV2S16(u8 *data, v2s16 p)
|
||||||
{
|
{
|
||||||
writeS16(&data[0], p.X);
|
writeS16(&data[0], p.X);
|
||||||
@ -171,6 +190,62 @@ inline v3s16 readV3S16(u8 *data)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The above stuff directly interfaced to iostream
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline void writeU8(std::ostream &os, u8 p)
|
||||||
|
{
|
||||||
|
char buf[1];
|
||||||
|
writeU8((u8*)buf, p);
|
||||||
|
os.write(buf, 1);
|
||||||
|
}
|
||||||
|
inline u8 readU8(std::istream &is)
|
||||||
|
{
|
||||||
|
char buf[1];
|
||||||
|
is.read(buf, 1);
|
||||||
|
return readU8((u8*)buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void writeU16(std::ostream &os, u16 p)
|
||||||
|
{
|
||||||
|
char buf[2];
|
||||||
|
writeU16((u8*)buf, p);
|
||||||
|
os.write(buf, 2);
|
||||||
|
}
|
||||||
|
inline u16 readU16(std::istream &is)
|
||||||
|
{
|
||||||
|
char buf[12];
|
||||||
|
is.read(buf, 12);
|
||||||
|
return readU16((u8*)buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void writeF1000(std::ostream &os, f32 p)
|
||||||
|
{
|
||||||
|
char buf[2];
|
||||||
|
writeF1000((u8*)buf, p);
|
||||||
|
os.write(buf, 2);
|
||||||
|
}
|
||||||
|
inline f32 readF1000(std::istream &is)
|
||||||
|
{
|
||||||
|
char buf[12];
|
||||||
|
is.read(buf, 12);
|
||||||
|
return readF1000((u8*)buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void writeV3F1000(std::ostream &os, v3f p)
|
||||||
|
{
|
||||||
|
char buf[12];
|
||||||
|
writeV3F1000((u8*)buf, p);
|
||||||
|
os.write(buf, 12);
|
||||||
|
}
|
||||||
|
inline v3f readV3F1000(std::istream &is)
|
||||||
|
{
|
||||||
|
char buf[12];
|
||||||
|
is.read(buf, 12);
|
||||||
|
return readV3F1000((u8*)buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
None of these are used at the moment
|
None of these are used at the moment
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user