summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcheapie <no-email-for-you@example.com>2023-08-11 21:32:24 -0500
committercheapie <no-email-for-you@example.com>2023-08-11 21:32:24 -0500
commita39b70a90a530d95b66b39b16512733ec094bd14 (patch)
tree547c36847f63a6e9cbfd2c5abb006a42890b82c4
parent08cbd3adfe523ae8ad4e7263f11ff5ae1d521230 (diff)
downloadcelevator-a39b70a90a530d95b66b39b16512733ec094bd14.tar
celevator-a39b70a90a530d95b66b39b16512733ec094bd14.tar.gz
celevator-a39b70a90a530d95b66b39b16512733ec094bd14.tar.bz2
celevator-a39b70a90a530d95b66b39b16512733ec094bd14.tar.xz
celevator-a39b70a90a530d95b66b39b16512733ec094bd14.zip
Handle entities unloading
If the car disappears while moving (someone did /clearobjects, the server restarted, the mapblock unloaded, etc.), simulate the rest of the motion and spawn a new car upon arrival
-rw-r--r--car.lua23
-rw-r--r--drive_entity.lua49
2 files changed, 70 insertions, 2 deletions
diff --git a/car.lua b/car.lua
index 5211ecb..a391bf7 100644
--- a/car.lua
+++ b/car.lua
@@ -1,3 +1,5 @@
+celevator.car = {}
+
local pieces = {
{
_position = "000",
@@ -344,3 +346,24 @@ for _,def in ipairs(pieces) do
def.light_source = 9
minetest.register_node("celevator:car_"..def._position,def)
end
+
+function celevator.car.spawncar(origin,yaw)
+ local right = vector.rotate_around_axis(vector.new(1,0,0),vector.new(0,1,0),yaw)
+ local back = vector.rotate_around_axis(vector.new(0,0,1),vector.new(0,1,0),yaw)
+ local up = vector.new(0,1,0)
+ for x=0,1,1 do
+ for y=0,2,1 do
+ for z=0,2,1 do
+ local pos = vector.copy(origin)
+ pos = vector.add(pos,vector.multiply(right,x))
+ pos = vector.add(pos,vector.multiply(back,z))
+ pos = vector.add(pos,vector.multiply(up,y))
+ local node = {
+ name = string.format("celevator:car_%d%d%d",x,y,z),
+ param2 = minetest.dir_to_fourdir(minetest.yaw_to_dir(yaw)),
+ }
+ minetest.set_node(pos,node)
+ end
+ end
+ end
+end
diff --git a/drive_entity.lua b/drive_entity.lua
index ace5dd6..16633a3 100644
--- a/drive_entity.lua
+++ b/drive_entity.lua
@@ -16,6 +16,10 @@ local function update_ui(pos)
status = string.format("Running: Up, %0.02f m/s",vel)
elseif state == "running" and vel < 0 then
status = string.format("Running: Down, %0.02f m/s",math.abs(vel))
+ elseif state == "fakerunning" and vel > 0 then
+ status = string.format("Running (simulated): Up, %0.02f m/s",vel)
+ elseif state == "fakerunning" and vel < 0 then
+ status = string.format("Running (simulated): Down, %0.02f m/s",math.abs(vel))
end
meta:set_string("infotext",string.format("Drive - %s - Position: %0.02f m",status,apos))
end
@@ -132,11 +136,17 @@ function celevator.drives.entity.nodestoentities(nodes)
local refs = {}
for _,pos in ipairs(nodes) do
local node = minetest.get_node(pos)
+ local attachobjs = minetest.get_objects_inside_radius(pos,0.9)
local eref = minetest.add_entity(pos,"celevator:car_moving")
eref:set_properties({
wield_item = node.name,
})
eref:set_yaw(minetest.dir_to_yaw(minetest.fourdir_to_dir(node.param2)))
+ for _,attachref in ipairs(attachobjs) do
+ local attachpos = attachref:get_pos()
+ local attachoffset = vector.subtract(pos,attachpos)
+ attachref:set_attach(eref,"",attachoffset)
+ end
minetest.remove_node(pos)
table.insert(refs,eref)
end
@@ -155,7 +165,7 @@ function celevator.drives.entity.entitiestonodes(refs)
end
end
-function celevator.drives.entity.step()
+function celevator.drives.entity.step(dtime)
local entitydrives_running = minetest.deserialize(celevator.storage:get_string("entitydrives_running")) or {}
local save = false
for i,hash in ipairs(entitydrives_running) do
@@ -170,7 +180,7 @@ function celevator.drives.entity.step()
else
local meta = minetest.get_meta(pos)
local state = meta:get_string("state")
- if not (state == "running" or state == "start") then
+ if not (state == "running" or state == "start" or state == "fakerunning") then
table.remove(entitydrives_running,i)
else
local dpos = tonumber(meta:get_string("dpos")) or 0
@@ -194,13 +204,23 @@ function celevator.drives.entity.step()
table.insert(nodes,carpos)
end
end
+ local carparam2 = minetest.get_node(nodes[1]).param2
+ meta:set_int("carparam2",carparam2)
local handles = celevator.drives.entity.nodestoentities(nodes)
celevator.drives.entity.entityinfo[hash] = {
handles = handles,
}
meta:set_string("state","running")
elseif state == "running" then
+ if not celevator.drives.entity.entityinfo[hash] then
+ meta:set_string("state","fakerunning")
+ return
+ end
local handles = celevator.drives.entity.entityinfo[hash].handles
+ if (not handles) or (not handles[1]:get_pos()) then
+ meta:set_string("state","fakerunning")
+ return
+ end
local apos = handles[1]:get_pos().y - origin.y
local dremain = math.abs(dpos-apos)
local dmoved = math.abs(apos-startpos)
@@ -226,6 +246,31 @@ function celevator.drives.entity.step()
meta:set_string("apos",tostring(apos))
sound = vel ~= 0
meta:set_string("vel",tostring(vel))
+ elseif state == "fakerunning" then
+ local apos = tonumber(meta:get_string("apos")) or 0
+ local dremain = math.abs(dpos-apos)
+ local dmoved = math.abs(apos-startpos)
+ local vel
+ if dremain < 0.05 then
+ vel = 0
+ meta:set_string("state","stopped")
+ local carparam2 = meta:get_int("carparam2")
+ celevator.car.spawncar(vector.round(vector.add(origin,vector.new(0,apos,0))),minetest.dir_to_yaw(minetest.fourdir_to_dir(carparam2)))
+ apos = math.floor(apos+0.5)
+ elseif dremain < 0.2 then
+ vel = 0.2
+ elseif dremain < maxvel and dremain < dmoved then
+ vel = dremain
+ elseif dmoved+0.1 > maxvel then
+ vel = maxvel
+ else
+ vel = dmoved+0.1
+ end
+ if dpos < apos then vel = 0-vel end
+ apos = apos+(vel*dtime)
+ meta:set_string("apos",tostring(apos))
+ sound = vel ~= 0
+ meta:set_string("vel",tostring(vel))
end
end
end