From 6752e72679668a3f75504f17ed80faa74a36e440 Mon Sep 17 00:00:00 2001 From: Duane Robertson Date: Sun, 18 Sep 2016 18:38:12 -0500 Subject: [PATCH] Initial large pod work. --- deco.lua | 267 +++++++++++++++++------ depends.txt | 14 +- init.lua | 421 ++++++++++++++++++++++++++++++++---- mapgen.lua | 605 +++++++++++++++++++++++++++++++++++++++++----------- nodes.lua | 6 +- 5 files changed, 1073 insertions(+), 240 deletions(-) diff --git a/deco.lua b/deco.lua index e46a8ac..ee0076e 100644 --- a/deco.lua +++ b/deco.lua @@ -1,32 +1,121 @@ ------------------ --- Decorations -- ------------------ +local low_size = 138 +local road_level = 1 +local dirt_depth = 5 +local water_diff = 8 +local water_level = road_level - water_diff --- The main decoration handler, through the game's decoration manager. - - --- A list of all schematics, for re-use. loud_walking.schematics = {} -function table.contains_substring(t, s) - if type(s) ~= "string" then - return nil +local math_floor = math.floor +local math_ceil = math.ceil +local math_abs = math.abs +local math_random = math.random + +local csize + +local heat_noise = {offset = 50, scale = 50, seed = 5349, spread = {x = 750, y = 750, z = 750}, octaves = 3, persist = 0.5, lacunarity = 2} +local heat_blend_noise = {offset = 0, scale = 1.5, seed = 13, spread = {x = 8, y = 8, z = 8}, octaves = 2, persist = 1.0, lacunarity = 2} +local humidity_noise = {offset = 50, scale = 50, seed = 842, spread = {x = 750, y = 750, z = 750}, octaves = 3, persist = 0.5, lacunarity = 2} +local humidity_blend_noise = {offset = 0, scale = 1.5, seed = 90003, spread = {x = 8, y = 8, z = 8}, octaves = 2, persist = 1.0, lacunarity = 2} + + +do + local biome_mod = { + coniferous_forest_dunes = { heat_point = 35, humidity_point = 60, }, + coniferous_forest = { heat_point = 35, humidity_point = 60, }, + coniferous_forest_ocean = { heat_point = 35, humidity_point = 60, }, + deciduous_forest = { heat_point = 60, humidity_point = 60, }, + deciduous_forest_ocean = { heat_point = 60, humidity_point = 60, }, + deciduous_forest_swamp = { heat_point = 60, humidity_point = 60, }, + desert = { heat_point = 80, humidity_point = 10, }, + desert_ocean = { heat_point = 80, humidity_point = 10, }, + glacier = {}, + glacier_ocean = {}, + rainforest = { heat_point = 85, humidity_point = 70, }, + rainforest_ocean = { heat_point = 85, humidity_point = 70, }, + rainforest_swamp = { heat_point = 85, humidity_point = 70, }, + sandstone_grassland_dunes = { heat_point = 55, humidity_point = 40, }, + sandstone_grassland = { heat_point = 55, humidity_point = 40, }, + sandstone_grassland_ocean = { heat_point = 55, humidity_point = 40, }, + savanna = { heat_point = 80, humidity_point = 25, }, + savanna_ocean = { heat_point = 80, humidity_point = 25, }, + savanna_swamp = { heat_point = 80, humidity_point = 25, }, + stone_grassland_dunes = { heat_point = 35, humidity_point = 40, }, + stone_grassland = { heat_point = 35, humidity_point = 40, }, + stone_grassland_ocean = { heat_point = 35, humidity_point = 40, }, + taiga = {}, + taiga_ocean = {}, + tundra = { node_river_water = "loud_walking:thin_ice", }, + tundra_beach = { node_river_water = "loud_walking:thin_ice", }, + tundra_ocean = {}, + } + local rereg = {} + + for n, bi in pairs(biome_mod) do + for i, rbi in pairs(minetest.registered_biomes) do + if rbi.name == n then + rereg[#rereg+1] = table.copy(rbi) + for j, prop in pairs(bi) do + rereg[#rereg][j] = prop + end + end + end end - for key, value in pairs(t) do - if type(value) == 'string' and s:find(value) then - if key then - return key - else - return true - end - end - end - return false + minetest.clear_registered_biomes() + + for _, bi in pairs(rereg) do + minetest.register_biome(bi) + end + + rereg = {} + for _, dec in pairs(minetest.registered_decorations) do + rereg[#rereg+1] = dec + end + minetest.clear_registered_decorations() + for _, dec in pairs(rereg) do + minetest.register_decoration(dec) + end + rereg = nil + + + minetest.register_biome({ + name = "desertstone_grassland", + --node_dust = "", + node_top = "default:dirt_with_grass", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 1, + node_stone = "default:desert_stone", + node_riverbed = "default:sand", + depth_riverbed = 2, + --node_water_top = "", + --depth_water_top = , + --node_water = "", + --node_river_water = "", + y_min = 6, + y_max = 31000, + heat_point = 80, + humidity_point = 55, + }) + + + minetest.register_decoration({ + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 80, + fill_ratio = 0.1, + biomes = {"desertstone_grassland", }, + y_min = 1, + y_max = 31000, + decoration = "default:junglegrass", + }) end --- Copy all the decorations except the ones I don't like. +flowers.register_decorations() + + loud_walking.decorations = {} local bad_deco = {} for _, i in pairs({"apple_tree", "pine_tree", "jungle_tree", "acacia_tree", "aspen_tree", }) do @@ -35,7 +124,7 @@ end do for _, odeco in pairs(minetest.registered_decorations) do - if not bad_deco[odeco.schematic] then + if not odeco.schematic then local deco = {} if odeco.biomes then deco.biomes = {} @@ -50,7 +139,7 @@ do deco.fill_ratio = odeco.fill_ratio if odeco.noise_params then - deco.fill_ratio = math.max(0.001, odeco.noise_params.scale + odeco.noise_params.offset) + deco.fill_ratio = math.max(0.001, (odeco.noise_params.scale + odeco.noise_params.offset) / 4) end local nod = minetest.registered_nodes[deco.decoration] @@ -65,31 +154,6 @@ end minetest.clear_registered_decorations() --- Create and initialize a table for a schematic. -function loud_walking.schematic_array(width, height, depth) - -- Dimensions of data array. - local s = {size={x=width, y=height, z=depth}} - s.data = {} - - for z = 0,depth-1 do - for y = 0,height-1 do - for x = 0,width-1 do - local i = z*width*height + y*width + x + 1 - s.data[i] = {} - s.data[i].name = "air" - s.data[i].param1 = 000 - end - end - end - - s.yslice_prob = {} - - return s -end - - -dofile(loud_walking.path.."/deco_trees.lua") - local function register_flower(name, desc, biomes, chance) local groups = {} @@ -160,24 +224,91 @@ local function register_decoration(deco, place_on, biomes, chance) } end -if crops then - register_decoration( - "crops:pumpkin_plant_4", - { "default:dirt_with_grass" }, - {"stone_grassland", "sandstone_grassland", "deciduous_forest", - "coniferous_forest"}, - 0.002 - ) - register_decoration( - "crops:melon_plant_4", - { "default:dirt_with_grass" }, - {"deciduous_forest", "coniferous_forest", "tundra"}, - 0.002 - ) - register_decoration( - "crops:tomato_plant_4", - { "default:dirt_with_grass" }, - {"rainforest"}, - 0.002 - ) + +loud_walking.biomes = {} +local biomes = loud_walking.biomes +local biome_names = {} +do + --local biome_terrain_scale = {} + --biome_terrain_scale["coniferous_forest"] = 0.75 + --biome_terrain_scale["rainforest"] = 0.33 + --biome_terrain_scale["underground"] = 1.5 + + local tree_biomes = {} + tree_biomes["deciduous_forest"] = {"apple_tree", 'aspen_tree'} + tree_biomes["coniferous_forest"] = {"pine_tree"} + tree_biomes["taiga"] = {"pine_tree"} + tree_biomes["rainforest"] = {"jungle_tree"} + tree_biomes["rainforest_swamp"] = {"jungle_tree"} + tree_biomes["coniferous_forest"] = {"pine_tree"} + tree_biomes["savanna"] = {"acacia_tree"} + + for i, obiome in pairs(minetest.registered_biomes) do + local biome = table.copy(obiome) + biome.special_tree_prob = 2 * 25 + if string.match(biome.name, "^rainforest") then + biome.special_tree_prob = 0.8 * 25 + end + if biome.name == "savanna" then + biome.special_tree_prob = 30 * 25 + end + --biome.terrain_scale = biome_terrain_scale[biome] or 0.5 + --if string.find(biome.name, "ocean") then + -- biome.terrain_scale = 1 + --end + --if string.find(biome.name, "swamp") then + -- biome.terrain_scale = 0.25 + --end + --if string.find(biome.name, "beach") then + -- biome.terrain_scale = 0.25 + --end + --if string.find(biome.name, "^underground$") then + -- biome.node_top = "default:stone" + --end + biome.special_trees = tree_biomes[biome.name] + biomes[biome.name] = biome + biome_names[#biome_names+1] = biome.name + end end + + +local function get_decoration(biome_name) + for i, deco in pairs(loud_walking.decorations) do + if not deco.biomes or deco.biomes[biome_name] then + local range = 1000 + if deco.deco_type == "simple" then + if deco.fill_ratio and math.random(range) - 1 < deco.fill_ratio * 1000 then + return deco.decoration + end + else + -- nop + end + end + end +end + + +-- Create and initialize a table for a schematic. +function loud_walking.schematic_array(width, height, depth) + -- Dimensions of data array. + local s = {size={x=width, y=height, z=depth}} + s.data = {} + + for z = 0,depth-1 do + for y = 0,height-1 do + for x = 0,width-1 do + local i = z*width*height + y*width + x + 1 + s.data[i] = {} + s.data[i].name = "air" + s.data[i].param1 = 000 + end + end + end + + s.yslice_prob = {} + + return s +end + + +dofile(loud_walking.path.."/deco_trees.lua") diff --git a/depends.txt b/depends.txt index 16acb5d..3f2c161 100644 --- a/depends.txt +++ b/depends.txt @@ -1,7 +1,19 @@ default flowers +wool +bucket +beds +stairs +vessels +mobs +farming? +hunger? +mobs_monster? +mobs_creeper? +kpgmobs? +mobs_fish? +3d_armor? crops? ethereal? -farming? farming_plus? moreores? diff --git a/init.lua b/init.lua index 8660490..cd70333 100644 --- a/init.lua +++ b/init.lua @@ -1,46 +1,74 @@ --- Check for necessary mod functions and abort if they aren't available. -if not minetest.get_biome_id then - minetest.log() - minetest.log("* Not loading Cityscape *") - minetest.log("Cityscape requires mod functions which are") - minetest.log(" not exposed by your Minetest build.") - minetest.log() - return -end - loud_walking = {} loud_walking.version = "1.0" +loud_walking.time_factor = 10 -- affects growth abms +loud_walking.light_max = 8 -- light intensity for mushroom growth loud_walking.path = minetest.get_modpath(minetest.get_current_modname()) -loud_walking.first_flag = 0 +loud_walking.world = minetest.get_worldpath() +loud_walking.breakable_wood = minetest.setting_getbool('loud_walking_breakable_wood') +if loud_walking.breakable_wood == nil then + loud_walking.breakable_wood = false +end + +local armor_mod = minetest.get_modpath("3d_armor") and armor and armor.set_player_armor + +loud_walking.elixir_armor = minetest.setting_getbool('loud_walking_use_armor_elixirs') +if loud_walking.elixir_armor == nil then + loud_walking.elixir_armor = true +end + +loud_walking.expire_elixir_on_death = minetest.setting_getbool('loud_walking_expire_elixir_on_death') +if loud_walking.expire_elixir_on_death == nil then + loud_walking.expire_elixir_on_death = true +end + +loud_walking.breakable_wood = minetest.setting_getbool('loud_walking_breakable_wood') +if loud_walking.breakable_wood == nil then + loud_walking.breakable_wood = false +end + +loud_walking.starting_equipment = minetest.setting_getbool('loud_walking_starting_equipment') +if loud_walking.starting_equipment == nil then + loud_walking.starting_equipment = false +end + +loud_walking.quick_leaf_decay = minetest.setting_getbool('loud_walking_quick_leaf_decay') +if loud_walking.quick_leaf_decay == nil then + loud_walking.quick_leaf_decay = false +end + +loud_walking.DEBUG = false -- for maintenance only + + +local inp = io.open(loud_walking.world..'/loud_walking_data.txt','r') +if inp then + local d = inp:read('*a') + loud_walking.db = minetest.deserialize(d) + inp:close() +end +if not loud_walking.db then + loud_walking.db = {} +end +for _, i in pairs({'teleport_data', 'hunger', 'status', 'translocators'}) do + if not loud_walking.db[i] then + loud_walking.db[i] = {} + end +end + + +if not minetest.set_mapgen_setting then + return +end minetest.register_on_mapgen_init(function(mgparams) minetest.set_mapgen_params({mgname="singlenode", flags="nolight"}) end) -if default then - if default.register_ores then - default.register_ores() - end - if default.register_blobs then - default.register_blobs() - end - if default.register_biomes then - default.register_biomes() - end - if default.register_decorations then - default.register_decorations() - end - if flowers.register_decorations then - flowers.register_decorations() - end -end - -- Modify a node to add a group function minetest.add_group(node, groups) local def = minetest.registered_items[node] - if not def then + if not (node and def and groups and type(groups) == 'table') then return false end local def_groups = def.groups or {} @@ -56,39 +84,340 @@ function minetest.add_group(node, groups) end function loud_walking.clone_node(name) + if not (name and type(name) == 'string') then + return + end + local node = minetest.registered_nodes[name] local node2 = table.copy(node) return node2 end -function loud_walking.node(name) - if not loud_walking.node_cache then - loud_walking.node_cache = {} + +loud_walking.registered_status = {} +function loud_walking.register_status(def) + if not (def and loud_walking.registered_status and type(def) == 'table') then + return end - if not loud_walking.node_cache[name] then - loud_walking.node_cache[name] = minetest.get_content_id(name) - if name ~= "ignore" and loud_walking.node_cache[name] == 127 then - print("*** Failure to find node: "..name) - end - end - - return loud_walking.node_cache[name] + loud_walking.registered_status[def.name] = { + remove = def.remove, + start = def.start, + during = def.during, + terminate = def.terminate, + } end +function loud_walking.set_status(player_name, status, time, param) + if not (player_name and type(player_name) == 'string' and status and type(status) == 'string') and loud_walking.db and loud_walking.db.status and loud_walking.db.status[player_name] then + return + end + + local player = minetest.get_player_by_name(player_name) + local def = loud_walking.registered_status[status] + if not (def and player) then + return + end + + if not param then + param = {} + end + + if time then + param.remove = (minetest.get_gametime() or 0) + time + end + + loud_walking.db.status[player_name][status] = param + if def.start then + def.start(player) + end +end + +function loud_walking.remove_status(player_name, status) + if not (player_name and type(player_name) == 'string' and status and type(status) == 'string') and loud_walking.db and loud_walking.db.status and loud_walking.db.status[player_name] then + return + end + + local player = minetest.get_player_by_name(player_name) + local def = loud_walking.registered_status[status] + if player and def then + if def.terminate then + loud_walking.db.status[player_name][status] = def.terminate(player) + else + loud_walking.db.status[player_name][status] = nil + end + end +end + + +--dofile(loud_walking.path .. "/recipe_list.lua") dofile(loud_walking.path .. "/nodes.lua") dofile(loud_walking.path .. "/deco.lua") dofile(loud_walking.path .. "/deco_caves.lua") +--dofile(loud_walking.path .. "/schematics.lua") +--dofile(loud_walking.path .. "/wallhammer.lua") dofile(loud_walking.path .. "/mapgen.lua") +--dofile(loud_walking.path .. "/wooden_buckets.lua") +--dofile(loud_walking.path .. "/tools.lua") +--dofile(loud_walking.path .. "/molotov.lua") +--dofile(loud_walking.path .. "/elixir.lua") +--dofile(loud_walking.path .. "/chat.lua") + +if minetest.get_modpath("mobs") and mobs and mobs.mod == "redo" then + --dofile(loud_walking.path .. "/mobs.lua") +end + +--dofile(loud_walking.path .. "/abms.lua") + +--loud_walking.print_recipes() -minetest.register_on_newplayer(loud_walking.respawn) -minetest.register_on_respawnplayer(loud_walking.respawn) +-- Attempt to save data at shutdown (as well as periodically). +minetest.register_on_shutdown(function() + local out = io.open(loud_walking.world..'/loud_walking_data.txt','w') + if out then + print('Squaresville: Saving database at shutdown') + out:write(minetest.serialize(loud_walking.db)) + out:close() + end +end) + + +local hunger_mod = minetest.get_modpath("hunger") +loud_walking.hunger_id = {} + +function loud_walking.hunger_change(player, change) + if not (player and change and type(change) == 'number') then + return + end + + local player_name = player:get_player_name() + if hunger_mod then + if change < 0 and hunger and hunger.update_hunger and hunger.players then + hunger.update_hunger(player, hunger.players[player_name].lvl + change * 4) + end + return + end + + if not (loud_walking.db.hunger and loud_walking.hunger_id) then + return + end + + local hp = player:get_hp() + if not (hp and type(hp) == 'number') then + return + end + + if change < 0 or hp >= 16 then + loud_walking.db.hunger[player_name] = math.min(20, math.max(0, loud_walking.db.hunger[player_name] + change)) + player:hud_change(loud_walking.hunger_id[player_name], 'number', loud_walking.db.hunger[player_name]) + if loud_walking.db.hunger[player_name] == 0 then + player:set_hp(hp - 1) + end + end +end + +local hunger_hud +if not hunger_mod then + hunger_hud = function(player) + if not (player and loud_walking.db.hunger and loud_walking.hunger_id) then + return + end + + local player_name = player:get_player_name() + + if not loud_walking.db.hunger[player_name] then + loud_walking.db.hunger[player_name] = 20 + end + + local hunger_bar = { + hud_elem_type = 'statbar', + position = {x=0.52, y=1}, + offset = {x = 0, y = -90}, + name = "hunger", + text = "farming_bread.png", + number = loud_walking.db.hunger[player_name], + direction = 0, + size = { x=24, y=24 }, + } + + loud_walking.hunger_id[player_name] = player:hud_add(hunger_bar) + end + + minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing) + if not (hp_change and type(hp_change) == 'number') then + return + end + + if hp_change > 0 then + loud_walking.hunger_change(user, hp_change) + end + end) +end + +minetest.register_on_dieplayer(function(player) + if loud_walking.db.status and 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 loud_walking.db.status[player_name] then + for status in pairs(loud_walking.db.status[player_name]) do + local def = loud_walking.registered_status[status] + if not def.remain_after_death then + loud_walking.remove_status(player_name, status) + end + end + end + + if loud_walking.db.hunger and loud_walking.hunger_id and not hunger_mod then + loud_walking.db.hunger[player_name] = 20 + player:hud_change(loud_walking.hunger_id[player_name], 'number', 20) + end +end) + +loud_walking.armor_id = {} +local armor_hud +if not armor_mod then + armor_hud = function(player) + if not (player and loud_walking.armor_id) then + return + end + + local player_name = player:get_player_name() + if not player_name then + return + end + + local armor_icon = { + hud_elem_type = 'image', + name = "armor_icon", + text = 'loud_walking_shield.png', + scale = {x=1,y=1}, + position = {x=0.8, y=1}, + offset = {x = -30, y = -80}, + } + + local armor_text = { + hud_elem_type = 'text', + name = "armor_text", + text = '0%', + number = 0xFFFFFF, + position = {x=0.8, y=1}, + offset = {x = 0, y = -80}, + } + + loud_walking.armor_id[player_name] = {} + loud_walking.armor_id[player_name].icon = player:hud_add(armor_icon) + loud_walking.armor_id[player_name].text = player:hud_add(armor_text) + end + + loud_walking.display_armor = function(player) + if not (player and loud_walking.armor_id) then + return + end + + local player_name = player:get_player_name() + local armor = player:get_armor_groups() + if not (player_name and armor and armor.fleshy) then + return + end + + player:hud_change(loud_walking.armor_id[player_name].text, 'text', (100 - armor.fleshy)..'%') + end +end + + +if loud_walking.starting_equipment then + minetest.register_on_newplayer(function(player) + local inv = player:get_inventory() + inv:add_item("main", 'default:sword_wood') + inv:add_item("main", 'default:axe_wood') + inv:add_item("main", 'default:pick_wood') + inv:add_item("main", 'default:apple 10') + inv:add_item("main", 'default:torch 10') + if minetest.registered_items['unified_inventory:bag_small'] then + inv:add_item("main", 'unified_inventory:bag_small') + end + end) +end --- Inserting helps to ensure that loud_walking operates first. -table.insert(minetest.registered_on_generateds, 1, loud_walking.generate) minetest.register_on_joinplayer(function(player) - player:set_sky("#000000", "plain", {}) + if not (player and loud_walking.db.status) 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 not loud_walking.db.status[player_name] then + loud_walking.db.status[player_name] = {} + end + + if armor_hud then + armor_hud(player) + end + + if hunger_hud then + hunger_hud(player) + end + + -- If there's an armor mod, we wait for it to load armor. + if loud_walking.load_armor_elixir and not armor_mod then + loud_walking.load_armor_elixir(player) + end +end) + +-- support for 3d_armor +-- This may or may not work with all versions. +if armor_mod then + local old_set_player_armor = armor.set_player_armor + + armor.set_player_armor = function(self, player) + old_set_player_armor(self, player) + if loud_walking.load_armor_elixir then + loud_walking.load_armor_elixir(player) + end + end +end + + +---------------------------------------------------------------------- + + +if loud_walking.quick_leaf_decay then + for name, node in pairs(minetest.registered_nodes) do + if node.groups.leafdecay then + node.groups.leafdecay = 0 + node.groups.qfc_leafdecay = 0 + end + end +end + + +local breakable = {} +breakable['loud_walking:wood_rotten'] = true +breakable['loud_walking:glowing_fungal_wood'] = true +if not loud_walking.breakable_wood then + print('* Fun Caves: Wood is NOT breakable by hand.') + for _, item in pairs(minetest.registered_items) do + if (item.groups.tree or item.groups.wood) and not breakable[item.name] then + local groups = table.copy(item.groups) + groups.oddly_breakable_by_hand = nil + minetest.override_item(item.name, {groups=groups}) + end + end +end + +minetest.register_on_joinplayer(function(player) + player:set_sky("#4070FF", "plain", {}) end) diff --git a/mapgen.lua b/mapgen.lua index 677900f..77939f1 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -1,6 +1,17 @@ -local node = loud_walking.node +-- 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 +}) + +loud_walking.node = node -local bevel = 40 local cloud_i = 0.5 local glass = {"loud_walking:sky_scrith", "loud_walking:cloud_scrith", "loud_walking:transparent_scrith"} @@ -82,9 +93,59 @@ local cave_stones = { "loud_walking:stone_with_salt", } local mushroom_stones = {} -mushroom_stones[node("default:stone")] = true -mushroom_stones[node("loud_walking:stone_with_algae")] = true -mushroom_stones[node("loud_walking:stone_with_lichen")] = true +mushroom_stones[node["default:stone"]] = true +mushroom_stones[node["loud_walking:stone_with_algae"]] = true +mushroom_stones[node["loud_walking:stone_with_lichen"]] = true + +local function connection(x, y, z) + local min_x = math.floor((x + 32) / csize.x) + local min_y = math.floor((y + 32) / csize.y) + local min_z = math.floor((z + 32) / csize.z) + + --local seed_noise = minetest.get_perlin({offset = 0, scale = 32768, + --seed = 5202, spread = {x = 80, y = 80, z = 80}, octaves = 2, + --persist = 0.4, lacunarity = 2}) + --math.randomseed(seed_noise:get2d({x=minp.x, y=minp.z})) + + local ct = min_x % 2 + min_y % 2 + min_z % 2 + local r = min_x % 2 + 2 * (min_y % 2) + 4 * (min_z % 2) + if ct == 1 then + return r + end + + return nil +end + +local function get_decoration(biome) + if not loud_walking.decorations then + return + end + + for i, deco in pairs(loud_walking.decorations) do + if not deco.biomes or deco.biomes[biome] then + local range = 1000 + if deco.deco_type == "simple" then + if deco.fill_ratio and math.random(range) - 1 < deco.fill_ratio * 1000 then + return deco.decoration + end + else + -- nop + end + end + end +end + + +local pod_size = 100 +local half_pod = math.floor(pod_size / 2) +local bridge_size = 50 +local fcsize = pod_size + bridge_size +local bevel = half_pod +local room_size = 20 +local control_off = math.floor(room_size / 4) +local biome_look = {} +local cave_look = {} + local function place_schematic(pos, schem, center) local rot = math.random(4) - 1 @@ -112,18 +173,18 @@ local function place_schematic(pos, schem, center) elseif rot == 3 then x, z = z1, schem.size.x - x1 - 1 end - local dz = pos.z - minp.z + z - local dx = pos.x - minp.x + x - if pos.x + x > minp.x and pos.x + x < maxp.x and pos.z + z > minp.z and pos.z + z < maxp.z then + local fdz = (pos.z + z) % fcsize + local fdx = (pos.x + x) % fcsize + if fdz < pod_size - 1 and fdz > 0 and fdx < pod_size - 1 and fdx > 0 then local ivm = a:index(pos.x + x, pos.y, pos.z + z) local isch = z1 * schem.size.y * schem.size.x + x1 + 1 for y = 0, schem.size.y - 1 do - local dy = pos.y - minp.y + y - if math.min(dx, csize.x - dx) + math.min(dy, csize.y - dy) + math.min(dz, csize.z - dz) > bevel then + local fdy = (pos.y + y) % fcsize + if math.min(fdx, pod_size - fdx) + math.min(fdy, pod_size - fdy) + math.min(fdz, pod_size - fdz) > bevel then if yslice[y] or 255 >= math.random(255) then local prob = schem.data[isch].prob or schem.data[isch].param1 or 255 if prob >= math.random(255) and schem.data[isch].name ~= "air" then - data[ivm] = node(schem.data[isch].name) + data[ivm] = node[schem.data[isch].name] end local param2 = schem.data[isch].param2 or 0 p2data[ivm] = param2 @@ -138,43 +199,41 @@ local function place_schematic(pos, schem, center) end end -local function is_pod(x, y, z) - local min_x = math.floor((x + 32) / csize.x) - local min_y = math.floor((y + 32) / csize.y) - local min_z = math.floor((z + 32) / csize.z) - if min_x % 2 == 0 and min_y % 2 == 0 and min_z % 2 == 0 then - return true +local function get_biome(x, y, z) + local px = math.floor(x / fcsize) + local py = math.floor(y / fcsize) + local pz = math.floor(z / fcsize) + + if px % 10 == 6 and pz % 10 == 6 then + return "control" + else + local hash = px * 1000000 + py * 1000 + pz + if not biome_look[hash] then + -- use the same seed (based on perlin noise). + local seed_noise = minetest.get_perlin({offset = 0, scale = 32768, seed = 5202, spread = {x = 80, y = 80, z = 80}, octaves = 2, persist = 0.4, lacunarity = 2}) + math.randomseed(seed_noise:get3d({x=px, y=py, z=pz})) + + local rarity = "common" + if math.random(5) > 4 then + rarity = "uncommon" + end + biome_look[hash] = biome_names[rarity][math.random(#biome_names[rarity])] + + local cave_lining + if math.random(3) ~= 1 then + cave_lining = cave_stones[math.random(#cave_stones)] + end + cave_look[hash] = cave_lining + end + + --return biome_look[hash], cave_look[hash] + return 'deciduous_forest', nil end - --if min_x % 2 == 1 and min_y % 4 == 0 and min_z % 2 == 1 then - -- return true - --elseif min_x % 2 == 0 and min_y % 4 == 2 and min_z % 2 == 0 then - -- return true - --end - - return false end -local function connection(x, y, z) - local min_x = math.floor((x + 32) / csize.x) - local min_y = math.floor((y + 32) / csize.y) - local min_z = math.floor((z + 32) / csize.z) - --local seed_noise = minetest.get_perlin({offset = 0, scale = 32768, - --seed = 5202, spread = {x = 80, y = 80, z = 80}, octaves = 2, - --persist = 0.4, lacunarity = 2}) - --math.randomseed(seed_noise:get2d({x=minp.x, y=minp.z})) - - local ct = min_x % 2 + min_y % 2 + min_z % 2 - local r = min_x % 2 + 2 * (min_y % 2) + 4 * (min_z % 2) - if ct == 1 then - return r - end - - return nil -end - -local function get_height(dx, dz, terrain_scale, ocean, index) +local function get_height_old(dx, dz, terrain_scale, ocean, index) local terr local half = math.floor(csize.y / 2 + 0.5) terrain_scale = terrain_scale or 1 @@ -205,37 +264,319 @@ local function get_height(dx, dz, terrain_scale, ocean, index) return terr end -local function get_biome(px, pz) - if px % 10 == 6 and pz % 10 == 6 then - return "control" - else - local sr = math.random(5) - local rarity = "common" - if sr > 4 then - rarity = "uncommon" - end - local biome = biome_names[rarity][math.random(#biome_names[rarity])] - return biome +local function get_height(fdx, fdz, y, index, heights, terrain_scale, ocean) + local py = math.floor(y / fcsize) + + if not terrain_scale then + return end + + if not heights[py] then + heights[py] = minetest.get_perlin_map(terrain_noise, csize):get2dMap_flat({x=minp.x, y=minp.z}) + end + + local terr = math.floor(heights[py][index] * terrain_scale + 0.5) + + local d = half_pod - 2 - math.abs(math.abs(fdx - (half_pod - 0.5)) - math.abs(fdz - (half_pod - 0.5))) + if math.abs(terr) > d then + if terr > 0 then + terr = math.floor(d + 0.5) + elseif not ocean then + terr = math.floor(0.5 - d) + end + end + + return terr end -local function get_decoration(biome) - for i, deco in pairs(loud_walking.decorations) do - if not deco.biomes or deco.biomes[biome] then - local range = 1000 - if deco.deco_type == "simple" then - if deco.fill_ratio and math.random(range) - 1 < deco.fill_ratio * 1000 then - return deco.decoration + +local function generate(p_minp, p_maxp, seed) + minp, maxp = p_minp, p_maxp + vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + vm:get_data(data) + --p2data = vm:get_param2_data() + a = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) + csize = vector.add(vector.subtract(maxp, minp), 1) + + vm:set_lighting({day = 15, night = 0}, minp, maxp) + lightmap = vm:get_light_data() + + local ground = half_pod + local heights = {} + cloud = minetest.get_perlin_map(cloud_noise, csize):get2dMap_flat(minp) + cave = minetest.get_perlin_map(cave_noise, csize):get3dMap_flat(minp) + + local index = 0 + local index3d = 0 + for z = minp.z, maxp.z do + local dz = z - minp.z + local fdz = z % fcsize + for x = minp.x, maxp.x do + index = index + 1 + local dx = x - minp.x + local fdx = x % fcsize + local in_cave = false + index3d = dz * csize.y * csize.x + dx + 1 + local ivm = a:index(x, minp.y, z) + local cave_height = 0 + for y = minp.y, maxp.y do + local dy = y - minp.y + local fdy = y % fcsize + local biome, cave_lining = get_biome(x, y, z) + local node_top = biomes[biome].node_top or "default:dirt_with_grass" + local node_filler = biomes[biome].node_filler or "default:dirt" + local node_water_top = biomes[biome].node_water_top or "default:water_source" + local node_water = biomes[biome].node_water or "default:water_source" + local depth_top = biomes[biome].depth_top or 1 + local depth_water_top = biomes[biome].node_water_top or 1 + local depth_filler = biomes[biome].depth_filler or 1 + local node_stone = biomes[biome].node_stone or "default:stone" + local ocean = string.find(biome, "ocean") and true or false + local swamp = string.find(biome, "swamp") and true or false + local beach = string.find(biome, "beach") and true or false + local dunes = string.find(biome, "dunes") and true or false + local height = half_pod - 5 + if not (biome == "underground" or biome == 'control') then + height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean) end - else - -- nop + + if biome == "control" and math.abs(fdx - half_pod) < 3 and math.abs(fdz - half_pod) < 3 then + data[ivm] = node["loud_walking:air_ladder"] + elseif fdz >= pod_size or fdx >= pod_size or fdy >= pod_size then + if (fdy == half_pod and fdx == half_pod) or (fdy == half_pod and fdz == half_pod) then + data[ivm] = node['loud_walking:scrith'] + else + data[ivm] = node['air'] + end + elseif math.min(fdx, pod_size - fdx) + math.min(fdy, pod_size - fdy) + math.min(fdz, pod_size - fdz) < bevel then + data[ivm] = node['air'] + lightmap[ivm] = 0 + in_cave = false + elseif (fdx == 0 or fdx == pod_size - 1) or (fdz == 0 or fdz == pod_size - 1) or (fdy == 0 or fdy == pod_size - 1) or math.min(fdx, pod_size - fdx) + math.min(fdy, pod_size - fdy) + math.min(fdz, pod_size - fdz) < bevel + 1 then + if math.abs(fdy - half_pod - 2) < 2 and (fdz == half_pod or fdx == half_pod) then + data[ivm] = node["air"] + else + if biome == "control" then + data[ivm] = node[glass[3]] + elseif fdy < half_pod then + data[ivm] = node["loud_walking:scrith"] + lightmap[ivm] = 0 + elseif biome == "underground" then + data[ivm] = node["loud_walking:scrith"] + lightmap[ivm] = 0 + elseif fdy == pod_size - 1 then + data[ivm] = node[glass[cloud[index] < cloud_i and 1 or 2]] + else + data[ivm] = node[glass[1]] + end + end + elseif fdz == 0 and fdz == pod_size - 1 or fdx == 0 and fdx == pod_size - 1 or fdy == 0 and fdy == pod_size - 1 then + data[ivm] = node['loud_walking:scrith'] + elseif biome == "control" and fdy % 5 == 0 then + data[ivm] = node["loud_walking:control_floor"] + elseif biome == "control" and (math.abs(fdx - half_pod) < 3 or math.abs(fdz - half_pod) < 3) then + data[ivm] = node["air"] + elseif biome == "control" and ((math.abs(fdx - half_pod) % room_size == 3 and (math.abs(fdz - half_pod) - 12) % room_size > 3) or (math.abs(fdz - half_pod) % room_size == 3 and (math.abs(fdx - half_pod) - 12) % room_size > 3)) then + data[ivm] = node["loud_walking:control_wall"] + elseif biome == "control" then + -- + elseif (((fdx == (half_pod - control_off) or fdx == (half_pod + control_off)) and fdz >= (half_pod - control_off) and fdz <= (half_pod + control_off)) or ((fdz == (half_pod - control_off) or fdz == (half_pod + control_off)) and fdx >= (half_pod - control_off) and fdx <= (half_pod + control_off))) and fdx ~= half_pod and fdz ~= half_pod and fdy == csize.y - 2 then + data[ivm] = node["loud_walking:controls"] + elseif (((fdx == (half_pod - control_off) or fdx == (half_pod + control_off)) and fdz >= (half_pod - control_off) and fdz <= (half_pod + control_off)) or ((fdz == (half_pod - control_off) or fdz == (half_pod + control_off)) and fdx >= (half_pod - control_off) and fdx <= (half_pod + control_off))) and fdx ~= half_pod and fdz ~= half_pod and fdy > csize.y - control_off then + data[ivm] = node[glass[3]] + elseif fdz >= (half_pod - control_off) and fdz <= (half_pod + control_off) and fdx >= (half_pod - control_off) and fdx <= (half_pod + control_off) and fdy == csize.y - control_off then + data[ivm] = node[glass[3]] + elseif not in_cave and (ocean or swamp or beach) and fdy > height + ground and fdy <= half_pod and fdy == height + ground + 1 then + -- ** water decorations ** + --local deco = get_decoration(biome) + --if deco then + -- data[ivm] = node[deco] + --end + elseif not in_cave and fdy == height + ground + 1 then + local deco = get_decoration(biome) + if deco then + data[ivm] = node[deco] + end + elseif (ocean or swamp or beach) and fdy > height + ground and fdy <= half_pod and fdy >= half_pod - depth_water_top then + data[ivm] = node[node_water_top] + in_cave = false + elseif (ocean or swamp or beach) and fdy > height + ground and fdy <= half_pod then + data[ivm] = node[node_water] + in_cave = false + elseif fdy > height + ground then + data[ivm] = node["air"] + in_cave = false + elseif cave[index3d] ^ 2 > (biome == "underground" and 0.5 or 1.3 - math.sin(fdy / (half_pod * 0.2))) then + cave_height = cave_height + 1 + if height + ground >= fdy and not in_cave and fdy > height + ground - 10 then + data[ivm] = node[node_top] + elseif fdy == 1 then + if not cave_lining and not ocean and not swamp and not beach and biome ~= "glacier" and math.random(6) == 1 then + data[ivm] = node["default:lava_source"] + elseif ocean or swamp or beach then + data[ivm] = node[node_filler] + end + elseif (ocean or swamp or beach) and not in_cave and node_stone == "default:stone" and fdy < half_pod and math.random(20) == 1 then + data[ivm] = node["loud_walking:glowing_fungal_stone"] + elseif (ocean or swamp or beach) and fdy < half_pod then + data[ivm] = node[node_water] + elseif cave_height == 3 and node_filler == "default:dirt" and mushroom_stones[data[ivm - 3 * a.ystride]] and math.random(40) == 1 then + data[ivm] = node["loud_walking:giant_mushroom_cap"] + data[ivm - a.ystride] = node["loud_walking:giant_mushroom_stem"] + data[ivm - 2 * a.ystride] = node["loud_walking:giant_mushroom_stem"] + data[ivm - 3 * a.ystride] = node[node_filler] + elseif cave_height == 2 and node_filler == "default:dirt" and mushroom_stones[data[ivm - 2 * a.ystride]] and math.random(20) == 1 then + data[ivm] = node["loud_walking:huge_mushroom_cap"] + data[ivm - a.ystride] = node["loud_walking:giant_mushroom_stem"] + data[ivm - 2 * a.ystride] = node[node_filler] + elseif not in_cave and node_stone == "default:stone" and not cave_lining and math.random(10) == 1 then + data[ivm] = node["loud_walking:stalagmite"] + elseif not in_cave and node_stone == "default:ice" and math.random(10) == 1 then + data[ivm] = node["loud_walking:icicle_up"] + else + data[ivm] = node["air"] + end + in_cave = true + --lightmap[ivm] = 0 + elseif cave_lining and cave[index3d] ^ 2 > (biome == "underground" and 0.4 or 1.2 - math.sin(fdy / (half_pod * 0.2))) then + data[ivm] = node[cave_lining] + lightmap[ivm] = 0 + elseif fdy > height + ground - depth_top then + data[ivm] = node[node_top] + lightmap[ivm] = 0 + in_cave = false + elseif fdy > height + ground - depth_filler - depth_top then + data[ivm] = node[node_filler] + lightmap[ivm] = 0 + in_cave = false + else + data[ivm] = node[node_stone] + if in_cave and node_stone == "default:stone" and math.random(20) == 1 then + data[ivm] = node["loud_walking:glowing_fungal_stone"] + elseif in_cave and not (ocean or swamp or beach) and node_stone == "default:stone" and not cave_lining and math.random(10) == 1 then + data[ivm - a.ystride] = node["loud_walking:stalactite"] + elseif in_cave and not (ocean or swamp or beach) and node_stone == "default:ice" and math.random(10) == 1 then + data[ivm - a.ystride] = node["loud_walking:icicle_down"] + end + lightmap[ivm] = 0 + in_cave = false + end + + if not in_cave then + cave_height = 0 + end + + ivm = ivm + a.ystride + index3d = index3d + csize.x end end end + + local index = 0 + for z = minp.z, maxp.z do + local fdz = z % fcsize + for x = minp.x, maxp.x do + local fdx = x % fcsize + index = index + 1 + for y = minp.y, maxp.y do + local fdy = y % fcsize + if fdz % 5 == 0 and fdx % 5 == 0 then + local fdy = y % fcsize + local pod = fdz < pod_size and fdx < pod_size and fdy < pod_size + local biome, cave_lining = get_biome(x, y, z) + local ocean = string.find(biome, "ocean") and true or false + local height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean) + + if pod and fdy == height + ground and biomes[biome].special_tree_prob and math.random(biomes[biome].special_tree_prob) == 1 then + local rx = x + math.random(5) - 1 + local rz = z + math.random(5) - 1 + local swamp = string.find(biome, "swamp") and true or false + local node_top = biomes[biome].node_top or "default:dirt_with_grass" + + local ivm = a:index(rx, y, rz) + if (swamp or data[ivm + a.ystride] ~= node["default:water_source"]) and (data[ivm] == node[node_top]) then + if biomes[biome].special_trees then + local tree_type = biomes[biome].special_trees[math.random(#biomes[biome].special_trees)] + if tree_type and loud_walking.schematics then + local schem = loud_walking.schematics[tree_type][math.random(#loud_walking.schematics[tree_type])] + local pos = {x=rx, y=y, z=rz} + -- The minetest schematic functions don't seem very accurate. + place_schematic(pos, schem, true) + end + else + -- regular schematics? + end + end + end + end + end + end + end + + if false and pod and biome == "control" then + for dy = 0, 15 do + for dz = 0, 1 do + for dx = 0, 1 do + local x1 = minp.x + dx * 26 + 17 + local z1 = minp.z + dz * 26 + 17 + local y1 = minp.y + dy * 5 + + local sr = math.random(6) + for z = 0, 20 do + local ivm = a:index(x1, y1, z1 + z) + for x = 0, 20 do + if sr == 1 then + if dy > 0 then + if data[ivm] == node["loud_walking:control_floor_alert_down"] then + data[ivm] = node["loud_walking:control_floor_alert_both"] + else + data[ivm] = node["loud_walking:control_floor_alert_up"] + end + end + if dy < 15 then + data[ivm + a.ystride * 5] = node["loud_walking:control_floor_alert_down"] + end + elseif sr == 2 then + if x > 1 and x < 19 and z > 1 and z < 19 and (z - 2) % 4 ~= 0 and (x - 2) % 4 ~= 0 then + for y = 1, 4 do + data[ivm + y * a.ystride] = node["loud_walking:air_ladder"] + end + end + elseif sr == 3 then + if dy > 0 and data[ivm] ~= node["loud_walking:control_floor_alert_down"] and x > 0 and z > 0 and x < 20 and z < 20 then + data[ivm] = node["loud_walking:control_floor_growth"] + local sr2 = math.random(20) + if sr2 == 1 then + data[ivm + a.ystride] = node["loud_walking:control_plant_1"] + elseif sr2 == 2 then + data[ivm + a.ystride] = node["loud_walking:control_plant_2"] + end + end + elseif sr == 4 then + if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math.abs(z - 10) > 3) or ((z == 1 or z == 19) and math.abs(x - 10) > 3)) then + data[ivm + 3 * a.ystride] = node["loud_walking:controls"] + end + end + + ivm = ivm + 1 + end + end + end + end + end + end + + vm:set_data(data) + minetest.generate_ores(vm, minp, maxp) + --vm:set_param2_data(p2data) + vm:set_light_data(lightmap) + vm:update_liquids() + vm:calc_lighting(minp, maxp, false) + vm:write_to_map() end -function loud_walking.generate(p_minp, p_maxp, seed) +local function generate_old(p_minp, p_maxp, seed) minp, maxp = p_minp, p_maxp vm, emin, emax = minetest.get_mapgen_object("voxelmanip") vm:get_data(data) @@ -318,123 +659,123 @@ function loud_walking.generate(p_minp, p_maxp, seed) local dy = y - minp.y if pod then if biome == "control" and math.abs(dx - half) < 3 and math.abs(dz - half) < 3 then - data[ivm] = node("loud_walking:air_ladder") + data[ivm] = node["loud_walking:air_ladder"] elseif math.min(dx, csize.x - dx) + math.min(dy, csize.y - dy) + math.min(dz, csize.z - dz) < bevel then - data[ivm] = node("air") + data[ivm] = node["air"] lightmap[ivm] = 0 in_cave = false elseif (dx == 0 or dx == csize.x - 1) or (dz == 0 or dz == csize.z - 1) or (dy == 0 or dy == csize.y - 1) or math.min(dx, csize.x - dx) + math.min(dy, csize.y - dy) + math.min(dz, csize.z - dz) < bevel + 1 then if math.abs(dy - half - 2) < 2 and (dz == half or dx == half) then - data[ivm] = node("air") + data[ivm] = node["air"] else if biome == "control" then - data[ivm] = node(glass[3]) + data[ivm] = node[glass[3]] elseif dy < half then - data[ivm] = node("loud_walking:scrith") + data[ivm] = node["loud_walking:scrith"] lightmap[ivm] = 0 elseif biome == "underground" then - data[ivm] = node("loud_walking:scrith") + data[ivm] = node["loud_walking:scrith"] lightmap[ivm] = 0 elseif dy == csize.y - 1 then - data[ivm] = node(glass[cloud[index] < cloud_i and 1 or 2]) + data[ivm] = node[glass[cloud[index] < cloud_i and 1 or 2]] else - data[ivm] = node(glass[1]) + data[ivm] = node[glass[1]] end end in_cave = false elseif biome == "control" and dy % 5 == 0 then - data[ivm] = node("loud_walking:control_floor") + data[ivm] = node["loud_walking:control_floor"] elseif biome == "control" and (math.abs(dx - half) < 3 or math.abs(dz - half) < 3) then - data[ivm] = node("air") + data[ivm] = node["air"] elseif biome == "control" and ((math.abs(dx - half) % 20 == 3 and (math.abs(dz - half) - 12) % 20 > 3) or (math.abs(dz - half) % 20 == 3 and (math.abs(dx - half) - 12) % 20 > 3)) then - data[ivm] = node("loud_walking:control_wall") + data[ivm] = node["loud_walking:control_wall"] elseif biome == "control" then -- elseif (((dx == 35 or dx == 45) and dz >= 35 and dz <= 45) or ((dz == 35 or dz == 45) and dx >= 35 and dx <= 45)) and dx ~= 40 and dz ~= 40 and dy == csize.y - 2 then - data[ivm] = node("loud_walking:controls") + data[ivm] = node["loud_walking:controls"] elseif (((dx == 35 or dx == 45) and dz >= 35 and dz <= 45) or ((dz == 35 or dz == 45) and dx >= 35 and dx <= 45)) and dx ~= 40 and dz ~= 40 and dy > csize.y - 5 then - data[ivm] = node(glass[3]) + data[ivm] = node[glass[3]] elseif dz >= 35 and dz <= 45 and dx >= 35 and dx <= 45 and dy == csize.y - 5 then - data[ivm] = node(glass[3]) + data[ivm] = node[glass[3]] elseif not in_cave and (ocean or swamp or beach) and dy > terr + ground and dy <= half and dy == terr + ground + 1 then -- ** water decorations ** --local deco = get_decoration(biome) --if deco then - -- data[ivm] = node(deco) + -- data[ivm] = node[deco] --end elseif not in_cave and dy == terr + ground + 1 then local deco = get_decoration(biome) if deco then - data[ivm] = node(deco) + data[ivm] = node[deco] end elseif (ocean or swamp or beach) and dy > terr + ground and dy <= half and dy >= half - depth_water_top then - data[ivm] = node(node_water_top) + data[ivm] = node[node_water_top] in_cave = false elseif (ocean or swamp or beach) and dy > terr + ground and dy <= half then - data[ivm] = node(node_water) + data[ivm] = node[node_water] in_cave = false elseif dy > terr + ground then - data[ivm] = node("air") + data[ivm] = node["air"] in_cave = false elseif cave[index3d] ^ 2 > (biome == "underground" and 0.5 or 1.3 - math.sin(dy / (half * 0.2))) then cave_height = cave_height + 1 if terr + ground >= dy and not in_cave and dy > terr + ground - 10 then - data[ivm] = node(node_top) + data[ivm] = node[node_top] elseif dy == 1 then if not cave_lining and not ocean and not swamp and not beach and biome ~= "glacier" and math.random(6) == 1 then - data[ivm] = node("default:lava_source") + data[ivm] = node["default:lava_source"] elseif ocean or swamp or beach then - data[ivm] = node(node_filler) + data[ivm] = node[node_filler] end elseif (ocean or swamp or beach) and not in_cave and node_stone == "default:stone" and dy < half and math.random(20) == 1 then - data[ivm] = node("loud_walking:glowing_fungal_stone") + data[ivm] = node["loud_walking:glowing_fungal_stone"] elseif (ocean or swamp or beach) and dy < half then - data[ivm] = node(node_water) + data[ivm] = node[node_water] elseif cave_height == 3 and node_filler == "default:dirt" and mushroom_stones[data[ivm - 3 * a.ystride]] and math.random(40) == 1 then - data[ivm] = node("loud_walking:giant_mushroom_cap") - data[ivm - a.ystride] = node("loud_walking:giant_mushroom_stem") - data[ivm - 2 * a.ystride] = node("loud_walking:giant_mushroom_stem") - data[ivm - 3 * a.ystride] = node(node_filler) + data[ivm] = node["loud_walking:giant_mushroom_cap"] + data[ivm - a.ystride] = node["loud_walking:giant_mushroom_stem"] + data[ivm - 2 * a.ystride] = node["loud_walking:giant_mushroom_stem"] + data[ivm - 3 * a.ystride] = node[node_filler] elseif cave_height == 2 and node_filler == "default:dirt" and mushroom_stones[data[ivm - 2 * a.ystride]] and math.random(20) == 1 then - data[ivm] = node("loud_walking:huge_mushroom_cap") - data[ivm - a.ystride] = node("loud_walking:giant_mushroom_stem") - data[ivm - 2 * a.ystride] = node(node_filler) + data[ivm] = node["loud_walking:huge_mushroom_cap"] + data[ivm - a.ystride] = node["loud_walking:giant_mushroom_stem"] + data[ivm - 2 * a.ystride] = node[node_filler] elseif not in_cave and node_stone == "default:stone" and not cave_lining and math.random(10) == 1 then - data[ivm] = node("loud_walking:stalagmite") + data[ivm] = node["loud_walking:stalagmite"] elseif not in_cave and node_stone == "default:ice" and math.random(10) == 1 then - data[ivm] = node("loud_walking:icicle_up") + data[ivm] = node["loud_walking:icicle_up"] else - data[ivm] = node("air") + data[ivm] = node["air"] end in_cave = true lightmap[ivm] = 0 elseif cave_lining and cave[index3d] ^ 2 > (biome == "underground" and 0.4 or 1.2 - math.sin(dy / (half * 0.2))) then - data[ivm] = node(cave_lining) + data[ivm] = node[cave_lining] lightmap[ivm] = 0 elseif dy > terr + ground - depth_top then - data[ivm] = node(node_top) + data[ivm] = node[node_top] lightmap[ivm] = 0 in_cave = false elseif dy > terr + ground - depth_filler - depth_top then - data[ivm] = node(node_filler) + data[ivm] = node[node_filler] lightmap[ivm] = 0 in_cave = false else - data[ivm] = node(node_stone) + data[ivm] = node[node_stone] if in_cave and node_stone == "default:stone" and math.random(20) == 1 then - data[ivm] = node("loud_walking:glowing_fungal_stone") + data[ivm] = node["loud_walking:glowing_fungal_stone"] elseif in_cave and not (ocean or swamp or beach) and node_stone == "default:stone" and not cave_lining and math.random(10) == 1 then - data[ivm - a.ystride] = node("loud_walking:stalactite") + data[ivm - a.ystride] = node["loud_walking:stalactite"] elseif in_cave and not (ocean or swamp or beach) and node_stone == "default:ice" and math.random(10) == 1 then - data[ivm - a.ystride] = node("loud_walking:icicle_down") + data[ivm - a.ystride] = node["loud_walking:icicle_down"] end lightmap[ivm] = 0 in_cave = false end elseif biome == "control" and math.abs(dx - half) < 3 and math.abs(dz - half) < 3 then - data[ivm] = node("loud_walking:air_ladder") + data[ivm] = node["loud_walking:air_ladder"] elseif connection and dy == half and ((dx == half and connection % 4 == 0) or (dz == half and connection % 2 == 1)) then - data[ivm] = node("loud_walking:scrith") + data[ivm] = node["loud_walking:scrith"] lightmap[ivm] = 0 end @@ -456,10 +797,10 @@ function loud_walking.generate(p_minp, p_maxp, seed) local y = minp.y + get_height(x - minp.x, z - minp.z, biomes[biome].terrain_scale, ocean) + ground local ivm = a:index(x, y, z) - if (swamp or data[ivm + a.ystride] ~= node("default:water_source")) and (data[ivm] == node(node_top)) then + if (swamp or data[ivm + a.ystride] ~= node["default:water_source"]) and (data[ivm] == node[node_top]) then if biomes[biome].special_trees then local tree_type = biomes[biome].special_trees[math.random(#biomes[biome].special_trees)] - if tree_type then + if tree_type and loud_walking.schematics then local schem = loud_walking.schematics[tree_type][math.random(#loud_walking.schematics[tree_type])] local pos = {x=x, y=y, z=z} -- The minetest schematic functions don't seem very accurate. @@ -488,34 +829,34 @@ function loud_walking.generate(p_minp, p_maxp, seed) for x = 0, 20 do if sr == 1 then if dy > 0 then - if data[ivm] == node("loud_walking:control_floor_alert_down") then - data[ivm] = node("loud_walking:control_floor_alert_both") + if data[ivm] == node["loud_walking:control_floor_alert_down"] then + data[ivm] = node["loud_walking:control_floor_alert_both"] else - data[ivm] = node("loud_walking:control_floor_alert_up") + data[ivm] = node["loud_walking:control_floor_alert_up"] end end if dy < 15 then - data[ivm + a.ystride * 5] = node("loud_walking:control_floor_alert_down") + data[ivm + a.ystride * 5] = node["loud_walking:control_floor_alert_down"] end elseif sr == 2 then if x > 1 and x < 19 and z > 1 and z < 19 and (z - 2) % 4 ~= 0 and (x - 2) % 4 ~= 0 then for y = 1, 4 do - data[ivm + y * a.ystride] = node("loud_walking:air_ladder") + data[ivm + y * a.ystride] = node["loud_walking:air_ladder"] end end elseif sr == 3 then - if dy > 0 and data[ivm] ~= node("loud_walking:control_floor_alert_down") and x > 0 and z > 0 and x < 20 and z < 20 then - data[ivm] = node("loud_walking:control_floor_growth") + if dy > 0 and data[ivm] ~= node["loud_walking:control_floor_alert_down"] and x > 0 and z > 0 and x < 20 and z < 20 then + data[ivm] = node["loud_walking:control_floor_growth"] local sr2 = math.random(20) if sr2 == 1 then - data[ivm + a.ystride] = node("loud_walking:control_plant_1") + data[ivm + a.ystride] = node["loud_walking:control_plant_1"] elseif sr2 == 2 then - data[ivm + a.ystride] = node("loud_walking:control_plant_2") + data[ivm + a.ystride] = node["loud_walking:control_plant_2"] end end elseif sr == 4 then if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math.abs(z - 10) > 3) or ((z == 1 or z == 19) and math.abs(x - 10) > 3)) then - data[ivm + 3 * a.ystride] = node("loud_walking:controls") + data[ivm + 3 * a.ystride] = node["loud_walking:controls"] end end @@ -542,13 +883,30 @@ function loud_walking.generate(p_minp, p_maxp, seed) vm, a, heightmap, biomemap = nil, nil, nil, nil end + +local function pgenerate(...) + --local status, err = pcall(generate, ...) + local status, err = true + generate(...) + if not status then + print('Squaresville: Could not generate terrain:') + print(dump(err)) + collectgarbage("collect") + end +end + + +-- Inserting helps to ensure that squaresville operates first. +table.insert(minetest.registered_on_generateds, 1, pgenerate) + + function loud_walking.respawn(player) while true do local px = math.random(-10, 10) * 2 - 1 local pz = math.random(-10, 10) * 2 - local x = 80 * px + 8 - local z = 80 * pz + 8 - local y = 9 + local x = pod_size * px + local z = pod_size * pz + local y = half_pod + 1 local pos = {x=x,y=y,z=z} local node = minetest.get_node(pos) @@ -558,3 +916,6 @@ function loud_walking.respawn(player) end end end + +minetest.register_on_newplayer(loud_walking.respawn) +minetest.register_on_respawnplayer(loud_walking.respawn) diff --git a/nodes.lua b/nodes.lua index 21dea63..089a3aa 100644 --- a/nodes.lua +++ b/nodes.lua @@ -36,7 +36,7 @@ minetest.register_node("loud_walking:sky_scrith", { local node = loud_walking.clone_node("loud_walking:sky_scrith") node.tiles = {"loud_walking_cloud_glass.png"} minetest.register_node("loud_walking:cloud_scrith", node) -local node = loud_walking.clone_node("loud_walking:sky_scrith") +node = loud_walking.clone_node("loud_walking:sky_scrith") node.tiles = {"loud_walking_glass_detail.png"} minetest.register_node("loud_walking:transparent_scrith", node) @@ -49,10 +49,10 @@ minetest.register_node("loud_walking:control_floor", { groups = {}, sounds = default.node_sound_stone_defaults(), }) -local node = loud_walking.clone_node("loud_walking:control_floor") +node = loud_walking.clone_node("loud_walking:control_floor") node.tiles = { "loud_walking_control_floor.png", "loud_walking_control_floor_alert.png", "loud_walking_control_floor.png"} minetest.register_node("loud_walking:control_floor_alert_down", node) -local node = loud_walking.clone_node("loud_walking:control_floor") +node = loud_walking.clone_node("loud_walking:control_floor") node.tiles = {"loud_walking_control_floor_alert.png", "loud_walking_control_floor.png", "loud_walking_control_floor.png"} minetest.register_node("loud_walking:control_floor_alert_up", node) node.tiles = {"loud_walking_control_floor_alert.png", "loud_walking_control_floor_alert.png", "loud_walking_control_floor.png"}