Skip to content

Instantly share code, notes, and snippets.

@Lupus
Created July 22, 2025 08:56
Show Gist options
  • Select an option

  • Save Lupus/d6e81c0b9d10ab73ff34ab2c5a4c9eae to your computer and use it in GitHub Desktop.

Select an option

Save Lupus/d6e81c0b9d10ab73ff34ab2c5a4c9eae to your computer and use it in GitHub Desktop.

Revisions

  1. Lupus created this gist Jul 22, 2025.
    227 changes: 227 additions & 0 deletions train_data.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,227 @@
    -- Get train information from station
    function getTrainData()
    local trains = {}

    -- Get the track graph from the station
    local success, trackGraph = pcall(function() return station:getTrackGraph() end)

    if success and trackGraph then
    -- Get all trains in the track graph
    local success2, trainList = pcall(function() return trackGraph:getTrains() end)

    if success2 and trainList then
    -- Process each train
    for i, train in ipairs(trainList) do
    local trainInfo = {
    name = "Train " .. i,
    destination = "Unknown",
    status = "In Network",
    statusColor = COLOR_TRANSIT,
    cars = 0,
    cargo = "Unknown",
    isManual = false -- Default to auto
    }

    -- Try to get train name
    local nameSuccess, name = pcall(function() return train:getName() end)
    if nameSuccess and name and name ~= "" then
    trainInfo.name = name
    end

    -- Try to get destination from time table
    local destSuccess = false
    local ttSuccess, timeTable = pcall(function() return train:getTimeTable() end)
    if ttSuccess and timeTable then
    -- Get current stop index
    local currentStopSuccess, currentStopIdx = pcall(function() return timeTable:getCurrentStop() end)
    if currentStopSuccess and currentStopIdx then
    -- Get the stop at that index
    local stopSuccess, stop = pcall(function() return timeTable:getStop(currentStopIdx) end)
    if stopSuccess and stop then
    -- Get station from stop
    if stop and stop.station then
    -- Get station name
    local stationNameSuccess, stationName = pcall(function() return stop.station.name end)
    if stationNameSuccess and stationName then
    trainInfo.destination = stationName
    destSuccess = true
    end
    end
    end
    end
    end

    -- If no destination found, check if train has time table
    if not destSuccess then
    local hasTimeTableSuccess, hasTimeTable = pcall(function() return train.hasTimeTable end)
    if hasTimeTableSuccess and hasTimeTable then
    trainInfo.destination = "No stops"
    else
    trainInfo.destination = "No schedule"
    end
    end

    -- Try to get train vehicles and cargo details
    local vehicleSuccess, vehicles = pcall(function() return train:getVehicles() end)
    if vehicleSuccess and vehicles then
    trainInfo.cars = #vehicles

    -- Collect cargo information from all vehicles
    local cargoMap = {} -- Map of item type hash to count
    local typeMap = {} -- Map of item type hash to type object
    local totalItems = 0
    local hasInventory = false

    for vIdx, vehicle in ipairs(vehicles) do
    if vIdx > 5 then
    break -- Limit to first 5 vehicles
    end

    local invSuccess, inventories = pcall(function() return vehicle:getInventories() end)
    if invSuccess and inventories then
    for invIdx, inv in ipairs(inventories) do
    if invIdx > 2 then
    break -- Only check first 2 inventories per vehicle
    end

    -- Get item count
    local countSuccess, count = pcall(function() return inv.itemCount end)
    if countSuccess and count then
    totalItems = totalItems + count
    hasInventory = true
    end

    -- Try to get individual items
    local sizeSuccess, invSize = pcall(function() return inv.size end)
    if sizeSuccess and invSize then
    local maxSlots = math.min(invSize, 10) -- Only check first 10 slots
    for slot = 0, maxSlots - 1 do
    local stackSuccess, stack = pcall(function() return inv:getStack(slot) end)
    if stackSuccess and stack then
    -- Access the item type through the proper chain
    local typeSuccess = false
    local itemType = nil
    local itemCount = 0

    -- Try to get stack count
    local countSuccess, stackCount = pcall(function() return stack.count end)
    if countSuccess and stackCount and stackCount > 0 then
    itemCount = stackCount

    -- Try to get item and then type
    local itemSuccess, item = pcall(function() return stack.item end)
    if itemSuccess and item then
    typeSuccess, itemType = pcall(function() return item.type end)
    end

    -- If we have a valid item type with count > 0
    if typeSuccess and itemType then
    -- Get the hash of the item type
    local hashSuccess, typeHash = pcall(function() return itemType.hash end)
    if hashSuccess and typeHash then
    -- Store count by hash
    cargoMap[typeHash] = (cargoMap[typeHash] or 0) + itemCount
    -- Store type object for later name lookup
    typeMap[typeHash] = itemType
    end
    end
    end
    end
    end
    end
    end
    end
    end

    -- Format cargo display
    if hasInventory then
    if totalItems == 0 then
    trainInfo.cargo = "Empty"
    else
    -- Convert cargo map to list with names
    local cargoItems = {}

    for typeHash, count in pairs(cargoMap) do
    local itemType = typeMap[typeHash]
    if itemType then
    -- Try to get the item name
    local nameSuccess, itemName = pcall(function() return itemType.name end)
    local displayName = "Unknown"

    if nameSuccess and itemName then
    displayName = tostring(itemName)
    -- Truncate if too long
    if #displayName > 15 then
    displayName = string.sub(displayName, 1, 13) .. ".."
    end
    end

    table.insert(cargoItems, {
    name = displayName,
    count = count
    })
    end
    end

    -- Sort by count (descending)
    table.sort(cargoItems, function(a, b)
    return a.count > b.count
    end)

    -- Format cargo display
    local cargoList = {}
    for idx, item in ipairs(cargoItems) do
    if idx > 3 then break end -- Show only top 3 items
    table.insert(cargoList, item.name .. ": " .. formatNumber(item.count))
    end

    if #cargoList > 0 then
    trainInfo.cargo = table.concat(cargoList, ", ")
    if #cargoItems > 3 then
    trainInfo.cargo = trainInfo.cargo .. " ..."
    end
    else
    -- Fallback if we couldn't get item details
    trainInfo.cargo = formatNumber(totalItems) .. " items"
    end
    end
    else
    trainInfo.cargo = "No inventory"
    end
    end

    -- Try to get train's self-driving status
    local selfDrivingSuccess, selfDriving = pcall(function() return train.isSelfDriving end)
    if selfDrivingSuccess then
    if not selfDriving then
    trainInfo.status = "Manual"
    trainInfo.statusColor = COLOR_MANUAL
    trainInfo.isManual = true
    end
    else
    -- If we can't determine self-driving status, check other indicators
    -- Check if player driven
    local playerDrivenSuccess, isPlayerDriven = pcall(function() return train.isPlayerDriven end)
    if playerDrivenSuccess and isPlayerDriven then
    trainInfo.status = "Manual"
    trainInfo.statusColor = COLOR_MANUAL
    trainInfo.isManual = true
    end
    end

    -- Try to check if train is docked
    local dockedSuccess, isDocked = pcall(function() return train.isDocked end)
    if dockedSuccess and isDocked then
    trainInfo.status = "Docked"
    trainInfo.statusColor = COLOR_DOCKED

    -- If docked at our station, mark it
    if trainInfo.destination == station.name then
    trainInfo.status = "Docked Here"
    end
    end

    table.insert(trains, trainInfo)
    end
    end
    end