diff --git a/simconvoi.cc b/simconvoi.cc index 5144244be..22096928a 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -134,6 +134,7 @@ void convoi_t::init(player_t *player) sum_speed_limit = 0; maxspeed_average_count = 0; next_reservation_index = 0; + reserved_tiles.clear(); alte_richtung = ribi_t::none; next_wolke = 0; @@ -261,6 +262,21 @@ void convoi_t::unreserve_route() // free all reserved blocks uint16 dummy; lok->block_reserver(get_route(), back()->get_route_index(), dummy, dummy, 100000, false, true); + // free all tiles held by reserved_tiles + if( reserved_tiles.get_count()>0 ) { + 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(); + } } } } @@ -272,10 +288,23 @@ void convoi_t::unreserve_route() void convoi_t::reserve_route() { 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)) ) ); + if( reserved_tiles.get_count()>0 ) { + // reservation is controlled by reserved_tiles + 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)] ) ); + } + } + } + } + else { + // reservation is controlled by next_reservation_index + 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)) ) ); + } } } } @@ -1197,6 +1226,9 @@ void convoi_t::step() set_schedule(schedule); schedule_target = koord3d::invalid; + + // unreserve all tiles + unreserve_route(); if( schedule->empty() ) { // no entry => no route ... @@ -2564,6 +2596,24 @@ void convoi_t::rdwr(loadsave_t *file) file->rdwr_short( next_stop_index ); file->rdwr_short( next_reservation_index ); } + + if( file->get_version()>=120008 ) { + uint32 count = reserved_tiles.get_count(); + file->rdwr_long(count); + if( file->is_loading() ) { // reading + reserved_tiles.clear(); + for( uint32 i=0; iis_loading() ) { reserve_route(); diff --git a/simconvoi.h b/simconvoi.h index cba4c23a6..3d1167033 100644 --- a/simconvoi.h +++ b/simconvoi.h @@ -251,6 +251,13 @@ private: * @author prissi */ uint16 next_reservation_index; + + /** + * This holds coordinates reserved by this convoy. + * Used when reservation is triggered by longblocksignal. + * @author THLeaderH + */ + vector_tpl reserved_tiles; /** * The convoi is not processed every sync step for various actions @@ -854,6 +861,15 @@ public: */ uint16 get_next_reservation_index() const {return next_reservation_index;} void set_next_reservation_index(uint16 n); + + /* these functions modify only reserved_tiles. + * reservation of tiles has to be done separately. + * @author THLeaderH + */ + void unreserve_pos(koord3d pos) { reserved_tiles.remove(pos); } + void reserve_pos(koord3d pos) {reserved_tiles.append_unique(pos); } + bool is_reservation_empty() const { return reserved_tiles.empty(); } + vector_tpl& get_reserved_tiles() { return reserved_tiles; } /* 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 2e8731bfa..72a29915b 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->get_next_reservation_index()==0 && c->is_reservation_empty() ) { assert(c!=NULL); // eventually search new route route_t const& r = *c->get_route(); @@ -2458,11 +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 @@ -2594,7 +2589,7 @@ bool rail_vehicle_t::is_longblock_signal_clear(signal_t *sig, uint16 next_block, { // longblock signal: first check, whether there is a signal coming up on the route => just like normal signal uint16 next_signal, next_crossing; - if( !block_reserver( cnv->get_route(), next_block+1, next_signal, next_crossing, 0, true, false ) ) { + if( !block_reserver( cnv->get_route(), next_block+1, next_signal, next_crossing, 0, true, false, true ) ) { // not even the "Normal" signal route part is free => no bother checking further on sig->set_state( roadsign_t::rot ); restart_speed = 0; @@ -2613,6 +2608,22 @@ bool rail_vehicle_t::is_longblock_signal_clear(signal_t *sig, uint16 next_block, restart_speed = -1; return false; } + + // now we have to maintain reservation with reserved_tiles, that is slower than using next_reservation_index + // copy all tiles that are already reserved + bool add_pos = false; + vector_tpl tiles_convoy_on; + for( uint16 i=0; iget_vehicle_count(); i++ ) { + tiles_convoy_on.append_unique(cnv->get_vehikel(i)->get_pos()); + } + for( uint16 i=0; iget_route()->get_count(); i++ ) { + if( !add_pos && tiles_convoy_on.is_contained(cnv->get_route()->at(i)) ) { + add_pos = true; + } + if( add_pos ) { + cnv->reserve_pos(cnv->get_route()->at(i)); + } + } // now we can use the route search array // (route until end is already reserved at this point!) @@ -2632,18 +2643,13 @@ bool rail_vehicle_t::is_longblock_signal_clear(signal_t *sig, uint16 next_block, break; } 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 ); + success = block_reserver( &target_rt, 1, next_next_signal, dummy, 0, true, false, true ); } 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; @@ -2651,7 +2657,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; @@ -3019,7 +3037,7 @@ bool rail_vehicle_t::can_enter_tile(const grund_t *gr, sint32 &restart_speed, ui * return the last checked block * @author prissi */ -bool rail_vehicle_t::block_reserver(const route_t *route, uint16 start_index, uint16 &next_signal_index, uint16 &next_crossing_index, int count, bool reserve, bool force_unreserve ) const +bool rail_vehicle_t::block_reserver(const route_t *route, uint16 start_index, uint16 &next_signal_index, uint16 &next_crossing_index, int count, bool reserve, bool force_unreserve, bool use_vector ) const { bool success=true; #ifdef MAX_CHOOSE_BLOCK_TILES @@ -3073,6 +3091,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 if( use_vector ){ + // use reserved_tiles instead of next_reservation_index to hold reservations. + cnv->reserve_pos(pos); + } if(next_crossing_index==INVALID_INDEX && sch1->is_crossing()) { next_crossing_index = i; } @@ -3087,6 +3109,8 @@ 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; + // If reservation is controlled by next_reservation_index, this does nothing. + cnv->unreserve_pos(pos); } if(sch1->has_signal()) { signal_t* signal = gr->find(); @@ -3113,6 +3137,7 @@ 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_pos(route->at(j)); } cnv->set_next_reservation_index( start_index ); return false; @@ -3141,6 +3166,10 @@ void rail_vehicle_t::leave_tile() schiene_t *sch0 = (schiene_t *) gr->get_weg(get_waytype()); if(sch0) { sch0->unreserve(this); + if( cnv ) { + // If reservation is controlled by next_reservation_index, this does nothing. + cnv->unreserve_pos(get_pos()); + } // tell next signal? // and switch to red if(sch0->has_signal()) { diff --git a/vehicle/simvehicle.h b/vehicle/simvehicle.h index c060f5285..4390b6bd7 100644 --- a/vehicle/simvehicle.h +++ b/vehicle/simvehicle.h @@ -572,7 +572,7 @@ public: // reserves or un-reserves all blocks and returns the handle to the next block (if there) // returns true on successful reservation - bool block_reserver(const route_t *route, uint16 start_index, uint16 &next_signal, uint16 &next_crossing, int signal_count, bool reserve, bool force_unreserve ) const; + bool block_reserver(const route_t *route, uint16 start_index, uint16 &next_signal, uint16 &next_crossing, int signal_count, bool reserve, bool force_unreserve, bool use_vector = false ) const; void leave_tile();