diff --git a/.gitmodules b/.gitmodules index 30bc9739..2b7a65dc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "mods/boats"] - path = mods/boats - url = https://git.tchncs.de/Illuna-Minetest/boats.git [submodule "mods/illuna"] path = mods/illuna url = https://git.tchncs.de/Illuna-Minetest/illuna.git @@ -16,9 +13,6 @@ [submodule "mods/mobs_animal"] path = mods/mobs_animal url = https://git.tchncs.de/Illuna-Minetest/mobs_animal.git -[submodule "mods/farming"] - path = mods/farming - url = https://git.tchncs.de/Illuna-Minetest/farming.git [submodule "mods/worldedit"] path = mods/worldedit url = https://github.com/Uberi/Minetest-WorldEdit diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 00000000..f087d303 --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,17 @@ +unused_args = false +allow_defined_top = true + +read_globals = { + "DIR_DELIM", + "minetest", "core", + "dump", + "vector", "nodeupdate", + "VoxelManip", "VoxelArea", + "PseudoRandom", "ItemStack", +} + +-- Overwrites minetest.handle_node_drops +files["mods/creative/init.lua"].globals = { "minetest" } + +-- Don't report on legacy definitions of globals. +files["mods/default/legacy.lua"].global = false diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..805fe08c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: generic + +branches: + only: + - master + +sudo: required + +before_install: + - sudo apt-get update + - sudo apt-get install -y luarocks + - sudo luarocks install luacheck + +script: luacheck --no-color ./mods diff --git a/game_api.txt b/game_api.txt index 0cdd3012..2f0715f8 100644 --- a/game_api.txt +++ b/game_api.txt @@ -62,6 +62,11 @@ Beds API } } +Creative API +------------ + +A global string called `creative.formspec_add` was added which allows mods to add additional formspec elements onto the default creative inventory formspec to be drawn after each update. + Doors API --------- @@ -245,6 +250,18 @@ Give Initial Stuff API ^ str is a comma separated list of initial stuff ^ Adds items to the list of items to be given +Nyancat API +----------- + +`nyancat.place(pos, facedir, length)` + +^ Place a cat at `pos` facing `facedir` with tail length `length` + Only accepts facedir 0-3, if facedir > 3 then it will be interpreted as facedir = 0 + +`nyancat.generate(minp, maxp, seed)` + +^ Called by `minetest.register_on_generated`. To disable nyancat generation, + you can redefine nyancat.generate() to be an empty function TNT API ---------- @@ -331,7 +348,7 @@ To use it, add the `on_screwdriver` function to the node definition. * `new_param2` the new value of param2 that would have been set if on_rotate wasn't there * return value: false to disallow rotation, nil to keep default behaviour, true to allow it but to indicate that changed have already been made (so the screwdriver will wear out) - * use `on_rotate = screwdriver.disallow` to always disallow rotation + * use `on_rotate = false` to always disallow rotation * use `on_rotate = screwdriver.rotate_simple` to allow only face rotation diff --git a/minetest.conf.example b/minetest.conf.example index 813f1957..f5e4e85d 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -5,6 +5,12 @@ # Whether creative mode (fast digging of all blocks, unlimited resources) should be enabled #creative_mode = false +# Sets the behaviour of the inventory items when a player dies. +# "bones": Store all items inside a bone node but drop items if inside protected area +# "drop": Drop all items on the ground +# "keep": Player keeps all items +#bones_mode = "bones" + # The time in seconds after which the bones of a dead player can be looted by everyone # 0 to disable #share_bones_time = 1200 @@ -14,9 +20,9 @@ # 0 to disable. By default it is "share_bones_time" divide by four. #share_bones_time_early = 300 -# Whether standard fire should be disabled ('basic flame' nodes will disappear) -# 'permanent flame' nodes will remain with either setting -#disable_fire = false +# Whether fire should be enabled. If disabled, 'basic flame' nodes will disappear. +# 'permanent flame' nodes will remain with either setting. +#enable_fire = true # Whether the stuff in initial_stuff should be given to new players #give_initial_stuff = false diff --git a/mods/beds/functions.lua b/mods/beds/functions.lua index 5eed27d9..b1c2c977 100644 --- a/mods/beds/functions.lua +++ b/mods/beds/functions.lua @@ -70,7 +70,7 @@ local function lay_down(player, pos, bed_pos, state, skip) -- physics, eye_offset, etc player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) - player:set_look_yaw(math.random(1, 180) / 100) + player:set_look_horizontal(math.random(1, 180) / 100) default.player_attached[name] = false player:set_physics_override(1, 1, 1) hud_flags.wielditem = true @@ -85,7 +85,7 @@ local function lay_down(player, pos, bed_pos, state, skip) -- physics, eye_offset, etc player:set_eye_offset({x = 0, y = -13, z = 0}, {x = 0, y = 0, z = 0}) local yaw, param2 = get_look_yaw(bed_pos) - player:set_look_yaw(yaw) + player:set_look_horizontal(yaw) local dir = minetest.facedir_to_dir(param2) local p = {x = bed_pos.x + dir.x / 2, y = bed_pos.y, z = bed_pos.z + dir.z / 2} player:set_physics_override(0, 0, 0) diff --git a/mods/boats b/mods/boats deleted file mode 160000 index a7534e93..00000000 --- a/mods/boats +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a7534e938834c1a0322e49df796f613ca1f55880 diff --git a/mods/bones/README.txt b/mods/bones/README.txt index b40a384d..cf99bc8b 100644 --- a/mods/bones/README.txt +++ b/mods/bones/README.txt @@ -14,4 +14,4 @@ http://creativecommons.org/licenses/by-sa/3.0/ Authors of media files ---------------------- -Bad_Command_ +All textures: paramat diff --git a/mods/bones/init.lua b/mods/bones/init.lua index a55e340d..13af52b5 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -1,7 +1,5 @@ -- Minetest 0.4 mod: bones --- See README.txt for licensing and other information. - -bones = {} +-- See README.txt for licensing and other information. local function is_owner(pos, name) local owner = minetest.get_meta(pos):get_string("owner") @@ -11,7 +9,7 @@ local function is_owner(pos, name) return false end -bones.bones_formspec = +local bones_formspec = "size[8,9]" .. default.gui_bg .. default.gui_bg_img .. @@ -29,7 +27,7 @@ local share_bones_time_early = tonumber(minetest.setting_get("share_bones_time_e minetest.register_node("bones:bones", { description = "Bones", tiles = { - "bones_top.png", + "bones_top.png^[transform2", "bones_bottom.png", "bones_side.png", "bones_side.png", @@ -37,12 +35,9 @@ minetest.register_node("bones:bones", { "bones_front.png" }, paramtype2 = "facedir", - groups = {dig_immediate=2}, - sounds = default.node_sound_dirt_defaults({ - footstep = {name="default_gravel_footstep", gain=0.5}, - dug = {name="default_gravel_footstep", gain=1.0}, - }), - + groups = {dig_immediate = 2}, + sounds = default.node_sound_gravel_defaults(), + can_dig = function(pos, player) local inv = minetest.get_meta(pos):get_inventory() local name = "" @@ -51,46 +46,46 @@ minetest.register_node("bones:bones", { end return is_owner(pos, name) and inv:is_empty("main") end, - + allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) if is_owner(pos, player:get_player_name()) then return count end return 0 end, - + allow_metadata_inventory_put = function(pos, listname, index, stack, player) return 0 end, - + allow_metadata_inventory_take = function(pos, listname, index, stack, player) if is_owner(pos, player:get_player_name()) then return stack:get_count() end return 0 end, - + on_metadata_inventory_take = function(pos, listname, index, stack, player) local meta = minetest.get_meta(pos) if meta:get_inventory():is_empty("main") then minetest.remove_node(pos) end end, - + on_punch = function(pos, node, player) - if(not is_owner(pos, player:get_player_name())) then + if not is_owner(pos, player:get_player_name()) then return end - - if(minetest.get_meta(pos):get_string("infotext") == "") then + + if minetest.get_meta(pos):get_string("infotext") == "" then return end - + local inv = minetest.get_meta(pos):get_inventory() local player_inv = player:get_inventory() local has_space = true - - for i=1,inv:get_size("main") do + + for i = 1, inv:get_size("main") do local stk = inv:get_stack("main", i) if player_inv:room_for_item("main", stk) then inv:set_stack("main", i, nil) @@ -100,7 +95,7 @@ minetest.register_node("bones:bones", { break end end - + -- remove bones if player emptied them if has_space then if player_inv:room_for_item("main", {name = "bones:bones"}) then @@ -111,12 +106,12 @@ minetest.register_node("bones:bones", { minetest.remove_node(pos) end end, - + on_timer = function(pos, elapsed) local meta = minetest.get_meta(pos) local time = meta:get_int("time") + elapsed if time >= share_bones_time then - meta:set_string("infotext", meta:get_string("owner").."'s old bones") + meta:set_string("infotext", meta:get_string("owner") .. "'s old bones") meta:set_string("owner", "") else meta:set_int("time", time) @@ -131,13 +126,9 @@ local function may_replace(pos, player) local node_name = minetest.get_node(pos).name local node_definition = minetest.registered_nodes[node_name] - -- if the node is unknown, we let the protection mod decide - -- this is consistent with when a player could dig or not dig it - -- unknown decoration would often be removed - -- while unknown building materials in use would usually be left + -- if the node is unknown, we return false if not node_definition then - -- only replace nodes that are not protected - return not minetest.is_protected(pos, player:get_player_name()) + return false end -- allow replacing air and liquids @@ -157,73 +148,100 @@ local function may_replace(pos, player) return node_definition.buildable_to and not minetest.is_protected(pos, player:get_player_name()) end +local drop = function(pos, itemstack) + local obj = minetest.add_item(pos, itemstack:take_item(itemstack:get_count())) + if obj then + obj:setvelocity({ + x = math.random(-10, 10) / 9, + y = 5, + z = math.random(-10, 10) / 9, + }) + end +end + minetest.register_on_dieplayer(function(player) - if minetest.setting_getbool("creative_mode") then + + local bones_mode = minetest.setting_get("bones_mode") or "bones" + if bones_mode ~= "bones" and bones_mode ~= "drop" and bones_mode ~= "keep" then + bones_mode = "bones" + end + + -- return if keep inventory set or in creative mode + if bones_mode == "keep" or minetest.setting_getbool("creative_mode") then return end - + local player_inv = player:get_inventory() if player_inv:is_empty("main") and player_inv:is_empty("craft") then return end - local pos = player:getpos() - pos.x = math.floor(pos.x+0.5) - pos.y = math.floor(pos.y+0.5) - pos.z = math.floor(pos.z+0.5) - local param2 = minetest.dir_to_facedir(player:get_look_dir()) + local pos = vector.round(player:getpos()) local player_name = player:get_player_name() - if (not may_replace(pos, player)) then - if (may_replace({x=pos.x, y=pos.y+1, z=pos.z}, player)) then - -- drop one node above if there's space - -- this should solve most cases of protection related deaths in which players dig straight down - -- yet keeps the bones reachable - pos.y = pos.y+1 - else - -- drop items instead of delete - for i=1,player_inv:get_size("main") do - minetest.add_item(pos, player_inv:get_stack("main", i)) - end - for i=1,player_inv:get_size("craft") do - minetest.add_item(pos, player_inv:get_stack("craft", i)) - end - -- empty lists main and craft - player_inv:set_list("main", {}) - player_inv:set_list("craft", {}) - return - end + -- check if it's possible to place bones, if not go 1 higher + if bones_mode == "bones" and not may_replace(pos, player) then + pos.y = pos.y + 1 end + + -- still cannot place bones? change mode to 'drop' + if bones_mode == "bones" and not may_replace(pos, player) then + bones_mode = "drop" + end + + if bones_mode == "drop" then + + -- drop inventory items + for i = 1, player_inv:get_size("main") do + drop(pos, player_inv:get_stack("main", i)) + end + player_inv:set_list("main", {}) + + -- drop crafting grid items + for i = 1, player_inv:get_size("craft") do + drop(pos, player_inv:get_stack("craft", i)) + end + player_inv:set_list("craft", {}) + + drop(pos, ItemStack("bones:bones")) + return + end +<<<<<<< HEAD minetest.set_node(pos, {name="bones:bones", param2=param2}) minetest.chat_send_player(player_name, "Your stuff is waiting for you at "..minetest.pos_to_string(pos).. ". Go and grab it! ;-)") minetest.log("action", player_name.." left their bones at "..minetest.pos_to_string(pos)) +======= + + local param2 = minetest.dir_to_facedir(player:get_look_dir()) + minetest.set_node(pos, {name = "bones:bones", param2 = param2}) +>>>>>>> 5e9e3f7e84fafd6ece535b1c7aff3b9ea4e6405b local meta = minetest.get_meta(pos) local inv = meta:get_inventory() - inv:set_size("main", 8*4) + inv:set_size("main", 8 * 4) inv:set_list("main", player_inv:get_list("main")) - - for i=1,player_inv:get_size("craft") do + + for i = 1, player_inv:get_size("craft") do local stack = player_inv:get_stack("craft", i) if inv:room_for_item("main", stack) then inv:add_item("main", stack) else --drop if no space left - minetest.add_item(pos, stack) + drop(pos, stack) end end - + player_inv:set_list("main", {}) player_inv:set_list("craft", {}) - - meta:set_string("formspec", bones.bones_formspec) + + meta:set_string("formspec", bones_formspec) meta:set_string("owner", player_name) - + if share_bones_time ~= 0 then - meta:set_string("infotext", player_name.."'s fresh bones") + meta:set_string("infotext", player_name .. "'s fresh bones") if share_bones_time_early == 0 or not minetest.is_protected(pos, player_name) then meta:set_int("time", 0) diff --git a/mods/bones/textures/bones_bottom.png b/mods/bones/textures/bones_bottom.png index ada72cea..859c6bbe 100644 Binary files a/mods/bones/textures/bones_bottom.png and b/mods/bones/textures/bones_bottom.png differ diff --git a/mods/bones/textures/bones_front.png b/mods/bones/textures/bones_front.png index 9dcbb97b..1e524370 100644 Binary files a/mods/bones/textures/bones_front.png and b/mods/bones/textures/bones_front.png differ diff --git a/mods/bones/textures/bones_rear.png b/mods/bones/textures/bones_rear.png index 8e1ac10b..4cfe236d 100644 Binary files a/mods/bones/textures/bones_rear.png and b/mods/bones/textures/bones_rear.png differ diff --git a/mods/bones/textures/bones_side.png b/mods/bones/textures/bones_side.png index 3b4810c6..a07595f4 100644 Binary files a/mods/bones/textures/bones_side.png and b/mods/bones/textures/bones_side.png differ diff --git a/mods/bones/textures/bones_top.png b/mods/bones/textures/bones_top.png index 61198647..198a8a2d 100644 Binary files a/mods/bones/textures/bones_top.png and b/mods/bones/textures/bones_top.png differ diff --git a/mods/bucket/init.lua b/mods/bucket/init.lua index 3770be6a..a7cb0f27 100644 --- a/mods/bucket/init.lua +++ b/mods/bucket/init.lua @@ -141,7 +141,7 @@ minetest.register_craftitem("bucket:bucket_empty", { else local pos = user:getpos() pos.y = math.floor(pos.y + 0.5) - core.add_item(pos, liquiddef.itemname) + minetest.add_item(pos, liquiddef.itemname) end -- set to return empty buckets minus 1 diff --git a/mods/creative/init.lua b/mods/creative/init.lua index 3b0076c1..cc7f81c8 100644 --- a/mods/creative/init.lua +++ b/mods/creative/init.lua @@ -125,7 +125,7 @@ creative.set_creative_formspec = function(player, start_i) tooltip[creative_clear;Reset] listring[current_player;main] ]] .. - "field[0.3,3.5;2.2,1;creative_filter;;" .. inv.filter .. "]" .. + "field[0.3,3.5;2.2,1;creative_filter;;" .. minetest.formspec_escape(inv.filter) .. ";false]" .. "listring[detached:creative_" .. player_name .. ";main]" .. "tabheader[0,0;creative_tabs;Crafting,All,Nodes,Tools,Items;" .. tostring(inv.tab_id) .. ";true;false]" .. "list[detached:creative_" .. player_name .. ";main;0,0;8,3;" .. tostring(start_i) .. "]" .. @@ -192,7 +192,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) inv.filter = "" creative.update_creative_inventory(player_name) creative.set_creative_formspec(player, 0) - elseif fields.creative_search then + elseif fields.creative_search or + fields.key_enter_field == "creative_filter" then player_inventory[player_name].start_i = 1 inv.filter = fields.creative_filter:lower() creative.update_creative_inventory(player_name) diff --git a/mods/default/README.txt b/mods/default/README.txt index 9648f2ca..85c5a4ef 100644 --- a/mods/default/README.txt +++ b/mods/default/README.txt @@ -51,13 +51,11 @@ RealBadAngel's animated water (WTFPL): default_water_flowing_animated.png VanessaE (WTFPL): - default_nc_back.png - default_nc_front.png - default_nc_rb.png - default_nc_side.png default_desert_sand.png default_desert_stone.png default_sand.png + default_mese_crystal.png + default_mese_crystal_fragment.png Calinou (CC BY-SA): default_brick.png @@ -125,6 +123,7 @@ paramat (CC BY-SA 3.0): default_grass.png default_grass_side.png default_snow_side.png + default_mese_block.png brunob.santos (CC BY-SA 4.0): default_desert_cobble.png diff --git a/mods/default/aliases.lua b/mods/default/aliases.lua index 193433c1..1a877ecf 100644 --- a/mods/default/aliases.lua +++ b/mods/default/aliases.lua @@ -41,8 +41,6 @@ minetest.register_alias("locked_chest", "default:chest_locked") minetest.register_alias("cobble", "default:cobble") minetest.register_alias("mossycobble", "default:mossycobble") minetest.register_alias("steelblock", "default:steelblock") -minetest.register_alias("nyancat", "default:nyancat") -minetest.register_alias("nyancat_rainbow", "default:nyancat_rainbow") minetest.register_alias("sapling", "default:sapling") minetest.register_alias("apple", "default:apple") @@ -79,4 +77,3 @@ minetest.register_alias("default:pinewood", "default:pine_wood") minetest.register_alias("default:ladder", "default:ladder_wood") minetest.register_alias("default:sign_wall", "default:sign_wall_wood") - diff --git a/mods/default/crafting.lua b/mods/default/crafting.lua index 3bfce07c..1151f47b 100644 --- a/mods/default/crafting.lua +++ b/mods/default/crafting.lua @@ -888,18 +888,6 @@ minetest.register_craft({ burntime = 30, }) -minetest.register_craft({ - type = "fuel", - recipe = "default:nyancat", - burntime = 1, -}) - -minetest.register_craft({ - type = "fuel", - recipe = "default:nyancat_rainbow", - burntime = 1, -}) - minetest.register_craft({ type = "fuel", recipe = "group:sapling", @@ -935,4 +923,3 @@ minetest.register_craft({ recipe = "default:dry_grass_1", burntime = 2, }) - diff --git a/mods/default/functions.lua b/mods/default/functions.lua index 6db8463b..867d6bc0 100644 --- a/mods/default/functions.lua +++ b/mods/default/functions.lua @@ -120,6 +120,7 @@ default.cool_lava = function(pos, node) end minetest.register_abm({ + label = "Lava cooling", nodenames = {"default:lava_source", "default:lava_flowing"}, neighbors = {"group:water"}, interval = 1, @@ -134,6 +135,7 @@ minetest.register_abm({ -- -- optimized helper to put all items in an inventory into a drops list -- + function default.get_inventory_drops(pos, inventory, drops) local inv = minetest.get_meta(pos):get_inventory() local n = #drops @@ -198,6 +200,7 @@ function default.grow_papyrus(pos, node) end minetest.register_abm({ + label = "Grow cactus", nodenames = {"default:cactus"}, neighbors = {"group:sand"}, interval = 12, @@ -208,6 +211,7 @@ minetest.register_abm({ }) minetest.register_abm({ + label = "Grow papyrus", nodenames = {"default:papyrus"}, neighbors = {"default:dirt", "default:dirt_with_grass"}, interval = 14, @@ -235,6 +239,7 @@ end -- -- Fence registration helper -- + function default.register_fence(name, def) minetest.register_craft({ output = name .. " 4", @@ -281,16 +286,7 @@ end -- Leafdecay -- -default.leafdecay_trunk_cache = {} -default.leafdecay_enable_cache = true --- Spread the load of finding trunks -default.leafdecay_trunk_find_allow_accumulator = 0 - -minetest.register_globalstep(function(dtime) - local finds_per_second = 5000 - default.leafdecay_trunk_find_allow_accumulator = - math.floor(dtime * finds_per_second) -end) +-- Prevent decay of placed leaves default.after_place_leaves = function(pos, placer, itemstack, pointed_thing) if placer and not placer:get_player_control().sneak then @@ -300,79 +296,44 @@ default.after_place_leaves = function(pos, placer, itemstack, pointed_thing) end end -minetest.register_abm({ - nodenames = {"group:leafdecay"}, - neighbors = {"air", "group:liquid"}, - -- A low interval and a high inverse chance spreads the load - interval = 2, - chance = 5, +-- Leafdecay ABM - action = function(p0, node, _, _) - --print("leafdecay ABM at "..p0.x..", "..p0.y..", "..p0.z..")") - local do_preserve = false - local d = minetest.registered_nodes[node.name].groups.leafdecay - if not d or d == 0 then - --print("not groups.leafdecay") +minetest.register_abm({ + label = "Leaf decay", + nodenames = {"group:leafdecay"}, + neighbors = {"air"}, + interval = 2, + chance = 10, + catch_up = false, + + action = function(pos, node, _, _) + -- Check if leaf is placed + if node.param2 ~= 0 then return end - local n0 = minetest.get_node(p0) - if n0.param2 ~= 0 then - --print("param2 ~= 0") + + local rad = minetest.registered_nodes[node.name].groups.leafdecay + -- Assume ignore is a trunk, to make this + -- work at the border of a loaded area + if minetest.find_node_near(pos, rad, {"ignore", "group:tree"}) then return end - local p0_hash = nil - if default.leafdecay_enable_cache then - p0_hash = minetest.hash_node_position(p0) - local trunkp = default.leafdecay_trunk_cache[p0_hash] - if trunkp then - local n = minetest.get_node(trunkp) - local reg = minetest.registered_nodes[n.name] - -- Assume ignore is a trunk, to make the thing - -- work at the border of the active area - if n.name == "ignore" or (reg and reg.groups.tree and - reg.groups.tree ~= 0) then - --print("cached trunk still exists") - return - end - --print("cached trunk is invalid") - -- Cache is invalid - table.remove(default.leafdecay_trunk_cache, p0_hash) + -- Drop stuff + local itemstacks = minetest.get_node_drops(node.name) + for _, itemname in ipairs(itemstacks) do + if itemname ~= node.name or + minetest.get_item_group(node.name, "leafdecay_drop") ~= 0 then + local p_drop = { + x = pos.x - 0.5 + math.random(), + y = pos.y - 0.5 + math.random(), + z = pos.z - 0.5 + math.random(), + } + minetest.add_item(p_drop, itemname) end end - if default.leafdecay_trunk_find_allow_accumulator <= 0 then - return - end - default.leafdecay_trunk_find_allow_accumulator = - default.leafdecay_trunk_find_allow_accumulator - 1 - -- Assume ignore is a trunk, to make the thing - -- work at the border of the active area - local p1 = minetest.find_node_near(p0, d, {"ignore", "group:tree"}) - if p1 then - do_preserve = true - if default.leafdecay_enable_cache then - --print("caching trunk") - -- Cache the trunk - default.leafdecay_trunk_cache[p0_hash] = p1 - end - end - if not do_preserve then - -- Drop stuff other than the node itself - local itemstacks = minetest.get_node_drops(n0.name) - for _, itemname in ipairs(itemstacks) do - if minetest.get_item_group(n0.name, "leafdecay_drop") ~= 0 or - itemname ~= n0.name then - local p_drop = { - x = p0.x - 0.5 + math.random(), - y = p0.y - 0.5 + math.random(), - z = p0.z - 0.5 + math.random(), - } - minetest.add_item(p_drop, itemname) - end - end - -- Remove node - minetest.remove_node(p0) - nodeupdate(p0) - end + -- Remove node + minetest.remove_node(pos) + nodeupdate(pos) end }) @@ -382,6 +343,7 @@ minetest.register_abm({ -- minetest.register_abm({ + label = "Grass spread", nodenames = {"default:dirt"}, neighbors = { "default:dirt_with_grass", @@ -433,11 +395,13 @@ minetest.register_abm({ end }) + -- -- Grass and dry grass removed in darkness -- minetest.register_abm({ + label = "Grass covered", nodenames = { "default:dirt_with_grass", "default:dirt_with_dry_grass", @@ -464,6 +428,7 @@ minetest.register_abm({ -- minetest.register_abm({ + label = "Moss growth", nodenames = {"default:cobble", "stairs:slab_cobble", "stairs:stair_cobble"}, neighbors = {"group:water"}, interval = 16, @@ -479,3 +444,43 @@ minetest.register_abm({ end end }) + + +-- +-- Checks if specified volume intersects a protected volume +-- + +function default.intersects_protection(minp, maxp, player_name, interval) + -- 'interval' is the largest allowed interval for the 3D lattice of checks + + -- Compute the optimal float step 'd' for each axis so that all corners and + -- borders are checked. 'd' will be smaller or equal to 'interval'. + -- Subtracting 1e-4 ensures that the max co-ordinate will be reached by the + -- for loop (which might otherwise not be the case due to rounding errors). + local d = {} + for _, c in pairs({"x", "y", "z"}) do + if maxp[c] > minp[c] then + d[c] = (maxp[c] - minp[c]) / math.ceil((maxp[c] - minp[c]) / interval) - 1e-4 + elseif maxp[c] == minp[c] then + d[c] = 1 -- Any value larger than 0 to avoid division by zero + else -- maxp[c] < minp[c], print error and treat as protection intersected + minetest.log("error", "maxp < minp in 'default.intersects_protection()'") + return true + end + end + + for zf = minp.z, maxp.z, d.z do + local z = math.floor(zf + 0.5) + for yf = minp.y, maxp.y, d.y do + local y = math.floor(yf + 0.5) + for xf = minp.x, maxp.x, d.x do + local x = math.floor(xf + 0.5) + if minetest.is_protected({x = x, y = y, z = z}, player_name) then + return true + end + end + end + end + + return false +end diff --git a/mods/default/init.lua b/mods/default/init.lua index b362fc75..594ea36a 100644 --- a/mods/default/init.lua +++ b/mods/default/init.lua @@ -35,14 +35,16 @@ default.gui_survival_form = "size[8,8.5]".. default.get_hotbar_bg(0,4.25) -- Load files -dofile(minetest.get_modpath("default").."/functions.lua") -dofile(minetest.get_modpath("default").."/trees.lua") -dofile(minetest.get_modpath("default").."/nodes.lua") -dofile(minetest.get_modpath("default").."/furnace.lua") -dofile(minetest.get_modpath("default").."/tools.lua") -dofile(minetest.get_modpath("default").."/craftitems.lua") -dofile(minetest.get_modpath("default").."/crafting.lua") -dofile(minetest.get_modpath("default").."/mapgen.lua") -dofile(minetest.get_modpath("default").."/player.lua") -dofile(minetest.get_modpath("default").."/aliases.lua") -dofile(minetest.get_modpath("default").."/legacy.lua") +local default_path = minetest.get_modpath("default") + +dofile(default_path.."/functions.lua") +dofile(default_path.."/trees.lua") +dofile(default_path.."/nodes.lua") +dofile(default_path.."/furnace.lua") +dofile(default_path.."/tools.lua") +dofile(default_path.."/craftitems.lua") +dofile(default_path.."/crafting.lua") +dofile(default_path.."/mapgen.lua") +dofile(default_path.."/player.lua") +dofile(default_path.."/aliases.lua") +dofile(default_path.."/legacy.lua") diff --git a/mods/default/mapgen.lua b/mods/default/mapgen.lua index 7d0b0fd4..52aa294c 100644 --- a/mods/default/mapgen.lua +++ b/mods/default/mapgen.lua @@ -49,7 +49,7 @@ function default.register_ores() -- Clay -- This first to avoid clay in sand blobs - minetest.register_ore({ + minetest.register_ore({ ore_type = "blob", ore = "default:clay", wherein = {"default:sand"}, @@ -70,7 +70,7 @@ function default.register_ores() -- Sand - minetest.register_ore({ + minetest.register_ore({ ore_type = "blob", ore = "default:sand", wherein = {"default:stone", "default:sandstone", @@ -1464,73 +1464,16 @@ function default.register_decorations() end --- --- Generate nyan cats --- - --- All mapgens except singlenode - -function default.make_nyancat(pos, facedir, length) - local tailvec = {x = 0, y = 0, z = 0} - if facedir == 0 then - tailvec.z = 1 - elseif facedir == 1 then - tailvec.x = 1 - elseif facedir == 2 then - tailvec.z = -1 - elseif facedir == 3 then - tailvec.x = -1 - else - facedir = 0 - tailvec.z = 1 - end - local p = {x = pos.x, y = pos.y, z = pos.z} - minetest.set_node(p, {name = "default:nyancat", param2 = facedir}) - for i = 1, length do - p.x = p.x + tailvec.x - p.z = p.z + tailvec.z - minetest.set_node(p, {name = "default:nyancat_rainbow", param2 = facedir}) - end -end - -function default.generate_nyancats(minp, maxp, seed) - local height_min = -31000 - local height_max = -32 - if maxp.y < height_min or minp.y > height_max then - return - end - local y_min = math.max(minp.y, height_min) - local y_max = math.min(maxp.y, height_max) - local volume = (maxp.x - minp.x + 1) * (y_max - y_min + 1) * (maxp.z - minp.z + 1) - local pr = PseudoRandom(seed + 9324342) - local max_num_nyancats = math.floor(volume / (16 * 16 * 16)) - for i = 1, max_num_nyancats do - if pr:next(0, 1000) == 0 then - local x0 = pr:next(minp.x, maxp.x) - local y0 = pr:next(minp.y, maxp.y) - local z0 = pr:next(minp.z, maxp.z) - local p0 = {x = x0, y = y0, z = z0} - default.make_nyancat(p0, pr:next(0, 3), pr:next(3, 15)) - end - end -end - - -- -- Detect mapgen to select functions -- --- Mods using singlenode mapgen can call these functions to enable --- the use of minetest.generate_ores or minetest.generate_decorations - local mg_name = minetest.get_mapgen_setting("mg_name") if mg_name == "v6" then default.register_ores() default.register_mgv6_decorations() - minetest.register_on_generated(default.generate_nyancats) -elseif mg_name ~= "singlenode" then +else default.register_biomes() default.register_ores() default.register_decorations() - minetest.register_on_generated(default.generate_nyancats) end diff --git a/mods/default/nodes.lua b/mods/default/nodes.lua index 958e35fd..79aea5bb 100644 --- a/mods/default/nodes.lua +++ b/mods/default/nodes.lua @@ -178,8 +178,6 @@ Misc ---- default:cloud -default:nyancat -default:nyancat_rainbow --]] @@ -424,6 +422,7 @@ minetest.register_node("default:snow", { paramtype = "light", buildable_to = true, floodable = true, + walkable = false, drawtype = "nodebox", node_box = { type = "fixed", @@ -487,7 +486,7 @@ minetest.register_node("default:wood", { place_param2 = 0, tiles = {"default_wood.png"}, is_ground_content = false, - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, wood = 1}, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, sounds = default.node_sound_wood_defaults(), }) @@ -502,9 +501,6 @@ minetest.register_node("default:sapling", { sunlight_propagates = true, walkable = false, on_timer = default.grow_sapling, - on_construct = function(pos) - minetest.get_node_timer(pos):start(math.random(2400,4800)) - end, selection_box = { type = "fixed", fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3} @@ -512,6 +508,23 @@ minetest.register_node("default:sapling", { groups = {snappy = 2, dig_immediate = 3, flammable = 2, attached_node = 1, sapling = 1}, sounds = default.node_sound_leaves_defaults(), + + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(2400,4800)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:sapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -2, y = 1, z = -2}, + {x = 2, y = 6, z = 2}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, }) minetest.register_node("default:leaves", { @@ -589,7 +602,7 @@ minetest.register_node("default:junglewood", { place_param2 = 0, tiles = {"default_junglewood.png"}, is_ground_content = false, - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, wood = 1}, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, sounds = default.node_sound_wood_defaults(), }) @@ -626,9 +639,6 @@ minetest.register_node("default:junglesapling", { sunlight_propagates = true, walkable = false, on_timer = default.grow_sapling, - on_construct = function(pos) - minetest.get_node_timer(pos):start(math.random(2400,4800)) - end, selection_box = { type = "fixed", fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3} @@ -636,6 +646,23 @@ minetest.register_node("default:junglesapling", { groups = {snappy = 2, dig_immediate = 3, flammable = 2, attached_node = 1, sapling = 1}, sounds = default.node_sound_leaves_defaults(), + + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(2400,4800)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:junglesapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -2, y = 1, z = -2}, + {x = 2, y = 15, z = 2}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, }) @@ -645,7 +672,7 @@ minetest.register_node("default:pine_tree", { "default_pine_tree.png"}, paramtype2 = "facedir", is_ground_content = false, - groups = {tree = 1, choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + groups = {tree = 1, choppy = 3, oddly_breakable_by_hand = 1, flammable = 3}, sounds = default.node_sound_wood_defaults(), on_place = minetest.rotate_node @@ -657,7 +684,7 @@ minetest.register_node("default:pine_wood", { place_param2 = 0, tiles = {"default_pine_wood.png"}, is_ground_content = false, - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, wood = 1}, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3, wood = 1}, sounds = default.node_sound_wood_defaults(), }) @@ -693,16 +720,30 @@ minetest.register_node("default:pine_sapling", { sunlight_propagates = true, walkable = false, on_timer = default.grow_sapling, - on_construct = function(pos) - minetest.get_node_timer(pos):start(math.random(2400,4800)) - end, selection_box = { type = "fixed", fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3} }, - groups = {snappy = 2, dig_immediate = 3, flammable = 2, + groups = {snappy = 2, dig_immediate = 3, flammable = 3, attached_node = 1, sapling = 1}, sounds = default.node_sound_leaves_defaults(), + + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(2400,4800)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:pine_sapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -2, y = 1, z = -2}, + {x = 2, y = 12, z = 2}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, }) @@ -724,7 +765,7 @@ minetest.register_node("default:acacia_wood", { place_param2 = 0, tiles = {"default_acacia_wood.png"}, is_ground_content = false, - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, wood = 1}, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, sounds = default.node_sound_wood_defaults(), }) @@ -760,9 +801,6 @@ minetest.register_node("default:acacia_sapling", { sunlight_propagates = true, walkable = false, on_timer = default.grow_sapling, - on_construct = function(pos) - minetest.get_node_timer(pos):start(math.random(2400,4800)) - end, selection_box = { type = "fixed", fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3} @@ -770,6 +808,23 @@ minetest.register_node("default:acacia_sapling", { groups = {snappy = 2, dig_immediate = 3, flammable = 2, attached_node = 1, sapling = 1}, sounds = default.node_sound_leaves_defaults(), + + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(2400,4800)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:acacia_sapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -4, y = 1, z = -4}, + {x = 4, y = 6, z = 4}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, }) minetest.register_node("default:aspen_tree", { @@ -778,7 +833,7 @@ minetest.register_node("default:aspen_tree", { "default_aspen_tree.png"}, paramtype2 = "facedir", is_ground_content = false, - groups = {tree = 1, choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + groups = {tree = 1, choppy = 3, oddly_breakable_by_hand = 1, flammable = 3}, sounds = default.node_sound_wood_defaults(), on_place = minetest.rotate_node @@ -790,7 +845,7 @@ minetest.register_node("default:aspen_wood", { place_param2 = 0, tiles = {"default_aspen_wood.png"}, is_ground_content = false, - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, wood = 1}, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3, wood = 1}, sounds = default.node_sound_wood_defaults(), }) @@ -826,17 +881,32 @@ minetest.register_node("default:aspen_sapling", { sunlight_propagates = true, walkable = false, on_timer = default.grow_sapling, - on_construct = function(pos) - minetest.get_node_timer(pos):start(math.random(2400,4800)) - end, selection_box = { type = "fixed", fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3} }, - groups = {snappy = 2, dig_immediate = 3, flammable = 2, + groups = {snappy = 2, dig_immediate = 3, flammable = 3, attached_node = 1, sapling = 1}, sounds = default.node_sound_leaves_defaults(), + + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(2400,4800)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:aspen_sapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -2, y = 1, z = -2}, + {x = 2, y = 12, z = 2}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, }) + -- -- Ores -- @@ -1521,7 +1591,6 @@ minetest.register_node("default:chest", { on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec", chest_formspec) - meta:set_string("infotext", "Chest") local inv = meta:get_inventory() inv:set_size("main", 8*4) end, @@ -1572,7 +1641,6 @@ minetest.register_node("default:chest_locked", { end, on_construct = function(pos) local meta = minetest.get_meta(pos) - meta:set_string("infotext", "Locked Chest") meta:set_string("owner", "") local inv = meta:get_inventory() inv:set_size("main", 8 * 4) @@ -1713,7 +1781,6 @@ local function register_sign(material, desc, def) --local n = minetest.get_node(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec", "field[text;;${text}]") - meta:set_string("infotext", "\"\"") end, on_receive_fields = function(pos, formname, fields, sender) --print("Sign at "..minetest.pos_to_string(pos).." got "..dump(fields)) @@ -1789,7 +1856,9 @@ minetest.register_node("default:ladder_steel", { default.register_fence("default:fence_wood", { description = "Wooden Fence", - texture = "default_wood.png", + texture = "default_fence_wood.png", + inventory_image = "default_fence_overlay.png^default_wood.png^default_fence_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_overlay.png^default_wood.png^default_fence_overlay.png^[makealpha:255,126,126", material = "default:wood", groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, sounds = default.node_sound_wood_defaults() @@ -1797,7 +1866,9 @@ default.register_fence("default:fence_wood", { default.register_fence("default:fence_acacia_wood", { description = "Acacia Fence", - texture = "default_acacia_wood.png", + texture = "default_fence_acacia_wood.png", + inventory_image = "default_fence_overlay.png^default_acacia_wood.png^default_fence_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_overlay.png^default_acacia_wood.png^default_fence_overlay.png^[makealpha:255,126,126", material = "default:acacia_wood", groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, sounds = default.node_sound_wood_defaults() @@ -1805,7 +1876,9 @@ default.register_fence("default:fence_acacia_wood", { default.register_fence("default:fence_junglewood", { description = "Junglewood Fence", - texture = "default_junglewood.png", + texture = "default_fence_junglewood.png", + inventory_image = "default_fence_overlay.png^default_junglewood.png^default_fence_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_overlay.png^default_junglewood.png^default_fence_overlay.png^[makealpha:255,126,126", material = "default:junglewood", groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, sounds = default.node_sound_wood_defaults() @@ -1813,17 +1886,21 @@ default.register_fence("default:fence_junglewood", { default.register_fence("default:fence_pine_wood", { description = "Pine Fence", - texture = "default_pine_wood.png", + texture = "default_fence_pine_wood.png", + inventory_image = "default_fence_overlay.png^default_pine_wood.png^default_fence_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_overlay.png^default_pine_wood.png^default_fence_overlay.png^[makealpha:255,126,126", material = "default:pine_wood", - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, sounds = default.node_sound_wood_defaults() }) default.register_fence("default:fence_aspen_wood", { description = "Aspen Fence", - texture = "default_aspen_wood.png", + texture = "default_fence_aspen_wood.png", + inventory_image = "default_fence_overlay.png^default_aspen_wood.png^default_fence_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_overlay.png^default_aspen_wood.png^default_fence_overlay.png^[makealpha:255,126,126", material = "default:aspen_wood", - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, sounds = default.node_sound_wood_defaults() }) @@ -1905,26 +1982,3 @@ minetest.register_node("default:cloud", { sounds = default.node_sound_defaults(), groups = {not_in_creative_inventory = 1}, }) - -minetest.register_node("default:nyancat", { - description = "Nyan Cat", - tiles = {"default_nc_side.png", "default_nc_side.png", "default_nc_side.png", - "default_nc_side.png", "default_nc_back.png", "default_nc_front.png"}, - paramtype2 = "facedir", - groups = {cracky = 2}, - is_ground_content = false, - legacy_facedir_simple = true, - sounds = default.node_sound_defaults(), -}) - -minetest.register_node("default:nyancat_rainbow", { - description = "Nyan Cat Rainbow", - tiles = { - "default_nc_rb.png^[transformR90", "default_nc_rb.png^[transformR90", - "default_nc_rb.png", "default_nc_rb.png" - }, - paramtype2 = "facedir", - groups = {cracky = 2}, - is_ground_content = false, - sounds = default.node_sound_defaults(), -}) diff --git a/mods/default/textures/default_desert_stone_brick.png b/mods/default/textures/default_desert_stone_brick.png index 42d9f277..941523ec 100644 Binary files a/mods/default/textures/default_desert_stone_brick.png and b/mods/default/textures/default_desert_stone_brick.png differ diff --git a/mods/default/textures/default_mese_block.png b/mods/default/textures/default_mese_block.png index 2e6895d3..e30994e2 100644 Binary files a/mods/default/textures/default_mese_block.png and b/mods/default/textures/default_mese_block.png differ diff --git a/mods/default/textures/default_stone_brick.png b/mods/default/textures/default_stone_brick.png index be949ab6..4312b5cb 100644 Binary files a/mods/default/textures/default_stone_brick.png and b/mods/default/textures/default_stone_brick.png differ diff --git a/mods/default/trees.lua b/mods/default/trees.lua index 07071c74..5cd7e156 100644 --- a/mods/default/trees.lua +++ b/mods/default/trees.lua @@ -27,10 +27,8 @@ end -- 'is snow nearby' function local function is_snow_nearby(pos) - return #minetest.find_nodes_in_area( - {x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}, - {x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}, - {"default:snow", "default:snowblock", "default:dirt_with_snow"}) > 0 + return minetest.find_node_near(pos, 1, + {"default:snow", "default:snowblock", "default:dirt_with_snow"}) end @@ -43,12 +41,12 @@ function default.grow_sapling(pos) return end - local mapgen = minetest.get_mapgen_params().mgname + local mg_name = minetest.get_mapgen_setting("mg_name") local node = minetest.get_node(pos) if node.name == "default:sapling" then minetest.log("action", "A sapling grows into a tree at ".. minetest.pos_to_string(pos)) - if mapgen == "v6" then + if mg_name == "v6" then default.grow_tree(pos, random(1, 4) == 1) else default.grow_new_apple_tree(pos) @@ -56,7 +54,7 @@ function default.grow_sapling(pos) elseif node.name == "default:junglesapling" then minetest.log("action", "A jungle sapling grows into a tree at ".. minetest.pos_to_string(pos)) - if mapgen == "v6" then + if mg_name == "v6" then default.grow_jungle_tree(pos) else default.grow_new_jungle_tree(pos) @@ -65,7 +63,7 @@ function default.grow_sapling(pos) minetest.log("action", "A pine sapling grows into a tree at ".. minetest.pos_to_string(pos)) local snow = is_snow_nearby(pos) - if mapgen == "v6" then + if mg_name == "v6" then default.grow_pine_tree(pos, snow) elseif snow then default.grow_new_snowy_pine_tree(pos) @@ -418,6 +416,7 @@ function default.grow_new_acacia_tree(pos) path, "random", nil, false) end + -- New aspen tree function default.grow_new_aspen_tree(pos) @@ -426,3 +425,48 @@ function default.grow_new_aspen_tree(pos) minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2}, path, "0", nil, false) end + + +-- +-- Sapling 'on place' function to check protection of node and resulting tree volume +-- + +function default.sapling_on_place(itemstack, placer, pointed_thing, + sapling_name, minp_relative, maxp_relative, interval) + -- Position of sapling + local pos = pointed_thing.under + local node = minetest.get_node(pos) + local pdef = minetest.registered_nodes[node.name] + if not pdef or not pdef.buildable_to then + pos = pointed_thing.above + node = minetest.get_node(pos) + pdef = minetest.registered_nodes[node.name] + if not pdef or not pdef.buildable_to then + return itemstack + end + end + + local player_name = placer:get_player_name() + -- Check sapling position for protection + if minetest.is_protected(pos, player_name) then + minetest.record_protection_violation(pos, player_name) + return itemstack + end + -- Check tree volume for protection + if not default.intersects_protection( + vector.add(pos, minp_relative), + vector.add(pos, maxp_relative), + player_name, + interval) then + minetest.set_node(pos, {name = sapling_name}) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + else + minetest.record_protection_violation(pos, player_name) + -- Print extra information to explain + minetest.chat_send_player(player_name, "Tree will intersect protection") + end + + return itemstack +end diff --git a/mods/doors/init.lua b/mods/doors/init.lua index 60f81e07..0888077f 100644 --- a/mods/doors/init.lua +++ b/mods/doors/init.lua @@ -185,7 +185,7 @@ end local function on_place_node(place_to, newnode, placer, oldnode, itemstack, pointed_thing) -- Run script hook - for _, callback in ipairs(core.registered_on_placenodes) do + for _, callback in ipairs(minetest.registered_on_placenodes) do -- Deepcopy pos, node and pointed_thing because callback can modify them local place_to_copy = {x = place_to.x, y = place_to.y, z = place_to.z} local newnode_copy = @@ -203,6 +203,14 @@ local function on_place_node(place_to, newnode, end end +local function can_dig_door(pos, digger) + local digger_name = digger and digger:get_player_name() + if digger_name and minetest.get_player_privs(digger_name).protection_bypass then + return true + end + return minetest.get_meta(pos):get_string("doors_owner") == digger_name +end + function doors.register(name, def) if not name:find(":") then name = "doors:" .. name @@ -273,8 +281,10 @@ function doors.register(name, def) end local above = {x = pos.x, y = pos.y + 1, z = pos.z} - if not minetest.registered_nodes[ - minetest.get_node(above).name].buildable_to then + local top_node = minetest.get_node_or_nil(above) + local topdef = top_node and minetest.registered_nodes[top_node.name] + + if not topdef or not topdef.buildable_to then return itemstack end @@ -336,21 +346,6 @@ function doors.register(name, def) end def.recipe = nil - local can_dig = function(pos, digger) - if not def.protected then - return true - end - if minetest.check_player_privs(digger, "protection_bypass") then - return true - end - local meta = minetest.get_meta(pos) - local owner_name - if digger then - owner_name = digger:get_player_name() - end - return meta:get_string("doors_owner") == owner_name - end - if not def.sounds then def.sounds = default.node_sound_wood_defaults() end @@ -379,14 +374,10 @@ function doors.register(name, def) minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z}) nodeupdate({x = pos.x, y = pos.y + 1, z = pos.z}) end - def.can_dig = function(pos, player) - return can_dig(pos, player) - end - def.on_rotate = function(pos, node, user, mode, new_param2) - return false - end + def.on_rotate = screwdriver and screwdriver.rotate_simple or false if def.protected then + def.can_dig = can_dig_door def.on_blast = function() end else def.on_blast = function(pos, intensity) @@ -540,16 +531,6 @@ function doors.register_trapdoor(name, def) local name_closed = name local name_opened = name.."_open" - local function check_player_priv(pos, player) - if not def.protected or - minetest.check_player_privs(player, "protection_bypass") then - return true - end - local meta = minetest.get_meta(pos) - local player_name = player and player:get_player_name() - return meta:get_string("doors_owner") == player_name - end - def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) _doors.trapdoor_toggle(pos, node, clicker) return itemstack @@ -560,9 +541,9 @@ function doors.register_trapdoor(name, def) def.paramtype = "light" def.paramtype2 = "facedir" def.is_ground_content = false - def.can_dig = check_player_priv if def.protected then + def.can_dig = can_dig_door def.after_place_node = function(pos, placer, itemstack, pointed_thing) local pn = placer:get_player_name() local meta = minetest.get_meta(pos) @@ -576,7 +557,6 @@ function doors.register_trapdoor(name, def) else def.on_blast = function(pos, intensity) minetest.remove_node(pos) - minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z}) return {name} end end @@ -604,8 +584,10 @@ function doors.register_trapdoor(name, def) type = "fixed", fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5} } - def_closed.tiles = {def.tile_front, def.tile_front, def.tile_side, def.tile_side, - def.tile_side, def.tile_side} + def_closed.tiles = {def.tile_front, + def.tile_front .. '^[transformFY', + def.tile_side, def.tile_side, + def.tile_side, def.tile_side} def_opened.node_box = { type = "fixed", @@ -618,7 +600,8 @@ function doors.register_trapdoor(name, def) def_opened.tiles = {def.tile_side, def.tile_side, def.tile_side .. '^[transform3', def.tile_side .. '^[transform1', - def.tile_front, def.tile_front} + def.tile_front .. '^[transform46', + def.tile_front .. '^[transform6'} def_opened.drop = name_closed def_opened.groups.not_in_creative_inventory = 1 @@ -655,8 +638,8 @@ doors.register_trapdoor("doors:trapdoor_steel", { minetest.register_craft({ output = 'doors:trapdoor 2', recipe = { - {'group:wood', 'group:wood', ''}, - {'group:wood', 'group:wood', ''}, + {'group:wood', 'group:wood', 'group:wood'}, + {'group:wood', 'group:wood', 'group:wood'}, {'', '', ''}, } }) @@ -721,7 +704,7 @@ function doors.register_fencegate(name, def) fence_open.collision_box = { type = "fixed", fixed = {{-1/2, -1/2, -1/4, -3/8, 1/2, 1/4}, - {-5/8, -3/8, -14/16, -3/8, 3/8, 0}}, + {-5/8, -3/8, -1/2, -3/8, 3/8, 0}}, } minetest.register_node(":" .. name .. "_closed", fence_closed) @@ -761,12 +744,12 @@ doors.register_fencegate("doors:gate_pine_wood", { description = "Pine Fence Gate", texture = "default_pine_wood.png", material = "default:pine_wood", - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2} + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3} }) doors.register_fencegate("doors:gate_aspen_wood", { description = "Aspen Fence Gate", texture = "default_aspen_wood.png", material = "default:aspen_wood", - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2} + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3} }) diff --git a/mods/farming b/mods/farming deleted file mode 160000 index de0e7dcc..00000000 --- a/mods/farming +++ /dev/null @@ -1 +0,0 @@ -Subproject commit de0e7dcc328df01e4934378efefb0cdd7a373e38 diff --git a/mods/fire/init.lua b/mods/fire/init.lua index 34613da5..6543ceef 100644 --- a/mods/fire/init.lua +++ b/mods/fire/init.lua @@ -221,6 +221,7 @@ end -- Extinguish all flames quickly with water, snow, ice minetest.register_abm({ + label = "Extinguish flame", nodenames = {"fire:basic_flame", "fire:permanent_flame"}, neighbors = {"group:puts_out_fire"}, interval = 3, @@ -234,13 +235,21 @@ minetest.register_abm({ }) --- Enable the following ABMs according to 'disable fire' setting +-- Enable the following ABMs according to 'enable fire' setting -if minetest.setting_getbool("disable_fire") then +local fire_enabled = minetest.setting_getbool("enable_fire") +if fire_enabled == nil then + -- New setting not specified, check for old setting. + -- If old setting is also not specified, 'not nil' is true. + fire_enabled = not minetest.setting_getbool("disable_fire") +end + +if not fire_enabled then -- Remove basic flames only minetest.register_abm({ + label = "Remove disabled fire", nodenames = {"fire:basic_flame"}, interval = 7, chance = 1, @@ -248,11 +257,12 @@ if minetest.setting_getbool("disable_fire") then action = minetest.remove_node, }) -else +else -- Fire enabled -- Ignite neighboring nodes, add basic flames minetest.register_abm({ + label = "Ignite flame", nodenames = {"group:flammable"}, neighbors = {"group:igniter"}, interval = 7, @@ -273,6 +283,7 @@ else -- Remove flammable nodes minetest.register_abm({ + label = "Remove flammable nodes", nodenames = {"fire:basic_flame"}, neighbors = "group:flammable", interval = 5, diff --git a/mods/flowers/init.lua b/mods/flowers/init.lua index c80375d9..c60d0897 100644 --- a/mods/flowers/init.lua +++ b/mods/flowers/init.lua @@ -110,6 +110,7 @@ function flowers.flower_spread(pos, node) end minetest.register_abm({ + label = "Flower spread", nodenames = {"group:flora"}, neighbors = {"default:dirt_with_grass", "default:dirt_with_dry_grass", "default:desert_sand"}, @@ -167,6 +168,7 @@ minetest.register_node("flowers:mushroom_brown", { -- Mushroom spread and death minetest.register_abm({ + label = "Mushroom spread", nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"}, interval = 11, chance = 50, @@ -206,6 +208,8 @@ minetest.register_alias("flowers:mushroom_spores_brown", "flowers:mushroom_brown minetest.register_alias("flowers:mushroom_spores_red", "flowers:mushroom_red") minetest.register_alias("flowers:mushroom_fertile_brown", "flowers:mushroom_brown") minetest.register_alias("flowers:mushroom_fertile_red", "flowers:mushroom_red") +minetest.register_alias("mushroom:brown_natural", "flowers:mushroom_brown") +minetest.register_alias("mushroom:red_natural", "flowers:mushroom_red") -- @@ -243,14 +247,17 @@ minetest.register_node("flowers:waterlily", { local def = minetest.registered_nodes[node] local player_name = placer:get_player_name() - if def and def.liquidtype == "source" and minetest.get_item_group(node, "water") > 0 then + if def and def.liquidtype == "source" and + minetest.get_item_group(node, "water") > 0 then if not minetest.is_protected(pos, player_name) then - minetest.set_node(pos, {name = "flowers:waterlily", param2 = math.random(0, 3)}) + minetest.set_node(pos, {name = "flowers:waterlily", + param2 = math.random(0, 3)}) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end else - minetest.chat_send_player(player_name, "This area is protected") - end - if not minetest.setting_getbool("creative_mode") then - itemstack:take_item() + minetest.chat_send_player(player_name, "Node is protected") + minetest.record_protection_violation(pos, player_name) end end return itemstack diff --git a/mods/nyancat/README.txt b/mods/nyancat/README.txt new file mode 100644 index 00000000..2e7de71d --- /dev/null +++ b/mods/nyancat/README.txt @@ -0,0 +1,29 @@ +Minetest Game mod: nyancat +========================== + +License of source code: +----------------------- +Copyright (C) 2011-2012 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +http://www.gnu.org/licenses/lgpl-2.1.html + +License of media (textures and sounds) +-------------------------------------- +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +http://creativecommons.org/licenses/by-sa/3.0/ + +Authors of media files +----------------------- +Everything not listed in here: +Copyright (C) 2010-2012 celeron55, Perttu Ahola + +VanessaE (WTFPL): + nyancat_front.png + nyancat_back.png + nyancat_side.png + nyancat_rainbow.png diff --git a/mods/nyancat/depends.txt b/mods/nyancat/depends.txt new file mode 100644 index 00000000..4ad96d51 --- /dev/null +++ b/mods/nyancat/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/nyancat/init.lua b/mods/nyancat/init.lua new file mode 100644 index 00000000..677ed50a --- /dev/null +++ b/mods/nyancat/init.lua @@ -0,0 +1,85 @@ +minetest.register_node("nyancat:nyancat", { + description = "Nyan Cat", + tiles = {"nyancat_side.png", "nyancat_side.png", "nyancat_side.png", + "nyancat_side.png", "nyancat_back.png", "nyancat_front.png"}, + paramtype2 = "facedir", + groups = {cracky = 2}, + is_ground_content = false, + legacy_facedir_simple = true, + sounds = default.node_sound_defaults(), +}) + +minetest.register_node("nyancat:nyancat_rainbow", { + description = "Nyan Cat Rainbow", + tiles = { + "nyancat_rainbow.png^[transformR90", + "nyancat_rainbow.png^[transformR90", + "nyancat_rainbow.png" + }, + paramtype2 = "facedir", + groups = {cracky = 2}, + is_ground_content = false, + sounds = default.node_sound_defaults(), +}) + +minetest.register_craft({ + type = "fuel", + recipe = "nyancat:nyancat", + burntime = 1, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "nyancat:nyancat_rainbow", + burntime = 1, +}) + +nyancat = {} + +function nyancat.place(pos, facedir, length) + if facedir > 3 then + facedir = 0 + end + local tailvec = minetest.facedir_to_dir(facedir) + local p = {x = pos.x, y = pos.y, z = pos.z} + minetest.set_node(p, {name = "nyancat:nyancat", param2 = facedir}) + for i = 1, length do + p.x = p.x + tailvec.x + p.z = p.z + tailvec.z + minetest.set_node(p, {name = "nyancat:nyancat_rainbow", param2 = facedir}) + end +end + +function nyancat.generate(minp, maxp, seed) + local height_min = -31000 + local height_max = -32 + if maxp.y < height_min or minp.y > height_max then + return + end + local y_min = math.max(minp.y, height_min) + local y_max = math.min(maxp.y, height_max) + local volume = (maxp.x - minp.x + 1) * (y_max - y_min + 1) * (maxp.z - minp.z + 1) + local pr = PseudoRandom(seed + 9324342) + local max_num_nyancats = math.floor(volume / (16 * 16 * 16)) + for i = 1, max_num_nyancats do + if pr:next(0, 1000) == 0 then + local x0 = pr:next(minp.x, maxp.x) + local y0 = pr:next(minp.y, maxp.y) + local z0 = pr:next(minp.z, maxp.z) + local p0 = {x = x0, y = y0, z = z0} + nyancat.place(p0, pr:next(0, 3), pr:next(3, 15)) + end + end +end + +minetest.register_on_generated(function(minp, maxp, seed) + nyancat.generate(minp, maxp, seed) +end) + +-- Legacy +minetest.register_alias("default:nyancat", "nyancat:nyancat") +minetest.register_alias("default:nyancat_rainbow", "nyancat:nyancat_rainbow") +minetest.register_alias("nyancat", "nyancat:nyancat") +minetest.register_alias("nyancat_rainbow", "nyancat:nyancat_rainbow") +default.make_nyancat = nyancat.place +default.generate_nyancats = nyancat.generate diff --git a/mods/default/textures/default_nc_back.png b/mods/nyancat/textures/nyancat_back.png similarity index 100% rename from mods/default/textures/default_nc_back.png rename to mods/nyancat/textures/nyancat_back.png diff --git a/mods/default/textures/default_nc_front.png b/mods/nyancat/textures/nyancat_front.png similarity index 100% rename from mods/default/textures/default_nc_front.png rename to mods/nyancat/textures/nyancat_front.png diff --git a/mods/default/textures/default_nc_rb.png b/mods/nyancat/textures/nyancat_rainbow.png similarity index 100% rename from mods/default/textures/default_nc_rb.png rename to mods/nyancat/textures/nyancat_rainbow.png diff --git a/mods/default/textures/default_nc_side.png b/mods/nyancat/textures/nyancat_side.png similarity index 100% rename from mods/default/textures/default_nc_side.png rename to mods/nyancat/textures/nyancat_side.png diff --git a/mods/screwdriver/init.lua b/mods/screwdriver/init.lua index 5e6df62f..e73b618f 100644 --- a/mods/screwdriver/init.lua +++ b/mods/screwdriver/init.lua @@ -64,6 +64,7 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses) end else if not ndef or not ndef.paramtype2 == "facedir" or + ndef.on_rotate == false or (ndef.drawtype == "nodebox" and not ndef.node_box.type == "fixed") or node.param2 == nil then diff --git a/mods/stairs/init.lua b/mods/stairs/init.lua index 81e2d111..38640778 100644 --- a/mods/stairs/init.lua +++ b/mods/stairs/init.lua @@ -239,6 +239,7 @@ end if replace then minetest.register_abm({ + label = "Slab replace", nodenames = {"group:slabs_replace"}, interval = 16, chance = 1, @@ -271,7 +272,7 @@ end stairs.register_stair_and_slab( "wood", "default:wood", - {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3}, + {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, {"default_wood.png"}, "Wooden Stair", "Wooden Slab", @@ -281,7 +282,7 @@ stairs.register_stair_and_slab( stairs.register_stair_and_slab( "junglewood", "default:junglewood", - {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3}, + {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, {"default_junglewood.png"}, "Jungle Wood Stair", "Jungle Wood Slab", @@ -291,7 +292,7 @@ stairs.register_stair_and_slab( stairs.register_stair_and_slab( "pine_wood", "default:pine_wood", - {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3}, + {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, {"default_pine_wood.png"}, "Pine Wood Stair", "Pine Wood Slab", @@ -301,7 +302,7 @@ stairs.register_stair_and_slab( stairs.register_stair_and_slab( "acacia_wood", "default:acacia_wood", - {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3}, + {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, {"default_acacia_wood.png"}, "Acacia Wood Stair", "Acacia Wood Slab", @@ -311,7 +312,7 @@ stairs.register_stair_and_slab( stairs.register_stair_and_slab( "aspen_wood", "default:aspen_wood", - {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3}, + {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, {"default_aspen_wood.png"}, "Aspen Wood Stair", "Aspen Wood Slab", diff --git a/mods/tnt/init.lua b/mods/tnt/init.lua index 4a704cc4..01758cd1 100644 --- a/mods/tnt/init.lua +++ b/mods/tnt/init.lua @@ -42,7 +42,7 @@ end local function eject_drops(drops, pos, radius) local drop_pos = vector.new(pos) for _, item in pairs(drops) do - local count = item:get_count() + local count = math.min(item:get_count(), item:get_stack_max()) while count > 0 do local take = math.max(1,math.min(radius * radius, count, @@ -78,7 +78,6 @@ local function add_drop(drops, item) end end - local function destroy(drops, npos, cid, c_air, c_fire, on_blast_queue, ignore_protection, ignore_on_blast) if not ignore_protection and minetest.is_protected(npos, "") then return cid @@ -102,7 +101,6 @@ local function destroy(drops, npos, cid, c_air, c_fire, on_blast_queue, ignore_p end end - local function calc_velocity(pos1, pos2, old_vel, power) -- Avoid errors caused by a vector of zero length if vector.equals(pos1, pos2) then @@ -488,28 +486,31 @@ minetest.register_node("tnt:gunpowder_burning", { end, }) -minetest.register_abm({ - nodenames = {"group:tnt", "tnt:gunpowder"}, - neighbors = {"fire:basic_flame", "default:lava_source", "default:lava_flowing"}, - interval = 4, - chance = 1, - action = tnt.burn, -}) - minetest.register_craft({ output = "tnt:gunpowder", type = "shapeless", recipe = {"default:coal_lump", "default:gravel"} }) -minetest.register_craft({ - output = "tnt:tnt", - recipe = { - {"", "group:wood", ""}, - {"group:wood", "tnt:gunpowder", "group:wood"}, - {"", "group:wood", ""} - } -}) +if enable_tnt then + minetest.register_craft({ + output = "tnt:tnt", + recipe = { + {"", "group:wood", ""}, + {"group:wood", "tnt:gunpowder", "group:wood"}, + {"", "group:wood", ""} + } + }) + + minetest.register_abm({ + label = "TNT ignition", + nodenames = {"group:tnt", "tnt:gunpowder"}, + neighbors = {"fire:basic_flame", "default:lava_source", "default:lava_flowing"}, + interval = 4, + chance = 1, + action = tnt.burn, + }) +end function tnt.register_tnt(def) local name @@ -588,4 +589,3 @@ tnt.register_tnt({ description = "TNT", radius = tnt_radius, }) -