From ea38185d96798ad10c532103f0c7fc9add872c04 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Sat, 10 Jun 2017 20:26:53 +0200 Subject: [PATCH] resizing bugfix, area protection added --- depends.txt | 1 + init.lua | 170 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 131 insertions(+), 40 deletions(-) diff --git a/depends.txt b/depends.txt index 4ad96d5..0c9f73e 100644 --- a/depends.txt +++ b/depends.txt @@ -1 +1,2 @@ default +areas? \ No newline at end of file diff --git a/init.lua b/init.lua index 4624bed..92a728e 100644 --- a/init.lua +++ b/init.lua @@ -3,8 +3,8 @@ Tower Crane Mod =============== - v0.04 by JoSt - + v0.05 by JoSt + Copyright (C) 2017 Joachim Stolberg LGPLv2.1+ See LICENSE.txt for more information @@ -14,7 +14,8 @@ 2017-06-06 v0.02 Hook bugfix 2017-06-07 v0.03 fixed 2 bugs, added config.lua and sound 2017-06-08 v0.04 recipe and rope length now configurable - + 2017-06-10 v0.05 resizing bugfix, area protection added + ]]-- @@ -26,9 +27,9 @@ dofile(minetest.get_modpath("towercrane") .. "/config.lua") --## Tower Crane Hook --################################################################################################## local hook = { - physical = true, + physical = true, collisionbox = {-0.2, -0.2, -0.2, 0.2, 0.2, 0.2}, - collide_with_objects = false, + collide_with_objects = false, visual = "cube", visual_size = {x=0.6, y=0.6}, textures = { @@ -47,6 +48,7 @@ local hook = { speed_up=0, sound=nil, } + ---------------------------------------------------------------------------------------------------- -- Enter/leave the Hook ---------------------------------------------------------------------------------------------------- @@ -94,7 +96,7 @@ function hook:on_step(dtime) elseif self.speed_forward < 0 then self.speed_forward = self.speed_forward + velocity end - + if ctrl.right then -- right self.speed_right = math.min(self.speed_right + velocity, max_speed) elseif ctrl.left then -- left @@ -127,6 +129,7 @@ function hook:on_step(dtime) if pos.z < self.pos1.z then vz= velocity end if pos.z > self.pos2.z then vz= -velocity end + -- sound control if vx ~= 0 or vz ~= 0 or self.speed_up ~= 0 then if self.sound == nil then self.sound = minetest.sound_play({name="crane"},{object=self.object, @@ -137,7 +140,7 @@ function hook:on_step(dtime) minetest.sound_stop(self.sound) self.sound = nil end - + self.object:setvelocity({x=vx, y=self.speed_up,z=vz}) else self.object:setvelocity({x=0, y=0,z=0}) @@ -175,7 +178,7 @@ local function check_space(pos, dir, height, width) return false end end - + pos.x = pos.x + dir.x*2 pos.z = pos.z + dir.z*2 for i = 1,width+3 do @@ -204,7 +207,7 @@ local function construct_crane(pos, dir, height, width, owner) pos.y = pos.y + 1 minetest.env:add_node(pos, {name="towercrane:mast"}) end - + pos.y = pos.y - 2 pos.x = pos.x - dir.x pos.z = pos.z - dir.z @@ -217,7 +220,7 @@ local function construct_crane(pos, dir, height, width, owner) minetest.env:add_node(pos, {name="towercrane:balance"}) pos.x = pos.x + 3 * dir.x pos.z = pos.z + 3 * dir.z - + for i = 1,width do pos.x = pos.x + dir.x pos.z = pos.z + dir.z @@ -232,10 +235,10 @@ end ---------------------------------------------------------------------------------------------------- -- Remove the crane ---------------------------------------------------------------------------------------------------- -local function dig_crane(pos, dir, height, width) +local function remove_crane(pos, dir, height, width) pos.y = pos.y + 1 minetest.env:remove_node(pos, {name="towercrane:mast_ctrl_off"}) - + for i = 1,height+1 do pos.y = pos.y + 1 minetest.env:remove_node(pos, {name="towercrane:mast"}) @@ -253,7 +256,7 @@ local function dig_crane(pos, dir, height, width) minetest.env:remove_node(pos, {name="towercrane:balance"}) pos.x = pos.x + 3 * dir.x pos.z = pos.z + 3 * dir.z - + for i = 1,width do pos.x = pos.x + dir.x pos.z = pos.z + dir.z @@ -275,6 +278,81 @@ local function place_hook(pos, dir) return minetest.add_entity(pos, "towercrane:hook") end + +---------------------------------------------------------------------------------------------------- +-- Check if the given construction area is not already protected +---------------------------------------------------------------------------------------------------- +local function check_area(pos1, pos2, owner) + if not areas then return true end + for id, a in ipairs(areas:getAreasIntersectingArea(pos1, pos2)) do + print(dump(a.owner)) + if a.owner ~= owner then + return false + end + end + return true +end + +---------------------------------------------------------------------------------------------------- +-- Calculate and set the protection area (pos1, pos2) +---------------------------------------------------------------------------------------------------- +local function protect_area(pos, dir, height, width, owner) + if not areas then return 0 end + -- pos1 = close/right/below + dir = turnright(dir) + dir = turnright(dir) + local pos1 = vector.add(pos, vector.multiply(dir, 2)) + dir = turnleft(dir) + pos1 = vector.add(pos1, vector.multiply(dir, width/2)) + dir = turnleft(dir) + pos1.y = pos.y - 2 + + -- pos2 = far/left/above + local pos2 = vector.add(pos1, vector.multiply(dir, width+2)) + dir = turnleft(dir) + pos2 = vector.add(pos2, vector.multiply(dir, width)) + pos2.y = pos.y + 2 + height + + -- add area + local canAdd, errMsg = areas:canPlayerAddArea(pos1, pos2, owner) + if canAdd then + local id = areas:add(owner, owner .. "'s construction site", pos1, pos2, nil) + areas:save() + return id + end + return nil +end + +---------------------------------------------------------------------------------------------------- +-- Remove the protection area +---------------------------------------------------------------------------------------------------- +local function remove_area(id, owner) + if not areas then return end + if areas:isAreaOwner(id, owner) then + areas:remove(id) + areas:save() + end +end + +---------------------------------------------------------------------------------------------------- +-- Check user input (height, width) +---------------------------------------------------------------------------------------------------- +local function check_input(fields) + local size = string.split(fields.size, ",") + if #size == 2 then + local height = tonumber(size[1]) + local width = tonumber(size[2]) + if height ~= nil and width ~= nil then + height = math.max(height, 8) + height = math.min(height, towercrane.max_height) + width = math.max(width, 8) + width = math.min(width, towercrane.max_width) + return height, width + end + end + return 0, 0 +end + ---------------------------------------------------------------------------------------------------- -- Register Crane base ---------------------------------------------------------------------------------------------------- @@ -317,40 +395,42 @@ minetest.register_node("towercrane:base", { return end local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + local dir = minetest.string_to_pos(meta:get_string("dir")) + local height = meta:get_int("height") + local width = meta:get_int("width") + local id = meta:get_int("id") if not player or not player:is_player() then return end - local owner = meta:get_string("owner") if player:get_player_name() ~= owner then return end - - local dir = minetest.string_to_pos(meta:get_string("dir")) - local height = meta:get_int("height") - local width = meta:get_int("width") + -- destroy area and crane if dir ~= nil and height ~= nil and width ~= nil then - dig_crane(pos, dir, height, width) + remove_area(id, owner) + remove_crane(table.copy(pos), dir, height, width) end - --check for correct size format - size = string.split(fields.size, ",") - if #size == 2 then - local height = tonumber(size[1]) - local width = tonumber(size[2]) - if height ~= nil and width ~= nil then - height = math.max(height, 8) - height = math.min(height, towercrane.max_height) - width = math.max(width, 8) - width = math.min(width, towercrane.max_width) - meta:set_int("height", height) - meta:set_int("width", width) - meta:set_string("infotext", "Crane size: " .. height .. "," .. width) - if dir ~= nil then - if check_space(table.copy(pos), dir, height, width) then - construct_crane(table.copy(pos), dir, height, width, owner) + + -- evaluate user input + height, width = check_input(fields) + if height ~= 0 then + meta:set_int("height", height) + meta:set_int("width", width) + meta:set_string("infotext", "Crane size: " .. height .. "," .. width) + if dir ~= nil then + if check_space(table.copy(pos), dir, height, width) then + -- add protection area + local id = protect_area(table.copy(pos), table.copy(dir), height, width, owner) + if id ~= nil then + meta:set_int("id", id) + construct_crane(table.copy(pos), table.copy(dir), height, width, owner) else - minetest.chat_send_player(owner, "Too less space to raise up the tower crane!") + minetest.chat_send_player(owner, "Construction area is already protected!") end + else + minetest.chat_send_player(owner, "Too less space to raise up the tower crane!") end end end @@ -362,13 +442,19 @@ minetest.register_node("towercrane:base", { local dir = minetest.string_to_pos(meta:get_string("dir")) local height = meta:get_int("height") local width = meta:get_int("width") + local id = meta:get_int("id") + local owner = meta:get_string("owner") + -- remove protection area + if id ~= nil then + remove_area(id, owner) + end -- remove crane if dir ~= nil and height ~= nil and width ~= nil then - dig_crane(pos, dir, height, width) + remove_crane(pos, dir, height, width) end -- remove hook - local id = minetest.hash_node_position(pos) + id = minetest.hash_node_position(pos) if towercrane.id then towercrane.id:remove() towercrane.id = nil @@ -427,6 +513,7 @@ minetest.register_node("towercrane:mast_ctrl_on", { "towercrane_mast_ctrl.png", "towercrane_mast_ctrl.png", }, + -- switch the crane OFF on_rightclick = function (pos, node, clicker) local meta = minetest.get_meta(pos) if not clicker or not clicker:is_player() then @@ -475,8 +562,9 @@ minetest.register_node("towercrane:mast_ctrl_off", { "towercrane_mast_ctrl.png", "towercrane_mast_ctrl.png", }, + -- switch the crane ON on_rightclick = function (pos, node, clicker) - -- switch switch on, calculate the construction area, and place the hook + -- calculate the construction area, and place the hook local meta = minetest.get_meta(pos) -- only the owner is allowed to switch if not clicker or not clicker:is_player() then @@ -494,7 +582,9 @@ minetest.register_node("towercrane:mast_ctrl_off", { local id = minetest.hash_node_position(pos) towercrane.id = place_hook(table.copy(pos), dir) - -- calculate the construction area dimension (pos, pos2) + -- + -- calculate the construction area dimension (pos1, pos2) + -- local height = meta:get_int("height") local width = meta:get_int("width")