1 local minetest,math,vector,pairs,ItemStack,ipairs = minetest,math,vector,pairs,ItemStack,ipairs
3 local path = minetest.get_modpath("itemhandling")
4 dofile(path.."/magnet.lua")
7 local creative_mode = minetest.settings:get_bool("creative_mode")
18 if not creative_mode then
19 function minetest.handle_node_drops(pos, drops, digger)
20 meta = digger:get_wielded_item():get_meta()
21 --careful = meta:get_int("careful")
22 fortune = 1--meta:get_int("fortune") + 1
23 autorepair = meta:get_int("autorepair")
25 -- drops = {minetest.get_node(pos).name}
28 for _,item in ipairs(drops) do
30 if type(item) == "string" then
34 count = item:get_count()
35 name = item:get_name()
38 object = minetest.add_item(pos, name)
41 x=math.random(-2,2)*math.random(),
43 z=math.random(-2,2)*math.random()
48 local experience_amount = minetest.get_item_group(minetest.get_node(pos).name,"experience")
49 if experience_amount > 0 then
50 minetest.throw_experience(pos, experience_amount)
53 --auto repair the item
54 if autorepair > 0 and math.random(0,1000) < autorepair then
55 local itemstack = digger:get_wielded_item()
56 itemstack:add_wear(autorepair*-100)
57 digger:set_wielded_item(itemstack)
62 function minetest.handle_node_drops(pos, drops, digger)
64 minetest.register_on_dignode(function(pos, oldnode, digger)
66 --if digger and digger:is_player() then
67 -- local inv = digger:get_inventory()
68 -- if inv and not inv:contains_item("main", oldnode) and inv:room_for_item("main", oldnode) then
69 -- inv:add_item("main", oldnode)
73 minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
74 return(itemstack:get_name())
80 function minetest.throw_item(pos, item)
81 -- Take item in any format
83 object = minetest.add_entity(pos, "__builtin:item")
85 object:get_luaentity():set_item(stack)
87 x=math.random(-2,2)*math.random(),
89 z=math.random(-2,2)*math.random()
96 function minetest.throw_experience(pos, amount)
98 object = minetest.add_entity(pos, "experience:orb")
100 object:set_velocity({
101 x=math.random(-2,2)*math.random(),
103 z=math.random(-2,2)*math.random()
111 local dropper_is_player
118 function minetest.item_drop(itemstack, dropper, pos)
119 dropper_is_player = dropper and dropper:is_player()
120 c_pos = table.copy(pos)
121 if dropper_is_player then
122 sneak = dropper:get_player_control().sneak
123 c_pos.y = c_pos.y + 1.2
125 count = itemstack:get_count()
130 count = itemstack:get_count()
133 item = itemstack:take_item(count)
134 object = minetest.add_item(c_pos, item)
136 if dropper_is_player then
137 dir = dropper:get_look_dir()
139 dir.y = dir.y * 2.9 + 2
141 dir = vector.add(dir,dropper:get_player_velocity())
142 object:set_velocity(dir)
143 object:get_luaentity().dropped_by = dropper:get_player_name()
144 object:get_luaentity().collection_timer = 0
154 local set_item = function(self, item)
155 stack = ItemStack(item or self.itemstring)
156 self.itemstring = stack:to_string()
157 if self.itemstring == "" then
158 -- item not yet known
162 itemname = stack:is_known() and stack:get_name() or "unknown"
164 def = minetest.registered_nodes[itemname]
166 self.object:set_properties({
167 textures = {itemname},
168 wield_item = self.itemstring,
169 glow = def and def.light_source,
174 local get_staticdata = function(self)
175 return minetest.serialize({
176 itemstring = self.itemstring,
178 dropped_by = self.dropped_by,
179 collection_timer = self.collection_timer,
180 collectable = self.collectable,
181 try_timer = self.try_timer,
182 collected = self.collected,
183 delete_timer = self.delete_timer,
184 collector = self.collector,
185 magnet_timer = self.magnet_timer,
190 local on_activate = function(self, staticdata, dtime_s)
191 if string.sub(staticdata, 1, string.len("return")) == "return" then
192 data = minetest.deserialize(staticdata)
193 if data and type(data) == "table" then
194 self.itemstring = data.itemstring
195 self.age = (data.age or 0) + dtime_s
196 self.dropped_by = data.dropped_by
197 self.magnet_timer = data.magnet_timer
198 self.collection_timer = data.collection_timer
199 self.collectable = data.collectable
200 self.try_timer = data.try_timer
201 self.collected = data.collected
202 self.delete_timer = data.delete_timer
203 self.collector = data.collector
206 self.itemstring = staticdata
208 self.object:set_armor_groups({immortal = 1})
209 self.object:set_velocity({x = 0, y = 2, z = 0})
210 self.object:set_acceleration({x = 0, y = -9.81, z = 0})
211 set_item(self,self.itemstring)
214 local enable_physics = function(self)
215 if not self.physical_state then
216 self.physical_state = true
217 self.object:set_properties({physical = true})
218 self.object:set_velocity({x=0, y=0, z=0})
219 self.object:set_acceleration({x=0, y=-9.81, z=0})
223 local disable_physics = function(self)
224 if self.physical_state then
225 self.physical_state = false
226 self.object:set_properties({physical = false})
227 self.object:set_velocity({x=0, y=0, z=0})
228 self.object:set_acceleration({x=0, y=0, z=0})
233 ["fire:fire"] = true,
234 ["nether:lava"] = true,
235 ["nether:lavaflow"] = true,
236 ["main:lava"] = true,
237 ["main:lavaflow"] = true
240 {x=1, y=0, z=0}, {x=-1, y=0, z= 0},
241 {x=0, y=0, z=1}, {x= 0, y=0, z=-1},
246 local player_velocity
264 local item_step = function(self, dtime, moveresult)
265 pos = self.object:get_pos()
270 --if item set to be collected then only execute go to player
271 if self.collected == true then
272 if not self.collector then
277 collector = minetest.get_player_by_name(self.collector)
279 self.magnet_timer = self.magnet_timer + dtime
281 disable_physics(self)
284 pos2 = collector:get_pos()
285 player_velocity = collector:get_player_velocity()
286 pos2.y = pos2.y + 0.5
288 distance = vector.distance(pos2,pos)
290 if distance > 2 or distance < 0.3 or self.magnet_timer > 0.2 or self.old_magnet_distance and self.old_magnet_distance < distance then
295 direction = vector.normalize(vector.subtract(pos2,pos))
297 multiplier = 10 - distance -- changed
299 velocity = vector.add(player_velocity,vector.multiply(direction,multiplier))
301 self.object:set_velocity(velocity)
303 self.old_magnet_distance = distance
307 -- the collector doesn't exist
313 --allow entity to be collected after timer
314 if self.collectable == false and self.collection_timer >= 2.5 then
315 self.collectable = true
316 elseif self.collectable == false then
317 self.collection_timer = self.collection_timer + dtime
320 self.age = self.age + dtime
321 if self.age > 300 then
325 -- polling eases the server load
326 if self.poll_timer > 0 then
327 self.poll_timer = self.poll_timer - dtime
328 if self.poll_timer <= 0 then
334 if moveresult and moveresult.touching_ground and table.getn(moveresult.collisions) > 0 then
335 node = minetest.get_node_or_nil(moveresult.collisions[1].node_pos)
341 i_node = minetest.get_node_or_nil(pos)
343 -- Remove nodes in 'ignore' and burns items
345 if i_node.name == "ignore" then
348 elseif i_node and burn_nodes[i_node.name] then
349 minetest.add_particlespawner({
354 minvel = vector.new(-1,0.5,-1),
355 maxvel = vector.new(1,1,1),
356 minacc = {x=0, y=1, z=0},
357 maxacc = {x=0, y=2, z=0},
362 collisiondetection = false,
364 texture = "smoke.png",
366 minetest.sound_play("fire_extinguish", {pos=pos,gain=0.3,pitch=math.random(80,100)/100})
374 snode = minetest.get_node_or_nil(pos)
375 if snode and snode ~= "air" then
376 snode = minetest.registered_nodes[snode.name] or {}
377 is_stuck = (snode.walkable == nil or snode.walkable == true)
378 and (snode.collision_box == nil or snode.collision_box.type == "regular")
379 and (snode.node_box == nil or snode.node_box.type == "regular")
382 -- Push item out when stuck inside solid node
385 -- Check which one of the 4 sides is free
387 cnode = minetest.get_node(vector.add(pos, order[o])).name
388 cdef = minetest.registered_nodes[cnode] or {}
389 if cnode ~= "ignore" and cdef.walkable == false then
395 -- If none of the 4 sides is free, check upwards
397 shootdir = {x=0, y=1, z=0}
398 cnode = minetest.get_node(vector.add(pos, shootdir)).name
399 if cnode == "ignore" then
400 shootdir = nil -- Do not push into ignore
405 -- shove that thing outta there
406 fpos = vector.round(pos)
407 if shootdir.x ~= 0 then
408 shootdir = vector.multiply(shootdir,0.74)
409 self.object:move_to(vector.new(fpos.x+shootdir.x,pos.y,pos.z))
410 elseif shootdir.y ~= 0 then
411 shootdir = vector.multiply(shootdir,0.72)
412 self.object:move_to(vector.new(pos.x,fpos.y+shootdir.y,pos.z))
413 elseif shootdir.z ~= 0 then
414 shootdir = vector.multiply(shootdir,0.74)
415 self.object:move_to(vector.new(pos.x,pos.y,fpos.z+shootdir.z))
424 -- Slide on slippery nodes
425 def = node and minetest.registered_nodes[node.name]
426 vel = self.object:get_velocity()
427 if def and def.walkable then
428 slippery = minetest.get_item_group(node.name, "slippery")
429 if slippery ~= 0 then
430 if math.abs(vel.x) > 0.2 or math.abs(vel.z) > 0.2 then
431 -- Horizontal deceleration
432 slip_factor = 4.0 / (slippery + 4)
433 self.object:set_acceleration({
434 x = -vel.x * slip_factor,
436 z = -vel.z * slip_factor
439 elseif (vel.x ~= 0 or vel.z ~= 0) and math.abs(vel.x) <= 0.2 and math.abs(vel.z) <= 0.2 then
440 self.object:set_velocity(vector.new(0,vel.y,0))
441 self.object:set_acceleration(vector.new(0,-9.81,0))
444 if math.abs(vel.x) > 0.2 or math.abs(vel.z) > 0.2 then
445 self.object:add_velocity({
451 elseif (vel.x ~= 0 or vel.z ~= 0) and math.abs(vel.x) <= 0.2 and math.abs(vel.z) <= 0.2 then
452 self.object:set_velocity(vector.new(0,vel.y,0))
453 self.object:set_acceleration(vector.new(0,-9.81,0))
456 elseif vel.x ~= 0 or vel.y ~= 0 or vel.z ~= 0 then
460 if change == false and self.poll_timer == 0 then
461 self.poll_timer = 0.5
466 minetest.register_entity(":__builtin:item", {
467 initial_properties = {
469 visual = "wielditem",
472 automatic_rotate = 1.5,
476 collide_with_objects = false,
477 collisionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
478 selectionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
479 visual_size = {x = 0.21, y = 0.21},
483 slippery_state = false,
484 physical_state = true,
487 -- Pushing item out of solid nodes
489 force_out_start = nil,
490 -- Collection Variables
491 collection_timer = 2,
496 -- Used for server delay
502 get_staticdata = function(self)
503 return(get_staticdata(self))
505 on_activate = function(self, staticdata, dtime_s)
506 on_activate(self, staticdata, dtime_s)
509 on_step = function(self, dtime, moveresult)
510 item_step(self, dtime, moveresult)
515 minetest.register_chatcommand("gimme", {
517 description = "Spawn x amount of a mob, used as /spawn 'mob' 10 or /spawn 'mob' for one",
518 privs = {server=true},
519 func = function(name)
520 local player = minetest.get_player_by_name(name)
521 local pos = player:get_pos()
525 minetest.throw_item(pos, "main:dirt")