src/group_cmd.cpp
branchNewGRF_ports
changeset 6743 cabfaa4a0295
parent 6720 35756db7e577
child 6800 6c09e1e86fcb
equal deleted inserted replaced
6742:1337d6c9b97b 6743:cabfaa4a0295
    17 #include "aircraft.h"
    17 #include "aircraft.h"
    18 #include "string.h"
    18 #include "string.h"
    19 #include "window.h"
    19 #include "window.h"
    20 #include "vehicle_gui.h"
    20 #include "vehicle_gui.h"
    21 #include "strings.h"
    21 #include "strings.h"
       
    22 #include "misc/autoptr.hpp"
    22 
    23 
    23 /**
    24 /**
    24  * Update the num engines of a groupID. Decrease the old one and increase the new one
    25  * Update the num engines of a groupID. Decrease the old one and increase the new one
    25  * @note called in SetTrainGroupID and UpdateTrainGroupID
    26  * @note called in SetTrainGroupID and UpdateTrainGroupID
    26  * @param i     EngineID we have to update
    27  * @param i     EngineID we have to update
    37 		if (!IsDefaultGroupID(new_g) && IsValidGroupID(new_g)) GetGroup(new_g)->num_engines[i]++;
    38 		if (!IsDefaultGroupID(new_g) && IsValidGroupID(new_g)) GetGroup(new_g)->num_engines[i]++;
    38 	}
    39 	}
    39 }
    40 }
    40 
    41 
    41 
    42 
    42 /**
    43 DEFINE_OLD_POOL_GENERIC(Group, Group)
    43  * Called if a new block is added to the group-pool
    44 
    44  */
    45 
    45 static void GroupPoolNewBlock(uint start_item)
    46 Group::Group(StringID str)
    46 {
    47 {
    47 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
    48 	this->string_id = str;
    48 	 * TODO - This is just a temporary stage, this will be removed. */
    49 }
    49 	for (Group *g = GetGroup(start_item); g != NULL; g = (g->index + 1U < GetGroupPoolSize()) ? GetGroup(g->index + 1) : NULL) g->index = start_item++;
    50 
    50 }
    51 Group::~Group()
    51 
    52 {
    52 DEFINE_OLD_POOL(Group, Group, GroupPoolNewBlock, NULL)
    53 	this->QuickFree();
    53 
    54 	this->string_id = STR_NULL;
    54 static Group *AllocateGroup(void)
    55 }
    55 {
    56 
    56 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
    57 void Group::QuickFree()
    57 	 * TODO - This is just a temporary stage, this will be removed. */
    58 {
    58 	for (Group *g = GetGroup(0); g != NULL; g = (g->index + 1U < GetGroupPoolSize()) ? GetGroup(g->index + 1) : NULL) {
    59 	DeleteName(this->string_id);
    59 		if (!IsValidGroup(g)) {
    60 }
    60 			const GroupID index = g->index;
    61 
    61 
    62 bool Group::IsValid() const
    62 			memset(g, 0, sizeof(*g));
    63 {
    63 			g->index = index;
    64 	return this->string_id != STR_NULL;
    64 
       
    65 			return g;
       
    66 		}
       
    67 	}
       
    68 
       
    69 	/* Check if we can add a block to the pool */
       
    70 	return (AddBlockToPool(&_Group_pool)) ? AllocateGroup() : NULL;
       
    71 }
    65 }
    72 
    66 
    73 void InitializeGroup(void)
    67 void InitializeGroup(void)
    74 {
    68 {
    75 	CleanPool(&_Group_pool);
    69 	_Group_pool.CleanPool();
    76 	AddBlockToPool(&_Group_pool);
    70 	_Group_pool.AddBlockToPool();
    77 }
    71 }
    78 
    72 
    79 
    73 
    80 static WindowClass GetWCForVT(VehicleType vt)
    74 static WindowClass GetWCForVT(VehicleType vt)
    81 {
    75 {
    98 CommandCost CmdCreateGroup(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    92 CommandCost CmdCreateGroup(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    99 {
    93 {
   100 	VehicleType vt = (VehicleType)p1;
    94 	VehicleType vt = (VehicleType)p1;
   101 	if (!IsPlayerBuildableVehicleType(vt)) return CMD_ERROR;
    95 	if (!IsPlayerBuildableVehicleType(vt)) return CMD_ERROR;
   102 
    96 
   103 	Group *g = AllocateGroup();
    97 	AutoPtrT<Group> g_auto_delete;
       
    98 
       
    99 	Group *g = new Group(STR_EMPTY);
   104 	if (g == NULL) return CMD_ERROR;
   100 	if (g == NULL) return CMD_ERROR;
   105 
   101 
       
   102 	g_auto_delete = g;
       
   103 
   106 	if (flags & DC_EXEC) {
   104 	if (flags & DC_EXEC) {
   107 		g->owner = _current_player;
   105 		g->owner = _current_player;
   108 		g->string_id = STR_EMPTY;
       
   109 		g->replace_protection = false;
   106 		g->replace_protection = false;
   110 		g->vehicle_type = vt;
   107 		g->vehicle_type = vt;
   111 
   108 
   112 		InvalidateWindowData(GetWCForVT(vt), (vt << 11) | VLW_GROUP_LIST | _current_player);
   109 		InvalidateWindowData(GetWCForVT(vt), (vt << 11) | VLW_GROUP_LIST | _current_player);
       
   110 
       
   111 		g_auto_delete.Detach();
   113 	}
   112 	}
   114 
   113 
   115 	return CommandCost();
   114 	return CommandCost();
   116 }
   115 }
   117 
   116 
   151 
   150 
   152 		VehicleType vt = g->vehicle_type;
   151 		VehicleType vt = g->vehicle_type;
   153 
   152 
   154 		/* Delete the Replace Vehicle Windows */
   153 		/* Delete the Replace Vehicle Windows */
   155 		DeleteWindowById(WC_REPLACE_VEHICLE, g->vehicle_type);
   154 		DeleteWindowById(WC_REPLACE_VEHICLE, g->vehicle_type);
   156 		DeleteGroup(g);
   155 		delete g;
   157 
   156 
   158 		InvalidateWindowData(GetWCForVT(vt), (vt << 11) | VLW_GROUP_LIST | _current_player);
   157 		InvalidateWindowData(GetWCForVT(vt), (vt << 11) | VLW_GROUP_LIST | _current_player);
   159 	}
   158 	}
   160 
   159 
   161 	return CommandCost();
   160 	return CommandCost();
   357  * @note Called in CmdSellRailWagon and DeleteLasWagon,
   356  * @note Called in CmdSellRailWagon and DeleteLasWagon,
   358  * @param v     FrontEngine of the train we want to remove.
   357  * @param v     FrontEngine of the train we want to remove.
   359  */
   358  */
   360 void RemoveVehicleFromGroup(const Vehicle *v)
   359 void RemoveVehicleFromGroup(const Vehicle *v)
   361 {
   360 {
   362 	if (!IsValidVehicle(v) || !(v->HasFront() && v->IsPrimaryVehicle())) return;
   361 	if (!v->IsValid() || !(v->HasFront() && v->IsPrimaryVehicle())) return;
   363 
   362 
   364 	if (!IsDefaultGroupID(v->group_id)) DecreaseGroupNumVehicle(v->group_id);
   363 	if (!IsDefaultGroupID(v->group_id)) DecreaseGroupNumVehicle(v->group_id);
   365 }
   364 }
   366 
   365 
   367 
   366 
   373  */
   372  */
   374 void SetTrainGroupID(Vehicle *v, GroupID new_g)
   373 void SetTrainGroupID(Vehicle *v, GroupID new_g)
   375 {
   374 {
   376 	if (!IsValidGroupID(new_g) && !IsDefaultGroupID(new_g)) return;
   375 	if (!IsValidGroupID(new_g) && !IsDefaultGroupID(new_g)) return;
   377 
   376 
   378 	assert(IsValidVehicle(v) && v->type == VEH_TRAIN && IsFrontEngine(v));
   377 	assert(v->IsValid() && v->type == VEH_TRAIN && IsFrontEngine(v));
   379 
   378 
   380 	for (Vehicle *u = v; u != NULL; u = u->next) {
   379 	for (Vehicle *u = v; u != NULL; u = u->next) {
   381 		if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
   380 		if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
   382 
   381 
   383 		u->group_id = new_g;
   382 		u->group_id = new_g;
   395  * @note Called in CmdBuildRailVehicle, CmdBuildRailWagon, CmdMoveRailVehicle, CmdSellRailWagon
   394  * @note Called in CmdBuildRailVehicle, CmdBuildRailWagon, CmdMoveRailVehicle, CmdSellRailWagon
   396  * @param v First vehicle of the chain.
   395  * @param v First vehicle of the chain.
   397  */
   396  */
   398 void UpdateTrainGroupID(Vehicle *v)
   397 void UpdateTrainGroupID(Vehicle *v)
   399 {
   398 {
   400 	assert(IsValidVehicle(v) && v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v)));
   399 	assert(v->IsValid() && v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v)));
   401 
   400 
   402 	GroupID new_g = IsFrontEngine(v) ? v->group_id : (GroupID)DEFAULT_GROUP;
   401 	GroupID new_g = IsFrontEngine(v) ? v->group_id : (GroupID)DEFAULT_GROUP;
   403 	for (Vehicle *u = v; u != NULL; u = u->next) {
   402 	for (Vehicle *u = v; u != NULL; u = u->next) {
   404 		if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
   403 		if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
   405 
   404 
   414 void RemoveAllGroupsForPlayer(const Player *p)
   413 void RemoveAllGroupsForPlayer(const Player *p)
   415 {
   414 {
   416 	Group *g;
   415 	Group *g;
   417 
   416 
   418 	FOR_ALL_GROUPS(g) {
   417 	FOR_ALL_GROUPS(g) {
   419 		if (p->index == g->owner) DeleteGroup(g);
   418 		if (p->index == g->owner) delete g;
   420 	}
   419 	}
   421 }
   420 }
   422 
   421 
   423 
   422 
   424 static const SaveLoad _group_desc[] = {
   423 static const SaveLoad _group_desc[] = {
   445 static void Load_GROUP(void)
   444 static void Load_GROUP(void)
   446 {
   445 {
   447 	int index;
   446 	int index;
   448 
   447 
   449 	while ((index = SlIterateArray()) != -1) {
   448 	while ((index = SlIterateArray()) != -1) {
   450 		if (!AddBlockIfNeeded(&_Group_pool, index)) {
   449 		Group *g = new (index) Group();
   451 			error("Groups: failed loading savegame: too many groups");
       
   452 		}
       
   453 
       
   454 		Group *g = GetGroup(index);
       
   455 		SlObject(g, _group_desc);
   450 		SlObject(g, _group_desc);
   456 	}
   451 	}
   457 }
   452 }
   458 
   453 
   459 extern const ChunkHandler _group_chunk_handlers[] = {
   454 extern const ChunkHandler _group_chunk_handlers[] = {