changeset 10170:888c46c8f633 draft

(svn r14362) -Fix (r3403): Also connect multiheaded parts in free wagon chains.
author frosch <frosch@openttd.org>
date Sat, 20 Sep 2008 10:53:08 +0000
parents bb8afd0513a0
children 30dfce0ba15d
files src/train_cmd.cpp
diffstat 1 files changed, 44 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -4434,8 +4434,23 @@
 	}
 
 	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
-			for (Vehicle *u = v; u != NULL; u = u->Next()) {
+		if (v->type == VEH_TRAIN) {
+			/* Two ways to associate multiheaded parts to each other:
+			 * sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>..
+			 * bracket-matching:    Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>..
+			 *
+			 * Note: Old savegames might contain chains which do not comply with these rules, e.g.
+			 *   - the front and read parts have invalid orders
+			 *   - different engine types might be combined
+			 *   - there might be different amounts of front and rear parts.
+			 *
+			 * Note: The multiheaded parts need to be matched exactly like they are matched on the server, else desyncs will occur.
+			 *   This is why two matching strategies are needed.
+			 */
+
+			bool sequential_matching = IsFrontEngine(v);
+
+			for (Vehicle *u = v; u != NULL; u = GetNextVehicle(u)) {
 				if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
 
 				if (IsMultiheaded(u)) {
@@ -4445,14 +4460,35 @@
 						u->spritenum--;
 					}
 
+					/* Find a matching back part */
+					EngineID eid = u->engine_type;
 					Vehicle *w;
-					for (w = u->Next(); w != NULL && (w->engine_type != u->engine_type || w->u.rail.other_multiheaded_part != NULL); w = GetNextVehicle(w)) {}
+					if (sequential_matching) {
+						for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) {
+							if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue;
+
+							/* we found a car to partner with this engine. Now we will make sure it face the right way */
+							if (IsTrainEngine(w)) {
+								ClearTrainEngine(w);
+								w->spritenum++;
+							}
+							break;
+						}
+					} else {
+						uint stack_pos = 0;
+						for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) {
+							if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue;
+
+							if (IsTrainEngine(w)) {
+								stack_pos++;
+							} else {
+								if (stack_pos == 0) break;
+								stack_pos--;
+							}
+						}
+					}
+
 					if (w != NULL) {
-						/* we found a car to partner with this engine. Now we will make sure it face the right way */
-						if (IsTrainEngine(w)) {
-							ClearTrainEngine(w);
-							w->spritenum++;
-						}
 						w->u.rail.other_multiheaded_part = u;
 						u->u.rail.other_multiheaded_part = w;
 					} else {