1
0
mirror of https://github.com/HybridDog/builtin_item.git synced 2025-06-30 07:20:32 +02:00

Compare commits

1 Commits

Author SHA1 Message Date
5ecccfcff1 Version MFF. 2018-09-06 21:32:52 +02:00
8 changed files with 247 additions and 141 deletions

4
.gitignore vendored
View File

@ -1,4 +0,0 @@
## Generic ignorable patterns and files
*~
.*.swp
debug.txt

View File

@ -1,12 +0,0 @@
read_globals = {
minetest = {
fields = {
registered_entities = {
read_only = false,
other_fields = true
}
},
other_fields = true
},
"vector"
}

View File

@ -1,2 +0,0 @@
MIT for the code
The original mod was licensed under WTFPL.

View File

@ -1,2 +0,0 @@
For a description of this Minetest mod, see
https://forum.minetest.net/viewtopic.php?f=9&t=10271.

38
README.txt Executable file
View File

@ -0,0 +1,38 @@
=== BUILTIN_ITEM MOD for MINETEST-C55 ===
by PilzAdam
Features:
This mod adds some new features to the builtin items:
- The items are pushed by flowing water
- The items are destroyed by lava
- The items are removed after 300 seconds or the time that is specified by
remove_items in minetest.conf (0 disables it)
How to install:
Unzip the archive an place it in minetest-base-directory/mods/minetest/
if you have a windows client or a linux run-in-place client. If you have
a linux system-wide instalation place it in ~/.minetest/mods/minetest/.
If you want to install this mod only in one world create the folder
worldmods/ in your worlddirectory.
For further information or help see:
http://wiki.minetest.com/wiki/Installing_Mods
License:
WTFPL (see below)
See also:
http://minetest.net/
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

303
init.lua Normal file → Executable file
View File

@ -1,127 +1,216 @@
-- Use the movement gravity for the downwards acceleration. local time = tonumber(minetest.setting_get("remove_items"))
-- The setting may change in-game but for simplicity we don't support this. if not time then
local movement_gravity = tonumber(minetest.settings:get("movement_gravity")) time = 1800 -- set to 30 minutes the time before remove a dropped item
or 9.81 end
-- get_flow_raw determines the horizontal flow vector for a flowing liquid node, unwalkable_nodes = {}
-- or returns nothing if the flow is zero
local neighbour_offsets = { minetest.after(0, function()
{x=-1, y=0, z=0}, for itemname, node in pairs(minetest.registered_nodes) do
{x=1, y=0, z=0}, if node.walkable == false then
{x=0, y=0, z=-1}, table.insert(unwalkable_nodes, 1, itemname)
{x=0, y=0, z=1} end
} end
local function get_flow_raw(pos) end)
-- FIXME: Do we need to treat nodes with special liquid_range differently?
local get_flowing_dir = function(self)
local pos = self.object:getpos()
local param2 = minetest.get_node(pos).param2 local param2 = minetest.get_node(pos).param2
if param2 == 15 then for i,d in ipairs({-1, 1, -1, 1}) do
-- The liquid has full height and flows downwards if i<3 then
return pos.x = pos.x+d
end
local flow = {x = 0, y = 0, z = 0}
local height = param2 % 8
for n = 1, 4 do
local node = minetest.get_node(vector.add(pos, neighbour_offsets[n]))
local def = minetest.registered_nodes[node.name]
local height_other
if not def or def.walkable then
-- A solid node, so no flow happens
height_other = height
elseif def.liquidtype == "source" then
-- Assume that relevant liquid comes from this source
height_other = 8
elseif def.liquidtype == "flowing" then
-- This neighbour is also a flowing liquid
height_other = node.param2 % 8
else else
-- There is a free space, e.g. air or a plant pos.z = pos.z+d
height_other = 0
end end
local fl = vector.multiply(neighbour_offsets[n], height - height_other)
flow = vector.add(flow, fl) local name = minetest.get_node(pos).name
local par2 = minetest.get_node(pos).param2
if name == "default:water_flowing" and par2 < param2 then
return pos
end end
if vector.equals(flow, {x = 0, y = 0, z = 0}) then
if i<3 then
pos.x = pos.x-d
else
pos.z = pos.z-d
end
end
return nil
end
minetest.register_entity(":__builtin:item", {
initial_properties = {
hp_max = 1,
physical = true,
collisionbox = {-0.175, -0.175, -0.175, 0.175, 0.175, 0.175},
collide_with_objects = false,
visual = "sprite",
visual_size = {x=0.5, y=0.5},
textures = {""},
spritediv = {x=1, y=1},
initial_sprite_basepos = {x=0, y=0},
is_visible = false,
timer = 0,
},
itemstring = "",
physical_state = true,
set_item = function(self, itemstring)
self.itemstring = itemstring
local stack = ItemStack(itemstring)
local itemtable = stack:to_table()
local itemname = nil
if itemtable then
itemname = stack:to_table().name
end
local item_texture = nil
local item_type = ""
if minetest.registered_items[itemname] then
item_texture = minetest.registered_items[itemname].inventory_image
item_type = minetest.registered_items[itemname].type
end
local prop = {
is_visible = true,
visual = "wielditem",
textures = {(itemname or "unknown_item.png")},
visual_size = {x=0.175, y=0.175},
automatic_rotate = math.pi * 0.5,
}
self.object:set_properties(prop)
end,
get_staticdata = function(self)
--return self.itemstring
return minetest.serialize({
itemstring = self.itemstring,
always_collect = self.always_collect,
timer = self.timer,
})
end,
on_activate = function(self, staticdata, dtime_s)
if string.sub(staticdata, 1, string.len("return")) == "return" then
local data = minetest.deserialize(staticdata)
if data and type(data) == "table" then
self.itemstring = data.itemstring
self.always_collect = data.always_collect
self.timer = data.timer
if not self.timer then
self.timer = 0
end
self.timer = self.timer+dtime_s
end
else
self.itemstring = staticdata
end
self.object:set_armor_groups({immortal=1})
self.object:setvelocity({x=0, y=2, z=0})
self.object:setacceleration({x=0, y=-10, z=0})
self:set_item(self.itemstring)
end,
on_step = function(self, dtime)
if not self.timer then
self.timer = 0
end
self.timer = self.timer + dtime
if self.itemstring == "" or (time ~= 0 and (self.timer > time)) then
self.object:remove()
return return
end end
return vector.normalize(flow)
end
-- get_flow caches the results from get_flow_raw for 10 s local p = self.object:getpos()
local flow_cache = {}
setmetatable(flow_cache, {__mode = "kv"})
local function get_flow(pos)
local vi = minetest.hash_node_position(pos)
local t = minetest.get_us_time()
if flow_cache[vi]
and t - flow_cache[vi][1] < 10 * 1000000 then
return flow_cache[vi][2]
end
local flow = get_flow_raw(pos)
flow_cache[vi] = {t, flow}
return flow
end
local item_entity = minetest.registered_entities["__builtin:item"] local name = minetest.get_node(p).name
local old_on_step = item_entity.on_step if not minetest.registered_nodes[name] then return end
if minetest.registered_nodes[name].damage_per_second > 0 or name == "maptools:igniter" then
item_entity.makes_footstep_sound = true minetest.sound_play("builtin_item_lava", {pos = p, gain = 0.5})
-- The "bt_" prefix shows that the value comes from builtin_item self.object:remove()
item_entity.bt_timer = 0 return
item_entity.on_step = function(self, dtime, ...)
-- Remember the velocity before an original on_step can change it
local vel_desired
if self.bt_reset_velocity then
vel_desired = self.object:get_velocity()
end end
old_on_step(self, dtime, ...) --[[ if name == "default:water_source" then
self.object:setacceleration({x = 0, y = 4, z = 0})
else
self.object:setacceleration({x = 0, y = -10, z = 0})
end
--]]
-- Ignore the item if it should not interact with physics if minetest.registered_nodes[name].liquidtype == "flowing" then
local vec = get_flowing_dir(self)
if vec then
local v = self.object:getvelocity()
if v and vec.x-p.x > 0 then
self.object:setacceleration({x = 0, y = 0, z = 0})
self.object:setvelocity({x = 1, y = -0.22, z = 0})
elseif v and vec.x-p.x < 0 then
self.object:setacceleration({x = 0, y = 0, z = 0})
self.object:setvelocity({x = -1, y = -0.22, z = 0})
elseif v and vec.z-p.z > 0 then
self.object:setacceleration({x = 0, y = 0, z = 0})
self.object:setvelocity({x = 0, y = -0.22, z = 1})
elseif v and vec.z-p.z < 0 then
self.object:setacceleration({x = 0, y = 0, z = 0})
self.object:setvelocity({x = 0, y = -0.22, z = -1})
end
self.object:setacceleration({x = 0, y = -10, z = 0})
self.physical_state = true
self.object:set_properties({
physical = true
})
return
end
end
p.y = p.y - 0.3
local nn = minetest.get_node(p).name
-- If node is not registered or node is walkably solid.
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable then
if self.physical_state then
self.object:setvelocity({x=0,y=0,z=0})
self.object:setacceleration({x=0, y=0, z=0})
self.physical_state = false
self.object:set_properties({
physical = false
})
end
else
if not self.physical_state then if not self.physical_state then
return self.object:setvelocity({x=0,y=0,z=0})
self.object:setacceleration({x=0, y=-10, z=0})
self.physical_state = true
self.object:set_properties({
physical = true
})
end
end end
-- Reset the velocity if needed -- Eject if not walkable
if vel_desired local upnode = minetest.get_node({x = p.x, y = math.ceil(p.y), z = p.z}).name
and not vector.equals(self.object:get_velocity(), vel_desired) then if minetest.registered_nodes[upnode] and minetest.registered_nodes[upnode].walkable then
self.object:set_velocity(vel_desired) local minp, maxp = {x=p.x-1, y=math.ceil(p.y), z=p.z-1}, {x=p.x+1, y=math.ceil(p.y)+1, z=p.z+1}
local nodes = minetest.find_nodes_in_area(minp, maxp, unwalkable_nodes)
if table.getn(nodes) > 0 then
self.object:setpos(nodes[math.random(1,#nodes)])
end end
end
-- For performance reasons, skip the remaining code in frequent steps end,
self.bt_timer = self.bt_timer + dtime --[[ This causes a duplication glitch if a player walks upon an item and clicks on it at the same time.
if self.bt_timer < 0.1 then on_punch = function(self, hitter)
if self.itemstring ~= "" then
local left = hitter:get_inventory():add_item("main", self.itemstring)
if not left:is_empty() then
self.itemstring = left:to_string()
return return
end end
self.bt_timer = 0 end
self.object:remove()
end,
--]]
})
local p = self.object:get_pos() if minetest.setting_get("log_mods") then
local pos = vector.round(p) minetest.log("action", "[builtin_item] loaded.")
local nodename = minetest.get_node(pos).name
if self.bt_reset_velocity then
-- Set the item acceleration to its default (changed again below)
self.object:set_acceleration({x=0, y=-movement_gravity, z=0})
self.bt_reset_velocity = nil
end
local def = minetest.registered_nodes[nodename]
if not def or not def.liquidtype or def.liquidtype ~= "flowing" then
return
end
local flow = get_flow(pos)
if not flow then
return
end
local vel_current = vel_desired or self.object:get_velocity()
local acc
if vector.dot(vel_current, flow) < 1.0 then
acc = vector.multiply(flow, 2.0)
else
-- The item is already accelerated by the fluids
acc = {x = 0, y = 0, z = 0}
end
acc.y = -movement_gravity
self.object:set_acceleration(acc)
self.bt_reset_velocity = true
end end
minetest.register_entity(":__builtin:item", item_entity)

View File

@ -1 +0,0 @@
name = builtin_item

BIN
sounds/builtin_item_lava.ogg Executable file

Binary file not shown.