diff options
27 files changed, 368 insertions, 110 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/chatcommands.lua b/builtin/chatcommands.lua index 9f55f1afc..f25a276ea 100644 --- a/builtin/chatcommands.lua +++ b/builtin/chatcommands.lua @@ -215,8 +215,8 @@ minetest.register_chatcommand("clearpassword", { privs = {password=true}, func = function(name, param) toname = param - if not toname then - minetest.chat_send_player(toname, "Name field required") + if toname == "" then + minetest.chat_send_player(name, "Name field required") return end minetest.set_player_password(toname, '') diff --git a/builtin/falling.lua b/builtin/falling.lua new file mode 100644 index 000000000..3912727c3 --- /dev/null +++ b/builtin/falling.lua @@ -0,0 +1,141 @@ +-- 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) + -- Round p to prevent falling entities to get stuck + p.x = math.floor(p.x+0.5) + p.y = math.floor(p.y+0.5) + p.z = math.floor(p.z+0.5) + + 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/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 442937bd1..500b514d9 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 ---------------------------------------------- @@ -693,6 +694,11 @@ image[<X>,<Y>;<W>,<H>;<texture name>] ^ Show an image ^ Position and size units are inventory slots +background[<X>,<Y>;<W>,<H>;<texture name>] +^ Use a background. Inventory rectangles are not drawn then. +^ Position and size units are inventory slots +^ Example for formspec 8x4 in 16x resolution: image shall be sized 8*16px x 4*16px + field[<X>,<Y>;<W>,<H>;<name>;<label>;<default>] ^ Textual field; will be sent to server when a button is clicked ^ x and y position the field relative to the top left of the menu @@ -1346,6 +1352,8 @@ Node definition (register_node) liquid_alternative_flowing = "", -- Flowing version of source liquid liquid_alternative_source = "", -- Source version of flowing liquid liquid_viscosity = 0, -- Higher viscosity = slower flow (max. 7) + liquid_renewable = true, -- Can new liquid source be created by placing + two or more sources nearly? light_source = 0, -- Amount of light emitted by node damage_per_second = 0, -- If player is inside node, this damage is caused node_box = {type="regular"}, -- See "Node boxes" 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/games/minimal/mods/default/textures/default_nc_back.png b/games/minimal/mods/default/textures/default_nc_back.png Binary files differindex f09f41658..febd7384a 100644 --- a/games/minimal/mods/default/textures/default_nc_back.png +++ b/games/minimal/mods/default/textures/default_nc_back.png diff --git a/games/minimal/mods/default/textures/default_nc_front.png b/games/minimal/mods/default/textures/default_nc_front.png Binary files differindex cad9edab1..53b02d174 100644 --- a/games/minimal/mods/default/textures/default_nc_front.png +++ b/games/minimal/mods/default/textures/default_nc_front.png diff --git a/games/minimal/mods/default/textures/default_nc_rb.png b/games/minimal/mods/default/textures/default_nc_rb.png Binary files differindex 7ebc9930d..7183e6986 100644 --- a/games/minimal/mods/default/textures/default_nc_rb.png +++ b/games/minimal/mods/default/textures/default_nc_rb.png diff --git a/games/minimal/mods/default/textures/default_nc_side.png b/games/minimal/mods/default/textures/default_nc_side.png Binary files differindex f954045fb..0a34c8bef 100644 --- a/games/minimal/mods/default/textures/default_nc_side.png +++ b/games/minimal/mods/default/textures/default_nc_side.png diff --git a/src/camera.cpp b/src/camera.cpp index f87f660e9..43f26cd8f 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -189,7 +189,7 @@ void Camera::step(f32 dtime) if (m_digging_button != -1) { - f32 offset = dtime * 3.5; + f32 offset = dtime * 4.5; float m_digging_anim_was = m_digging_anim; m_digging_anim += offset; if (m_digging_anim >= 1) @@ -336,13 +336,13 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize, if (m_digging_button != -1) { f32 digfrac = m_digging_anim; - wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * M_PI); - wield_position.Y += 15 * sin(digfrac * 2 * M_PI); - wield_position.Z += 5 * digfrac; - + wield_position.X -= 50 * sin(pow(digfrac, 0.8f) * M_PI); + wield_position.Y += 24 * sin(digfrac * 1.8 * M_PI); + wield_position.Z += 25 * 0.5; + // Euler angles are PURE EVIL, so why not use quaternions? core::quaternion quat_begin(wield_rotation * core::DEGTORAD); - core::quaternion quat_end(v3f(90, -10, -130) * core::DEGTORAD); + core::quaternion quat_end(v3f(80, 30, 100) * core::DEGTORAD); core::quaternion quat_slerp; quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * M_PI)); quat_slerp.toEuler(wield_rotation); diff --git a/src/clientmap.cpp b/src/clientmap.cpp index 64d5656d4..02c9fe9b1 100644 --- a/src/clientmap.cpp +++ b/src/clientmap.cpp @@ -413,6 +413,10 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) m_last_drawn_sectors.clear(); } + bool use_trilinear_filter = g_settings->getBool("trilinear_filter"); + bool use_bilinear_filter = g_settings->getBool("bilinear_filter"); + bool use_anisotropic_filter = g_settings->getBool("anisotropic_filter"); + /* Get time for measuring timeout. @@ -544,6 +548,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) for(u32 i=0; i<c; i++) { scene::IMeshBuffer *buf = mesh->getMeshBuffer(i); + + buf->getMaterial().setFlag(video::EMF_TRILINEAR_FILTER, use_trilinear_filter); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, use_bilinear_filter); + buf->getMaterial().setFlag(video::EMF_ANISOTROPIC_FILTER, use_anisotropic_filter); + const video::SMaterial& material = buf->getMaterial(); video::IMaterialRenderer* rnd = driver->getMaterialRenderer(material.MaterialType); 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/defaultsettings.cpp b/src/defaultsettings.cpp index 3b37c18dc..6eaa28410 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -142,5 +142,10 @@ void set_default_settings(Settings *settings) settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); settings->setDefault("dedicated_server_step", "0.05"); settings->setDefault("ignore_world_load_errors", "false"); + settings->setDefault("mip_map", "false"); + settings->setDefault("anisotropic_filter", "false"); + settings->setDefault("bilinear_filter", "false"); + settings->setDefault("trilinear_filter", "false"); + } diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 9bdcdd5fb..4db020c11 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -199,6 +199,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) m_inventorylists.clear(); m_images.clear(); + m_backgrounds.clear(); m_fields.clear(); Strfnd f(m_formspec_string); @@ -278,9 +279,26 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) <<", geom=("<<geom.X<<","<<geom.Y<<")" <<std::endl; if(bp_set != 2) - errorstream<<"WARNING: invalid use of button without a size[] element"<<std::endl; + errorstream<<"WARNING: invalid use of image without a size[] element"<<std::endl; m_images.push_back(ImageDrawSpec(name, pos, geom)); } + else if(type == "background") + { + v2s32 pos = basepos; + pos.X += stof(f.next(",")) * (float)spacing.X - ((float)spacing.X-(float)imgsize.X)/2; + pos.Y += stof(f.next(";")) * (float)spacing.Y - ((float)spacing.Y-(float)imgsize.Y)/2; + v2s32 geom; + geom.X = stof(f.next(",")) * (float)spacing.X; + geom.Y = stof(f.next(";")) * (float)spacing.Y; + std::string name = f.next("]"); + infostream<<"image name="<<name + <<", pos=("<<pos.X<<","<<pos.Y<<")" + <<", geom=("<<geom.X<<","<<geom.Y<<")" + <<std::endl; + if(bp_set != 2) + errorstream<<"WARNING: invalid use of background without a size[] element"<<std::endl; + m_backgrounds.push_back(ImageDrawSpec(name, pos, geom)); + } else if(type == "field") { std::string fname = f.next(";"); @@ -693,17 +711,28 @@ void GUIFormSpecMenu::drawMenu() m_tooltip_element->setVisible(false); /* - Draw items - Phase 0: Item slot rectangles - Phase 1: Item images; prepare tooltip + Draw backgrounds */ - - for(int phase=0; phase<=1; phase++) - for(u32 i=0; i<m_inventorylists.size(); i++) + for(u32 i=0; i<m_backgrounds.size(); i++) { - drawList(m_inventorylists[i], phase); + const ImageDrawSpec &spec = m_backgrounds[i]; + video::ITexture *texture = + m_gamedef->tsrc()->getTextureRaw(spec.name); + // Image size on screen + core::rect<s32> imgrect(0, 0, spec.geom.X, spec.geom.Y); + // Image rectangle on screen + core::rect<s32> rect = imgrect + spec.pos; + const video::SColor color(255,255,255,255); + const video::SColor colors[] = {color,color,color,color}; + driver->draw2DImage(texture, rect, + core::rect<s32>(core::position2d<s32>(0,0), + core::dimension2di(texture->getOriginalSize())), + NULL/*&AbsoluteClippingRect*/, colors, true); } - + + /* + Draw images + */ for(u32 i=0; i<m_images.size(); i++) { const ImageDrawSpec &spec = m_images[i]; @@ -722,6 +751,20 @@ void GUIFormSpecMenu::drawMenu() } /* + Draw items + Phase 0: Item slot rectangles + Phase 1: Item images; prepare tooltip + If backgrounds used, do not draw Item slot rectangles + */ + int start_phase=0; + if (m_backgrounds.size() > 0) start_phase=1; + for(int phase=start_phase; phase<=1; phase++) + for(u32 i=0; i<m_inventorylists.size(); i++) + { + drawList(m_inventorylists[i], phase); + } + + /* Draw dragged item stack */ drawSelectedItem(); diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 5c01bdcd2..890b54d61 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -206,6 +206,7 @@ protected: TextDest *m_text_dst; core::array<ListDrawSpec> m_inventorylists; + core::array<ImageDrawSpec> m_backgrounds; core::array<ImageDrawSpec> m_images; core::array<FieldSpec> m_fields; diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 5e0a3c38f..0bdb44e5d 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -98,6 +98,10 @@ enum GUI_ID_SMOOTH_LIGHTING_CB, GUI_ID_3D_CLOUDS_CB, GUI_ID_OPAQUE_WATER_CB, + GUI_ID_MIPMAP_CB, + GUI_ID_ANISOTROPIC_CB, + GUI_ID_BILINEAR_CB, + GUI_ID_TRILINEAR_CB, GUI_ID_DAMAGE_CB, GUI_ID_CREATIVE_CB, GUI_ID_JOIN_GAME_BUTTON, @@ -580,6 +584,38 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) Environment->addCheckBox(m_data->opaque_water, rect, this, GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water")); } + + + // Anisotropic/mipmap/bi-/trilinear settings + + { + core::rect<s32> rect(0, 0, option_w+20, 30); + rect += m_topleft_client + v2s32(option_x+175, option_y); + Environment->addCheckBox(m_data->mip_map, rect, this, + GUI_ID_MIPMAP_CB, wgettext("Mip-Mapping")); + } + + { + core::rect<s32> rect(0, 0, option_w+20, 30); + rect += m_topleft_client + v2s32(option_x+175, option_y+20); + Environment->addCheckBox(m_data->anisotropic_filter, rect, this, + GUI_ID_ANISOTROPIC_CB, wgettext("Anisotropic Filtering")); + } + + { + core::rect<s32> rect(0, 0, option_w+20, 30); + rect += m_topleft_client + v2s32(option_x+175, option_y+20*2); + Environment->addCheckBox(m_data->bilinear_filter, rect, this, + GUI_ID_BILINEAR_CB, wgettext("Bi-Linear Filtering")); + } + + { + core::rect<s32> rect(0, 0, option_w+20, 30); + rect += m_topleft_client + v2s32(option_x+175, option_y+20*3); + Environment->addCheckBox(m_data->trilinear_filter, rect, this, + GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering")); + } + // Key change button { core::rect<s32> rect(0, 0, 120, 30); @@ -761,6 +797,30 @@ void GUIMainMenu::readInput(MainMenuData *dst) } { + gui::IGUIElement *e = getElementFromId(GUI_ID_MIPMAP_CB); + if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) + dst->mip_map = ((gui::IGUICheckBox*)e)->isChecked(); + } + + { + gui::IGUIElement *e = getElementFromId(GUI_ID_ANISOTROPIC_CB); + if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) + dst->anisotropic_filter = ((gui::IGUICheckBox*)e)->isChecked(); + } + + { + gui::IGUIElement *e = getElementFromId(GUI_ID_BILINEAR_CB); + if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) + dst->bilinear_filter = ((gui::IGUICheckBox*)e)->isChecked(); + } + + { + gui::IGUIElement *e = getElementFromId(GUI_ID_TRILINEAR_CB); + if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) + dst->trilinear_filter = ((gui::IGUICheckBox*)e)->isChecked(); + } + + { gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX); if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX) dst->selected_world = ((gui::IGUIListBox*)e)->getSelected(); diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index 715deb47d..abfc6bdb4 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -41,6 +41,10 @@ struct MainMenuData bool smooth_lighting; bool clouds_3d; bool opaque_water; + bool mip_map; + bool anisotropic_filter; + bool bilinear_filter; + bool trilinear_filter; // Server options bool creative_mode; bool enable_damage; diff --git a/src/main.cpp b/src/main.cpp index 6075e9d10..dcc47cd6b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1292,9 +1292,6 @@ int main(int argc, char *argv[]) video::IVideoDriver* driver = device->getVideoDriver(); - // Disable mipmaps (because some of them look ugly) - driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); - /* This changes the minimum allowed number of vertices in a VBO. Default is 500. @@ -1439,6 +1436,11 @@ int main(int argc, char *argv[]) menudata.smooth_lighting = g_settings->getBool("smooth_lighting"); menudata.clouds_3d = g_settings->getBool("enable_3d_clouds"); menudata.opaque_water = g_settings->getBool("opaque_water"); + menudata.mip_map = g_settings->getBool("mip_map"); + menudata.anisotropic_filter = g_settings->getBool("anisotropic_filter"); + menudata.bilinear_filter = g_settings->getBool("bilinear_filter"); + menudata.trilinear_filter = g_settings->getBool("trilinear_filter"); + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, menudata.mip_map); menudata.creative_mode = g_settings->getBool("creative_mode"); menudata.enable_damage = g_settings->getBool("enable_damage"); // Default to selecting nothing @@ -1552,6 +1554,12 @@ int main(int argc, char *argv[]) g_settings->set("smooth_lighting", itos(menudata.smooth_lighting)); g_settings->set("enable_3d_clouds", itos(menudata.clouds_3d)); g_settings->set("opaque_water", itos(menudata.opaque_water)); + + g_settings->set("mip_map", itos(menudata.mip_map)); + g_settings->set("anisotropic_filter", itos(menudata.anisotropic_filter)); + g_settings->set("bilinear_filter", itos(menudata.bilinear_filter)); + g_settings->set("trilinear_filter", itos(menudata.trilinear_filter)); + g_settings->set("creative_mode", itos(menudata.creative_mode)); g_settings->set("enable_damage", itos(menudata.enable_damage)); g_settings->set("name", playername); diff --git a/src/map.cpp b/src/map.cpp index 39c6d292b..2845f3a67 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1746,12 +1746,12 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks) content_t new_node_content; s8 new_node_level = -1; s8 max_node_level = -1; - if (num_sources >= 2 || liquid_type == LIQUID_SOURCE) { + if ((num_sources >= 2 && nodemgr->get(liquid_kind).liquid_renewable) || liquid_type == LIQUID_SOURCE) { // liquid_kind will be set to either the flowing alternative of the node (if it's a liquid) // or the flowing alternative of the first of the surrounding sources (if it's air), so // it's perfectly safe to use liquid_kind here to determine the new node content. new_node_content = nodemgr->getId(nodemgr->get(liquid_kind).liquid_alternative_source); - } else if (num_sources == 1 && sources[0].t != NEIGHBOR_LOWER) { + } else if (num_sources >= 1 && sources[0].t != NEIGHBOR_LOWER) { // liquid_kind is set properly, see above new_node_content = liquid_kind; max_node_level = new_node_level = LIQUID_LEVEL_MAX; 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/nodedef.cpp b/src/nodedef.cpp index d644dc229..180219ba8 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -203,6 +203,7 @@ void ContentFeatures::reset() liquid_alternative_flowing = ""; liquid_alternative_source = ""; liquid_viscosity = 0; + liquid_renewable = true; light_source = 0; damage_per_second = 0; node_box = NodeBox(); @@ -262,6 +263,9 @@ void ContentFeatures::serialize(std::ostream &os) serializeSimpleSoundSpec(sound_footstep, os); serializeSimpleSoundSpec(sound_dig, os); serializeSimpleSoundSpec(sound_dug, os); + // Stuff below should be moved to correct place in a version that otherwise changes + // the protocol version + writeU8(os, liquid_renewable); } void ContentFeatures::deSerialize(std::istream &is) @@ -319,6 +323,9 @@ void ContentFeatures::deSerialize(std::istream &is) // If you add anything here, insert it primarily inside the try-catch // block to not need to increase the version. try{ + // Stuff below should be moved to correct place in a version that + // otherwise changes the protocol version + liquid_renewable = readU8(is); }catch(SerializationError &e) {}; } diff --git a/src/nodedef.h b/src/nodedef.h index 7c6931834..4ff6c6b48 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -209,6 +209,8 @@ struct ContentFeatures // 1 giving almost instantaneous propagation and 7 being // the slowest possible u8 liquid_viscosity; + // Is liquid renewable (new liquid source will be created between 2 existing) + bool liquid_renewable; // Amount of light the node emits u8 light_source; u32 damage_per_second; 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 9fa927ff3..09900ce1f 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -1238,6 +1238,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) // the slowest possible f.liquid_viscosity = getintfield_default(L, index, "liquid_viscosity", f.liquid_viscosity); + getboolfield(L, index, "liquid_renewable", f.liquid_renewable); // Amount of light the node emits f.light_source = getintfield_default(L, index, "light_source", f.light_source); 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 |