aboutsummaryrefslogtreecommitdiff
path: root/advtrains/trainlogic.lua
Commit message (Collapse)AuthorAge
* LZB: Look ahead before movement, not afterorwell962021-02-12
|
* Fix hud and trainlogic to work togetherorwell962021-02-10
|
* Replace deprecated object:getxxx()/setxxx() by get_xxx()/set_xxx()orwell962021-02-10
|
* Remove debug facilitiesorwell962021-02-10
|
* Rewrite movement logic againorwell962021-02-10
|
* Add debug prints, modify LZB to fix problems with look_aheadorwell962021-02-10
|
* Start using path_invalidate_ahead()orwell962021-02-10
|
* More debug info to hopefully gain more info on the bugorwell962021-02-10
|
* Fix things, rework signal aspect select dialog, transform old aspects on-the-flyorwell962021-02-10
|
* Always do zero-barrier check and prevent LZB 0 overruns in movement logicorwell962021-02-10
|
* Fix lots of things around new LZBorwell962021-02-10
|
* Remove pcall wrappers completely, add command to disable advtrains mainlooporwell962021-02-10
|
* Implement a LZB speed lookup table for the path and rewrite velocity controlsorwell962021-02-10
|
* Discard get_node_or_nil() for area-loaded check and use either a ↵orwell962021-02-03
| | | | | | distance-based approach or minetest.is_block_active() if available See also https://github.com/minetest/minetest/pull/10897
* add maximum length parameter to split_at_fc and split_off_locomotiveGabriel Pérez-Cerezo2020-08-21
|
* Add command to split off locomotiveGabriel Pérez-Cerezo2020-07-28
|
* Add function to step through freight codesGabriel Pérez-Cerezo2020-07-26
|
* add split_train_at_fc luaatc commandGabriel Pérez-Cerezo2020-07-26
| | | | | | This command splits the train at the second non-empty FC it encounters, taking with it the first few freight cars that all go to the same destination.
* Add workaround to unload wagons that are too far away from playersorwell962020-07-12
|
* Add autocouple modeGabriel Pérez-Cerezo2020-06-29
| | | | | | | The shunting mode no longer makes trains couple, since it was meant for other purposes. For autocoupling, the new autocoupling mode is used. If trains are in autocouple mode, they couple when they collide with another train.
* Workaround to handle split points (dt. aufgefahrene Weichen), fixing H#77orwell962020-06-10
|
* Fix trains flipping when autocouplingGabriel Pérez-Cerezo2020-06-08
|
* Simplify and optimize path_get_index_by_offset (cherrypicked)orwell962019-12-09
|
* Tentative fix for #31Gabriel Pérez-Cerezo2019-12-03
| | | | | This might fix #31 by clearing the HUD entry for the player when joining
* Don't spawn couple entities when not loadedorwell962019-11-26
|
* remove obsolete code/commentsorwell962019-11-26
|
* Shunting mode now couples trains on collision.Gabriel Pérez-Cerezo2019-08-11
| | | | Trains now get coupled when one of them is in coupling mode.
* Add decoupling to luaatcGabriel Pérez-Cerezo2019-08-11
|
* Change API to return the id of a newly created train when discouplingGabriel Pérez-Cerezo2019-08-09
|
* Run entity overrun checking only in loaded areasorwell962019-06-05
|
* Move LZB system to core and unify approach callback mechanismorwell962019-04-16
|
* Add setting for death behavior and implement damage checks betterorwell962019-03-09
|
* Prioritize LZB callback (possible bugfix for H#100)orwell962019-02-19
|
* Point speed restriction railsorwell962019-01-24
|
* Possible fix for braking problems + debug outputsorwell962019-01-23
|
* output step distance in train (debugging purposes)orwell962019-01-22
|
* Make "Can't restore train" a log message instead of atwarn()orwell962019-01-22
|
* Warn when something clears the path winthin train steporwell962019-01-22
|
* Revert "Correct last commit"orwell962019-01-22
| | | | This reverts commit 5f290819cdb78303396f9f89907ebbc66a9d74b3.
* Revert "Debugging code to trace down path_invalidate within callbacks error"orwell962019-01-22
| | | | This reverts commit 1965e846b6c61958063ea13e2ac88ae18b701d09.
* Revert "Index NaN check (tracking obscure error detected on LW migration)"orwell962019-01-22
| | | | This reverts commit e915b61da6f18efa49b6afacb7e9ca181d59cc5c.
* Correct last commitorwell962019-01-22
|
* Debugging code to trace down path_invalidate within callbacks errororwell962019-01-22
|
* Workaroundorwell962019-01-21
|
* Do not run train steps when path has been deletedorwell962019-01-21
|
* Avoid division through zero in get_accelerationorwell962019-01-21
|
* Index NaN check (tracking obscure error detected on LW migration)orwell962019-01-21
|
* Fix player_to_train_mapping (H#74)orwell962018-12-16
| | | | Entries were not inserted, thus neither damage protection nor teleport-to-train did work
* Fix crashes:orwell962018-12-10
| | | | | 1. when train hit a route, nil access to already cancelled route caused crash 2. fix crash when trying to ensure_init a train that doesn't exist
* Shunt signals (not exactly Ks), along with fixes in other components that ↵orwell962018-12-08
| | | | those rely on
pan class="hl com"> the following reasonable defaults are automatically assumed: main = { free = true, } dst = { free = true, } shunt = { free = false, proceed_as_main = false, } end, } on_rightclick = advtrains.interlocking.signal_rc_handler can_dig = advtrains.interlocking.signal_can_dig after_dig_node = advtrains.interlocking.signal_after_dig (If you need to specify custom can_dig or after_dig_node callbacks, please call those functions anyway!) Important note: If your signal should support external ways to set its aspect (e.g. via mesecons), there are some things that need to be considered: - advtrains.interlocking.signal_get_supposed_aspect(pos) won't respect this - Whenever you change the signal aspect, and that aspect change did not happen through a call to advtrains.interlocking.signal_set_aspect(pos, asp), you are *required* to call this function: advtrains.interlocking.signal_on_aspect_changed(pos) in order to notify trains about the aspect change. This function will query get_aspect to retrieve the new aspect. ]]-- local DANGER = { main = { free = false, speed = 0, }, shunt = { free = false, }, dst = { free = false, speed = 0, }, info = {} } advtrains.interlocking.DANGER = DANGER local function fillout_aspect(asp) if not asp.main then asp.main = { free = true, } end if not asp.dst then asp.dst = { free = true, } end if not asp.shunt then asp.shunt = { free = false, proceed_as_main = false, } end if not asp.info then asp.info = {} end end function advtrains.interlocking.update_signal_aspect(tcbs) if tcbs.signal then local asp = tcbs.aspect or DANGER advtrains.interlocking.signal_set_aspect(tcbs.signal, asp) end end function advtrains.interlocking.signal_can_dig(pos) return not advtrains.interlocking.db.get_sigd_for_signal(pos) end function advtrains.interlocking.signal_after_dig(pos) -- clear influence point advtrains.interlocking.db.clear_ip_by_signalpos(pos) end function advtrains.interlocking.signal_set_aspect(pos, asp) fillout_aspect(asp) local node=advtrains.ndb.get_node(pos) local ndef=minetest.registered_nodes[node.name] if ndef and ndef.advtrains and ndef.advtrains.set_aspect then ndef.advtrains.set_aspect(pos, node, asp) advtrains.interlocking.signal_on_aspect_changed(pos) end end -- should be called when aspect has changed on this signal. function advtrains.interlocking.signal_on_aspect_changed(pos) local ipts, iconn = advtrains.interlocking.db.get_ip_by_signalpos(pos) if not ipts then return end local ipos = minetest.string_to_pos(ipts) local tns = advtrains.occ.get_trains_over(ipos) for id, sidx in pairs(tns) do -- local train = advtrains.trains[id] --if train.index <= sidx then minetest.after(0, advtrains.invalidate_path, id) --end end end function advtrains.interlocking.signal_rc_handler(pos, node, player, itemstack, pointed_thing) local pname = player:get_player_name() local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos) if sigd then advtrains.interlocking.show_signalling_form(sigd, pname) else local ndef = minetest.registered_nodes[node.name] if ndef.advtrains and ndef.advtrains.set_aspect then -- permit to set aspect manually minetest.show_formspec(pname, "at_il_sigasp_"..minetest.pos_to_string(pos), "field[aspect;Set Aspect ('A' to assign IP);D0D0D]") else --static signal - only IP advtrains.interlocking.show_ip_form(pos, pname) end end end minetest.register_on_player_receive_fields(function(player, formname, fields) local pname = player:get_player_name() local pts = string.match(formname, "^at_il_sigasp_(.+)$") local pos if pts then pos = minetest.string_to_pos(pts) end if pos and fields.aspect then if fields.aspect == "A" then advtrains.interlocking.show_ip_form(pos, pname) return end local mfs, msps, dfs, dsps, shs = string.match(fields.aspect, "^([FD])([-0-9]+)([FD])([-0-9]+)([FD])$") local asp = { main = { free = mfs=="F", speed = tonumber(msps), }, shunt = { free = shs=="F", }, dst = { free = dfs=="F", speed = tonumber(dsps), }, info = { call_on = false, -- Call-on route, expect train in track ahead dead_end = false, -- Route ends on a dead end (e.g. bumper) } } advtrains.interlocking.signal_set_aspect(pos, asp) end end) -- Returns the aspect the signal at pos is supposed to show function advtrains.interlocking.signal_get_supposed_aspect(pos) local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos) if sigd then local tcbs = advtrains.interlocking.db.get_tcbs(sigd) if tcbs.aspect then return tcbs.aspect end end return DANGER; end -- Returns the actual aspect of the signal at position, as returned by the nodedef. -- returns nil when there's no signal at the position function advtrains.interlocking.signal_get_aspect(pos) local node=advtrains.ndb.get_node(pos) local ndef=minetest.registered_nodes[node.name] if ndef and ndef.advtrains and ndef.advtrains.get_aspect then local asp = ndef.advtrains.get_aspect(pos, node) if not asp then asp = DANGER end fillout_aspect(asp) return asp end return nil end -- Returns the "supported_aspects" of the signal at position, as returned by the nodedef. -- returns nil when there's no signal at the position function advtrains.interlocking.signal_get_supported_aspects(pos) local node=advtrains.ndb.get_node(pos) local ndef=minetest.registered_nodes[node.name] if ndef and ndef.advtrains and ndef.advtrains.supported_aspects then local asp = ndef.advtrains.supported_aspects return asp end return nil end local players_assign_ip = {} local function ipmarker(ipos, connid) local node_ok, conns, rhe = advtrains.get_rail_info_at(ipos, advtrains.all_tracktypes) if not node_ok then return end local yaw = advtrains.dir_to_angle(conns[connid].c) -- using tcbmarker here local obj = minetest.add_entity(vector.add(ipos, {x=0, y=0.2, z=0}), "advtrains_interlocking:tcbmarker") if not obj then return end obj:set_yaw(yaw) obj:set_properties({ textures = { "at_il_signal_ip.png" }, }) end -- shows small info form for signal IP state/assignment -- only_notset: show only if it is not set yet (used by signal tcb assignment) function advtrains.interlocking.show_ip_form(pos, pname, only_notset) if not minetest.check_player_privs(pname, "interlocking") then return end local form = "size[7,5]label[0.5,0.5;Signal at "..minetest.pos_to_string(pos).."]" local pts, connid = advtrains.interlocking.db.get_ip_by_signalpos(pos) if pts then form = form.."label[0.5,1.5;Influence point is set at "..pts.."/"..connid.."]" form = form.."button_exit[0.5,2.5; 5,1;set;Move]" form = form.."button_exit[0.5,3.5; 5,1;clear;Clear]" local ipos = minetest.string_to_pos(pts) ipmarker(ipos, connid) else form = form.."label[0.5,1.5;Influence point is not set.]" form = form.."label[0.5,2.0;It is recommended to set an influence point.]" form = form.."label[0.5,2.5;This is the point where trains will obey the signal.]" form = form.."button_exit[0.5,3.5; 5,1;set;Set]" end if not only_notset or not pts then minetest.show_formspec(pname, "at_il_ipassign_"..minetest.pos_to_string(pos), form) end end minetest.register_on_player_receive_fields(function(player, formname, fields) local pname = player:get_player_name() if not minetest.check_player_privs(pname, {train_operator=true, interlocking=true}) then return end local pts = string.match(formname, "^at_il_ipassign_([^_]+)$") local pos if pts then pos = minetest.string_to_pos(pts) end if pos then if fields.set then advtrains.interlocking.signal_init_ip_assign(pos, pname) elseif fields.clear then advtrains.interlocking.db.clear_ip_by_signalpos(pos) end end end) -- inits the signal IP assignment process function advtrains.interlocking.signal_init_ip_assign(pos, pname) if not minetest.check_player_privs(pname, "interlocking") then minetest.chat_send_player(pname, "Insufficient privileges to use this!") return end --remove old IP --advtrains.interlocking.db.clear_ip_by_signalpos(pos) minetest.chat_send_player(pname, "Configuring Signal: Please look in train's driving direction and punch rail to set influence point.") players_assign_ip[pname] = pos end minetest.register_on_punchnode(function(pos, node, player, pointed_thing) local pname = player:get_player_name() if not minetest.check_player_privs(pname, "interlocking") then return end -- IP assignment local signalpos = players_assign_ip[pname] if signalpos then if vector.distance(pos, signalpos)<=50 then local node_ok, conns, rhe = advtrains.get_rail_info_at(pos, advtrains.all_tracktypes) if node_ok and #conns == 2 then local yaw = player:get_look_horizontal() local plconnid = advtrains.yawToClosestConn(yaw, conns) -- add assignment if not already present.