Advertisement
Guest User

Untitled

a guest
Mar 25th, 2019
622
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 22.93 KB | None | 0 0
  1. --basic settings
  2. local item_drop_settings                 = {} --settings table
  3. item_drop_settings.age                   = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
  4. item_drop_settings.radius_magnet         = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect!
  5. item_drop_settings.radius_collect        = 0.2 --radius of collection
  6. item_drop_settings.player_collect_height = 1.0 --added to their pos y value
  7. item_drop_settings.collection_safety     = false --do this to prevent items from flying away on laggy servers
  8. item_drop_settings.random_item_velocity  = true --this sets random item velocity if velocity is 0
  9. item_drop_settings.drop_single_item      = false --if true, the drop control drops 1 item instead of the entire stack, and sneak+drop drops the stack
  10. -- drop_single_item is disabled by default because it is annoying to throw away items from the intentory screen
  11.  
  12. item_drop_settings.magnet_time           = 0.75 -- how many seconds an item follows the player before giving up
  13.  
  14. local get_gravity = function()
  15.     return tonumber(minetest.settings:get("movement_gravity")) or 9.81
  16. end
  17.  
  18. local check_pickup_achievements = function(object, player)
  19.     local itemname = ItemStack(object:get_luaentity().itemstring):get_name()
  20.     if minetest.get_item_group(itemname, "tree") ~= 0 then
  21.         awards.unlock(player:get_player_name(), "mcl:mineWood")
  22.     elseif itemname == "mcl_mobitems:blaze_rod" then
  23.         awards.unlock(player:get_player_name(), "mcl:blazeRod")
  24.     elseif itemname == "mcl_mobitems:leather" then
  25.         awards.unlock(player:get_player_name(), "mcl:killCow")
  26.     elseif itemname == "mcl_core:diamond" then
  27.         awards.unlock(player:get_player_name(), "mcl:diamonds")
  28.     end
  29. end
  30.  
  31. local enable_physics = function(object, luaentity, ignore_check)
  32.     if luaentity.physical_state == false or ignore_check == true then
  33.         luaentity.physical_state = true
  34.         object:set_properties({
  35.             physical = true
  36.         })
  37.         object:set_velocity({x=0,y=0,z=0})
  38.         object:set_acceleration({x=0,y=-get_gravity(),z=0})
  39.     end
  40. end
  41.  
  42. local disable_physics = function(object, luaentity, ignore_check, reset_movement)
  43.     if luaentity.physical_state == true or ignore_check == true then
  44.         luaentity.physical_state = false
  45.         object:set_properties({
  46.             physical = false
  47.         })
  48.         if reset_movement ~= false then
  49.             object:set_velocity({x=0,y=0,z=0})
  50.             object:set_acceleration({x=0,y=0,z=0})
  51.         end
  52.     end
  53. end
  54.  
  55. minetest.register_globalstep(function(dtime)
  56.     for _,player in ipairs(minetest.get_connected_players()) do
  57.         if player:get_hp() > 0 or not minetest.settings:get_bool("enable_damage") then
  58.             local pos = player:get_pos()
  59.             local inv = player:get_inventory()
  60.             local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z}
  61.  
  62.             --magnet and collection
  63.             for _,object in ipairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.radius_magnet)) do
  64.                 if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
  65.                     object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
  66.                     local collected = false
  67.                     if object:get_luaentity()._magnet_timer >= 0 and object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
  68.  
  69.                         -- Collection
  70.                         if vector.distance(checkpos, object:get_pos()) <= item_drop_settings.radius_collect and not object:get_luaentity()._removed then
  71.                             -- Ignore if itemstring is not set yet
  72.                             if object:get_luaentity().itemstring ~= "" then
  73.                                 inv:add_item("main", ItemStack(object:get_luaentity().itemstring))
  74.                                 minetest.sound_play("item_drop_pickup", {
  75.                                     pos = pos,
  76.                                     max_hear_distance = 16,
  77.                                     gain = 1.0,
  78.                                 })
  79.                                 check_pickup_achievements(object, player)
  80.  
  81.  
  82.                                 -- Destroy entity
  83.                                 -- This just prevents this section to be run again because object:remove() doesn't remove the item immediately.
  84.                                 object:get_luaentity()._removed = true
  85.                                 object:remove()
  86.                                 collected = true
  87.                             end
  88.  
  89.                         -- Magnet
  90.                         else
  91.                             --move this to the front so players can see animation before collection
  92.                             if not collected then
  93.                                 if object:get_luaentity()._magnet_timer > 1 then
  94.                                     object:get_luaentity()._magnet_timer = -item_drop_settings.magnet_time
  95.                                     object:get_luaentity()._magnet_active = false
  96.                                 elseif object:get_luaentity()._magnet_timer < 0 then
  97.                                     object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
  98.                                 end
  99.                             end
  100.  
  101.                             object:get_luaentity()._magnet_active = true
  102.                             object:get_luaentity()._collector_timer = 0
  103.  
  104.                             -- Move object to player
  105.                             disable_physics(object, object:get_luaentity())
  106.                            
  107.                             object:move_to(checkpos)
  108.  
  109.                             --fix eternally falling items
  110.                             minetest.after(0, function(object)
  111.                                 local lua = object:get_luaentity()
  112.                                 if lua then
  113.                                     object:set_acceleration({x=0, y=0, z=0})
  114.                                 end
  115.                             end, object)
  116.  
  117.  
  118.                             --this is a safety to prevent items flying away on laggy servers
  119.                             if item_drop_settings.collection_safety == true then
  120.                                 if object:get_luaentity().init ~= true then
  121.                                     object:get_luaentity().init = true
  122.                                     minetest.after(1, function(args)
  123.                                         local playername = args[1]
  124.                                         local player = minetest.get_player_by_name(playername)
  125.                                         local object = args[2]
  126.                                         local lua = object:get_luaentity()
  127.                                         if player == nil or not player:is_player() or object == nil or lua == nil or lua.itemstring == nil then
  128.                                             return
  129.                                         end
  130.                                         if inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
  131.                                             inv:add_item("main", ItemStack(object:get_luaentity().itemstring))
  132.                                             if not object:get_luaentity()._removed then
  133.                                                 minetest.sound_play("item_drop_pickup", {
  134.                                                     pos = pos,
  135.                                                     max_hear_distance = 16,
  136.                                                     gain = 1.0,
  137.                                                 })
  138.                                             end
  139.                                             check_pickup_achievements(object, player)
  140.                                             object:get_luaentity()._removed = true
  141.                                             object:remove()
  142.                                         else
  143.                                             enable_physics(object, object:get_luaentity())
  144.                                         end
  145.                                     end, {player:get_player_name(), object})
  146.                                 end
  147.                             end
  148.                         end
  149.                     end
  150.  
  151.                 end
  152.             end
  153.  
  154.         end
  155.     end
  156. end)
  157.  
  158. local minigroups = { "shearsy", "swordy", "shearsy_wool", "swordy_cobweb" }
  159. local basegroups = { "pickaxey", "axey", "shovely" }
  160. local materials = { "wood", "gold", "stone", "iron", "diamond" }
  161.  
  162. -- Checks if the given node would drop its useful drop if dug by a tool
  163. -- with the given tool capabilities. Returns true if it will yield its useful
  164. -- drop, false otherwise.
  165. local check_can_drop = function(node_name, tool_capabilities)
  166.     local handy = minetest.get_item_group(node_name, "handy")
  167.     local dig_immediate = minetest.get_item_group(node_name, "dig_immediate")
  168.     if handy == 1 or dig_immediate == 2 or dig_immediate == 3 then
  169.         return true
  170.     else
  171.         local toolgroupcaps
  172.         if tool_capabilities then
  173.             toolgroupcaps = tool_capabilities.groupcaps
  174.         else
  175.             return false
  176.         end
  177.  
  178.         -- Compare node groups with tool capabilities
  179.         for m=1, #minigroups do
  180.             local minigroup = minigroups[m]
  181.             local g = minetest.get_item_group(node_name, minigroup)
  182.             if g ~= 0 then
  183.                 local plus = minigroup .. "_dig"
  184.                 if toolgroupcaps[plus] then
  185.                     return true
  186.                 end
  187.             end
  188.         end
  189.         for b=1, #basegroups do
  190.             local basegroup = basegroups[b]
  191.             local g = minetest.get_item_group(node_name, basegroup)
  192.             if g ~= 0 then
  193.                 for m=g, #materials do
  194.                     local plus = basegroup .. "_dig_"..materials[m]
  195.                     if toolgroupcaps[plus] then
  196.                         return true
  197.                     end
  198.                 end
  199.             end
  200.         end
  201.  
  202.         return false
  203.     end
  204. end
  205.  
  206. function minetest.handle_node_drops(pos, drops, digger)
  207.     -- NOTE: This function override allows digger to be nil.
  208.     -- This means there is no digger. This is a special case which allows this function to be called
  209.     -- by hand. Creative Mode is intentionally ignored in this case.
  210.  
  211.     local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true)
  212.     if (digger ~= nil and minetest.settings:get_bool("creative_mode")) or doTileDrops == false then
  213.         return
  214.     end
  215.  
  216.     -- Check if node will yield its useful drop by the digger's tool
  217.     local dug_node = minetest.get_node(pos)
  218.     local toolcaps
  219.     if digger ~= nil then
  220.         local tool = digger:get_wielded_item()
  221.         toolcaps = tool:get_tool_capabilities()
  222.  
  223.         if not check_can_drop(dug_node.name, toolcaps) then
  224.             return
  225.         end
  226.     end
  227.  
  228.     --[[ Special node drops when dug by shears by reading _mcl_shears_drop
  229.     from the node definition.
  230.     Definition of _mcl_shears_drop:
  231.     * true: Drop itself when dug by shears
  232.     * table: Drop every itemstring in this table when dub by shears
  233.     ]]
  234.     local nodedef = minetest.registered_nodes[dug_node.name]
  235.     if toolcaps ~= nil and toolcaps.groupcaps and toolcaps.groupcaps.shearsy_dig and nodedef._mcl_shears_drop then
  236.         if nodedef._mcl_shears_drop == true then
  237.             drops = { dug_node.name }
  238.         else
  239.             drops = nodedef._mcl_shears_drop
  240.         end
  241.     end
  242.  
  243.     for _,item in ipairs(drops) do
  244.         local count
  245.         if type(item) == "string" then
  246.             count = ItemStack(item):get_count()
  247.         else
  248.             count = item:get_count()
  249.         end
  250.         local drop_item = ItemStack(item)
  251.         drop_item:set_count(1)
  252.         for i=1,count do
  253.             local obj = core.add_item(pos, drop_item)
  254.             if obj ~= nil then
  255.                 local x = math.random(1, 5)
  256.                 if math.random(1,2) == 1 then
  257.                     x = -x
  258.                 end
  259.                 local z = math.random(1, 5)
  260.                 if math.random(1,2) == 1 then
  261.                     z = -z
  262.                 end
  263.                 obj:set_velocity({x=1/x, y=obj:get_velocity().y, z=1/z})
  264.             end
  265.         end
  266.     end
  267. end
  268.  
  269. -- Drop single items by default
  270. function minetest.item_drop(itemstack, dropper, pos)
  271.     if dropper and dropper:is_player() then
  272.         local v = dropper:get_look_dir()
  273.         local p = {x=pos.x, y=pos.y+1.2, z=pos.z}
  274.         local cs = itemstack:get_count()
  275.         if dropper:get_player_control().sneak then
  276.             cs = 1
  277.         end
  278.         local item = itemstack:take_item(cs)
  279.         local obj = core.add_item(p, item)
  280.         if obj then
  281.             v.x = v.x*4
  282.             v.y = v.y*4 + 2
  283.             v.z = v.z*4
  284.             obj:set_velocity(v)
  285.             -- Force collection delay
  286.             obj:get_luaentity()._insta_collect = false
  287.             return itemstack
  288.         end
  289.     end
  290. end
  291.  
  292. --modify builtin:item
  293.  
  294. local time_to_live = tonumber(minetest.settings:get("item_entity_ttl"))
  295. if not time_to_live then
  296.     time_to_live = 300
  297. end
  298.  
  299. core.register_entity(":__builtin:item", {
  300.     initial_properties = {
  301.         hp_max = 1,
  302.         physical = true,
  303.         collide_with_objects = false,
  304.         collisionbox = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3},
  305.         pointable = false,
  306.         visual = "wielditem",
  307.         visual_size = {x = 0.4, y = 0.4},
  308.         textures = {""},
  309.         spritediv = {x = 1, y = 1},
  310.         initial_sprite_basepos = {x = 0, y = 0},
  311.         is_visible = false,
  312.         infotext = "",
  313.     },
  314.  
  315.     -- Itemstring of dropped item. The empty string is used when the item is not yet initialized yet.
  316.     -- The itemstring MUST be set immediately to a non-empty string after creating the entity.
  317.     -- The hand is NOT permitted as dropped item. ;-)
  318.     -- Item entities will be deleted if they still have an empty itemstring on their first on_step tick.
  319.     itemstring = '',
  320.  
  321.     -- If true, item will fall
  322.     physical_state = true,
  323.  
  324.     -- If item entity is currently flowing in water
  325.     _flowing = false,
  326.  
  327.     -- Number of seconds this item entity has existed so far
  328.     age = 0,
  329.  
  330.     set_item = function(self, itemstring)
  331.         self.itemstring = itemstring
  332.         if self.itemstring == "" then
  333.             -- item not yet known
  334.             return
  335.         end
  336.         local stack = ItemStack(itemstring)
  337.         local count = stack:get_count()
  338.         local max_count = stack:get_stack_max()
  339.         if count > max_count then
  340.             count = max_count
  341.             self.itemstring = stack:get_name().." "..max_count
  342.         end
  343.         local s = 0.2 + 0.1 * (count / max_count)
  344.         local c = s
  345.         local itemtable = stack:to_table()
  346.         local itemname = nil
  347.         local description = ""
  348.         if itemtable then
  349.             itemname = stack:to_table().name
  350.         end
  351.         local item_texture = nil
  352.         local item_type = ""
  353.         if core.registered_items[itemname] then
  354.             item_texture = core.registered_items[itemname].inventory_image
  355.             item_type = core.registered_items[itemname].type
  356.             description = core.registered_items[itemname].description
  357.         end
  358.         local prop = {
  359.             is_visible = true,
  360.             visual = "wielditem",
  361.             textures = {itemname},
  362.             visual_size = {x = s, y = s},
  363.             collisionbox = {-c, -c, -c, c, c, c},
  364.             automatic_rotate = math.pi * 0.5,
  365.             infotext = description,
  366.         }
  367.         self.object:set_properties(prop)
  368.         if item_drop_settings.random_item_velocity == true then
  369.             minetest.after(0, function(self)
  370.                 if not self or not self.object or not self.object:get_luaentity() then
  371.                     return
  372.                 end
  373.                 local vel = self.object:get_velocity()
  374.                 if vel and vel.x == 0 and vel.z == 0 then
  375.                     local x = math.random(1, 5)
  376.                     if math.random(1,2) == 1 then
  377.                         x = -x
  378.                     end
  379.                     local z = math.random(1, 5)
  380.                     if math.random(1,2) == 1 then
  381.                         z = -z
  382.                     end
  383.                     local y = math.random(2,4)
  384.                     self.object:set_velocity({x=1/x, y=y, z=1/z})
  385.                 end
  386.             end, self)
  387.         end
  388.  
  389.     end,
  390.  
  391.     get_staticdata = function(self)
  392.         return core.serialize({
  393.             itemstring = self.itemstring,
  394.             always_collect = self.always_collect,
  395.             age = self.age,
  396.             _insta_collect = self._insta_collect,
  397.             _flowing = self._flowing,
  398.             _removed = self._removed,
  399.         })
  400.     end,
  401.  
  402.     on_activate = function(self, staticdata, dtime_s)
  403.         if string.sub(staticdata, 1, string.len("return")) == "return" then
  404.             local data = core.deserialize(staticdata)
  405.             if data and type(data) == "table" then
  406.                 self.itemstring = data.itemstring
  407.                 self.always_collect = data.always_collect
  408.                 if data.age then
  409.                     self.age = data.age + dtime_s
  410.                 else
  411.                     self.age = dtime_s
  412.                 end
  413.                 --remember collection data
  414.                 -- If true, can collect item without delay
  415.                 self._insta_collect = data._insta_collect
  416.                 self._flowing = data._flowing
  417.                 self._removed = data._removed
  418.             end
  419.         else
  420.             self.itemstring = staticdata
  421.         end
  422.         if self._removed then
  423.             self._removed = true
  424.             self.object:remove()
  425.             return
  426.         end
  427.         if self._insta_collect == nil then
  428.             -- Intentionally default, since delayed collection is rare
  429.             self._insta_collect = true
  430.         end
  431.         if self._flowing == nil then
  432.             self._flowing = false
  433.         end
  434.         self._magnet_timer = 0
  435.         self._magnet_active = false
  436.         -- How long ago the last possible collector was detected. nil = none in this session
  437.         self._collector_timer = nil
  438.         -- Used to apply additional force
  439.         self._force = nil
  440.         self._forcestart = nil
  441.         self._forcetimer = 0
  442.  
  443.         self.object:set_armor_groups({immortal = 1})
  444.         self.object:set_velocity({x = 0, y = 2, z = 0})
  445.         self.object:set_acceleration({x = 0, y = -get_gravity(), z = 0})
  446.         self:set_item(self.itemstring)
  447.     end,
  448.  
  449.     try_merge_with = function(self, own_stack, object, entity)
  450.         if self.age == entity.age or entity._removed then
  451.             -- Can not merge with itself and remove entity
  452.             return false
  453.         end
  454.  
  455.         local stack = ItemStack(entity.itemstring)
  456.         local name = stack:get_name()
  457.         if own_stack:get_name() ~= name or
  458.                 own_stack:get_meta() ~= stack:get_meta() or
  459.                 own_stack:get_wear() ~= stack:get_wear() or
  460.                 own_stack:get_free_space() == 0 then
  461.             -- Can not merge different or full stack
  462.             return false
  463.         end
  464.  
  465.         local count = own_stack:get_count()
  466.         local total_count = stack:get_count() + count
  467.         local max_count = stack:get_stack_max()
  468.  
  469.         if total_count > max_count then
  470.             return false
  471.         end
  472.         -- Merge the remote stack into this one
  473.  
  474.         local pos = object:get_pos()
  475.         pos.y = pos.y + ((total_count - count) / max_count) * 0.15
  476.         self.object:move_to(pos)
  477.  
  478.         self.age = 0 -- Handle as new entity
  479.         own_stack:set_count(total_count)
  480.         self:set_item(own_stack:to_string())
  481.  
  482.         entity._removed = true
  483.         object:remove()
  484.         return true
  485.     end,
  486.  
  487.     on_step = function(self, dtime)
  488.         if self._removed then
  489.             return
  490.         end
  491.         self.age = self.age + dtime
  492.         if self._collector_timer ~= nil then
  493.             self._collector_timer = self._collector_timer + dtime
  494.         end
  495.         if time_to_live > 0 and self.age > time_to_live then
  496.             self._removed = true
  497.             self.object:remove()
  498.             return
  499.         end
  500.         -- Delete corrupted item entities. The itemstring MUST be non-empty on its first step,
  501.         -- otherwise there might have some data corruption.
  502.         if self.itemstring == "" then
  503.             minetest.log("warning", "Item entity with empty itemstring found at "..minetest.pos_to_string(self.object:get_pos()).. "! Deleting it now.")
  504.             self._removed = true
  505.             self.object:remove()
  506.         end
  507.  
  508.         local p = self.object:get_pos()
  509.         local node = core.get_node_or_nil(p)
  510.         local in_unloaded = (node == nil)
  511.  
  512.         -- If no collector was found for a long enough time, declare the magnet as disabled
  513.         if self._magnet_active and (self._collector_timer == nil or (self._collector_timer > item_drop_settings.magnet_time)) then
  514.             self._magnet_active = false
  515.             enable_physics(self.object, self)
  516.             return
  517.         end
  518.         if in_unloaded then
  519.             -- Don't infinetly fall into unloaded map
  520.             disable_physics(self.object, self)
  521.             return
  522.         end
  523.  
  524.         -- Destroy item in lava, fire or special nodes
  525.         local nn = node.name
  526.         local def = minetest.registered_nodes[nn]
  527.         local lg = minetest.get_item_group(nn, "lava")
  528.         local fg = minetest.get_item_group(nn, "fire")
  529.         local dg = minetest.get_item_group(nn, "destroys_items")
  530.         if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then
  531.             if dg ~= 2 then
  532.                 minetest.sound_play("builtin_item_lava", {pos = self.object:get_pos(), gain = 0.5})
  533.             end
  534.             self._removed = true
  535.             self.object:remove()
  536.             return
  537.         end
  538.  
  539.         -- Push item out when stuck inside solid opaque node
  540.         if def and def.walkable and def.groups and def.groups.opaque == 1 then
  541.             local shootdir
  542.             local cx = p.x % 1
  543.             local cz = p.z % 1
  544.             local order = {}
  545.  
  546.             -- First prepare the order in which the 4 sides are to be checked.
  547.             -- 1st: closest
  548.             -- 2nd: other direction
  549.             -- 3rd and 4th: other axis
  550.             local cxcz = function(o, cw, one, zero)
  551.                 if cw > 0 then
  552.                     table.insert(o, { [one]=1, y=0, [zero]=0 })
  553.                     table.insert(o, { [one]=-1, y=0, [zero]=0 })
  554.                 else
  555.                     table.insert(o, { [one]=-1, y=0, [zero]=0 })
  556.                     table.insert(o, { [one]=1, y=0, [zero]=0 })
  557.                 end
  558.                 return o
  559.             end
  560.             if math.abs(cx) > math.abs(cz) then
  561.                 order = cxcz(order, cx, "x", "z")
  562.                 order = cxcz(order, cz, "z", "x")
  563.             else
  564.                 order = cxcz(order, cz, "z", "x")
  565.                 order = cxcz(order, cx, "x", "z")
  566.             end
  567.  
  568.             -- Check which one of the 4 sides is free
  569.             for o=1, #order do
  570.                 local nn = minetest.get_node(vector.add(p, order[o])).name
  571.                 local def = minetest.registered_nodes[nn]
  572.                 if def and def.walkable == false and nn ~= "ignore" then
  573.                     shootdir = order[o]
  574.                     break
  575.                 end
  576.             end
  577.             -- If none of the 4 sides is free, shoot upwards
  578.             if shootdir == nil then
  579.                 shootdir = { x=0, y=1, z=0 }
  580.                 local nn = minetest.get_node(vector.add(p, shootdir)).name
  581.                 if nn == "ignore" then
  582.                     -- Do not push into ignore
  583.                     return
  584.                 end
  585.             end
  586.  
  587.             -- Set new item moving speed accordingly
  588.             local newv = vector.multiply(shootdir, 3)
  589.             self.object:set_acceleration({x = 0, y = 0, z = 0})
  590.             self.object:set_velocity(newv)
  591.  
  592.             disable_physics(self.object, self, false, false)
  593.  
  594.             if shootdir.y == 0 then
  595.                 self._force = newv
  596.                 p.x = math.floor(p.x)
  597.                 p.y = math.floor(p.y)
  598.                 p.z = math.floor(p.z)
  599.                 self._forcestart = p
  600.                 self._forcetimer = 1
  601.             end
  602.             return
  603.         end
  604.  
  605.         -- This code is run after the entity got a push from above “push away” code.
  606.         -- It is responsible for making sure the entity is entirely outside the solid node
  607.         -- (with its full collision box), not just its center.
  608.         if self._forcetimer > 0 then
  609.             local cbox = self.object:get_properties().collisionbox
  610.             local ok = false
  611.             if self._force.x > 0 and (p.x > (self._forcestart.x + 0.5 + (cbox[4] - cbox[1])/2)) then ok = true
  612.             elseif self._force.x < 0 and (p.x < (self._forcestart.x + 0.5 - (cbox[4] - cbox[1])/2)) then ok = true
  613.             elseif self._force.z > 0 and (p.z > (self._forcestart.z + 0.5 + (cbox[6] - cbox[3])/2)) then ok = true
  614.             elseif self._force.z < 0 and (p.z < (self._forcestart.z + 0.5 - (cbox[6] - cbox[3])/2)) then ok = true end
  615.             -- Item was successfully forced out. No more pushing
  616.             if ok then
  617.                 self._forcetimer = -1
  618.                 self._force = nil
  619.                 enable_physics(self.object, self)
  620.             else
  621.                 self._forcetimer = self._forcetimer - dtime
  622.             end
  623.             return
  624.         elseif self._force then
  625.             self._force = nil
  626.             enable_physics(self.object, self)
  627.             return
  628.         end
  629.  
  630.         -- Move item around on flowing liquids
  631.         if def and def.liquidtype == "flowing" then
  632.  
  633.             --[[ Get flowing direction (function call from flowlib), if there's a liquid.
  634.             NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
  635.             Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]]
  636.             local vec = flowlib.quick_flow(p, node)
  637.             -- Just to make sure we don't manipulate the speed for no reason
  638.             if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
  639.                 -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
  640.                 local f = 1.39
  641.                 -- Set new item moving speed into the direciton of the liquid
  642.                 local newv = vector.multiply(vec, f)
  643.                 self.object:set_acceleration({x = 0, y = 0, z = 0})
  644.                 self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z})
  645.  
  646.                 self.physical_state = true
  647.                 self._flowing = true
  648.                 self.object:set_properties({
  649.                     physical = true
  650.                 })
  651.                 return
  652.             end
  653.         elseif self._flowing == true then
  654.             -- Disable flowing physics if not on/in flowing liquid
  655.             self._flowing = false
  656.             enable_physics(self.object, self, true)
  657.             return
  658.         end
  659.  
  660.         -- If node is not registered or node is walkably solid and resting on nodebox
  661.         local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
  662.         local v = self.object:get_velocity()
  663.  
  664.         if not core.registered_nodes[nn] or core.registered_nodes[nn].walkable and v.y == 0 then
  665.             if self.physical_state then
  666.                 local own_stack = ItemStack(self.object:get_luaentity().itemstring)
  667.                 -- Merge with close entities of the same item
  668.                 for _, object in ipairs(core.get_objects_inside_radius(p, 0.8)) do
  669.                     local obj = object:get_luaentity()
  670.                     if obj and obj.name == "__builtin:item"
  671.                             and obj.physical_state == false then
  672.                         if self:try_merge_with(own_stack, object, obj) then
  673.                             return
  674.                         end
  675.                     end
  676.                 end
  677.                 disable_physics(self.object, self)
  678.             end
  679.         else
  680.             if self._magnet_active == false then
  681.                 enable_physics(self.object, self)
  682.             end
  683.         end
  684.     end,
  685.  
  686.     -- Note: on_punch intentionally left out. The player should *not* be able to collect items by punching
  687. })
  688.  
  689. if minetest.settings:get_bool("log_mods") then
  690.     minetest.log("action", "mcl_item_entity loaded")
  691. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement