From 54c16c96692545ff24dc9ebd7bf4ba8cb6570bfc Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Sun, 31 May 2020 21:53:46 +0200 Subject: [PATCH] arena mode --- arena.lua | 62 ++++++++++++++++++ init.lua | 9 ++- items.lua | 35 ++++++---- player.lua | 51 +++++++++++--- region.lua | 35 ++++++++++ textures/creative_regions_protector_arena.png | Bin 0 -> 618 bytes textures/creative_regions_protector_nofly.png | Bin 2183 -> 619 bytes 7 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 arena.lua create mode 100644 textures/creative_regions_protector_arena.png 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 0000000000000000000000000000000000000000..b610705ba67c16a6ec4e72e459bad18c9f360d80 GIT binary patch literal 618 zcmV-w0+s!VP)EX>4Tx04R}tkv&MmKpe$iQ%glE4lO9^kfAzR5EXIMDionYs1;guFuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|}?mh0_0YbgZG^=YI&~)2O zCE{WxyDA1>5x@}o5e8&t8FP}9M91-U4)O(glehxvqHp#<}3Kz%wIeIyFxmAr=d5th6yJni}yGaa7fG$`>*o ztDLtuYvn3y-jlyDl+#z1xlVH!2`pj>5=1DdqJ%PR#Aww?v5=zucnANW>zBx-kgEhn zjs;YpL3aJ%fAG6oD?d5mC57TZ;Kgx1Mu6Zh(5N}i_p#$NP5}QiaHY5Wl{zrBaL#0k|*GO0000FP)t-sEh!{OK{i%TNQr%L|A2tf1jTIt z000SaNLh0L01FcU01FcV0GgZ_0001SNklEX>4Tx04R}tkv&MmKpe$iTZ8dEUV96d_TWPnc~o@KgW5pNJrZCX0#ec}i!N(%8g@u)!;B!1+&?D8Aug2R5E z88OnSdEyAMP-tVhjaku9i6@DpimFk*KjX5(d5g1JuCnGm`3pliZDpD3G>4GDB9S6a(osRPrWq}N(n^a$wP1}?5!n!E>G?g0Hyx@1U>6rkzP z=YjV#`lc)pz6HA1+}@h|IDG)p)K&5ZI5-4G3Y5L>@e=N?_TK(I)9mjDwp?<;o<=`c eldcCI5(#ifS#tmY3ljhU3ljkVnw%Ju{s)QmO2a<@ delta 2018 zcmV<82Oaq91cwojBYy?)dQ@0+Qek%>aB^>EX>4U6ba`-PAZ2)IW&i+q+O1dX(c~x$ z{7)1Y0*H4wJgYW?3;!B~ZS3(kyIXa3jg1jVLfsOKX#f7|;vZaOBne}EaM3x5%S00? zp%ElsaXyta^SM6c(YW=CQ$Xm_cx(RjX^l_lx7UQjhRXMT5r3A1!cwG8#q-j`@@UuH zN%RxHQkr{VU zQ4vt-LK#(6QeCzAE~>yqLydq55f#$2F94%RMKeygRVS~bt~vm$LQQCmZaRHY({7yh ziVCn?6^4?6GKDEW-r}3^Z*I|h86i?KoUwvmG`=C45~95F*&Na7Jk$Af3`yIVC-jR|;_q04Tw8 z(uOh+P}Wj~lVr4ZBs>KgwlT-6IhHIr8r`T(0K#ggJ+O&70W4!I_~T6ghmzISSZkg2 zHV7MSa(~(xXPtB2jUt!4_QqT9y!XLJpMnl1*x-T>A;gd(MU5J0ql-R<7-LE#5)38i zN*JHelPT+Lvdu309CFO5fIh_(TU_xalvq-wsw>Jwb=B8UV@*wohDy;)v&}W%LW?bR zaINcZy6vv}9(wHQL~Wt^asLHsYN19GsWHxu+qny}*84x3*fVdwBfY3BB zlR+6n1G#~jjD)1H1SjplMpQKr1B9k2vR$3nUC8|rZo-B?!i|21oEXskAIJ$n_lesJ zYIW>$Wg^B|IASU_vad-Oz@w0gL6!1}@RbUX8jT=zwL=bZsIr;anJPjYsxnqtlD6@j zAb(qKLCmow>5>wUHKlZG=a`JN(o1zVw6w`N@t7Bg)rk7J*u$=os+8%0 zDZtFlIdOdRY;!F|{6@ZuJ&NhjuP@(@cei3&#J;*u-@f|@9`$L(Ijex@jAIGD#&ce? z?1%TUqt?v!IILvLgQW+cR*Ac{COywe(tj5dt7ZYbUtpe~qIOJYB6(BIR74bZ7&ep= z`(lD>C9(mf`XIMr-&?>wMm{(8$ToNl%D#vEWSX)`MoSLH%yYw}TM^ujY z1#MY=Imx~uv6UVxmc+eE8XC-&$KvfFz6w?N{M&?@fD@wn76GC;fekPT^y+IWlVCy zCNf(UxbxzSRFSM)bR&DXmy{&U2PUi3fF1IR%6MOGg zg|A7iuY8ToS8R=i{jJUy7cb}peO<~{6t7aJJ~Fn>T>F->o1)6Og39z-sIiE{M;r2XPk}nntx<_79MIO za;={Ek5dnK8xt?%sk3i5B6UjKwt5_7=ZLV1ia=GllIB|F8!&qzz0|DP0@HCWVZWpC z(JqF?7>=c0o6_3}VkNd%nf*g)J&p*-#v0j)M!Hq`v1be7_~(p?8AX8C(d0h5t%bC# z8;*!qaoBQGY~Ea@;g-p*uYbtVIEAsm=vEN>%?XjObw6w27p6Y<_SVHMwf~~XK850& z*+%uKXUQAR5>K#bzR6DY;&#ZmIQY)dw;GFu zrflZEhC_eA9~90LY_BJ2w;lN{A;X^Kg42B4*RR=E71+c$x<~OJM}KyTV>}c>W&i*I zglR)VP)S2WAaHVTW@&6?004NLeUUv#!$2IxUsH=B6$LwpI%KF$7DPoHwF*V35Nd^1 z9ZW9$f+h_~ii@M*T5#}VvFhOBtgC~oAP9bdI5|2gx=4xtOA0MwJUH&hyL*qjcYshY zGtKH42Q=L_Q;E2k$$zejov#RC2w}v~Co{{KlcXek$Jadqe7%eDEdO(Vjvh5K8V^%aZ z;wj>&s_B$3WIR?mZ*kVjRo1*Ge_=SMuPk$&<}eai#1bTkP=8QG31!&SR|z^P7E-hy z_wf(9eu-QPxk_NGn4P0EeG-VIC+yMrj4B3=jDM(Yu=YjV#`lc+4p A4gdfE