diff --git a/asteroids.lua b/asteroids.lua index a0031ad..00d99e5 100644 --- a/asteroids.lua +++ b/asteroids.lua @@ -43,11 +43,17 @@ local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = local biome_noise = {offset = 0.0, scale = 1.0, spread = {x = 400, y = 400, z = 400}, seed = -1471, octaves = 3, persist = 0.5, lacunarity = 2.0} fun_caves.asteroids = function(minp, maxp, data, p2data, area, node) + if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then + return + end + if minp.y < 11168 or minp.y > 15168 then return end - math.randomseed(minetest.get_us_time()) + -- What's this for? + --math.randomseed(minetest.get_us_time()) + local density = 4 + math.abs(minp.y - 13168) / 500 local empty = false if math.random(math.floor(density)) ~= 1 then @@ -60,6 +66,9 @@ fun_caves.asteroids = function(minp, maxp, data, p2data, area, node) local map_min = {x = minp.x, y = minp.y, z = minp.z} local asteroid_1 = minetest.get_perlin_map(asteroid_noise_1, map_max):get3dMap_flat(map_min) + if not asteroid_1 then + return + end local write = false diff --git a/cavegen.lua b/cavegen.lua index 9d02834..7a4aa26 100644 --- a/cavegen.lua +++ b/cavegen.lua @@ -19,6 +19,10 @@ ground_nodes[minetest.get_content_id('default:dirt_with_dry_grass')] = true fun_caves.cavegen = function(minp, maxp, data, area, node, heightmap, underzone) + if not (minp and maxp and data and area and node and type(data) == 'table') then + return + end + local csize = vector.add(vector.subtract(maxp, minp), 1) local map_max = {x = csize.x, y = csize.y + 2, z = csize.z} local map_min = {x = minp.x, y = minp.y - 1, z = minp.z} @@ -32,6 +36,9 @@ fun_caves.cavegen = function(minp, maxp, data, area, node, heightmap, underzone) local cave_1 = minetest.get_perlin_map(fun_caves.cave_noise_1, map_max):get3dMap_flat(map_min) local cave_2 = minetest.get_perlin_map(fun_caves.cave_noise_2, map_max):get3dMap_flat(map_min) local cave_3 = minetest.get_perlin_map(cave_noise_3, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) + if not (cave_1 and cave_2 and cave_3) then + return + end local write = false diff --git a/chat.lua b/chat.lua index 79789e5..f14fd76 100644 --- a/chat.lua +++ b/chat.lua @@ -3,7 +3,15 @@ minetest.register_chatcommand("armor", { description = "Display your armor values", privs = {}, func = function(player_name, param) + if not (player_name and type(player_name) == 'string' and player_name ~= '') then + return + end + local player = minetest.get_player_by_name(player_name) + if not player then + return + end + local armor = player:get_armor_groups() if armor then minetest.chat_send_player(player_name, "Armor:") @@ -13,7 +21,12 @@ minetest.register_chatcommand("armor", { if fun_caves.db.status[player_name].armor_elixir then local armor_time = fun_caves.db.status[player_name].armor_elixir.remove - local min = math.floor(math.max(0, armor_time - minetest.get_gametime()) / 60) + local game_time = minetest.get_gametime() + if not (armor_time and type(armor_time) == 'number' and game_time and type(game_time) == 'number') then + return + end + + local min = math.floor(math.max(0, armor_time - game_time) / 60) minetest.chat_send_player(player_name, "Your armor elixir will expire in "..min..' minutes.') end end @@ -25,11 +38,19 @@ minetest.register_chatcommand("setspawn", { params = "", description = "change your spawn position", privs = {}, - func = function(name, param) - local player = minetest.get_player_by_name(name) + func = function(player_name, param) + if not (player_name and type(player_name) == 'string' and player_name ~= '') then + return + end + + local player = minetest.get_player_by_name(player_name) + if not player then + return + end + local pos = player:getpos() - beds.spawn[name] = pos - minetest.chat_send_player(name, 'Your spawn position has been changed.') + beds.spawn[player_name] = pos + minetest.chat_send_player(player_name, 'Your spawn position has been changed.') end, }) @@ -38,21 +59,38 @@ minetest.register_chatcommand("fixlight", { params = "", description = "attempt to fix light bugs", privs = {}, - func = function(name, param) - local privs = minetest.check_player_privs(name, {server=true}) + func = function(player_name, param) + if not (player_name and type(player_name) == 'string' and player_name ~= '') then + return + end + + local privs = minetest.check_player_privs(player_name, {server=true}) if not privs then return end - print('Fun Caves: '..name..' used the fixlight command') - local player = minetest.get_player_by_name(name) - local pos = vector.round(player:getpos()) + print('Fun Caves: '..player_name..' used the fixlight command') + local player = minetest.get_player_by_name(player_name) + if not player then + return + end + + local pos = player:getpos() + if not pos then + return + end + pos = vector.round(pos) + local radius = tonumber(param) or 50 radius = math.floor(radius) local minp = vector.subtract(pos, radius) local maxp = vector.add(pos, radius) local vm = minetest.get_voxel_manip(minp, maxp) + if not vm then + return + end + --vm:set_lighting({day = 0, night = 0}, minp, maxp) vm:calc_lighting(minp, maxp) vm:update_liquids() @@ -66,24 +104,39 @@ minetest.register_chatcommand("flatten", { params = "", description = "flatten terrain", privs = {}, - func = function(name, param) - local privs = minetest.check_player_privs(name, {server=true}) + func = function(player_name, param) + if not (player_name and type(player_name) == 'string' and player_name ~= '') then + return + end + + local privs = minetest.check_player_privs(player_name, {server=true}) if not privs then return end - print('Fun Caves: '..name..' used the flatten command') - local player = minetest.get_player_by_name(name) - local pos = vector.round(player:getpos()) + print('Fun Caves: '..player_name..' used the flatten command') + local player = minetest.get_player_by_name(player_name) + if not player then + return + end + + local pos = player:getpos() + if not pos then + return + end + pos = vector.round(pos) + local radius = tonumber(param) or 50 radius = math.floor(radius) local minp = vector.subtract(pos, radius) minp.y = minp.y - math.ceil(radius / 2) local maxp = vector.add(pos, radius) maxp.y = maxp.y + math.ceil(radius / 2) + local air = minetest.get_content_id('air') local stone = minetest.get_content_id('default:stone') local water = minetest.get_content_id('default:water_source') + local waters = {} waters[minetest.get_content_id('default:water_source')] = true waters[minetest.get_content_id('default:river_water_source')] = true @@ -94,6 +147,10 @@ minetest.register_chatcommand("flatten", { end local vm = minetest.get_voxel_manip(minp, maxp) + if not vm then + return + end + local emin, emax = vm:read_from_map(minp, maxp) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local data = vm:get_data() @@ -107,7 +164,7 @@ minetest.register_chatcommand("flatten", { for y = maxp.y, minp.y, -1 do if stones[data[ivm]] then if y >= maxp.y then - print('Terrain altitude exceeds the radius.') + minetest.chat_send_player(player_name, 'Terrain altitude exceeds the given radius.') return end heightmap[index] = y @@ -119,7 +176,7 @@ minetest.register_chatcommand("flatten", { end if not heightmap[index] then - print('Terrain altitude exceeds the radius.') + minetest.chat_send_player(player_name, 'Terrain altitude exceeds the given radius.') return end diff --git a/cloudgen.lua b/cloudgen.lua index e8a4072..3b9024f 100644 --- a/cloudgen.lua +++ b/cloudgen.lua @@ -1,4 +1,117 @@ -dofile(fun_caves.path .. "/deco_clouds.lua") + +local newnode = fun_caves.clone_node("default:dirt") +newnode.description = "Cloud" +newnode.tiles = {'fun_caves_cloud.png'} +newnode.sunlight_propagates = true +minetest.register_node("fun_caves:cloud", newnode) + +newnode = fun_caves.clone_node("default:dirt") +newnode.description = "Storm Cloud" +newnode.tiles = {'fun_caves_storm_cloud.png'} +--newnode.sunlight_propagates = true +minetest.register_node("fun_caves:storm_cloud", newnode) + +minetest.register_node("fun_caves:wispy_cloud", { + description = "Wispy Cloud", + tiles = {'fun_caves_wisp.png'}, + sunlight_propagates = true, + use_texture_alpha = true, + drawtype = "glasslike", + paramtype = 'light', + walkable = false, + buildable_to = true, + pointable = false, +}) + +minetest.register_node("fun_caves:moon_weed", { + description = "Moon Weed", + drawtype = "plantlike", + tiles = {"fun_caves_moon_weed.png"}, + inventory_image = "fun_caves_moon_weed.png", + waving = false, + sunlight_propagates = true, + paramtype = "light", + light_source = 8, + walkable = false, + groups = {snappy=3,flammable=2,flora=1,attached_node=1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}, + }, +}) + +minetest.register_node("fun_caves:leaves_lumin", { + description = "Leaves", + drawtype = "allfaces_optional", + waving = 1, + visual_scale = 1.3, + tiles = {"default_leaves.png^[colorize:#FFDF00:150"}, + special_tiles = {"default_leaves_simple.png^[colorize:#FFDF00:150"}, + paramtype = "light", + is_ground_content = false, + light_source = 8, + groups = {snappy = 3, leafdecay = 4, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + --{ + -- -- player will get sapling with 1/20 chance + -- items = {'default:sapling'}, + -- rarity = 20, + --}, + { + -- player will get leaves only if he get no saplings, + -- this is because max_items is 1 + items = {'fun_caves:leaves_lumin'}, + } + } + }, + sounds = default.node_sound_leaves_defaults(), + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("fun_caves:lumin_tree", { + description = "Lumin Tree", + tiles = { + "default_tree_top.png", "default_tree_top.png", "fun_caves_lumin_tree.png" + }, + paramtype = "light", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}, } + }, + paramtype2 = "facedir", + is_ground_content = false, + groups = {tree = 1, choppy = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + + on_place = minetest.rotate_node +}) + +newnode = fun_caves.clone_node("default:stone_with_iron") +newnode.description = "Silver Lining" +newnode.tiles = {'fun_caves_cloud.png^default_mineral_coal.png^[colorize:#FFFFFF:175'} +newnode.drop = "fun_caves:silver_lump" +minetest.register_node("fun_caves:silver_lining", newnode) + +minetest.register_craftitem("fun_caves:silver_lump", { + description = "Lump of Silver", + inventory_image = 'default_coal_lump.png^[colorize:#FFFFFF:175', +}) + +minetest.register_craftitem("fun_caves:silver_ingot", { + description = "Silver Ingot", + inventory_image = 'default_steel_ingot.png^[colorize:#FFFFFF:175', +}) + +minetest.register_craft({ + type = "cooking", + output = "fun_caves:silver_ingot", + recipe = "fun_caves:silver_lump", +}) local max_depth = 31000 @@ -10,6 +123,10 @@ local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = local biome_noise = {offset = 0.0, scale = 1.0, spread = {x = 400, y = 400, z = 400}, seed = -1471, octaves = 3, persist = 0.5, lacunarity = 2.0} fun_caves.cloudgen = function(minp, maxp, data, p2data, area, node) + if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then + return + end + if minp.y ~= 4368 then return end @@ -22,6 +139,9 @@ fun_caves.cloudgen = function(minp, maxp, data, p2data, area, node) local cloud_2 = minetest.get_perlin_map(cloud_noise_2, map_max):get3dMap_flat(map_min) local plant_n = minetest.get_perlin_map(plant_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) local biome_n = minetest.get_perlin_map(biome_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) + if not (cloud_1 and cloud_2 and plant_n and biome_n) then + return + end local write = false diff --git a/deco.lua b/deco.lua index e9cfd53..4d7f82d 100644 --- a/deco.lua +++ b/deco.lua @@ -137,6 +137,10 @@ end -- Create and initialize a table for a schematic. function fun_caves.schematic_array(width, height, depth) + if not (width and height and depth and type(width) == 'number' and type(height) == 'number' and type(depth) == 'number') then + return + end + -- Dimensions of data array. local s = {size={x=width, y=height, z=depth}} s.data = {} diff --git a/deco_clouds.lua b/deco_clouds.lua deleted file mode 100644 index f2b78e3..0000000 --- a/deco_clouds.lua +++ /dev/null @@ -1,114 +0,0 @@ - -local newnode = fun_caves.clone_node("default:dirt") -newnode.description = "Cloud" -newnode.tiles = {'fun_caves_cloud.png'} -newnode.sunlight_propagates = true -minetest.register_node("fun_caves:cloud", newnode) - -newnode = fun_caves.clone_node("default:dirt") -newnode.description = "Storm Cloud" -newnode.tiles = {'fun_caves_storm_cloud.png'} ---newnode.sunlight_propagates = true -minetest.register_node("fun_caves:storm_cloud", newnode) - -minetest.register_node("fun_caves:wispy_cloud", { - description = "Wispy Cloud", - tiles = {'fun_caves_wisp.png'}, - sunlight_propagates = true, - use_texture_alpha = true, - drawtype = "glasslike", - paramtype = 'light', - walkable = false, - buildable_to = true, - pointable = false, -}) - -minetest.register_node("fun_caves:moon_weed", { - description = "Moon Weed", - drawtype = "plantlike", - tiles = {"fun_caves_moon_weed.png"}, - inventory_image = "fun_caves_moon_weed.png", - waving = false, - sunlight_propagates = true, - paramtype = "light", - light_source = 8, - walkable = false, - groups = {snappy=3,flammable=2,flora=1,attached_node=1}, - sounds = default.node_sound_leaves_defaults(), - selection_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}, - }, -}) - -minetest.register_node("fun_caves:leaves_lumin", { - description = "Leaves", - drawtype = "allfaces_optional", - waving = 1, - visual_scale = 1.3, - tiles = {"default_leaves.png^[colorize:#FFDF00:150"}, - special_tiles = {"default_leaves_simple.png^[colorize:#FFDF00:150"}, - paramtype = "light", - is_ground_content = false, - light_source = 8, - groups = {snappy = 3, leafdecay = 4, flammable = 2, leaves = 1}, - drop = { - max_items = 1, - items = { - --{ - -- -- player will get sapling with 1/20 chance - -- items = {'default:sapling'}, - -- rarity = 20, - --}, - { - -- player will get leaves only if he get no saplings, - -- this is because max_items is 1 - items = {'fun_caves:leaves_lumin'}, - } - } - }, - sounds = default.node_sound_leaves_defaults(), - - after_place_node = default.after_place_leaves, -}) - -minetest.register_node("fun_caves:lumin_tree", { - description = "Lumin Tree", - tiles = { - "default_tree_top.png", "default_tree_top.png", "fun_caves_lumin_tree.png" - }, - paramtype = "light", - drawtype = "nodebox", - node_box = { - type = "fixed", - fixed = { {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}, } - }, - paramtype2 = "facedir", - is_ground_content = false, - groups = {tree = 1, choppy = 2, flammable = 2}, - sounds = default.node_sound_wood_defaults(), - - on_place = minetest.rotate_node -}) - -newnode = fun_caves.clone_node("default:stone_with_iron") -newnode.description = "Silver Lining" -newnode.tiles = {'fun_caves_cloud.png^default_mineral_coal.png^[colorize:#FFFFFF:175'} -newnode.drop = "fun_caves:silver_lump" -minetest.register_node("fun_caves:silver_lining", newnode) - -minetest.register_craftitem("fun_caves:silver_lump", { - description = "Lump of Silver", - inventory_image = 'default_coal_lump.png^[colorize:#FFFFFF:175', -}) - -minetest.register_craftitem("fun_caves:silver_ingot", { - description = "Silver Ingot", - inventory_image = 'default_steel_ingot.png^[colorize:#FFFFFF:175', -}) - -minetest.register_craft({ - type = "cooking", - output = "fun_caves:silver_ingot", - recipe = "fun_caves:silver_lump", -}) diff --git a/deco_plants.lua b/deco_plants.lua index 06e1872..8d68949 100644 --- a/deco_plants.lua +++ b/deco_plants.lua @@ -1,5 +1,9 @@ fun_caves.water_plants = {} local function register_water_plant(desc) + if not (desc and type(desc) == 'table') then + return + end + fun_caves.water_plants[#fun_caves.water_plants+1] = desc end @@ -129,6 +133,10 @@ for _, plant in ipairs(fun_caves.plantlist) do }, sounds = plant.sounds or default.node_sound_leaves_defaults(), after_dig_node = function(pos, oldnode, oldmetadata, digger) + if not (pos and oldnode) then + return + end + local replacement = oldnode.name:gsub('.*_water_(.*)', 'default:%1') if replacement:find('cloud$') then replacement = replacement:gsub('^default', 'fun_caves') @@ -151,6 +159,10 @@ end local function register_flower(name, seed, biomes) + if not (name and seed and biomes and type(name) == 'string' and type(seed) == 'number' and type(biomes) == 'table') then + return + end + local param = { deco_type = "simple", place_on = {"default:dirt_with_grass"}, diff --git a/deco_rocks.lua b/deco_rocks.lua index 737a192..5e09e21 100644 --- a/deco_rocks.lua +++ b/deco_rocks.lua @@ -1,5 +1,9 @@ -- Place a small nodebox. local function small_cube(grid, pos, diameters) + if not (grid and pos and diameters and type(grid) == 'table' and type(diameters) == 'table') then + return + end + local rock = {} rock[1] = pos.x @@ -83,6 +87,10 @@ minetest.register_node("fun_caves:small_rocks", { groups = {stone=1, oddly_breakable_by_hand=3, dig_immediate = 3}, sounds = default.node_sound_stone_defaults(), after_place_node = function(pos, placer, itemstack, pointed_thing) + if not pos then + return + end + minetest.set_node(pos, {name = "fun_caves:small_rocks"..math.random(6)}) end, }) diff --git a/decogen.lua b/decogen.lua index 022e6b6..89fba19 100644 --- a/decogen.lua +++ b/decogen.lua @@ -25,7 +25,11 @@ local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = -- Air needs to be placed prior to decorations. -fun_caves.decogen = function(minp, maxp, data, p2data, area, node, heightmap, biomemap, biome_ids, underzone, dis_map) +fun_caves.decogen = function(minp, maxp, data, p2data, area, node, heightmap, biomemap, biome_ids, underzone) + if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then + return + end + csize = vector.add(vector.subtract(maxp, minp), 1) local map_max = {x = csize.x, y = csize.y + 2, z = csize.z} @@ -33,6 +37,9 @@ fun_caves.decogen = function(minp, maxp, data, p2data, area, node, heightmap, bi local biome_n = minetest.get_perlin_map(biome_noise, map_max):get3dMap_flat(map_min) local plant_n = minetest.get_perlin_map(plant_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) + if not (biome_n and plant_n) then + return + end local math_random = math.random local dis_map = {} @@ -350,7 +357,11 @@ fun_caves.decogen = function(minp, maxp, data, p2data, area, node, heightmap, bi pos.x = x pos.y = y pos.z = z - local posm, count = minetest.find_nodes_in_area(pos, pos, desc.place_on) + local posm = minetest.find_nodes_in_area(pos, pos, desc.place_on) + if not (posm and type(posm) == 'table') then + return + end + if #posm > 0 then node_match_cache[desc.content_id][data[ivm]] = "good" else diff --git a/demon.lua b/demon.lua index ef8cd43..b70b017 100644 --- a/demon.lua +++ b/demon.lua @@ -14,6 +14,10 @@ minetest.register_node("fun_caves:freezing_vapor", { }) local function snow_effect(pos, radius) + if not (pos and radius and type(radius) == 'number') then + return + end + minetest.add_particlespawner({ amount = 30, time = 1, @@ -86,6 +90,10 @@ mobs:register_mob("fun_caves:ice_demon", { animation_speed = 30, fly_in = 'fun_caves:freezing_vapor', do_custom = function(self) + if not self then + return + end + -- This has to happen fast. if self.attack then self.fly = true @@ -163,6 +171,10 @@ local snow_demon = { }, animation_speed = 30, do_custom = function(self) + if not self then + return + end + if not self.attack then self.fly = false end @@ -185,9 +197,17 @@ local snow_demon = { fun_caves.register_status({ name = 'slow_cold', start = function(player) + if not player then + return + end + player:set_physics_override({speed=0.3}) end, terminate = function(player) + if not player then + return + end + player:set_physics_override({speed=1}) end, }) diff --git a/elixir.lua b/elixir.lua index b3e976f..7adb1bd 100644 --- a/elixir.lua +++ b/elixir.lua @@ -74,6 +74,7 @@ local elixir_ingredients = { 'fun_caves:orchid', 'fun_caves:petrified_wood', 'fun_caves:pillar_coral', + 'fun_caves:silver_lump', 'fun_caves:small_rocks', 'fun_caves:staghorn_coral', 'fun_caves:stalactite', @@ -148,16 +149,20 @@ if count > 15 then }) minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) - if itemstack:get_name() ~= "fun_caves:elixir" then + if not (player and itemstack and old_craft_grid and itemstack:get_name() == "fun_caves:elixir") then return end local ingredients = {} - for i = 1, player:get_inventory():get_size("craft") do + local inv = player:get_inventory() + if not inv then + return + end + + for i = 1, inv:get_size("craft") do local name = old_craft_grid[i]:get_name() - if name ~= '' and name ~= 'fun_caves:syrup' and not name:find('green_slimeball$') then + if name ~= '' and name ~= 'fun_caves:syrup' and type(name) == 'string' and not name:find('green_slimeball$') then ingredients[#ingredients+1] = name - --print(name) end end end) @@ -167,6 +172,10 @@ end fun_caves.register_status({ name = 'breathe', terminate = function(player) + if not player then + return + end + local player_name = player:get_player_name() minetest.chat_send_player(player_name, minetest.colorize('#FF0000', 'Your breathing becomes more difficult...')) end, @@ -176,8 +185,16 @@ minetest.register_craftitem("fun_caves:elixir_breathe", { description = 'Dr Robertson\'s Patented Easy Breathing Elixir', inventory_image = "fun_caves_elixir_breathe.png", on_use = function(itemstack, user, pointed_thing) + if not (itemstack and user) then + return + end + local player_name = user:get_player_name() - fun_caves.set_status(user:get_player_name(), 'breathe', elixir_duration) + if not (player_name and type(player_name) == 'string' and player_name ~= '') then + return + end + + fun_caves.set_status(player_name, 'breathe', elixir_duration) minetest.chat_send_player(player_name, 'Your breathing becomes easier...') itemstack:take_item() return itemstack @@ -207,6 +224,10 @@ minetest.register_craft({ fun_caves.register_status({ name = 'damage_elixir', terminate = function(player) + if not player then + return + end + local player_name = player:get_player_name() minetest.chat_send_player(player_name, minetest.colorize('#FF0000', 'You feel weaker...')) fun_caves.db.status[player_name].damage_elixir = nil @@ -217,10 +238,22 @@ fun_caves.register_status({ fun_caves.register_status({ name = 'armor_elixir', terminate = function(player) + if not player then + return + end + local player_name = player:get_player_name() + if not (player_name and type(player_name) == 'string' and player_name ~= '') then + return + end + local armor_elixir = fun_caves.db.status[player_name].armor_elixir local factor = armor_elixir.factor local armor = player:get_armor_groups() + if not (armor and armor.fleshy) then + return + end + armor.fleshy = math.min(100, math.max(1, math.ceil(armor.fleshy / factor))) player:set_armor_groups(armor) minetest.chat_send_player(player_name, minetest.colorize('#FF0000', 'Your skin feels softer...')) @@ -232,10 +265,22 @@ fun_caves.register_status({ if fun_caves.expire_elixir_on_death then minetest.register_on_dieplayer(function(player) + if not player then + return + end + local player_name = player:get_player_name() + if not (player_name and type(player_name) == 'string' and player_name ~= '') then + return + end + if fun_caves.db.status[player_name] and fun_caves.db.status[player_name].armor_elixir then local factor = fun_caves.db.status[player_name].armor_elixir.factor local armor = player:get_armor_groups() + if not (armor and armor.fleshy) then + return + end + armor.fleshy = math.min(100, math.max(1, math.ceil(armor.fleshy / factor))) player:set_armor_groups(armor) fun_caves.db.status[player_name].armor_elixir = nil @@ -246,7 +291,14 @@ end local function increase_damage(user, bonus) + if not user then + return + end + local player_name = user:get_player_name() + if not (player_name and type(player_name) == 'string' and player_name ~= '') then + return + end minetest.chat_send_player(player_name, 'You feel strong...') fun_caves.set_status(player_name, 'damage_elixir', elixir_duration, {bonus = bonus}) @@ -254,8 +306,19 @@ end local function armor(user, factor) + if not user then + return + end + local player_name = user:get_player_name() + if not (player_name and type(player_name) == 'string' and player_name ~= '') then + return + end + local armor = user:get_armor_groups() + if not (armor and armor.fleshy) then + return + end if fun_caves.db.status[player_name].armor_elixir then local old_factor = fun_caves.db.status[player_name].armor_elixir.factor @@ -297,6 +360,10 @@ if fun_caves.elixir_armor then groups = {dig_immediate = 3, vessel = 1}, sounds = default.node_sound_glass_defaults(), on_use = function(itemstack, user, pointed_thing) + if not (itemstack and user) then + return + end + armor(user, value) itemstack:take_item() return itemstack @@ -347,6 +414,10 @@ for _, desc in pairs(descs) do groups = {dig_immediate = 3, vessel = 1}, sounds = default.node_sound_glass_defaults(), on_use = function(itemstack, user, pointed_thing) + if not (itemstack and user) then + return + end + increase_damage(user, bonus) itemstack:take_item() return itemstack diff --git a/fortress.lua b/fortress.lua index c7f85b9..7234c88 100644 --- a/fortress.lua +++ b/fortress.lua @@ -89,7 +89,15 @@ newnode.description = "Treasure Chest" newnode.on_construct = nil newnode.drop = 'default:chest' newnode.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if not pos then + return + end + local meta = minetest.get_meta(pos) + if not meta then + return + end + local ready = meta:get_string('formspec') if ready == '' then local level = math.max(6, math.ceil(pos.y / math.floor(max_depth / 6))) @@ -123,6 +131,10 @@ function table.shuffle(self) end function unionfind(max) + if not (max and type(max) == 'number') then + return + end + local u = { _parent = {}, _rank = {} } for i = 0, max-1 do @@ -164,6 +176,10 @@ end local function maze_floor(y2, minp, maxp, data, area, node) + if not (y2 and minp and maxp and data and area and node and type(y2) == 'number' and type(data) == 'table') then + return + end + -- walls is zero-based. local walls = {} for i = 0, 2 * cells * cells - 1 do @@ -290,7 +306,12 @@ local designs = { {0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0}, }, } + local function design_floor(y2, minp, maxp, data, area, node) + if not (y2 and minp and maxp and data and area and node and type(y2) == 'number' and type(data) == 'table') then + return + end + local design = designs[math.random(#designs)] local py = minp.y + y2 * cell_size @@ -341,6 +362,10 @@ end fun_caves.fortress = function(minp_in, maxp_in, data, area, node) + if not (minp_in and maxp_in and data and area and node and type(data) == 'table') then + return + end + -- hungry maze -- chests (w traps) -- step traps (math based) @@ -357,6 +382,9 @@ fun_caves.fortress = function(minp_in, maxp_in, data, area, node) local treasure_count = 0 local csize = vector.add(vector.subtract(maxp_in, minp_in), 1) local floor_1 = minetest.get_perlin_map(floor_noise_1, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp_in.x, y=minp_in.z}) + if not floor_1 then + return + end for y2 = 0, cells-1 do local floor_type = math.random(20) diff --git a/fungal_tree.lua b/fungal_tree.lua index e97cd40..13ea6fe 100644 --- a/fungal_tree.lua +++ b/fungal_tree.lua @@ -39,6 +39,10 @@ minetest.register_node("fun_caves:fungal_tree_fruit", { local fruit = minetest.get_content_id("fun_caves:fungal_tree_fruit") function fun_caves.make_fungal_tree(data, area, ivm, height) + if not (data and area and ivm and height and type(data) == 'table' and type(ivm) == 'number' and type(height) == 'number') then + return + end + local leaf = minetest.get_content_id(fungal_tree_leaves[math.random(#fungal_tree_leaves)]) local air = minetest.get_content_id('air') for y = 0, height do diff --git a/goblin.lua b/goblin.lua index b30519a..a8d8af7 100644 --- a/goblin.lua +++ b/goblin.lua @@ -61,7 +61,7 @@ local traps = { local function goblin_do(self) - if not fun_caves.custom_ready(self) then + if not (self and fun_caves.custom_ready(self)) then return end @@ -412,7 +412,16 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - for _,object in ipairs(minetest.get_objects_inside_radius(pos, 0.95)) do -- IDKWTF this is but it works + if not pos then + return + end + + local objects = minetest.get_objects_inside_radius(pos, 0.95) + if not (objects and type(objects) == 'table') then + return + end + + for _, object in ipairs(objects) do -- IDKWTF this is but it works if object:is_player() then object:set_physics_override({speed = 0.1}) minetest.after(1, function() -- this effect is temporary @@ -442,7 +451,16 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - for _,object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do + if not pos then + return + end + + local objects = minetest.get_objects_inside_radius(pos, 2) + if not (objects and type(objects) == 'table') then + return + end + + for _, object in ipairs(objects) do if object:is_player() then minetest.set_node(pos, {name="fire:basic_flame"}) if object:get_hp() > 0 then @@ -459,6 +477,10 @@ local diamond_trap if (not singleplayer and setting ~= true) or (singleplayer and setting == false) then -- wimpier trap for non-tnt settings diamond_trap = function(pos, player) + if not (pos and player) then + return + end + minetest.set_node(pos, {name="default:lava_source"}) if player:get_hp() > 0 then player:set_hp(player:get_hp()-2) @@ -468,8 +490,15 @@ if (not singleplayer and setting ~= true) or (singleplayer and setting == false) else -- 5... 4... 3... 2... 1... diamond_trap = function(pos, player) + if not (pos and player) then + return + end + minetest.set_node(pos, {name="tnt:tnt_burning"}) - minetest.get_node_timer(pos):start(5) + local timer = minetest.get_node_timer(pos) + if timer then + timer:start(5) + end minetest.sound_play("default_dig_crumbly", {pos = pos, gain = 0.5, max_hear_distance = 10}) end end @@ -482,6 +511,10 @@ minetest.register_node("fun_caves:stone_with_diamond_trap", { is_ground_content = false, sounds = default.node_sound_stone_defaults(), on_dig = function(pos, node, digger) + if not (pos and digger) then + return + end + if math.random(3) == 1 then diamond_trap(pos, digger) else @@ -495,7 +528,16 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos) - for _,object in ipairs(minetest.get_objects_inside_radius(pos, 3)) do + if not pos then + return + end + + local objects = minetest.get_objects_inside_radius(pos, 3) + if not (objects and type(objects) == 'table') then + return + end + + for _,object in ipairs(objects) do if object:is_player() then diamond_trap(pos, object) end @@ -536,6 +578,10 @@ bucket.register_liquid( ) local gold_trap = function(pos, player) + if not (pos and player) then + return + end + minetest.set_node(pos, {name="fun_caves:molten_gold_source"}) minetest.sound_play("default_dig_crumbly", {pos = pos, gain = 0.5, max_hear_distance = 10}) end @@ -548,6 +594,10 @@ minetest.register_node("fun_caves:stone_with_gold_trap", { is_ground_content = false, sounds = default.node_sound_stone_defaults(), on_dig = function(pos, node, digger) + if not (pos and digger) then + return + end + if math.random(3) == 1 then gold_trap(pos, digger) else @@ -561,7 +611,16 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos) - for _,object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do + if not pos then + return + end + + local objects = minetest.get_objects_inside_radius(pos, 2) + if not (objects and type(objects) == 'table') then + return + end + + for _,object in ipairs(objects) do if object:is_player() then gold_trap(pos, object) end @@ -571,15 +630,24 @@ minetest.register_abm({ local ice_trap = function(pos, player) + if not (pos and player) then + return + end + local ppos = player:getpos() if ppos then ppos.y = ppos.y + 1 local p1 = vector.subtract(ppos, 2) local p2 = vector.add(ppos, 2) local nodes = minetest.find_nodes_in_area(p1, p2, 'air') + if not (nodes and type(nodes) == 'table') then + return + end + for _, npos in pairs(nodes) do minetest.set_node(npos, {name="default:ice"}) end + minetest.set_node(pos, {name="default:ice"}) end end @@ -592,6 +660,10 @@ minetest.register_node("fun_caves:ice_trap", { is_ground_content = false, sounds = default.node_sound_stone_defaults(), on_dig = function(pos, node, digger) + if not (pos and digger) then + return + end + if math.random(3) == 1 then ice_trap(pos, digger) else @@ -605,7 +677,16 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos) - for _,object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do + if not pos then + return + end + + local objects = minetest.get_objects_inside_radius(pos, 2) + if not (objects and type(objects) == 'table') then + return + end + + for _,object in ipairs(objects) do if object:is_player() then ice_trap(pos, object) end @@ -615,6 +696,10 @@ minetest.register_abm({ local function lightning_effects(pos, radius) + if not (pos and radius) then + return + end + minetest.add_particlespawner({ amount = 30, time = 1, @@ -633,6 +718,10 @@ local function lightning_effects(pos, radius) end local copper_trap = function(pos, player) + if not (pos and player) then + return + end + if player:get_hp() > 0 then player:set_hp(player:get_hp()-1) lightning_effects(pos, 3) @@ -648,6 +737,10 @@ minetest.register_node("fun_caves:stone_with_copper_trap", { is_ground_content = false, sounds = default.node_sound_stone_defaults(), on_dig = function(pos, node, digger) + if not (pos and digger) then + return + end + if math.random(3) == 1 then copper_trap(pos, digger) else @@ -662,7 +755,16 @@ minetest.register_abm({ interval = 1, chance = 2, action = function(pos) - for _,object in ipairs(minetest.get_objects_inside_radius(pos, 3)) do + if not pos then + return + end + + local objects = minetest.get_objects_inside_radius(pos, 3) + if not (objects and type(objects) == 'table') then + return + end + + for _,object in ipairs(objects) do if object:is_player() then copper_trap(pos, object) end @@ -681,6 +783,10 @@ minetest.register_node("fun_caves:stone_with_iron_trap", { is_ground_content = false, sounds = default.node_sound_stone_defaults(), on_dig = function(pos, node, digger) + if not (pos and digger) then + return + end + if math.random(3) == 1 then copper_trap(pos, digger) else @@ -694,7 +800,16 @@ minetest.register_abm({ interval = 2, chance = 2, action = function(pos, node, active_object_count, active_object_count_wider) - for _,object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do + if not pos then + return + end + + local objects = minetest.get_objects_inside_radius(pos, 3) + if not (objects and type(objects) == 'table') then + return + end + + for _, object in ipairs(objects) do if object:is_player() then copper_trap(pos, object) end diff --git a/mapgen.lua b/mapgen.lua index 0c1cf0d..9eb27d3 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -8,9 +8,14 @@ local fortress_noise = {offset = 0, scale = 1, seed = -4082, spread = {x = 7, y -- This tables looks up nodes that aren't already stored. local node = setmetatable({}, { __index = function(t, k) + if not (t and k and type(t) == 'table') then + return + end + t[k] = minetest.get_content_id(k) return t[k] - end}) + end +}) local data = {} local p2data = {} -- vm rotation data buffer @@ -41,6 +46,10 @@ end --end fun_caves.is_fortress = function(pos, cs) + if not pos then + return + end + -- Fix this to get csize, somehow. -- Remember that this function may be called -- before any chunks are generated. @@ -60,6 +69,10 @@ fun_caves.is_fortress = function(pos, cs) local z = math.floor((pos.z + offset) / cs.z) local n = minetest.get_perlin(fortress_noise):get3d({x=x, y=y, z=z}) + if not (n and type(n) == 'number') then + return + end + if math.floor((n * 10000) % (fun_caves.DEBUG and 4 or 19)) == 1 then return true end @@ -68,6 +81,10 @@ fun_caves.is_fortress = function(pos, cs) end fun_caves.place_schematic = function(minp, maxp, data, p2data, area, node, pos, schem, center) + if not (minp and maxp and data and p2data and area and node and pos and schem and type(data) == 'table' and type(p2data) == 'table' and type(schem) == 'table') then + return + end + local rot = math.random(4) - 1 local yslice = {} if schem.yslice_prob then @@ -119,6 +136,10 @@ fun_caves.place_schematic = function(minp, maxp, data, p2data, area, node, pos, end fun_caves.surround = function(node, data, area, ivm) + if not (node and data and area and ivm and type(data) == 'table' and type(ivm) == 'number') then + return + end + -- Check to make sure that a plant root is fully surrounded. -- This is due to the kludgy way you have to make water plants -- in minetest, to avoid bubbles. @@ -345,8 +366,16 @@ fun_caves.cave_biomes = { local function generate(p_minp, p_maxp, seed) + if not (p_minp and p_maxp and seed) then + return + end + local minp, maxp = p_minp, p_maxp local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + if not (vm and emin and emax) then + return + end + vm:get_data(data) p2data = vm:get_param2_data() local heightmap @@ -358,7 +387,14 @@ local function generate(p_minp, p_maxp, seed) end -- use the same seed (based on perlin noise). - math.randomseed(minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z})) + do + local seed = minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z}) + if not (seed and type(seed) == 'number') then + return + end + + math.randomseed(seed) + end local write = false local write_p2, write_p4 = false, false diff --git a/mobs.lua b/mobs.lua index bf93dad..01355b4 100644 --- a/mobs.lua +++ b/mobs.lua @@ -1,12 +1,19 @@ -- search/replace -- lets mobs change the terrain -- used for goblin traps and torch thieving fun_caves.search_replace = function(pos, search_rate, replace_what, replace_with) + if not (pos and search_rate and replace_what and replace_with and type(search_rate) == 'number' and type(replace_what) == 'string' and type(replace_with) == 'string') then + return + end + if math.random(search_rate) == 1 then local p1 = vector.subtract(pos, 1) local p2 = vector.add(pos, 1) --look for nodes local nodelist = minetest.find_nodes_in_area(p1, p2, replace_what) + if not (nodelist and type(nodelist) == 'table') then + return + end if #nodelist > 0 then for _, new_pos in pairs(nodelist) do @@ -18,6 +25,10 @@ fun_caves.search_replace = function(pos, search_rate, replace_what, replace_with end function fun_caves.climb(self) + if not self then + return + end + if self.state == "stand" and math.random() < 0.2 then if self.fall_speed == 2 then self.fall_speed = -2 @@ -31,44 +42,61 @@ end -- causes mobs to take damage from hot/cold surfaces fun_caves.surface_damage = function(self, cold_natured) - --if not self.fun_caves_damage_timer then - -- self.fun_caves_damage_timer = 0 - --end + if not self then + return + end - --self.fun_caves_damage_timer = self.fun_caves_damage_timer + 1 - --if self.fun_caves_damage_timer > 30 then - -- self.fun_caves_damage_timer = 0 - local pos = self.object:getpos() - local minp = vector.subtract(pos, 1.5) - local maxp = vector.add(pos, 1.5) - local counts = 0 - if self.lava_damage > 1 then - counts = minetest.find_nodes_in_area(minp, maxp, {"group:surface_hot"}) - if #counts > 0 then - self.health = self.health - math.floor(self.lava_damage / 2) - effect(pos, 5, "fire_basic_flame.png") - end + local pos = self.object:getpos() + if not pos then + return + end + + local minp = vector.subtract(pos, 1.5) + local maxp = vector.add(pos, 1.5) + local counts = 0 + if self.lava_damage > 1 then + counts = minetest.find_nodes_in_area(minp, maxp, {"group:surface_hot"}) + if not (counts and type(counts) == 'table') then + return end - if not cold_natured then - counts = minetest.find_nodes_in_area(minp, maxp, {"group:surface_cold"}) - if #counts > 0 then - self.health = self.health - 1 - end + if #counts > 0 then + self.health = self.health - math.floor(self.lava_damage / 2) + effect(pos, 5, "fire_basic_flame.png") + end + end + + if not cold_natured then + counts = minetest.find_nodes_in_area(minp, maxp, {"group:surface_cold"}) + if not (counts and type(counts) == 'table') then + return end - check_for_death(self) - --end + if #counts > 0 then + self.health = self.health - 1 + end + end + + check_for_death(self) end -- executed in a mob's do_custom() to regulate their actions -- if false, do nothing local custom_delay = 2000000 fun_caves.custom_ready = function(self, delay) + if not self then + return + end + local time = minetest.get_us_time() + if not (time and type(time) == 'number') then + return + end + if not delay then delay = custom_delay end + if not self.custom_time or time - self.custom_time > delay then self.custom_time = time return true @@ -156,12 +184,17 @@ for _, mob in pairs(mob_stats) do end local function fun_caves_punch(self, puncher, time_from_last_punch, tool_capabilities, dir) + if not self then + return + end + if puncher and puncher.get_player_name then local player_name = puncher:get_player_name() - if player_name and player_name ~= '' and fun_caves.db.status[player_name] and fun_caves.db.status[player_name].damage_elixir and tool_capabilities and tool_capabilities.damage_groups and tool_capabilities.damage_groups.fleshy then + if player_name and type(player_name) == 'string' and player_name ~= '' and fun_caves.db.status[player_name] and fun_caves.db.status[player_name].damage_elixir and tool_capabilities and tool_capabilities.damage_groups and tool_capabilities.damage_groups.fleshy then tool_capabilities.damage_groups.fleshy = tool_capabilities.damage_groups.fleshy + fun_caves.db.status[player_name].damage_elixir.bonus end end + self.on_punch_orig(self, puncher, time_from_last_punch, tool_capabilities, dir) end @@ -214,6 +247,10 @@ if minetest.registered_entities["dmobs:dragon"] and minetest.registered_entities local m = table.copy(minetest.registered_entities["mobs_yeti:snowball"]) m.hit_player = function(self, player) + if not (self and player) then + return + end + player:punch(self.object, 1.0, { full_punch_interval = 1.0, damage_groups = {fleshy = 8}, @@ -221,6 +258,10 @@ if minetest.registered_entities["dmobs:dragon"] and minetest.registered_entities end m.hit_mob = function(self, player) + if not (self and player) then + return + end + player:punch(self.object, 1.0, { full_punch_interval = 1.0, damage_groups = {fleshy = 8}, @@ -236,7 +277,7 @@ if minetest.registered_entities["dmobs:fox"] then -- fire_walk overwrites bones, under some circumstances. -- Keep it disabled until it's definitely working. local function fire_walk(self) - if not fun_caves.custom_ready(self, 1000000) then + if not (self and fun_caves.custom_ready(self, 1000000)) then return end @@ -246,6 +287,10 @@ if minetest.registered_entities["dmobs:fox"] then --look for nodes local nodelist = minetest.find_nodes_in_area(p1, p2, "air") + if not (nodelist and type(nodelist) == 'table') then + return + end + for n in pairs(nodelist) do --minetest.set_node(pos, {name='fire:basic_flame'}) end @@ -310,7 +355,7 @@ mobs:register_mob("fun_caves:star", { fall_damage = 0, lifetimer = 360, do_custom = function(self) - if not fun_caves.custom_ready(self) then + if not (self and fun_caves.custom_ready(self)) then return end @@ -326,7 +371,7 @@ mobs:spawn_specific("fun_caves:star", {'default:stone', 'fun_caves:asteroid_wate if minetest.registered_entities["mobs:bee"] then local function bee_summon(self) - if self.state ~= 'attack' then + if not (self and self.state == 'attack') then return end @@ -345,11 +390,14 @@ if minetest.registered_entities["mobs:bee"] then --look for nodes local nodelist = minetest.find_nodes_in_area(p1, p2, "air") + if not (nodelist and type(nodelist) == 'table') then + return + end if #nodelist > 0 then for key,value in pairs(nodelist) do minetest.add_entity(value, "fun_caves:killer_bee_drone") - print("A bee summons reinforcement.") + print("Fun Caves: A bee summons reinforcement.") return -- only one at a time end end @@ -357,7 +405,7 @@ if minetest.registered_entities["mobs:bee"] then end local function bee_do(self) - if not fun_caves.custom_ready(self) then + if not (self and fun_caves.custom_ready(self)) then return end @@ -513,7 +561,7 @@ if minetest.registered_entities["mobs_monster:spider"] then } m.water_damage = 0 m.do_custom = function(self) - if not fun_caves.custom_ready(self) then + if not (self and fun_caves.custom_ready(self)) then return end @@ -540,7 +588,7 @@ if minetest.registered_entities["mobs_monster:spider"] then } m.water_damage = 0 m.do_custom = function(self) - if not fun_caves.custom_ready(self) then + if not (self and fun_caves.custom_ready(self)) then return end @@ -573,7 +621,7 @@ if minetest.registered_entities["mobs_monster:spider"] then {name = "farming:cotton", chance = 2, min = 1, max = 2}, } m.do_custom = function(self) - if not fun_caves.custom_ready(self) then + if not (self and fun_caves.custom_ready(self)) then return end @@ -608,6 +656,10 @@ if minetest.registered_entities["mobs_monster:spider"] then m.jump = false m.drops = { {name = "mobs:meat_raw", chance = 1, min = 1, max = 1}, } m.do_custom = function(self) + if not self then + return + end + if not self.fun_caves_damage_timer then self.fun_caves_damage_timer = 0 end diff --git a/nodes.lua b/nodes.lua index 36f76fc..744632a 100644 --- a/nodes.lua +++ b/nodes.lua @@ -4,6 +4,10 @@ local max_depth = 31000 local old_is_protected = minetest.is_protected function minetest.is_protected(pos, name) + if not (pos and name and type(name) == 'string') then + return + end + local node = get_node_or_nil(pos) if node and get_item_group(node.name, "fortress") ~= 0 then return true @@ -133,6 +137,10 @@ minetest.register_craft({ }) local function rope_remove(pos) + if not pos then + return + end + for i = 1, 100 do local newpos = table.copy(pos) newpos.y = newpos.y - i @@ -166,19 +174,21 @@ for length = 10, 50, 10 do legacy_wallmounted = true, sounds = default.node_sound_leaves_defaults(), after_place_node = function(pos, placer, itemstack, pointed_thing) - if pointed_thing and pointed_thing.above then - local pos = pointed_thing.above - local orig = minetest.get_node_or_nil(pos) - if orig and orig.name and orig.param2 and good_params[orig.param2] then - for i = 1, length do - local newpos = table.copy(pos) - newpos.y = newpos.y - i - local node = minetest.get_node_or_nil(newpos) - if node and node.name and node.name == 'air' then - minetest.set_node(newpos, {name='fun_caves:rope_ladder_piece', param2=orig.param2}) - else - break - end + if not (pointed_thing and pointed_thing.above) then + return + end + + local pos_old = pointed_thing.above + local orig = minetest.get_node_or_nil(pos_old) + if orig and orig.name and orig.param2 and good_params[orig.param2] then + for i = 1, length do + local newpos = table.copy(pos_old) + newpos.y = newpos.y - i + local node = minetest.get_node_or_nil(newpos) + if node and node.name and node.name == 'air' then + minetest.set_node(newpos, {name='fun_caves:rope_ladder_piece', param2=orig.param2}) + else + break end end end diff --git a/pyramid.lua b/pyramid.lua index fee0b25..e5296a1 100644 --- a/pyramid.lua +++ b/pyramid.lua @@ -34,7 +34,15 @@ newnode.light_source = 1 newnode.on_construct = nil newnode.drop = 'default:chest' newnode.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if not (pos and clicker) then + return + end + local meta = minetest.get_meta(pos) + if not meta then + return + end + local ready = meta:get_string('formspec') if ready == '' then @@ -65,6 +73,10 @@ local pyramid_noise_1 = {offset = 0, scale = 1, seed = -6012, spread = {x = 20, fun_caves.pyramid = function(minp, maxp, data, p2data, area, biomemap, biome_ids, node, heightmap) + if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then + return + end + if math.random(20) ~= 1 then return end @@ -104,6 +116,9 @@ fun_caves.pyramid = function(minp, maxp, data, p2data, area, biomemap, biome_ids local map_min = {x = minp.x, y = minp.y, z = minp.z} local pyramid_1 = minetest.get_perlin_map(pyramid_noise_1, map_max):get3dMap_flat(map_min) + if not pyramid_1 then + return + end local write = true local p2write = false diff --git a/skyseagen.lua b/skyseagen.lua index 4c23975..8bf1970 100644 --- a/skyseagen.lua +++ b/skyseagen.lua @@ -17,6 +17,10 @@ local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = local biome_noise = {offset = 0.0, scale = 1.0, spread = {x = 400, y = 400, z = 400}, seed = -1471, octaves = 3, persist = 0.5, lacunarity = 2.0} fun_caves.skysea = function(minp, maxp, data, p2data, area, node) + if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then + return + end + if minp.y ~= 8768 then return end @@ -26,6 +30,9 @@ fun_caves.skysea = function(minp, maxp, data, p2data, area, node) local terrain_1 = minetest.get_perlin_map(terrain_noise_1, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) local plant_n = minetest.get_perlin_map(plant_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) local biome_n = minetest.get_perlin_map(biome_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) + if not (terrain_1 and plant_n and biome_n) then + return + end local write = false diff --git a/spec_bomb.lua b/spec_bomb.lua index c0a8d14..b5d6675 100644 --- a/spec_bomb.lua +++ b/spec_bomb.lua @@ -1,9 +1,17 @@ local function disintigrate(pos, radius, node_name, user_name, dropped) + if not (pos and radius and node_name and user_name and type(radius) == 'number' and type(user_name) == 'string') then + return + end + local node_id = minetest.get_content_id(node_name) local air = minetest.get_content_id('air') local minp = vector.subtract(pos, radius) local maxp = vector.add(pos, radius) local vm = minetest.get_voxel_manip() + if not vm then + return + end + local emin, emax = vm:read_from_map(minp, maxp) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local data = vm:get_data() @@ -50,6 +58,10 @@ end local function floor(pos, blocks, node_name, user_name) + if not (pos and blocks and node_name and user_name and type(blocks) == 'number' and type(node_name) == 'string' and type(user_name) == 'string') then + return + end + local p = {y = pos.y} local count = 0 for r = 1, blocks do @@ -90,14 +102,21 @@ for _, node in pairs(nodes) do newnode.inventory_image = '[inventorycube{tnt_top.png{'..node_texture..'{tnt_side.png' newnode.drop = bomb_name newnode.on_punch = function(pos, node, puncher, pointed_thing) - if puncher:get_wielded_item():get_name() ~= "default:torch" then + if not (pos and puncher) then return end + + local wield = puncher:get_wielded_item() + if not wield or wield:get_name() ~= "default:torch" then + return + end + minetest.after(5, function() local pos_node = minetest.get_node_or_nil(pos) - if pos_node.name ~= bomb_name then + if not (pos_node and pos_node.name == bomb_name) then return end + disintigrate(pos, 5, node_name, puncher:get_player_name(), comp) minetest.remove_node(pos) end) @@ -137,14 +156,21 @@ for _, node in pairs(nodes) do newnode.inventory_image = '[inventorycube{'..node_texture..'{'..node_texture..'{'..node_texture..'^fun_caves_expand.png' newnode.drop = bomb_name newnode.on_punch = function(pos, node, puncher, pointed_thing) - if puncher:get_wielded_item():get_name() ~= "default:torch" then + if not (pos and puncher) then return end + + local wield = puncher:get_wielded_item() + if not wield or wield:get_name() ~= "default:torch" then + return + end + minetest.after(5, function() local pos_node = minetest.get_node_or_nil(pos) - if pos_node.name ~= bomb_name then + if not (pos_node and pos_node.name == bomb_name) then return end + floor(pos, 100, node_name, puncher:get_player_name()) minetest.set_node(pos, {name = node_name}) end) @@ -217,6 +243,10 @@ local function power(player, pos, tool_type, max) local air = minetest.get_content_id('air') local vm = minetest.get_voxel_manip() + if not vm then + return + end + local emin, emax = vm:read_from_map(minp, maxp) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local data = vm:get_data() @@ -270,7 +300,10 @@ local function power(player, pos, tool_type, max) local tp = tool:get_tool_capabilities() local def = ItemStack({name=names[id]}):get_definition() local dp = minetest.get_dig_params(def.groups, tp) - print(dp.wear) + if not dp then + return + end + tool:add_wear(dp.wear * number) end @@ -289,11 +322,16 @@ minetest.register_tool("fun_caves:chainsaw", { damage_groups = {fleshy=4}, }, on_use = function(itemstack, user, pointed_thing) + if not (user and pointed_thing) then + return + end + minetest.sound_play('chainsaw', { object = user, gain = 0.1, max_hear_distance = 30 }) + return power(user, pointed_thing.under, 'axe') end, }) @@ -310,11 +348,16 @@ minetest.register_tool("fun_caves:jackhammer", { damage_groups = {fleshy=4}, }, on_use = function(itemstack, user, pointed_thing) + if not (user and pointed_thing) then + return + end + minetest.sound_play('jackhammer', { object = user, gain = 0.1, max_hear_distance = 30 }) + return power(user, pointed_thing.under, 'pick') end, }) diff --git a/tesseract.lua b/tesseract.lua index c30d2ae..d627e06 100644 --- a/tesseract.lua +++ b/tesseract.lua @@ -1,12 +1,15 @@ local max_depth = 31000 local function teleporter(user, area, power) - if not user then + if not (user and area and power and type(power) == 'number') then return end local name = user:get_player_name() local pos = user:getpos() + if not (name and pos and name ~= '' and type(name) == 'string') then + return + end if not fun_caves.db.teleport_data[name] then fun_caves.db.teleport_data[name] = {} @@ -84,10 +87,18 @@ local function teleporter(user, area, power) c1 = minetest.get_perlin(fun_caves.cave_noise_1):get3d(newpos) c2 = minetest.get_perlin(fun_caves.cave_noise_2):get3d(newpos) + if not (c1 and c2 and type(c1) == 'number' and type(c2) == 'number') then + return + end + if c1 * c2 > fun_caves.cave_width then newpos.y = newpos.y - 1 c1 = minetest.get_perlin(fun_caves.cave_noise_1):get3d(newpos) c2 = minetest.get_perlin(fun_caves.cave_noise_2):get3d(newpos) + if not (c1 and c2 and type(c1) == 'number' and type(c2) == 'number') then + return + end + if c1 * c2 > fun_caves.cave_width then good = true break @@ -312,7 +323,15 @@ minetest.register_craft({ local function translocate(pos, node, clicker, itemstack, pointed_thing) + if not (pos and clicker) then + return + end + local meta = minetest.get_meta(pos) + if not meta then + return + end + local id = meta:get_string('id') local owner = meta:get_string('owner') if not (id and tonumber(id)) then @@ -348,6 +367,10 @@ local function translocate(pos, node, clicker, itemstack, pointed_thing) minetest.set_node(pos2, {name = 'fun_caves:translocator'}) local meta = minetest.get_meta(pos2) + if not meta then + return + end + meta:set_string('id', id) meta:set_string('owner', owner) @@ -357,19 +380,21 @@ local function translocate(pos, node, clicker, itemstack, pointed_thing) end local function trans_use(itemstack, user, pointed_thing) - if not itemstack then + if not (itemstack and user) then return end + local data = minetest.deserialize(itemstack:get_metadata()) if not (data and data.id) then return end + local player_name = user:get_player_name() minetest.chat_send_player(player_name, "You see a serial number: "..data.id) end local function trans_place(itemstack, placer, pointed_thing) - if not (itemstack and pointed_thing) then + if not (itemstack and placer and pointed_thing) then return end @@ -395,6 +420,10 @@ local function trans_place(itemstack, placer, pointed_thing) if place_good then pair[#pair+1] = pos local meta = minetest.get_meta(pos) + if not meta then + return + end + meta:set_string('id', data.id) meta:set_string('owner', data.owner) end @@ -402,7 +431,7 @@ local function trans_place(itemstack, placer, pointed_thing) end local function trans_dig(pos, node, digger) - if not (pos and digger) then + if not (pos and node and digger) then return end @@ -412,6 +441,10 @@ local function trans_dig(pos, node, digger) end local meta = minetest.get_meta(pos) + if not meta then + return + end + local id = meta:get_string('id') local owner = meta:get_string('owner') if owner == '' then @@ -452,7 +485,15 @@ local function trans_dig(pos, node, digger) end local function trans_dest(pos) + if not pos then + return + end + local meta = minetest.get_meta(pos) + if not meta then + return + end + local id = meta:get_string('id') local owner = meta:get_string('owner') if not (id and owner) then @@ -470,6 +511,10 @@ local function trans_dest(pos) end minetest.set_node(pos, {name = 'fun_caves:translocator'}) local meta = minetest.get_meta(pos) + if not meta then + return + end + meta:set_string('id', id) meta:set_string('owner', owner) @@ -515,7 +560,7 @@ for _, gem in pairs(gems) do end minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) - if itemstack:get_name() ~= "fun_caves:translocator" then + if not (itemstack and player and itemstack:get_name() == "fun_caves:translocator") then return end diff --git a/treegen.lua b/treegen.lua index a4aaa58..9d06376 100644 --- a/treegen.lua +++ b/treegen.lua @@ -178,28 +178,6 @@ minetest.register_node("fun_caves:syrup", { sounds = default.node_sound_glass_defaults(), }) -minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) - local name = itemstack:get_name() - if not (name and name == 'fun_caves:syrup') then - return - end - - local bucket - local index - for i = 1, player:get_inventory():get_size("craft") do - if (old_craft_grid[i]:get_name()):find('^fun_caves:bucket') then - bucket = old_craft_grid[i]:get_name() - index = i - end - end - if not bucket then - return - end - - bucket = bucket:gsub('sap', 'empty') - craft_inv:set_stack("craft", index, bucket) -end) - newnode = fun_caves.clone_node("default:tree") newnode.description = "Glowing Fungal Wood" newnode.tiles = {"fun_caves_tree.png^vmg_glowing_fungal.png",} @@ -282,6 +260,32 @@ minetest.register_craft({ }, }) +minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) + if not (itemstack and player and old_craft_grid and craft_inv) then + return + end + + local name = itemstack:get_name() + if not (name and name == 'fun_caves:syrup') then + return + end + + local bucket + local index + for i = 1, player:get_inventory():get_size("craft") do + if (old_craft_grid[i]:get_name()):find('^fun_caves:bucket') then + bucket = old_craft_grid[i]:get_name() + index = i + end + end + if not bucket then + return + end + + bucket = bucket:gsub('sap', 'empty') + craft_inv:set_stack("craft", index, bucket) +end) + minetest.register_craft({ type = "cooking", output = "fun_caves:amber", @@ -305,8 +309,12 @@ local wood_noise = {offset = 0, scale = 1, seed = -4640, spread = {x = 32, y = 3 fun_caves.treegen = function(minp, maxp, data, p2data, area, node) + if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then + return + end + local tree_n = minetest.get_perlin(tree_noise_1):get2d({x=math.floor((minp.x + 32) / 160) * 80, y=math.floor((minp.z + 32) / 160) * 80}) - if minp.y < -112 or minp.y > 208 or (not fun_caves.DEBUG and tree_n < 1) then + if not tree_n or minp.y < -112 or minp.y > 208 or (not fun_caves.DEBUG and tree_n < 1) then return end @@ -315,6 +323,9 @@ fun_caves.treegen = function(minp, maxp, data, p2data, area, node) local map_min = {x = minp.x, y = minp.y - 1, z = minp.z} local wood_1 = minetest.get_perlin_map(wood_noise, map_max):get3dMap_flat(map_min) + if not wood_1 then + return + end local write = false diff --git a/village.lua b/village.lua index 8a1f3e3..5fa31e0 100644 --- a/village.lua +++ b/village.lua @@ -29,7 +29,7 @@ if mobs and mobs.mod == "redo" then end end local function savage_gathering(self) - if not fun_caves.custom_ready(self) then + if not (self and fun_caves.custom_ready(self)) then return end @@ -45,7 +45,10 @@ if mobs and mobs.mod == "redo" then local p = soil[math.random(#soil)] p.y = p.y + 1 minetest.add_node(p, {name = 'farming:seed_wheat', param2 = 1}) - minetest.get_node_timer(p):start(math.random(166, 286)) + local timer = minetest.get_node_timer(p) + if timer then + timer:start(math.random(166, 286)) + end end end @@ -115,6 +118,10 @@ end local function build_hut(data, area, node, pos, turf) + if not (data and area and node and pos and turf and type(data) == 'table') then + return + end + local door = {x = ({2,7})[math.random(2)], z = ({2,7})[math.random(2)]} for z = 1, 8 do @@ -151,6 +158,10 @@ local function build_hut(data, area, node, pos, turf) end fun_caves.village = function(minp, maxp, data, p2data, area, node, biome, heightmap) + if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then + return + end + if not biome or math.random(10) ~= 1 then return end diff --git a/wallhammer.lua b/wallhammer.lua index d8614e1..8973128 100644 --- a/wallhammer.lua +++ b/wallhammer.lua @@ -23,34 +23,11 @@ local default_material = { } local function parti(pos) - minetest.add_particlespawner(25, 0.3, - pos, pos, - {x=2, y=0.2, z=2}, {x=-2, y=2, z=-2}, - {x=0, y=-6, z=0}, {x=0, y=-10, z=0}, - 0.2, 1, - 0.2, 2, - true, "wallhammer_parti.png") -end - -local function get_pointed_thing(player, range) - local plpos = player:getpos() - plpos.y = plpos.y+1.625 - local dir = player:get_look_dir() - local p2 = vector.add(plpos, vector.multiply(dir, range)) - local _,pos = minetest.line_of_sight(plpos, p2) if not pos then return end - local check = minetest.get_node(pos) - if string.find(check.name, '_foot') then - pos = vector.add(pos, dir) - print('added') - end - return { - under = vector.round(pos), - above = vector.round(vector.subtract(pos, dir)), - type = "node" - } + + minetest.add_particlespawner(25, 0.3, pos, pos, {x=2, y=0.2, z=2}, {x=-2, y=2, z=-2}, {x=0, y=-6, z=0}, {x=0, y=-10, z=0}, 0.2, 1, 0.2, 2, true, "wallhammer_parti.png") end minetest.register_tool( "fun_caves:wall_hammer",{ @@ -66,13 +43,23 @@ minetest.register_tool( "fun_caves:wall_hammer",{ damage_groups = {fleshy=4}, }, on_use = function(itemstack, user, pointed_thing) + if not (pointed_thing and user and itemstack) then + return + end if pointed_thing.type ~= "node" then return end local pos = pointed_thing.under + if not pos then + return + end + local node = minetest.get_node(pos) + if not node then + return + end for i in ipairs (default_material) do local item = default_material [i][1] @@ -85,7 +72,11 @@ minetest.register_tool( "fun_caves:wall_hammer",{ end if node.name == item then - minetest.set_node(pos,{name = "fun_caves:"..mat.."_foot", param2=minetest.dir_to_facedir(user:get_look_dir())}) + local node = { + name = "fun_caves:"..mat.."_foot", + param2=minetest.dir_to_facedir(user:get_look_dir()) + } + minetest.set_node(pos, node) parti(pos) end end diff --git a/wooden_buckets.lua b/wooden_buckets.lua index 564ca3e..62d4e90 100644 --- a/wooden_buckets.lua +++ b/wooden_buckets.lua @@ -1,61 +1,66 @@ local function register_liquid_wood(source, itemname, inventory_image, name, groups) - if itemname ~= nil then - if inventory_image then - inventory_image = inventory_image..'^fun_caves_wood_bucket_overlay.png' - end - minetest.register_craftitem(itemname, { - description = name, - inventory_image = inventory_image, - stack_max = 1, - liquids_pointable = true, - groups = groups, - - on_place = function(itemstack, user, pointed_thing) - -- Must be pointing to node - if pointed_thing.type ~= "node" then - return - end - - local node = minetest.get_node_or_nil(pointed_thing.under) - local ndef = node and minetest.registered_nodes[node.name] - - -- Call on_rightclick if the pointed node defines it - if ndef and ndef.on_rightclick and - user and not user:get_player_control().sneak then - return ndef.on_rightclick( - pointed_thing.under, - node, user, - itemstack) - end - - local lpos - - -- Check if pointing to a buildable node - if ndef and ndef.buildable_to then - -- buildable; replace the node - lpos = pointed_thing.under - else - -- not buildable to; place the liquid above - -- check if the node above can be replaced - lpos = pointed_thing.above - local node = minetest.get_node_or_nil(lpos) - local above_ndef = node and minetest.registered_nodes[node.name] - - if not above_ndef or not above_ndef.buildable_to then - -- do not remove the bucket with the liquid - return itemstack - end - end - - if minetest.is_protected(lpos, user and user:get_player_name() or "") then - return - end - - minetest.set_node(lpos, {name = source}) - return ItemStack("fun_caves:bucket_wood_empty") - end - }) + if not (source and itemname and inventory_image and name and type(source) == 'string' and type(itemname) == 'string' and type(inventory_image) == 'string') then + return end + + inventory_image = inventory_image..'^fun_caves_wood_bucket_overlay.png' + minetest.register_craftitem(itemname, { + description = name, + inventory_image = inventory_image, + stack_max = 1, + liquids_pointable = true, + groups = groups, + + on_place = function(itemstack, user, pointed_thing) + if not (user and pointed_thing) then + return + end + + -- Must be pointing to node + if pointed_thing.type ~= "node" then + return + end + + local node = minetest.get_node_or_nil(pointed_thing.under) + local ndef = node and minetest.registered_nodes[node.name] + + -- Call on_rightclick if the pointed node defines it + if ndef and ndef.on_rightclick and + user and not user:get_player_control().sneak then + return ndef.on_rightclick(pointed_thing.under, node, user, itemstack) + end + + local lpos + + -- Check if pointing to a buildable node + if ndef and ndef.buildable_to then + -- buildable; replace the node + lpos = pointed_thing.under + else + -- not buildable to; place the liquid above + -- check if the node above can be replaced + lpos = pointed_thing.above + local node = minetest.get_node_or_nil(lpos) + if not node then + return + end + + local above_ndef = node and minetest.registered_nodes[node.name] + + if not above_ndef or not above_ndef.buildable_to then + -- do not remove the bucket with the liquid + return itemstack + end + end + + if minetest.is_protected(lpos, user and user:get_player_name() or "") then + return + end + + minetest.set_node(lpos, {name = source}) + return ItemStack("fun_caves:bucket_wood_empty") + end + }) end for fluid, def in pairs(bucket.liquids) do @@ -86,11 +91,16 @@ minetest.register_craftitem("fun_caves:bucket_wood_empty", { liquids_pointable = true, on_use = function(itemstack, user, pointed_thing) -- Must be pointing to node - if pointed_thing.type ~= "node" then + if not (user and pointed_thing and pointed_thing.type == "node") then return end + -- Check if pointing to a liquid source local node = minetest.get_node(pointed_thing.under) + if not node then + return + end + local liquiddef = bucket.liquids[node.name] if node.name ~= liquiddef.source then return