diff --git a/nc_sky_isgen/init.lua b/nc_sky_isgen/init.lua index 51b94dd..78accfe 100644 --- a/nc_sky_isgen/init.lua +++ b/nc_sky_isgen/init.lua @@ -84,13 +84,24 @@ local function spawn_island(name,pos) ref:set_pos({x=pos.x,y=pos.y+256,z=pos.z}) end local store = minetest.get_mod_storage() +local players = minetest.deserialize(store:get_string("players")) or {} +local cells = minetest.deserialize(store:get_string("cells")) or {} +local function save() + store:set_string("players",minetest.serialize(players)) + store:set_string("cells",minetest.serialize(cells)) +end local function pid(x,z) return "i"..x.."_"..z end local function checkpos(x,z) - if store:get_string(pid(x,z)) == "" then - return true + local cell = cells[pid(x,z)] + local v = true + if cell then + v = cell.valid + else + v = store:get_string(pid(x,z)) == "" end + return v end minetest.override_item("ignore",{ drawtype = "normal", @@ -105,11 +116,32 @@ local function gen_island_pos(name) x,z = x+math.random(-1,1),z+math.random(-1,1) ok = checkpos(x,z) end - store:set_string(pid(x,z),name) - local range = {min={x=x*128-64,y=256-64,z=z*128-64},max={x=x*128+64,y=256+64,z=z*128+64}} - local ip = {x=x*128+math.random(-32,32),y=256+math.random(-32,32),z=z*128+math.random(-32,32)} - spawn_island(name,ip) - return pid(x,z),ip,range + local range,ip + local ocell = cells[pid(x,z)] + if ocell and ocell.valid then + range = ocell.islandrange + ip = ocell.islandpos + if players[ocell.name] and players[ocell.name].island == pid(x,z) then + players[ocell.name] = nil + end + local ref = minetest.get_player_by_name(name) + local pos = ip + pos = {x=f(pos.x),y=f(pos.y),z=f(pos.z)} + ref:set_pos({x=pos.x,y=pos.y+256,z=pos.z}) + else + range = {min={x=x*128-64,y=256-64,z=z*128-64},max={x=x*128+64,y=256+64,z=z*128+64}} + ip = {x=x*128+math.random(-32,32),y=256+math.random(-32,32),z=z*128+math.random(-32,32)} + spawn_island(name,ip) + end + local pl = { + island = pid(x,z), + islandpos = ip, + islandrange = range, + name = name + } + players[name] = pl + cells[pid(x,z)] = pl + save() end local updrate = 0.5 local to_upd = updrate @@ -141,61 +173,150 @@ minetest.register_globalstep(function(dt) end end) -minetest.register_chatcommand("reset",{ - description = "Reset your island", +local function get_standing_island(name) + local ref = minetest.get_player_by_name(name) + local pos = ref:get_pos() + local x = math.floor(pos.x/128+.5) + local z = math.floor(pos.z/128+.5) + return pid(x,z) +end + +minetest.register_chatcommand("assign", { + description = "Reassign this island", + privs = {server = true}, func = function(name,param) - local ref = minetest.get_player_by_name(name) - local meta = ref:get_meta() - local r = meta:get_string("islandrange") - r = minetest.deserialize(r) - minetest.emerge_area(r.min,r.max,function(bp,act,crem) - if crem > 0 then - return - end - local ref = minetest.get_player_by_name(name) - local meta = ref:get_meta() - local istr = meta:get_string("islandpos") - local pos = minetest.string_to_pos(istr) - if pos then - local r = meta:get_string("islandrange") - r = minetest.deserialize(r) - print("Resetting island "..istr.." owned by "..name) - air_c = minetest.get_content_id("air") - local vm = VoxelManip(r.min,r.max) - local rmi,rma = vm:get_emerged_area() - local var = VoxelArea:new{MinEdge=rmi,MaxEdge=rma} - local d = vm:get_data() - for x=r.min.x,r.max.x do - for y=r.min.y,r.max.y do - for z=r.min.z,r.max.z do - local i = var:index(x,y,z) - d[i] = air_c - end - end - end - local cpos = {x=(r.min.x+r.max.x)/2,y=(r.min.y+r.max.y)/2,z=(r.min.z+r.max.z)/2}; - local r = - (abs(r.min.x-cpos.x)+abs(r.max.x-cpos.x)+ - abs(r.min.y-cpos.y)+abs(r.max.y-cpos.y)+ - abs(r.min.z-cpos.z)+abs(r.max.z-cpos.z))/6 - for k,v in pairs(minetest.get_objects_inside_radius(cpos,r)) do - v:remove() - end - vm:set_data(d) - vm:write_to_map() - spawn_island(name,pos) - end - end) + local is = get_standing_island(name) + if not minetest.get_player_by_name(param) then + minetest.chat_send_player(name,"No player "..param) + return + end + players[param] = nil + if not cells[is] then + minetest.chat_send_player(name,"No island here") + return + end + if not cells[is] then + range = {min={x=x*128-64,y=256-64,z=z*128-64},max={x=x*128+64,y=256+64,z=z*128+64}} + ip = {x=x*128+math.random(-32,32),y=256+math.random(-32,32),z=z*128+math.random(-32,32)} + spawn_island(param,ip) + else + cells[is].name = param + end + minetest.chat_send_player(name,"OK") + save() + end +}) + +minetest.register_chatcommand("unassign", { + description = "Unassign this island", + privs = {server = true}, + func = function(name,param) + local is = get_standing_island(name) + if not cells[is] then + minetest.chat_send_player(name,"This cell is not assigned") + return + end + local nam = cells[is].name + players[nam] = nil + cells[is].name = "" + store:set_string(is,"") + minetest.chat_send_player(name,"OK") + save() + end +}) + +minetest.register_chatcommand("validate", { + description = "Make this island avaible for newcomers", + privs = {server = true}, + func = function(name,param) + local is = get_standing_island(name) + if cells[is] then + cells[is].valid = true + minetest.chat_send_player(name,"OK") + else + minetest.chat_send_player(name,"No island here") + return + end + save() + end +}) + +minetest.register_chatcommand("invalidate", { + description = "Make this island unavaible for newcomers", + privs = {server = true}, + func = function(name,param) + local is = get_standing_island(name) + if cells[is] then + cells[is].valid = false + else + minetest.chat_send_player(name,"No island here") + return + end + save() + end +}) + +minetest.register_chatcommand("query", { + description = "Query information about this island", + func = function(name,param) + local is = get_standing_island(name) + if cells[is] then + minetest.chat_send_player(name,is..": [") + minetest.chat_send_player(name," owner: "..((cells[is].name == "" and "(none)" or cells[is].name) or "(none)")) + minetest.chat_send_player(name," takeable: "..tostring(cells[is].valid)) + minetest.chat_send_player(name," pos: "..minetest.pos_to_string(cells[is].islandpos)) + minetest.chat_send_player(name," range: "..minetest.serialize(cells[is].islandrange)) + minetest.chat_send_player(name,"]") + else + minetest.chat_send_player(name,is..": No island here") + end + save() + end +}) + +minetest.register_chatcommand("reset",{ + description = "Get a new island", + privs = {interact = true}, + func = function(name) + local pl = players[name] + if pl then + store:set_string(pl.island,"") + pl.name = nil + pl.valid = false + end + gen_island_pos(name) end }) minetest.register_on_joinplayer(function(ref) local meta = ref:get_meta() local name = ref:get_player_name() - if meta:get_string("island") == "" then - local p,ip,r = gen_island_pos(name) - meta:set_string("island",p) - meta:set_string("islandpos",minetest.pos_to_string(ip)) - meta:set_string("islandrange",minetest.serialize(r)) + if meta:get_string("island") ~= "" then + if not cells[meta:get_string("island")] then + local pl = { + island = meta:get_string("island"), + islandpos = minetest.string_to_pos(meta:get_string("islandpos")), + islandrange = minetest.deserialize(meta:get_string("islandrange")), + name = name + } + players[name] = pl + cells[meta:get_string("island")] = pl + else + gen_island_pos(name) + end + save() + meta:set_string("island","") + meta:set_string("islandpos","") + meta:set_string("islandrange","") + else + if not players[name] then + gen_island_pos(name) + else + local p = players[name] + local c = cells[p.island] + if c.name ~= p.name then + gen_island_pos(name) + end + end end end) \ No newline at end of file