diff --git a/api.lua b/api.lua index e8b9c7a..12cfe22 100644 --- a/api.lua +++ b/api.lua @@ -1,4 +1,11 @@ +--plants to place in openfarming +local plants = { ["farming:blueberries"]="air", ["farming:carrot"]="air", ["farming:coffee_beans"]="air", ["farming:corn"]="air", ["farming:cucumber"]="air", + ["farming:melon_slice"]="air", ["farming:potato"]="air", ["farming:pumpkin_slice"]="air", ["farming:raspberries"]="air", ["farming:rhubarb"]="air", + ["farming:tomato"]="air", ["farming:seed_cotton"]="air", ["farming:seed_wheat"]="air",["default:papyrus"]="air", ["farming:trellis"]="air", + ["farming:grapes"]="farming:trellis", ["farming:beanpole"]="air", ["farming:beans"]="farming:beanpole", + } + --- Returns a list of areas that include the provided position. function areas:getAreasAtPos(pos) local res = {} @@ -57,9 +64,30 @@ function areas:canInteract(pos, name) return true end local owned = false + if pos == nil then return not owned end -- pour éviter crash avec nénuphar for _, area in pairs(self:getAreasAtPos(pos)) do if area.owner == name or area.open then return true + elseif area.openfarming then + -- if area is openfarming + local node = minetest.get_node(pos).name + if not minetest.registered_nodes[node] then return false end + local player = minetest.get_player_by_name(name) + if not player then return false end + local wstack = player:get_wielded_item():get_name() + if wstack == "" then wstack = "hand" end + + --on_dig + if minetest.get_item_group(node, "plant") == 1 and (wstack == "hand" or minetest.registered_tools[wstack]) then + return true + end + + --on_place + if plants[wstack] ~= nil and plants[wstack] == node then + return true + end + + owned = true else owned = true end @@ -126,3 +154,73 @@ function areas:canInteractInArea(pos1, pos2, name, allow_open) return true end + + +function areas:canMakeArea(pos1, pos2, name) --MFF crabman(25/02/2016) fix areas in areas + if name and minetest.check_player_privs(name, self.adminPrivs) then + return true + end + areas:sortPos(pos1, pos2) + + local id_areas_intersect = {} + local areas = self:getAreasIntersectingArea(pos1, pos2) + + if not areas then return true end + + for id, area in pairs(areas) do + if area.owner == name and self:isSubarea(pos1, pos2, id) then + return true + end + if not area.open and not self:isAreaOwner(id, name) then + table.insert(id_areas_intersect, id) + end + end + + if #id_areas_intersect > 0 then + return false, id_areas_intersect[1] + end + + return true +end + + +--MFF crabman(5/03/2016 ) return special area pos if a spawn is set. +--1 party (2 party in beds mod) +function areas:getSpawn(pos) + for _, area in pairs(areas:getAreasAtPos(pos)) do + if area.spawn and area.spawn.x then + return area.spawn + end + end + return nil +end + +--MFF DEBUT crabman(17/09/2015 ) respawn player in special area(event) if a spawn is set. +--1 party (2 party in beds mod) +local dead_players = {} +minetest.register_on_dieplayer(function(player) + local player_name = player:get_player_name() + if not player_name then return end + local pos = player:getpos() + if pos then + dead_players[player_name] = pos + end +end) + + +function areas:onRespawn(player) + local player_name = player:get_player_name() + if not player_name or not dead_players[player_name] then return false end + local pos = dead_players[player_name] + dead_players[player_name] = nil + if pos then + for _, area in pairs(areas:getAreasAtPos(pos)) do + if area.spawn then + player:setpos(area.spawn) + return true + end + end + end + return false +end +--FIN diff --git a/chatcommands.lua b/chatcommands.lua index 6079e93..5b56169 100644 --- a/chatcommands.lua +++ b/chatcommands.lua @@ -60,7 +60,7 @@ minetest.register_chatcommand("set_owner", { local id = areas:add(ownerName, areaName, pos1, pos2, nil) areas:save() - + minetest.chat_send_player(ownerName, "You have been granted control over area #".. id..". Type /list_areas to show your areas.") @@ -286,6 +286,28 @@ minetest.register_chatcommand("area_open", { }) +minetest.register_chatcommand("area_openfarming", { + params = "", + description = "Toggle an area open (anyone can interact farming) or closed", + func = function(name, param) + local id = tonumber(param) + if not id then + return false, "Invalid usage, see /help area_openfarming." + end + + if not areas:isAreaOwner(id, name) then + return false, "Area "..id.." does not exist" + .." or is not owned by you." + end + local openfarming = not areas.areas[id].openfarming + -- Save false as nil to avoid inflating the DB. + areas.areas[id].openfarming = openfarming or nil + areas:save() + return true, ("Area %s to farming."):format(openfarming and "opened" or "closed") + end +}) + + minetest.register_chatcommand("move_area", { params = "", description = "Move (or resize) an area to the current positions.", @@ -403,3 +425,63 @@ minetest.register_chatcommand("area_info", { end, }) + +--MFF DEBUT crabman(17/09/2015 ) respawn player at in special area(event) if a spawn is set. +minetest.register_chatcommand("area_addspawn", { + params = "", + privs = areas.adminPrivs, + description = "Define special spawn for area", + func = function(name, param) + local id = param:match("^(%d+)") + if not id then + return false, "Invalid usage, see /help area_addspawn." + end + + id = tonumber(id) + if not id then + return false, "Error, Param id must be int." + end + + local player = minetest.get_player_by_name(name) + if not player then + return false, "Error, there is not player" + end + local pos = player:getpos() + if not pos then + return false, "Error, there is not pos." + end + + if not areas.areas[id] then + return false, "Area ".. id .." does not exist." + end + areas.areas[id].spawn = pos + areas:save() + return true, "spawn of area ".. id .." defined." + end +}) + +minetest.register_chatcommand("area_delspawn", { + params = "", + privs = areas.adminPrivs, + description = "Delete special spawn of area", + func = function(name, param) + local id = param:match("^(%d+)") + if not id then + return false, "Invalid usage, see /help area_delspawn." + end + + id = tonumber(id) + if not id then + return false, "Error, Param id must be int." + end + + if not areas.areas[id] then + return false, "Area ".. id .." does not exist." + end + areas.areas[id].spawn = nil + areas:save() + return true, "spawn of area ".. id .." deleted." + end +}) +-- FIN + diff --git a/hud.lua b/hud.lua index 4908b92..75d3188 100644 --- a/hud.lua +++ b/hud.lua @@ -2,43 +2,82 @@ areas.hud = {} -minetest.register_globalstep(function(dtime) +local function tick() for _, player in pairs(minetest.get_connected_players()) do local name = player:get_player_name() local pos = vector.round(player:getpos()) - local areaStrings = {} + local area_text = "No area(s)\n\n" + local area_owner_name = "" + local mod_owner = 0 + local mod_open = 0 + local mod_farming = 0 + local area_name = "" + local nb_areas = 0 for id, area in pairs(areas:getAreasAtPos(pos)) do - table.insert(areaStrings, ("%s [%u] (%s%s)") - :format(area.name, id, area.owner, - area.open and ":open" or "")) + nb_areas = nb_areas+1 + if areas:isAreaOwner(id, name) then + mod_owner = 1 + end + + if area.open then + mod_open = 1 + end + if area.openfarming then + mod_farming = 1 + end + + if not area.parent then + area_owner_name = area.owner + area_name = area.name + end end - local areaString = "Areas:" - if #areaStrings > 0 then - areaString = areaString.."\n".. - table.concat(areaStrings, "\n") + + local icon = "areas_not_area.png" + if nb_areas > 0 then + local plural = "" + if nb_areas > 1 then + plural = "s" + end + area_text = ("%s\nOwner: %s\n%u area" .. plural):format(area_name, area_owner_name, nb_areas) + icon = ("areas_%u_%u_%u.png"):format(mod_owner, mod_open, mod_farming) end - local hud = areas.hud[name] - if not hud then - hud = {} - areas.hud[name] = hud - hud.areasId = player:hud_add({ + if not areas.hud[name] then + areas.hud[name] = {} + areas.hud[name].icon = player:hud_add({ + hud_elem_type = "image", + position = {x=0,y=1}, + scale = {x=1,y=1}, + offset = {x=26,y=-60}, + text = icon, + }) + + areas.hud[name].areas_id = player:hud_add({ hud_elem_type = "text", name = "Areas", number = 0xFFFFFF, position = {x=0, y=1}, - offset = {x=8, y=-8}, - text = areaString, - scale = {x=200, y=60}, + offset = {x=48, y=-40}, + text = area_text, + scale = {x=1, y=1}, alignment = {x=1, y=-1}, }) - hud.oldAreas = areaString - return - elseif hud.oldAreas ~= areaString then - player:hud_change(hud.areasId, "text", areaString) - hud.oldAreas = areaString + areas.hud[name].old_area_text = area_text + areas.hud[name].old_icon = icon + else + if areas.hud[name].old_area_text ~= area_text then + player:hud_change(areas.hud[name].areas_id, "text", area_text) + areas.hud[name].old_area_text = area_text + end + if areas.hud[name].old_icon ~= icon then + player:hud_change(areas.hud[name].icon, "text", icon) + areas.hud[name].old_icon = icon + end end end -end) + minetest.after(1.5, tick) +end + +tick() minetest.register_on_leaveplayer(function(player) areas.hud[player:get_player_name()] = nil diff --git a/internal.lua b/internal.lua index 05a31cd..45d7f5f 100644 --- a/internal.lua +++ b/internal.lua @@ -1,3 +1,5 @@ +-- Mega_builder privilege +minetest.register_privilege("megabuilder","Can protect an infinite amount of areas.") function areas:player_exists(name) return minetest.auth_table[name] ~= nil @@ -195,33 +197,37 @@ function areas:canPlayerAddArea(pos1, pos2, name) .." the necessary privilege." end - local max_size = privs.areas_high_limit and - self.config.self_protection_max_size_high or - self.config.self_protection_max_size - if - (pos2.x - pos1.x) > max_size.x or - (pos2.y - pos1.y) > max_size.y or - (pos2.z - pos1.z) > max_size.z then - return false, "Area is too big." - end - - -- Check number of areas the user has and make sure it not above the max - local count = 0 - for _, area in pairs(self.areas) do - if area.owner == name then - count = count + 1 + -- MFF: megabuilders skip checks on size and number of areas. + if not privs["megabuilder"] then + -- Check size + local max_size = privs.areas_high_limit and + self.config.self_protection_max_size_high or + self.config.self_protection_max_size + if + (pos2.x - pos1.x) > max_size.x or + (pos2.y - pos1.y) > max_size.y or + (pos2.z - pos1.z) > max_size.z then + return false, "Area is too big." + end + + -- Check number of areas the user has and make sure it not above the max + local count = 0 + for _, area in pairs(self.areas) do + if area.owner == name then + count = count + 1 + end + end + local max_areas = privs.areas_high_limit and + self.config.self_protection_max_areas_high or + self.config.self_protection_max_areas + if count >= max_areas then + return false, "You have reached the maximum amount of" + .." areas that you are allowed to protect." end - end - local max_areas = privs.areas_high_limit and - self.config.self_protection_max_areas_high or - self.config.self_protection_max_areas - if count >= max_areas then - return false, "You have reached the maximum amount of" - .." areas that you are allowed to protect." end -- Check intersecting areas - local can, id = self:canInteractInArea(pos1, pos2, name) + local can, id = self:canMakeArea(pos1, pos2, name) --MFF crabman(25/02/2016) fix areas in areas if not can then local area = self.areas[id] return false, ("The area intersects with %s [%u] (%s).") diff --git a/settings.lua b/settings.lua index 140a655..ecd384f 100644 --- a/settings.lua +++ b/settings.lua @@ -30,10 +30,10 @@ setting("string", "filename", world_path.."/areas.dat") -- Allow players with a privilege create their own areas -- within the maximum size and number. -setting("boolean", "self_protection", false) +setting("boolean", "self_protection", true) setting("string", "self_protection_privilege", "interact") -setting("position", "self_protection_max_size", {x=64, y=128, z=64}) -setting("number", "self_protection_max_areas", 4) +setting("position", "self_protection_max_size", {x=128, y=128, z=128}) +setting("number", "self_protection_max_areas", 30) -- For players with the areas_high_limit privilege. setting("position", "self_protection_max_size_high", {x=512, y=512, z=512}) setting("number", "self_protection_max_areas_high", 32) diff --git a/textures/areas_0_0_0.png b/textures/areas_0_0_0.png new file mode 100644 index 0000000..dbdabc2 Binary files /dev/null and b/textures/areas_0_0_0.png differ diff --git a/textures/areas_0_0_1.png b/textures/areas_0_0_1.png new file mode 100644 index 0000000..c8f5581 Binary files /dev/null and b/textures/areas_0_0_1.png differ diff --git a/textures/areas_0_1_0.png b/textures/areas_0_1_0.png new file mode 100644 index 0000000..e787507 Binary files /dev/null and b/textures/areas_0_1_0.png differ diff --git a/textures/areas_0_1_1.png b/textures/areas_0_1_1.png new file mode 100644 index 0000000..e787507 Binary files /dev/null and b/textures/areas_0_1_1.png differ diff --git a/textures/areas_1_0_0.png b/textures/areas_1_0_0.png new file mode 100644 index 0000000..6b910ff Binary files /dev/null and b/textures/areas_1_0_0.png differ diff --git a/textures/areas_1_0_1.png b/textures/areas_1_0_1.png new file mode 100644 index 0000000..a5d73e2 Binary files /dev/null and b/textures/areas_1_0_1.png differ diff --git a/textures/areas_1_1_0.png b/textures/areas_1_1_0.png new file mode 100644 index 0000000..9f98416 Binary files /dev/null and b/textures/areas_1_1_0.png differ diff --git a/textures/areas_1_1_1.png b/textures/areas_1_1_1.png new file mode 100644 index 0000000..44a6dc0 Binary files /dev/null and b/textures/areas_1_1_1.png differ diff --git a/textures/areas_not_area.png b/textures/areas_not_area.png new file mode 100644 index 0000000..1c4c779 Binary files /dev/null and b/textures/areas_not_area.png differ diff --git a/textures/areas_pos1.png b/textures/areas_pos1.png index 4c304aa..cbd4337 100644 Binary files a/textures/areas_pos1.png and b/textures/areas_pos1.png differ diff --git a/textures/areas_pos2.png b/textures/areas_pos2.png index 1502f16..5214780 100644 Binary files a/textures/areas_pos2.png and b/textures/areas_pos2.png differ