rewrite collision system again

this time, it is based on nodes that trains stand on.
advtrains.detector (in tracks.lua) keeps a table with nodes that trains are standing /driving on. This will be used now for detector rails.
This commit is contained in:
orwell96 2016-11-10 20:24:47 +01:00
parent 6a0186f042
commit ab652da5f4
4 changed files with 128 additions and 16 deletions

View File

@ -4,10 +4,10 @@ advtrains={}
advtrains.modpath = minetest.get_modpath("advtrains")
print=function(text)
minetest.log("action", tostring(text) or "<non-string>")
end
--print=function(text)
-- minetest.log("action", tostring(text) or "<non-string>")
--end
print = function(t) minetest.log("action", t) minetest.chat_send_all(t) end
dofile(advtrains.modpath.."/helpers.lua");
dofile(advtrains.modpath.."/debugitems.lua");

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -238,7 +238,6 @@ function advtrains.register_tracks(tracktype, def, preset)
--make trackplacer base def
advtrains.trackplacer.register_tracktype(def.nodename_prefix, preset.tpdefault)
advtrains.trackplacer.register_track_placer(def.nodename_prefix, def.texture_prefix, def.description)
for suffix, conns in pairs(preset.variant) do
for rotid, rotation in ipairs(preset.rotation) do
if not def.formats[suffix] or def.formats[suffix][rotid] then
@ -246,6 +245,7 @@ function advtrains.register_tracks(tracktype, def, preset)
if preset.switch[suffix] then
switchfunc, mesecontbl=make_switchfunc(preset.switch[suffix]..rotation, preset.switchmc[suffix])
end
minetest.register_node(def.nodename_prefix.."_"..suffix..rotation, advtrains.merge_tables(
common_def,
make_overdef(
@ -293,6 +293,70 @@ function advtrains.get_track_connections(name, param2)
return (nodedef.connect1 + 4 * noderot)%16, (nodedef.connect2 + 4 * noderot)%16, nodedef.rely1 or 0, nodedef.rely2 or 0, nodedef.railheight or 0
end
--detector code
--holds a table with nodes on which trains are on.
advtrains.detector = {}
advtrains.detector.on_node = {}
advtrains.detector.on_node_restore = {}
--set if paths were invalidated before. tells trainlogic.lua to call advtrains.detector.finalize_restore()
advtrains.detector.clean_step_before = false
--when train enters a node, call this
--The entry already being contained in advtrains.detector.on_node_restore will not trigger an on_train_enter event on the node. (when path is reset, this is saved).
function advtrains.detector.enter_node(pos, train_id)
local pts = minetest.pos_to_string(advtrains.round_vector_floor_y(pos))
--print("enterNode "..pts.." "..train_id)
if not advtrains.detector.on_node[pts] then
advtrains.detector.on_node[pts]=train_id
if advtrains.detector.on_node_restore[pts] then
advtrains.detector.on_node_restore[pts]=nil
else
advtrains.detector.call_enter_callback(advtrains.round_vector_floor_y(pos), train_id)
end
end
end
function advtrains.detector.leave_node(pos, train_id)
local pts = minetest.pos_to_string(advtrains.round_vector_floor_y(pos))
--print("leaveNode "..pts.." "..train_id)
if advtrains.detector.on_node[pts] then
advtrains.detector.call_leave_callback(advtrains.round_vector_floor_y(pos), train_id)
advtrains.detector.on_node[pts]=nil
end
end
--called immediately before invalidating paths
function advtrains.detector.setup_restore()
--print("setup_restore")
advtrains.detector.on_node_restore = advtrains.detector.on_node
advtrains.detector.on_node = {}
end
--called one step after invalidating paths, when all trains have restored their path and called enter_node for their contents.
function advtrains.detector.finalize_restore()
--print("finalize_restore")
for pts, train_id in pairs(advtrains.detector.on_node_restore) do
--print("called leave callback "..pts.." "..train_id)
advtrains.detector.call_leave_callback(minetest.string_to_pos(pts), train_id)
end
advtrains.detector.on_node_restore = {}
end
function advtrains.detector.call_enter_callback(pos, train_id)
--print("instructed to call enter calback")
local node = minetest.get_node(pos) --this spares the check if node is nil, it has a name in any case
local mregnode=minetest.registered_nodes[node.name]
if mregnode and mregnode.advtrains and mregnode.advtrains.on_train_enter then
mregnode.advtrains.on_train_enter(pos, train_id)
end
end
function advtrains.detector.call_leave_callback(pos, train_id)
--print("instructed to call leave calback")
local node = minetest.get_node(pos) --this spares the check if node is nil, it has a name in any case
local mregnode=minetest.registered_nodes[node.name]
if mregnode and mregnode.advtrains and mregnode.advtrains.on_train_leave then
mregnode.advtrains.on_train_leave(pos, train_id)
end
end
--END code, BEGIN definition
--definition format: ([] optional)
--[[{

View File

@ -155,6 +155,12 @@ minetest.register_globalstep(function(dtime)
for k,v in pairs(advtrains.trains) do
advtrains.train_step(k, v, dtime)
end
--see tracks.lua
if advtrains.detector.clean_step_before then
advtrains.detector.finalize_restore()
end
printbm("trainsteps", t)
endstep()
end)
@ -204,6 +210,41 @@ function advtrains.train_step(id, train, dtime)
if train.tarvelocity<0 then train.tarvelocity=0 end
end
--update advtrains.detector
if not train.detector_old_index then
train.detector_old_index = math.floor(train_end_index)
train.detector_old_end_index = math.floor(train_end_index)
end
local ifo, ifn, ibo, ibn = train.detector_old_index, math.floor(train.index), train.detector_old_end_index, math.floor(train_end_index)
if ifn>ifo then
for i=ifo, ifn do
if path[i] then
advtrains.detector.enter_node(path[i], id)
end
end
elseif ifn<ifo then
for i=ifn, ifo do
if path[i] then
advtrains.detector.leave_node(path[i], id)
end
end
end
if ibn<ibo then
for i=ibn, ibn do
if path[i] then
advtrains.detector.enter_node(path[i], id)
end
end
elseif ibn>ibo then
for i=ibo, ibn do
if path[i] then
advtrains.detector.leave_node(path[i], id)
end
end
end
train.detector_old_index = math.floor(train.index)
train.detector_old_end_index = math.floor(train_end_index)
if train_moves then
--check for collisions by finding objects
--front
@ -224,20 +265,22 @@ function advtrains.train_step(id, train, dtime)
end
end
end
--new train collisions (only search in the direction of the driving train)
local coll_search_radius=2
local coll_grace=0
--heh, new collision again.
--this time, based on NODES and the advtrains.detector.on_node table.
local collpos
local coll_grace=1
if train.velocity>0 then
collpos=advtrains.get_real_index_position(path, train.index-coll_grace)
elseif train.velocity<0 then
collpos=advtrains.get_real_index_position(path, train_end_index+coll_grace)
end
if collpos then
local objrefs=minetest.get_objects_inside_radius(collpos, coll_search_radius)
for _,v in pairs(objrefs) do
local le=v:get_luaentity()
if le and le.is_wagon and le.initialized and le.train_id~=id then
local rcollpos=advtrains.round_vector_floor_y(collpos)
for x=-1,1 do
for z=-1,1 do
local testpts=minetest.pos_to_string(vector.add(rcollpos, {x=x, y=0, z=z}))
if advtrains.detector.on_node[testpts] and advtrains.detector.on_node[testpts]~=id then
--collides
train.recently_collided_with_env=true
train.velocity=-0.5*train.velocity
train.tarvelocity=0
@ -245,6 +288,7 @@ function advtrains.train_step(id, train, dtime)
end
end
end
end
--check for any trainpart entities if they have been unloaded. do this only if train is near a player, to not spawn entities into unloaded areas
train.check_trainpartload=(train.check_trainpartload or 0)-dtime
local node_range=(math.max((minetest.setting_get("active_block_range") or 0),1)*16)
@ -775,6 +819,10 @@ function advtrains.invalidate_all_paths()
v.index=nil
v.min_index_on_track=nil
v.max_index_on_track=nil
advtrains.detector.setup_restore()
v.detector_old_index=nil
v.detector_old_end_index=nil
end
end