From 680e21af426b922ca4e5aee48019f5b4d2cdb106 Mon Sep 17 00:00:00 2001 From: HybridDog Date: Thu, 10 Sep 2015 21:45:08 +0200 Subject: [PATCH] fix wireless pos comparison and update jammer, there might be a possibility to somehow cause a not ending loop --- moremesecons_wireless/init.lua | 125 +++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 38 deletions(-) diff --git a/moremesecons_wireless/init.lua b/moremesecons_wireless/init.lua index adcc481..2ff4f9b 100644 --- a/moremesecons_wireless/init.lua +++ b/moremesecons_wireless/init.lua @@ -3,42 +3,47 @@ local JAMMER_MAX_DISTANCE = 15 local wireless = {} local wireless_rids = {} +-- localize these functions with small names because they work fairly fast +local get = vector.get_data_from_pos +local set = vector.set_data_to_pos +local remove = vector.remove_data_from_pos -local register = function(pos) - local RID = vector.get_data_from_pos(wireless_rids, pos.z,pos.y,pos.x) - if not RID then - table.insert(wireless, pos) - vector.set_data_to_pos(wireless_rids, pos.z,pos.y,pos.x, #wireless) +-- if the wireless at pos isn't stored yet, put it into the tables +local function register_RID(pos) + if get(wireless_rids, pos.z,pos.y,pos.x) then + return + end + local RID = #wireless+1 + wireless[RID] = pos + set(wireless_rids, pos.z,pos.y,pos.x, RID) +end + +local is_jammed +local function wireless_activate(pos) + if is_jammed(pos) then + -- jamming doesn't disallow receiving signals, only sending them + return + end + local channel_first_wireless = minetest.get_meta(pos):get_string("channel") + for i = 1, #wireless do + if not vector.equals(wireless[i], pos) + and minetest.get_meta(wireless[i]):get_string("channel") == channel_first_wireless then + mesecon.receptor_on(wireless[i]) + end end end -local wireless_activate = function(pos) - if not minetest.registered_nodes["moremesecons_wireless:wireless"] then return end - local channel_first_wireless = nil - +local function wireless_deactivate(pos) + if is_jammed(pos) then + return + end + local channel_first_wireless = minetest.get_meta(pos):get_string("channel") for i = 1, #wireless do - meta = minetest.get_meta(pos) - channel_first_wireless = meta:get_string("channel") - meta = minetest.get_meta(wireless[i]) - if wireless[i] ~= pos and meta:get_string("channel") == channel_first_wireless and not minetest.find_node_near(pos, JAMMER_MAX_DISTANCE, {"moremesecons_wireless:jammer_on"}) then - mesecon.receptor_on(wireless[i]) - end - end -end - -local wireless_deactivate = function(pos) - if not minetest.registered_nodes["moremesecons_wireless:wireless"] then return end - local meta = minetest.get_meta(pos) - local channel_first_wireless = nil - - for i = 1, #wireless do - meta = minetest.get_meta(pos) - channel_first_wireless = meta:get_string("channel") - meta = minetest.get_meta(wireless[i]) - if wireless[i] ~= pos and meta:get_string("channel") == channel_first_wireless and not minetest.find_node_near(pos, JAMMER_MAX_DISTANCE, {"moremesecons_wireless:jammer_on"}) then + if not vector.equals(wireless[i], pos) + and minetest.get_meta(wireless[i]):get_string("channel") == channel_first_wireless then mesecon.receptor_off(wireless[i]) end - end + end end minetest.register_node("moremesecons_wireless:wireless", { @@ -56,10 +61,10 @@ minetest.register_node("moremesecons_wireless:wireless", { on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec", "field[channel;channel;${channel}]") - register(pos) + register_RID(pos) end, on_destruct = function(pos) - local RID = vector.get_data_from_pos(wireless_rids, pos.z,pos.y,pos.x) + local RID = get(wireless_rids, pos.z,pos.y,pos.x) if RID then table.remove(wireless, RID) vector.remove_data_from_pos(wireless_rids, pos.z,pos.y,pos.x) @@ -71,6 +76,38 @@ minetest.register_node("moremesecons_wireless:wireless", { end, }) +local jammers = {} +local function add_jammer(pos) + if get(jammers, pos.z,pos.y,pos.x) then + return + end + set(jammers, pos.z,pos.y,pos.x, true) +end + +local function remove_jammer(pos) + remove(jammers, pos.z,pos.y,pos.x) +end + +-- looks big, but should work fast +function is_jammed(pos) + local pz,py,px = vector.unpack(pos) + for z,yxs in pairs(jammers) do + if math.abs(pz-z) <= JAMMER_MAX_DISTANCE then + for y,xs in pairs(yxs) do + if math.abs(py-y) <= JAMMER_MAX_DISTANCE then + for x in pairs(xs) do + if math.abs(px-x) <= JAMMER_MAX_DISTANCE + and (px-x)^2+(py-y)^2+(pz-z)^2 <= JAMMER_MAX_DISTANCE^2 then + return true + end + end + end + end + end + end + return false +end + mesecon.register_node("moremesecons_wireless:jammer", { description="Wireless Jammer", paramtype = "light", @@ -79,16 +116,21 @@ mesecon.register_node("moremesecons_wireless:jammer", { groups = {dig_immediate=2}, mesecons = {effector = { action_on = function(pos) - table.foreach(pos, print) + add_jammer(pos) minetest.swap_node(pos, {name="moremesecons_wireless:jammer_on"}) - end }} + end + }} },{ tiles = {"moremesecons_jammer_on.png"}, groups = {dig_immediate=2, not_in_creative_inventory=1}, mesecons = {effector = { action_off = function(pos) + remove_jammer(pos) minetest.swap_node(pos, {name="moremesecons_wireless:jammer_off"}) - end }} + end + }}, + on_destruct = remove_jammer, + on_construct = add_jammer, }) minetest.register_craft({ @@ -108,8 +150,15 @@ minetest.register_craft({ }) minetest.register_abm({ - nodenames = {"moremesecons_wireless:wireless"}, - interval=1, - chance=1, - action = register + nodenames = {"moremesecons_wireless:jammer_on"}, + interval = 5, + chance = 1, + action = add_jammer +}) + +minetest.register_abm({ + nodenames = {"moremesecons_wireless:wireless"}, + interval = 5, + chance = 1, + action = register_RID })