diff --git a/data/clienttextures/smoke_puff.png b/data/clienttextures/smoke_puff.png new file mode 100644 index 000000000..e346d204c Binary files /dev/null and b/data/clienttextures/smoke_puff.png differ diff --git a/data/mods/experimental/init.lua b/data/mods/experimental/init.lua index 76b787031..1ee3fdc2e 100644 --- a/data/mods/experimental/init.lua +++ b/data/mods/experimental/init.lua @@ -378,10 +378,9 @@ minetest.register_alias("TNT", "experimental:tnt") -- The dummyball! -- -minetest.register_alias("dummyball", "experimental:dummyball") - minetest.register_entity("experimental:dummyball", { -- Static definition + hp_max = 20, physical = false, collisionbox = {-0.4,-0.4,-0.4, 0.4,0.4,0.4}, visual = "sprite", @@ -419,6 +418,32 @@ minetest.register_entity("experimental:dummyball", { end, }) +minetest.register_on_chat_message(function(name, message) + local cmd = "/dummyball" + if message:sub(0, #cmd) == cmd then + if not minetest.get_player_privs(name)["give"] then + minetest.chat_send_player(name, "you don't have permission to spawn (give)") + return true -- Handled chat message + end + if not minetest.get_player_privs(name)["interact"] then + minetest.chat_send_player(name, "you don't have permission to interact") + return true -- Handled chat message + end + local player = minetest.env:get_player_by_name(name) + if player == nil then + print("Unable to spawn entity, player is nil") + return true -- Handled chat message + end + local entityname = "experimental:dummyball" + local p = player:getpos() + p.y = p.y + 1 + minetest.env:add_entity(p, entityname) + minetest.chat_send_player(name, '"'..entityname + ..'" spawned.'); + return true -- Handled chat message + end +end) + -- -- A test entity for testing animated and yaw-modulated sprites -- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 860722712..d72128e01 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -157,6 +157,7 @@ endif() # Client sources set(minetest_SRCS ${common_SRCS} + content_cso.cpp content_mapblock.cpp content_cao.cpp mesh.cpp diff --git a/src/clientsimpleobject.h b/src/clientsimpleobject.h new file mode 100644 index 000000000..ad0abfe3c --- /dev/null +++ b/src/clientsimpleobject.h @@ -0,0 +1,38 @@ +/* +Minetest-c55 +Copyright (C) 2012 celeron55, Perttu Ahola + +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 CLIENTSIMPLEOBJECT_HEADER +#define CLIENTSIMPLEOBJECT_HEADER + +#include "irrlichttypes.h" +class ClientEnvironment; + +class ClientSimpleObject +{ +protected: +public: + bool m_to_be_removed; + + ClientSimpleObject(): m_to_be_removed(false) {} + virtual ~ClientSimpleObject(){} + virtual void step(float dtime){} +}; + +#endif + diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 01f13df4e..3aba4c7cb 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "utility.h" // For IntervalLimiter #include "itemdef.h" #include "tool.h" +#include "content_cso.h" class Settings; struct ToolCapabilities; @@ -538,6 +539,7 @@ void ItemCAO::initialize(const std::string &data) class LuaEntityCAO : public ClientActiveObject { private: + scene::ISceneManager *m_smgr; core::aabbox3d m_selection_box; scene::IMeshSceneNode *m_meshnode; scene::IBillboardSceneNode *m_spritenode; @@ -562,6 +564,7 @@ private: public: LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env): ClientActiveObject(0, gamedef, env), + m_smgr(NULL), m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.), m_meshnode(NULL), m_spritenode(NULL), @@ -646,6 +649,8 @@ public: void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, IrrlichtDevice *irr) { + m_smgr = smgr; + if(m_meshnode != NULL || m_spritenode != NULL) return; @@ -701,15 +706,16 @@ public: void updateLight(u8 light_at_pos) { + bool is_visible = (m_hp != 0); u8 li = decode_light(light_at_pos); video::SColor color(255,li,li,li); if(m_meshnode){ setMeshColor(m_meshnode->getMesh(), color); - m_meshnode->setVisible(true); + m_meshnode->setVisible(is_visible); } if(m_spritenode){ m_spritenode->setColor(color); - m_spritenode->setVisible(true); + m_spritenode->setVisible(is_visible); } } @@ -947,12 +953,19 @@ public: if(result.did_punch && result.damage != 0) { - if(result.damage < m_hp) + if(result.damage < m_hp){ m_hp -= result.damage; - else + } else { m_hp = 0; + // TODO: Execute defined fast response + // As there is no definition, make a smoke puff + ClientSimpleObject *simple = createSmokePuff( + m_smgr, m_env, m_position, + m_prop->visual_size * BS); + m_env->addSimpleObject(simple); + } // TODO: Execute defined fast response - // I guess flashing is fine as of now + // Flashing shall suffice as there is no definition updateTextures("^[brighten"); m_reset_textures_timer = 0.1; } diff --git a/src/content_cso.cpp b/src/content_cso.cpp new file mode 100644 index 000000000..ce6ce0a21 --- /dev/null +++ b/src/content_cso.cpp @@ -0,0 +1,89 @@ +/* +Minetest-c55 +Copyright (C) 2012 celeron55, Perttu Ahola + +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 "content_cso.h" +#include +#include "tile.h" +#include "environment.h" +#include "gamedef.h" +#include "log.h" + +static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill, + float txs, float tys, int col, int row) +{ + video::SMaterial& material = bill->getMaterial(0); + core::matrix4& matrix = material.getTextureMatrix(0); + matrix.setTextureTranslate(txs*col, tys*row); + matrix.setTextureScale(txs, tys); +} + +class SmokePuffCSO: public ClientSimpleObject +{ + float m_age; + scene::IBillboardSceneNode *m_spritenode; +public: + SmokePuffCSO(scene::ISceneManager *smgr, + ClientEnvironment *env, v3f pos, v2f size): + m_age(0), + m_spritenode(NULL) + { + infostream<<"SmokePuffCSO: constructing"<addBillboardSceneNode( + NULL, v2f(1,1), pos, -1); + m_spritenode->setMaterialTexture(0, + env->getGameDef()->tsrc()->getTextureRaw("smoke_puff.png")); + m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false); + m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); + //m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); + m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL); + m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true); + m_spritenode->setColor(video::SColor(255,0,0,0)); + m_spritenode->setVisible(true); + m_spritenode->setSize(size); + /* Update brightness */ + u8 light = 64; + try{ + MapNode n = env->getMap().getNode(floatToInt(pos, BS)); + light = decode_light(n.getLightBlend(env->getDayNightRatio(), + env->getGameDef()->ndef())); + } + catch(InvalidPositionException &e){} + video::SColor color(255,light,light,light); + m_spritenode->setColor(color); + } + virtual ~SmokePuffCSO() + { + infostream<<"SmokePuffCSO: destructing"<remove(); + } + void step(float dtime) + { + m_age += dtime; + if(m_age > 1.0){ + m_to_be_removed = true; + } + } +}; + +ClientSimpleObject* createSmokePuff(scene::ISceneManager *smgr, + ClientEnvironment *env, v3f pos, v2f size) +{ + return new SmokePuffCSO(smgr, env, pos, size); +} + diff --git a/src/content_cso.h b/src/content_cso.h new file mode 100644 index 000000000..127107c16 --- /dev/null +++ b/src/content_cso.h @@ -0,0 +1,30 @@ +/* +Minetest-c55 +Copyright (C) 2012 celeron55, Perttu Ahola + +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 CONTENT_CSO_HEADER +#define CONTENT_CSO_HEADER + +#include "common_irrlicht.h" +#include "clientsimpleobject.h" + +ClientSimpleObject* createSmokePuff(scene::ISceneManager *smgr, + ClientEnvironment *env, v3f pos, v2f size); + +#endif + diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 568e4b1da..b04f03f26 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -381,42 +381,45 @@ void LuaEntitySAO::addedToEnvironment() { ServerActiveObject::addedToEnvironment(); - // Create entity from name and state + // Create entity from name lua_State *L = m_env->getLua(); - m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str(), - m_init_state.c_str()); + m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str()); if(m_registered){ // Get properties scriptapi_luaentity_get_properties(L, m_id, m_prop); + // Initialize HP from properties + m_hp = m_prop->hp_max; } + + // Activate entity, supplying serialized state + scriptapi_luaentity_activate(L, m_id, 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); std::string name; std::string state; s16 hp = 1; v3f velocity; float yaw = 0; - // check if version is supported - if(version == 0){ - name = deSerializeString(is); - state = deSerializeLongString(is); - } - else if(version == 1){ - name = deSerializeString(is); - state = deSerializeLongString(is); - hp = readS16(is); - velocity = readV3F1000(is); - yaw = readF1000(is); - } - else{ - return NULL; + if(data != ""){ + std::istringstream is(data, std::ios::binary); + // read version + u8 version = readU8(is); + // check if version is supported + if(version == 0){ + name = deSerializeString(is); + state = deSerializeLongString(is); + } + else if(version == 1){ + name = deSerializeString(is); + state = deSerializeLongString(is); + hp = readS16(is); + velocity = readV3F1000(is); + yaw = readF1000(is); + } } // create object infostream<<"LuaEntitySAO::create(name=\""<getLua(); diff --git a/src/environment.cpp b/src/environment.cpp index 6f1d8ff55..6a8943d12 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -1806,6 +1806,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) #ifndef SERVER +#include "clientsimpleobject.h" + /* ClientEnvironment */ @@ -1831,6 +1833,12 @@ ClientEnvironment::~ClientEnvironment() delete i.getNode()->getValue(); } + for(core::list::Iterator + i = m_simple_objects.begin(); i != m_simple_objects.end(); i++) + { + delete *i; + } + // Drop/delete map m_map->drop(); } @@ -2108,6 +2116,22 @@ void ClientEnvironment::step(float dtime) obj->updateLight(light); } } + + /* + Step and handle simple objects + */ + for(core::list::Iterator + i = m_simple_objects.begin(); i != m_simple_objects.end();) + { + ClientSimpleObject *simple = *i; + core::list::Iterator cur = i; + i++; + simple->step(dtime); + if(simple->m_to_be_removed){ + delete simple; + m_simple_objects.erase(cur); + } + } } void ClientEnvironment::updateMeshes(v3s16 blockpos) @@ -2119,6 +2143,11 @@ void ClientEnvironment::expireMeshes(bool only_daynight_diffed) { m_map->expireMeshes(only_daynight_diffed); } + +void ClientEnvironment::addSimpleObject(ClientSimpleObject *simple) +{ + m_simple_objects.push_back(simple); +} ClientActiveObject* ClientEnvironment::getActiveObject(u16 id) { diff --git a/src/environment.h b/src/environment.h index 89c9fd676..fcd16e296 100644 --- a/src/environment.h +++ b/src/environment.h @@ -356,6 +356,7 @@ private: #ifndef SERVER #include "clientobject.h" +class ClientSimpleObject; /* The client-side environment. @@ -424,6 +425,12 @@ public: } } + /* + ClientSimpleObjects + */ + + void addSimpleObject(ClientSimpleObject *simple); + /* ActiveObjects */ @@ -469,6 +476,7 @@ private: IGameDef *m_gamedef; IrrlichtDevice *m_irr; core::map m_active_objects; + core::list m_simple_objects; Queue m_client_event_queue; IntervalLimiter m_active_object_light_update_interval; IntervalLimiter m_lava_hurt_interval; diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 541baa61c..7bdf7a9f4 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -4226,8 +4226,7 @@ void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp) luaentity */ -bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name, - const std::string &staticdata) +bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name) { realitycheck(L); assert(lua_checkstack(L, 20)); @@ -4274,6 +4273,21 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name, lua_pushvalue(L, object); // Copy object to top of stack lua_settable(L, -3); + return true; +} + +void scriptapi_luaentity_activate(lua_State *L, u16 id, + const std::string &staticdata) +{ + realitycheck(L); + assert(lua_checkstack(L, 20)); + infostream<<"scriptapi_luaentity_activate: id="<