diff --git Makefile Makefile
index 742f04ad1..7dc75a6f8 100644
--- Makefile
+++ Makefile
@@ -593,6 +593,7 @@ SOURCES += src/simutrans/utils/sha1_hash.cc
 SOURCES += src/simutrans/utils/simrandom.cc
 SOURCES += src/simutrans/utils/simstring.cc
 SOURCES += src/simutrans/utils/simthread.cc
+SOURCES += src/simutrans/utils/sync_list.cc
 SOURCES += src/simutrans/utils/unicode.cc
 SOURCES += src/simutrans/vehicle/air_vehicle.cc
 SOURCES += src/simutrans/vehicle/movingobj.cc
diff --git cmake/SimutransSourceList.cmake cmake/SimutransSourceList.cmake
index 7cdd6c7f7..34cfc756f 100644
--- cmake/SimutransSourceList.cmake
+++ cmake/SimutransSourceList.cmake
@@ -308,6 +308,7 @@ target_sources(simutrans PRIVATE
 		src/simutrans/utils/simrandom.cc
 		src/simutrans/utils/simstring.cc
 		src/simutrans/utils/simthread.cc
+		src/simutrans/utils/sync_list.cc
 		src/simutrans/utils/unicode.cc
 		src/simutrans/vehicle/air_vehicle.cc
 		src/simutrans/vehicle/movingobj.cc
diff --git src/simutrans/obj/gebaeude.cc src/simutrans/obj/gebaeude.cc
index 198257643..c632bf189 100644
--- src/simutrans/obj/gebaeude.cc
+++ src/simutrans/obj/gebaeude.cc
@@ -83,7 +83,7 @@ gebaeude_t::gebaeude_t(loadsave_t *file) : obj_t()
 		set_yoff(0);
 	}
 	if(tile  &&  tile->get_phases()>1) {
-		welt->sync_eyecandy.add( this );
+		welt->sync_buildings.add( this );
 		sync = true;
 	}
 }
@@ -124,7 +124,7 @@ gebaeude_t::~gebaeude_t()
 
 	if(sync) {
 		sync = false;
-		welt->sync_eyecandy.remove(this);
+		welt->sync_buildings.remove(this);
 	}
 
 	// tiles might be invalid, if no description is found during loading
@@ -253,7 +253,7 @@ void gebaeude_t::set_tile( const building_tile_desc_t *new_tile, bool start_with
 #ifdef MULTI_THREAD
 			pthread_mutex_lock( &sync_mutex );
 #endif
-			welt->sync_eyecandy.remove(this);
+			welt->sync_buildings.remove(this);
 			sync = false;
 			anim_frame = 0;
 #ifdef MULTI_THREAD
@@ -268,7 +268,7 @@ void gebaeude_t::set_tile( const building_tile_desc_t *new_tile, bool start_with
 #endif
 		anim_frame = sim_async_rand( new_tile->get_phases() );
 		anim_time = 0;
-		welt->sync_eyecandy.add(this);
+		welt->sync_buildings.add(this);
 		sync = true;
 #ifdef MULTI_THREAD
 		pthread_mutex_unlock( &sync_mutex );
diff --git src/simutrans/obj/gebaeude.h src/simutrans/obj/gebaeude.h
index 62c4b26f2..5eac06a3d 100644
--- src/simutrans/obj/gebaeude.h
+++ src/simutrans/obj/gebaeude.h
@@ -19,7 +19,7 @@ class grund_t;
 /**
  * Asynchronous or synchronous animations for buildings.
  */
-class gebaeude_t : public obj_t, sync_steppable
+class gebaeude_t : public obj_t
 {
 private:
 	const building_tile_desc_t *tile;
@@ -138,7 +138,7 @@ public:
 	 * Play animations of animated buildings.
 	 * Count-down to replace construction site image by regular image.
 	 */
-	sync_result sync_step(uint32 delta_t) OVERRIDE;
+	sync_result sync_step(uint32 delta_t);
 
 	/**
 	 * @return Den level (die Ausbaustufe) des Gebaudes
diff --git src/simutrans/obj/leitung2.cc src/simutrans/obj/leitung2.cc
index b26458917..9a39b21f3 100644
--- src/simutrans/obj/leitung2.cc
+++ src/simutrans/obj/leitung2.cc
@@ -656,7 +656,7 @@ senke_t::senke_t(loadsave_t *file) : leitung_t( koord3d::invalid, NULL )
 
 	rdwr( file );
 
-	welt->sync.add(this);
+	welt->sync_senkes.add(this);
 }
 
 
@@ -671,7 +671,7 @@ senke_t::senke_t(koord3d pos, player_t *player) : leitung_t(pos, player)
 
 	player_t::book_construction_costs(player, welt->get_settings().cst_transformer, get_pos().get_2d(), powerline_wt);
 
-	welt->sync.add(this);
+	welt->sync_senkes.add(this);
 }
 
 
@@ -680,7 +680,7 @@ senke_t::~senke_t()
 	// one last final income
 	pay_revenue();
 
-	welt->sync.remove( this );
+	welt->sync_senkes.remove( this );
 	if(fab!=NULL) {
 		fab->remove_transformer_connected(this);
 		fab = NULL;
diff --git src/simutrans/obj/leitung2.h src/simutrans/obj/leitung2.h
index aa70c62c3..cf282e09f 100644
--- src/simutrans/obj/leitung2.h
+++ src/simutrans/obj/leitung2.h
@@ -183,7 +183,7 @@ public:
  * Distribution transformers act as an interface between power networks and
  * and power consuming factories.
  */
-class senke_t : public leitung_t, public sync_steppable
+class senke_t : public leitung_t
 {
 public:
 	static void new_world();
@@ -251,7 +251,7 @@ public:
 	 * Frequency determined by the percentage of power supplied.
 	 * Gives players a visual indication of a power network with insufficient generation.
 	 */
-	sync_result sync_step(uint32 delta_t) OVERRIDE;
+	sync_result sync_step(uint32 delta_t);
 
 	const char *get_name() const OVERRIDE {return "Abspanntransformator";}
 
diff --git src/simutrans/obj/roadsign.cc src/simutrans/obj/roadsign.cc
index a10ae2cfa..175c6b161 100644
--- src/simutrans/obj/roadsign.cc
+++ src/simutrans/obj/roadsign.cc
@@ -62,7 +62,7 @@ roadsign_t::roadsign_t(loadsave_t *file) : obj_t ()
 	}
 	// only traffic light need switches
 	if(  automatic  ) {
-		welt->sync.add(this);
+		welt->sync_roadsigns.add(this);
 	}
 }
 
@@ -94,7 +94,7 @@ roadsign_t::roadsign_t(player_t *player, koord3d pos, ribi_t::ribi dir, const ro
 	automatic = (desc->get_count()>4  &&  desc->get_wtyp()==road_wt)  ||  (desc->get_count()>2  &&  desc->is_private_way());
 	// only traffic light need switches
 	if(  automatic  ) {
-		welt->sync.add(this);
+		welt->sync_roadsigns.add(this);
 	}
 }
 
@@ -120,7 +120,7 @@ roadsign_t::~roadsign_t()
 		}
 	}
 	if(automatic) {
-		welt->sync.remove(this);
+		welt->sync_roadsigns.remove(this);
 	}
 }
 
diff --git src/simutrans/obj/roadsign.h src/simutrans/obj/roadsign.h
index 7ee3d9e3e..7768202e5 100644
--- src/simutrans/obj/roadsign.h
+++ src/simutrans/obj/roadsign.h
@@ -19,7 +19,7 @@ class tool_selector_t;
 /**
  * road sign for traffic (one way minimum speed, traffic lights)
  */
-class roadsign_t : public obj_t, public sync_steppable
+class roadsign_t : public obj_t
 {
 protected:
 	image_id image;
@@ -104,7 +104,7 @@ public:
 	bool is_free_route(uint8 check_dir) const { return desc->is_choose_sign() &&  check_dir == dir; }
 
 	// changes the state of a traffic light
-	sync_result sync_step(uint32) OVERRIDE;
+	sync_result sync_step(uint32);
 
 	// change the phases of the traffic lights
 	uint8 get_ticks_ns() const { return ticks_ns; }
diff --git src/simutrans/obj/sync_steppable.h src/simutrans/obj/sync_steppable.h
index 556d3f6e6..edd987dfa 100644
--- src/simutrans/obj/sync_steppable.h
+++ src/simutrans/obj/sync_steppable.h
@@ -15,18 +15,5 @@ enum sync_result {
 	SYNC_DELETE  ///< delete object and remove from list
 };
 
-/**
- * All synchronously moving things must implement this interface.
- */
-class sync_steppable
-{
-public:
-	/**
-	 * Method for real-time features of an object.
-	 */
-	virtual sync_result sync_step(uint32 delta_t) = 0;
-
-	virtual ~sync_steppable() {}
-};
 
 #endif
diff --git src/simutrans/obj/wolke.cc src/simutrans/obj/wolke.cc
index 67ecc7079..d98ddcc65 100644
--- src/simutrans/obj/wolke.cc
+++ src/simutrans/obj/wolke.cc
@@ -64,7 +64,7 @@ wolke_t::~wolke_t()
 {
 	mark_image_dirty( get_image(), calc_yoff() );
 	if(  insta_zeit != lifetime  ) {
-		welt->sync_way_eyecandy.remove( this );
+		welt->sync_clouds.remove( this );
 	}
 }
 
diff --git src/simutrans/obj/wolke.h src/simutrans/obj/wolke.h
index 9727f57b3..3698e7436 100644
--- src/simutrans/obj/wolke.h
+++ src/simutrans/obj/wolke.h
@@ -24,7 +24,7 @@ class karte_t;
 /**
  * smoke clouds (formerly sync_wolke_t)
  */
-class wolke_t : public obj_no_info_t, public sync_steppable
+class wolke_t : public obj_no_info_t
 {
 private:
 	static vector_tpl<const skin_desc_t *>all_clouds;
@@ -37,6 +37,10 @@ private:
 
 	sint16 calc_yoff() const; // calculate the smoke height using uplift and insta_zeit
 
+public:
+	// padding to increase the from 32 to 40 bytes for sync_step performance reasons. Do not use for data storage.
+	char pad[8];
+
 public:
 	static bool register_desc(const skin_desc_t *desc);
 
@@ -47,7 +51,7 @@ public:
 	wolke_t(koord3d pos, sint8 xoff, sint8 yoff, sint16 hoff, uint16 lifetime, uint16 uplift, const skin_desc_t *cloud );
 	~wolke_t();
 
-	sync_result sync_step(uint32 delta_t) OVERRIDE;
+	sync_result sync_step(uint32 delta_t);
 
 	const char* get_name() const OVERRIDE { return "Wolke"; }
 	typ get_typ() const OVERRIDE { return sync_wolke; }
diff --git src/simutrans/simconvoi.cc src/simutrans/simconvoi.cc
index 040b990ce..f72ee0439 100644
--- src/simutrans/simconvoi.cc
+++ src/simutrans/simconvoi.cc
@@ -206,7 +206,7 @@ DBG_MESSAGE("convoi_t::~convoi_t()", "destroying %d, %p", self.get_id(), this);
 		welt->get_viewport()->set_follow_convoi( convoihandle_t() );
 	}
 
-	welt->sync.remove( this );
+	welt->sync_convois.remove( this );
 	welt->rem_convoi( self );
 
 	// if lineless convoy -> unregister from stops
@@ -1364,7 +1364,7 @@ void convoi_t::step()
 
 		// just waiting for action here
 		case INITIAL:
-			welt->sync.remove(this);
+			welt->sync_convois.remove(this);
 			// FALLTHROUGH
 		case EDIT_SCHEDULE:
 		case NO_ROUTE:
@@ -1548,7 +1548,7 @@ void convoi_t::start()
 		gr->obj_add( fahr[0] );
 
 		// put into sync list
-		welt->sync.add(this);
+		welt->sync_convois.add(this);
 
 		alte_richtung = ribi_t::none;
 		no_load = false;
diff --git src/simutrans/simconvoi.h src/simutrans/simconvoi.h
index ac9878602..da0ff56f7 100644
--- src/simutrans/simconvoi.h
+++ src/simutrans/simconvoi.h
@@ -36,7 +36,7 @@ class cbuffer_t;
 /**
  * Base class for all vehicle consists. Convoys can be referenced by handles, see halthandle_t.
  */
-class convoi_t : public sync_steppable, public overtaker_t
+class convoi_t : public overtaker_t
 {
 public:
 	enum {
@@ -54,7 +54,7 @@ public:
 	/** Constants */
 	enum { default_vehicle_length = 4 };
 
-	enum states {
+	enum states : uint8 {
 		INITIAL,
 		EDIT_SCHEDULE,
 		ROUTING_1,
@@ -80,7 +80,7 @@ private:
 	 * concentrated at the beginning of the structure.
 	 * All computations are for 64bit builds.
 	 *
-	 * We start with a 24 bytes header from virtual tables and data of overtaker_t :(
+	 * We start with a 16 bytes header from virtual tables and data of overtaker_t :(
 	 */
 
 	/**
@@ -97,7 +97,9 @@ private:
 	uint32 last_load_tick;
 
 	states state;
-	// 32 bytes (state is int is 4 byte)
+
+	// if state == LOADING, this is true while unloading
+	bool unloading_state;
 
 	/**
 	* holds id of line with pending update
@@ -105,19 +107,21 @@ private:
 	*/
 	linehandle_t line_update_pending;
 
+	// 28 bytes (state is 1 byte)
+
 	uint16 recalc_data_front  : 1; ///< true, when front vehicle has to recalculate braking
 	uint16 recalc_data        : 1; ///< true, when convoy has to recalculate weights and speed limits
 	uint16 recalc_speed_limit : 1; ///< true, when convoy has to recalculate speed limits
 
 	uint16 previous_delta_v   :12; /// 12 bit! // Stores the previous delta_v value; otherwise these digits are lost during calculation and vehicle do not accelerate
-	// 36 bytes
-	/**
-	 * Overall performance with Gear.
-	 * Used in movement calculations.
-	 */
-	sint32 sum_gear_and_power;
+
+	// 32 bytes
+
+	sint32 akt_speed;         // current speed
+	sint32 akt_speed_soll;    // target speed
 
 	// 40 bytes
+
 	/**
 	 * sum_weight: unloaded weight of all vehicles
 	 * sum_gesamtweight: total weight of all vehicles
@@ -126,9 +130,17 @@ private:
 	 */
 	sint64 sum_gesamtweight;
 	sint64 sum_friction_weight;
+
 	// 56 bytes
-	sint32 akt_speed_soll;    // target speed
-	sint32 akt_speed;         // current speed
+
+	/**
+	 * Overall performance with Gear.
+	 * Used in movement calculations.
+	 */
+	sint32 sum_gear_and_power;
+
+	sint32 sp_soll;           // steps to go
+
 	// 64 bytes
 
 	/**
@@ -138,9 +150,6 @@ private:
 	 */
 	route_t::index_t next_stop_index;
 
-	// if state == LOADING, this is true while unloading
-	bool unloading_state;
-
 	sint32 speed_limit;
 	// needed for speed control/calculation
 	sint32 brake_speed_soll;    // brake target speed
@@ -150,7 +159,6 @@ private:
 	 */
 	sint32 min_top_speed;
 
-	sint32 sp_soll;           // steps to go
 	sint32 max_record_speed; // current convois fastest speed ever
 
 	// things for the world record
@@ -285,7 +293,6 @@ private:
 	sint32 speedbonus_kmh; // speed used for speedbonus calculation in km/h
 	sint32 maxspeed_average_count; // just a simple count to average for statistics
 
-
 	ribi_t::ribi alte_richtung;
 
 	/**
@@ -429,10 +436,8 @@ public:
 	 */
 	void set_state( uint16 new_state ) { assert(new_state<MAX_STATES); state = (states)new_state; }
 
-	/**
-	* get state
-	*/
-	int get_state() const { return state; }
+	/// get state
+	states get_state() const { return state; }
 
 	/**
 	* true if in waiting state (maybe also due to starting)
@@ -574,7 +579,7 @@ public:
 	 * moving the vehicles of a convoi and acceleration/deceleration
 	 * all other stuff => convoi_t::step()
 	 */
-	sync_result sync_step(uint32 delta_t) OVERRIDE;
+	sync_result sync_step(uint32 delta_t);
 
 	/**
 	 * All things like route search or loading, that may take a little
diff --git src/simutrans/simfab.cc src/simutrans/simfab.cc
index 719d89b27..3634d7092 100644
--- src/simutrans/simfab.cc
+++ src/simutrans/simfab.cc
@@ -1592,7 +1592,7 @@ void fabrik_t::smoke()
 		const koord offset = ( desc->get_smokeoffset(rot)*OBJECT_OFFSET_STEPS)/16;
 		wolke_t *smoke =  new wolke_t(gr->get_pos(), offset.x, 0, offset.y, desc->get_smokelifetime(), desc->get_smokeuplift(), rada->get_images() );
 		gr->obj_add(smoke);
-		welt->sync_way_eyecandy.add( smoke );
+		welt->sync_clouds.add( smoke );
 	}
 
 	// maybe sound?
diff --git src/simutrans/tool/simtool.cc src/simutrans/tool/simtool.cc
index 0a2890a56..fbe4103d5 100644
--- src/simutrans/tool/simtool.cc
+++ src/simutrans/tool/simtool.cc
@@ -6091,7 +6091,7 @@ const char *tool_add_citycar_t::work( player_t *player, koord3d pos )
 		// add citycar
 		private_car_t* vt = new private_car_t(gr, koord::invalid, default_param);
 		gr->obj_add(vt);
-		welt->sync.add(vt);
+		welt->sync_private_cars.add(vt);
 		return NULL;
 	}
 	return "";
diff --git src/simutrans/utils/sync_list.cc src/simutrans/utils/sync_list.cc
new file mode 100644
index 000000000..e21877a8f
--- /dev/null
+++ src/simutrans/utils/sync_list.cc
@@ -0,0 +1,6 @@
+/*
+ * This file is part of the Simutrans project under the Artistic License.
+ * (see LICENSE.txt)
+ */
+
+#include "sync_list.h"
diff --git src/simutrans/utils/sync_list.h src/simutrans/utils/sync_list.h
new file mode 100644
index 000000000..847bfaccd
--- /dev/null
+++ src/simutrans/utils/sync_list.h
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the Simutrans project under the Artistic License.
+ * (see LICENSE.txt)
+ */
+
+#ifndef UTILS_SYNC_LIST_H
+#define UTILS_SYNC_LIST_H
+
+
+#include "../simtypes.h"
+#include "../tpl/vector_tpl.h"
+#include "../obj/sync_steppable.h"
+
+#include <cassert>
+
+
+
+template<class S>
+class sync_list_t
+{
+	vector_tpl<S *> list;  ///< list of sync-steppable objects
+	S *currently_deleting; ///< deleted during sync_step, safeguard calls to remove
+	bool sync_step_running;
+
+public:
+	sync_list_t() :
+		currently_deleting(NULL),
+		sync_step_running(false)
+	{
+	}
+
+	void add(S *obj)
+	{
+		assert(!sync_step_running);
+		list.append(obj);
+	}
+
+	void remove(S *obj)
+	{
+		if(sync_step_running) {
+			if (obj == currently_deleting) {
+				return;
+			}
+			assert(false);
+		}
+		else {
+			list.remove(obj);
+		}
+	}
+	/// clears list, does not delete the objects
+	void clear()
+	{
+		list.clear();
+		currently_deleting = NULL;
+		sync_step_running = false;
+	}
+
+	void sync_step(uint32 delta_t)
+	{
+		sync_step_running = true;
+		currently_deleting = NULL;
+
+		for(uint32 i=0; i<list.get_count();i++) {
+			S *ss = list[i];
+			switch(ss->sync_step(delta_t)) {
+				case SYNC_OK:
+					break;
+				case SYNC_DELETE:
+					currently_deleting = ss;
+					delete ss;
+					currently_deleting = NULL;
+					/* fall-through */
+				case SYNC_REMOVE:
+					ss = list.pop_back();
+					if (i < list.get_count()) {
+						list[i] = ss;
+					}
+			}
+		}
+		sync_step_running = false;
+	}
+
+};
+
+
+#endif
diff --git src/simutrans/vehicle/movingobj.cc src/simutrans/vehicle/movingobj.cc
index fc2c319ee..4e3d2f94b 100644
--- src/simutrans/vehicle/movingobj.cc
+++ src/simutrans/vehicle/movingobj.cc
@@ -153,7 +153,7 @@ movingobj_t::movingobj_t(loadsave_t *file) : vehicle_base_t()
 {
 	rdwr(file);
 	if(get_desc()) {
-		welt->sync.add( this );
+		welt->sync_movingobjs.add( this );
 	}
 }
 
@@ -165,13 +165,13 @@ movingobj_t::movingobj_t(koord3d pos, const groundobj_desc_t *b ) : vehicle_base
 	timetochange = 0; // will do random direct change anyway during next step
 	direction = calc_set_direction( koord3d(0,0,0), koord3d(koord::west,0) );
 	calc_image();
-	welt->sync.add( this );
+	welt->sync_movingobjs.add( this );
 }
 
 
 movingobj_t::~movingobj_t()
 {
-	welt->sync.remove( this );
+	welt->sync_movingobjs.remove( this );
 }
 
 
diff --git src/simutrans/vehicle/movingobj.h src/simutrans/vehicle/movingobj.h
index 1f709aa6f..e8b40156d 100644
--- src/simutrans/vehicle/movingobj.h
+++ src/simutrans/vehicle/movingobj.h
@@ -19,7 +19,7 @@
 /**
  * moving stuff like sheep or birds
  */
-class movingobj_t : public vehicle_base_t, public sync_steppable
+class movingobj_t : public vehicle_base_t
 {
 private:
 	/// distance to move
@@ -54,7 +54,7 @@ public:
 	movingobj_t(koord3d pos, const groundobj_desc_t *);
 	~movingobj_t();
 
-	sync_result sync_step(uint32 delta_t) OVERRIDE;
+	sync_result sync_step(uint32 delta_t);
 
 	// always free
 	virtual bool check_next_tile(const grund_t *) const;
diff --git src/simutrans/vehicle/pedestrian.cc src/simutrans/vehicle/pedestrian.cc
index 47e038f23..68cc0393d 100644
--- src/simutrans/vehicle/pedestrian.cc
+++ src/simutrans/vehicle/pedestrian.cc
@@ -66,7 +66,7 @@ pedestrian_t::pedestrian_t(loadsave_t *file)
 	steps_offset = 0;
 	rdwr(file);
 	if(desc) {
-		welt->sync.add(this);
+		welt->sync_pedestrians.add(this);
 		ped_offset = desc->get_offset();
 	}
 	calc_disp_lane();
@@ -124,7 +124,7 @@ pedestrian_t::pedestrian_t(grund_t *gr) :
 pedestrian_t::~pedestrian_t()
 {
 	if(  time_to_life>0  ) {
-		welt->sync.remove( this );
+		welt->sync_pedestrians.remove( this );
 	}
 }
 
@@ -218,7 +218,7 @@ void pedestrian_t::generate_pedestrians_at(const koord3d k, int &count)
 						// walk a little
 						fg->sync_step( (i & 3) * 64 * 24);
 					}
-					welt->sync.add(fg);
+					welt->sync_pedestrians.add(fg);
 					count--;
 				}
 				else {
diff --git src/simutrans/vehicle/pedestrian.h src/simutrans/vehicle/pedestrian.h
index 6b794e5f4..514010b52 100644
--- src/simutrans/vehicle/pedestrian.h
+++ src/simutrans/vehicle/pedestrian.h
@@ -55,7 +55,7 @@ public:
 
 	void info(cbuffer_t & buf) const OVERRIDE;
 
-	sync_result sync_step(uint32 delta_t) OVERRIDE;
+	sync_result sync_step(uint32 delta_t);
 
 	///@ returns true if pedestrian walks on the left side of the road
 	bool is_on_left() const { return on_left; }
diff --git src/simutrans/vehicle/simroadtraffic.cc src/simutrans/vehicle/simroadtraffic.cc
index c5b1c91ac..eb70d084a 100644
--- src/simutrans/vehicle/simroadtraffic.cc
+++ src/simutrans/vehicle/simroadtraffic.cc
@@ -315,7 +315,7 @@ private_car_t::~private_car_t()
 
 	// just to be sure we are removed from this list!
 	if(time_to_life>0) {
-		welt->sync.remove(this);
+		welt->sync_private_cars.remove(this);
 	}
 	welt->buche( -1, karte_t::WORLD_CITYCARS );
 }
@@ -328,7 +328,7 @@ private_car_t::private_car_t(loadsave_t *file) :
 	ms_traffic_jam = 0;
 	calc_disp_lane();
 	if(desc) {
-		welt->sync.add(this);
+		welt->sync_private_cars.add(this);
 	}
 	welt->buche( +1, karte_t::WORLD_CITYCARS );
 }
diff --git src/simutrans/vehicle/simroadtraffic.h src/simutrans/vehicle/simroadtraffic.h
index 16a30b69c..3998b2829 100644
--- src/simutrans/vehicle/simroadtraffic.h
+++ src/simutrans/vehicle/simroadtraffic.h
@@ -23,7 +23,7 @@ class karte_t;
  * differ from the vehicles defined herein for the individual traffic
  * (pedestrians, citycars, movingobj aka flock of sheep).
  */
-class road_user_t : public vehicle_base_t, public sync_steppable
+class road_user_t : public vehicle_base_t
 {
 protected:
 	/**
@@ -114,7 +114,7 @@ public:
 
 	const citycar_desc_t *get_desc() const { return desc; }
 
-	sync_result sync_step(uint32 delta_t) OVERRIDE;
+	sync_result sync_step(uint32 delta_t);
 
 	void hop(grund_t *gr) OVERRIDE;
 
diff --git src/simutrans/vehicle/vehicle.cc src/simutrans/vehicle/vehicle.cc
index 33a0255ea..e84d149f4 100644
--- src/simutrans/vehicle/vehicle.cc
+++ src/simutrans/vehicle/vehicle.cc
@@ -660,7 +660,7 @@ void vehicle_t::make_smoke() const
 					delete abgas;
 				}
 				else {
-					welt->sync_way_eyecandy.add( abgas );
+					welt->sync_clouds.add( abgas );
 				}
 			}
 		}
diff --git src/simutrans/world/simcity.cc src/simutrans/world/simcity.cc
index 3fb8224e7..06589ee2c 100644
--- src/simutrans/world/simcity.cc
+++ src/simutrans/world/simcity.cc
@@ -1701,7 +1701,7 @@ void stadt_t::new_month( bool recalc_destinations )
 						if(  ribi_t::is_twoway(w->get_ribi_unmasked())  &&  player_t::check_owner(NULL,w->get_owner())  &&  gr->find<private_car_t>() == NULL  ) {
 							private_car_t* vt = new private_car_t(gr, koord::invalid);
 							gr->obj_add(vt);
-							welt->sync.add(vt);
+							welt->sync_private_cars.add(vt);
 							number_of_cars--;
 						}
 					}
diff --git src/simutrans/world/simworld.cc src/simutrans/world/simworld.cc
index d076367da..fa8284668 100644
--- src/simutrans/world/simworld.cc
+++ src/simutrans/world/simworld.cc
@@ -60,6 +60,7 @@
 #include "../obj/groundobj.h"
 #include "../obj/gebaeude.h"
 #include "../obj/leitung2.h"
+#include "../obj/wolke.h"
 
 #include "../gui/password_frame.h"
 #include "../gui/messagebox.h"
@@ -438,9 +439,15 @@ void karte_t::destroy()
 	ls.set_progress( old_progress );
 
 	// removes all moving stuff from the sync_step
-	sync.clear();
-	sync_eyecandy.clear();
-	sync_way_eyecandy.clear();
+	sync_convois.clear();
+	sync_buildings.clear();
+	sync_senkes.clear();
+	sync_roadsigns.clear();
+	sync_clouds.clear();
+	sync_pedestrians.clear();
+	sync_private_cars.clear();
+	sync_movingobjs.clear();
+
 	old_progress += cached_size.x*cached_size.y;
 	ls.set_progress( old_progress );
 	DBG_MESSAGE("karte_t::destroy()", "sync list cleared");
@@ -2576,60 +2583,6 @@ stadt_t *karte_t::find_nearest_city(const koord k) const
 }
 
 
-// -------- Verwaltung von synchronen Objekten ------------------
-
-void karte_t::sync_list_t::add(sync_steppable *obj)
-{
-	assert(!sync_step_running);
-	list.append(obj);
-}
-
-void karte_t::sync_list_t::remove(sync_steppable *obj)
-{
-	if(sync_step_running) {
-		if (obj == currently_deleting) {
-			return;
-		}
-		assert(false);
-	}
-	else {
-		list.remove(obj);
-	}
-}
-
-void karte_t::sync_list_t::clear()
-{
-	list.clear();
-	currently_deleting = NULL;
-	sync_step_running = false;
-}
-
-void karte_t::sync_list_t::sync_step(uint32 delta_t)
-{
-	sync_step_running = true;
-	currently_deleting = NULL;
-
-	for(uint32 i=0; i<list.get_count();i++) {
-		sync_steppable *ss = list[i];
-		switch(ss->sync_step(delta_t)) {
-			case SYNC_OK:
-				break;
-			case SYNC_DELETE:
-				currently_deleting = ss;
-				delete ss;
-				currently_deleting = NULL;
-				/* fall-through */
-			case SYNC_REMOVE:
-				ss = list.pop_back();
-				if (i < list.get_count()) {
-					list[i] = ss;
-				}
-		}
-	}
-	sync_step_running = false;
-}
-
-
 /*
  * this routine is called before an image is displayed
  * it moves vehicles and pedestrians
@@ -2651,20 +2604,17 @@ void karte_t::sync_step(uint32 delta_t)
 
 	set_random_mode( INTERACTIVE_RANDOM );
 
-	/* animations do not require exact sync
-		* foundations etc are added removed frequently during city growth
-		* => they are now in a hastable!
-		*/
-	sync_eyecandy.sync_step( delta_t );
-
-	/* pedestrians do not require exact sync and are added/removed frequently
-		* => they are now in a hastable!
-		*/
-	sync_way_eyecandy.sync_step( delta_t );
+	sync_buildings.sync_step(delta_t);
+	sync_clouds.sync_step(delta_t);
 
 	clear_random_mode( INTERACTIVE_RANDOM );
 
-	sync.sync_step( delta_t );
+	sync_convois.sync_step(delta_t);
+	sync_private_cars.sync_step(delta_t);
+	sync_pedestrians.sync_step(delta_t);
+	sync_movingobjs.sync_step(delta_t);
+	sync_roadsigns.sync_step(delta_t);
+	sync_senkes.sync_step(delta_t);
 
 	ticker::update();
 
@@ -4718,7 +4668,7 @@ void karte_t::rdwr_gamestate(loadsave_t *file, loadingscreen_t *ls)
 				}
 			}
 			else {
-				sync.add( cnv );
+				sync_convois.add( cnv );
 			}
 			if(  (convoi_array.get_count()&7) == 0  ) {
 				ls->set_progress( get_size().y+(get_size().y*convoi_array.get_count())/(2*max_convoi)+128 );
diff --git src/simutrans/world/simworld.h src/simutrans/world/simworld.h
index a84cfbf33..484a81b22 100644
--- src/simutrans/world/simworld.h
+++ src/simutrans/world/simworld.h
@@ -24,6 +24,7 @@
 #include "../dataobj/rect.h"
 
 #include "../utils/checklist.h"
+#include "../utils/sync_list.h"
 #include "../utils/sha1_hash.h"
 
 #include "simplan.h"
@@ -53,6 +54,8 @@ class viewport_t;
 class records_t;
 class loadingscreen_t;
 class terraformer_t;
+class wolke_t;
+class movingobj_t;
 
 
 /**
@@ -1016,25 +1019,14 @@ public:
 	/// rotate map view by 90 degrees
 	void rotate90();
 
-	class sync_list_t {
-			friend class karte_t;
-		public:
-			sync_list_t() : currently_deleting(NULL), sync_step_running(false) {}
-			void add(sync_steppable *obj);
-			void remove(sync_steppable *obj);
-		private:
-			void sync_step(uint32 delta_t);
-			/// clears list, does not delete the objects
-			void clear();
-
-			vector_tpl<sync_steppable *> list;  ///< list of sync-steppable objects
-			sync_steppable* currently_deleting; ///< deleted durign sync_step, safeguard calls to remove
-			bool sync_step_running;
-	};
-
-	sync_list_t sync;              ///< vehicles, transformers, traffic lights
-	sync_list_t sync_eyecandy;     ///< animated buildings
-	sync_list_t sync_way_eyecandy; ///< smoke
+	sync_list_t<convoi_t>      sync_convois;
+	sync_list_t<gebaeude_t>    sync_buildings;
+	sync_list_t<senke_t>       sync_senkes; ///< power drains
+	sync_list_t<roadsign_t>    sync_roadsigns;
+	sync_list_t<wolke_t>       sync_clouds; ///< smoke
+	sync_list_t<pedestrian_t>  sync_pedestrians;
+	sync_list_t<private_car_t> sync_private_cars;
+	sync_list_t<movingobj_t>   sync_movingobjs;
 
 	/**
 	 * Synchronous stepping of objects like vehicles.
