diff --git a/README.txt b/README.txt index 5df0457..34109c6 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -moonrealm 0.10.1 by paramat +moonrealm 0.10.2 by paramat For Minetest 0.4.14 or later Depends default Licenses: Code LGPL 2.1. Media CC BY-SA 3.0 diff --git a/init.lua b/init.lua index d714646..ea054e0 100644 --- a/init.lua +++ b/init.lua @@ -1,569 +1,7 @@ --- Parameters - -local YMIN = -8000 -- Approx lower limit -local GRADCEN = 1 -- Gradient centre / terrain centre average level -local YMAX = 8000 -- Approx upper limit -local XMIN = -8000 -- Approx horizontal limits -local XMAX = 8000 -local ZMIN = -8000 -local ZMAX = 8000 - -local CENAMP = 64 -- Grad centre amplitude, terrain centre is varied by this -local HIGRAD = 128 -- Surface generating noise gradient above gradcen, controls depth of upper terrain -local LOGRAD = 128 -- Surface generating noise gradient below gradcen, controls depth of lower terrain -local HEXP = 0.5 -- Noise offset exponent above gradcen, 1 = normal 3D perlin terrain -local LEXP = 2 -- Noise offset exponent below gradcen -local STOT = 0.04 -- Stone density threshold, depth of dust - -local ICECHA = 1 / (13 * 13 * 13) -- Ice chance per dust node at terrain centre, decreases with altitude -local ICEGRAD = 128 -- Ice gradient, vertical distance for no ice -local ORECHA = 7 * 7 * 7 -- Ore 1/x chance per stone node -local TFIS = 0.01 -- Fissure threshold. Controls size of fissures -local FOOT = true -- Footprints in dust - --- 3D noise for terrain - -local np_terrain = { - offset = 0, - scale = 1, - spread = {x = 384, y = 384, z = 384}, - seed = 58588900033, - octaves = 5, - persist = 0.67 -} - --- 3D noise for alt terrain, 414 / 256 = golden ratio - -local np_terralt = { - offset = 0, - scale = 1, - spread = {x = 311, y = 311, z = 311}, - seed = 13331930910, - octaves = 5, - persist = 0.67 -} - --- 2D noise for smooth terrain - -local np_smooth = { - offset = 0, - scale = 1, - spread = {x = 512, y = 512, z = 512}, - seed = 113, - octaves = 3, - persist = 0.4 -} - --- 3D noise for fissures - -local np_fissure = { - offset = 0, - scale = 1, - spread = {x = 192, y = 192, z = 192}, - seed = 8181112, - octaves = 4, - persist = 0.5 -} - - --- 3D noise for faults - -local np_fault = { - offset = 0, - scale = 1, - spread = {x = 414, y = 828, z = 414}, - seed = 14440002, - octaves = 4, - persist = 0.5 -} - --- 2D noise for terrain centre - -local np_gradcen = { - offset = 0, - scale = 1, - spread = {x = 1024, y = 1024, z = 1024}, - seed = 9344, - octaves = 4, - persist = 0.4 -} - --- 2D noise for terrain blend - -local np_terblen = { - offset = 0, - scale = 1, - spread = {x = 1024, y = 1024, z = 1024}, - seed = -13002, - octaves = 3, - persist = 0.4 -} - - -- Do files dofile(minetest.get_modpath("moonrealm") .. "/nodes.lua") dofile(minetest.get_modpath("moonrealm") .. "/crafting.lua") dofile(minetest.get_modpath("moonrealm") .. "/functions.lua") dofile(minetest.get_modpath("moonrealm") .. "/rover.lua") - - --- Set mapgen parameters - -minetest.set_mapgen_params({mgname = "singlenode", water_level = -31000}) - - --- Player positions, spacesuit texture status - -local player_pos = {} -local player_pos_previous = {} -local player_spacesuit = {} - -minetest.register_on_joinplayer(function(player) - player_pos_previous[player:get_player_name()] = {x = 0, y = 0, z = 0} - - if player:get_inventory():contains_item("main", "moonrealm:spacesuit") then - player:set_properties({textures = {"moonrealm_space_character.png"}}) - player_spacesuit[player:get_player_name()] = true - else - player:set_properties({textures = {"moonrealm_character.png"}}) - player_spacesuit[player:get_player_name()] = false - end -end) - -minetest.register_on_leaveplayer(function(player) - player_pos_previous[player:get_player_name()] = nil - player_spacesuit[player:get_player_name()] = nil -end) - - --- Globalstep function - -minetest.register_globalstep(function(dtime) - for _, player in ipairs(minetest.get_connected_players()) do - if FOOT and math.random() < 0.15 and -- footprints - player_pos_previous[player:get_player_name()] ~= nil then - local pos = player:getpos() - player_pos[player:get_player_name()] = { - x = math.floor(pos.x + 0.5), - y = math.floor(pos.y + 0.2), - z = math.floor(pos.z + 0.5) - } - local p_ground = { - x = math.floor(pos.x + 0.5), - y = math.floor(pos.y + 0.4), - z = math.floor(pos.z + 0.5) - } - local n_ground = minetest.get_node(p_ground).name - local p_groundpl = { - x = math.floor(pos.x + 0.5), - y = math.floor(pos.y - 0.5), - z = math.floor(pos.z + 0.5) - } - if player_pos[player:get_player_name()].x ~= - player_pos_previous[player:get_player_name()].x or - player_pos[player:get_player_name()].y < - player_pos_previous[player:get_player_name()].y or - player_pos[player:get_player_name()].z ~= - player_pos_previous[player:get_player_name()].z then - if n_ground == "moonrealm:dust" then - if math.random() < 0.5 then - minetest.add_node( - p_groundpl, - {name = "moonrealm:dustprint1"} - ) - else - minetest.add_node( - p_groundpl, - {name = "moonrealm:dustprint2"} - ) - end - end - end - player_pos_previous[player:get_player_name()] = { - x = player_pos[player:get_player_name()].x, - y = player_pos[player:get_player_name()].y, - z = player_pos[player:get_player_name()].z - } - end - - if math.random() < 0.04 then -- spacesuit restores breath, reset spacesuit texture - if player:get_inventory():contains_item("main", "moonrealm:spacesuit") then - if player:get_breath() < 10 then - player:set_breath(10) - end - - if player_spacesuit[player:get_player_name()] == false then -- if no spacesuit texture, add - player:set_properties({textures = {"moonrealm_space_character.png"}}) - player_spacesuit[player:get_player_name()] = true - end - else -- no spacesuit in inventory - if player_spacesuit[player:get_player_name()] == true then -- if spacesuit texture, remove - player:set_properties({textures = {"moonrealm_character.png"}}) - player_spacesuit[player:get_player_name()] = false - end - end - end - - if math.random() < 0.01 then -- set gravity, skybox and override light - local pos = player:getpos() - if pos.y > YMIN and pos.y < YMAX then -- entering realm - player:set_physics_override(1, 0.6, 0.2) -- speed, jump, gravity - local skytextures = { - "moonrealm_posy.png", - "moonrealm_negy.png", - "moonrealm_posz.png", - "moonrealm_negz.png", - "moonrealm_negx.png", - "moonrealm_posx.png", - } - player:set_sky({r = 0, g = 0, b = 0, a = 0}, "skybox", skytextures) - player:override_day_night_ratio(1) - else -- on leaving realm - player:set_physics_override(1, 1, 1) - player:set_sky({}, "regular", {}) - player:override_day_night_ratio(nil) - end - end - end -end) - - --- Initialize noise objects to nil - -local nobj_terrain = nil -local nobj_terralt = nil -local nobj_fissure = nil -local nobj_fault = nil - -local nobj_smooth = nil -local nobj_terblen = nil -local nobj_gradcen = nil - - --- Localise noise buffers - -local nbuf_terrain -local nbuf_terralt -local nbuf_fissure -local nbuf_fault - -local nbuf_smooth -local nbuf_terblen -local nbuf_gradcen - - --- Localise data buffer - -local dbuf - - --- On generated function - -minetest.register_on_generated(function(minp, maxp, seed) - if minp.x < XMIN or maxp.x > XMAX or - minp.y < YMIN or maxp.y > YMAX or - minp.z < ZMIN or maxp.z > ZMAX then - return - end - - --local t1 = os.clock() - local x1 = maxp.x - local y1 = maxp.y - local z1 = maxp.z - local x0 = minp.x - local y0 = minp.y - local z0 = minp.z - - local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") - local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax} - local data = vm:get_data(dbuf) - - local c_air = minetest.get_content_id("air") - local c_ignore = minetest.get_content_id("ignore") - local c_mese = minetest.get_content_id("moonrealm:mese") - local c_mrironore = minetest.get_content_id("moonrealm:ironore") - local c_mrcopperore = minetest.get_content_id("moonrealm:copperore") - local c_mrgoldore = minetest.get_content_id("moonrealm:goldore") - local c_mrdiamondore = minetest.get_content_id("moonrealm:diamondore") - local c_mrstone = minetest.get_content_id("moonrealm:stone") - local c_waterice = minetest.get_content_id("moonrealm:waterice") - local c_dust = minetest.get_content_id("moonrealm:dust") - local c_vacuum = minetest.get_content_id("moonrealm:vacuum") - - local chulens = x1 - x0 + 1 - local pmaplens2d = {x = chulens, y = chulens, z = 1} - local pmaplens3d = {x = chulens, y = chulens, z = chulens} - local minpos2d = {x = x0, y = z0} - local minpos3d = {x = x0, y = y0, z = z0} - - nobj_terrain = nobj_terrain or minetest.get_perlin_map(np_terrain, pmaplens3d) - nobj_terralt = nobj_terralt or minetest.get_perlin_map(np_terralt, pmaplens3d) - nobj_fissure = nobj_fissure or minetest.get_perlin_map(np_fissure, pmaplens3d) - nobj_fault = nobj_fault or minetest.get_perlin_map(np_fault, pmaplens3d) - - nobj_smooth = nobj_smooth or minetest.get_perlin_map(np_smooth, pmaplens2d) - nobj_terblen = nobj_terblen or minetest.get_perlin_map(np_terblen, pmaplens2d) - nobj_gradcen = nobj_gradcen or minetest.get_perlin_map(np_gradcen, pmaplens2d) - - local nvals_terrain = nobj_terrain:get3dMap_flat(minpos3d, nbuf_terrain) - local nvals_terralt = nobj_terralt:get3dMap_flat(minpos3d, nbuf_terralt) - local nvals_fissure = nobj_fissure:get3dMap_flat(minpos3d, nbuf_fissure) - local nvals_fault = nobj_fault :get3dMap_flat(minpos3d, nbuf_fault) - - local nvals_smooth = nobj_smooth :get2dMap_flat(minpos2d, nbuf_smooth) - local nvals_terblen = nobj_terblen:get2dMap_flat(minpos2d, nbuf_terblen) - local nvals_gradcen = nobj_gradcen:get2dMap_flat(minpos2d, nbuf_gradcen) - - local ni3d = 1 - local ni2d = 1 - local stable = {} - - for z = z0, z1 do - local viu = area:index(x0, y0 - 1, z) - - for x = x0, x1 do - local si = x - x0 + 1 - local nodid = data[viu] - if nodid == c_vacuum then - stable[si] = false - else - stable[si] = true - end - viu = viu + 1 - end - - for y = y0, y1 do - local vi = area:index(x0, y, z) - local icecha = ICECHA * (1 + (GRADCEN - y) / ICEGRAD) - - for x = x0, x1 do - local nodid = data[vi] - local empty = (nodid == c_air or nodid == c_ignore) - local grad - local density - local si = x - x0 + 1 - local terblen = math.max(math.min( - math.abs(nvals_terblen[ni2d]) * 4, 1.5), 0.5) - 0.5 - local gradcen = GRADCEN + nvals_gradcen[ni2d] * CENAMP - - if y > gradcen then - grad = -((y - gradcen) / HIGRAD) ^ HEXP - else - grad = ((gradcen - y) / LOGRAD) ^ LEXP - end - - if nvals_fault[ni3d] >= 0 then - density = (nvals_terrain[ni3d] + - nvals_terralt[ni3d]) / 2 * (1 - terblen) + - nvals_smooth[ni2d] * terblen + grad - else - density = (nvals_terrain[ni3d] - - nvals_terralt[ni3d]) / 2 * (1 - terblen) - - nvals_smooth[ni2d] * terblen + grad - end - - if density > 0 and empty then -- if terrain and node empty - local nofis = false - if math.abs(nvals_fissure[ni3d]) > TFIS then - nofis = true - end - if density >= STOT and nofis then -- stone, ores - if math.random(ORECHA) == 2 then - local osel = math.random(25) - if osel == 25 then - data[vi] = c_mese - elseif osel >= 22 then - data[vi] = c_mrdiamondore - elseif osel >= 19 then - data[vi] = c_mrgoldore - elseif osel >= 10 then - data[vi] = c_mrcopperore - else - data[vi] = c_mrironore - end - else - data[vi] = c_mrstone - end - stable[si] = true - elseif density < STOT then -- fine materials - if nofis and stable[si] then - if math.random() < icecha then - data[vi] = c_waterice - else - data[vi] = c_dust - end - else -- fissure - data[vi] = c_vacuum - stable[si] = false - end - else -- fissure or unstable missing node - data[vi] = c_vacuum - stable[si] = false - end - else -- vacuum or spawn egg - if empty then - data[vi] = c_vacuum - end - stable[si] = false - end - - ni3d = ni3d + 1 - ni2d = ni2d + 1 - vi = vi + 1 - end - ni2d = ni2d - chulens - end - ni2d = ni2d + chulens - end - - vm:set_data(data) - vm:set_lighting({day=0, night=0}) - vm:calc_lighting() - vm:write_to_map(data) - - --local chugent = math.ceil((os.clock() - t1) * 1000) - --print ("[moonrealm] chunk generation " .. chugent .. " ms") -end) - - --- Find spawn function, dependant on chunk size of 80 nodes --- TODO allow any chunksize, search using 2D noises first - -local function moonrealm_find_spawn() - local PSCA = 8 - - local nobj_terrain = nil - local nobj_terralt = nil - local nobj_fault = nil - - local nobj_smooth = nil - local nobj_terblen = nil - local nobj_gradcen = nil - - for chunk = 1, 128 do - print ("[moonrealm] searching for spawn " .. chunk) - - local x0 = 80 * math.random(-PSCA, PSCA) - 32 - local z0 = 80 * math.random(-PSCA, PSCA) - 32 - local y0 = 80 * math.floor((GRADCEN + 32) / 80) - 32 - local x1 = x0 + 79 - local z1 = z0 + 79 - local y1 = y0 + 79 - - local chulens = x1 - x0 + 1 - local pmaplens2d = {x = chulens, y = chulens, z = 1} - local pmaplens3d = {x = chulens, y = chulens, z = chulens} - local minpos2d = {x = x0, y = z0} - local minpos3d = {x = x0, y = y0, z = z0} - - nobj_terrain = nobj_terrain or minetest.get_perlin_map(np_terrain, pmaplens3d) - nobj_terralt = nobj_terralt or minetest.get_perlin_map(np_terralt, pmaplens3d) - nobj_fault = nobj_fault or minetest.get_perlin_map(np_fault, pmaplens3d) - - nobj_smooth = nobj_smooth or minetest.get_perlin_map(np_smooth, pmaplens2d) - nobj_terblen = nobj_terblen or minetest.get_perlin_map(np_terblen, pmaplens2d) - nobj_gradcen = nobj_gradcen or minetest.get_perlin_map(np_gradcen, pmaplens2d) - - local nvals_terrain = nobj_terrain:get3dMap_flat(minpos3d) - local nvals_terralt = nobj_terralt:get3dMap_flat(minpos3d) - local nvals_fault = nobj_fault :get3dMap_flat(minpos3d) - - local nvals_smooth = nobj_smooth :get2dMap_flat(minpos2d) - local nvals_terblen = nobj_terblen:get2dMap_flat(minpos2d) - local nvals_gradcen = nobj_gradcen:get2dMap_flat(minpos2d) - - local ni3d = 1 - local ni2d = 1 - local stable = {} - - for z = z0, z1 do - for y = y0, y1 do - for x = x0, x1 do - local si = x - x0 + 1 - local grad - local density - local terblen = math.max(math.min( - math.abs(nvals_terblen[ni2d]) * 4, 1.5), 0.5) - 0.5 - local gradcen = GRADCEN + nvals_gradcen[ni2d] * CENAMP - - if y > gradcen then - grad = -((y - gradcen) / HIGRAD) ^ HEXP - else - grad = ((gradcen - y) / LOGRAD) ^ LEXP - end - - if nvals_fault[ni3d] >= 0 then - density = (nvals_terrain[ni3d] + - nvals_terralt[ni3d]) / 2 * (1 - terblen) + - nvals_smooth[ni2d] * terblen + grad - else - density = (nvals_terrain[ni3d] - - nvals_terralt[ni3d]) / 2 * (1 - terblen) - - nvals_smooth[ni2d] * terblen + grad - end - - if density >= STOT then - stable[si] = true - -- just above ground, smooth terrain, away from faults - elseif stable[si] and density < 0 and terblen == 1 and - math.abs(nvals_fault[ni3d]) > 0.25 then - return {x = x, y = y, z = z} - end - - ni3d = ni3d + 1 - ni2d = ni2d + 1 - end - ni2d = ni2d - chulens - end - ni2d = ni2d + chulens - end - end - - return {x = 0, y = GRADCEN, z = 0} -- fallback spawn point -end - - --- Spawn newplayer function - -minetest.register_on_newplayer(function(player) - local spawn_pos = moonrealm_find_spawn() - print ("[moonrealm] spawn new player (" .. spawn_pos.x .. " " .. - spawn_pos.y .. " " .. spawn_pos.z .. ")") - player:setpos(spawn_pos) - - local inv = player:get_inventory() - inv:add_item("main", "default:pick_diamond 4") - inv:add_item("main", "default:shovel_diamond 4") - inv:add_item("main", "default:axe_diamond 4") - inv:add_item("main", "default:apple 64") - inv:add_item("main", "moonrealm:photovoltaic 256") - inv:add_item("main", "moonrealm:light 16") - inv:add_item("main", "moonrealm:glass 16") - inv:add_item("main", "moonrealm:storage 4") - inv:add_item("main", "moonrealm:airlock 4") - inv:add_item("main", "moonrealm:airgen 4") - inv:add_item("main", "moonrealm:air_cylinder 4") - inv:add_item("main", "moonrealm:hlsource 4") - inv:add_item("main", "moonrealm:sapling 4") - inv:add_item("main", "moonrealm:spacesuit 4") - inv:add_item("main", "moonrealm:rover") -end) - - --- Respawn player function - -minetest.register_on_respawnplayer(function(player) - local spawn_pos = moonrealm_find_spawn() - print ("[moonrealm] respawn player (" .. spawn_pos.x .. " " .. - spawn_pos.y .. " " .. spawn_pos.z .. ")") - player:setpos(spawn_pos) - - local inv = player:get_inventory() - inv:add_item("main", "default:pick_diamond") - inv:add_item("main", "default:shovel_diamond 4") - inv:add_item("main", "default:apple 16") - inv:add_item("main", "moonrealm:spacesuit") - - return true -end) +dofile(minetest.get_modpath("moonrealm") .. "/mapgen.lua") diff --git a/mapgen.lua b/mapgen.lua new file mode 100644 index 0000000..d287d7b --- /dev/null +++ b/mapgen.lua @@ -0,0 +1,578 @@ +-- Parameters + +local YMIN = -8000 -- Approx lower limit +local GRADCEN = 1 -- Gradient centre / terrain centre average level +local YMAX = 8000 -- Approx upper limit +local XMIN = -8000 -- Approx horizontal limits +local XMAX = 8000 +local ZMIN = -8000 +local ZMAX = 8000 + +local CENAMP = 64 -- Grad centre amplitude, terrain centre is varied by this +local HIGRAD = 128 -- Surface generating noise gradient above gradcen, controls depth of upper terrain +local LOGRAD = 128 -- Surface generating noise gradient below gradcen, controls depth of lower terrain +local HEXP = 0.5 -- Noise offset exponent above gradcen, 1 = normal 3D perlin terrain +local LEXP = 2 -- Noise offset exponent below gradcen +local STOT = 0.04 -- Stone density threshold, depth of dust + +local ICECHA = 1 / (13 * 13 * 13) -- Ice chance per dust node at terrain centre, decreases with altitude +local ICEGRAD = 128 -- Ice gradient, vertical distance for no ice +local ORECHA = 7 * 7 * 7 -- Ore 1/x chance per stone node +local TFIS = 0.01 -- Fissure threshold. Controls size of fissures +local FOOT = true -- Footprints in dust + +-- 3D noise for terrain + +local np_terrain = { + offset = 0, + scale = 1, + spread = {x = 384, y = 384, z = 384}, + seed = 58588900033, + octaves = 5, + persist = 0.67 +} + +-- 3D noise for alt terrain, 414 / 256 = golden ratio + +local np_terralt = { + offset = 0, + scale = 1, + spread = {x = 311, y = 311, z = 311}, + seed = 13331930910, + octaves = 5, + persist = 0.67 +} + +-- 2D noise for smooth terrain + +local np_smooth = { + offset = 0, + scale = 1, + spread = {x = 512, y = 512, z = 512}, + seed = 113, + octaves = 3, + persist = 0.4 +} + +-- 3D noise for fissures + +local np_fissure = { + offset = 0, + scale = 1, + spread = {x = 192, y = 192, z = 192}, + seed = 8181112, + octaves = 4, + persist = 0.5 +} + + +-- 3D noise for faults + +local np_fault = { + offset = 0, + scale = 1, + spread = {x = 414, y = 828, z = 414}, + seed = 14440002, + octaves = 4, + persist = 0.5 +} + +-- 2D noise for terrain centre + +local np_gradcen = { + offset = 0, + scale = 1, + spread = {x = 1024, y = 1024, z = 1024}, + seed = 9344, + octaves = 4, + persist = 0.4 +} + +-- 2D noise for terrain blend + +local np_terblen = { + offset = 0, + scale = 1, + spread = {x = 1024, y = 1024, z = 1024}, + seed = -13002, + octaves = 3, + persist = 0.4 +} + + +-- Set mapgen parameters + +minetest.set_mapgen_params({mgname = "singlenode", water_level = -31000}) + + +-- Player positions, spacesuit texture status + +local player_pos = {} +local player_pos_previous = {} +local player_spacesuit = {} -- To avoid unnecessary resetting of character model + +minetest.register_on_joinplayer(function(player) + player_pos_previous[player:get_player_name()] = {x = 0, y = 0, z = 0} + + if player:get_inventory():contains_item("main", "moonrealm:spacesuit") then + player:set_properties({textures = {"moonrealm_space_character.png"}}) + player_spacesuit[player:get_player_name()] = true + player:get_inventory():set_stack("hand", 1, "moonrealm:glove") + else + player:set_properties({textures = {"character.png"}}) + player_spacesuit[player:get_player_name()] = false + player:get_inventory():set_stack("hand", 1, "") + end +end) + +minetest.register_on_leaveplayer(function(player) + player_pos_previous[player:get_player_name()] = nil + player_spacesuit[player:get_player_name()] = nil +end) + + +-- Globalstep function + +minetest.register_globalstep(function(dtime) + for _, player in ipairs(minetest.get_connected_players()) do + + -- Footprints + if FOOT and math.random() < 0.15 and + player_pos_previous[player:get_player_name()] ~= nil then + local pos = player:getpos() + player_pos[player:get_player_name()] = { + x = math.floor(pos.x + 0.5), + y = math.floor(pos.y + 0.2), + z = math.floor(pos.z + 0.5) + } + local p_ground = { + x = math.floor(pos.x + 0.5), + y = math.floor(pos.y + 0.4), + z = math.floor(pos.z + 0.5) + } + local n_ground = minetest.get_node(p_ground).name + local p_groundpl = { + x = math.floor(pos.x + 0.5), + y = math.floor(pos.y - 0.5), + z = math.floor(pos.z + 0.5) + } + if player_pos[player:get_player_name()].x ~= + player_pos_previous[player:get_player_name()].x or + player_pos[player:get_player_name()].y < + player_pos_previous[player:get_player_name()].y or + player_pos[player:get_player_name()].z ~= + player_pos_previous[player:get_player_name()].z then + if n_ground == "moonrealm:dust" then + if math.random() < 0.5 then + minetest.add_node( + p_groundpl, + {name = "moonrealm:dustprint1"} + ) + else + minetest.add_node( + p_groundpl, + {name = "moonrealm:dustprint2"} + ) + end + end + end + player_pos_previous[player:get_player_name()] = { + x = player_pos[player:get_player_name()].x, + y = player_pos[player:get_player_name()].y, + z = player_pos[player:get_player_name()].z + } + end + + -- Spacesuit. Restore breath, reset spacesuit texture and glove + if math.random() < 0.04 then + if player:get_inventory():contains_item("main", "moonrealm:spacesuit") then + -- Spacesuit in inventory + if player:get_breath() < 10 then + player:set_breath(10) + end + if player_spacesuit[player:get_player_name()] == false then + player:set_properties({textures = {"moonrealm_space_character.png"}}) + player_spacesuit[player:get_player_name()] = true + player:get_inventory():set_stack("hand", 1, "moonrealm:glove") + end + else + -- No spacesuit in inventory + if player_spacesuit[player:get_player_name()] == true then + player:set_properties({textures = {"character.png"}}) + player_spacesuit[player:get_player_name()] = false + player:get_inventory():set_stack("hand", 1, "") + end + end + end + + -- Set gravity and skybox, override light + if math.random() < 0.01 then + local pos = player:getpos() + if pos.y > YMIN and pos.y < YMAX then -- Entering realm + player:set_physics_override(1, 0.6, 0.2) -- Speed, jump, gravity + local skytextures = { + "moonrealm_posy.png", + "moonrealm_negy.png", + "moonrealm_posz.png", + "moonrealm_negz.png", + "moonrealm_negx.png", + "moonrealm_posx.png", + } + player:set_sky({r = 0, g = 0, b = 0, a = 0}, "skybox", skytextures) + player:override_day_night_ratio(1) + else + -- Leaving realm + player:set_physics_override(1, 1, 1) + player:set_sky({}, "regular", {}) + player:override_day_night_ratio(nil) + end + end + end +end) + + +-- Initialize noise objects to nil + +local nobj_terrain = nil +local nobj_terralt = nil +local nobj_fissure = nil +local nobj_fault = nil + +local nobj_smooth = nil +local nobj_terblen = nil +local nobj_gradcen = nil + + +-- Localise noise buffers + +local nbuf_terrain +local nbuf_terralt +local nbuf_fissure +local nbuf_fault + +local nbuf_smooth +local nbuf_terblen +local nbuf_gradcen + + +-- Localise data buffer + +local dbuf + + +-- On generated function + +minetest.register_on_generated(function(minp, maxp, seed) + if minp.x < XMIN or maxp.x > XMAX or + minp.y < YMIN or maxp.y > YMAX or + minp.z < ZMIN or maxp.z > ZMAX then + return + end + + --local t1 = os.clock() + local x1 = maxp.x + local y1 = maxp.y + local z1 = maxp.z + local x0 = minp.x + local y0 = minp.y + local z0 = minp.z + + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax} + local data = vm:get_data(dbuf) + + local c_air = minetest.get_content_id("air") + local c_ignore = minetest.get_content_id("ignore") + local c_mese = minetest.get_content_id("moonrealm:mese") + local c_mrironore = minetest.get_content_id("moonrealm:ironore") + local c_mrcopperore = minetest.get_content_id("moonrealm:copperore") + local c_mrgoldore = minetest.get_content_id("moonrealm:goldore") + local c_mrdiamondore = minetest.get_content_id("moonrealm:diamondore") + local c_mrstone = minetest.get_content_id("moonrealm:stone") + local c_waterice = minetest.get_content_id("moonrealm:waterice") + local c_dust = minetest.get_content_id("moonrealm:dust") + local c_vacuum = minetest.get_content_id("moonrealm:vacuum") + + local chulens = x1 - x0 + 1 + local pmaplens2d = {x = chulens, y = chulens, z = 1} + local pmaplens3d = {x = chulens, y = chulens, z = chulens} + local minpos2d = {x = x0, y = z0} + local minpos3d = {x = x0, y = y0, z = z0} + + nobj_terrain = nobj_terrain or minetest.get_perlin_map(np_terrain, pmaplens3d) + nobj_terralt = nobj_terralt or minetest.get_perlin_map(np_terralt, pmaplens3d) + nobj_fissure = nobj_fissure or minetest.get_perlin_map(np_fissure, pmaplens3d) + nobj_fault = nobj_fault or minetest.get_perlin_map(np_fault, pmaplens3d) + + nobj_smooth = nobj_smooth or minetest.get_perlin_map(np_smooth, pmaplens2d) + nobj_terblen = nobj_terblen or minetest.get_perlin_map(np_terblen, pmaplens2d) + nobj_gradcen = nobj_gradcen or minetest.get_perlin_map(np_gradcen, pmaplens2d) + + local nvals_terrain = nobj_terrain:get3dMap_flat(minpos3d, nbuf_terrain) + local nvals_terralt = nobj_terralt:get3dMap_flat(minpos3d, nbuf_terralt) + local nvals_fissure = nobj_fissure:get3dMap_flat(minpos3d, nbuf_fissure) + local nvals_fault = nobj_fault :get3dMap_flat(minpos3d, nbuf_fault) + + local nvals_smooth = nobj_smooth :get2dMap_flat(minpos2d, nbuf_smooth) + local nvals_terblen = nobj_terblen:get2dMap_flat(minpos2d, nbuf_terblen) + local nvals_gradcen = nobj_gradcen:get2dMap_flat(minpos2d, nbuf_gradcen) + + local ni3d = 1 + local ni2d = 1 + local stable = {} + + for z = z0, z1 do + local viu = area:index(x0, y0 - 1, z) + + for x = x0, x1 do + local si = x - x0 + 1 + local nodid = data[viu] + if nodid == c_vacuum then + stable[si] = false + else + stable[si] = true + end + viu = viu + 1 + end + + for y = y0, y1 do + local vi = area:index(x0, y, z) + local icecha = ICECHA * (1 + (GRADCEN - y) / ICEGRAD) + + for x = x0, x1 do + local nodid = data[vi] + local empty = nodid == c_air or nodid == c_ignore + local grad + local density + local si = x - x0 + 1 + local terblen = math.max(math.min( + math.abs(nvals_terblen[ni2d]) * 4, 1.5), 0.5) - 0.5 + local gradcen = GRADCEN + nvals_gradcen[ni2d] * CENAMP + + if y > gradcen then + grad = -((y - gradcen) / HIGRAD) ^ HEXP + else + grad = ((gradcen - y) / LOGRAD) ^ LEXP + end + + if nvals_fault[ni3d] >= 0 then + density = (nvals_terrain[ni3d] + + nvals_terralt[ni3d]) / 2 * (1 - terblen) + + nvals_smooth[ni2d] * terblen + grad + else + density = (nvals_terrain[ni3d] - + nvals_terralt[ni3d]) / 2 * (1 - terblen) - + nvals_smooth[ni2d] * terblen + grad + end + + if density > 0 and empty then + -- Terrain and node empty + local nofis = false + if math.abs(nvals_fissure[ni3d]) > TFIS then + nofis = true + end + if density >= STOT and nofis then + -- Stone, ores + if math.random(ORECHA) == 2 then + local osel = math.random(25) + if osel == 25 then + data[vi] = c_mese + elseif osel >= 22 then + data[vi] = c_mrdiamondore + elseif osel >= 19 then + data[vi] = c_mrgoldore + elseif osel >= 10 then + data[vi] = c_mrcopperore + else + data[vi] = c_mrironore + end + else + data[vi] = c_mrstone + end + stable[si] = true + elseif density < STOT then + -- Fine materials or fissure + if nofis and stable[si] then + -- Fine materials + if math.random() < icecha then + data[vi] = c_waterice + else + data[vi] = c_dust + end + else + -- Fissure + data[vi] = c_vacuum + stable[si] = false + end + else + -- Fissure or unstable missing node + data[vi] = c_vacuum + stable[si] = false + end + else + -- Vacuum + if empty then + data[vi] = c_vacuum + end + stable[si] = false + end + + ni3d = ni3d + 1 + ni2d = ni2d + 1 + vi = vi + 1 + end + ni2d = ni2d - chulens + end + ni2d = ni2d + chulens + end + + vm:set_data(data) + vm:set_lighting({day=0, night=0}) + vm:calc_lighting() + vm:write_to_map(data) + + --local chugent = math.ceil((os.clock() - t1) * 1000) + --print ("[moonrealm] chunk generation " .. chugent .. " ms") +end) + + +-- Find spawn function, dependant on chunk size of 80 nodes +-- TODO Allow any chunksize, search using 2D noises first + +local function moonrealm_find_spawn() + local PSCA = 8 + + local nobj_terrain = nil + local nobj_terralt = nil + local nobj_fault = nil + + local nobj_smooth = nil + local nobj_terblen = nil + local nobj_gradcen = nil + + for chunk = 1, 128 do + print ("[moonrealm] searching for spawn " .. chunk) + + local x0 = 80 * math.random(-PSCA, PSCA) - 32 + local z0 = 80 * math.random(-PSCA, PSCA) - 32 + local y0 = 80 * math.floor((GRADCEN + 32) / 80) - 32 + local x1 = x0 + 79 + local z1 = z0 + 79 + local y1 = y0 + 79 + + local chulens = x1 - x0 + 1 + local pmaplens2d = {x = chulens, y = chulens, z = 1} + local pmaplens3d = {x = chulens, y = chulens, z = chulens} + local minpos2d = {x = x0, y = z0} + local minpos3d = {x = x0, y = y0, z = z0} + + nobj_terrain = nobj_terrain or minetest.get_perlin_map(np_terrain, pmaplens3d) + nobj_terralt = nobj_terralt or minetest.get_perlin_map(np_terralt, pmaplens3d) + nobj_fault = nobj_fault or minetest.get_perlin_map(np_fault, pmaplens3d) + + nobj_smooth = nobj_smooth or minetest.get_perlin_map(np_smooth, pmaplens2d) + nobj_terblen = nobj_terblen or minetest.get_perlin_map(np_terblen, pmaplens2d) + nobj_gradcen = nobj_gradcen or minetest.get_perlin_map(np_gradcen, pmaplens2d) + + local nvals_terrain = nobj_terrain:get3dMap_flat(minpos3d) + local nvals_terralt = nobj_terralt:get3dMap_flat(minpos3d) + local nvals_fault = nobj_fault :get3dMap_flat(minpos3d) + + local nvals_smooth = nobj_smooth :get2dMap_flat(minpos2d) + local nvals_terblen = nobj_terblen:get2dMap_flat(minpos2d) + local nvals_gradcen = nobj_gradcen:get2dMap_flat(minpos2d) + + local ni3d = 1 + local ni2d = 1 + local stable = {} + + for z = z0, z1 do + for y = y0, y1 do + for x = x0, x1 do + local si = x - x0 + 1 + local grad + local density + local terblen = math.max(math.min( + math.abs(nvals_terblen[ni2d]) * 4, 1.5), 0.5) - 0.5 + local gradcen = GRADCEN + nvals_gradcen[ni2d] * CENAMP + + if y > gradcen then + grad = -((y - gradcen) / HIGRAD) ^ HEXP + else + grad = ((gradcen - y) / LOGRAD) ^ LEXP + end + + if nvals_fault[ni3d] >= 0 then + density = (nvals_terrain[ni3d] + + nvals_terralt[ni3d]) / 2 * (1 - terblen) + + nvals_smooth[ni2d] * terblen + grad + else + density = (nvals_terrain[ni3d] - + nvals_terralt[ni3d]) / 2 * (1 - terblen) - + nvals_smooth[ni2d] * terblen + grad + end + + if density >= STOT then + stable[si] = true + -- Just above ground, smooth terrain, away from faults + elseif stable[si] and density < 0 and terblen == 1 and + math.abs(nvals_fault[ni3d]) > 0.25 then + return {x = x, y = y, z = z} + end + + ni3d = ni3d + 1 + ni2d = ni2d + 1 + end + ni2d = ni2d - chulens + end + ni2d = ni2d + chulens + end + end + + return {x = 0, y = GRADCEN, z = 0} -- Fallback spawn point +end + + +-- Spawn newplayer function + +minetest.register_on_newplayer(function(player) + local spawn_pos = moonrealm_find_spawn() + print ("[moonrealm] spawn new player (" .. spawn_pos.x .. " " .. + spawn_pos.y .. " " .. spawn_pos.z .. ")") + player:setpos(spawn_pos) + + local inv = player:get_inventory() + inv:add_item("main", "default:pick_diamond 4") + inv:add_item("main", "default:shovel_diamond 4") + inv:add_item("main", "default:axe_diamond 4") + inv:add_item("main", "default:apple 64") + inv:add_item("main", "moonrealm:photovoltaic 256") + inv:add_item("main", "moonrealm:light 16") + inv:add_item("main", "moonrealm:glass 16") + inv:add_item("main", "moonrealm:storage 4") + inv:add_item("main", "moonrealm:airlock 4") + inv:add_item("main", "moonrealm:airgen 4") + inv:add_item("main", "moonrealm:air_cylinder 4") + inv:add_item("main", "moonrealm:hlsource 4") + inv:add_item("main", "moonrealm:sapling 4") + inv:add_item("main", "moonrealm:spacesuit 4") + inv:add_item("main", "moonrealm:rover") +end) + + +-- Respawn player function + +minetest.register_on_respawnplayer(function(player) + local spawn_pos = moonrealm_find_spawn() + print ("[moonrealm] respawn player (" .. spawn_pos.x .. " " .. + spawn_pos.y .. " " .. spawn_pos.z .. ")") + player:setpos(spawn_pos) + + local inv = player:get_inventory() + inv:add_item("main", "default:pick_diamond") + inv:add_item("main", "default:shovel_diamond 4") + inv:add_item("main", "default:apple 16") + inv:add_item("main", "moonrealm:spacesuit") + + return true +end) diff --git a/nodes.lua b/nodes.lua index 9e5b1da..ef17424 100644 --- a/nodes.lua +++ b/nodes.lua @@ -497,3 +497,24 @@ minetest.register_craftitem("moonrealm:lifesupport", { inventory_image = "moonrealm_lifesupport.png", groups = {not_in_creative_inventory = 1}, }) + + +-- Glove + +minetest.register_item("moonrealm:glove", { + type = "none", + wield_image = "moonrealm_glove.png", + wield_scale = {x = 1, y = 1, z = 2.5}, + stack_max = 1, + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level = 0, + groupcaps = { + crumbly = {times = {[2] = 3.00, [3] = 0.70}, uses = 0, maxlevel = 1}, + snappy = {times = {[3] = 0.40}, uses = 0, maxlevel = 1}, + oddly_breakable_by_hand = + {times = {[1] = 3.50, [2] = 2.00, [3] = 0.70}, uses = 0} + }, + damage_groups = {fleshy = 1}, + } +}) diff --git a/rover.lua b/rover.lua index a75e1b8..ec7e02c 100644 --- a/rover.lua +++ b/rover.lua @@ -6,11 +6,6 @@ local STEPH = 1.1 -- Stepheight, 0.6 = climb slabs, 1.1 = climb nodes -- Functions -local function is_ground(pos) - return minetest.registered_nodes[minetest.get_node(pos).name].walkable -end - - local function get_sign(i) if i == 0 then return 0 @@ -32,15 +27,16 @@ local function get_v(v) end --- Rover +-- Rover entity local rover = { physical = true, collide_with_objects = true, - collisionbox = {-0.53, -1.0, -0.53, 0.53, 1.0, 0.53}, + collisionbox = {-0.7, -1.0, -0.7, 0.7, 1.0, 0.7}, visual = "cube", visual_size = {x = 2.0, y = 2.0}, - textures = { -- top base rightside leftside front back + textures = { + -- Top, base, right, left, front, back "moonrealm_rover_top.png", "moonrealm_rover_base.png", "moonrealm_rover_right.png", @@ -56,6 +52,47 @@ local rover = { } +-- Rover item + +minetest.register_craftitem("moonrealm:rover", { + description = "Rover", + inventory_image = "moonrealm_rover_front.png", + wield_scale = {x = 2, y = 2, z = 2}, + + on_place = function(itemstack, placer, pointed_thing) + local under = pointed_thing.under + local node = minetest.get_node(under) + local udef = minetest.registered_nodes[node.name] + if udef and udef.on_rightclick and + not (placer and placer:get_player_control().sneak) then + return udef.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end + + if pointed_thing.type == "node" and + minetest.registered_nodes[node.name].walkable then + under.y = under.y + 1.5 + local rover = minetest.add_entity(under, "moonrealm:rover") + if rover then + rover:setyaw(placer:get_look_horizontal()) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + end + end + + return itemstack + end, +}) + + +-- Register entity + +minetest.register_entity("moonrealm:rover", rover) + + +-- Rover entity functions + function rover:on_rightclick(clicker) if not clicker or not clicker:is_player() then return @@ -68,6 +105,14 @@ function rover:on_rightclick(clicker) default.player_attached[name] = false default.player_set_animation(clicker, "stand" , 30) elseif not self.driver then + local attach = clicker:get_attach() + if attach and attach:get_luaentity() then + local luaentity = attach:get_luaentity() + if luaentity.driver then + luaentity.driver = nil + end + clicker:set_detach() + end self.driver = clicker clicker:set_attach(self.object, "", {x = 0, y = 3, z = -2}, {x = 0, y = 0, z = 0}) @@ -75,7 +120,7 @@ function rover:on_rightclick(clicker) minetest.after(0.2, function() default.player_set_animation(clicker, "sit" , 30) end) - self.object:setyaw(clicker:get_look_yaw() - math.pi / 2) + clicker:set_look_horizontal(self.object:getyaw()) end end @@ -96,20 +141,29 @@ end function rover.on_punch(self, puncher, time_from_last_punch, tool_capabilities, direction) - if self.driver then - self.driver:set_detach() - local name = self.driver:get_player_name() - default.player_attached[name] = false - default.player_set_animation(self.driver, "stand" , 30) - self.driver = nil + if not puncher or not puncher:is_player() or self.removed then + return end - -- delay remove to ensure player is detached - minetest.after(0.1, function() - self.object:remove() - end) - if puncher and puncher:is_player() and - not minetest.setting_getbool("creative_mode") then - puncher:get_inventory():add_item("main", "moonrealm:rover") + if self.driver and puncher == self.driver then + self.driver = nil + puncher:set_detach() + default.player_attached[puncher:get_player_name()] = false + end + if not self.driver then + self.removed = true + local inv = puncher:get_inventory() + if not minetest.setting_getbool("creative_mode") + or not inv:contains_item("main", "moonrealm:rover") then + local leftover = inv:add_item("main", "moonrealm:rover") + -- If no room in inventory add a replacement rover to the world + if not leftover:is_empty() then + minetest.add_item(self.object:getpos(), leftover) + end + end + -- Delay remove to ensure player is detached + minetest.after(0.1, function() + self.object:remove() + end) end end @@ -144,6 +198,7 @@ function rover:on_step(dtime) self.object:setyaw(self.object:getyaw() - turn) end end + local s = get_sign(self.v) self.v = self.v - 0.03 * s if s ~= get_sign(self.v) then @@ -155,87 +210,9 @@ function rover:on_step(dtime) if absv > MAXSP then self.v = MAXSP * get_sign(self.v) end + self.object:setacceleration({x = 0, y = -1.962, z = 0}) self.object:setvelocity(get_velocity(self.v, self.object:getyaw(), self.object:getvelocity().y)) self.object:setpos(self.object:getpos()) end - - --- Register entity - -minetest.register_entity("moonrealm:rover", rover) - - --- Item - -minetest.register_craftitem("moonrealm:rover", { - description = "Rover", - inventory_image = "moonrealm_rover_front.png", - wield_scale = {x = 2, y = 2, z = 2}, - liquids_pointable = true, - - on_place = function(itemstack, placer, pointed_thing) - if pointed_thing.type ~= "node" then - return - end - - if not is_ground(pointed_thing.under) then - return - end - - pointed_thing.under.y = pointed_thing.under.y + 1.5 - minetest.add_entity(pointed_thing.under, "moonrealm:rover") - if not minetest.setting_getbool("creative_mode") then - itemstack:take_item() - end - return itemstack - end, -}) - ---[[ -minetest.register_craftitem("mesecar:motor", { - description = "Mesecar Motor", - inventory_image = "mesecar_motor.png", - groups = {not_in_creative_inventory=1}, -}) - - -minetest.register_craftitem("mesecar:battery", { - description = "Mesecar Battery", - inventory_image = "mesecar_battery.png", - groups = {not_in_creative_inventory=1}, -}) - - --- Crafting - -minetest.register_craft({ - output = "mesecar:motor", - recipe = { - {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"}, - {"default:copper_ingot", "default:steel_ingot", "default:copper_ingot"}, - {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"}, - }, -}) - - -minetest.register_craft({ - output = "mesecar:battery", - recipe = { - {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, - {"default:steel_ingot", "default:mese_block", "default:steel_ingot"}, - {"default:copper_ingot", "default:copper_ingot", "default:steel_ingot"}, - }, -}) - - -minetest.register_craft({ - output = "mesecar:mesecar4", -- Mesecar - recipe = { - {"default:steel_ingot", "dye:yellow", "default:steel_ingot"}, - {"default:steel_ingot", "group:wool", "default:glass"}, - {"mesecar:motor", "mesecar:battery", "mesecar:motor"}, - }, -}) ---]] diff --git a/textures/moonrealm_character.png b/textures/moonrealm_character.png deleted file mode 100644 index 0502178..0000000 Binary files a/textures/moonrealm_character.png and /dev/null differ diff --git a/textures/moonrealm_glove.png b/textures/moonrealm_glove.png new file mode 100644 index 0000000..856dcf5 Binary files /dev/null and b/textures/moonrealm_glove.png differ diff --git a/textures/moonrealm_rover_back.png b/textures/moonrealm_rover_back.png index 8d34cb9..a458887 100644 Binary files a/textures/moonrealm_rover_back.png and b/textures/moonrealm_rover_back.png differ diff --git a/textures/moonrealm_rover_base.png b/textures/moonrealm_rover_base.png index 453dc1a..5a51e43 100644 Binary files a/textures/moonrealm_rover_base.png and b/textures/moonrealm_rover_base.png differ diff --git a/textures/moonrealm_rover_front.png b/textures/moonrealm_rover_front.png index e9a91d3..0609c19 100644 Binary files a/textures/moonrealm_rover_front.png and b/textures/moonrealm_rover_front.png differ diff --git a/textures/moonrealm_rover_left.png b/textures/moonrealm_rover_left.png index fb29bed..e87676b 100644 Binary files a/textures/moonrealm_rover_left.png and b/textures/moonrealm_rover_left.png differ diff --git a/textures/moonrealm_rover_right.png b/textures/moonrealm_rover_right.png index d81e6c4..fe160c3 100644 Binary files a/textures/moonrealm_rover_right.png and b/textures/moonrealm_rover_right.png differ diff --git a/textures/moonrealm_space_character.png b/textures/moonrealm_space_character.png index 996de3e..f7def6a 100644 Binary files a/textures/moonrealm_space_character.png and b/textures/moonrealm_space_character.png differ