aboutsummaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAge
...
* Add Automatic Routesetting UIorwell962019-01-09
| | | | Settings have no effect so far
* Add "routingcode" propertyorwell962019-01-09
| | | | Used for ARS and stop points
* Make track protection radius configurableorwell962018-12-18
|
* 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 144e1fc4e01741f8cdd5a579ae84cde85c420d78 (there's no self in one of the ↵orwell962018-12-10
| | | | instructions)
* 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
* Change get_inventory_formspec API - add invname parameterorwell962018-12-10
|
* Signs (static signals)orwell962018-12-08
|
* Shunt signals (not exactly Ks), along with fixes in other components that ↵orwell962018-12-08
| | | | those rely on
* Apply speed restriction 0.5 indexes later, do not cap tarvelocity by ↵orwell962018-12-04
| | | | speed_restriction
* Do not set speed_restriction for nprorwell962018-12-04
|
* no debugpringorwell962018-11-29
|
* Added on_train_approach callback, non-permanent external LZB brakepoints and ↵orwell962018-11-29
| | | | | | basis for "stop rails" Stop rails ATM use the aforementioned things to add a pointwise "2" speed restriction. Seems to work.
* Implement new position encoding function and benchmark itorwell962018-11-29
| | | | | This shall replace all "pos_to_string" hashes in the long term. Performs a bit better than pos_to_string (but still worse than the "nested tables" layout the nodedb uses (an unmatched open parenthesis leaves a tension that will stay all day... 2 do even more
* Fix discouple positioning when wagon was just loadedorwell962018-11-20
|
* Add set_aspect functionorwell962018-11-20
| | | | | This allows incorporating signals implementing the signal API in LuaAutomation projects Note that it circumvents TCB assignments (a signal assigned to a TCB can be set to green even if no route is set
* Add Note regarding pcnaming and interlocking signalsorwell962018-11-20
|
* Remove superfluous "tarvelocity" assignmentsorwell962018-11-20
|
* Make "Line" property accessible from OBC and gettable via LATC, change ↵orwell962018-11-20
| | | | subway wagon texture handling
* Remove debug printorwell962018-11-20
|
* Permit basic signal aspect settingorwell962018-11-19
| | | | (basically only usable with Ks signals, because they're the only signals supporting slow move and/or shunt move
* Fix protection regarding tracks (track_builder and railway_operator) and ↵orwell962018-11-12
| | | | documentation on privileges
* Increase savefile version to 2orwell962018-11-10
| | | | (Master downgrade protection)
* Remove "couple locks" and apply protection to the actual coupling process, ↵orwell962018-11-10
| | | | and fix permissions on that
* Ks signals emit some lightorwell962018-11-05
| | | | Else you can't see them in the dark...
* Allow pcnaming for any signalsorwell962018-11-05
|
* Replace "Allow accelereting train towards signal"orwell962018-10-30
| | | | This is a better implementation of the same goal. The last commit caused trains to overrun the IP sometimes. Haven't noticed so far with this approach
* No static_save for discouple entitiesorwell962018-10-30
|
* Make fillout_aspect also fill "info" fieldorwell962018-10-30
|
* Do not allow static signals for routesettingorwell962018-10-30
|
* Fix Ks signals not setting aspect (missing set_aspect function)orwell962018-10-30
|
* Document fix 0a982b6356b2f4b6a28e74f9f90c4f584169a96dorwell962018-10-29
| | | | Add comment that explains why fix was necessary
* Actually set last_connid to 1, to prevent warningorwell962018-10-29
|
* Do not print "couldn't determine section" warning when all traverser ends ↵orwell962018-10-29
| | | | were end-of-track
* Handle the case that a train is not initialized (train_ensure_init returns ↵orwell962018-10-29
| | | | | | nil/false) Fixes H#72
* Allow to accelerate trains slowly towards red signals from stand.orwell962018-10-29
| | | | Previously, it was impossible to accelerate a standing train once it was ~10m in front of a red signal.
* Fix typo in signal assignment, causing crashorwell962018-10-29
|
* Miscellaneous routesetting fixesorwell962018-10-29
| | | | | | | - Move handling of "route_committed" to the routesetting function - Put aspect in every TCBS on the way - Add "route_origin" to TCBS fields to prevent subroute cancelling - Cancel entire route when another train enters from the wrong TCB
* atdump() to treat certain values specialorwell962018-10-29
|
* Fix signal_get_aspect()orwell962018-10-29
| | | | Had a series of bugs as result, like auto-clearing IPs and not-working lzb
* Small fixes which do not have any effectorwell962018-10-29
|
* Add Interlocking Tool to inspect route locksorwell962018-10-26
|
* Add "Reset track section" functionorwell962018-10-26
|
* Complete Ks Main signalsorwell962018-10-26
|
* Fix demo signalsorwell962018-10-25
|
* Add doc for supported_aspects, improve other doc and aspect autofillorwell962018-10-25
|
* Display route_rsn when denying routesetting by subroute locked.orwell962018-10-25
|
* Fix node database ATC rail bugorwell962018-10-17
| | | | | | | After successfully registering newly-placed ATC rails in the nodedb, the rail's after_place_node() callback (local apn_func()) immediately cleared it again by passing a "node" object that was actually a player object and thus had no "name" or "param2" to ndb.update(), which it handled how it should not in this situation. Since those ndb.update calls were unnecessary anyways, I removed them completely.
* Prevent any user control except "Brake" when an ATC override is presentorwell962018-10-17
| | | | Solves the problem of accidentally breaking atc-driven trains
* Improve ATC-LZB-User control interaction, smoothen LZB control operationsorwell962018-10-17
| | | | (prevent flickering view when atc battles against lzb)
n class="hl opt">.atprint_context_tid then advtrains.path_print(advtrains.trains[advtrains.atprint_context_tid], atdebug) atwarn(advtrains.trains[advtrains.atprint_context_tid].debug) end end) if not succ then reload_saves() else return return1, return2, return3, return4 end end advtrains.modpath = minetest.get_modpath("advtrains") --Advtrains dump (special treatment of pos and sigd) function atdump(t, intend) local str if type(t)=="table" then if t.x and t.y and t.z then str=minetest.pos_to_string(t) elseif t.p and t.s then -- interlocking sigd str="S["..minetest.pos_to_string(t.p).."/"..t.s.."]" elseif advtrains.lines and t.s and t.m then -- RwT str=advtrains.lines.rwt.to_string(t) else str="{" local intd = (intend or "") .. " " for k,v in pairs(t) do if type(k)~="string" or not string.match(k, "^path[_]?") then -- do not print anything path-related str = str .. "\n" .. intd .. atdump(k, intd) .. " = " ..atdump(v, intd) end end str = str .. "\n" .. (intend or "") .. "}" end elseif type(t)=="boolean" then if t then str="true" else str="false" end elseif type(t)=="function" then str="<function>" elseif type(t)=="userdata" then str="<userdata>" else str=""..t end return str end function advtrains.print_concat_table(a) local str="" local stra="" local t for i=1,20 do t=a[i] if t==nil then stra=stra.."nil " else str=str..stra stra="" str=str..atdump(t).." " end end return str end atprint=function() end atlog=function(t, ...) local text=advtrains.print_concat_table({t, ...}) minetest.log("action", "[advtrains]"..text) end atwarn=function(t, ...) local text=advtrains.print_concat_table({t, ...}) minetest.log("warning", "[advtrains]"..text) minetest.chat_send_all("[advtrains] -!- "..text) end sid=function(id) if id then return string.sub(id, -6) end end --ONLY use this function for temporary debugging. for consistent debug prints use atprint atdebug=function(t, ...) local text=advtrains.print_concat_table({t, ...}) minetest.log("action", "[advtrains]"..text) minetest.chat_send_all("[advtrains]"..text) end if minetest.settings:get_bool("advtrains_enable_debugging") then atprint=function(t, ...) local context=advtrains.atprint_context_tid or "" if not context then return end local text=advtrains.print_concat_table({t, ...}) advtrains.drb_record(context, text) --atlog("@@",advtrains.atprint_context_tid,t,...) end dofile(advtrains.modpath.."/debugringbuffer.lua") end function assertt(var, typ) if type(var)~=typ then error("Assertion failed, variable has to be of type "..typ) end end dofile(advtrains.modpath.."/helpers.lua"); --dofile(advtrains.modpath.."/debugitems.lua"); advtrains.meseconrules = {{x=0, y=0, z=-1}, {x=1, y=0, z=0}, {x=-1, y=0, z=0}, {x=0, y=0, z=1}, {x=1, y=1, z=0}, {x=1, y=-1, z=0}, {x=-1, y=1, z=0}, {x=-1, y=-1, z=0}, {x=0, y=1, z=1}, {x=0, y=-1, z=1}, {x=0, y=1, z=-1}, {x=0, y=-1, z=-1}, {x=0, y=-2, z=0}} advtrains.fpath=minetest.get_worldpath().."/advtrains" dofile(advtrains.modpath.."/path.lua") dofile(advtrains.modpath.."/trainlogic.lua") dofile(advtrains.modpath.."/trainhud.lua") dofile(advtrains.modpath.."/trackplacer.lua") dofile(advtrains.modpath.."/copytool.lua") dofile(advtrains.modpath.."/tracks.lua") dofile(advtrains.modpath.."/occupation.lua") dofile(advtrains.modpath.."/atc.lua") dofile(advtrains.modpath.."/wagons.lua") dofile(advtrains.modpath.."/protection.lua") dofile(advtrains.modpath.."/trackdb_legacy.lua") dofile(advtrains.modpath.."/nodedb.lua") dofile(advtrains.modpath.."/couple.lua") dofile(advtrains.modpath.."/signals.lua") dofile(advtrains.modpath.."/misc_nodes.lua") dofile(advtrains.modpath.."/crafting.lua") dofile(advtrains.modpath.."/craft_items.lua") dofile(advtrains.modpath.."/log.lua") dofile(advtrains.modpath.."/passive.lua") if mesecon then dofile(advtrains.modpath.."/p_mesecon_iface.lua") end dofile(advtrains.modpath.."/lzb.lua") --load/save -- backup variables, used if someone should accidentally delete a sub-mod local MDS_interlocking, MDS_lines advtrains.fpath=minetest.get_worldpath().."/advtrains" dofile(advtrains.modpath.."/log.lua") function advtrains.read_component(name) local path = advtrains.fpath.."_"..name minetest.log("action", "[advtrains] loading "..path) local file, err = io.open(path, "r") if not file then minetest.log("warning", " Failed to read advtrains save data from file "..path..": "..(err or "Unknown Error")) minetest.log("warning", " (this is normal when first enabling advtrains on this world)") return end local tbl = minetest.deserialize(file:read("*a")) file:close() return tbl end function advtrains.avt_load() -- check for new, split advtrains save file local version = advtrains.read_component("version") local tbl if version and version == 3 then -- we are dealing with the new, split-up system minetest.log("action", "[advtrains] loading savefiles version 3") local il_save = { tcbs = true, ts = true, signalass = true, rs_locks = true, rs_callbacks = true, influence_points = true, npr_rails = true, } tbl={ trains = true, wagon_save = true, ptmap = true, atc = true, ndb = true, lines = true, version = 2, } for i,k in pairs(il_save) do il_save[i] = advtrains.read_component("interlocking_"..i) end for i,k in pairs(tbl) do tbl[i] = advtrains.read_component(i) end tbl["interlocking"] = il_save else local file, err = io.open(advtrains.fpath, "r") if not file then minetest.log("warning", " Failed to read advtrains save data from file "..advtrains.fpath..": "..(err or "Unknown Error")) minetest.log("warning", " (this is normal when first enabling advtrains on this world)") return else tbl = minetest.deserialize(file:read("*a")) file:close() end end if type(tbl) == "table" then if tbl.version then --congrats, we have the new save format. advtrains.trains = tbl.trains --Save the train id into the train table to avoid having to pass id around for id, train in pairs(advtrains.trains) do train.id = id end advtrains.wagons = tbl.wagon_save advtrains.player_to_train_mapping = tbl.ptmap or {} advtrains.ndb.load_data(tbl.ndb) advtrains.atc.load_data(tbl.atc) if advtrains.interlocking then advtrains.interlocking.db.load(tbl.interlocking) else MDS_interlocking = tbl.interlocking end if advtrains.lines then advtrains.lines.load(tbl.lines) else MDS_lines = tbl.lines end --remove wagon_save entries that are not part of a train local todel=advtrains.merge_tables(advtrains.wagon_save) for tid, train in pairs(advtrains.trains) do train.id = tid for _, wid in ipairs(train.trainparts) do todel[wid]=nil end end for wid, _ in pairs(todel) do atwarn("Removing unused wagon", wid, "from wagon_save table.") advtrains.wagon_save[wid]=nil end else --oh no, its the old one... advtrains.trains=tbl --load ATC advtrains.fpath_atc=minetest.get_worldpath().."/advtrains_atc" local file, err = io.open(advtrains.fpath_atc, "r") if not file then local er=err or "Unknown Error" atprint("Failed loading advtrains atc save file "..er) else local tbl = minetest.deserialize(file:read("*a")) if type(tbl) == "table" then advtrains.atc.controllers=tbl.controllers end file:close() end --load wagon saves advtrains.fpath_ws=minetest.get_worldpath().."/advtrains_wagon_save" local file, err = io.open(advtrains.fpath_ws, "r") if not file then local er=err or "Unknown Error" atprint("Failed loading advtrains save file "..er) else local tbl = minetest.deserialize(file:read("*a")) if type(tbl) == "table" then advtrains.wagon_save=tbl end file:close() end end else minetest.log("error", " Failed to deserialize advtrains save data: Not a table!") end end advtrains.save_component = function (tbl, name) -- Saves each component of the advtrains file separately -- -- required for now to shrink the advtrains db to overcome lua -- limitations. local datastr = minetest.serialize(tbl) if not datastr then minetest.log("error", " Failed to serialize advtrains save data!") return end local path = advtrains.fpath.."_"..name local success = minetest.safe_file_write(path, datastr) if not success then minetest.log("error", " Failed to write advtrains save data to file "..path) end end advtrains.avt_save = function(remove_players_from_wagons) --atprint("saving") if remove_players_from_wagons then for w_id, data in pairs(advtrains.wagons) do data.seatp={} end advtrains.player_to_train_mapping={} end local tmp_trains={} for id, train in pairs(advtrains.trains) do --first, deep_copy the train if #train.trainparts > 0 then local v=advtrains.save_keys(train, { "last_pos", "last_connid", "last_frac", "velocity", "tarvelocity", "trainparts", "recently_collided_with_env", "atc_brake_target", "atc_wait_finish", "atc_command", "atc_delay", "door_open", "text_outside", "text_inside", "line", "routingcode", "il_sections", "speed_restriction", "is_shunt", "points_split", "autocouple" }) --then save it tmp_trains[id]=v else atwarn("Train",id,"had no wagons left because of some bug. It is being deleted. Wave it goodbye!") advtrains.remove_train(id) end end for id, wdata in pairs(advtrains.wagons) do local _,proto = advtrains.get_wagon_prototype(wdata) if proto.has_inventory then local inv=minetest.get_inventory({type="detached", name="advtrains_wgn_"..id}) if inv then -- inventory is not initialized when wagon was never loaded -- TOOD: What happens with unloading rails when they don't find the inventory? wdata.ser_inv=advtrains.serialize_inventory(inv) end end -- TODO apply save-keys here too -- TODO temp wdata.dcpl_lock = nil end --versions: -- 1 - Initial new save format. -- 2 - version as of tss branch 11-2018+ local il_save if advtrains.interlocking then il_save = advtrains.interlocking.db.save() else il_save = MDS_interlocking end local ln_save if advtrains.lines then ln_save = advtrains.lines.save() else ln_save = MDS_lines end local save_tbl={ trains = tmp_trains, wagon_save = advtrains.wagons, ptmap = advtrains.player_to_train_mapping, atc = advtrains.atc.save_data(), ndb = advtrains.ndb.save_data(), lines = ln_save, version = 3, } for i,k in pairs(save_tbl) do advtrains.save_component(k,i) end for i,k in pairs(il_save) do advtrains.save_component(k,"interlocking_"..i) end if DUMP_DEBUG_SAVE then local file, err = io.open(advtrains.fpath.."_DUMP", "w") if err then return end file:write(dump(save_tbl)) file:close() local file, err = io.open(advtrains.fpath.."_interlocking_DUMP", "w") if err then return end file:write(dump(il_save)) file:close() end end --## MAIN LOOP ##-- --Calls all subsequent main tasks of both advtrains and atlatc local init_load=false local save_interval=20 local save_timer=save_interval advtrains.mainloop_runcnt=0 local t = 0 minetest.register_globalstep(function(dtime_mt) return advtrains.pcall(function() advtrains.mainloop_runcnt=advtrains.mainloop_runcnt+1 --atprint("Running the main loop, runcnt",advtrains.mainloop_runcnt) --call load once. see advtrains.load() comment if not init_load then advtrains.load() end local dtime if GENERATE_ATRICIFIAL_LAG then dtime = 0.2 if os.clock()<t then return end t = os.clock()+0.2 else --limit dtime: if trains move too far in one step, automation may cause stuck and wrongly braking trains dtime=dtime_mt if dtime>0.2 then atprint("Limiting dtime to 0.2!") dtime=0.2 end end advtrains.mainloop_trainlogic(dtime) if advtrains_itm_mainloop then advtrains_itm_mainloop(dtime) end if atlatc then atlatc.mainloop_stepcode(dtime) atlatc.interrupt.mainloop(dtime) end if advtrains.lines then advtrains.lines.step(dtime) end --trigger a save when necessary save_timer=save_timer-dtime if save_timer<=0 then local t=os.clock() --save advtrains.save() save_timer=save_interval atprintbm("saving", t) end end) end) --if something goes wrong in these functions, there is no help. no pcall here. --## MAIN LOAD ROUTINE ## -- Causes the loading of everything -- first time called in main loop (after the init phase) because luaautomation has to initialize first. function advtrains.load() advtrains.avt_load() --loading advtrains. includes ndb at advtrains.ndb.load_data() if atlatc then atlatc.load() --includes interrupts end if advtrains_itm_init then advtrains_itm_init() end init_load=true no_action=false atlog("[load_all]Loaded advtrains save files") end --## MAIN SAVE ROUTINE ## -- Causes the saving of everything function advtrains.save(remove_players_from_wagons) if not init_load then --wait... we haven't loaded yet?! atwarn("Instructed to save() but load() was never called!") return end advtrains.avt_save(remove_players_from_wagons) --saving advtrains. includes ndb at advtrains.ndb.save_data() if atlatc then atlatc.save() end atprint("[save_all]Saved advtrains save files") --TODO very simple yet hacky workaround for the "green signals" bug advtrains.invalidate_all_paths() end minetest.register_on_shutdown(advtrains.save) -- This chat command provides a solution to the problem known on the LinuxWorks server -- There are many players that joined a single time, got on a train and then left forever -- These players still occupy seats in the trains. minetest.register_chatcommand("at_empty_seats", { params = "", -- Short parameter description description = "Detach all players, especially the offline ones, from all trains. Use only when no one serious is on a train.", -- Full description privs = {train_operator=true, server=true}, -- Require the "privs" privilege to run func = function(name, param) return advtrains.pcall(function() atwarn("Data is being saved. While saving, advtrains will remove the players from trains. Save files will be reloaded afterwards!") advtrains.save(true) reload_saves() end) end, }) -- This chat command solves another problem: Trains getting randomly stuck. minetest.register_chatcommand("at_reroute", { params = "", description = "Delete all train routes, force them to recalculate", privs = {train_operator=true}, -- Only train operator is required, since this is relatively safe. func = function(name, param) return advtrains.pcall(function() advtrains.invalidate_all_paths() return true, "Successfully invalidated train routes" end) end, }) local tot=(os.clock()-lot)*1000 minetest.log("action", "[advtrains] Loaded in "..tot.."ms")