Compare commits
21 Commits
master
...
sapier-201
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52996cd5eb | ||
|
|
61ae136431 | ||
|
|
30f16ded7e | ||
|
|
d9ffd30445 | ||
|
|
c525330153 | ||
|
|
435ea846db | ||
|
|
34eabf4df0 | ||
|
|
413afa77d0 | ||
|
|
ffe6025f61 | ||
|
|
f34f75291b | ||
|
|
8929a47296 | ||
|
|
0947644729 | ||
|
|
77df09540c | ||
|
|
6bf4931fc2 | ||
|
|
3454e67793 | ||
|
|
0c78767754 | ||
|
|
f0679969b2 | ||
|
|
285f5a0259 | ||
|
|
71186974fa | ||
|
|
525bc8855f | ||
|
|
de166e75a1 |
@@ -1302,7 +1302,7 @@ minetest.register_node("default:rail", {
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
--fixed = <default>
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
material = minetest.digprop_dirtlike(0.75),
|
||||
})
|
||||
|
||||
1
data/mods/stairs/depends.txt
Normal file
1
data/mods/stairs/depends.txt
Normal file
@@ -0,0 +1 @@
|
||||
default
|
||||
93
data/mods/stairs/init.lua
Normal file
93
data/mods/stairs/init.lua
Normal file
@@ -0,0 +1,93 @@
|
||||
stairs = {}
|
||||
|
||||
-- Node will be called stairs:stair_<subname>
|
||||
function stairs.register_stair(subname, recipeitem, material, images, description)
|
||||
minetest.register_node("stairs:stair_" .. subname, {
|
||||
description = description,
|
||||
drawtype = "nodebox",
|
||||
tile_images = images,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = true,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
{-0.5, 0, 0, 0.5, 0.5, 0.5},
|
||||
},
|
||||
},
|
||||
material = material,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'stairs:stair_' .. subname .. ' 4',
|
||||
recipe = {
|
||||
{recipeitem, "", ""},
|
||||
{recipeitem, recipeitem, ""},
|
||||
{recipeitem, recipeitem, recipeitem},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
-- Node will be called stairs:slab_<subname>
|
||||
function stairs.register_slab(subname, recipeitem, material, images, description)
|
||||
minetest.register_node("stairs:slab_" .. subname, {
|
||||
description = description,
|
||||
drawtype = "nodebox",
|
||||
tile_images = images,
|
||||
paramtype = "light",
|
||||
is_ground_content = true,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
},
|
||||
material = material,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'stairs:slab_' .. subname .. ' 3',
|
||||
recipe = {
|
||||
{recipeitem, recipeitem, recipeitem},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
-- Nodes will be called stairs:{stair,slab}_<subname>
|
||||
function stairs.register_stair_and_slab(subname, recipeitem, material, images, desc_stair, desc_slab)
|
||||
stairs.register_stair(subname, recipeitem, material, images, desc_stair)
|
||||
stairs.register_slab(subname, recipeitem, material, images, desc_slab)
|
||||
end
|
||||
|
||||
stairs.register_stair_and_slab("wood", "default:wood",
|
||||
minetest.digprop_woodlike(0.75),
|
||||
{"default_wood.png"},
|
||||
"Wooden stair",
|
||||
"Wooden slab")
|
||||
|
||||
stairs.register_stair_and_slab("stone", "default:stone",
|
||||
minetest.digprop_stonelike(0.75),
|
||||
{"default_stone.png"},
|
||||
"Stone stair",
|
||||
"Stone slab")
|
||||
|
||||
stairs.register_stair_and_slab("cobble", "default:cobble",
|
||||
minetest.digprop_stonelike(0.75),
|
||||
{"default_cobble.png"},
|
||||
"Cobble stair",
|
||||
"Cobble slab")
|
||||
|
||||
stairs.register_stair_and_slab("brick", "default:brick",
|
||||
minetest.digprop_stonelike(0.75),
|
||||
{"default_brick.png"},
|
||||
"Brick stair",
|
||||
"Brick slab")
|
||||
|
||||
stairs.register_stair_and_slab("sandstone", "default:sandstone",
|
||||
minetest.digprop_stonelike(0.75),
|
||||
{"default_sandstone.png"},
|
||||
"Sandstone stair",
|
||||
"Sandstone slab")
|
||||
@@ -114,6 +114,7 @@ set(common_SRCS
|
||||
collision.cpp
|
||||
nodemetadata.cpp
|
||||
serverobject.cpp
|
||||
serverlinkableobject.cpp
|
||||
noise.cpp
|
||||
porting.cpp
|
||||
materials.cpp
|
||||
@@ -166,6 +167,7 @@ set(minetest_SRCS
|
||||
camera.cpp
|
||||
clouds.cpp
|
||||
clientobject.cpp
|
||||
clientlinkableobject.cpp
|
||||
guiMainMenu.cpp
|
||||
guiKeyChangeMenu.cpp
|
||||
guiMessageMenu.cpp
|
||||
@@ -281,7 +283,7 @@ else()
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall ${WARNING_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall ${WARNING_FLAGS}")
|
||||
|
||||
if(USE_GPROF)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
|
||||
|
||||
123
src/clientlinkableobject.cpp
Normal file
123
src/clientlinkableobject.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2012 sapier sapier at gmx dot net
|
||||
|
||||
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 "clientlinkableobject.h"
|
||||
|
||||
ClientLinkableObject::ClientLinkableObject() {
|
||||
|
||||
this->m_Parent = NULL;
|
||||
}
|
||||
|
||||
ClientLinkableObject::~ClientLinkableObject() {
|
||||
if (this->isLinked())
|
||||
this->unlink(this);
|
||||
}
|
||||
|
||||
|
||||
void ClientLinkableObject::link(ClientLinkableObject* entity) {
|
||||
//TODO check if entity is already linkt (shouldn't be the case but just to be sure)
|
||||
this->m_LinkedObjects.push_back(entity);
|
||||
}
|
||||
|
||||
void ClientLinkableObject::unlink(ClientLinkableObject* entity) {
|
||||
this->m_LinkedObjects.remove(entity);
|
||||
}
|
||||
|
||||
|
||||
void ClientLinkableObject::stepLinkedObjects(v3f pos,float dtime) {
|
||||
for(std::list<ClientLinkableObject*>::iterator i = this->m_LinkedObjects.begin();
|
||||
i != this->m_LinkedObjects.end(); i++) {
|
||||
(*i)->setPosition(pos,dtime);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientLinkableObject::handleLinkUnlinkMessages(u8 cmd,std::istringstream* is,ClientEnvironment *m_env) {
|
||||
if(cmd == 3) // Link entity
|
||||
{
|
||||
//Object to link entity to
|
||||
u16 object_id = readU16(*is);
|
||||
//offset against linked object
|
||||
v3f offset = readV3F1000(*is);
|
||||
|
||||
ClientActiveObject* parent_cao = m_env->getActiveObject(object_id);
|
||||
|
||||
ClientLinkableObject* parent = dynamic_cast<ClientLinkableObject*>(parent_cao);
|
||||
|
||||
if (parent != NULL) {
|
||||
this->linkEntity(offset,parent);
|
||||
}
|
||||
else {
|
||||
errorstream << "Invalid object to link to!" << std::endl;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
else if(cmd == 4) // UnLink entity
|
||||
{
|
||||
if (this->m_Parent == NULL) {
|
||||
errorstream << "Unlinking object not linked!" << std::endl;
|
||||
}
|
||||
|
||||
this->unlinkEntity();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ClientLinkableObject::linkEntity(v3f offset, ClientLinkableObject* parent) {
|
||||
//already linked unlink first
|
||||
if (this->m_Parent != NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO add linkchain support
|
||||
if (this->m_LinkedObjects.size() > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parent->link(this);
|
||||
updateLinkState(true);
|
||||
this->m_linkOffset = offset;
|
||||
this->m_Parent = parent;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ClientLinkableObject::unlinkEntity() {
|
||||
if (this->m_Parent != NULL) {
|
||||
|
||||
updateLinkState(false);
|
||||
this->m_Parent->unlink(this);
|
||||
this->m_Parent = NULL;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClientLinkableObject::isLinked() {
|
||||
if (this->m_Parent != NULL)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
65
src/clientlinkableobject.h
Normal file
65
src/clientlinkableobject.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2012 sapier sapier at gmx dot net
|
||||
|
||||
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 CLIENTLINKABLEOBJECT_H_
|
||||
#define CLIENTLINKABLEOBJECT_H_
|
||||
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <irrlichttypes.h>
|
||||
#include "clientobject.h"
|
||||
#include "environment.h"
|
||||
#include "content_object.h"
|
||||
#include "utility.h"
|
||||
#include "log.h"
|
||||
|
||||
class ClientLinkableObject {
|
||||
public:
|
||||
ClientLinkableObject();
|
||||
~ClientLinkableObject();
|
||||
//internal communication between entitys NOT to be used by user
|
||||
void link(ClientLinkableObject* entity);
|
||||
void unlink(ClientLinkableObject* entity);
|
||||
|
||||
virtual void setPosition(v3f toset, float dtime) = 0;
|
||||
virtual void updateLinkState(bool value) = 0;
|
||||
|
||||
protected:
|
||||
void stepLinkedObjects(v3f pos,float dtime);
|
||||
|
||||
bool handleLinkUnlinkMessages(u8 cmd,std::istringstream* is,ClientEnvironment *m_env);
|
||||
|
||||
|
||||
//user driven functions (exported by lua)
|
||||
bool linkEntity(v3f offset, ClientLinkableObject* parent);
|
||||
bool unlinkEntity();
|
||||
|
||||
bool isLinked();
|
||||
v3f m_linkOffset;
|
||||
|
||||
|
||||
private:
|
||||
ClientLinkableObject* m_Parent;
|
||||
|
||||
std::list<ClientLinkableObject*> m_LinkedObjects;
|
||||
};
|
||||
|
||||
|
||||
#endif /* CLIENTLINKABLEOBJECT_H_ */
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2012 sapier
|
||||
|
||||
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
|
||||
@@ -16,9 +16,21 @@ 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 __COLLIDABLEOBJECT_H__
|
||||
#define __COLLIDABLEOBJECT_H__
|
||||
|
||||
#ifndef CONTENT_CAO_HEADER
|
||||
#define CONTENT_CAO_HEADER
|
||||
#include <irrlichttypes.h>
|
||||
|
||||
#endif
|
||||
class CollidableObject {
|
||||
public:
|
||||
virtual aabb3f* getCollisionBox() = 0;
|
||||
|
||||
inline float getFlexibility() { return m_Flexibility; }
|
||||
inline int getWeight() { return m_Weight; }
|
||||
protected:
|
||||
int m_Weight;
|
||||
float m_Flexibility;
|
||||
aabb3f m_collisionbox;
|
||||
};
|
||||
|
||||
#endif //__COLLIDABLEOBJECT_H__
|
||||
@@ -18,32 +18,276 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "collision.h"
|
||||
#include "collidableobject.h"
|
||||
#include "mapblock.h"
|
||||
#include "map.h"
|
||||
#include "nodedef.h"
|
||||
#include "gamedef.h"
|
||||
#include "environment.h"
|
||||
#include "log.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f)
|
||||
// Helper function:
|
||||
// Checks for collision of a moving aabbox with a static aabbox
|
||||
// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
|
||||
// The time after which the collision occurs is stored in dtime.
|
||||
int axisAlignedCollision(
|
||||
const aabb3f &staticbox, const aabb3f &movingbox,
|
||||
const v3f &speed, f32 d, f32 &dtime)
|
||||
{
|
||||
//TimeTaker tt("axisAlignedCollision");
|
||||
|
||||
f32 xsize = (staticbox.MaxEdge.X - staticbox.MinEdge.X);
|
||||
f32 ysize = (staticbox.MaxEdge.Y - staticbox.MinEdge.Y);
|
||||
f32 zsize = (staticbox.MaxEdge.Z - staticbox.MinEdge.Z);
|
||||
|
||||
aabb3f relbox(
|
||||
movingbox.MinEdge.X - staticbox.MinEdge.X,
|
||||
movingbox.MinEdge.Y - staticbox.MinEdge.Y,
|
||||
movingbox.MinEdge.Z - staticbox.MinEdge.Z,
|
||||
movingbox.MaxEdge.X - staticbox.MinEdge.X,
|
||||
movingbox.MaxEdge.Y - staticbox.MinEdge.Y,
|
||||
movingbox.MaxEdge.Z - staticbox.MinEdge.Z
|
||||
);
|
||||
|
||||
if(speed.X > 0) // Check for collision with X- plane
|
||||
{
|
||||
if(relbox.MaxEdge.X <= d)
|
||||
{
|
||||
dtime = - relbox.MaxEdge.X / speed.X;
|
||||
if((relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 0;
|
||||
}
|
||||
else if(relbox.MinEdge.X > xsize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(speed.X < 0) // Check for collision with X+ plane
|
||||
{
|
||||
if(relbox.MinEdge.X >= xsize - d)
|
||||
{
|
||||
dtime = (xsize - relbox.MinEdge.X) / speed.X;
|
||||
if((relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 0;
|
||||
}
|
||||
else if(relbox.MaxEdge.X < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// NO else if here
|
||||
|
||||
if(speed.Y > 0) // Check for collision with Y- plane
|
||||
{
|
||||
if(relbox.MaxEdge.Y <= d)
|
||||
{
|
||||
dtime = - relbox.MaxEdge.Y / speed.Y;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 1;
|
||||
}
|
||||
else if(relbox.MinEdge.Y > ysize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(speed.Y < 0) // Check for collision with Y+ plane
|
||||
{
|
||||
if(relbox.MinEdge.Y >= ysize - d)
|
||||
{
|
||||
dtime = (ysize - relbox.MinEdge.Y) / speed.Y;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Z + speed.Z * dtime < zsize) &&
|
||||
(relbox.MaxEdge.Z + speed.Z * dtime > 0))
|
||||
return 1;
|
||||
}
|
||||
else if(relbox.MaxEdge.Y < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// NO else if here
|
||||
|
||||
if(speed.Z > 0) // Check for collision with Z- plane
|
||||
{
|
||||
if(relbox.MaxEdge.Z <= d)
|
||||
{
|
||||
dtime = - relbox.MaxEdge.Z / speed.Z;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0))
|
||||
return 2;
|
||||
}
|
||||
//else if(relbox.MinEdge.Z > zsize)
|
||||
//{
|
||||
// return -1;
|
||||
//}
|
||||
}
|
||||
else if(speed.Z < 0) // Check for collision with Z+ plane
|
||||
{
|
||||
if(relbox.MinEdge.Z >= zsize - d)
|
||||
{
|
||||
dtime = (zsize - relbox.MinEdge.Z) / speed.Z;
|
||||
if((relbox.MinEdge.X + speed.X * dtime < xsize) &&
|
||||
(relbox.MaxEdge.X + speed.X * dtime > 0) &&
|
||||
(relbox.MinEdge.Y + speed.Y * dtime < ysize) &&
|
||||
(relbox.MaxEdge.Y + speed.Y * dtime > 0))
|
||||
return 2;
|
||||
}
|
||||
//else if(relbox.MaxEdge.Z < 0)
|
||||
//{
|
||||
// return -1;
|
||||
//}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Helper function:
|
||||
// Checks if moving the movingbox up by the given distance would hit a ceiling.
|
||||
bool wouldCollideWithCeiling(
|
||||
const std::vector<aabb3f> &staticboxes,
|
||||
const aabb3f &movingbox,
|
||||
f32 y_increase, f32 d)
|
||||
{
|
||||
//TimeTaker tt("wouldCollideWithCeiling");
|
||||
|
||||
assert(y_increase >= 0);
|
||||
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = staticboxes.begin();
|
||||
i != staticboxes.end(); i++)
|
||||
{
|
||||
const aabb3f& staticbox = *i;
|
||||
if((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) &&
|
||||
(movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) &&
|
||||
(movingbox.MinEdge.X < staticbox.MaxEdge.X) &&
|
||||
(movingbox.MaxEdge.X > staticbox.MinEdge.X) &&
|
||||
(movingbox.MinEdge.Z < staticbox.MaxEdge.Z) &&
|
||||
(movingbox.MaxEdge.Z > staticbox.MinEdge.Z))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
v3f oldpos_f = pos_f;
|
||||
v3s16 oldpos_i = floatToInt(oldpos_f, BS);
|
||||
/*
|
||||
Calculate new velocity
|
||||
*/
|
||||
speed_f += accel_f * dtime;
|
||||
|
||||
/*
|
||||
Calculate new position
|
||||
Collect node boxes in movement range
|
||||
*/
|
||||
pos_f += speed_f * dtime;
|
||||
std::vector<aabb3f> cboxes;
|
||||
std::vector<bool> is_unloaded;
|
||||
std::vector<bool> is_step_up;
|
||||
{
|
||||
TimeTaker tt2("collisionMoveSimple collect boxes");
|
||||
|
||||
v3s16 oldpos_i = floatToInt(pos_f, BS);
|
||||
v3s16 newpos_i = floatToInt(pos_f + speed_f * dtime, BS);
|
||||
s16 min_x = MYMIN(oldpos_i.X, newpos_i.X) + (box_0.MinEdge.X / BS) - 1;
|
||||
s16 min_y = MYMIN(oldpos_i.Y, newpos_i.Y) + (box_0.MinEdge.Y / BS) - 1;
|
||||
s16 min_z = MYMIN(oldpos_i.Z, newpos_i.Z) + (box_0.MinEdge.Z / BS) - 1;
|
||||
s16 max_x = MYMAX(oldpos_i.X, newpos_i.X) + (box_0.MaxEdge.X / BS) + 1;
|
||||
s16 max_y = MYMAX(oldpos_i.Y, newpos_i.Y) + (box_0.MaxEdge.Y / BS) + 1;
|
||||
s16 max_z = MYMAX(oldpos_i.Z, newpos_i.Z) + (box_0.MaxEdge.Z / BS) + 1;
|
||||
|
||||
for(s16 x = min_x; x <= max_x; x++)
|
||||
for(s16 y = min_y; y <= max_y; y++)
|
||||
for(s16 z = min_z; z <= max_z; z++)
|
||||
{
|
||||
try{
|
||||
// Object collides into walkable nodes
|
||||
MapNode n = map->getNode(v3s16(x,y,z));
|
||||
if(gamedef->getNodeDefManager()->get(n).walkable == false)
|
||||
continue;
|
||||
|
||||
std::vector<aabb3f> nodeboxes = n.getNodeBoxes(gamedef->ndef());
|
||||
for(std::vector<aabb3f>::iterator
|
||||
i = nodeboxes.begin();
|
||||
i != nodeboxes.end(); i++)
|
||||
{
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += v3f(x, y, z)*BS;
|
||||
box.MaxEdge += v3f(x, y, z)*BS;
|
||||
cboxes.push_back(box);
|
||||
is_unloaded.push_back(false);
|
||||
is_step_up.push_back(false);
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
// Collide with unloaded nodes
|
||||
aabb3f box = getNodeBox(v3s16(x,y,z), BS);
|
||||
cboxes.push_back(box);
|
||||
is_unloaded.push_back(true);
|
||||
is_step_up.push_back(false);
|
||||
}
|
||||
}
|
||||
} // tt2
|
||||
|
||||
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++)
|
||||
{
|
||||
CollidableObject* object = dynamic_cast<CollidableObject*>(*iter);
|
||||
|
||||
if (object != NULL)
|
||||
{
|
||||
aabb3f* object_collisionbox = object->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
|
||||
*/
|
||||
|
||||
// position in nodes
|
||||
v3s16 pos_i = floatToInt(pos_f, BS);
|
||||
|
||||
|
||||
/*
|
||||
Collision uncertainty radius
|
||||
Make it a bit larger than the maximum distance of movement
|
||||
@@ -54,49 +298,129 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
|
||||
// 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
|
||||
*/
|
||||
s16 min_x = (box_0.MinEdge.X / BS) - 2;
|
||||
s16 min_y = (box_0.MinEdge.Y / BS) - 2;
|
||||
s16 min_z = (box_0.MinEdge.Z / BS) - 2;
|
||||
s16 max_x = (box_0.MaxEdge.X / BS) + 1;
|
||||
s16 max_y = (box_0.MaxEdge.Y / BS) + 1;
|
||||
s16 max_z = (box_0.MaxEdge.Z / BS) + 1;
|
||||
for(s16 y = oldpos_i.Y + min_y; y <= oldpos_i.Y + max_y; y++)
|
||||
for(s16 z = oldpos_i.Z + min_z; z <= oldpos_i.Z + max_z; z++)
|
||||
for(s16 x = oldpos_i.X + min_x; x <= oldpos_i.X + max_x; x++)
|
||||
int loopcount = 0;
|
||||
|
||||
while(dtime > BS*1e-10)
|
||||
{
|
||||
try{
|
||||
// Object collides into walkable nodes
|
||||
MapNode n = map->getNode(v3s16(x,y,z));
|
||||
if(gamedef->getNodeDefManager()->get(n).walkable == false)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
TimeTaker tt3("collisionMoveSimple dtime loop");
|
||||
|
||||
// Avoid infinite loop
|
||||
loopcount++;
|
||||
if(loopcount >= 100)
|
||||
{
|
||||
// Doing nothing here will block the object from
|
||||
// walking over map borders
|
||||
infostream<<"collisionMoveSimple: WARNING: Loop count exceeded, "
|
||||
"aborting to avoid infiniite loop"<<std::endl;
|
||||
dtime = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||
|
||||
aabb3f movingbox = box_0;
|
||||
movingbox.MinEdge += pos_f;
|
||||
movingbox.MaxEdge += pos_f;
|
||||
|
||||
int nearest_collided = -1;
|
||||
f32 nearest_dtime = dtime;
|
||||
u32 nearest_boxindex = -1;
|
||||
|
||||
/*
|
||||
Go through every nodebox, find nearest collision
|
||||
*/
|
||||
for(u32 boxindex = 0; boxindex < cboxes.size(); boxindex++)
|
||||
{
|
||||
// Ignore if already stepped up this nodebox.
|
||||
if(is_step_up[boxindex])
|
||||
continue;
|
||||
|
||||
// Find nearest collision of the two boxes (raytracing-like)
|
||||
f32 dtime_tmp;
|
||||
int collided = axisAlignedCollision(
|
||||
cboxes[boxindex], movingbox, speed_f, d, dtime_tmp);
|
||||
|
||||
if(collided == -1 || dtime_tmp >= nearest_dtime)
|
||||
continue;
|
||||
|
||||
nearest_dtime = dtime_tmp;
|
||||
nearest_collided = collided;
|
||||
nearest_boxindex = boxindex;
|
||||
}
|
||||
|
||||
if(nearest_collided == -1)
|
||||
{
|
||||
// No collision with any collision box.
|
||||
pos_f += speed_f * dtime;
|
||||
dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, a collision occurred.
|
||||
|
||||
const aabb3f& cbox = cboxes[nearest_boxindex];
|
||||
|
||||
// Check for stairs.
|
||||
bool step_up = (nearest_collided != 1) && // must not be Y direction
|
||||
(movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
|
||||
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
|
||||
(!wouldCollideWithCeiling(cboxes, movingbox,
|
||||
cbox.MaxEdge.Y - movingbox.MinEdge.Y,
|
||||
d));
|
||||
|
||||
// Move to the point of collision and reduce dtime by nearest_dtime
|
||||
if(nearest_dtime < 0)
|
||||
{
|
||||
// Handle negative nearest_dtime (can be caused by the d allowance)
|
||||
if(!step_up)
|
||||
{
|
||||
if(nearest_collided == 0)
|
||||
pos_f.X += speed_f.X * nearest_dtime;
|
||||
if(nearest_collided == 1)
|
||||
pos_f.Y += speed_f.Y * nearest_dtime;
|
||||
if(nearest_collided == 2)
|
||||
pos_f.Z += speed_f.Z * nearest_dtime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pos_f += speed_f * nearest_dtime;
|
||||
dtime -= nearest_dtime;
|
||||
}
|
||||
|
||||
// Set the speed component that caused the collision to zero
|
||||
if(step_up)
|
||||
{
|
||||
// Special case: Handle stairs
|
||||
is_step_up[nearest_boxindex] = true;
|
||||
}
|
||||
else if(nearest_collided == 0) // X
|
||||
{
|
||||
speed_f.X = 0;
|
||||
result.collides = true;
|
||||
result.collides_xz = true;
|
||||
}
|
||||
else if(nearest_collided == 1) // Y
|
||||
{
|
||||
speed_f.Y = 0;
|
||||
result.collides = true;
|
||||
}
|
||||
else if(nearest_collided == 2) // Z
|
||||
{
|
||||
speed_f.Z = 0;
|
||||
result.collides = true;
|
||||
result.collides_xz = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Final touches: Check if standing on ground, step up stairs.
|
||||
*/
|
||||
aabb3f box = box_0;
|
||||
box.MinEdge += pos_f;
|
||||
box.MaxEdge += pos_f;
|
||||
for(u32 boxindex = 0; boxindex < cboxes.size(); boxindex++)
|
||||
{
|
||||
const aabb3f& cbox = cboxes[boxindex];
|
||||
|
||||
/*
|
||||
See if the object is touching ground.
|
||||
|
||||
@@ -107,108 +431,44 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
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
|
||||
cbox.MaxEdge.X-d > box.MinEdge.X &&
|
||||
cbox.MinEdge.X+d < box.MaxEdge.X &&
|
||||
cbox.MaxEdge.Z-d > box.MinEdge.Z &&
|
||||
cbox.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(is_step_up[boxindex])
|
||||
{
|
||||
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;
|
||||
}
|
||||
pos_f.Y += (cbox.MaxEdge.Y - box.MinEdge.Y);
|
||||
box = box_0;
|
||||
box.MinEdge += pos_f;
|
||||
box.MaxEdge += pos_f;
|
||||
}
|
||||
|
||||
/*
|
||||
If this is a collision, revert the pos_f in the main
|
||||
direction.
|
||||
*/
|
||||
if(other_axes_overlap && main_axis_collides)
|
||||
if(fabs(cbox.MaxEdge.Y-box.MinEdge.Y) < 0.15*BS)
|
||||
{
|
||||
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];
|
||||
result.collides = true;
|
||||
result.touching_ground = true;
|
||||
if(is_unloaded[boxindex])
|
||||
result.standing_on_unloaded = true;
|
||||
}
|
||||
|
||||
}
|
||||
} // xyz
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f)
|
||||
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)
|
||||
{
|
||||
TimeTaker tt("collisionMovePrecise");
|
||||
infostream<<"start collisionMovePrecise\n";
|
||||
|
||||
collisionMoveResult final_result;
|
||||
|
||||
// Maximum time increment (for collision detection etc)
|
||||
// time = distance / speed
|
||||
f32 dtime_max_increment = pos_max_d / speed_f.getLength();
|
||||
|
||||
// Maximum time increment is 10ms or lower
|
||||
if(dtime_max_increment > 0.01)
|
||||
dtime_max_increment = 0.01;
|
||||
|
||||
// Don't allow overly huge dtime
|
||||
if(dtime > 2.0)
|
||||
dtime = 2.0;
|
||||
|
||||
|
||||
f32 dtime_downcount = dtime;
|
||||
|
||||
u32 loopcount = 0;
|
||||
@@ -216,6 +476,16 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
{
|
||||
loopcount++;
|
||||
|
||||
// Maximum time increment (for collision detection etc)
|
||||
// time = distance / speed
|
||||
f32 dtime_max_increment = 1.0;
|
||||
if(speed_f.getLength() != 0)
|
||||
dtime_max_increment = pos_max_d / speed_f.getLength();
|
||||
|
||||
// Maximum time increment is 10ms or lower
|
||||
if(dtime_max_increment > 0.01)
|
||||
dtime_max_increment = 0.01;
|
||||
|
||||
f32 dtime_part;
|
||||
if(dtime_downcount > dtime_max_increment)
|
||||
{
|
||||
@@ -233,18 +503,22 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
|
||||
dtime_downcount = 0;
|
||||
}
|
||||
|
||||
collisionMoveResult result = collisionMoveSimple(map, gamedef,
|
||||
pos_max_d, box_0, dtime_part, pos_f, speed_f);
|
||||
collisionMoveResult result = collisionMoveSimple(env,
|
||||
pos_max_d, box_0, stepheight, dtime_part,
|
||||
pos_f, speed_f, accel_f);
|
||||
|
||||
if(result.touching_ground)
|
||||
final_result.touching_ground = true;
|
||||
if(result.collides)
|
||||
final_result.collides = true;
|
||||
if(result.collides_xz)
|
||||
final_result.collides_xz = true;
|
||||
if(result.standing_on_unloaded)
|
||||
final_result.standing_on_unloaded = true;
|
||||
}
|
||||
while(dtime_downcount > 0.001);
|
||||
|
||||
|
||||
|
||||
infostream<<"end collisionMovePrecise\n";
|
||||
return final_result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,30 +21,52 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define COLLISION_HEADER
|
||||
|
||||
#include "common_irrlicht.h"
|
||||
#include <vector>
|
||||
|
||||
class Map;
|
||||
class IGameDef;
|
||||
class Environment;
|
||||
|
||||
struct collisionMoveResult
|
||||
{
|
||||
bool touching_ground;
|
||||
bool collides;
|
||||
bool collides_xz;
|
||||
bool standing_on_unloaded;
|
||||
|
||||
collisionMoveResult():
|
||||
touching_ground(false),
|
||||
collides(false)
|
||||
collides(false),
|
||||
collides_xz(false),
|
||||
standing_on_unloaded(false)
|
||||
{}
|
||||
};
|
||||
|
||||
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
|
||||
collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||
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,
|
||||
f32 pos_max_d, const core::aabbox3d<f32> &box_0,
|
||||
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||
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);
|
||||
|
||||
// Helper function:
|
||||
// Checks for collision of a moving aabbox with a static aabbox
|
||||
// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
|
||||
// dtime receives time until first collision, invalid if -1 is returned
|
||||
int axisAlignedCollision(
|
||||
const aabb3f &staticbox, const aabb3f &movingbox,
|
||||
const v3f &speed, f32 d, f32 &dtime);
|
||||
|
||||
// Helper function:
|
||||
// Checks if moving the movingbox up by the given distance would hit a ceiling.
|
||||
bool wouldCollideWithCeiling(
|
||||
const std::vector<aabb3f> &staticboxes,
|
||||
const aabb3f &movingbox,
|
||||
f32 y_increase, f32 d);
|
||||
|
||||
|
||||
enum CollisionType
|
||||
{
|
||||
|
||||
@@ -17,10 +17,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "content_cao.h"
|
||||
#include "tile.h"
|
||||
#include "environment.h"
|
||||
#include "collision.h"
|
||||
#include "collidableobject.h"
|
||||
#include "clientlinkableobject.h"
|
||||
#include "settings.h"
|
||||
#include <ICameraSceneNode.h>
|
||||
#include <ITextSceneNode.h>
|
||||
@@ -1681,7 +1682,7 @@ void MobV2CAO::setLooks(const std::string &looks)
|
||||
|
||||
#include "luaentity_common.h"
|
||||
|
||||
class LuaEntityCAO : public ClientActiveObject
|
||||
class LuaEntityCAO : public ClientActiveObject , public CollidableObject , public ClientLinkableObject
|
||||
{
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
@@ -1815,6 +1816,33 @@ class LuaEntityCAO : public ClientActiveObject
|
||||
m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
|
||||
mesh->drop();
|
||||
|
||||
m_meshnode->setScale(v3f(1));
|
||||
// Will be shown when we know the brightness
|
||||
m_meshnode->setVisible(false);
|
||||
} else if(m_prop->visual == "cube_allfaces"){
|
||||
infostream<<"LuaEntityCAO::addToScene(): cube_allfaces"<<std::endl;
|
||||
scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS),true);
|
||||
m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
|
||||
mesh->drop();
|
||||
|
||||
m_meshnode->setScale(v3f(1));
|
||||
// Will be shown when we know the brightness
|
||||
m_meshnode->setVisible(false);
|
||||
} else if (m_prop->visual == "plant") {
|
||||
infostream<<"LuaEntityCAO::addToScene(): plant"<<std::endl;
|
||||
scene::IMesh *mesh = createPlantMesh(v3f(BS,BS,BS));
|
||||
m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
|
||||
mesh->drop();
|
||||
|
||||
m_meshnode->setScale(v3f(1));
|
||||
// Will be shown when we know the brightness
|
||||
m_meshnode->setVisible(false);
|
||||
} else if (m_prop->visual == "cube_disorted") {
|
||||
infostream<<"LuaEntityCAO::addToScene(): irregular_cube"<<std::endl;
|
||||
scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS), m_prop->collisionbox);
|
||||
m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
|
||||
mesh->drop();
|
||||
|
||||
m_meshnode->setScale(v3f(1));
|
||||
// Will be shown when we know the brightness
|
||||
m_meshnode->setVisible(false);
|
||||
@@ -1869,35 +1897,40 @@ class LuaEntityCAO : public ClientActiveObject
|
||||
|
||||
void step(float dtime, ClientEnvironment *env)
|
||||
{
|
||||
if(m_prop->physical){
|
||||
core::aabbox3d<f32> box = m_prop->collisionbox;
|
||||
box.MinEdge *= BS;
|
||||
box.MaxEdge *= BS;
|
||||
collisionMoveResult moveresult;
|
||||
f32 pos_max_d = BS*0.25; // Distance per iteration
|
||||
v3f p_pos = m_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
IGameDef *gamedef = env->getGameDef();
|
||||
moveresult = collisionMovePrecise(&env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, p_pos, p_velocity);
|
||||
// Apply results
|
||||
m_position = p_pos;
|
||||
m_velocity = p_velocity;
|
||||
|
||||
bool is_end_position = moveresult.collides;
|
||||
pos_translator.update(m_position, is_end_position, dtime);
|
||||
pos_translator.translate(dtime);
|
||||
updateNodePos();
|
||||
if(!this->isLinked()) {
|
||||
if(m_prop->physical){
|
||||
core::aabbox3d<f32> box = m_prop->collisionbox;
|
||||
box.MinEdge *= BS;
|
||||
box.MaxEdge *= BS;
|
||||
collisionMoveResult moveresult;
|
||||
f32 pos_max_d = BS*0.125; // Distance per iteration
|
||||
f32 stepheight = 0;
|
||||
v3f p_pos = m_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
v3f p_acceleration = m_acceleration;
|
||||
moveresult = collisionMovePrecise(env,
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
// Apply results
|
||||
m_position = p_pos;
|
||||
m_velocity = p_velocity;
|
||||
m_acceleration = p_acceleration;
|
||||
|
||||
m_velocity += dtime * m_acceleration;
|
||||
} else {
|
||||
m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
|
||||
m_velocity += dtime * m_acceleration;
|
||||
pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
|
||||
pos_translator.translate(dtime);
|
||||
updateNodePos();
|
||||
bool is_end_position = moveresult.collides;
|
||||
pos_translator.update(m_position, is_end_position, dtime);
|
||||
pos_translator.translate(dtime);
|
||||
updateNodePos();
|
||||
} else {
|
||||
m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
|
||||
m_velocity += dtime * m_acceleration;
|
||||
pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
|
||||
pos_translator.translate(dtime);
|
||||
updateNodePos();
|
||||
}
|
||||
}
|
||||
|
||||
stepLinkedObjects(this->m_position,dtime);
|
||||
|
||||
m_anim_timer += dtime;
|
||||
if(m_anim_timer >= m_anim_framelength){
|
||||
m_anim_timer -= m_anim_framelength;
|
||||
@@ -1970,26 +2003,51 @@ class LuaEntityCAO : public ClientActiveObject
|
||||
tsrc->getTextureRaw(texturestring));
|
||||
}
|
||||
if(m_meshnode){
|
||||
for (u32 i = 0; i < 6; ++i)
|
||||
{
|
||||
std::string texturestring = "unknown_block.png";
|
||||
if(m_prop->textures.size() > i)
|
||||
texturestring = m_prop->textures[i];
|
||||
texturestring += mod;
|
||||
AtlasPointer ap = tsrc->getTexture(texturestring);
|
||||
if (m_prop->visual == "plant") {
|
||||
for (u32 i = 0; i < 4; ++i) {
|
||||
std::string texturestring = "unknown_block.png";
|
||||
if(m_prop->textures.size() > 0)
|
||||
texturestring = m_prop->textures[0];
|
||||
texturestring += mod;
|
||||
AtlasPointer ap = tsrc->getTexture(texturestring);
|
||||
|
||||
// Get the tile texture and atlas transformation
|
||||
video::ITexture* atlas = ap.atlas;
|
||||
v2f pos = ap.pos;
|
||||
v2f size = ap.size;
|
||||
// Get the tile texture and atlas transformation
|
||||
video::ITexture* atlas = ap.atlas;
|
||||
v2f pos = ap.pos;
|
||||
v2f size = ap.size;
|
||||
|
||||
// Set material flags and texture
|
||||
video::SMaterial& material = m_meshnode->getMaterial(i);
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material.setTexture(0, atlas);
|
||||
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
|
||||
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
|
||||
// Set material flags and texture
|
||||
video::SMaterial& material = m_meshnode->getMaterial(i);
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material.setTexture(0, atlas);
|
||||
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
|
||||
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (u32 i = 0; i < 6; ++i) {
|
||||
std::string texturestring = "unknown_block.png";
|
||||
if(m_prop->textures.size() > i)
|
||||
texturestring = m_prop->textures[i];
|
||||
texturestring += mod;
|
||||
AtlasPointer ap = tsrc->getTexture(texturestring);
|
||||
|
||||
// Get the tile texture and atlas transformation
|
||||
video::ITexture* atlas = ap.atlas;
|
||||
v2f pos = ap.pos;
|
||||
v2f size = ap.size;
|
||||
|
||||
// Set material flags and texture
|
||||
video::SMaterial& material = m_meshnode->getMaterial(i);
|
||||
material.setFlag(video::EMF_LIGHTING, false);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material.setTexture(0, atlas);
|
||||
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
|
||||
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2044,7 +2102,37 @@ class LuaEntityCAO : public ClientActiveObject
|
||||
|
||||
updateTexturePos();
|
||||
}
|
||||
else if (handleLinkUnlinkMessages(cmd,&is,this->m_env))
|
||||
{
|
||||
//Link unlink already done in handleLinkUnlinkMessages!
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void setPosition(v3f toset, float dtime){
|
||||
if (this->isLinked()) {
|
||||
this->m_position = toset + this->m_linkOffset;
|
||||
pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
|
||||
pos_translator.translate(dtime);
|
||||
updateNodePos();
|
||||
}
|
||||
}
|
||||
|
||||
void updateLinkState(bool value) {}
|
||||
};
|
||||
|
||||
// Prototype
|
||||
@@ -2054,7 +2142,7 @@ LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
|
||||
PlayerCAO
|
||||
*/
|
||||
|
||||
class PlayerCAO : public ClientActiveObject
|
||||
class PlayerCAO : public ClientActiveObject, public CollidableObject , public ClientLinkableObject
|
||||
{
|
||||
private:
|
||||
core::aabbox3d<f32> m_selection_box;
|
||||
@@ -2114,6 +2202,17 @@ class PlayerCAO : public ClientActiveObject
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -2262,9 +2361,12 @@ class PlayerCAO : public ClientActiveObject
|
||||
|
||||
void step(float dtime, ClientEnvironment *env)
|
||||
{
|
||||
pos_translator.translate(dtime);
|
||||
if(!isLinked()) {
|
||||
pos_translator.translate(dtime);
|
||||
updateNodePos();
|
||||
}
|
||||
|
||||
updateVisibility();
|
||||
updateNodePos();
|
||||
|
||||
if(m_damage_visual_timer > 0){
|
||||
m_damage_visual_timer -= dtime;
|
||||
@@ -2305,6 +2407,10 @@ class PlayerCAO : public ClientActiveObject
|
||||
m_dead = readU8(is);
|
||||
updateVisibility();
|
||||
}
|
||||
else if (handleLinkUnlinkMessages(cmd,&is,this->m_env))
|
||||
{
|
||||
//Link unlink already done in handleLinkUnlinkMessages!
|
||||
}
|
||||
}
|
||||
|
||||
void updateTextures(const std::string &mod)
|
||||
@@ -2330,6 +2436,26 @@ class PlayerCAO : public ClientActiveObject
|
||||
}
|
||||
}
|
||||
}
|
||||
void setPosition(v3f toset, float dtime){
|
||||
if (isLinked()) {
|
||||
this->m_position = toset + this->m_linkOffset;
|
||||
pos_translator.update(this->m_position,false);
|
||||
updateNodePos();
|
||||
|
||||
if(m_is_local_player) {
|
||||
m_local_player->setPosition(this->m_position);
|
||||
}
|
||||
}
|
||||
else {
|
||||
errorstream<<"Got linked position update but not linked"<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void updateLinkState(bool value) {
|
||||
if(m_is_local_player) {
|
||||
m_local_player->Link(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Prototype
|
||||
|
||||
@@ -985,6 +985,72 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
collector.append(material_rail, vertices, 4, indices, 6);
|
||||
break;}
|
||||
case NDT_NODEBOX:
|
||||
{
|
||||
v3s16 facedirs[6] = {
|
||||
v3s16(0,1,0),
|
||||
v3s16(0,-1,0),
|
||||
v3s16(1,0,0),
|
||||
v3s16(-1,0,0),
|
||||
v3s16(0,0,1),
|
||||
v3s16(0,0,-1),
|
||||
};
|
||||
video::SMaterial material_nodebox[6];
|
||||
AtlasPointer pa_nodebox[6];
|
||||
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
material_nodebox[i].setFlag(video::EMF_LIGHTING, false);
|
||||
material_nodebox[i].setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_nodebox[i].setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_nodebox[i].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
TileSpec tile = getNodeTile(n, p, facedirs[i],
|
||||
&data->m_temp_mods, tsrc, nodedef);
|
||||
pa_nodebox[i] = tile.texture;
|
||||
material_nodebox[i].setTexture(0, pa_nodebox[i].atlas);
|
||||
}
|
||||
|
||||
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
|
||||
video::SColor c = MapBlock_LightColor(255, l);
|
||||
|
||||
v3f pos = intToFloat(p+blockpos_nodes, BS);
|
||||
|
||||
std::vector<aabb3f> boxes = n.getNodeBoxes(nodedef);
|
||||
for(std::vector<aabb3f>::iterator
|
||||
i = boxes.begin();
|
||||
i != boxes.end(); i++)
|
||||
{
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += pos;
|
||||
box.MaxEdge += pos;
|
||||
|
||||
// Compute texture coords
|
||||
f32 tx1 = (i->MinEdge.X/BS)+0.5;
|
||||
f32 ty1 = (i->MinEdge.Y/BS)+0.5;
|
||||
f32 tz1 = (i->MinEdge.Z/BS)+0.5;
|
||||
f32 tx2 = (i->MaxEdge.X/BS)+0.5;
|
||||
f32 ty2 = (i->MaxEdge.Y/BS)+0.5;
|
||||
f32 tz2 = (i->MaxEdge.Z/BS)+0.5;
|
||||
f32 txc[24] = {
|
||||
// up
|
||||
tx1, 1-tz2, tx2, 1-tz1,
|
||||
// down
|
||||
tx1, tz1, tx2, tz2,
|
||||
// right
|
||||
tz1, 1-ty2, tz2, 1-ty1,
|
||||
// left
|
||||
1-tz2, 1-ty2, 1-tz1, 1-ty1,
|
||||
// back
|
||||
1-tx2, 1-ty2, 1-tx1, 1-ty1,
|
||||
// front
|
||||
tx1, 1-ty2, tx2, 1-ty1,
|
||||
};
|
||||
|
||||
makeCuboid(&collector, box,
|
||||
material_nodebox, pa_nodebox, 6,
|
||||
c, txc);
|
||||
}
|
||||
break;}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "materials.h" // For MaterialProperties and ToolDiggingProperties
|
||||
#include "gamedef.h"
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
|
||||
/* Some helper functions */
|
||||
|
||||
// Y is copied, X and Z change is limited
|
||||
@@ -163,9 +161,11 @@ void ItemSAO::step(float dtime, bool send_recommended)
|
||||
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||
v3f pos_f = getBasePosition();
|
||||
v3f pos_f_old = pos_f;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
f32 stepheight = 0;
|
||||
moveresult = collisionMoveSimple(m_env,
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
pos_f, m_speed_f, accel_f);
|
||||
|
||||
if(send_recommended == false)
|
||||
return;
|
||||
@@ -404,9 +404,11 @@ void RatSAO::step(float dtime, bool send_recommended)
|
||||
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||
v3f pos_f = getBasePosition();
|
||||
v3f pos_f_old = pos_f;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
f32 stepheight = 0;
|
||||
moveresult = collisionMoveSimple(m_env,
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
pos_f, m_speed_f, accel_f);
|
||||
m_touching_ground = moveresult.touching_ground;
|
||||
|
||||
setBasePosition(pos_f);
|
||||
@@ -652,9 +654,11 @@ void Oerkki1SAO::step(float dtime, bool send_recommended)
|
||||
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);*/
|
||||
v3f pos_f = getBasePosition();
|
||||
v3f pos_f_old = pos_f;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
f32 stepheight = 0;
|
||||
moveresult = collisionMovePrecise(m_env,
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
pos_f, m_speed_f, accel_f);
|
||||
m_touching_ground = moveresult.touching_ground;
|
||||
|
||||
// Do collision damage
|
||||
@@ -899,9 +903,11 @@ void FireflySAO::step(float dtime, bool send_recommended)
|
||||
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||
v3f pos_f = getBasePosition();
|
||||
v3f pos_f_old = pos_f;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, pos_f, m_speed_f);
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
f32 stepheight = 0;
|
||||
moveresult = collisionMoveSimple(m_env,
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
pos_f, m_speed_f, accel_f);
|
||||
m_touching_ground = moveresult.touching_ground;
|
||||
|
||||
setBasePosition(pos_f);
|
||||
@@ -1618,16 +1624,17 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||
box.MaxEdge *= BS;
|
||||
collisionMoveResult moveresult;
|
||||
f32 pos_max_d = BS*0.25; // Distance per iteration
|
||||
v3f p_pos = getBasePosition();
|
||||
f32 stepheight = 0; // Maximum climbable step height
|
||||
v3f p_pos = m_base_position;
|
||||
v3f p_velocity = m_velocity;
|
||||
IGameDef *gamedef = m_env->getGameDef();
|
||||
moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
|
||||
pos_max_d, box, dtime, p_pos, p_velocity);
|
||||
v3f p_acceleration = m_acceleration;
|
||||
moveresult = collisionMovePrecise(m_env,
|
||||
pos_max_d, box, stepheight, dtime,
|
||||
p_pos, p_velocity, p_acceleration);
|
||||
// Apply results
|
||||
setBasePosition(p_pos);
|
||||
m_base_position = p_pos;
|
||||
m_velocity = p_velocity;
|
||||
|
||||
m_velocity += dtime * m_acceleration;
|
||||
m_acceleration = p_acceleration;
|
||||
} else {
|
||||
m_base_position += dtime * m_velocity + 0.5 * dtime
|
||||
* dtime * m_acceleration;
|
||||
@@ -1830,3 +1837,39 @@ 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;
|
||||
}
|
||||
|
||||
bool LuaEntitySAO::sendLinkMsg(ServerActiveObject* parent,v3f offset) {
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, 3);
|
||||
// parameters
|
||||
writeU16(os, parent->getId());
|
||||
writeV3F1000(os, offset);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaEntitySAO::sendUnlinkMsg() {
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, 4);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), false, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "serverobject.h"
|
||||
#include "content_object.h"
|
||||
#include "collidableobject.h"
|
||||
#include "serverlinkableobject.h"
|
||||
|
||||
class TestSAO : public ServerActiveObject
|
||||
{
|
||||
@@ -192,7 +194,7 @@ class MobV2SAO : public ServerActiveObject
|
||||
|
||||
struct LuaEntityProperties;
|
||||
|
||||
class LuaEntitySAO : public ServerActiveObject
|
||||
class LuaEntitySAO : public ServerActiveObject, public CollidableObject , public ServerLinkableObject
|
||||
{
|
||||
public:
|
||||
LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
||||
@@ -222,6 +224,9 @@ class LuaEntitySAO : public ServerActiveObject
|
||||
void setSprite(v2s16 p, int num_frames, float framelength,
|
||||
bool select_horiz_by_yawpitch);
|
||||
std::string getName();
|
||||
aabb3f* getCollisionBox();
|
||||
bool sendLinkMsg(ServerActiveObject* parent,v3f offset);
|
||||
bool sendUnlinkMsg();
|
||||
private:
|
||||
void sendPosition(bool do_interpolate, bool is_movement_end);
|
||||
|
||||
|
||||
@@ -765,6 +765,21 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
||||
abmhandler.apply(block);
|
||||
}
|
||||
|
||||
core::list<MapNode> ServerEnvironment::getNodesInsideRadius(v3s16 pos, float radius)
|
||||
{
|
||||
core::list<MapNode> nodes;
|
||||
for (int i = pos.X - radius; i < pos.X + radius; i ++)
|
||||
for (int j = pos.Y - radius; j < pos.Y + radius; j ++)
|
||||
for (int k = pos.Z - radius; k < pos.Z + radius; k ++) {
|
||||
v3s16 current_pos = v3s16(i,j,k);
|
||||
if (current_pos.getDistanceFrom(pos) < radius) {
|
||||
MapNode n = m_map->getNodeNoEx(current_pos);
|
||||
nodes.push_back(n);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
|
||||
{
|
||||
m_abms.push_back(ABMWithState(abm));
|
||||
@@ -920,7 +935,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 +1818,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
|
||||
|
||||
@@ -1877,6 +1908,7 @@ void ClientEnvironment::step(float dtime)
|
||||
Get the speed the player is going
|
||||
*/
|
||||
bool is_climbing = lplayer->is_climbing;
|
||||
bool linked = lplayer->m_linked;
|
||||
|
||||
f32 player_speed = lplayer->getSpeed().getLength();
|
||||
|
||||
@@ -1905,90 +1937,91 @@ void ClientEnvironment::step(float dtime)
|
||||
/*
|
||||
Stuff that has a maximum time increment
|
||||
*/
|
||||
if (!linked) {
|
||||
u32 loopcount = 0;
|
||||
do
|
||||
{
|
||||
loopcount++;
|
||||
|
||||
u32 loopcount = 0;
|
||||
do
|
||||
{
|
||||
loopcount++;
|
||||
|
||||
f32 dtime_part;
|
||||
if(dtime_downcount > dtime_max_increment)
|
||||
{
|
||||
dtime_part = dtime_max_increment;
|
||||
dtime_downcount -= dtime_part;
|
||||
}
|
||||
else
|
||||
{
|
||||
dtime_part = dtime_downcount;
|
||||
/*
|
||||
Setting this to 0 (no -=dtime_part) disables an infinite loop
|
||||
when dtime_part is so small that dtime_downcount -= dtime_part
|
||||
does nothing
|
||||
*/
|
||||
dtime_downcount = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Handle local player
|
||||
*/
|
||||
|
||||
{
|
||||
v3f lplayerpos = lplayer->getPosition();
|
||||
|
||||
// Apply physics
|
||||
if(free_move == false && is_climbing == false)
|
||||
f32 dtime_part;
|
||||
if(dtime_downcount > dtime_max_increment)
|
||||
{
|
||||
// Gravity
|
||||
v3f speed = lplayer->getSpeed();
|
||||
if(lplayer->swimming_up == false)
|
||||
speed.Y -= 9.81 * BS * dtime_part * 2;
|
||||
dtime_part = dtime_max_increment;
|
||||
dtime_downcount -= dtime_part;
|
||||
}
|
||||
else
|
||||
{
|
||||
dtime_part = dtime_downcount;
|
||||
/*
|
||||
Setting this to 0 (no -=dtime_part) disables an infinite loop
|
||||
when dtime_part is so small that dtime_downcount -= dtime_part
|
||||
does nothing
|
||||
*/
|
||||
dtime_downcount = 0;
|
||||
}
|
||||
|
||||
// Water resistance
|
||||
if(lplayer->in_water_stable || lplayer->in_water)
|
||||
/*
|
||||
Handle local player
|
||||
*/
|
||||
|
||||
{
|
||||
v3f lplayerpos = lplayer->getPosition();
|
||||
|
||||
// Apply physics
|
||||
if(free_move == false && is_climbing == false)
|
||||
{
|
||||
f32 max_down = 2.0*BS;
|
||||
if(speed.Y < -max_down) speed.Y = -max_down;
|
||||
// Gravity
|
||||
v3f speed = lplayer->getSpeed();
|
||||
if(lplayer->swimming_up == false)
|
||||
speed.Y -= 9.81 * BS * dtime_part * 2;
|
||||
|
||||
f32 max = 2.5*BS;
|
||||
if(speed.getLength() > max)
|
||||
// Water resistance
|
||||
if(lplayer->in_water_stable || lplayer->in_water)
|
||||
{
|
||||
speed = speed / speed.getLength() * max;
|
||||
f32 max_down = 2.0*BS;
|
||||
if(speed.Y < -max_down) speed.Y = -max_down;
|
||||
|
||||
f32 max = 2.5*BS;
|
||||
if(speed.getLength() > max)
|
||||
{
|
||||
speed = speed / speed.getLength() * max;
|
||||
}
|
||||
}
|
||||
|
||||
lplayer->setSpeed(speed);
|
||||
}
|
||||
|
||||
lplayer->setSpeed(speed);
|
||||
/*
|
||||
Move the lplayer.
|
||||
This also does collision detection.
|
||||
*/
|
||||
lplayer->move(dtime_part, this, position_max_increment,
|
||||
&player_collisions);
|
||||
}
|
||||
}
|
||||
while(dtime_downcount > 0.001);
|
||||
|
||||
/*
|
||||
Move the lplayer.
|
||||
This also does collision detection.
|
||||
*/
|
||||
lplayer->move(dtime_part, *m_map, position_max_increment,
|
||||
&player_collisions);
|
||||
}
|
||||
}
|
||||
while(dtime_downcount > 0.001);
|
||||
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
||||
|
||||
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
||||
|
||||
for(core::list<CollisionInfo>::Iterator
|
||||
i = player_collisions.begin();
|
||||
i != player_collisions.end(); i++)
|
||||
{
|
||||
CollisionInfo &info = *i;
|
||||
if(info.t == COLLISION_FALL)
|
||||
for(core::list<CollisionInfo>::Iterator
|
||||
i = player_collisions.begin();
|
||||
i != player_collisions.end(); i++)
|
||||
{
|
||||
//f32 tolerance = BS*10; // 2 without damage
|
||||
f32 tolerance = BS*12; // 3 without damage
|
||||
f32 factor = 1;
|
||||
if(info.speed > tolerance)
|
||||
CollisionInfo &info = *i;
|
||||
if(info.t == COLLISION_FALL)
|
||||
{
|
||||
f32 damage_f = (info.speed - tolerance)/BS*factor;
|
||||
u16 damage = (u16)(damage_f+0.5);
|
||||
damageLocalPlayer(damage, true);
|
||||
//f32 tolerance = BS*10; // 2 without damage
|
||||
f32 tolerance = BS*12; // 3 without damage
|
||||
f32 factor = 1;
|
||||
if(info.speed > tolerance)
|
||||
{
|
||||
f32 damage_f = (info.speed - tolerance)/BS*factor;
|
||||
u16 damage = (u16)(damage_f+0.5);
|
||||
damageLocalPlayer(damage, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
A quick draft of lava damage
|
||||
@@ -2034,7 +2067,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 +2344,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 @@ class Environment
|
||||
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;
|
||||
@@ -271,6 +274,9 @@ class ServerEnvironment : public Environment
|
||||
-------------------------------------------
|
||||
*/
|
||||
|
||||
// Find all nodes inside a radius around a point
|
||||
core::list<MapNode> getNodesInsideRadius(v3s16 pos, float radius);
|
||||
|
||||
// Find all active objects inside a radius around a point
|
||||
std::set<u16> getObjectsInsideRadius(v3f pos, float radius);
|
||||
|
||||
@@ -280,6 +286,8 @@ class ServerEnvironment : public Environment
|
||||
// This makes stuff happen
|
||||
void step(f32 dtime);
|
||||
|
||||
//get a list of all active objects
|
||||
core::list<ActiveObject*> getActiveObjects();
|
||||
private:
|
||||
|
||||
/*
|
||||
@@ -462,6 +470,9 @@ class ClientEnvironment : public Environment
|
||||
// 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;
|
||||
|
||||
274
src/game.cpp
274
src/game.cpp
@@ -293,44 +293,40 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
core::line3d<f32> shootline, f32 d,
|
||||
bool liquids_pointable,
|
||||
bool look_for_object,
|
||||
core::aabbox3d<f32> &hilightbox,
|
||||
bool &should_show_hilightbox,
|
||||
std::vector<aabb3f> &hilightboxes,
|
||||
ClientActiveObject *&selected_object)
|
||||
{
|
||||
PointedThing result;
|
||||
|
||||
hilightbox = core::aabbox3d<f32>(0,0,0,0,0,0);
|
||||
should_show_hilightbox = false;
|
||||
hilightboxes.clear();
|
||||
selected_object = NULL;
|
||||
|
||||
INodeDefManager *nodedef = client->getNodeDefManager();
|
||||
|
||||
// First try to find a pointed at active object
|
||||
if(look_for_object)
|
||||
{
|
||||
selected_object = client->getSelectedActiveObject(d*BS,
|
||||
camera_position, shootline);
|
||||
}
|
||||
if(selected_object != NULL)
|
||||
{
|
||||
core::aabbox3d<f32> *selection_box
|
||||
= selected_object->getSelectionBox();
|
||||
// Box should exist because object was returned in the
|
||||
// first place
|
||||
assert(selection_box);
|
||||
|
||||
v3f pos = selected_object->getPosition();
|
||||
if(selected_object != NULL)
|
||||
{
|
||||
if(selected_object->doShowSelectionBox())
|
||||
{
|
||||
aabb3f *selection_box = selected_object->getSelectionBox();
|
||||
// Box should exist because object was
|
||||
// returned in the first place
|
||||
assert(selection_box);
|
||||
|
||||
hilightbox = core::aabbox3d<f32>(
|
||||
selection_box->MinEdge + pos,
|
||||
selection_box->MaxEdge + pos
|
||||
);
|
||||
v3f pos = selected_object->getPosition();
|
||||
hilightboxes.push_back(aabb3f(
|
||||
selection_box->MinEdge + pos,
|
||||
selection_box->MaxEdge + pos));
|
||||
}
|
||||
|
||||
should_show_hilightbox = selected_object->doShowSelectionBox();
|
||||
|
||||
result.type = POINTEDTHING_OBJECT;
|
||||
result.object_id = selected_object->getId();
|
||||
return result;
|
||||
result.type = POINTEDTHING_OBJECT;
|
||||
result.object_id = selected_object->getId();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// That didn't work, try to find a pointed at node
|
||||
@@ -366,196 +362,64 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||
if(!isPointableNode(n, client, liquids_pointable))
|
||||
continue;
|
||||
|
||||
std::vector<aabb3f> boxes = n.getSelectionBoxes(client->ndef());
|
||||
|
||||
v3s16 np(x,y,z);
|
||||
v3f npf = intToFloat(np, BS);
|
||||
|
||||
f32 d = 0.01;
|
||||
|
||||
v3s16 dirs[6] = {
|
||||
v3s16(0,0,1), // back
|
||||
v3s16(0,1,0), // top
|
||||
v3s16(1,0,0), // right
|
||||
v3s16(0,0,-1), // front
|
||||
v3s16(0,-1,0), // bottom
|
||||
v3s16(-1,0,0), // left
|
||||
};
|
||||
|
||||
const ContentFeatures &f = nodedef->get(n);
|
||||
|
||||
if(f.selection_box.type == NODEBOX_FIXED)
|
||||
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = boxes.begin();
|
||||
i != boxes.end(); i++)
|
||||
{
|
||||
core::aabbox3d<f32> box = f.selection_box.fixed;
|
||||
aabb3f box = *i;
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
|
||||
v3s16 facedirs[6] = {
|
||||
v3s16(-1,0,0),
|
||||
v3s16(1,0,0),
|
||||
v3s16(0,-1,0),
|
||||
v3s16(0,1,0),
|
||||
v3s16(0,0,-1),
|
||||
v3s16(0,0,1),
|
||||
};
|
||||
|
||||
core::aabbox3d<f32> faceboxes[6] = {
|
||||
// X-
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MinEdge.X+d, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
// X+
|
||||
core::aabbox3d<f32>(
|
||||
box.MaxEdge.X-d, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
// Y-
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MinEdge.Y+d, box.MaxEdge.Z
|
||||
),
|
||||
// Y+
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MaxEdge.Y-d, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
// Z-
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MinEdge.Z+d
|
||||
),
|
||||
// Z+
|
||||
core::aabbox3d<f32>(
|
||||
box.MinEdge.X, box.MinEdge.Y, box.MaxEdge.Z-d,
|
||||
box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z
|
||||
),
|
||||
};
|
||||
|
||||
for(u16 i=0; i<6; i++)
|
||||
for(u16 j=0; j<6; j++)
|
||||
{
|
||||
v3f facedir_f(facedirs[i].X, facedirs[i].Y, facedirs[i].Z);
|
||||
v3f centerpoint = npf + facedir_f * BS/2;
|
||||
v3s16 facedir = g_6dirs[j];
|
||||
aabb3f facebox = box;
|
||||
|
||||
f32 d = 0.001*BS;
|
||||
if(facedir.X > 0)
|
||||
facebox.MinEdge.X = facebox.MaxEdge.X-d;
|
||||
else if(facedir.X < 0)
|
||||
facebox.MaxEdge.X = facebox.MinEdge.X+d;
|
||||
else if(facedir.Y > 0)
|
||||
facebox.MinEdge.Y = facebox.MaxEdge.Y-d;
|
||||
else if(facedir.Y < 0)
|
||||
facebox.MaxEdge.Y = facebox.MinEdge.Y+d;
|
||||
else if(facedir.Z > 0)
|
||||
facebox.MinEdge.Z = facebox.MaxEdge.Z-d;
|
||||
else if(facedir.Z < 0)
|
||||
facebox.MaxEdge.Z = facebox.MinEdge.Z+d;
|
||||
|
||||
v3f centerpoint = facebox.getCenter();
|
||||
f32 distance = (centerpoint - camera_position).getLength();
|
||||
if(distance >= mindistance)
|
||||
continue;
|
||||
if(!faceboxes[i].intersectsWithLine(shootline))
|
||||
if(!facebox.intersectsWithLine(shootline))
|
||||
continue;
|
||||
|
||||
v3s16 np_above = floatToInt(centerpoint + intToFloat(facedir, d), BS);
|
||||
|
||||
result.type = POINTEDTHING_NODE;
|
||||
result.node_undersurface = np;
|
||||
result.node_abovesurface = np+facedirs[i];
|
||||
result.node_abovesurface = np_above;
|
||||
mindistance = distance;
|
||||
hilightbox = box;
|
||||
should_show_hilightbox = true;
|
||||
}
|
||||
}
|
||||
else if(f.selection_box.type == NODEBOX_WALLMOUNTED)
|
||||
{
|
||||
v3s16 dir = n.getWallMountedDir(nodedef);
|
||||
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
||||
dir_f *= BS/2 - BS/6 - BS/20;
|
||||
v3f cpf = npf + dir_f;
|
||||
f32 distance = (cpf - camera_position).getLength();
|
||||
|
||||
core::aabbox3d<f32> box;
|
||||
|
||||
// top
|
||||
if(dir == v3s16(0,1,0)){
|
||||
box = f.selection_box.wall_top;
|
||||
}
|
||||
// bottom
|
||||
else if(dir == v3s16(0,-1,0)){
|
||||
box = f.selection_box.wall_bottom;
|
||||
}
|
||||
// side
|
||||
else{
|
||||
v3f vertices[2] =
|
||||
hilightboxes.clear();
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i2 = boxes.begin();
|
||||
i2 != boxes.end(); i2++)
|
||||
{
|
||||
f.selection_box.wall_side.MinEdge,
|
||||
f.selection_box.wall_side.MaxEdge
|
||||
};
|
||||
|
||||
for(s32 i=0; i<2; i++)
|
||||
{
|
||||
if(dir == v3s16(-1,0,0))
|
||||
vertices[i].rotateXZBy(0);
|
||||
if(dir == v3s16(1,0,0))
|
||||
vertices[i].rotateXZBy(180);
|
||||
if(dir == v3s16(0,0,-1))
|
||||
vertices[i].rotateXZBy(90);
|
||||
if(dir == v3s16(0,0,1))
|
||||
vertices[i].rotateXZBy(-90);
|
||||
}
|
||||
|
||||
box = core::aabbox3d<f32>(vertices[0]);
|
||||
box.addInternalPoint(vertices[1]);
|
||||
}
|
||||
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
|
||||
if(distance < mindistance)
|
||||
{
|
||||
if(box.intersectsWithLine(shootline))
|
||||
{
|
||||
result.type = POINTEDTHING_NODE;
|
||||
result.node_undersurface = np;
|
||||
result.node_abovesurface = np;
|
||||
mindistance = distance;
|
||||
hilightbox = box;
|
||||
should_show_hilightbox = true;
|
||||
aabb3f box = *i2;
|
||||
box.MinEdge += npf + v3f(-d,-d,-d);
|
||||
box.MaxEdge += npf + v3f(d,d,d);
|
||||
hilightboxes.push_back(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // NODEBOX_REGULAR
|
||||
{
|
||||
for(u16 i=0; i<6; i++)
|
||||
{
|
||||
v3f dir_f = v3f(dirs[i].X,
|
||||
dirs[i].Y, dirs[i].Z);
|
||||
v3f centerpoint = npf + dir_f * BS/2;
|
||||
f32 distance =
|
||||
(centerpoint - camera_position).getLength();
|
||||
|
||||
if(distance < mindistance)
|
||||
{
|
||||
core::CMatrix4<f32> m;
|
||||
m.buildRotateFromTo(v3f(0,0,1), dir_f);
|
||||
|
||||
// This is the back face
|
||||
v3f corners[2] = {
|
||||
v3f(BS/2, BS/2, BS/2),
|
||||
v3f(-BS/2, -BS/2, BS/2+d)
|
||||
};
|
||||
|
||||
for(u16 j=0; j<2; j++)
|
||||
{
|
||||
m.rotateVect(corners[j]);
|
||||
corners[j] += npf;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> facebox(corners[0]);
|
||||
facebox.addInternalPoint(corners[1]);
|
||||
|
||||
if(facebox.intersectsWithLine(shootline))
|
||||
{
|
||||
result.type = POINTEDTHING_NODE;
|
||||
result.node_undersurface = np;
|
||||
result.node_abovesurface = np + dirs[i];
|
||||
mindistance = distance;
|
||||
|
||||
//hilightbox = facebox;
|
||||
|
||||
const float d = 0.502;
|
||||
core::aabbox3d<f32> nodebox
|
||||
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||
v3f nodepos_f = intToFloat(np, BS);
|
||||
nodebox.MinEdge += nodepos_f;
|
||||
nodebox.MaxEdge += nodepos_f;
|
||||
hilightbox = nodebox;
|
||||
should_show_hilightbox = true;
|
||||
}
|
||||
} // if distance < mindistance
|
||||
} // for dirs
|
||||
} // regular block
|
||||
} // for coords
|
||||
|
||||
return result;
|
||||
@@ -1112,9 +976,6 @@ void the_game(
|
||||
else
|
||||
hotbar_imagesize = 64;
|
||||
|
||||
// Hilight boxes collected during the loop and displayed
|
||||
core::list< core::aabbox3d<f32> > hilightboxes;
|
||||
|
||||
// Info text
|
||||
std::wstring infotext;
|
||||
|
||||
@@ -1821,8 +1682,8 @@ void the_game(
|
||||
core::line3d<f32> shootline(camera_position,
|
||||
camera_position + camera_direction * BS * (d+1));
|
||||
|
||||
core::aabbox3d<f32> hilightbox;
|
||||
bool should_show_hilightbox = false;
|
||||
// Hilight boxes collected during the loop and displayed
|
||||
std::vector<aabb3f> hilightboxes;
|
||||
ClientActiveObject *selected_object = NULL;
|
||||
|
||||
PointedThing pointed = getPointedThing(
|
||||
@@ -1831,7 +1692,7 @@ void the_game(
|
||||
camera_position, shootline, d,
|
||||
playeritem_liquids_pointable, !ldown_for_dig,
|
||||
// output
|
||||
hilightbox, should_show_hilightbox,
|
||||
hilightboxes,
|
||||
selected_object);
|
||||
|
||||
if(pointed != pointed_old)
|
||||
@@ -1840,12 +1701,6 @@ void the_game(
|
||||
//dstream<<"Pointing at "<<pointed.dump()<<std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Visualize selection
|
||||
*/
|
||||
if(should_show_hilightbox)
|
||||
hilightboxes.push_back(hilightbox);
|
||||
|
||||
/*
|
||||
Stop digging when
|
||||
- releasing left mouse button
|
||||
@@ -2477,9 +2332,10 @@ void the_game(
|
||||
|
||||
if(show_hud)
|
||||
{
|
||||
for(core::list<aabb3f>::Iterator i=hilightboxes.begin();
|
||||
i != hilightboxes.end(); i++)
|
||||
{
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = hilightboxes.begin();
|
||||
i != hilightboxes.end(); i++)
|
||||
{
|
||||
/*infostream<<"hilightbox min="
|
||||
<<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")"
|
||||
<<" max="
|
||||
|
||||
@@ -132,7 +132,98 @@ v3s16 MapNode::getWallMountedDir(INodeDefManager *nodemgr) const
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<aabb3f> transformNodeBox(const MapNode &n,
|
||||
const NodeBox &nodebox, INodeDefManager *nodemgr)
|
||||
{
|
||||
std::vector<aabb3f> boxes;
|
||||
if(nodebox.type == NODEBOX_FIXED)
|
||||
{
|
||||
const std::vector<aabb3f> &fixed = nodebox.fixed;
|
||||
int facedir = n.getFaceDir(nodemgr);
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = fixed.begin();
|
||||
i != fixed.end(); i++)
|
||||
{
|
||||
aabb3f box = *i;
|
||||
if(facedir == 1)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(-90);
|
||||
box.MaxEdge.rotateXZBy(-90);
|
||||
box.repair();
|
||||
}
|
||||
else if(facedir == 2)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(180);
|
||||
box.MaxEdge.rotateXZBy(180);
|
||||
box.repair();
|
||||
}
|
||||
else if(facedir == 3)
|
||||
{
|
||||
box.MinEdge.rotateXZBy(90);
|
||||
box.MaxEdge.rotateXZBy(90);
|
||||
box.repair();
|
||||
}
|
||||
boxes.push_back(box);
|
||||
}
|
||||
}
|
||||
else if(nodebox.type == NODEBOX_WALLMOUNTED)
|
||||
{
|
||||
v3s16 dir = n.getWallMountedDir(nodemgr);
|
||||
|
||||
// top
|
||||
if(dir == v3s16(0,1,0))
|
||||
{
|
||||
boxes.push_back(nodebox.wall_top);
|
||||
}
|
||||
// bottom
|
||||
else if(dir == v3s16(0,-1,0))
|
||||
{
|
||||
boxes.push_back(nodebox.wall_bottom);
|
||||
}
|
||||
// side
|
||||
else
|
||||
{
|
||||
v3f vertices[2] =
|
||||
{
|
||||
nodebox.wall_side.MinEdge,
|
||||
nodebox.wall_side.MaxEdge
|
||||
};
|
||||
|
||||
for(s32 i=0; i<2; i++)
|
||||
{
|
||||
if(dir == v3s16(-1,0,0))
|
||||
vertices[i].rotateXZBy(0);
|
||||
if(dir == v3s16(1,0,0))
|
||||
vertices[i].rotateXZBy(180);
|
||||
if(dir == v3s16(0,0,-1))
|
||||
vertices[i].rotateXZBy(90);
|
||||
if(dir == v3s16(0,0,1))
|
||||
vertices[i].rotateXZBy(-90);
|
||||
}
|
||||
|
||||
aabb3f box = aabb3f(vertices[0]);
|
||||
box.addInternalPoint(vertices[1]);
|
||||
boxes.push_back(box);
|
||||
}
|
||||
}
|
||||
else // NODEBOX_REGULAR
|
||||
{
|
||||
boxes.push_back(aabb3f(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2));
|
||||
}
|
||||
return boxes;
|
||||
}
|
||||
|
||||
std::vector<aabb3f> MapNode::getNodeBoxes(INodeDefManager *nodemgr) const
|
||||
{
|
||||
const ContentFeatures &f = nodemgr->get(*this);
|
||||
return transformNodeBox(*this, f.node_box, nodemgr);
|
||||
}
|
||||
|
||||
std::vector<aabb3f> MapNode::getSelectionBoxes(INodeDefManager *nodemgr) const
|
||||
{
|
||||
const ContentFeatures &f = nodemgr->get(*this);
|
||||
return transformNodeBox(*this, f.selection_box, nodemgr);
|
||||
}
|
||||
|
||||
u32 MapNode::serializedLength(u8 version)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "light.h"
|
||||
#include <vector>
|
||||
|
||||
class INodeDefManager;
|
||||
|
||||
@@ -195,6 +196,17 @@ struct MapNode
|
||||
u8 getWallMounted(INodeDefManager *nodemgr) const;
|
||||
v3s16 getWallMountedDir(INodeDefManager *nodemgr) const;
|
||||
|
||||
/*
|
||||
Gets list of node boxes (used for rendering (NDT_NODEBOX)
|
||||
and collision)
|
||||
*/
|
||||
std::vector<aabb3f> getNodeBoxes(INodeDefManager *nodemgr) const;
|
||||
|
||||
/*
|
||||
Gets list of selection boxes
|
||||
*/
|
||||
std::vector<aabb3f> getSelectionBoxes(INodeDefManager *nodemgr) const;
|
||||
|
||||
/*
|
||||
Serialization functions
|
||||
*/
|
||||
|
||||
153
src/mesh.cpp
153
src/mesh.cpp
@@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY
|
||||
#endif
|
||||
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale)
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale,bool allfaces)
|
||||
{
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[24] =
|
||||
@@ -86,6 +86,157 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale)
|
||||
buf->drop();
|
||||
}
|
||||
|
||||
if (allfaces) {
|
||||
video::S3DVertex vertices[24] =
|
||||
{
|
||||
// Up
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,1,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,1,0, c, 1,1),
|
||||
// Down
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,-1,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,-1,0, c, 1,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,-1,0, c, 1,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,-1,0, c, 0,1),
|
||||
// Right
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 1,0,0, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 1,0,0, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 1,0,0, c, 1,0),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 1,0,0, c, 1,1),
|
||||
// Left
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, -1,0,0, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, -1,0,0, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, -1,0,0, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, -1,0,0, c, 1,0),
|
||||
// Back
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0,0,1, c, 1,1),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0,0,1, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0,0,1, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0,0,1, c, 1,0),
|
||||
// Front
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0,0,-1, c, 1,1),
|
||||
};
|
||||
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
|
||||
for (u32 i=0; i<6; ++i)
|
||||
{
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||
// Set default material
|
||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
// Add mesh buffer to mesh
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
scaleMesh(anim_mesh, scale); // also recalculates bounding box
|
||||
return anim_mesh;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale,core::aabbox3d<f32> box)
|
||||
{
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[24] =
|
||||
{
|
||||
// Up
|
||||
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 0,1,0, c, 0,1),
|
||||
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 0,1,0, c, 0,0),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 0,1,0, c, 1,0),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 0,1,0, c, 1,1),
|
||||
// Down
|
||||
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MinEdge.Z, 0,-1,0, c, 0,0),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MinEdge.Z, 0,-1,0, c, 1,0),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 0,-1,0, c, 1,1),
|
||||
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 0,-1,0, c, 0,1),
|
||||
// Right
|
||||
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MinEdge.Z, 1,0,0, c, 0,1),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 1,0,0, c, 0,0),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 1,0,0, c, 1,0),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 1,0,0, c, 1,1),
|
||||
// Left
|
||||
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MinEdge.Z, -1,0,0, c, 1,1),
|
||||
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MaxEdge.Z, -1,0,0, c, 0,1),
|
||||
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, -1,0,0, c, 0,0),
|
||||
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MinEdge.Z, -1,0,0, c, 1,0),
|
||||
// Back
|
||||
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 0,0,1, c, 1,1),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MaxEdge.Z, 0,0,1, c, 0,1),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 0,0,1, c, 0,0),
|
||||
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MaxEdge.Z, 0,0,1, c, 1,0),
|
||||
// Front
|
||||
video::S3DVertex(box.MinEdge.X,box.MinEdge.Y,box.MinEdge.Z, 0,0,-1, c, 0,1),
|
||||
video::S3DVertex(box.MinEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 0,0,-1, c, 0,0),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MaxEdge.Y,box.MinEdge.Z, 0,0,-1, c, 1,0),
|
||||
video::S3DVertex(box.MaxEdge.X,box.MinEdge.Y,box.MinEdge.Z, 0,0,-1, c, 1,1),
|
||||
};
|
||||
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
for (u32 i=0; i<6; ++i)
|
||||
{
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
scaleMesh(anim_mesh, scale); // also recalculates bounding box
|
||||
return anim_mesh;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* createPlantMesh(v3f scale)
|
||||
{
|
||||
video::SColor c(255,255,255,255);
|
||||
video::S3DVertex vertices[16] =
|
||||
{
|
||||
// Plane 1 Front
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, 0.5,0,-0.5, c, 0,1),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, 0.5,0,-0.5, c, 0,0),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, 0.5,0,-0.5, c, 1,0),
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, 0.5,0,-0.5, c, 1,1),
|
||||
// Plane 1 Back
|
||||
video::S3DVertex(+0.5,-0.5,+0.5, -0.5,0,0.5, c, 1,1),
|
||||
video::S3DVertex(+0.5,+0.5,+0.5, -0.5,0,0.5, c, 1,0),
|
||||
video::S3DVertex(-0.5,+0.5,-0.5, -0.5,0,0.5, c, 0,0),
|
||||
video::S3DVertex(-0.5,-0.5,-0.5, -0.5,0,0.5, c, 0,1),
|
||||
|
||||
// Plane 2 Front
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, -0.5,0,-0.5, c, 1,1),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, -0.5,0,-0.5, c, 1,0),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, -0.5,0,-0.5, c, 0,0),
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, -0.5,0,-0.5, c, 0,1),
|
||||
|
||||
// Plane 2 Back
|
||||
video::S3DVertex(+0.5,-0.5,-0.5, 0.5,0,0.5, c, 0,1),
|
||||
video::S3DVertex(+0.5,+0.5,-0.5, 0.5,0,0.5, c, 0,0),
|
||||
video::S3DVertex(-0.5,+0.5,+0.5, 0.5,0,0.5, c, 1,0),
|
||||
video::S3DVertex(-0.5,-0.5,+0.5, 0.5,0,0.5, c, 1,1)
|
||||
|
||||
};
|
||||
|
||||
u16 indices[6] = {0,1,2,2,3,0};
|
||||
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
for (u32 i=0; i<4; ++i)
|
||||
{
|
||||
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
buf->append(vertices + 4 * i, 4, indices, 6);
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
|
||||
mesh->drop();
|
||||
scaleMesh(anim_mesh, scale); // also recalculates bounding box
|
||||
|
||||
21
src/mesh.h
21
src/mesh.h
@@ -30,7 +30,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
The resulting mesh has 6 materials (up, down, right, left, back, front)
|
||||
which must be defined by the caller.
|
||||
*/
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale);
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale, bool allfaces=false);
|
||||
|
||||
/*
|
||||
Create a new cube mesh not linked to mapnode size.
|
||||
Vertices are defined by given box.
|
||||
|
||||
The resulting mesh has 6 materials (up, down, right, left, back, front)
|
||||
which must be defined by the caller.
|
||||
*/
|
||||
scene::IAnimatedMesh* createCubeMesh(v3f scale,core::aabbox3d<f32> box);
|
||||
|
||||
/*
|
||||
Create a new extruded mesh from a texture.
|
||||
@@ -42,6 +51,16 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale);
|
||||
scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
|
||||
video::IVideoDriver *driver, v3f scale);
|
||||
|
||||
|
||||
/*
|
||||
Create a new plant style mesh.
|
||||
Vertices are at (+-scale.X/2, +-scale.Y/2, +-scale.Z/2).
|
||||
|
||||
The resulting mesh has 4 materials (right, left, back, front)
|
||||
which must be defined by the caller.
|
||||
*/
|
||||
scene::IAnimatedMesh* createPlantMesh(v3f scale);
|
||||
|
||||
/*
|
||||
Multiplies each vertex coordinate by the specified scaling factors
|
||||
(componentwise vector multiplication).
|
||||
|
||||
@@ -32,34 +32,74 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
NodeBox
|
||||
*/
|
||||
|
||||
void NodeBox::reset()
|
||||
{
|
||||
type = NODEBOX_REGULAR;
|
||||
// default is empty
|
||||
fixed.clear();
|
||||
// default is sign/ladder-like
|
||||
wall_top = aabb3f(-BS/2, BS/2-BS/16., -BS/2, BS/2, BS/2, BS/2);
|
||||
wall_bottom = aabb3f(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2);
|
||||
wall_side = aabb3f(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2);
|
||||
}
|
||||
|
||||
void NodeBox::serialize(std::ostream &os) const
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
writeU8(os, 1); // version
|
||||
writeU8(os, type);
|
||||
writeV3F1000(os, fixed.MinEdge);
|
||||
writeV3F1000(os, fixed.MaxEdge);
|
||||
writeV3F1000(os, wall_top.MinEdge);
|
||||
writeV3F1000(os, wall_top.MaxEdge);
|
||||
writeV3F1000(os, wall_bottom.MinEdge);
|
||||
writeV3F1000(os, wall_bottom.MaxEdge);
|
||||
writeV3F1000(os, wall_side.MinEdge);
|
||||
writeV3F1000(os, wall_side.MaxEdge);
|
||||
|
||||
if(type == NODEBOX_FIXED)
|
||||
{
|
||||
writeU16(os, fixed.size());
|
||||
for(std::vector<aabb3f>::const_iterator
|
||||
i = fixed.begin();
|
||||
i != fixed.end(); i++)
|
||||
{
|
||||
writeV3F1000(os, i->MinEdge);
|
||||
writeV3F1000(os, i->MaxEdge);
|
||||
}
|
||||
}
|
||||
else if(type == NODEBOX_WALLMOUNTED)
|
||||
{
|
||||
writeV3F1000(os, wall_top.MinEdge);
|
||||
writeV3F1000(os, wall_top.MaxEdge);
|
||||
writeV3F1000(os, wall_bottom.MinEdge);
|
||||
writeV3F1000(os, wall_bottom.MaxEdge);
|
||||
writeV3F1000(os, wall_side.MinEdge);
|
||||
writeV3F1000(os, wall_side.MaxEdge);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeBox::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 0)
|
||||
if(version != 1)
|
||||
throw SerializationError("unsupported NodeBox version");
|
||||
|
||||
reset();
|
||||
|
||||
type = (enum NodeBoxType)readU8(is);
|
||||
fixed.MinEdge = readV3F1000(is);
|
||||
fixed.MaxEdge = readV3F1000(is);
|
||||
wall_top.MinEdge = readV3F1000(is);
|
||||
wall_top.MaxEdge = readV3F1000(is);
|
||||
wall_bottom.MinEdge = readV3F1000(is);
|
||||
wall_bottom.MaxEdge = readV3F1000(is);
|
||||
wall_side.MinEdge = readV3F1000(is);
|
||||
wall_side.MaxEdge = readV3F1000(is);
|
||||
|
||||
if(type == NODEBOX_FIXED)
|
||||
{
|
||||
u16 fixed_count = readU16(is);
|
||||
while(fixed_count--)
|
||||
{
|
||||
aabb3f box;
|
||||
box.MinEdge = readV3F1000(is);
|
||||
box.MaxEdge = readV3F1000(is);
|
||||
fixed.push_back(box);
|
||||
}
|
||||
}
|
||||
else if(type == NODEBOX_WALLMOUNTED)
|
||||
{
|
||||
wall_top.MinEdge = readV3F1000(is);
|
||||
wall_top.MaxEdge = readV3F1000(is);
|
||||
wall_bottom.MinEdge = readV3F1000(is);
|
||||
wall_bottom.MaxEdge = readV3F1000(is);
|
||||
wall_side.MinEdge = readV3F1000(is);
|
||||
wall_side.MaxEdge = readV3F1000(is);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -143,6 +183,7 @@ void ContentFeatures::reset()
|
||||
liquid_viscosity = 0;
|
||||
light_source = 0;
|
||||
damage_per_second = 0;
|
||||
node_box = NodeBox();
|
||||
selection_box = NodeBox();
|
||||
material = MaterialProperties();
|
||||
// Make unknown blocks diggable
|
||||
@@ -154,7 +195,7 @@ void ContentFeatures::reset()
|
||||
|
||||
void ContentFeatures::serialize(std::ostream &os)
|
||||
{
|
||||
writeU8(os, 1); // version
|
||||
writeU8(os, 2); // version
|
||||
os<<serializeString(name);
|
||||
writeU8(os, drawtype);
|
||||
writeF1000(os, visual_scale);
|
||||
@@ -187,6 +228,7 @@ void ContentFeatures::serialize(std::ostream &os)
|
||||
writeU8(os, liquid_viscosity);
|
||||
writeU8(os, light_source);
|
||||
writeU32(os, damage_per_second);
|
||||
node_box.serialize(os);
|
||||
selection_box.serialize(os);
|
||||
material.serialize(os);
|
||||
writeU8(os, legacy_facedir_simple);
|
||||
@@ -196,7 +238,7 @@ void ContentFeatures::serialize(std::ostream &os)
|
||||
void ContentFeatures::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 1)
|
||||
if(version != 2)
|
||||
throw SerializationError("unsupported ContentFeatures version");
|
||||
name = deSerializeString(is);
|
||||
drawtype = (enum NodeDrawType)readU8(is);
|
||||
@@ -232,6 +274,7 @@ void ContentFeatures::deSerialize(std::istream &is)
|
||||
liquid_viscosity = readU8(is);
|
||||
light_source = readU8(is);
|
||||
damage_per_second = readU32(is);
|
||||
node_box.deSerialize(is);
|
||||
selection_box.deSerialize(is);
|
||||
material.deSerialize(is);
|
||||
legacy_facedir_simple = readU8(is);
|
||||
@@ -509,6 +552,7 @@ class CNodeDefManager: public IWritableNodeDefManager
|
||||
case NDT_PLANTLIKE:
|
||||
case NDT_FENCELIKE:
|
||||
case NDT_RAILLIKE:
|
||||
case NDT_NODEBOX:
|
||||
f->solidness = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ enum LiquidType
|
||||
enum NodeBoxType
|
||||
{
|
||||
NODEBOX_REGULAR, // Regular block; allows buildable_to
|
||||
NODEBOX_FIXED, // Static separately defined box
|
||||
NODEBOX_FIXED, // Static separately defined box(es)
|
||||
NODEBOX_WALLMOUNTED, // Box for wall mounted nodes; (top, bottom, side)
|
||||
};
|
||||
|
||||
@@ -71,22 +71,16 @@ struct NodeBox
|
||||
enum NodeBoxType type;
|
||||
// NODEBOX_REGULAR (no parameters)
|
||||
// NODEBOX_FIXED
|
||||
core::aabbox3d<f32> fixed;
|
||||
std::vector<aabb3f> fixed;
|
||||
// NODEBOX_WALLMOUNTED
|
||||
core::aabbox3d<f32> wall_top;
|
||||
core::aabbox3d<f32> wall_bottom;
|
||||
core::aabbox3d<f32> wall_side; // being at the -X side
|
||||
aabb3f wall_top;
|
||||
aabb3f wall_bottom;
|
||||
aabb3f wall_side; // being at the -X side
|
||||
|
||||
NodeBox():
|
||||
type(NODEBOX_REGULAR),
|
||||
// default is rail-like
|
||||
fixed(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2),
|
||||
// default is sign/ladder-like
|
||||
wall_top(-BS/2, BS/2-BS/16., -BS/2, BS/2, BS/2, BS/2),
|
||||
wall_bottom(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2),
|
||||
wall_side(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2)
|
||||
{}
|
||||
NodeBox()
|
||||
{ reset(); }
|
||||
|
||||
void reset();
|
||||
void serialize(std::ostream &os) const;
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
@@ -122,6 +116,7 @@ enum NodeDrawType
|
||||
NDT_PLANTLIKE,
|
||||
NDT_FENCELIKE,
|
||||
NDT_RAILLIKE,
|
||||
NDT_NODEBOX,
|
||||
};
|
||||
|
||||
#define CF_SPECIAL_COUNT 2
|
||||
@@ -193,6 +188,7 @@ struct ContentFeatures
|
||||
// Amount of light the node emits
|
||||
u8 light_source;
|
||||
u32 damage_per_second;
|
||||
NodeBox node_box;
|
||||
NodeBox selection_box;
|
||||
MaterialProperties material;
|
||||
// Compatibility with old maps
|
||||
|
||||
234
src/player.cpp
234
src/player.cpp
@@ -188,7 +188,8 @@ void Player::deSerialize(std::istream &is)
|
||||
LocalPlayer::LocalPlayer(IGameDef *gamedef):
|
||||
Player(gamedef),
|
||||
m_sneak_node(32767,32767,32767),
|
||||
m_sneak_node_exists(false)
|
||||
m_sneak_node_exists(false),
|
||||
m_linked(false)
|
||||
{
|
||||
// Initialize hp to 0, so that no hearts will be shown if server
|
||||
// doesn't support health points
|
||||
@@ -199,29 +200,21 @@ 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();
|
||||
v3f oldpos = position;
|
||||
v3s16 oldpos_i = floatToInt(oldpos, BS);
|
||||
|
||||
v3f old_speed = m_speed;
|
||||
|
||||
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
||||
<<oldpos_i.Z<<")"<<std::endl;*/
|
||||
|
||||
/*
|
||||
Calculate new position
|
||||
*/
|
||||
position += m_speed * dtime;
|
||||
|
||||
// Skip collision detection if a special movement mode is used
|
||||
bool free_move = g_settings->getBool("free_move");
|
||||
if(free_move)
|
||||
{
|
||||
position += m_speed * dtime;
|
||||
setPosition(position);
|
||||
return;
|
||||
}
|
||||
@@ -230,9 +223,6 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
Collision detection
|
||||
*/
|
||||
|
||||
// Player position in nodes
|
||||
v3s16 pos_i = floatToInt(position, BS);
|
||||
|
||||
/*
|
||||
Check if player is in water (the oscillating value)
|
||||
*/
|
||||
@@ -282,30 +272,12 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
is_climbing = false;
|
||||
}
|
||||
|
||||
/*
|
||||
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);
|
||||
|
||||
float player_radius = BS*0.35;
|
||||
float player_height = BS*1.7;
|
||||
|
||||
// Maximum distance over border for sneaking
|
||||
f32 sneak_max = BS*0.4;
|
||||
|
||||
/*
|
||||
If sneaking, player has larger collision radius to keep from
|
||||
falling
|
||||
*/
|
||||
/*if(control.sneak)
|
||||
player_radius = sneak_max + d*1.1;*/
|
||||
|
||||
/*
|
||||
If sneaking, keep in range from the last walked node and don't
|
||||
fall off from it
|
||||
@@ -321,23 +293,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
if(position.Y < min_y)
|
||||
{
|
||||
position.Y = min_y;
|
||||
|
||||
//v3f old_speed = m_speed;
|
||||
|
||||
if(m_speed.Y < 0)
|
||||
m_speed.Y = 0;
|
||||
|
||||
/*if(collision_info)
|
||||
{
|
||||
// Report fall collision
|
||||
if(old_speed.Y < m_speed.Y - 0.1)
|
||||
{
|
||||
CollisionInfo info;
|
||||
info.t = COLLISION_FALL;
|
||||
info.speed = m_speed.Y - old_speed.Y;
|
||||
collision_info->push_back(info);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,176 +302,31 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||
Calculate player collision box (new and old)
|
||||
*/
|
||||
core::aabbox3d<f32> playerbox(
|
||||
position.X - player_radius,
|
||||
position.Y - 0.0,
|
||||
position.Z - player_radius,
|
||||
position.X + player_radius,
|
||||
position.Y + player_height,
|
||||
position.Z + player_radius
|
||||
);
|
||||
core::aabbox3d<f32> playerbox_old(
|
||||
oldpos.X - player_radius,
|
||||
oldpos.Y - 0.0,
|
||||
oldpos.Z - player_radius,
|
||||
oldpos.X + player_radius,
|
||||
oldpos.Y + player_height,
|
||||
oldpos.Z + player_radius
|
||||
-player_radius,
|
||||
0.0,
|
||||
-player_radius,
|
||||
player_radius,
|
||||
player_height,
|
||||
player_radius
|
||||
);
|
||||
|
||||
float player_stepheight = touching_ground ? (BS*0.6) : (BS*0.2);
|
||||
|
||||
v3f accel_f = v3f(0,0,0);
|
||||
|
||||
collisionMoveResult result = collisionMoveSimple(env,
|
||||
pos_max_d, playerbox, player_stepheight, dtime,
|
||||
position, m_speed, accel_f);
|
||||
|
||||
/*
|
||||
If the player's feet touch the topside of any node, this is
|
||||
set to true.
|
||||
|
||||
Player is allowed to jump when this is true.
|
||||
*/
|
||||
touching_ground = false;
|
||||
touching_ground = result.touching_ground;
|
||||
|
||||
/*std::cout<<"Checking collisions for ("
|
||||
<<oldpos_i.X<<","<<oldpos_i.Y<<","<<oldpos_i.Z
|
||||
<<") -> ("
|
||||
<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z
|
||||
<<"):"<<std::endl;*/
|
||||
|
||||
bool standing_on_unloaded = false;
|
||||
|
||||
/*
|
||||
Go through every node around the player
|
||||
*/
|
||||
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++)
|
||||
{
|
||||
bool is_unloaded = false;
|
||||
try{
|
||||
// Player collides into walkable nodes
|
||||
if(nodemgr->get(map.getNode(v3s16(x,y,z))).walkable == false)
|
||||
continue;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
is_unloaded = true;
|
||||
// Doing nothing here will block the player from
|
||||
// walking over map borders
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
|
||||
|
||||
/*
|
||||
See if the player is touching ground.
|
||||
|
||||
Player touches ground if player's minimum Y is near node's
|
||||
maximum Y and player'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-playerbox.MinEdge.Y) < d
|
||||
fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < 0.15*BS
|
||||
&& nodebox.MaxEdge.X-d > playerbox.MinEdge.X
|
||||
&& nodebox.MinEdge.X+d < playerbox.MaxEdge.X
|
||||
&& nodebox.MaxEdge.Z-d > playerbox.MinEdge.Z
|
||||
&& nodebox.MinEdge.Z+d < playerbox.MaxEdge.Z
|
||||
){
|
||||
touching_ground = true;
|
||||
if(is_unloaded)
|
||||
standing_on_unloaded = true;
|
||||
}
|
||||
|
||||
// If player doesn't intersect with node, ignore node.
|
||||
if(playerbox.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 playermax = playerbox.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 playermin = playerbox.MinEdge.dotProduct(dirs[i]);
|
||||
f32 playermax_old = playerbox_old.MaxEdge.dotProduct(dirs[i]);
|
||||
f32 playermin_old = playerbox_old.MinEdge.dotProduct(dirs[i]);
|
||||
|
||||
/*
|
||||
Check collision for the axis.
|
||||
Collision happens when player is going through a surface.
|
||||
*/
|
||||
/*f32 neg_d = d;
|
||||
f32 pos_d = d;
|
||||
// Make it easier to get on top of a node
|
||||
if(i == 1)
|
||||
neg_d = 0.15*BS;
|
||||
bool negative_axis_collides =
|
||||
(nodemax > playermin && nodemax <= playermin_old + neg_d
|
||||
&& m_speed.dotProduct(dirs[i]) < 0);
|
||||
bool positive_axis_collides =
|
||||
(nodemin < playermax && nodemin >= playermax_old - pos_d
|
||||
&& m_speed.dotProduct(dirs[i]) > 0);*/
|
||||
bool negative_axis_collides =
|
||||
(nodemax > playermin && nodemax <= playermin_old + d
|
||||
&& m_speed.dotProduct(dirs[i]) < 0);
|
||||
bool positive_axis_collides =
|
||||
(nodemin < playermax && nodemin >= playermax_old - d
|
||||
&& m_speed.dotProduct(dirs[i]) > 0);
|
||||
bool main_axis_collides =
|
||||
negative_axis_collides || positive_axis_collides;
|
||||
|
||||
/*
|
||||
Check overlap of player 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 playermax = playerbox.MaxEdge.dotProduct(dirs[j]);
|
||||
f32 playermin = playerbox.MinEdge.dotProduct(dirs[j]);
|
||||
if(!(nodemax - d > playermin && nodemin + d < playermax))
|
||||
{
|
||||
other_axes_overlap = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If this is a collision, revert the position in the main
|
||||
direction.
|
||||
*/
|
||||
if(other_axes_overlap && main_axis_collides)
|
||||
{
|
||||
//v3f old_speed = m_speed;
|
||||
|
||||
m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
|
||||
position -= position.dotProduct(dirs[i]) * dirs[i];
|
||||
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
||||
|
||||
/*if(collision_info)
|
||||
{
|
||||
// Report fall collision
|
||||
if(old_speed.Y < m_speed.Y - 0.1)
|
||||
{
|
||||
CollisionInfo info;
|
||||
info.t = COLLISION_FALL;
|
||||
info.speed = m_speed.Y - old_speed.Y;
|
||||
collision_info->push_back(info);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
||||
} // xyz
|
||||
bool standing_on_unloaded = result.standing_on_unloaded;
|
||||
|
||||
/*
|
||||
Check the nodes under the player to see from which node the
|
||||
@@ -610,9 +422,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)
|
||||
|
||||
11
src/player.h
11
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 @@ class Player
|
||||
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,14 +232,18 @@ class LocalPlayer : public Player
|
||||
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);
|
||||
|
||||
PlayerControl control;
|
||||
|
||||
inline void Link(bool value) {
|
||||
m_linked = value;
|
||||
}
|
||||
bool m_linked;
|
||||
private:
|
||||
// This is used for determining the sneaking range
|
||||
v3s16 m_sneak_node;
|
||||
|
||||
@@ -45,6 +45,7 @@ extern "C" {
|
||||
#include "mapblock.h" // For getNodeBlockPos
|
||||
#include "content_nodemeta.h"
|
||||
#include "utility.h"
|
||||
#include "serverlinkableobject.h"
|
||||
|
||||
static void stackDump(lua_State *L, std::ostream &o)
|
||||
{
|
||||
@@ -380,6 +381,7 @@ struct EnumString es_DrawType[] =
|
||||
{NDT_PLANTLIKE, "plantlike"},
|
||||
{NDT_FENCELIKE, "fencelike"},
|
||||
{NDT_RAILLIKE, "raillike"},
|
||||
{NDT_NODEBOX, "nodebox"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
@@ -586,32 +588,93 @@ static video::SColor readARGB8(lua_State *L, int index)
|
||||
return color;
|
||||
}
|
||||
|
||||
static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
|
||||
static aabb3f read_aabb3f(lua_State *L, int index, f32 scale)
|
||||
{
|
||||
core::aabbox3d<f32> box;
|
||||
if(lua_istable(L, -1)){
|
||||
lua_rawgeti(L, -1, 1);
|
||||
aabb3f box;
|
||||
if(lua_istable(L, index)){
|
||||
lua_rawgeti(L, index, 1);
|
||||
box.MinEdge.X = lua_tonumber(L, -1) * scale;
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 2);
|
||||
lua_rawgeti(L, index, 2);
|
||||
box.MinEdge.Y = lua_tonumber(L, -1) * scale;
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 3);
|
||||
lua_rawgeti(L, index, 3);
|
||||
box.MinEdge.Z = lua_tonumber(L, -1) * scale;
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 4);
|
||||
lua_rawgeti(L, index, 4);
|
||||
box.MaxEdge.X = lua_tonumber(L, -1) * scale;
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 5);
|
||||
lua_rawgeti(L, index, 5);
|
||||
box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 6);
|
||||
lua_rawgeti(L, index, 6);
|
||||
box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
static std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale)
|
||||
{
|
||||
std::vector<aabb3f> boxes;
|
||||
if(lua_istable(L, index)){
|
||||
int n = lua_objlen(L, index);
|
||||
|
||||
// Check if it's a single box or a list of boxes
|
||||
bool possibly_single_box = (n == 6);
|
||||
for(int i = 1; i <= n && possibly_single_box; i++){
|
||||
lua_rawgeti(L, index, i);
|
||||
if(!lua_isnumber(L, -1))
|
||||
possibly_single_box = false;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
if(possibly_single_box){
|
||||
// Read a single box
|
||||
boxes.push_back(read_aabb3f(L, index, scale));
|
||||
} else {
|
||||
// Read a list of boxes
|
||||
for(int i = 1; i <= n; i++)
|
||||
{
|
||||
lua_rawgeti(L, index, i);
|
||||
boxes.push_back(read_aabb3f(L, -1, scale));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return boxes;
|
||||
}
|
||||
|
||||
static NodeBox read_nodebox(lua_State *L, int index)
|
||||
{
|
||||
NodeBox nodebox;
|
||||
if(lua_istable(L, -1)){
|
||||
nodebox.type = (NodeBoxType)getenumfield(L, index, "type",
|
||||
es_NodeBoxType, NODEBOX_REGULAR);
|
||||
|
||||
lua_getfield(L, index, "fixed");
|
||||
if(lua_istable(L, -1))
|
||||
nodebox.fixed = read_aabb3f_vector(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "wall_top");
|
||||
if(lua_istable(L, -1))
|
||||
nodebox.wall_top = read_aabb3f(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "wall_bottom");
|
||||
if(lua_istable(L, -1))
|
||||
nodebox.wall_bottom = read_aabb3f(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "wall_side");
|
||||
if(lua_istable(L, -1))
|
||||
nodebox.wall_side = read_aabb3f(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return nodebox;
|
||||
}
|
||||
|
||||
/*
|
||||
MaterialProperties
|
||||
*/
|
||||
@@ -931,33 +994,16 @@ static ContentFeatures read_content_features(lua_State *L, int index)
|
||||
f.damage_per_second = getintfield_default(L, index,
|
||||
"damage_per_second", f.damage_per_second);
|
||||
|
||||
lua_getfield(L, index, "selection_box");
|
||||
if(lua_istable(L, -1)){
|
||||
f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
|
||||
es_NodeBoxType, NODEBOX_REGULAR);
|
||||
|
||||
lua_getfield(L, -1, "fixed");
|
||||
if(lua_istable(L, -1))
|
||||
f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "wall_top");
|
||||
if(lua_istable(L, -1))
|
||||
f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "wall_bottom");
|
||||
if(lua_istable(L, -1))
|
||||
f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "wall_side");
|
||||
if(lua_istable(L, -1))
|
||||
f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_getfield(L, index, "node_box");
|
||||
if(lua_istable(L, -1))
|
||||
f.node_box = read_nodebox(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "selection_box");
|
||||
if(lua_istable(L, -1))
|
||||
f.selection_box = read_nodebox(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "material");
|
||||
if(lua_istable(L, -1)){
|
||||
f.material = read_material_properties(L, -1);
|
||||
@@ -2211,7 +2257,7 @@ class ObjectRef
|
||||
get_server(L)->SendMovePlayer(player);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// moveto(self, pos, continuous=false)
|
||||
static int l_moveto(lua_State *L)
|
||||
{
|
||||
@@ -2540,6 +2586,62 @@ class ObjectRef
|
||||
return 1;
|
||||
}
|
||||
|
||||
// link(parent, offset)
|
||||
static int l_link(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref_child = checkobject(L, 1);
|
||||
ObjectRef *ref_parent = checkobject(L, 2);
|
||||
v3f offset = checkFloatPos(L, 3);
|
||||
|
||||
ServerActiveObject *child = getobject(ref_child);
|
||||
ServerActiveObject *parent = getobject(ref_parent);
|
||||
|
||||
if ((child == NULL) || (parent == NULL)) {
|
||||
errorstream << "LUA: link(): invalid parameters" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ServerLinkableObject* child_lua = dynamic_cast<ServerLinkableObject*>(child);
|
||||
ServerLinkableObject* parent_lua = dynamic_cast<ServerLinkableObject*>(parent);
|
||||
|
||||
if (child_lua == NULL) return 0;
|
||||
if (parent_lua == NULL) return 0;
|
||||
|
||||
if (child_lua->linkEntity(parent,offset)) {
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// unlink()
|
||||
static int l_unlink(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
|
||||
ServerActiveObject *obj = getobject(ref);
|
||||
|
||||
if (obj == NULL) {
|
||||
errorstream << "LUA: unlink(): invalid parameters" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ServerLinkableObject* tolink = dynamic_cast<ServerLinkableObject*>(obj);
|
||||
|
||||
if (tolink == NULL) return 0;
|
||||
|
||||
if (tolink->unlinkEntity()) {
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
ObjectRef(ServerActiveObject *object):
|
||||
m_object(object)
|
||||
@@ -2633,6 +2735,8 @@ const luaL_reg ObjectRef::methods[] = {
|
||||
method(ObjectRef, get_look_dir),
|
||||
method(ObjectRef, get_look_pitch),
|
||||
method(ObjectRef, get_look_yaw),
|
||||
method(ObjectRef, link),
|
||||
method(ObjectRef, unlink),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
@@ -2913,6 +3017,35 @@ class EnvRef
|
||||
return 1;
|
||||
}
|
||||
|
||||
// EnvRef:get_objects_inside_radius(pos, radius)
|
||||
static int l_get_nodes_inside_radius(lua_State *L)
|
||||
{
|
||||
// Get the table insert function
|
||||
lua_getglobal(L, "table");
|
||||
lua_getfield(L, -1, "insert");
|
||||
int table_insert = lua_gettop(L);
|
||||
// Get environemnt
|
||||
EnvRef *o = checkobject(L, 1);
|
||||
ServerEnvironment *env = o->m_env;
|
||||
if(env == NULL) return 0;
|
||||
// Do it
|
||||
v3s16 pos = read_v3s16(L, 2);
|
||||
float radius = luaL_checknumber(L, 3);// * BS;
|
||||
core::list<MapNode> nodes = env->getNodesInsideRadius(pos, radius);
|
||||
lua_newtable(L);
|
||||
int table = lua_gettop(L);
|
||||
for(core::list<MapNode>::Iterator
|
||||
i = nodes.begin(); i != nodes.end(); i++){
|
||||
// Insert object reference into table
|
||||
lua_pushvalue(L, table_insert);
|
||||
lua_pushvalue(L, table);
|
||||
pushnode(L, *i, env->getGameDef()->ndef());
|
||||
if(lua_pcall(L, 2, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// EnvRef:set_timeofday(val)
|
||||
// val = 0...1
|
||||
static int l_set_timeofday(lua_State *L)
|
||||
@@ -3022,6 +3155,7 @@ const luaL_reg EnvRef::methods[] = {
|
||||
method(EnvRef, get_meta),
|
||||
method(EnvRef, get_player_by_name),
|
||||
method(EnvRef, get_objects_inside_radius),
|
||||
method(EnvRef, get_nodes_inside_radius),
|
||||
method(EnvRef, set_timeofday),
|
||||
method(EnvRef, get_timeofday),
|
||||
{0,0}
|
||||
@@ -4274,7 +4408,7 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
|
||||
|
||||
lua_getfield(L, -1, "collisionbox");
|
||||
if(lua_istable(L, -1))
|
||||
prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
|
||||
prop->collisionbox = read_aabb3f(L, -1, 1.0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
getstringfield(L, -1, "visual", prop->visual);
|
||||
|
||||
53
src/serverlinkableobject.cpp
Normal file
53
src/serverlinkableobject.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2012 sapier sapier at gmx dot net
|
||||
|
||||
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 "serverlinkableobject.h"
|
||||
|
||||
|
||||
ServerLinkableObject::ServerLinkableObject() {
|
||||
this->m_Linked = false;
|
||||
}
|
||||
|
||||
ServerLinkableObject::~ServerLinkableObject() {}
|
||||
|
||||
bool ServerLinkableObject::linkEntity(ServerActiveObject* parent,v3f offset) {
|
||||
//check if entity is in correct state
|
||||
if (this->m_Linked == true) {
|
||||
errorstream<<"ServerLinkableObject: link but object already linked!"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
this->m_Linked = true;
|
||||
|
||||
errorstream<<"ServerLinkableObject: try to send link message!"<<std::endl;
|
||||
return sendLinkMsg(parent,offset);
|
||||
}
|
||||
|
||||
bool ServerLinkableObject::unlinkEntity() {
|
||||
//check if entity is in correct state
|
||||
if (this->m_Linked == false) {
|
||||
errorstream<<"ServerLinkableObject: unlink but object not linked!"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
this->m_Linked = false;
|
||||
|
||||
errorstream<<"ServerLinkableObject: try to send unlink message!"<<std::endl;
|
||||
return sendUnlinkMsg();
|
||||
}
|
||||
62
src/serverlinkableobject.h
Normal file
62
src/serverlinkableobject.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2012 sapier sapier at gmx dot net
|
||||
|
||||
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 SERVERLINKABLEOBJECT_H_
|
||||
#define SERVERLINKABLEOBJECT_H_
|
||||
|
||||
#include <sstream>
|
||||
#include <irrlichttypes.h>
|
||||
#include "serverobject.h"
|
||||
#include "content_object.h"
|
||||
#include "log.h"
|
||||
|
||||
//this ain't the right place to define this but until cao/sao split
|
||||
//is decided it'll have to stay here
|
||||
struct AO_Message_type {
|
||||
static const u8 SetPosition = 0x00;
|
||||
static const u8 SetTextureMod = 0x01;
|
||||
static const u8 SetSprite = 0x02;
|
||||
static const u8 Punched = 0x03;
|
||||
static const u8 TakeDamage = 0x04;
|
||||
static const u8 Shoot = 0x05;
|
||||
static const u8 Link = 0x06;
|
||||
static const u8 UnLink = 0x07;
|
||||
};
|
||||
|
||||
class ServerLinkableObject {
|
||||
public:
|
||||
ServerLinkableObject();
|
||||
~ServerLinkableObject();
|
||||
|
||||
bool linkEntity(ServerActiveObject* parent,v3f offset);
|
||||
bool unlinkEntity();
|
||||
|
||||
virtual bool sendLinkMsg(ServerActiveObject* parent,v3f offset) = 0;
|
||||
virtual bool sendUnlinkMsg() = 0;
|
||||
|
||||
protected:
|
||||
inline bool isLinked() { return m_Linked; }
|
||||
|
||||
private:
|
||||
bool m_Linked;
|
||||
|
||||
};
|
||||
|
||||
#endif /* SERVERLINKABLEOBJECT_H_ */
|
||||
@@ -43,8 +43,8 @@ ServerActiveObject* ServerActiveObject::create(u8 type,
|
||||
const std::string &data)
|
||||
{
|
||||
// Find factory function
|
||||
core::map<u16, Factory>::Node *n;
|
||||
n = m_types.find(type);
|
||||
core::map<u8, Factory>::Node *n;
|
||||
n = ServerActiveObject::getTypes().find(type);
|
||||
if(n == NULL)
|
||||
{
|
||||
// If factory is not found, just return.
|
||||
@@ -58,13 +58,13 @@ ServerActiveObject* ServerActiveObject::create(u8 type,
|
||||
return object;
|
||||
}
|
||||
|
||||
void ServerActiveObject::registerType(u16 type, Factory f)
|
||||
void ServerActiveObject::registerType(u8 type, Factory f)
|
||||
{
|
||||
core::map<u16, Factory>::Node *n;
|
||||
n = m_types.find(type);
|
||||
core::map<u8, Factory>::Node *n;
|
||||
n = ServerActiveObject::getTypes().find(type);
|
||||
if(n)
|
||||
return;
|
||||
m_types.insert(type, f);
|
||||
ServerActiveObject::getTypes().insert(type, f);
|
||||
}
|
||||
|
||||
ItemStack ServerActiveObject::getWieldedItem() const
|
||||
|
||||
@@ -209,14 +209,17 @@ class ServerActiveObject : public ActiveObject
|
||||
typedef ServerActiveObject* (*Factory)
|
||||
(ServerEnvironment *env, v3f pos,
|
||||
const std::string &data);
|
||||
static void registerType(u16 type, Factory f);
|
||||
static void registerType(u8 type, Factory f);
|
||||
|
||||
ServerEnvironment *m_env;
|
||||
v3f m_base_position;
|
||||
|
||||
private:
|
||||
// Used for creating objects based on type
|
||||
static core::map<u16, Factory> m_types;
|
||||
static core::map<u8, Factory>& getTypes()
|
||||
{
|
||||
static core::map<u8, Factory> types;
|
||||
return types;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -130,6 +130,9 @@ void ServerRemotePlayer::step(float dtime, bool send_recommended)
|
||||
if(send_recommended == false)
|
||||
return;
|
||||
|
||||
if(isLinked())
|
||||
return;
|
||||
|
||||
if(m_position_not_sent)
|
||||
{
|
||||
m_position_not_sent = false;
|
||||
@@ -262,9 +265,40 @@ 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;
|
||||
}
|
||||
|
||||
bool ServerRemotePlayer::sendLinkMsg(ServerActiveObject* parent,v3f offset) {
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, 3);
|
||||
// parameters
|
||||
writeU16(os, parent->getId());
|
||||
writeV3F1000(os, offset);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), true, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServerRemotePlayer::sendUnlinkMsg() {
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, 4);
|
||||
// create message and add to list
|
||||
ActiveObjectMessage aom(getId(), true, os.str());
|
||||
m_messages_out.push_back(aom);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,13 +22,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "player.h"
|
||||
#include "serverobject.h"
|
||||
#include "collidableobject.h"
|
||||
#include "serverlinkableobject.h"
|
||||
#include "content_object.h" // Object type IDs
|
||||
|
||||
/*
|
||||
Player on the server
|
||||
*/
|
||||
|
||||
class ServerRemotePlayer : public Player, public ServerActiveObject
|
||||
class ServerRemotePlayer : public Player, public ServerActiveObject , public CollidableObject , public ServerLinkableObject
|
||||
{
|
||||
public:
|
||||
ServerRemotePlayer(ServerEnvironment *env);
|
||||
@@ -40,7 +42,7 @@ class ServerRemotePlayer : public Player, public ServerActiveObject
|
||||
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,7 +95,9 @@ class ServerRemotePlayer : public Player, public ServerActiveObject
|
||||
bool m_is_in_environment;
|
||||
// Incremented by step(), read and reset by Server
|
||||
float m_time_from_last_punch;
|
||||
|
||||
aabb3f* getCollisionBox();
|
||||
bool sendLinkMsg(ServerActiveObject* parent,v3f offset);
|
||||
bool sendUnlinkMsg();
|
||||
private:
|
||||
bool m_position_not_sent;
|
||||
};
|
||||
|
||||
149
src/test.cpp
149
src/test.cpp
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "utility.h"
|
||||
#include "serialization.h"
|
||||
#include "voxel.h"
|
||||
#include "collision.h"
|
||||
#include <sstream>
|
||||
#include "porting.h"
|
||||
#include "content_mapnode.h"
|
||||
@@ -816,6 +817,153 @@ struct TestMapSector
|
||||
};
|
||||
#endif
|
||||
|
||||
struct TestCollision
|
||||
{
|
||||
void Run()
|
||||
{
|
||||
/*
|
||||
axisAlignedCollision
|
||||
*/
|
||||
|
||||
for(s16 bx = -3; bx <= 3; bx++)
|
||||
for(s16 by = -3; by <= 3; by++)
|
||||
for(s16 bz = -3; bz <= 3; bz++)
|
||||
{
|
||||
// X-
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx-2, by, bz, bx-1, by+1, bz+1);
|
||||
v3f v(1, 0, 0);
|
||||
f32 dtime = 0;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 0);
|
||||
assert(fabs(dtime - 1.000) < 0.001);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx-2, by, bz, bx-1, by+1, bz+1);
|
||||
v3f v(-1, 0, 0);
|
||||
f32 dtime = 0;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == -1);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx-2, by+1.5, bz, bx-1, by+2.5, bz-1);
|
||||
v3f v(1, 0, 0);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == -1);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx-2, by-1.5, bz, bx-1.5, by+0.5, bz+1);
|
||||
v3f v(0.5, 0.1, 0);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 0);
|
||||
assert(fabs(dtime - 3.000) < 0.001);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx-2, by-1.5, bz, bx-1.5, by+0.5, bz+1);
|
||||
v3f v(0.5, 0.1, 0);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 0);
|
||||
assert(fabs(dtime - 3.000) < 0.001);
|
||||
}
|
||||
|
||||
// X+
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx+2, by, bz, bx+3, by+1, bz+1);
|
||||
v3f v(-1, 0, 0);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 0);
|
||||
assert(fabs(dtime - 1.000) < 0.001);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx+2, by, bz, bx+3, by+1, bz+1);
|
||||
v3f v(1, 0, 0);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == -1);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx+2, by, bz+1.5, bx+3, by+1, bz+3.5);
|
||||
v3f v(-1, 0, 0);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == -1);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx+2, by-1.5, bz, bx+2.5, by-0.5, bz+1);
|
||||
v3f v(-0.5, 0.2, 0);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 1); // Y, not X!
|
||||
assert(fabs(dtime - 2.500) < 0.001);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
|
||||
aabb3f m(bx+2, by-1.5, bz, bx+2.5, by-0.5, bz+1);
|
||||
v3f v(-0.5, 0.3, 0);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 0);
|
||||
assert(fabs(dtime - 2.000) < 0.001);
|
||||
}
|
||||
|
||||
// TODO: Y-, Y+, Z-, Z+
|
||||
|
||||
// misc
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
|
||||
aabb3f m(bx+2.3, by+2.29, bz+2.29, bx+4.2, by+4.2, bz+4.2);
|
||||
v3f v(-1./3, -1./3, -1./3);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 0);
|
||||
assert(fabs(dtime - 0.9) < 0.001);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
|
||||
aabb3f m(bx+2.29, by+2.3, bz+2.29, bx+4.2, by+4.2, bz+4.2);
|
||||
v3f v(-1./3, -1./3, -1./3);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 1);
|
||||
assert(fabs(dtime - 0.9) < 0.001);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
|
||||
aabb3f m(bx+2.29, by+2.29, bz+2.3, bx+4.2, by+4.2, bz+4.2);
|
||||
v3f v(-1./3, -1./3, -1./3);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 2);
|
||||
assert(fabs(dtime - 0.9) < 0.001);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
|
||||
aabb3f m(bx-4.2, by-4.2, bz-4.2, bx-2.3, by-2.29, bz-2.29);
|
||||
v3f v(1./7, 1./7, 1./7);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 0);
|
||||
assert(fabs(dtime - 16.1) < 0.001);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
|
||||
aabb3f m(bx-4.2, by-4.2, bz-4.2, bx-2.29, by-2.3, bz-2.29);
|
||||
v3f v(1./7, 1./7, 1./7);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 1);
|
||||
assert(fabs(dtime - 16.1) < 0.001);
|
||||
}
|
||||
{
|
||||
aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
|
||||
aabb3f m(bx-4.2, by-4.2, bz-4.2, bx-2.29, by-2.29, bz-2.3);
|
||||
v3f v(1./7, 1./7, 1./7);
|
||||
f32 dtime;
|
||||
assert(axisAlignedCollision(s, m, v, 0, dtime) == 2);
|
||||
assert(fabs(dtime - 16.1) < 0.001);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct TestSocket
|
||||
{
|
||||
void Run()
|
||||
@@ -1279,6 +1427,7 @@ void run_tests()
|
||||
TESTPARAMS(TestVoxelManipulator, ndef);
|
||||
//TEST(TestMapBlock);
|
||||
//TEST(TestMapSector);
|
||||
TEST(TestCollision);
|
||||
if(INTERNET_SIMULATOR == false){
|
||||
TEST(TestSocket);
|
||||
dout_con<<"=== BEGIN RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
|
||||
|
||||
@@ -58,6 +58,14 @@ struct AtlasPointer
|
||||
v2f size; // Size in atlas
|
||||
u16 tiled; // X-wise tiling count. If 0, width of atlas is width of image.
|
||||
|
||||
AtlasPointer():
|
||||
id(0),
|
||||
atlas(NULL),
|
||||
pos(0,0),
|
||||
size(1,1),
|
||||
tiled(1)
|
||||
{}
|
||||
|
||||
AtlasPointer(
|
||||
u16 id_,
|
||||
video::ITexture *atlas_=NULL,
|
||||
|
||||
Reference in New Issue
Block a user