From 47d067d9ecda3318b246d4935a5200f9ea791714 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 8 May 2018 00:38:00 +0200 Subject: [PATCH 1/6] Make arrow stuck when they hit solid node (WIP) --- mods/ITEMS/mcl_bows/arrow.lua | 47 ++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index 0eda868950..27de706823 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -1,3 +1,6 @@ +-- Time in seconds after which a stuck arrow is deleted +local ARROW_TIMEOUT = 60 + local mod_mcl_hunger = minetest.get_modpath("mcl_hunger") local mod_awards = minetest.get_modpath("awards") and minetest.get_modpath("mcl_achievements") @@ -43,6 +46,7 @@ minetest.register_node("mcl_bows:arrow_box", { groups = {not_in_creative_inventory=1}, }) +-- FIXME: Restore arrow state properly on re-loading local THROWING_ARROW_ENTITY={ physical = false, visual = "wielditem", @@ -53,6 +57,8 @@ local THROWING_ARROW_ENTITY={ _lastpos={}, _startpos=nil, _damage=1, -- Damage on impact + _stuck=false, -- Whether arrow is stuck + _stucktimer=nil,-- Amount of time (in seconds) the arrow has been stuck so far _shooter=nil, -- ObjectRef of player or mob who shot it } @@ -60,8 +66,36 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime) local pos = self.object:getpos() local node = minetest.get_node(pos) + if self._stuck then + self._stucktimer = self._stucktimer + dtime + if self._stucktimer > ARROW_TIMEOUT then + self.object:remove() + return + end + local objects = minetest.get_objects_inside_radius(pos, 2) + for _,obj in ipairs(objects) do + if obj:is_player() then + if not minetest.settings:get_bool("creative_mode") then + -- Pickup arrow if player is nearby + if obj:get_inventory():room_for_item("main", "mcl_bows:arrow") then + obj:get_inventory():add_item("main", "mcl_bows:arrow") + minetest.sound_play("item_drop_pickup", { + pos = pos, + max_hear_distance = 16, + gain = 1.0, + }) + self.object:remove() + return + end + else + self.object:remove() + return + end + end + end + -- Check for object collision. Done every tick (hopefully this is not too stressing) - do + else local objs = minetest.get_objects_inside_radius(pos, 2) local closest_object local closest_distance @@ -128,13 +162,14 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime) end -- Check for node collision - if self._lastpos.x~=nil then + if self._lastpos.x~=nil and not self._stuck then local def = minetest.registered_nodes[node.name] if (def and def.walkable) or not def then - if not minetest.settings:get_bool("creative_mode") then - minetest.add_item(self._lastpos, 'mcl_bows:arrow') - end - self.object:remove() + -- Arrow is stuck and no longer moves + self._stuck = true + self._stucktimer = 0 + self.object:set_velocity({x=0, y=0, z=0}) + self.object:set_acceleration({x=0, y=0, z=0}) elseif (def and def.liquidtype ~= "none") then -- Slow down arrow in liquids local v = def.liquid_viscosity From af0025debc7d753e7bc62f0af7b6f90bdbf267f7 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 8 May 2018 13:46:39 +0200 Subject: [PATCH 2/6] Wooden buttons stay pushed by arrow --- mods/ITEMS/REDSTONE/mesecons_button/init.lua | 27 ++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_button/init.lua b/mods/ITEMS/REDSTONE/mesecons_button/init.lua index 20d329bf7b..362d8c7c73 100644 --- a/mods/ITEMS/REDSTONE/mesecons_button/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_button/init.lua @@ -66,7 +66,7 @@ end local buttonuse = "Rightclick the button to push it." -mesecon.register_button = function(basename, description, texture, recipeitem, sounds, plusgroups, button_timer, longdesc) +mesecon.register_button = function(basename, description, texture, recipeitem, sounds, plusgroups, button_timer, push_by_arrow, longdesc) local groups_off = table.copy(plusgroups) groups_off.attached_node=1 groups_off.dig_by_water=1 @@ -78,6 +78,11 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s groups_on.not_in_creative_inventory=1 groups_on.button=2 -- button (on) + if push_by_arrow then + groups_off.button_push_by_arrow = 1 + groups_on.button_push_by_arrow = 1 + end + minetest.register_node("mesecons_button:button_"..basename.."_off", { drawtype = "nodebox", tiles = {texture}, @@ -137,6 +142,22 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s on_timer = function(pos, elapsed) local node = minetest.get_node(pos) if node.name=="mesecons_button:button_"..basename.."_on" then --has not been dug + -- Is button pushable by arrow? + if push_by_arrow then + -- If there's an arrow stuck in the button, keep it pressed and check + -- it again later. + local objs = minetest.get_objects_inside_radius(pos, 1) + for o=1, #objs do + local entity = objs[o]:get_luaentity() + if entity and entity.name == "mcl_bows:arrow_entity" then + local timer = minetest.get_node_timer(pos) + timer:start(button_timer) + return + end + end + end + + -- Normal operation: Un-press the button minetest.set_node(pos, {name="mesecons_button:button_"..basename.."_off",param2=node.param2}) minetest.sound_play("mesecons_button_pop", {pos=pos}) mesecon.receptor_off(pos, button_get_output_rules(node)) @@ -160,6 +181,7 @@ mesecon.register_button( mcl_sounds.node_sound_stone_defaults(), {material_stone=1,handy=1,pickaxey=1}, 1, + false, "A stone button is a redstone component made out of stone which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1 second. It can only be placed on solid opaque full cubes (like cobblestone).") local woods = { @@ -180,7 +202,8 @@ for w=1, #woods do mcl_sounds.node_sound_wood_defaults(), {material_wood=1,handy=1,axey=1}, 1.5, - "A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. It can only be placed on solid opaque full cubes (like cobblestone).") + true, + "A wooden button is a redstone component made out of wood which can be pushed to provide redstone power. When pushed, it powers adjacent redstone components for 1.5 seconds. It can only be placed on solid opaque full cubes (like cobblestone). Wooden buttons may also be pushed by arrows.") minetest.register_craft({ type = "fuel", From 4339c80fd8ba0687d07397b1b071404ddfc4c105 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 8 May 2018 14:35:15 +0200 Subject: [PATCH 3/6] Make arrows stick in solid nodes propery, trigger wooden buttons --- mods/ITEMS/mcl_bows/arrow.lua | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index 27de706823..d5534d4f99 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -47,12 +47,15 @@ minetest.register_node("mcl_bows:arrow_box", { }) -- FIXME: Restore arrow state properly on re-loading -local THROWING_ARROW_ENTITY={ - physical = false, +-- FIXME: Arrow velocity is a bit strange. If the arrow flies VERY long, the acceleration can cause the velocity to become negative +-- and the arrow flies backwards. +local ARROW_ENTITY={ + physical = true, visual = "wielditem", visual_size = {x=0.4, y=0.4}, textures = {"mcl_bows:arrow_box"}, - collisionbox = {0,0,0,0,0,0}, + collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1}, + collide_with_objects = false, _lastpos={}, _startpos=nil, @@ -62,7 +65,7 @@ local THROWING_ARROW_ENTITY={ _shooter=nil, -- ObjectRef of player or mob who shot it } -THROWING_ARROW_ENTITY.on_step = function(self, dtime) +ARROW_ENTITY.on_step = function(self, dtime) local pos = self.object:getpos() local node = minetest.get_node(pos) @@ -157,19 +160,27 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime) end end self.object:remove() + return end end end -- Check for node collision + -- FIXME: Also collides with ignore if self._lastpos.x~=nil and not self._stuck then local def = minetest.registered_nodes[node.name] - if (def and def.walkable) or not def then + local vel = self.object:get_velocity() + -- Arrow has stopped + if (math.abs(vel.x) < 0.0001) or (math.abs(vel.z) < 0.0001) or (math.abs(vel.y) < 0.00001) then -- Arrow is stuck and no longer moves self._stuck = true self._stucktimer = 0 self.object:set_velocity({x=0, y=0, z=0}) self.object:set_acceleration({x=0, y=0, z=0}) + -- Push the button + if minetest.get_item_group(node.name, "button") > 0 and minetest.get_item_group(node.name, "button_push_by_arrow") == 1 and def.on_rightclick then + def.on_rightclick(pos, node) + end elseif (def and def.liquidtype ~= "none") then -- Slow down arrow in liquids local v = def.liquid_viscosity @@ -177,7 +188,6 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime) v = 0 end local vpenalty = math.max(0.1, 0.98 - 0.1 * v) - local vel = self.object:get_velocity() if math.abs(vel.x) > 0.001 then vel.x = vel.x * vpenalty end @@ -192,7 +202,7 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime) self._lastpos={x=pos.x, y=pos.y, z=pos.z} end -minetest.register_entity("mcl_bows:arrow_entity", THROWING_ARROW_ENTITY) +minetest.register_entity("mcl_bows:arrow_entity", ARROW_ENTITY) if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then minetest.register_craft({ From f392e23719827178878e852403d99ae997d6018f Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 8 May 2018 17:16:11 +0200 Subject: [PATCH 4/6] Implement staticdata for arrow entities --- mods/ITEMS/mcl_bows/arrow.lua | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index d5534d4f99..019cdb4abc 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -46,7 +46,6 @@ minetest.register_node("mcl_bows:arrow_box", { groups = {not_in_creative_inventory=1}, }) --- FIXME: Restore arrow state properly on re-loading -- FIXME: Arrow velocity is a bit strange. If the arrow flies VERY long, the acceleration can cause the velocity to become negative -- and the arrow flies backwards. local ARROW_ENTITY={ @@ -202,6 +201,37 @@ ARROW_ENTITY.on_step = function(self, dtime) self._lastpos={x=pos.x, y=pos.y, z=pos.z} end +ARROW_ENTITY.get_staticdata = function(self) + local out = { + lastpos = self._lastpos, + startpos = self._startpos, + damage = self._damage, + stuck = self._stuck, + stucktimer = self._stucktimer, + } + if self._shooter and self._shooter:is_player() then + out.shootername = self._shooter:get_player_name() + end + return minetest.serialize(out) +end + +ARROW_ENTITY.on_activate = function(self, staticdata, dtime_s) + local data = minetest.deserialize(staticdata) + if data then + self._lastpos = data.lastpos + self._startpos = data.startpos + self._damage = data.damage + self._stuck = data.stuck + self._stucktimer = data.stucktimer + if data.shootername then + local shooter = minetest.get_player_by_name(data.shootername) + if shooter and shooter:is_player() then + self._shooter = shooter + end + end + end +end + minetest.register_entity("mcl_bows:arrow_entity", ARROW_ENTITY) if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then From c43b8baff435bf58581aa2ce3b250033de6905bc Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 8 May 2018 18:22:08 +0200 Subject: [PATCH 5/6] =?UTF-8?q?Refactor=20arrow=E2=86=92button=20hit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mods/ITEMS/REDSTONE/mesecons_button/init.lua | 26 ++++++++++++++++---- mods/ITEMS/mcl_bows/arrow.lua | 4 +-- mods/ITEMS/mcl_bows/depends.txt | 1 + 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_button/init.lua b/mods/ITEMS/REDSTONE/mesecons_button/init.lua index 362d8c7c73..3e34670e0b 100644 --- a/mods/ITEMS/REDSTONE/mesecons_button/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_button/init.lua @@ -17,6 +17,20 @@ local boxes_on = { wall_top = { -4/16, 7/16, -2/16, 4/16, 8/16, 2/16 }, } +-- Push the button +mesecon.push_button = function(pos, node) + -- No-op if button is already pushed + if mesecon.is_receptor_on(node) then + return + end + local def = minetest.registered_nodes[node.name] + minetest.set_node(pos, {name="mesecons_button:button_"..def._mcl_button_basename.."_on", param2=node.param2}) + mesecon.receptor_on(pos, button_get_output_rules(node)) + minetest.sound_play("mesecons_button_push", {pos=pos}) + local timer = minetest.get_node_timer(pos) + timer:start(def._mcl_button_timer) +end + local on_button_place = function(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" then -- no interaction possible with entities @@ -103,17 +117,16 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s on_place = on_button_place, node_placement_prediction = "", on_rightclick = function (pos, node) - minetest.set_node(pos, {name="mesecons_button:button_"..basename.."_on", param2=node.param2}) - mesecon.receptor_on(pos, button_get_output_rules(node)) - minetest.sound_play("mesecons_button_push", {pos=pos}) - local timer = minetest.get_node_timer(pos) - timer:start(button_timer) + mesecon.push_button(pos, node) end, sounds = sounds, mesecons = {receptor = { state = mesecon.state.off, rules = button_get_output_rules, }}, + _mcl_button_basename = basename, + _mcl_button_timer = button_timer, + _mcl_blast_resistance = 2.5, _mcl_hardness = 0.5, }) @@ -139,6 +152,8 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s state = mesecon.state.on, rules = button_get_output_rules }}, + _mcl_button_basename = basename, + _mcl_button_timer = button_timer, on_timer = function(pos, elapsed) local node = minetest.get_node(pos) if node.name=="mesecons_button:button_"..basename.."_on" then --has not been dug @@ -163,6 +178,7 @@ mesecon.register_button = function(basename, description, texture, recipeitem, s mesecon.receptor_off(pos, button_get_output_rules(node)) end end, + _mcl_blast_resistance = 2.5, _mcl_hardness = 0.5, }) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index 019cdb4abc..8d05afface 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -177,8 +177,8 @@ ARROW_ENTITY.on_step = function(self, dtime) self.object:set_velocity({x=0, y=0, z=0}) self.object:set_acceleration({x=0, y=0, z=0}) -- Push the button - if minetest.get_item_group(node.name, "button") > 0 and minetest.get_item_group(node.name, "button_push_by_arrow") == 1 and def.on_rightclick then - def.on_rightclick(pos, node) + if minetest.get_modpath("mesecons_button") and minetest.get_item_group(node.name, "button") > 0 and minetest.get_item_group(node.name, "button_push_by_arrow") == 1 then + mesecon.push_button(pos, node) end elseif (def and def.liquidtype ~= "none") then -- Slow down arrow in liquids diff --git a/mods/ITEMS/mcl_bows/depends.txt b/mods/ITEMS/mcl_bows/depends.txt index 98f2eaa73d..eb7f075a1c 100644 --- a/mods/ITEMS/mcl_bows/depends.txt +++ b/mods/ITEMS/mcl_bows/depends.txt @@ -6,3 +6,4 @@ mcl_core? mcl_mobitems? mcl_playerphysics? doc? +mesecons_button? From 19dd11dfb897725b10bc36cf9be21a495fc42b04 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 8 May 2018 18:30:57 +0200 Subject: [PATCH 6/6] Fix mesecons crash caused by arrow --- mods/ITEMS/mcl_bows/arrow.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index 8d05afface..a7e06ae80d 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -66,7 +66,9 @@ local ARROW_ENTITY={ ARROW_ENTITY.on_step = function(self, dtime) local pos = self.object:getpos() - local node = minetest.get_node(pos) + local dpos = table.copy(pos) -- digital pos + dpos = vector.round(dpos) + local node = minetest.get_node(dpos) if self._stuck then self._stucktimer = self._stucktimer + dtime @@ -178,7 +180,7 @@ ARROW_ENTITY.on_step = function(self, dtime) self.object:set_acceleration({x=0, y=0, z=0}) -- Push the button if minetest.get_modpath("mesecons_button") and minetest.get_item_group(node.name, "button") > 0 and minetest.get_item_group(node.name, "button_push_by_arrow") == 1 then - mesecon.push_button(pos, node) + mesecon.push_button(dpos, node) end elseif (def and def.liquidtype ~= "none") then -- Slow down arrow in liquids