1
0
mirror of https://github.com/HybridDog/builtin_item.git synced 2025-06-29 23:10:30 +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.

305
init.lua Normal file → Executable file
View File

@ -1,127 +1,216 @@
-- Use the movement gravity for the downwards acceleration.
-- The setting may change in-game but for simplicity we don't support this.
local movement_gravity = tonumber(minetest.settings:get("movement_gravity"))
or 9.81
local time = tonumber(minetest.setting_get("remove_items"))
if not time then
time = 1800 -- set to 30 minutes the time before remove a dropped item
end
-- get_flow_raw determines the horizontal flow vector for a flowing liquid node,
-- or returns nothing if the flow is zero
local neighbour_offsets = {
{x=-1, y=0, z=0},
{x=1, y=0, z=0},
{x=0, y=0, z=-1},
{x=0, y=0, z=1}
}
local function get_flow_raw(pos)
-- FIXME: Do we need to treat nodes with special liquid_range differently?
unwalkable_nodes = {}
minetest.after(0, function()
for itemname, node in pairs(minetest.registered_nodes) do
if node.walkable == false then
table.insert(unwalkable_nodes, 1, itemname)
end
end
end)
local get_flowing_dir = function(self)
local pos = self.object:getpos()
local param2 = minetest.get_node(pos).param2
if param2 == 15 then
-- The liquid has full height and flows downwards
return
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
for i,d in ipairs({-1, 1, -1, 1}) do
if i<3 then
pos.x = pos.x+d
else
-- There is a free space, e.g. air or a plant
height_other = 0
pos.z = pos.z+d
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
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
end
return vector.normalize(flow)
local p = self.object:getpos()
local name = minetest.get_node(p).name
if not minetest.registered_nodes[name] then return end
if minetest.registered_nodes[name].damage_per_second > 0 or name == "maptools:igniter" then
minetest.sound_play("builtin_item_lava", {pos = p, gain = 0.5})
self.object:remove()
return
end
-- get_flow caches the results from get_flow_raw for 10 s
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]
--[[ 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
local flow = get_flow_raw(pos)
flow_cache[vi] = {t, flow}
return flow
--]]
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
local item_entity = minetest.registered_entities["__builtin:item"]
local old_on_step = item_entity.on_step
item_entity.makes_footstep_sound = true
-- The "bt_" prefix shows that the value comes from builtin_item
item_entity.bt_timer = 0
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()
self.object:setacceleration({x = 0, y = -10, z = 0})
self.physical_state = true
self.object:set_properties({
physical = true
})
return
end
end
old_on_step(self, dtime, ...)
-- Ignore the item if it should not interact with physics
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
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
-- Eject if not walkable
local upnode = minetest.get_node({x = p.x, y = math.ceil(p.y), z = p.z}).name
if minetest.registered_nodes[upnode] and minetest.registered_nodes[upnode].walkable then
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,
--[[ This causes a duplication glitch if a player walks upon an item and clicks on it at the same time.
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
end
end
self.object:remove()
end,
--]]
})
-- Reset the velocity if needed
if vel_desired
and not vector.equals(self.object:get_velocity(), vel_desired) then
self.object:set_velocity(vel_desired)
if minetest.setting_get("log_mods") then
minetest.log("action", "[builtin_item] loaded.")
end
-- For performance reasons, skip the remaining code in frequent steps
self.bt_timer = self.bt_timer + dtime
if self.bt_timer < 0.1 then
return
end
self.bt_timer = 0
local p = self.object:get_pos()
local pos = vector.round(p)
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
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.