diff --git a/init.lua b/init.lua index dcf2524..c535668 100644 --- a/init.lua +++ b/init.lua @@ -4,10 +4,10 @@ advtrains={} advtrains.modpath = minetest.get_modpath("advtrains") -print=function(text) - minetest.log("action", tostring(text) or "") -end - +--print=function(text) +-- minetest.log("action", tostring(text) or "") +--end +print = function(t) minetest.log("action", t) minetest.chat_send_all(t) end dofile(advtrains.modpath.."/helpers.lua"); dofile(advtrains.modpath.."/debugitems.lua"); diff --git a/textures/advtrains_dtrack_rail.png b/textures/advtrains_dtrack_rail.png index 5fb0c67..568e533 100644 Binary files a/textures/advtrains_dtrack_rail.png and b/textures/advtrains_dtrack_rail.png differ diff --git a/tracks.lua b/tracks.lua index 9a2b462..7ec0ab3 100644 --- a/tracks.lua +++ b/tracks.lua @@ -237,8 +237,7 @@ function advtrains.register_tracks(tracktype, def, preset) }, def.common or {}) --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) - + 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) --[[{ diff --git a/trainlogic.lua b/trainlogic.lua index 37d7b86..5b9390c 100644 --- a/trainlogic.lua +++ b/trainlogic.lua @@ -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 ifnibo 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,23 +265,26 @@ 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 - train.recently_collided_with_env=true - train.velocity=-0.5*train.velocity - train.tarvelocity=0 + 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 + end end end end @@ -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