diff options
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/common_irrlicht.h | 29 | ||||
| -rw-r--r-- | src/content_cao.cpp | 149 | ||||
| -rw-r--r-- | src/content_cao.h | 40 | ||||
| -rw-r--r-- | src/content_inventory.cpp | 6 | ||||
| -rw-r--r-- | src/content_inventory.h | 2 | ||||
| -rw-r--r-- | src/content_object.h | 2 | ||||
| -rw-r--r-- | src/content_sao.cpp | 154 | ||||
| -rw-r--r-- | src/content_sao.h | 46 | ||||
| -rw-r--r-- | src/environment.cpp | 39 | ||||
| -rw-r--r-- | src/environment.h | 17 | ||||
| -rw-r--r-- | src/inventory.cpp | 4 | ||||
| -rw-r--r-- | src/irrlichttypes.h | 52 | ||||
| -rw-r--r-- | src/porting.cpp | 10 | ||||
| -rw-r--r-- | src/script.cpp | 130 | ||||
| -rw-r--r-- | src/script.h | 33 | ||||
| -rw-r--r-- | src/scriptapi.cpp | 422 | ||||
| -rw-r--r-- | src/scriptapi.h | 43 | ||||
| -rw-r--r-- | src/server.cpp | 187 | ||||
| -rw-r--r-- | src/server.h | 15 | ||||
| -rw-r--r-- | src/serverobject.cpp | 11 | ||||
| -rw-r--r-- | src/serverobject.h | 6 |
22 files changed, 1212 insertions, 187 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f75c182bd..b41fc4a6c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -94,6 +94,8 @@ configure_file( ) set(common_SRCS + scriptapi.cpp + script.cpp log.cpp content_sao.cpp mapgen.cpp diff --git a/src/common_irrlicht.h b/src/common_irrlicht.h index f4c2f76ec..379c2d15a 100644 --- a/src/common_irrlicht.h +++ b/src/common_irrlicht.h @@ -23,13 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #define endSceneX(d){d->draw2DLine(v2s32(0,0),v2s32(1,0),\ video::SColor(255,30,30,30));d->endScene();} -#include <irrTypes.h> -#include <vector2d.h> -#include <vector3d.h> -#include <irrMap.h> -#include <irrList.h> -#include <irrArray.h> -#include <aabbox3d.h> +#include "irrlichttypes.h" + #ifndef SERVER #include <SColor.h> #include <IMesh.h> @@ -43,26 +38,6 @@ video::SColor(255,30,30,30));d->endScene();} #include <IGUIElement.h> #include <IGUIEnvironment.h> #endif -using namespace irr; -typedef core::vector3df v3f; -typedef core::vector3d<s16> v3s16; -typedef core::vector3d<s32> v3s32; - -typedef core::vector2d<f32> v2f; -typedef core::vector2d<s16> v2s16; -typedef core::vector2d<s32> v2s32; -typedef core::vector2d<u32> v2u32; -typedef core::vector2d<f32> v2f32; - -#ifdef _MSC_VER - // Windows - typedef unsigned long long u64; -#else - // Posix - #include <stdint.h> - typedef uint64_t u64; - //typedef unsigned long long u64; -#endif #endif diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 6cb2cee38..157a51886 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1264,3 +1264,152 @@ void MobV2CAO::setLooks(const std::string &looks) selection_size.X); } +/* + LuaEntityCAO +*/ + +// Prototype +LuaEntityCAO proto_LuaEntityCAO; + +LuaEntityCAO::LuaEntityCAO(): + ClientActiveObject(0), + m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.), + m_node(NULL), + m_position(v3f(0,10*BS,0)) +{ + ClientActiveObject::registerType(getType(), create); +} + +LuaEntityCAO::~LuaEntityCAO() +{ +} + +ClientActiveObject* LuaEntityCAO::create() +{ + return new LuaEntityCAO(); +} + +void LuaEntityCAO::addToScene(scene::ISceneManager *smgr) +{ + if(m_node != NULL) + return; + + video::IVideoDriver* driver = smgr->getVideoDriver(); + + scene::SMesh *mesh = new scene::SMesh(); + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + video::S3DVertex vertices[4] = + { + /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/ + video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1), + video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1), + video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0), + video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0), + }; + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); + //buf->getMaterial().setTexture(0, NULL); + // Initialize with the stick texture + buf->getMaterial().setTexture + (0, driver->getTexture(getTexturePath("mese.png").c_str())); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); + m_node = smgr->addMeshSceneNode(mesh, NULL); + mesh->drop(); + // Set it to use the materials of the meshbuffers directly. + // This is needed for changing the texture in the future + m_node->setReadOnlyMaterials(true); + updateNodePos(); +} + +void LuaEntityCAO::removeFromScene() +{ + if(m_node == NULL) + return; + + m_node->remove(); + m_node = NULL; +} + +void LuaEntityCAO::updateLight(u8 light_at_pos) +{ + if(m_node == NULL) + return; + + u8 li = decode_light(light_at_pos); + video::SColor color(255,li,li,li); + setMeshVerticesColor(m_node->getMesh(), color); +} + +v3s16 LuaEntityCAO::getLightPosition() +{ + return floatToInt(m_position, BS); +} + +void LuaEntityCAO::updateNodePos() +{ + if(m_node == NULL) + return; + + m_node->setPosition(m_position); +} + +void LuaEntityCAO::step(float dtime, ClientEnvironment *env) +{ + if(m_node) + { + /*v3f rot = m_node->getRotation(); + rot.Y += dtime * 120; + m_node->setRotation(rot);*/ + LocalPlayer *player = env->getLocalPlayer(); + assert(player); + v3f rot = m_node->getRotation(); + rot.Y = 180.0 - (player->getYaw()); + m_node->setRotation(rot); + } +} + +void LuaEntityCAO::processMessage(const std::string &data) +{ + infostream<<"LuaEntityCAO: Got message"<<std::endl; + std::istringstream is(data, std::ios::binary); + // command + u8 cmd = readU8(is); + if(cmd == 0) + { + // pos + m_position = readV3F1000(is); + updateNodePos(); + } +} + +void LuaEntityCAO::initialize(const std::string &data) +{ + infostream<<"LuaEntityCAO: Got init data"<<std::endl; + + { + std::istringstream is(data, std::ios::binary); + // version + u8 version = readU8(is); + // check version + if(version != 0) + return; + // pos + m_position = readV3F1000(is); + } + + updateNodePos(); +} + + diff --git a/src/content_cao.h b/src/content_cao.h index 963e1a488..c8554e737 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -376,6 +376,46 @@ private: Settings *m_properties; }; +/* + LuaEntityCAO +*/ + +class LuaEntityCAO : public ClientActiveObject +{ +public: + LuaEntityCAO(); + virtual ~LuaEntityCAO(); + + u8 getType() const + { + return ACTIVEOBJECT_TYPE_LUAENTITY; + } + + static ClientActiveObject* create(); + + void addToScene(scene::ISceneManager *smgr); + void removeFromScene(); + void updateLight(u8 light_at_pos); + v3s16 getLightPosition(); + void updateNodePos(); + + void step(float dtime, ClientEnvironment *env); + + void processMessage(const std::string &data); + + void initialize(const std::string &data); + + core::aabbox3d<f32>* getSelectionBox() + {return &m_selection_box;} + v3f getPosition() + {return m_position;} + +private: + core::aabbox3d<f32> m_selection_box; + scene::IMeshSceneNode *m_node; + v3f m_position; +}; + #endif diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp index 413ae8505..1d5c6b355 100644 --- a/src/content_inventory.cpp +++ b/src/content_inventory.cpp @@ -80,16 +80,16 @@ std::string item_craft_get_image_name(const std::string &subname) } ServerActiveObject* item_craft_create_object(const std::string &subname, - ServerEnvironment *env, u16 id, v3f pos) + ServerEnvironment *env, v3f pos) { if(subname == "rat") { - ServerActiveObject *obj = new RatSAO(env, id, pos); + ServerActiveObject *obj = new RatSAO(env, pos); return obj; } else if(subname == "firefly") { - ServerActiveObject *obj = new FireflySAO(env, id, pos); + ServerActiveObject *obj = new FireflySAO(env, pos); return obj; } diff --git a/src/content_inventory.h b/src/content_inventory.h index 91550bb9a..9fd4cb03b 100644 --- a/src/content_inventory.h +++ b/src/content_inventory.h @@ -33,7 +33,7 @@ InventoryItem* item_material_create_cook_result(content_t content); std::string item_craft_get_image_name(const std::string &subname); ServerActiveObject* item_craft_create_object(const std::string &subname, - ServerEnvironment *env, u16 id, v3f pos); + ServerEnvironment *env, v3f pos); s16 item_craft_get_drop_count(const std::string &subname); bool item_craft_is_cookable(const std::string &subname); InventoryItem* item_craft_create_cook_result(const std::string &subname); diff --git a/src/content_object.h b/src/content_object.h index a5fea7163..f092b2789 100644 --- a/src/content_object.h +++ b/src/content_object.h @@ -27,5 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define ACTIVEOBJECT_TYPE_FIREFLY 5 #define ACTIVEOBJECT_TYPE_MOBV2 6 +#define ACTIVEOBJECT_TYPE_LUAENTITY 7 + #endif diff --git a/src/content_sao.cpp b/src/content_sao.cpp index f22637185..d51e92a8c 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -49,20 +49,20 @@ void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase) */ // Prototype -TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0)); +TestSAO proto_TestSAO(NULL, v3f(0,0,0)); -TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), +TestSAO::TestSAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), m_timer1(0), m_age(0) { ServerActiveObject::registerType(getType(), create); } -ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* TestSAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { - return new TestSAO(env, id, pos); + return new TestSAO(env, pos); } void TestSAO::step(float dtime, bool send_recommended) @@ -107,11 +107,11 @@ void TestSAO::step(float dtime, bool send_recommended) */ // Prototype -ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), ""); +ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), ""); -ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos, +ItemSAO::ItemSAO(ServerEnvironment *env, v3f pos, const std::string inventorystring): - ServerActiveObject(env, id, pos), + ServerActiveObject(env, pos), m_inventorystring(inventorystring), m_speed_f(0,0,0), m_last_sent_position(0,0,0) @@ -119,7 +119,7 @@ ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos, ServerActiveObject::registerType(getType(), create); } -ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* ItemSAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); @@ -133,7 +133,7 @@ ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos, std::string inventorystring = deSerializeString(is); infostream<<"ItemSAO::create(): Creating item \"" <<inventorystring<<"\""<<std::endl; - return new ItemSAO(env, id, pos, inventorystring); + return new ItemSAO(env, pos, inventorystring); } void ItemSAO::step(float dtime, bool send_recommended) @@ -260,10 +260,10 @@ void ItemSAO::rightClick(Player *player) */ // Prototype -RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0)); +RatSAO proto_RatSAO(NULL, v3f(0,0,0)); -RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), +RatSAO::RatSAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), m_is_active(false), m_speed_f(0,0,0) { @@ -278,7 +278,7 @@ RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos): m_touching_ground = false; } -ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* RatSAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); @@ -289,7 +289,7 @@ ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos, // check if version is supported if(version != 0) return NULL; - return new RatSAO(env, id, pos); + return new RatSAO(env, pos); } void RatSAO::step(float dtime, bool send_recommended) @@ -447,10 +447,10 @@ InventoryItem* RatSAO::createPickedUpItem() */ // Prototype -Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0)); +Oerkki1SAO proto_Oerkki1SAO(NULL, v3f(0,0,0)); -Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), +Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), m_is_active(false), m_speed_f(0,0,0) { @@ -467,7 +467,7 @@ Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos): m_after_jump_timer = 0; } -ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); @@ -478,7 +478,7 @@ ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos, // check if version is supported if(version != 0) return NULL; - Oerkki1SAO *o = new Oerkki1SAO(env, id, pos); + Oerkki1SAO *o = new Oerkki1SAO(env, pos); o->m_hp = hp; return o; } @@ -739,10 +739,10 @@ void Oerkki1SAO::doDamage(u16 d) */ // Prototype -FireflySAO proto_FireflySAO(NULL, 0, v3f(0,0,0)); +FireflySAO proto_FireflySAO(NULL, v3f(0,0,0)); -FireflySAO::FireflySAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), +FireflySAO::FireflySAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), m_is_active(false), m_speed_f(0,0,0) { @@ -757,7 +757,7 @@ FireflySAO::FireflySAO(ServerEnvironment *env, u16 id, v3f pos): m_touching_ground = false; } -ServerActiveObject* FireflySAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* FireflySAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); @@ -768,7 +768,7 @@ ServerActiveObject* FireflySAO::create(ServerEnvironment *env, u16 id, v3f pos, // check if version is supported if(version != 0) return NULL; - return new FireflySAO(env, id, pos); + return new FireflySAO(env, pos); } void FireflySAO::step(float dtime, bool send_recommended) @@ -918,11 +918,11 @@ InventoryItem* FireflySAO::createPickedUpItem() */ // Prototype -MobV2SAO proto_MobV2SAO(NULL, 0, v3f(0,0,0), NULL); +MobV2SAO proto_MobV2SAO(NULL, v3f(0,0,0), NULL); -MobV2SAO::MobV2SAO(ServerEnvironment *env, u16 id, v3f pos, +MobV2SAO::MobV2SAO(ServerEnvironment *env, v3f pos, Settings *init_properties): - ServerActiveObject(env, id, pos), + ServerActiveObject(env, pos), m_move_type("ground_nodes"), m_speed(0,0,0), m_last_sent_position(0,0,0), @@ -961,13 +961,13 @@ MobV2SAO::~MobV2SAO() delete m_properties; } -ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); Settings properties; properties.parseConfigLines(is, "MobArgsEnd"); - MobV2SAO *o = new MobV2SAO(env, id, pos, &properties); + MobV2SAO *o = new MobV2SAO(env, pos, &properties); return o; } @@ -1174,7 +1174,7 @@ void MobV2SAO::step(float dtime, bool send_recommended) properties.set("player_hit_damage", "9"); properties.set("player_hit_distance", "2"); properties.set("player_hit_interval", "1"); - ServerActiveObject *obj = new MobV2SAO(m_env, 0, + ServerActiveObject *obj = new MobV2SAO(m_env, pos, &properties); //m_env->addActiveObjectAsStatic(obj); m_env->addActiveObject(obj); @@ -1490,3 +1490,95 @@ void MobV2SAO::doDamage(u16 d) } +/* + LuaEntitySAO +*/ + +#include "scriptapi.h" + +// Prototype +LuaEntitySAO proto_LuaEntitySAO(NULL, v3f(0,0,0), "_prototype", ""); + +LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, + const std::string &name, const std::string &state): + ServerActiveObject(env, pos), + m_init_name(name), + m_init_state(state), + m_registered(false) +{ + if(env == NULL){ + ServerActiveObject::registerType(getType(), create); + return; + } +} + +LuaEntitySAO::~LuaEntitySAO() +{ + if(m_registered){ + lua_State *L = m_env->getLua(); + scriptapi_luaentity_deregister(L, m_id); + } +} + +void LuaEntitySAO::addedToEnvironment(u16 id) +{ + ServerActiveObject::addedToEnvironment(id); + + // Create entity by name and state + m_registered = true; + lua_State *L = m_env->getLua(); + scriptapi_luaentity_register(L, id, m_init_name.c_str(), m_init_state.c_str()); +} + +ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos, + const std::string &data) +{ + std::istringstream is(data, std::ios::binary); + // read version + u8 version = readU8(is); + // check if version is supported + if(version != 0) + return NULL; + // read name + std::string name = deSerializeString(is); + // read state + std::string state = deSerializeLongString(is); + // create object + infostream<<"LuaEntitySAO::create(name=\""<<name<<"\" state=\"" + <<state<<"\")"<<std::endl; + return new LuaEntitySAO(env, pos, name, state); +} + +void LuaEntitySAO::step(float dtime, bool send_recommended) +{ + if(m_registered){ + lua_State *L = m_env->getLua(); + scriptapi_luaentity_step(L, m_id, dtime, send_recommended); + } +} + +std::string LuaEntitySAO::getClientInitializationData() +{ + std::ostringstream os(std::ios::binary); + // version + writeU8(os, 0); + // pos + writeV3F1000(os, m_base_position); + return os.str(); +} + +std::string LuaEntitySAO::getStaticData() +{ + infostream<<__FUNCTION_NAME<<std::endl; + std::ostringstream os(std::ios::binary); + // version + writeU8(os, 0); + // name + os<<serializeString(m_init_name); + // state + std::string state = scriptapi_luaentity_get_state(L, m_id); + os<<serializeString(state); + return os.str(); +} + + diff --git a/src/content_sao.h b/src/content_sao.h index f0ebf4f6f..44c0b7172 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -26,10 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc., class TestSAO : public ServerActiveObject { public: - TestSAO(ServerEnvironment *env, u16 id, v3f pos); + TestSAO(ServerEnvironment *env, v3f pos); u8 getType() const {return ACTIVEOBJECT_TYPE_TEST;} - static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, + static ServerActiveObject* create(ServerEnvironment *env, v3f pos, const std::string &data); void step(float dtime, bool send_recommended); private: @@ -40,11 +40,11 @@ private: class ItemSAO : public ServerActiveObject { public: - ItemSAO(ServerEnvironment *env, u16 id, v3f pos, + ItemSAO(ServerEnvironment *env, v3f pos, const std::string inventorystring); u8 getType() const {return ACTIVEOBJECT_TYPE_ITEM;} - static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, + static ServerActiveObject* create(ServerEnvironment *env, v3f pos, const std::string &data); void step(float dtime, bool send_recommended); std::string getClientInitializationData(); @@ -62,10 +62,10 @@ private: class RatSAO : public ServerActiveObject { public: - RatSAO(ServerEnvironment *env, u16 id, v3f pos); + RatSAO(ServerEnvironment *env, v3f po
std::map<int, scene::IMesh*>::iterator
it = m_extrusion_meshes.lower_bound(maxdim);
if (it == m_extrusion_meshes.end()) {
// no viable resolution found; use largest one
it = m_extrusion_meshes.find(MAX_EXTRUSION_MESH_RESOLUTION);
sanity_check(it != m_extrusion_meshes.end());
}
scene::IMesh *mesh = it->second;
mesh->grab();
return mesh;
}
// Returns a 1x1x1 cube mesh with one meshbuffer (material) per face
// Caller must drop the returned pointer
scene::IMesh* createCube()
{
m_cube->grab();
return m_cube;
}
private:
std::map<int, scene::IMesh*> m_extrusion_meshes;
scene::IMesh *m_cube;
};
ExtrusionMeshCache *g_extrusion_mesh_cache = NULL;
WieldMeshSceneNode::WieldMeshSceneNode(
scene::ISceneNode *parent,
scene::ISceneManager *mgr,
s32 id,
bool lighting
):
scene::ISceneNode(parent, mgr, id),
m_meshnode(NULL),
m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF),
m_lighting(lighting),
m_bounding_box(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
{
m_enable_shaders = g_settings->getBool("enable_shaders");
m_anisotropic_filter = g_settings->getBool("anisotropic_filter");
m_bilinear_filter = g_settings->getBool("bilinear_filter");
m_trilinear_filter = g_settings->getBool("trilinear_filter");
// If this is the first wield mesh scene node, create a cache
// for extrusion meshes (and a cube mesh), otherwise reuse it
if (g_extrusion_mesh_cache == NULL)
g_extrusion_mesh_cache = new ExtrusionMeshCache();
else
g_extrusion_mesh_cache->grab();
// Disable bounding box culling for this scene node
// since we won't calculate the bounding box.
setAutomaticCulling(scene::EAC_OFF);
// Create the child scene node
scene::IMesh *dummymesh = g_extrusion_mesh_cache->createCube();
m_meshnode = SceneManager->addMeshSceneNode(dummymesh, this, -1);
m_meshnode->setReadOnlyMaterials(false);
m_meshnode->setVisible(false);
dummymesh->drop(); // m_meshnode grabbed it
}
WieldMeshSceneNode::~WieldMeshSceneNode()
{
sanity_check(g_extrusion_mesh_cache);
if (g_extrusion_mesh_cache->drop())
g_extrusion_mesh_cache = NULL;
}
void WieldMeshSceneNode::setCube(const TileSpec tiles[6],
v3f wield_scale, ITextureSource *tsrc)
{
scene::IMesh *cubemesh = g_extrusion_mesh_cache->createCube();
changeToMesh(cubemesh);
cubemesh->drop();
m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR);
// Customize materials
for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) {
assert(i < 6);
video::SMaterial &material = m_meshnode->getMaterial(i);
if (tiles[i].animation_frame_count == 1) {
material.setTexture(0, tiles[i].texture);
} else {
FrameSpec animation_frame = tiles[i].frames[0];
material.setTexture(0, animation_frame.texture);
}
tiles[i].applyMaterialOptions(material);
}
}
void WieldMeshSceneNode::setExtruded(const std::string &imagename,
v3f wield_scale, ITextureSource *tsrc, u8 num_frames)
{
video::ITexture *texture = tsrc->getTexture(imagename);
if (!texture) {
changeToMesh(NULL);
return;
}
core::dimension2d<u32> dim = texture->getSize();
// Detect animation texture and pull off top frame instead of using entire thing
if (num_frames > 1) {
u32 frame_height = dim.Height / num_frames;
dim = core::dimension2d<u32>(dim.Width, frame_height);
}
scene::IMesh *mesh = g_extrusion_mesh_cache->create(dim);
changeToMesh(mesh);
mesh->drop();
m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR_EXTRUDED);
// Customize material
video::SMaterial &material = m_meshnode->getMaterial(0);
material.setTexture(0, tsrc->getTextureForMesh(imagename));
material.MaterialType = m_material_type;
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
// Enable bi/trilinear filtering only for high resolution textures
if (dim.Width > 32) {
material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter);
material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter);
} else {
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.setFlag(video::EMF_TRILINEAR_FILTER, false);
}
material.setFlag(video::EMF_ANISOTROPIC_FILTER, m_anisotropic_filter);
// mipmaps cause "thin black line" artifacts
#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
material.setFlag(video::EMF_USE_MIP_MAPS, false);
#endif
#if 0
//// TODO(RealBadAngel): Reactivate when shader is added for wield items
if (m_enable_shaders)
material.setTexture(2, tsrc->getTexture("disable_img.png"));
#endif
}
void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef)
{
ITextureSource *tsrc = gamedef->getTextureSource();
IItemDefManager *idef = gamedef->getItemDefManager();
//IShaderSource *shdrsrc = gamedef->getShaderSource();
INodeDefManager *ndef = gamedef->getNodeDefManager();
const ItemDefinition &def = item.getDefinition(idef);
const ContentFeatures &f = ndef->get(def.name);
content_t id = ndef->getId(def.name);
#if 0
//// TODO(RealBadAngel): Reactivate when shader is added for wield items
if (m_enable_shaders) {
u32 shader_id = shdrsrc->getShader("nodes_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
m_material_type = shdrsrc->getShaderInfo(shader_id).material;
}
#endif
// If wield_image is defined, it overrides everything else
if (def.wield_image != "") {
setExtruded(def.wield_image, def.wield_scale, tsrc, 1);
return;
}
// Handle nodes
// See also CItemDefManager::createClientCached()
else if (def.type == ITEM_NODE) {
if (f.mesh_ptr[0]) {
// e.g. mesh nodes and nodeboxes
changeToMesh(f.mesh_ptr[0]);
// mesh_ptr[0] is pre-scaled by BS * f->visual_scale
m_meshnode->setScale(
def.wield_scale * WIELD_SCALE_FACTOR
/ (BS * f.visual_scale));
} else if (f.drawtype == NDT_AIRLIKE) {
changeToMesh(NULL);
} else if (f.drawtype == NDT_PLANTLIKE) {
setExtruded(tsrc->getTextureName(f.tiles[0].texture_id), def.wield_scale, tsrc, f.tiles[0].animation_frame_count);
} else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES) {
setCube(f.tiles, def.wield_scale, tsrc);
} else {
//// TODO: Change false in the following constructor args to
//// appropriate value when shader is added for wield items (if applicable)
MeshMakeData mesh_make_data(gamedef, false);
MapNode mesh_make_node(id, 255, 0);
mesh_make_data.fillSingleNode(&mesh_make_node);
MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0));
changeToMesh(mapblock_mesh.getMesh());
translateMesh(m_meshnode->getMesh(), v3f(-BS, -BS, -BS));
m_meshnode->setScale(
def.wield_scale * WIELD_SCALE_FACTOR
/ (BS * f.visual_scale));
}
u32 material_count = m_meshnode->getMaterialCount();
if (material_count > 6) {
errorstream << "WieldMeshSceneNode::setItem: Invalid material "
"count " << material_count << ", truncating to 6" << std::endl;
material_count = 6;
}
for (u32 i = 0; i < material_count; ++i) {
video::SMaterial &material = m_meshnode->getMaterial(i);
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter);
material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter);
bool animated = (f.tiles[i].animation_frame_count > 1);
if (animated) {
FrameSpec animation_frame = f.tiles[i].frames[0];
material.setTexture(0, animation_frame.texture);
} else {
material.setTexture(0, f.tiles[i].texture);
}
material.MaterialType = m_material_type;
#if 0
//// TODO(RealBadAngel): Reactivate when shader is added for wield items
if (m_enable_shaders) {
if (f.tiles[i].normal_texture) {
if (animated) {
FrameSpec animation_frame = f.tiles[i].frames[0];
material.setTexture(1, animation_frame.normal_texture);
} else {
material.setTexture(1, f.tiles[i].normal_texture);
}
material.setTexture(2, tsrc->getTexture("enable_img.png"));
} else {
material.setTexture(2, tsrc->getTexture("disable_img.png"));
}
}
#endif
}
return;
}
else if (def.inventory_image != "") {
setExtruded(def.inventory_image, def.wield_scale, tsrc, 1);
return;
}
// no wield mesh found
changeToMesh(NULL);
}
void WieldMeshSceneNode::setColor(video::SColor color)
{
assert(!m_lighting);
setMeshColor(m_meshnode->getMesh(), color);
}
void WieldMeshSceneNode::render()
{
// note: if this method is changed to actually do something,
// you probably should implement OnRegisterSceneNode as well
}
void WieldMeshSceneNode::changeToMesh(scene::IMesh *mesh)
{
if (mesh == NULL) {
scene::IMesh *dummymesh = g_extrusion_mesh_cache->createCube();
m_meshnode->setVisible(false);
m_meshnode->setMesh(dummymesh);
dummymesh->drop(); // m_meshnode grabbed it
} else {
if (m_lighting) {
m_meshnode->setMesh(mesh);
} else {
/*
Lighting is disabled, this means the caller can (and probably will)
call setColor later. We therefore need to clone the mesh so that
setColor will only modify this scene node's mesh, not others'.
*/
scene::IMeshManipulator *meshmanip = SceneManager->getMeshManipulator();
scene::IMesh *new_mesh = meshmanip->createMeshCopy(mesh);
m_meshnode->setMesh(new_mesh);
new_mesh->drop(); // m_meshnode grabbed it
}
}
m_meshnode->setMaterialFlag(video::EMF_LIGHTING, m_lighting);
// need to normalize normals when lighting is enabled (because of setScale())
m_meshnode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, m_lighting);
m_meshnode->setVisible(true);
}
|
