diff options
-rw-r--r-- | builtin/builtin.lua | 1 | ||||
-rw-r--r-- | builtin/falling.lua | 136 | ||||
-rw-r--r-- | builtin/item_entity.lua | 16 | ||||
-rw-r--r-- | builtin/misc_register.lua | 2 | ||||
-rw-r--r-- | doc/lua_api.txt | 9 | ||||
-rw-r--r-- | games/minimal/mods/default/init.lua | 79 | ||||
-rw-r--r-- | src/content_cao.cpp | 30 | ||||
-rw-r--r-- | src/content_mapblock.cpp | 16 | ||||
-rw-r--r-- | src/content_sao.cpp | 10 | ||||
-rw-r--r-- | src/content_sao.h | 4 | ||||
-rw-r--r-- | src/environment.cpp | 40 | ||||
-rw-r--r-- | src/environment.h | 4 | ||||
-rw-r--r-- | src/mapgen.cpp | 2 | ||||
-rw-r--r-- | src/mesh.cpp | 3 | ||||
-rw-r--r-- | src/noise.cpp | 2 | ||||
-rw-r--r-- | src/scriptapi.cpp | 24 | ||||
-rw-r--r-- | src/scriptapi.h | 2 | ||||
-rw-r--r-- | src/serverobject.h | 2 | ||||
-rw-r--r-- | src/tile.cpp | 40 |
19 files changed, 288 insertions, 134 deletions
diff --git a/builtin/builtin.lua b/builtin/builtin.lua index a17841fc8..f2811fa9c 100644 --- a/builtin/builtin.lua +++ b/builtin/builtin.lua @@ -22,4 +22,5 @@ dofile(minetest.get_modpath("__builtin").."/auth.lua") dofile(minetest.get_modpath("__builtin").."/chatcommands.lua") dofile(minetest.get_modpath("__builtin").."/static_spawn.lua") dofile(minetest.get_modpath("__builtin").."/detached_inventory.lua") +dofile(minetest.get_modpath("__builtin").."/falling.lua") diff --git a/builtin/falling.lua b/builtin/falling.lua new file mode 100644 index 000000000..4a7f4167e --- /dev/null +++ b/builtin/falling.lua @@ -0,0 +1,136 @@ +-- Minetest: builtin/item.lua + +-- +-- Falling stuff +-- + +minetest.register_entity("__builtin:falling_node", { + initial_properties = { + physical = true, + collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, + visual = "wielditem", + textures = {}, + visual_size = {x=0.667, y=0.667}, + }, + + nodename = "", + + set_node = function(self, nodename) + self.nodename = nodename + local stack = ItemStack(nodename) + local itemtable = stack:to_table() + local itemname = nil + if itemtable then + itemname = stack:to_table().name + end + local item_texture = nil + local item_type = "" + if minetest.registered_items[itemname] then + item_texture = minetest.registered_items[itemname].inventory_image + item_type = minetest.registered_items[itemname].type + end + prop = { + is_visible = true, + textures = {nodename}, + } + self.object:set_properties(prop) + end, + + get_staticdata = function(self) + return self.nodename + end, + + on_activate = function(self, staticdata) + self.nodename = staticdata + self.object:set_armor_groups({immortal=1}) + --self.object:setacceleration({x=0, y=-10, z=0}) + self:set_node(self.nodename) + end, + + on_step = function(self, dtime) + -- Set gravity + self.object:setacceleration({x=0, y=-10, z=0}) + -- Turn to actual sand when collides to ground or just move + local pos = self.object:getpos() + local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point + local bcn = minetest.env:get_node(bcp) + -- Note: walkable is in the node definition, not in item groups + if minetest.registered_nodes[bcn.name] and + minetest.registered_nodes[bcn.name].walkable then + local np = {x=bcp.x, y=bcp.y+1, z=bcp.z} + -- Check what's here + local n2 = minetest.env:get_node(np) + -- If it's not air or liquid, remove node and replace it with + -- it's drops + if n2.name ~= "air" and (not minetest.registered_nodes[n2.name] or + minetest.registered_nodes[n2.name].liquidtype == "none") then + local drops = minetest.get_node_drops(n2.name, "") + minetest.env:remove_node(np) + -- Add dropped items + local _, dropped_item + for _, dropped_item in ipairs(drops) do + minetest.env:add_item(np, dropped_item) + end + -- Run script hook + local _, callback + for _, callback in ipairs(minetest.registered_on_dignodes) do + callback(np, n2, nil) + end + end + -- Create node and remove entity + minetest.env:add_node(np, {name=self.nodename}) + self.object:remove() + else + -- Do nothing + end + end +}) + +function spawn_falling_node(p, nodename) + obj = minetest.env:add_entity(p, "__builtin:falling_node") + obj:get_luaentity():set_node(nodename) +end + +-- +-- Some common functions +-- + +function nodeupdate_single(p) + n = minetest.env:get_node(p) + if minetest.get_node_group(n.name, "falling_node") ~= 0 then + p_bottom = {x=p.x, y=p.y-1, z=p.z} + n_bottom = minetest.env:get_node(p_bottom) + -- Note: walkable is in the node definition, not in item groups + if minetest.registered_nodes[n_bottom.name] and + not minetest.registered_nodes[n_bottom.name].walkable then + minetest.env:remove_node(p) + spawn_falling_node(p, n.name) + nodeupdate(p) + end + end +end + +function nodeupdate(p) + for x = -1,1 do + for y = -1,1 do + for z = -1,1 do + p2 = {x=p.x+x, y=p.y+y, z=p.z+z} + nodeupdate_single(p2) + end + end + end +end + +-- +-- Global callbacks +-- + +function on_placenode(p, node) + nodeupdate(p) +end +minetest.register_on_placenode(on_placenode) + +function on_dignode(p, node) + nodeupdate(p) +end +minetest.register_on_dignode(on_dignode) diff --git a/builtin/item_entity.lua b/builtin/item_entity.lua index 2d763d50b..2b12764f1 100644 --- a/builtin/item_entity.lua +++ b/builtin/item_entity.lua @@ -57,11 +57,23 @@ minetest.register_entity("__builtin:item", { end, get_staticdata = function(self) - return self.itemstring + --return self.itemstring + return minetest.serialize({ + itemstring = self.itemstring, + always_collect = self.always_collect, + }) end, on_activate = function(self, staticdata) - self.itemstring = staticdata + if string.sub(staticdata, 1, string.len("return")) == "return" then + local data = minetest.deserialize(staticdata) + if data and type(data) == "table" then + self.itemstring = data.itemstring + self.always_collect = data.always_collect + end + else + self.itemstring = staticdata + end self.object:set_armor_groups({immortal=1}) self.object:setvelocity({x=0, y=2, z=0}) self.object:setacceleration({x=0, y=-10, z=0}) diff --git a/builtin/misc_register.lua b/builtin/misc_register.lua index 4894e71bc..77c594de2 100644 --- a/builtin/misc_register.lua +++ b/builtin/misc_register.lua @@ -259,6 +259,7 @@ minetest.register_node(":air", { diggable = false, buildable_to = true, air_equivalent = true, + drop = "", groups = {not_in_creative_inventory=1}, }) @@ -274,6 +275,7 @@ minetest.register_node(":ignore", { diggable = false, buildable_to = true, -- A way to remove accidentally placed ignores air_equivalent = true, + drop = "", groups = {not_in_creative_inventory=1}, }) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 36dd6b2aa..301832618 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -456,6 +456,7 @@ Special groups - disable_jump: Player (and possibly other things) cannot jump from node - fall_damage_add_percent: damage speed = speed * (1 + value/100) - bouncy: value is bounce speed in percent +- falling_node: if there is no walkable block under the node it will fall Known damage and digging time defining groups ---------------------------------------------- @@ -1087,6 +1088,7 @@ methods: - punch(puncher, time_from_last_punch, tool_capabilities, direction) ^ puncher = an another ObjectRef, ^ time_from_last_punch = time since last punch action of the puncher + ^ direction: can be nil - right_click(clicker); clicker = an another ObjectRef - get_hp(): returns number of hitpoints (2 * number of hearts) - set_hp(hp): set number of hitpoints (2 * number of hearts) @@ -1236,7 +1238,7 @@ Entity definition (register_entity) initial_properties = <initial object properties>, - on_activate = function(self, staticdata), + on_activate = function(self, staticdata, dtime_s), on_step = function(self, dtime), on_punch = function(self, hitter), on_rightclick = function(self, clicker), @@ -1422,6 +1424,11 @@ Node definition (register_node) on_metadata_inventory_take = func(pos, listname, index, stack, player), ^ Called after the actual action has happened, according to what was allowed. ^ No return value + + on_blast = func(pos, intensity), + ^ intensity: 1.0 = mid range of regular TNT + ^ If defined, called when an explosion touches the node, instead of + removing the node } Recipe for register_craft: (shaped) diff --git a/games/minimal/mods/default/init.lua b/games/minimal/mods/default/init.lua index 176fe899b..5f4d8e063 100644 --- a/games/minimal/mods/default/init.lua +++ b/games/minimal/mods/default/init.lua @@ -769,7 +769,7 @@ minetest.register_node("default:sand", { description = "Sand", tiles ={"default_sand.png"}, is_ground_content = true, - groups = {crumbly=3}, + groups = {crumbly=3, falling_node=1}, sounds = default.node_sound_sand_defaults(), }) @@ -777,7 +777,7 @@ minetest.register_node("default:gravel", { description = "Gravel", tiles ={"default_gravel.png"}, is_ground_content = true, - groups = {crumbly=2}, + groups = {crumbly=2, falling_node=1}, sounds = default.node_sound_dirt_defaults({ footstep = {name="default_gravel_footstep", gain=0.45}, }), @@ -1586,73 +1586,22 @@ minetest.register_alias("mapgen_stone_with_coal", "default:stone_with_coal") minetest.register_alias("mapgen_stone_with_iron", "default:stone_with_iron") minetest.register_alias("mapgen_mese", "default:mese") --- --- Some common functions --- - -default.falling_node_names = {} - -function nodeupdate_single(p) - n = minetest.env:get_node(p) - if default.falling_node_names[n.name] ~= nil then - p_bottom = {x=p.x, y=p.y-1, z=p.z} - n_bottom = minetest.env:get_node(p_bottom) - if n_bottom.name == "air" then - minetest.env:remove_node(p) - minetest.env:add_entity(p, "default:falling_"..n.name) - nodeupdate(p) - end - end -end - -function nodeupdate(p) - for x = -1,1 do - for y = -1,1 do - for z = -1,1 do - p2 = {x=p.x+x, y=p.y+y, z=p.z+z} - nodeupdate_single(p2) - end - end - end +-- Support old code +function default.spawn_falling_node(p, nodename) + spawn_falling_node(p, nodename) end --- --- Falling stuff --- - +-- Horrible crap to support old code +-- Don't use this and never do what this does, it's completely wrong! +-- (More specifically, the client and the C++ code doesn't get the group) function default.register_falling_node(nodename, texture) - default.falling_node_names[nodename] = true - -- Override naming conventions for stuff like :default:falling_default:sand - minetest.register_entity(":default:falling_"..nodename, { - -- Static definition - physical = true, - collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, - visual = "cube", - textures = {texture,texture,texture,texture,texture,texture}, - -- State - -- Methods - on_step = function(self, dtime) - -- Set gravity - self.object:setacceleration({x=0, y=-10, z=0}) - -- Turn to actual sand when collides to ground or just move - local pos = self.object:getpos() - local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point - local bcn = minetest.env:get_node(bcp) - if bcn.name ~= "air" then - -- Turn to a sand node - local np = {x=bcp.x, y=bcp.y+1, z=bcp.z} - minetest.env:add_node(np, {name=nodename}) - self.object:remove() - else - -- Do nothing - end - end - }) + minetest.log("error", debug.traceback()) + minetest.log('error', "WARNING: default.register_falling_node is deprecated") + if minetest.registered_nodes[nodename] then + minetest.registered_nodes[nodename].groups.falling_node = 1 + end end -default.register_falling_node("default:sand", "default_sand.png") -default.register_falling_node("default:gravel", "default_gravel.png") - -- -- Global callbacks -- @@ -1665,13 +1614,11 @@ minetest.register_globalstep(on_step) function on_placenode(p, node) --print("on_placenode") - nodeupdate(p) end minetest.register_on_placenode(on_placenode) function on_dignode(p, node) --print("on_dignode") - nodeupdate(p) end minetest.register_on_dignode(on_dignode) diff --git a/src/content_cao.cpp b/src/content_cao.cpp index aa5c2d674..cb14cf395 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/serialize.h" #include "util/mathconstants.h" #include "map.h" +#include <IMeshManipulator.h> class Settings; struct ToolCapabilities; @@ -797,8 +798,15 @@ public: infostream<<"textures[0]: "<<m_prop.textures[0]<<std::endl; IItemDefManager *idef = m_gamedef->idef(); ItemStack item(m_prop.textures[0], 1, 0, "", idef); - scene::IMesh *mesh = item.getDefinition(idef).wield_mesh; + scene::IMesh *item_mesh = item.getDefinition(idef).wield_mesh; + + // Copy mesh to be able to set unique vertex colors + scene::IMeshManipulator *manip = + irr->getVideoDriver()->getMeshManipulator(); + scene::IMesh *mesh = manip->createMeshUniquePrimitives(item_mesh); + m_meshnode = smgr->addMeshSceneNode(mesh, NULL); + mesh->drop(); m_meshnode->setScale(v3f(m_prop.visual_size.X/2, m_prop.visual_size.Y/2, @@ -838,15 +846,17 @@ public: { bool is_visible = (m_hp != 0); u8 li = decode_light(light_at_pos); - m_last_light = li; - video::SColor color(255,li,li,li); - if(m_meshnode){ - setMeshColor(m_meshnode->getMesh(), color); - m_meshnode->setVisible(is_visible); - } - if(m_spritenode){ - m_spritenode->setColor(color); - m_spritenode->setVisible(is_visible); + if(li != m_last_light){ + m_last_light = li; + video::SColor color(255,li,li,li); + if(m_meshnode){ + setMeshColor(m_meshnode->getMesh(), color); + m_meshnode->setVisible(is_visible); + } + if(m_spritenode){ + m_spritenode->setColor(color); + m_spritenode->setVisible(is_visible); + } } } diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index ad819e793..ff8ef5276 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -492,15 +492,15 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // -Z towards +Z, thus the direction is +Z. // Rotate texture to make animation go in flow direction // Positive if liquid moves towards +Z - int dz = (corner_levels[side_corners[2][0]] + - corner_levels[side_corners[2][1]] < - corner_levels[side_corners[3][0]] + - corner_levels[side_corners[3][1]]); + int dz = (corner_levels[side_corners[3][0]] + + corner_levels[side_corners[3][1]]) - + (corner_levels[side_corners[2][0]] + + corner_levels[side_corners[2][1]]); // Positive if liquid moves towards +X - int dx = (corner_levels[side_corners[0][0]] + - corner_levels[side_corners[0][1]] < - corner_levels[side_corners[1][0]] + - corner_levels[side_corners[1][1]]); + int dx = (corner_levels[side_corners[1][0]] + + corner_levels[side_corners[1][1]]) - + (corner_levels[side_corners[0][0]] + + corner_levels[side_corners[0][1]]); // -X if(-dx >= abs(dz)) { diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 843ab29f7..7526e0353 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -376,9 +376,9 @@ LuaEntitySAO::~LuaEntitySAO() } } -void LuaEntitySAO::addedToEnvironment() +void LuaEntitySAO::addedToEnvironment(u32 dtime_s) { - ServerActiveObject::addedToEnvironment(); + ServerActiveObject::addedToEnvironment(dtime_s); // Create entity from name lua_State *L = m_env->getLua(); @@ -390,7 +390,7 @@ void LuaEntitySAO::addedToEnvironment() // 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()); + scriptapi_luaentity_activate(L, m_id, m_init_state.c_str(), dtime_s); } } @@ -805,9 +805,9 @@ std::string PlayerSAO::getDescription() } // Called after id has been set and has been inserted in environment -void PlayerSAO::addedToEnvironment() +void PlayerSAO::addedToEnvironment(u32 dtime_s) { - ServerActiveObject::addedToEnvironment(); + ServerActiveObject::addedToEnvironment(dtime_s); ServerActiveObject::setBasePosition(m_player->getPosition()); m_player->setPlayerSAO(this); m_player->peer_id = m_peer_id; diff --git a/src/content_sao.h b/src/content_sao.h index ff427bac6..05c77e2cb 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -43,7 +43,7 @@ public: { return ACTIVEOBJECT_TYPE_LUAENTITY; } u8 getSendType() const { return ACTIVEOBJECT_TYPE_GENERIC; } - virtual void addedToEnvironment(); + virtual void addedToEnvironment(u32 dtime_s); static ServerActiveObject* create(ServerEnvironment *env, v3f pos, const std::string &data); void step(float dtime, bool send_recommended); @@ -118,7 +118,7 @@ public: Active object <-> environment interface */ - void addedToEnvironment(); + void addedToEnvironment(u32 dtime_s); void removingFromEnvironment(); bool isStaticAllowed() const; bool unlimitedTransferDistance() const; diff --git a/src/environment.cpp b/src/environment.cpp index a49a5e384..4abba6359 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -743,19 +743,25 @@ neighbor_found: u32 active_object_count = block->m_static_objects.m_active.size(); // Find out how many objects this and all the neighbors contain u32 active_object_count_wider = 0; + u32 wider_unknown_count = 0; for(s16 x=-1; x<=1; x++) for(s16 y=-1; y<=1; y++) for(s16 z=-1; z<=1; z++) { MapBlock *block2 = map->getBlockNoCreateNoEx( block->getPos() + v3s16(x,y,z)); - if(block2==NULL) + if(block2==NULL){ + wider_unknown_count = 0; continue; + } active_object_count_wider += block2->m_static_objects.m_active.size() + block2->m_static_objects.m_stored.size(); } - + // Extrapolate + u32 wider_known_count = 3*3*3 - wider_unknown_count; + active_object_count_wider += wider_unknown_count * active_object_count_wider / wider_known_count; + // Call all the trigger variations i->abm->trigger(m_env, p, n); i->abm->trigger(m_env, p, n, @@ -784,7 +790,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) <<dtime_s<<" seconds old."<<std::endl;*/ // Activate stored objects - activateObjects(block); + activateObjects(block, dtime_s); // Run node timers std::map<v3s16, NodeTimer> elapsed_timers = @@ -1243,7 +1249,7 @@ u16 getFreeServerActiveObjectId( u16 ServerEnvironment::addActiveObject(ServerActiveObject *object) { assert(object); - u16 id = addActiveObjectRaw(object, true); + u16 id = addActiveObjectRaw(object, true, 0); return id; } @@ -1402,7 +1408,7 @@ ActiveObjectMessage ServerEnvironment::getActiveObjectMessage() */ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, - bool set_changed) + bool set_changed, u32 dtime_s) { assert(object); if(object->getId() == 0){ @@ -1442,7 +1448,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, // Register reference in scripting api (must be done before post-init) scriptapi_add_object_reference(m_lua, object); // Post-initialize object - object->addedToEnvironment(); + object->addedToEnvironment(dtime_s); // Add static data to block if(object->isStaticAllowed()) @@ -1465,9 +1471,10 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, "addActiveObjectRaw"); } else{ + v3s16 p = floatToInt(objectpos, BS); errorstream<<"ServerEnvironment::addActiveObjectRaw(): " <<"could not find block for storing id="<<object->getId() - <<" statically"<<std::endl; + <<" statically (pos="<<PP(p)<<")"<<std::endl; } } @@ -1578,7 +1585,7 @@ static void print_hexdump(std::ostream &o, const std::string &data) /* Convert stored objects from blocks near the players to active. */ -void ServerEnvironment::activateObjects(MapBlock *block) +void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) { if(block==NULL) return; @@ -1602,7 +1609,7 @@ void ServerEnvironment::activateObjects(MapBlock *block) "large amount of objects"); return; } - // A list for objects that couldn't be converted to static for some + // A list for objects that couldn't be converted to active for some // reason. They will be stored back. core::list<StaticObject> new_stored; // Loop through stored static objects @@ -1632,7 +1639,7 @@ void ServerEnvironment::activateObjects(MapBlock *block) <<"activated static object pos="<<PP(s_obj.pos/BS) <<" type="<<(int)s_obj.type<<std::endl; // This will also add the object to the active static list - addActiveObjectRaw(obj, false); + addActiveObjectRaw(obj, false, dtime_s); } // Clear stored list block->m_static_objects.m_stored.clear(); @@ -1756,7 +1763,12 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) // Add to the block where the object is located in v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); // Get or generate the block - MapBlock *block = m_map->emergeBlock(blockpos); + MapBlock *block = NULL; + try{ + block = m_map->emergeBlock(blockpos); + } catch(InvalidPositionException &e){ + // Handled via NULL pointer + } if(block) { @@ -1793,9 +1805,10 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) } else{ if(!force_delete){ + v3s16 p = floatToInt(objectpos, BS); errorstream<<"ServerEnv: Could not find or generate " <<"a block for storing id="<<obj->getId() - <<" statically"<<std::endl; + <<" statically (pos="<<PP(p)<<")"<<std::endl; continue; } } @@ -2129,6 +2142,7 @@ void ClientEnvironment::step(float dtime) Step active objects and update lighting of them */ + bool update_lighting = m_active_object_light_update_interval.step(dtime, 0.21); for(core::map<u16, ClientActiveObject*>::Iterator i = m_active_objects.getIterator(); i.atEnd()==false; i++) @@ -2137,7 +2151,7 @@ void ClientEnvironment::step(float dtime) // Step object obj->step(dtime, this); - if(m_active_object_light_update_interval.step(dtime, 0.21)) + if(update_lighting) { // Update lighting u8 light = 0; diff --git a/src/environment.h b/src/environment.h index bb1da2461..042229038 100644 --- a/src/environment.h +++ b/src/environment.h @@ -312,7 +312,7 @@ private: Returns the id of the object. Returns 0 if not added and thus deleted. */ - u16 addActiveObjectRaw(ServerActiveObject *object, bool set_changed); + u16 addActiveObjectRaw(ServerActiveObject *object, bool set_changed, u32 dtime_s); /* Remove all objects that satisfy (m_removed && m_known_by_count==0) @@ -322,7 +322,7 @@ private: /* Convert stored objects from block to active */ - void activateObjects(MapBlock *block); + void activateObjects(MapBlock *block, u32 dtime_s); /* Convert objects that are not in active blocks to static. diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 67e92f449..77b133020 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -1228,7 +1228,7 @@ double base_rock_level_2d(u64 seed, v2s16 p) 0.5+(float)p.X/125., 0.5+(float)p.Y/125., seed-932, 5, 0.7); b = rangelim(b, 0.0, 1000.0); - b = pow(b, 7); + b = b*b*b*b*b*b*b; b *= 5; b = rangelim(b, 0.5, 1000.0); // Values 1.5...100 give quite horrible looking slopes diff --git a/src/mesh.cpp b/src/mesh.cpp index 0f075f72b..b9ec82e18 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -433,6 +433,9 @@ video::ITexture *generateTextureFromMesh(scene::IMesh *mesh, } // Create render target texture + video::ITexture *oldtexture = driver->findTexture(texture_name.c_str()); + if(oldtexture) + driver->removeTexture(oldtexture); video::ITexture *rtt = driver->addRenderTargetTexture( dim, texture_name.c_str(), video::ECF_A8R8G8B8); if(rtt == NULL) diff --git a/src/noise.cpp b/src/noise.cpp index 4a7fc87e7..e75fbf4bd 100644 --- a/src/noise.cpp +++ b/src/noise.cpp @@ -37,7 +37,7 @@ double dotProduct(double vx, double vy, double wx, double wy){ } double easeCurve(double t){ - return 6*pow(t,5)-15*pow(t,4)+10*pow(t,3); + return t * t * t * (6. * t * t - 15. * t + 10.); } double linearInterpolation(double x0, double x1, double t){ diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index e87c35482..09900ce1f 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -2543,7 +2543,7 @@ private: return 0; } - // punch(self, puncher, tool_capabilities, direction, time_from_last_punch) + // punch(self, puncher, time_from_last_punch, tool_capabilities, dir) static int l_punch(lua_State *L) { ObjectRef *ref = checkobject(L, 1); @@ -2552,13 +2552,18 @@ private: ServerActiveObject *puncher = getobject(puncher_ref); if(co == NULL) return 0; if(puncher == NULL) return 0; - ToolCapabilities toolcap = read_tool_capabilities(L, 3); - v3f dir = read_v3f(L, 4); + v3f dir; + if(lua_type(L, 5) != LUA_TTABLE) + dir = co->getBasePosition() - puncher->getBasePosition(); + else + dir = read_v3f(L, 5); float time_from_last_punch = 1000000; - if(lua_isnumber(L, 5)) - time_from_last_punch = lua_tonumber(L, 5); + if(lua_isnumber(L, 3)) + time_from_last_punch = lua_tonumber(L, 3); + ToolCapabilities toolcap = read_tool_capabilities(L, 4); + dir.normalize(); // Do it - puncher->punch(dir, &toolcap, puncher, time_from_last_punch); + co->punch(dir, &toolcap, puncher, time_from_last_punch); return 0; } @@ -6479,7 +6484,7 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name) } void scriptapi_luaentity_activate(lua_State *L, u16 id, - const std::string &staticdata) + const std::string &staticdata, u32 dtime_s) { realitycheck(L); assert(lua_checkstack(L, 20)); @@ -6497,8 +6502,9 @@ void scriptapi_luaentity_activate(lua_State *L, u16 id, luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self lua_pushlstring(L, staticdata.c_str(), staticdata.size()); - // Call with 2 arguments, 0 results - if(lua_pcall(L, 2, 0, 0)) + lua_pushinteger(L, dtime_s); + // Call with 3 arguments, 0 results + if(lua_pcall(L, 3, 0, 0)) script_error(L, "error running function on_activate: %s\n", lua_tostring(L, -1)); } diff --git a/src/scriptapi.h b/src/scriptapi.h index 0ae359112..144cb3bc6 100644 --- a/src/scriptapi.h +++ b/src/scriptapi.h @@ -167,7 +167,7 @@ void scriptapi_detached_inventory_on_take(lua_State *L, // Returns true if succesfully added into Lua; false otherwise. bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name); void scriptapi_luaentity_activate(lua_State *L, u16 id, - const std::string &staticdata); + const std::string &staticdata, u32 dtime_s); void scriptapi_luaentity_rm(lua_State *L, u16 id); std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id); void scriptapi_luaentity_get_properties(lua_State *L, u16 id, diff --git a/src/serverobject.h b/src/serverobject.h index 6acd0dfee..ece53fd98 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -62,7 +62,7 @@ public: { return getType(); } // Called after id has been set and has been inserted in environment - virtual void addedToEnvironment(){}; + virtual void addedToEnvironment(u32 dtime_s){}; // Called before removing from environment virtual void removingFromEnvironment(){}; // Returns true if object's deletion is the job of the diff --git a/src/tile.cpp b/src/tile.cpp index f7f1779ca..e676c56c4 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -519,6 +519,15 @@ core::dimension2d<u32> imageTransformDimension(u32 transform, core::dimension2d< void imageTransform(u32 transform, video::IImage *src, video::IImage *dst); /* + Adds a new texture to the video driver and returns a pointer to it. + This pointer should not be dropped. Any texture that was registered + with that name before is removed (this may invalidate some ITexture + pointers). +*/ +video::ITexture* register_texture(video::IVideoDriver *driver, + std::string name, video::IImage *img); + +/* Generate image based on a string like "stone.png" or "[crack0". if baseimg is NULL, it is created. Otherwise stuff is made on it. */ @@ -686,11 +695,9 @@ u32 TextureSource::getTextureIdDirect(const std::string &name) " create texture \""<<name<<"\""<<std::endl; } + // Create texture from resulting image if(baseimg != NULL) - { - // Create texture from resulting image - t = driver->addTexture(name.c_str(), baseimg); - } + t = register_texture(driver, name, baseimg); /* Add texture to caches (add NULL textures too) @@ -809,7 +816,7 @@ void TextureSource::rebuildImagesAndTextures() // Create texture from resulting image video::ITexture *t = NULL; if(img) - t = driver->addTexture(sap->name.c_str(), img); + t = register_texture(driver, sap->name, img); // Replace texture sap->a.atlas = t; @@ -1044,7 +1051,7 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) /* Make texture */ - video::ITexture *t = driver->addTexture("__main_atlas__", atlas_img); + video::ITexture *t = register_texture(driver, "__main_atlas__", atlas_img); assert(t); /* @@ -1135,6 +1142,15 @@ video::IImage* generate_image_from_scratch(std::string name, return baseimg; } +video::ITexture* register_texture(video::IVideoDriver *driver, + std::string name, video::IImage *img) +{ + video::ITexture *old_texture = driver->findTexture(name.c_str()); + if(old_texture) + driver->removeTexture(old_texture); + return driver->addTexture(name.c_str(), img); +} + bool generate_image(std::string part_of_name, video::IImage *& baseimg, IrrlichtDevice *device, SourceImageCache *sourcecache) { @@ -1541,12 +1557,12 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, assert(img_top && img_left && img_right); // Create textures from images - video::ITexture *texture_top = driver->addTexture( - (imagename_top + "__temp__").c_str(), img_top); - video::ITexture *texture_left = driver->addTexture( - (imagename_left + "__temp__").c_str(), img_left); - video::ITexture *texture_right = driver->addTexture( - (imagename_right + "__temp__").c_str(), img_right); + video::ITexture *texture_top = register_texture(driver, + imagename_top + "__temp1__", img_top); + video::ITexture *texture_left = register_texture(driver, + imagename_left + "__temp2__", img_left); + video::ITexture *texture_right = register_texture(driver, + imagename_right + "__temp3__", img_right); assert(texture_top && texture_left && texture_right); // Drop images |