News:

Simutrans.com Portal
Our Simutrans site. You can find everything about Simutrans from here.

New feature: download-only mode

Started by victor_18993, July 12, 2026, 04:28:14 PM

Previous topic - Next topic

0 Members and 4 Guests are viewing this topic.

victor_18993

[EN]

LINK POST

Coming back to this old thread: rather than the full load/unload-per-wagon and route
whitelist system, I implemented only the narrow piece that was said to be acceptable
here - a per-stop "no load" flag in the schedule (the stop still unloads, it
just does not pick anything up):

Quote"'Nur Aufladen' wird es im Fahrplan sicher nicht geben, nur 'Nicht aufladen'."

So this is exactly the "Nicht Beladen" stop, nothing more - no "load only", no
per-wagon control, no whitelist, and the goods pathfinder is untouched.

How it works
  • A new [tt]bool no_load[/tt] on [tt]schedule_entry_t[/tt].
  • In [tt]convoi_t::hat_gehalten()[/tt] the loading phase is skipped when the current
    entry has the flag (mirroring the existing convoy-wide [tt]no_load[/tt]); unloading is
    unchanged, and [tt]loading_limit[/tt] is forced to 0 so the convoy does not wait for a
    load that will never come.
  • The checkbox reuses the existing [tt]"no load"[/tt] text, which already translates
    to "Unload only" in English ([tt]text/en.tab[/tt]) and is localised in every
    language, so no new translation string is needed.

Compatibility
Savegame is bumped ([tt]SIM_SAVE_MINOR[/tt]) and the field is guarded by the version,
so old saves load with the flag off. The schedule text serialisation
([tt]sscanf/sprintf_schedule[/tt], used to apply schedules to convoys and over the
network) is extended from 5 to an optional 6th value in a backward-compatible way, so
old-format strings still parse.

Tested
Added an automated regression test ([tt]test_transport_freight_no_load[/tt]): a pickup
stop flagged "no load" is served by a convoy and the freight is verified to stay put
(nothing loaded, departed or delivered). Full suite passes (202/202); with the guard
removed the new test fails as expected, so it really covers the behaviour.

Patch attached. If you would rather have a different label or place the checkbox
elsewhere in the schedule window, just say so.

[ES]

Retomo este hilo antiguo: en lugar del sistema completo de carga/descarga por vagón y
whitelist de rutas, implementé solo la pieza acotada que aquí se dio por aceptable - un
flag "no load" por parada en el horario (la parada sigue descargando; solo que
no recoge nada):

Quote"'Nur Aufladen' wird es im Fahrplan sicher nicht geben, nur 'Nicht aufladen'."

Es exactamente la parada "Nicht Beladen", nada más - sin "solo cargar", sin control por
vagón, sin whitelist, y sin tocar el pathfinder de mercancías.

Cómo funciona
  • Un nuevo [tt]bool no_load[/tt] en [tt]schedule_entry_t[/tt].
  • En [tt]convoi_t::hat_gehalten()[/tt] se salta la fase de carga cuando la entrada
    actual tiene el flag (espejando el [tt]no_load[/tt] de convoy que ya existe); la
    descarga no cambia, y se fuerza [tt]loading_limit[/tt] a 0 para que el convoy no espere
    una carga que nunca va a llegar.
  • El checkbox reutiliza la cadena existente [tt]"no load"[/tt], que ya se traduce como
    "Unload only" en inglés ([tt]text/en.tab[/tt]) y está localizada en todos los
    idiomas, así que no hace falta ninguna traducción nueva.

Compatibilidad
Se sube la versión de savegame ([tt]SIM_SAVE_MINOR[/tt]) y el campo va protegido por la
versión, así que las partidas viejas cargan con el flag desactivado. El serializado de
texto del horario ([tt]sscanf/sprintf_schedule[/tt], que se usa para aplicar horarios a
los convoyes y por la red) se extiende de 5 a un 6º valor opcional de forma
retrocompatible, así que las cadenas en formato viejo siguen parseando.

Probado
Añadí un test de regresión automatizado ([tt]test_transport_freight_no_load[/tt]): una
parada de recogida marcada "no load" es servida por un convoy y se comprueba que la
mercancía se queda (no se carga, ni sale, ni se entrega). La suite completa pasa
(202/202); quitando la guarda, el test nuevo falla como se espera, así que cubre de
verdad el comportamiento.

Parche adjunto. Si prefieres otra etiqueta o colocar el checkbox en otro sitio de la
ventana de horario, dilo.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

prissi

Unfortunately, all the logic from simhalt is uncomplete. The comnoiv should be still listed for a stop so one gets arrival times (but no departure times) but it is not added to connections. Otherwise, the connection is still existing and accepts goods and passengers.

victor_18993

Quote from: prissi on July 13, 2026, 01:45:32 PMUnfortunately, all the logic from simhalt is uncomplete. The comnoiv should be still listed for a stop so one gets arrival times (but no departure times) but it is not added to connections. Otherwise, the connection is still existing and accepts goods and passengers.

[EN]
Thanks, I understand the missing part now.
The current patch only prevents the physical loading operation in
convoi_t::hat_gehalten(), but the halt routing data still advertises the convoy as a usable outgoing connection. Therefore, passengers and goods may still route to the stop expecting to board a convoy that will never load them.
I will review the
simhalt connection registration logic so that a
no_load schedule entry:
  • remains registered as an arrival, allowing arrival times and unloading;
  • is not registered as a usable departure;
  • does not create an outgoing connection from that halt;
  • still allows passengers or goods already inside the convoy to continue through the stop.
I will also add regression coverage for routing, not only for the loading operation itself.


[ES]
Gracias, ahora entiendo la parte que falta.
El parche actual únicamente impide la operación física de carga en
convoi_t::hat_gehalten(), pero los datos de enrutamiento de la parada siguen anunciando el convoy como una conexión de salida utilizable. Por ello, los pasajeros y mercancías todavía pueden dirigirse a la parada esperando subir a un convoy que nunca los cargará.
Revisaré la lógica de registro de conexiones en
simhalt para que una entrada de horario con
no_load:
  • siga registrada como llegada, permitiendo mostrar la hora de llegada y descargar;
  • no se registre como una salida utilizable;
  • no genere una conexión de salida desde esa parada;
  • siga permitiendo que los pasajeros o mercancías que ya están dentro del convoy continúen a través de la parada.
También añadiré una prueba de regresión sobre el enrutamiento, no solo sobre la operación de carga.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

victor_18993

Quote from: prissi on July 13, 2026, 01:45:32 PMUnfortunately, all the logic from simhalt is uncomplete. The comnoiv should be still listed for a stop so one gets arrival times (but no departure times) but it is not added to connections. Otherwise, the connection is still existing and accepts goods and passengers.

You were right: preventing the convoy from loading was only half of the job.

I had stopped the convoy from loading, but I had not stopped the halt from
advertising that convoy as a usable connection.

Goods could therefore still find a route, travel to the halt, and wait there
for a service that would never pick them up. That is worse than having no
service at all, because the stranded goods can also congest the halt. It is
exactly the kind of cascade that this feature is intended to prevent.

The uncomfortable part is that my own test was asserting the bug.

It checked:

    get_freight_to_halt(...) == 18

In other words: "the 18 tonnes have a route and are waiting here."

I had interpreted that as proof that the feature worked. The test now asserts
the opposite.


THE TWO HALVES OF THE FIX

1. simhalt.cc — rebuild_connections()

When rebuilding its connections, a halt finds itself in the schedule and then
advertises a connection to every subsequent stop. Previously, it never checked
whether goods or passengers were actually allowed to board at that particular
schedule entry.

There is now a `loads_here` value, read from the current schedule entry. If the
entry does not allow loading, no outgoing connection is inserted for that
visit.

The flag belongs to the visit, not to the halt itself. The same schedule may
visit one halt more than once and permit loading only on the second visit.
Therefore, the value must be read again whenever the schedule walk returns to
that halt.

I deliberately did not modify `is_transfer`.

As the existing comment says, the transfer flag is used to accelerate route
searches by distinguishing transfer and non-transfer halts. The router follows
the actual connection graph, not the transfer flag itself.

Leaving it unchanged is therefore the conservative option. A halt at which one
convoy does not load can still be a perfectly valid transfer point for other
lines.


2. simconvoi.cc — set_schedule()

While looking for the first problem, I found a second one that a player would
encounter immediately:

    if( !f->matches(welt, schedule) ) {
        changed = true;
        ...
    }

`schedule_t::matches()` compares the stops but deliberately ignores values such
as minimum loading and waiting time. That is appropriate when determining
whether a convoy still belongs to the same line.

However, changing the `no_load` flag does not change any stop.

As a result:

- `changed` remained false;
- the schedule counter was not incremented;
- the halt connections were not rebuilt.

The convoy would stop loading, but the connection graph would continue routing
goods and passengers to it.

The stops do not need to be unregistered and registered again, but the
connection graph does need to be rebuilt.

The line-editing path was already correct:
`simlinemgmt.cc` increments the schedule counter unconditionally.


THE TESTS

The main test has been rewritten to verify the three behaviours required for
the feature to be correct.

1. A stop at which the convoy loads nothing is not a departure point.

  Freight generated there for a later stop receives no route:
  `generate_goods()` returns 0, and no freight waits at the halt.

  Before the fix, 18 tonnes waited there indefinitely.

2. The convoy can still unload there.

  Coal travelling in the opposite direction boards at a stop where loading is
  allowed, travels to the unload-only stop, and is delivered successfully:

      arrived == 18
      departed == 0

3. Clearing the flag restores the connection.

  The stops and the schedule remain unchanged; only the `no_load` flag is
  cleared. A route becomes available again and the coal departs:

      departed == 18

  This third case catches the missing schedule-counter update in
  `set_schedule()`.


I also verified both halves adversarially, because a test that still passes
after removing the fix proves very little.

- Removing the guard in `rebuild_connections()` makes the test fail with:

      1 == 0

  A route exists again even though the convoy will not pick anything up.

- Removing the schedule-counter update in `set_schedule()` makes the test fail
  with:

      0 == 1

  After clearing the flag, the halt remains unavailable because its
  connections were never rebuilt.


WHAT HAPPENS TO FREIGHT THAT IS ALREADY WAITING?

This consequence is worth stating explicitly because a player may notice it.

Suppose the player enables `no_load` while 18 tonnes of coal are already
waiting at the halt with a route through that convoy.

Once the connections are rebuilt, `reroute_goods()` searches for a new route
for every waiting ware.

- Freight with an alternative route is rerouted.
- Freight with no remaining route is removed and unbooked from the supplying
  factory's in-transit amount.

The goods are therefore discarded if no alternative service exists.

They also disappear silently: I checked the halt statistics, and `noroute`
remains at 0. The goods are removed from the waiting array without changing
the halt's no-route counter.

This behaviour is not introduced by the patch. It is the existing Simutrans
behaviour whenever waiting goods lose their last valid route; deleting the
last line serving a halt produces the same result.

However, because enabling `no_load` can trigger it, I added a separate
regression test:

    test_transport_freight_no_load_strands_waiting_freight

If these discarded goods should instead be recorded as "no route" so that the
player can see what happened, that would be a small separate change and should
probably be discussed independently.


Full test suite: 202/202 passed.

Updated patch attached.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

prissi

Sorry, this is a large patch and I have little time to review and test as aspect, like the departing display in halt_info.cc (which should only show arrival times for instance). I plan to do a release this weekend, so I will test its integration after that.

There are already quite big changes in code since last version, so I would first get those out before working on the next big thing.

victor_18993

#5
Thanks, that makes sense.
I'll leave the patch as is until the release to avoid creating unnecessary conflicts with current code changes.
After the release, I'll update/rebase it to the new version and review it.

halt_info.cc

as well. With a


no_load

During the visit, the convoy must remain visible as an arrival but must not appear as a usable departure from that stop.
I'm in no rush. Thanks for taking the time to review and test the integration after the release.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

Isaac Eiland-Hall

Brief reminder to provide [EN] pretty please :)

victor_18993

En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)