-- toggle_areas mod by h3ndrik toggle_areas = {} local mod_storage = minetest.get_mod_storage() toggle_areas.astore = AreaStore() toggle_areas.area_privs = {} areas_owner_privs = minetest.settings:get("toggle_areas.owner_privs") or "+creative, +fast, +fly" areas_guest_privs = minetest.settings:get("toggle_areas.guest_privs") or "-fly, -fast" default_privs = minetest.settings:get("toggle_areas.default_privs") or "-creative, +fast, -fly" function toggle_areas:load_areas() local test = minetest.deserialize(mod_storage:get_string("astore")) local edge1 = { x=-10, y=-10, z=-10 } local edge2 = { x=10, y=10, z=10 } local data = "Testarea" local astore_id = self.astore:insert_area(edge1, edge2, tostring(data)) toggle_areas:set_area_privs(astore_id, "+creative, +fast, +fly") end function toggle_areas:save_areas() local datastr = minetest.serialize(self.astore) if not datastr then minetest.log("error", "[toggle_areas] Failed to serialize area data!") return end mod_storage:set_string("astore", datastr) end function toggle_areas:set_area_privs(id, privs_string) toggle_areas.area_privs[id] = privs_string end function toggle_areas:decode_privs_string(str) -- minetest/builtin/common/misc_helpers.lua:core.string_to_privs() assert(type(str) == "string") local delim = ',' local privs_grant = {} local privs_revoke = {} for _, priv in pairs(string.split(str, delim)) do priv = priv:trim() local toggle = string.sub(priv, 1, 1) priv = string.sub(priv, 2) if toggle == '+' then privs_grant[priv] = true privs_revoke[priv] = nil elseif toggle == '-' then privs_revoke[priv] = true privs_grant[priv] = nil end end return privs_grant, privs_revoke end function toggle_areas:is_areas_mod(area_id) local is_areas_id = string.sub(id, 1, 2) == "a_" local a_id = tonumber( string.sub(id, 3) ) return is_areas_id, a_id end function toggle_areas:get_area_size(astore_area) local pos1 = astore_area.min local pos2 = astore_area.max local x = math.abs( pos2.x - pos1.x ) local z = math.abs( pos2.z - pos1.x ) return x*z end function toggle_areas:save_player_privs(player) local name = player:get_player_name() local pmeta = player:get_meta() local privs = minetest.get_player_privs(name) pmeta:set_string("toggle_areas_privs", minetest.serialize(privs)) end function toggle_areas:restore_player_privs(player) local name = player:get_player_name() local pmeta = player:get_meta() local privs = minetest.deserialize(pmeta:get_string("toggle_areas_privs")) if privs then minetest.set_player_privs(name, privs) pmeta:set_string("toggle_areas_privs", nil) end end function toggle_areas:save_player_inventory(player, listname) local name = player:get_player_name() local pmeta = player:get_meta() local inv = player:get_inventory() local player_items = inv:get_list("main") inv:set_list(listname, player_items) end function toggle_areas:restore_player_inventory(player, listname) local name = player:get_player_name() local pmeta = player:get_meta() local inv = player:get_inventory() local player_items = inv:get_list(listname) or {} inv:set_list("main", player_items) end function toggle_areas:player_enter_area(player, privstring) local name = player:get_player_name() local has_creative = minetest.check_player_privs(name, {creative=true}) local privs_grant, privs_revoke = toggle_areas:decode_privs_string(privstring) if not has_creative and privs_grant.creative and not privs_revoke.creative then minetest.chat_send_player(name, "You entered creative mode") toggle_areas:save_player_inventory(player, "saved_survival") toggle_areas:restore_player_inventory(player, "saved_creative") if minetest.get_modpath("unified_inventory") then unified_inventory.set_inventory_formspec(player, unified_inventory.default) end elseif has_creative and privs_revoke.creative then minetest.chat_send_player(name, "You entered survival mode") toggle_areas:save_player_inventory(player, "saved_creative") toggle_areas:restore_player_inventory(player, "saved_survival") end local has_privs = minetest.get_player_privs(name) local privs = has_privs for newpriv, _ in pairs(privs_grant) do privs[newpriv] = true end for newpriv, _ in pairs(privs_revoke) do privs[newpriv] = nil end minetest.set_player_privs(name, privs) end function toggle_areas:update_player(player) local name = player:get_player_name() local pos = vector.round(player:get_pos()) local pmeta = player:get_meta() -- pmeta:mark_as_private("toggle_areas") local player_last_active_areas = pmeta:get_string("toggle_areas.active_areas") or "-1" local player_active_areas = "-1" local areas_owner = false local areas_guest = false local areas_open = false local new_area = nil local smallest_area = {} if minetest.check_player_privs(name, { protection_bypass=true }) then minetest.log("warning", "[toggle_areas] Player has protection_bypass priv") return end -- enter area local current_areas = self.astore:get_areas_for_pos(pos, true, true) for astore_id, astore_area in pairs( current_areas ) do local areasize = toggle_areas:get_area_size(astore_area) if not smallest_area.size or areasize < smallest_area.size then smallest_area.id = astore_id smallest_area.size = areasize end end if smallest_area.id then player_active_areas = tostring(smallest_area.id) end -- enter areas mod area local a_current_areas = {} if minetest.get_modpath("areas") then a_current_areas = areas:getAreasAtPos(pos) for a_id, a_area in pairs( a_current_areas ) do player_active_areas = player_active_areas .. ", a"..a_id if a_area.owner == name then areas_owner = true break elseif a_area.open then areas_open = true break else areas_guest = true --continue end end end local privstring = default_privs if smallest_area.id and toggle_areas.area_privs[smallest_area.id] then privstring = toggle_areas.area_privs[smallest_area.id] end if areas_owner or areas_open then privstring = privstring .. ", " .. areas_owner_privs elseif areas_guest then privstring = privstring .. ", " .. areas_guest_privs for _, a in pairs(string.split(player_active_areas, ",")) do a = a:trim() if string.sub(a, 1, 1) == "a" then if toggle_areas.area_privs[a] then privstring = privstring .. ", " .. toggle_areas.area_privs[a] end end end end if player_active_areas ~= player_last_active_areas then minetest.log("warning", "[toggle_areas] player entering new area "..player_last_active_areas.."->"..player_active_areas) toggle_areas:player_enter_area(player, privstring) pmeta:set_string("toggle_areas.active_areas", player_active_areas) end -- print(dump(pmeta:to_table())) end toggle_areas:load_areas() local timer = 0 minetest.register_globalstep(function(dtime) timer = timer + dtime if timer >= 1 then for _, player in pairs(minetest.get_connected_players()) do toggle_areas:update_player(player) end end end) -- areas mod hud if minetest.get_modpath("areas") then local function areas_hud_handler(pos, areas) local current_areas = toggle_areas.astore:get_areas_for_pos(pos, false, true) for astore_id, astore_area in pairs( current_areas ) do if astore_id then table.insert(areas, { id = "mod:"..astore_id, name = astore_area.data, --owner = "", }) end end end areas:registerHudHandler(areas_hud_handler) end