diff --git a/simconvoi.cc b/simconvoi.cc index 581b0219f..523db7f35 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -133,7 +133,7 @@ void convoi_t::init(player_t *player) distance_since_last_stop = 0; sum_speed_limit = 0; maxspeed_average_count = 0; - next_reservation_index = 0; + reserved_tiles.clear(); alte_richtung = ribi_t::none; next_wolke = 0; @@ -249,33 +249,54 @@ bool convoi_t::is_waypoint( koord3d ziel ) const /** - * unreserves the whole remaining route + * unreserves all reserved tiles, except tiles which we are on. */ -void convoi_t::unreserve_route() + +void convoi_t::unreserve_all() { - // need a route, vehicles, and vehicles must belong to this convoi - // (otherwise crash during loading when fahr[0]->convoi is not initialized yet - if( !route.empty() && anz_vehikel>0 && fahr[0]->get_convoi() == this ) { - rail_vehicle_t* lok = dynamic_cast(fahr[0]); - if (lok) { - // free all reserved blocks - uint16 dummy; - lok->block_reserver(get_route(), back()->get_route_index(), dummy, dummy, 100000, false, true); + vector_tpl tiles_convoy_on; + for( uint16 i=0; iget_pos()); + } + for( uint32 i=0; ilookup(reserved_tiles[i]); + schiene_t *sch = gr ? (schiene_t *)gr->get_weg( front()->get_waytype() ) : NULL; + if( sch && !tiles_convoy_on.is_contained(reserved_tiles[i]) ) { + sch->unreserve(this->self); } } + reserved_tiles.clear(); } /** * reserves route until next_reservation_index */ -void convoi_t::reserve_route() +void convoi_t::reserve_route(uint16 next_reservation_index) { if( !route.empty() && anz_vehikel>0 && (is_waiting() || state==DRIVING || state==LEAVING_DEPOT) ) { for( int idx = back()->get_route_index(); idx < next_reservation_index /*&& idx < route.get_count()*/; idx++ ) { if( grund_t *gr = welt->lookup( route.at(idx) ) ) { if( schiene_t *sch = (schiene_t *)gr->get_weg( front()->get_waytype() ) ) { sch->reserve( self, ribi_type( route.at(max(1u,idx)-1u), route.at(min(route.get_count()-1u,idx+1u)) ) ); + reserved_tiles.append(route.at(idx)); + } + } + } + } +} + + +/** + * reserve tiles of reserved_tiles + */ +void convoi_t::reserve_tiles() +{ + if( anz_vehikel>0 && (is_waiting() || state==DRIVING || state==LEAVING_DEPOT) ) { + for( uint32 idx = 0; idx < reserved_tiles.get_count(); idx++ ) { + if( grund_t *gr = welt->lookup( reserved_tiles[idx] ) ) { + if( schiene_t *sch = (schiene_t *)gr->get_weg( front()->get_waytype() ) ) { + sch->reserve( self, ribi_type( reserved_tiles[max(1u,idx)-1u], reserved_tiles[min(reserved_tiles.get_count()-1u,idx+1u)] ) ); } } } @@ -1197,6 +1218,9 @@ void convoi_t::step() set_schedule(schedule); schedule_target = koord3d::invalid; + + // unreserve all tiles + unreserve_all(); if( schedule->empty() ) { // no entry => no route ... @@ -1465,7 +1489,7 @@ void convoi_t::new_month() void convoi_t::betrete_depot(depot_t *dep) { // first remove reservation, if train is still on track - unreserve_route(); + unreserve_all(); // Hajo: remove vehicles from world data structure for(unsigned i=0; iget_version()>=111003 ) { file->rdwr_short( next_stop_index ); - file->rdwr_short( next_reservation_index ); + + if( file->get_version() >= 120008 ) { + // read/load reserved_tiles. + uint32 n = reserved_tiles.get_count(); + file->rdwr_long(n); + if( file->is_loading() ) { + reserved_tiles.clear(); + for( uint32 i = 0; i < n; i++ ) { + koord3d pos; + pos.rdwr(file); + reserved_tiles.append(pos); + } + reserve_tiles(); + } else { + // writing... + for( uint32 i = 0; i < n; i++ ) { + reserved_tiles[i].rdwr(file); + } + } + } + else if( file->is_loading() ) { + uint16 next_reservation_index; + file->rdwr_short( next_reservation_index ); + reserve_route(next_reservation_index); + } + } if( file->is_loading() ) { - reserve_route(); recalc_catg_index(); } } @@ -3491,19 +3539,6 @@ void convoi_t::set_next_stop_index(uint16 n) } -/* including this route_index, the route was reserved the last time - * currently only used for tracks - */ -void convoi_t::set_next_reservation_index(uint16 n) -{ - // stop at station or signals, not at waypoints - if( n==INVALID_INDEX ) { - n = route.get_count()-1; - } - next_reservation_index = n; -} - - /* * the current state saved as color * Meanings are BLACK (ok), WHITE (no convois), YELLOW (no vehicle moved), RED (last month income minus), BLUE (at least one convoi vehicle is obsolete) diff --git a/simconvoi.h b/simconvoi.h index cba4c23a6..a37bbf38c 100644 --- a/simconvoi.h +++ b/simconvoi.h @@ -246,11 +246,10 @@ private: uint16 next_stop_index; /** - * this give the index until which the route has been reserved. It is used for - * restoring reservations after loading a game. - * @author prissi + * this holds rail tiles reserved by this convoy. + * @author THLeaderH */ - uint16 next_reservation_index; + vector_tpl reserved_tiles; /** * The convoi is not processed every sync step for various actions @@ -318,13 +317,13 @@ private: */ bool can_go_alte_richtung(); - /** - * remove all track reservations (trains only) - */ - void unreserve_route(); + // reserve tiles of reserved_tiles. + // this function is for loading. + void reserve_tiles(); - // reserve route until next_reservation_index - void reserve_route(); + // reserve route until given index + // this function is for compatibility + void reserve_route(uint16 next_reservation_index); /** * Mark first and last vehicle. @@ -849,11 +848,19 @@ public: uint16 get_next_stop_index() const {return next_stop_index;} void set_next_stop_index(uint16 n); - /* including this route_index, the route was reserved the last time + /* these function modify only reserved_tiles + * reservation of tiles has to be done separately. * currently only used for tracks */ - uint16 get_next_reservation_index() const {return next_reservation_index;} - void set_next_reservation_index(uint16 n); + void unreserve(koord3d pos) { reserved_tiles.remove(pos); } + void reserve(koord3d pos) { reserved_tiles.append_unique(pos); } + bool is_reservation_empty() const { return reserved_tiles.empty(); } + vector_tpl& get_reserved_tiles() { return reserved_tiles; } + + /** + * remove all track reservations (trains only) + */ + void unreserve_all(); /* the current state of the convoi */ PIXVAL get_status_color() const; diff --git a/simversion.h b/simversion.h index 24c89802d..2a7b7859c 100644 --- a/simversion.h +++ b/simversion.h @@ -17,8 +17,8 @@ // Beware: SAVEGAME minor is often ahead of version minor when there were patches. // ==> These have no direct connection at all! -#define SIM_SAVE_MINOR 7 -#define SIM_SERVER_MINOR 7 +#define SIM_SAVE_MINOR 8 +#define SIM_SERVER_MINOR 8 // NOTE: increment before next release to enable save/load of new features #define MAKEOBJ_VERSION "60.2" diff --git a/vehicle/simvehicle.cc b/vehicle/simvehicle.cc index ea1e8b861..16b075d91 100644 --- a/vehicle/simvehicle.cc +++ b/vehicle/simvehicle.cc @@ -2429,7 +2429,7 @@ void rail_vehicle_t::set_convoi(convoi_t *c) target_halt = halthandle_t(); } } - else if( c->get_next_reservation_index()==0 ) { + else if( c->is_reservation_empty() ) { assert(c!=NULL); // eventually search new route route_t const& r = *c->get_route(); @@ -2458,12 +2458,6 @@ void rail_vehicle_t::set_convoi(convoi_t *c) // need to reset halt reservation (if there was one) bool rail_vehicle_t::calc_route(koord3d start, koord3d ziel, sint32 max_speed, route_t* route) { - if(leading && route_indexget_route()->get_count()) { - // free all reserved blocks - uint16 dummy; - block_reserver(cnv->get_route(), cnv->back()->get_route_index(), dummy, dummy, target_halt.is_bound() ? 100000 : 1, false, true); - } - cnv->set_next_reservation_index( 0 ); // nothing to reserve target_halt = halthandle_t(); // no block reserved // use length 8888 tiles to advance to the end of all stations return route->calc_route(welt, start, ziel, this, max_speed, 8888 /*cnv->get_tile_length()*/ ); @@ -2629,17 +2623,12 @@ bool rail_vehicle_t::is_longblock_signal_clear(signal_t *sig, uint16 next_block, bool success = target_rt.calc_route( welt, cur_pos, cnv->get_schedule()->entries[schedule_index].pos, this, speed_to_kmh(cnv->get_min_top_speed()), 8888 /*cnv->get_tile_length()*/ ); if( success ) { success = block_reserver( &target_rt, 1, next_next_signal, dummy, 0, true, false ); - block_reserver( &target_rt, 1, dummy, dummy, 0, false, false ); } if( success ) { // ok, would be free if( next_next_signal finished - // (however, if it is this signal, we need to renew reservation ... - if( target_rt.at(next_next_signal) == cnv->get_route()->at( next_block ) ) { - block_reserver( cnv->get_route(), next_block+1, next_signal, next_crossing, 0, true, false ); - } sig->set_state( roadsign_t::gruen ); cnv->set_next_stop_index( min( min( next_crossing, next_signal ), cnv->get_route()->get_count() ) ); return true; @@ -2647,7 +2636,19 @@ bool rail_vehicle_t::is_longblock_signal_clear(signal_t *sig, uint16 next_block, } if( !success ) { - block_reserver( cnv->get_route(), next_block+1, next_next_signal, dummy, 0, false, false ); + // unreserve tiles which we reserved in this routine. + // find the index from which we unreserve the tiles. + sint32 start_idx; + for( start_idx=0; start_idx<(sint32)cnv->get_reserved_tiles().get_count() && cnv->get_reserved_tiles()[start_idx]!=cnv->get_route()->at(next_block+1) ; start_idx++ ) ; + // now we unreserve the tiles + for( sint32 i=cnv->get_reserved_tiles().get_count()-1; i>=start_idx; i-- ) { + grund_t* gr = welt->lookup( cnv->get_reserved_tiles()[i]); + schiene_t * sch1 = gr ? (schiene_t *)gr->get_weg(get_waytype()) : NULL; + if( sch1 ) { + sch1->unreserve(cnv->self); + } + cnv->get_reserved_tiles().remove_at(i); + } sig->set_state( roadsign_t::rot ); restart_speed = 0; return false; @@ -3018,7 +3019,6 @@ bool rail_vehicle_t::block_reserver(const route_t *route, uint16 start_index, ui slist_tpl signs; // switch all signals on their way too ... if(start_index>=route->get_count()) { - cnv->set_next_reservation_index( max(route->get_count(),1)-1 ); return 0; } @@ -3026,10 +3026,6 @@ bool rail_vehicle_t::block_reserver(const route_t *route, uint16 start_index, ui start_index++; } - if( !reserve ) { - cnv->set_next_reservation_index( start_index ); - } - // find next block segment en route uint16 i=start_index; next_signal_index=INVALID_INDEX; @@ -3063,6 +3059,10 @@ bool rail_vehicle_t::block_reserver(const route_t *route, uint16 start_index, ui if( !sch1->reserve( cnv->self, ribi_type( route->at(max(1u,i)-1u), route->at(min(route->get_count()-1u,i+1u)) ) ) ) { success = false; } + else { + // success + cnv->reserve(pos); + } if(next_crossing_index==INVALID_INDEX && sch1->is_crossing()) { next_crossing_index = i; } @@ -3077,6 +3077,7 @@ bool rail_vehicle_t::block_reserver(const route_t *route, uint16 start_index, ui else { // un-reserve from here (used during sale, since there might be reserved tiles not freed) unreserve_now = !force_unreserve; + cnv->unreserve(pos); } if(sch1->has_signal()) { signal_t* signal = gr->find(); @@ -3103,8 +3104,8 @@ bool rail_vehicle_t::block_reserver(const route_t *route, uint16 start_index, ui for ( int j=start_index; jlookup( route->at(j))->get_weg(get_waytype()); sch1->unreserve(cnv->self); + cnv->unreserve(route->at(j)); } - cnv->set_next_reservation_index( start_index ); return false; } @@ -3114,7 +3115,6 @@ bool rail_vehicle_t::block_reserver(const route_t *route, uint16 start_index, ui signal->set_state(roadsign_t::gruen); } } - cnv->set_next_reservation_index( i ); return true; } @@ -3131,6 +3131,9 @@ void rail_vehicle_t::leave_tile() schiene_t *sch0 = (schiene_t *) gr->get_weg(get_waytype()); if(sch0) { sch0->unreserve(this); + if( cnv ) { + cnv->unreserve( get_pos() ); + } // tell next signal? // and switch to red if(sch0->has_signal()) {