diff --git a/arena.lua b/arena.lua new file mode 100644 index 0000000..dfe0c22 --- /dev/null +++ b/arena.lua @@ -0,0 +1,62 @@ +minetest.register_privilege("arena", { + description = "Player is involved in an arena battle.", + give_to_singleplayer= false, +}) + +local drop = function(pos, itemstack) + local obj = minetest.add_item(pos, itemstack:take_item(itemstack:get_count())) + if obj then + obj:set_velocity({ + x = math.random(-10, 10) / 9, + y = 5, + z = math.random(-10, 10) / 9, + }) + end +end + +function creative_regions.drop_everything(player, drop_bones) + local player_inventory_lists = { "main", "craft" } + local player_inv = player:get_inventory() + local pos = player:get_pos() + + for _, list_name in ipairs(player_inventory_lists) do + for i = 1, player_inv:get_size(list_name) do + drop(pos, player_inv:get_stack(list_name, i)) + end + player_inv:set_list(list_name, {}) + end + if drop_bones then + drop(pos, ItemStack("bones:bones")) +-- minetest.item_drop(itemstack, player, pos) + end +end + +minetest.register_on_dieplayer(function(player) + local player_name = player:get_player_name() + if minetest.check_player_privs(player_name, {arena=true}) then + creative_regions.drop_everything(player, true) + local privs = minetest.get_player_privs(player_name) + privs["arena"] = nil + minetest.set_player_privs(player_name, privs) + end +end) + +if minetest.get_modpath("areas") then + + minetest.register_node("creative_regions:protector_arena", { + description = "Arena protector", + tiles = {"creative_regions_protector_arena.png"}, + tiles = {"default_cobble.png^default_tool_diamondsword.png"}, + is_ground_content = true, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=1}, + light_source = 1, + after_place_node = function(pos, placer, itemstack, pointed_thing) + return creative_regions.protector_set_area_privs(pos, placer, itemstack, pointed_thing, "-creative -fast, -fly, +arena", "Arena Protector") + end, + can_dig = creative_regions.protector_can_dig, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + return creative_regions.protector_remove_area_privs(pos, oldnode, oldmetadata, digger, "Arena protector") + end + }) + +end diff --git a/init.lua b/init.lua index a51ac24..be89f9e 100644 --- a/init.lua +++ b/init.lua @@ -1,5 +1,7 @@ -- creative_regions mod by h3ndrik +local S = minetest.get_translator("creative_regions") + creative_regions = {} @@ -8,6 +10,7 @@ areas_guest_privs = minetest.settings:get("creative_regions.guest_privs") or "" noregion_privs = minetest.settings:get("creative_regions.noregion_privs") or "-creative, +fast, -fly" default_privs = minetest.settings:get("creative_regions.default_privs") or "+creative, +fast, +fly" +non_sticky_privs = {"arena"} -- always remove areas priv when not explicitly requested by current area creative_regions.modpath = minetest.get_modpath("creative_regions") dofile(creative_regions.modpath.."/region.lua") @@ -15,6 +18,7 @@ dofile(creative_regions.modpath.."/player.lua") dofile(creative_regions.modpath.."/chatcommands.lua") dofile(creative_regions.modpath.."/items.lua") dofile(creative_regions.modpath.."/mod_areas.lua") +dofile(creative_regions.modpath.."/arena.lua") function creative_regions:update_player(player) @@ -75,9 +79,9 @@ function creative_regions:update_player(player) if string.sub(region.id, 1, 1) == "a" then areas_individual_override = true end - elseif string.sub(region.id, 1, 1) == "r" then + elseif string.sub(region.id, 1, 1) == "r" then -- region creative_regions:add_privs_from_string(new_privs_table, default_privs) - elseif string.sub(region.id, 1, 1) == "a" then + elseif string.sub(region.id, 1, 1) == "a" then -- areas mod if not areas_individual_override then creative_regions:add_privs_from_string(new_privs_table, areas_guest_privs) end @@ -90,6 +94,7 @@ function creative_regions:update_player(player) end -- did the regions change? update + -- ToDo: Update on privileges changed local player_last_active_region_str = pmeta:get_string("creative_regions.active_regions") or "" if player_active_region_str ~= player_last_active_region_str then creative_regions:player_enter_region(player, new_privs_table) diff --git a/items.lua b/items.lua index 4c480d2..d66dcc4 100644 --- a/items.lua +++ b/items.lua @@ -1,6 +1,6 @@ if minetest.get_modpath("areas") then - function creative_regions.protector_set_noflyzone(pos, placer, itemstack, pointed_thing) + function creative_regions.protector_set_area_privs(pos, placer, itemstack, pointed_thing, privstring, description) if not pos or not placer then return end @@ -17,15 +17,16 @@ if minetest.get_modpath("areas") then end if player_owns_id then - meta:set_string("infotext", string.format("No-Fly-Zone Protector for area %s owned by %s", player_owns_id, name)) + meta:set_string("infotext", string.format(description.." for area %s owned by %s", player_owns_id, name)) meta:set_string("area_id", player_owns_id) + meta:set_string("privstring", privstring) meta:set_string("owner", name) - creative_regions.set_region_privs(tostring(player_owns_id), "-fast, -fly") - minetest.chat_send_player(name, "[creative_regions] No-Fly-Zone set for region " .. player_owns_id) + creative_regions.add_region_privs(tostring(player_owns_id), privstring) + minetest.chat_send_player(name, "[creative_regions] "..description.." set for region " .. player_owns_id) creative_regions.save_regions() else - minetest.chat_send_player(name, "[creative_regions] You need to be inside an area to set a No-Fly-Zone") + minetest.chat_send_player(name, "[creative_regions] You need to be inside an area to set a "..description) minetest.after(0.2, function(pos) minetest.remove_node(pos) end, pos) @@ -40,6 +41,7 @@ if minetest.get_modpath("areas") then local name = player:get_player_name() local meta = minetest.get_meta(pos) local id = meta:get_string("area_id") + local privstring = meta:get_string("privstring") local owner = meta:get_string("owner") local player_owns_id = nil @@ -59,26 +61,30 @@ if minetest.get_modpath("areas") then if player_owns_id then return true else - minetest.chat_send_player(name, "[creative_regions] Cannot remove No-Fly-Zone "..id.." owned by "..owner) + minetest.chat_send_player(name, "[creative_regions] Cannot remove protector block for area "..id.." owned by "..owner) return false end end - function creative_regions.protector_remove_noflyzone(pos, oldnode, oldmetadata, digger) + function creative_regions.protector_remove_area_privs(pos, oldnode, oldmetadata, digger, description) if not oldmetadata or not oldmetadata.fields then return end local owner = oldmetadata.fields.owner local stored_id = oldmetadata.fields.area_id + local privstring = oldmetadata.fields.privstring local name = digger:get_player_name() local current_areas = areas:getAreasAtPos(pos) for areas_id, areas_area in pairs( current_areas ) do local id = "a"..tostring(areas_id) if stored_id == id then - creative_regions.set_region_privs(tostring(id), nil) - minetest.chat_send_player(name, "[creative_regions] No-Fly-Zone for area " .. id .. " removed") + local success = creative_regions.strip_region_privs(tostring(id), privstring) + minetest.chat_send_player(name, "[creative_regions] "..description.." removed for area " .. id) + if not success then + minetest.chat_send_player(name, "[creative_regions] Failed to remove privileges!") + end creative_regions.save_regions() end end @@ -86,14 +92,19 @@ if minetest.get_modpath("areas") then end minetest.register_node("creative_regions:protector_nofly", { - description = "No-Fly-Zone Protector", + description = "No-Fly-Zone protector", tiles = {"creative_regions_protector_nofly.png"}, + tiles = {"default_cobble.png^default_clay_brick.png"}, is_ground_content = true, groups = {snappy=2,choppy=2,oddly_breakable_by_hand=1}, light_source = 1, - after_place_node = creative_regions.protector_set_noflyzone, + after_place_node = function(pos, placer, itemstack, pointed_thing) + return creative_regions.protector_set_area_privs(pos, placer, itemstack, pointed_thing, "-fast, -fly", "No-Fly-Zone Protector") + end, can_dig = creative_regions.protector_can_dig, - after_dig_node = creative_regions.protector_remove_noflyzone, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + return creative_regions.protector_remove_area_privs(pos, oldnode, oldmetadata, digger, "No-Fly-Zone protector") + end }) --minetest.register_alias("noflyzone", "creative_regions:noflyprotector") diff --git a/player.lua b/player.lua index cc6ec81..b73a5d7 100644 --- a/player.lua +++ b/player.lua @@ -59,24 +59,55 @@ end function creative_regions:player_enter_region(player, new_privs_table) local name = player:get_player_name() local has_creative = minetest.check_player_privs(name, {creative=true}) + local has_arena = minetest.check_player_privs(name, {arena=true}) + local old_mode = nil + if has_arena then + old_mode = "arena" + elseif has_creative then + old_mode = "creative" + else + old_mode = "survival" + end + local privs_grant, privs_revoke = creative_regions:decode_privs_table(new_privs_table) - if not has_creative and privs_grant.creative and not privs_revoke.creative then - minetest.chat_send_player(name, "You entered creative mode") - creative_regions:save_player_inventory(player, "saved_survival") - creative_regions:restore_player_inventory(player, "saved_creative") - if minetest.get_modpath("unified_inventory") then - unified_inventory.set_inventory_formspec(player, unified_inventory.default) + local new_mode = nil + if privs_grant.arena and not privs_revoke.arena then + new_mode = "arena" + elseif privs_grant.creative and not privs_revoke.creative then + new_mode = "creative" + else + new_mode = "survival" + end + + if new_mode ~= old_mode then + + if old_mode == "arena" then + -- leaving arena (alive) + creative_regions.drop_everything(player, false) end - elseif has_creative and privs_revoke.creative then - minetest.chat_send_player(name, "You entered survival mode") - creative_regions:save_player_inventory(player, "saved_creative") - creative_regions:restore_player_inventory(player, "saved_survival") + + minetest.chat_send_player(name, "You entered "..new_mode.." mode") + creative_regions:save_player_inventory(player, "saved_"..old_mode) + creative_regions:restore_player_inventory(player, "saved_"..new_mode) + + if new_mode == "creative" then + if minetest.get_modpath("unified_inventory") then + unified_inventory.set_inventory_formspec(player, unified_inventory.default) + end + elseif new_mode == "arena" then + local inv = player:get_inventory() + inv:set_list("main", {}) + end + end local has_privs = minetest.get_player_privs(name) local privs = has_privs + for _, p in pairs(non_sticky_privs) do + privs[p] = nil + end for newpriv, _ in pairs(privs_grant) do privs[newpriv] = true end diff --git a/region.lua b/region.lua index 59b1444..1ba674e 100644 --- a/region.lua +++ b/region.lua @@ -36,6 +36,41 @@ function creative_regions.set_region_privs(id, privs_string) creative_regions.region_privs[tostring(id)] = privs_string end +function creative_regions.add_region_privs(id, privs_string) + local region_privs = creative_regions.region_privs[tostring(id)] + if not region_privs or region_privs == '' then + creative_regions.region_privs[tostring(id)] = privs_string + else + creative_regions.region_privs[tostring(id)] = region_privs .. ", " .. privs_string + end +end + +function creative_regions.strip_region_privs(id, privs_string) + local region_privs = creative_regions.region_privs[tostring(id)] + if not privs_string then + return false + end + + local find = privs_string:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0") + local new_region_privs = region_privs:gsub(find..",%s?", "", 1) + if new_region_privs == region_privs then + new_region_privs = region_privs:gsub(",%s?"..find, "", 1) + end + if new_region_privs == region_privs then + new_region_privs = region_privs:gsub(find, "", 1) + end + + if not new_region_privs or new_region_privs == region_privs then + return false + elseif new_region_privs == "" then + creative_regions.region_privs[tostring(id)] = nil + return true + else + creative_regions.region_privs[tostring(id)] = new_region_privs + return true + end +end + function creative_regions:decode_privs_table(privs_table) local privs_grant = {} local privs_revoke = {} diff --git a/textures/creative_regions_protector_arena.png b/textures/creative_regions_protector_arena.png new file mode 100644 index 0000000..b610705 Binary files /dev/null and b/textures/creative_regions_protector_arena.png differ diff --git a/textures/creative_regions_protector_nofly.png b/textures/creative_regions_protector_nofly.png index ccc3e5c..b0f94b2 100644 Binary files a/textures/creative_regions_protector_nofly.png and b/textures/creative_regions_protector_nofly.png differ