z=topdir.x*backdir.y - backdir.x*topdir.y}
end
+local function vector_copy(v)
+ return { x = v.x, y = v.y, z = v.z }
+end
+
+local function rectilinear_distance(v)
+ return math.abs(v.x + v.y + v.z)
+end
+
local fakePlayer = {
get_player_name = function() return ":pipeworks" end,
-- any other player functions called by allow_metadata_inventory_take anywhere...
end
local item1 = pipeworks.tube_item(vector.add(frompos, vector.multiply(dir, 1.4)), item)
item1:get_luaentity().start_pos = vector.add(frompos, dir)
- item1:setvelocity(dir)
+ item1:get_luaentity().velocity = vector_copy(dir)
+ item1:setvelocity(dir, 1.001, {x=0,y=0,z=0})
item1:setacceleration({x=0, y=0, z=0})
return true-- only fire one item, please
end
local cmeta = minetest.get_meta(pos)
local n
local can_go
- local speed = math.abs(velocity.x + velocity.y + velocity.z)
+ local speed = rectilinear_distance(velocity)
local vel = {x = velocity.x/speed, y = velocity.y/speed, z = velocity.z/speed,speed=speed}
if speed >= 4.1 then
speed = 4
end,
get_staticdata = function(self)
- if self.start_pos == nil or self.removed then
- return
+ if self.removed then return end
+ if self.start_pos == nil then
+ local pos = self.object:getpos()
+ self.start_pos = roundpos(pos)
end
- local velocity = self.object:getvelocity()
self.object:setpos(self.start_pos)
+ if self.velocity == nil then
+ local vel = self.object:getvelocity()
+ if rectilinear_distance(vel) ~= 0 then
+ self.velocity = vector_copy(vel)
+ self.object:setvelocity(self.velocity, 1.001/rectilinear_distance(self.velocity), {x=0,y=0,z=0})
+ end
+ end
return minetest.serialize({
itemstring = self.itemstring,
- velocity = velocity,
+ velocity = self.velocity or self.object:getvelocity(),
start_pos = self.start_pos
})
end,
end
if itemname then
- self.start_pos=item.start_pos
- self.object:setvelocity(item.velocity)
- self.object:setacceleration({x=0, y=0, z=0})
- self.object:setpos(item.start_pos)
+ self.start_pos = item.start_pos
+ self.object:setpos(item.start_pos)
+ if rectilinear_distance(item.velocity) ~= 0 then
+ self.velocity = item.velocity
+ self.object:setvelocity(item.velocity, 1.001/rectilinear_distance(item.velocity), {x=0,y=0,z=0})
+ end
+ self.object:setacceleration({x=0, y=0, z=0})
end
self:set_item(item.itemstring)
end,
local pos = self.object:getpos()
self.start_pos = roundpos(pos)
end
+ if self.velocity == nil then
+ local vel = self.object:getvelocity()
+ if rectilinear_distance(vel) == 0 then return end
+ self.velocity = vector_copy(vel)
+ end
local pos = self.object:getpos()
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local stack = ItemStack(self.itemstring)
local drop_pos = nil
- local velocity = self.object:getvelocity()
-
- if velocity == nil then return end
-
- local velocitycopy = {x = velocity.x, y = velocity.y, z = velocity.z}
-
- local moved = false
- local speed = math.abs(velocity.x + velocity.y + velocity.z)
- local vel = {x = velocity.x / speed, y = velocity.y / speed, z = velocity.z / speed, speed = speed}
-
- if math.abs(vel.x) == 1 then
- local next_node = math.abs(pos.x - self.start_pos.x)
- if next_node >= 1 then
- self.start_pos.x = self.start_pos.x + vel.x
- moved = true
- end
- elseif math.abs(vel.y) == 1 then
- local next_node = math.abs(pos.y - self.start_pos.y)
- if next_node >= 1 then
- self.start_pos.y = self.start_pos.y + vel.y
- moved = true
- end
- elseif math.abs(vel.z) == 1 then
- local next_node = math.abs(pos.z - self.start_pos.z)
- if next_node >= 1 then
- self.start_pos.z = self.start_pos.z + vel.z
- moved = true
+ local velocity = self.velocity
+ local dist_moved = rectilinear_distance(vector.subtract(pos, self.start_pos))
+ if dist_moved < 1 then
+ if rectilinear_distance(self.object:getvelocity()) == 0 then
+ -- Items shouldn't ever get stuck like this.
+ -- But it's best to be paranoid about
+ -- the engine's mathematical correctness.
+ self.object:setvelocity(velocity, (1.001-dist_moved)/rectilinear_distance(velocity), {x=0,y=0,z=0})
end
+ return
end
-
- local sposcopy = {x = self.start_pos.x, y = self.start_pos.y, z = self.start_pos.z}
+
+ local speed = rectilinear_distance(velocity)
+ local dir = vector.divide(velocity, speed)
+ local velocitycopy = vector_copy(velocity)
+ self.start_pos = vector.add(self.start_pos, dir)
+ local sposcopy = vector_copy(self.start_pos)
node = minetest.get_node(self.start_pos)
- if moved and minetest.get_item_group(node.name, "tubedevice_receiver") == 1 then
+ if minetest.get_item_group(node.name, "tubedevice_receiver") == 1 then
local leftover = nil
if minetest.registered_nodes[node.name].tube and minetest.registered_nodes[node.name].tube.insert_object then
+ local vel = { x = dir.x, y = dir.y, z = dir.z, speed = speed }
leftover = minetest.registered_nodes[node.name].tube.insert_object(self.start_pos, node, stack, vel)
else
leftover = stack
velocity.x = -velocity.x
velocity.y = -velocity.y
velocity.z = -velocity.z
- self.object:setvelocity(velocity)
+ self.velocity = velocity
+ self.object:setpos(self.start_pos)
+ self.object:setvelocity(velocity, 1.001/rectilinear_distance(velocity), { x=0, y=0, z=0 })
self:set_item(leftover:to_string())
return
end
- if moved then
- if go_next (self.start_pos, velocity, stack) == 0 then
- drop_pos = minetest.find_node_near(vector.add(self.start_pos, velocity), 1, "air")
- if drop_pos then
- minetest.item_drop(stack, "", drop_pos)
- self:remove()
- end
+ if go_next (self.start_pos, velocity, stack) == 0 then
+ drop_pos = minetest.find_node_near(vector.add(self.start_pos, velocity), 1, "air")
+ if drop_pos then
+ minetest.item_drop(stack, "", drop_pos)
+ self:remove()
end
end
if velocity.x~=velocitycopy.x or velocity.y~=velocitycopy.y or velocity.z~=velocitycopy.z or
self.start_pos.x~=sposcopy.x or self.start_pos.y~=sposcopy.y or self.start_pos.z~=sposcopy.z then
self.object:setpos(self.start_pos)
- self.object:setvelocity(velocity)
+ dist_moved = 0
+ self.velocity = velocity
+ else
+ dist_moved = rectilinear_distance(vector.subtract(pos, self.start_pos))
end
+ self.object:setvelocity(velocity, (1.001-dist_moved)/rectilinear_distance(velocity), {x=0,y=0,z=0})
end
})
if object:get_luaentity().itemstring ~= "" then
local titem = pipeworks.tube_item(pos,object:get_luaentity().itemstring)
titem:get_luaentity().start_pos = {x = pos.x, y = pos.y-1, z = pos.z}
- titem:setvelocity({x = 0.01, y = 1, z = -0.01})
+ titem:get_luaentity().velocity = {x=0,y=1,z=0}
+ titem:setvelocity({x=0,y=1,z=0}, 1.001, {x=0,y=0,z=0})
titem:setacceleration({x = 0, y = 0, z = 0})
end
object:get_luaentity().itemstring = ""
if object:get_luaentity().itemstring ~= "" then
local titem = pipeworks.tube_item(pos, object:get_luaentity().itemstring)
titem:get_luaentity().start_pos = {x = pos.x, y = pos.y-1, z = pos.z}
- titem:setvelocity({x = 0.01, y = 1, z = -0.01})
+ titem:get_luaentity().velocity = {x=0,y=1,z=0}
+ titem:setvelocity({x=0,y=1,z=0}, 1.001, {x=0,y=0,z=0})
titem:setacceleration({x = 0, y = 0, z = 0})
end
object:get_luaentity().itemstring = ""
insert_object = function(pos, node, stack, direction)
item1 = pipeworks.tube_item(pos, stack)
item1:get_luaentity().start_pos = pos
- item1:setvelocity({x = direction.x*direction.speed, y = direction.y*direction.speed, z = direction.z*direction.speed})
+ local vel = { x = direction.x*direction.speed, y = direction.y*direction.speed, z = direction.z*direction.speed }
+ item1:get_luaentity().velocity = vel
+ item1:setvelocity(vel, 1.001, {x=0,y=0,z=0})
item1:setacceleration({x = 0, y = 0, z = 0})
return ItemStack("")
end,