changeset 15279:4e1862aebea2 draft

(svn r19914) -Codechange: Wrap a helper class around temporary assignments of _current_company to ensure proper restoration.
author frosch <frosch@openttd.org>
date Mon, 31 May 2010 20:22:57 +0000
parents 7c541560c52b
children 2155d91cbe00
files projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/ai/ai_core.cpp src/ai/ai_gui.cpp src/aircraft_cmd.cpp src/core/backup_type.hpp src/disaster_cmd.cpp src/economy.cpp src/industry_cmd.cpp src/industry_gui.cpp src/misc_cmd.cpp src/openttd.cpp src/rail_cmd.cpp src/roadveh_cmd.cpp src/saveload/afterload.cpp src/town_cmd.cpp src/vehicle.cpp src/water_cmd.cpp
diffstat 19 files changed, 256 insertions(+), 117 deletions(-) [+]
line wrap: on
line diff
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -1676,6 +1676,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\core\backup_type.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\core\bitmath_func.cpp"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -1673,6 +1673,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\core\backup_type.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\core\bitmath_func.cpp"
 				>
 			</File>
--- a/source.list
+++ b/source.list
@@ -344,6 +344,7 @@
 core/alloc_func.cpp
 core/alloc_func.hpp
 core/alloc_type.hpp
+core/backup_type.hpp
 core/bitmath_func.cpp
 core/bitmath_func.hpp
 core/endian_func.hpp
--- a/src/ai/ai_core.cpp
+++ b/src/ai/ai_core.cpp
@@ -10,6 +10,7 @@
 /** @file ai_core.cpp Implementation of AI. */
 
 #include "../stdafx.h"
+#include "../core/backup_type.hpp"
 #include "../core/bitmath_func.hpp"
 #include "../company_base.h"
 #include "../company_func.h"
@@ -68,13 +69,15 @@
 	assert(_settings_game.difficulty.competitor_speed <= 4);
 	if ((AI::frame_counter & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return;
 
+	Backup<CompanyByte> cur_company(_current_company);
 	const Company *c;
 	FOR_ALL_COMPANIES(c) {
 		if (c->is_ai) {
-			_current_company = c->index;
+			cur_company.Change(c->index);
 			c->ai_instance->GameLoop();
 		}
 	}
+	cur_company.Restore();
 
 	/* Occasionally collect garbage; every 255 ticks do one company.
 	 * Effectively collecting garbage once every two months per AI. */
@@ -82,8 +85,6 @@
 		CompanyID cid = (CompanyID)GB(AI::frame_counter, 8, 4);
 		if (Company::IsValidAiID(cid)) Company::Get(cid)->ai_instance->CollectGarbage();
 	}
-
-	_current_company = OWNER_NONE;
 }
 
 /* static */ uint AI::GetTick()
@@ -95,14 +96,13 @@
 {
 	if (_networking && !_network_server) return;
 
-	CompanyID old_company = _current_company;
-	_current_company = company;
+	Backup<CompanyByte> cur_company(_current_company, company);
 	Company *c = Company::Get(company);
 
 	delete c->ai_instance;
 	c->ai_instance = NULL;
 
-	_current_company = old_company;
+	cur_company.Restore();
 
 	InvalidateWindowData(WC_AI_DEBUG, 0, -1);
 	DeleteWindowById(WC_AI_SETTINGS, company);
@@ -112,11 +112,10 @@
 {
 	if (_networking && !_network_server) return;
 
-	CompanyID old_company = _current_company;
-	_current_company = company;
+	Backup<CompanyByte> cur_company(_current_company, company);
 	Company::Get(company)->ai_instance->Suspend();
 
-	_current_company = old_company;
+	cur_company.Restore();
 }
 
 /* static */ void AI::KillAll()
@@ -202,10 +201,9 @@
 	}
 
 	/* Queue the event */
-	CompanyID old_company = _current_company;
-	_current_company = company;
+	Backup<CompanyByte> cur_company(_current_company, company);
 	AIEventController::InsertEvent(event);
-	_current_company = old_company;
+	cur_company.Restore();
 
 	event->Release();
 }
@@ -249,10 +247,9 @@
 		Company *c = Company::GetIfValid(company);
 		assert(c != NULL && c->ai_instance != NULL);
 
-		CompanyID old_company = _current_company;
-		_current_company = company;
+		Backup<CompanyByte> cur_company(_current_company, company);
 		c->ai_instance->Save();
-		_current_company = old_company;
+		cur_company.Restore();
 	} else {
 		AIInstance::SaveEmpty();
 	}
@@ -264,10 +261,9 @@
 		Company *c = Company::GetIfValid(company);
 		assert(c != NULL && c->ai_instance != NULL);
 
-		CompanyID old_company = _current_company;
-		_current_company = company;
+		Backup<CompanyByte> cur_company(_current_company, company);
 		c->ai_instance->Load(version);
-		_current_company = old_company;
+		cur_company.Restore();
 	} else {
 		/* Read, but ignore, the load data */
 		AIInstance::LoadEmpty();
--- a/src/ai/ai_gui.cpp
+++ b/src/ai/ai_gui.cpp
@@ -26,6 +26,7 @@
 #include "../textbuf_gui.h"
 #include "../settings_func.h"
 #include "../network/network_content.h"
+#include "../core/backup_type.hpp"
 
 #include "ai.hpp"
 #include "api/ai_log.hpp"
@@ -819,10 +820,9 @@
 			DrawCompanyIcon(i, button->pos_x + button->current_x / 2 - 7 + offset, this->GetWidget<NWidgetBase>(AID_WIDGET_COMPANY_BUTTON_START + i)->pos_y + 2 + offset);
 		}
 
-		CompanyID old_company = _current_company;
-		_current_company = ai_debug_company;
+		Backup<CompanyByte> cur_company(_current_company, ai_debug_company);
 		AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
-		_current_company = old_company;
+		cur_company.Restore();
 
 		int scroll_count = (log == NULL) ? 0 : log->used;
 		if (this->vscroll.GetCount() != scroll_count) {
@@ -875,10 +875,9 @@
 
 		switch (widget) {
 			case AID_WIDGET_LOG_PANEL: {
-				CompanyID old_company = _current_company;
-				_current_company = ai_debug_company;
+				Backup<CompanyByte> cur_company(_current_company, ai_debug_company);
 				AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
-				_current_company = old_company;
+				cur_company.Restore();
 				if (log == NULL) return;
 
 				int y = this->top_offset;
@@ -915,10 +914,9 @@
 		this->RaiseWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
 		ai_debug_company = show_ai;
 
-		CompanyID old_company = _current_company;
-		_current_company = ai_debug_company;
+		Backup<CompanyByte> cur_company(_current_company, ai_debug_company);
 		AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
-		_current_company = old_company;
+		cur_company.Restore();
 		this->vscroll.SetCount((log == NULL) ? 0 : log->used);
 
 		this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
@@ -1011,8 +1009,7 @@
 		/* If the log message is related to the active company tab, check the break string */
 		if (data == ai_debug_company && this->break_check_enabled && !StrEmpty(this->edit_str_buf)) {
 			/* Get the log instance of the active company */
-			CompanyID old_company = _current_company;
-			_current_company = ai_debug_company;
+			Backup<CompanyByte> cur_company(_current_company, ai_debug_company);
 			AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 
 			if (log != NULL && case_sensitive_break_check?
@@ -1032,7 +1029,7 @@
 				this->highlight_row = log->pos;
 			}
 
-			_current_company = old_company;
+			cur_company.Restore();
 		}
 	}
 
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -36,6 +36,7 @@
 #include "engine_base.h"
 #include "engine_func.h"
 #include "core/random_func.hpp"
+#include "core/backup_type.hpp"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -1203,12 +1204,9 @@
 	 */
 	const Station *st = GetTargetAirportIfValid(v);
 	if (st == NULL) {
-		CommandCost ret;
-		CompanyID old_company = _current_company;
-
-		_current_company = v->owner;
-		ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
-		_current_company = old_company;
+		Backup<CompanyByte> cur_company(_current_company, v->owner);
+		CommandCost ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
+		cur_company.Restore();
 
 		if (ret.Failed()) CrashAirplane(v);
 	} else if (!v->current_order.IsType(OT_GOTO_DEPOT)) {
@@ -1512,9 +1510,9 @@
 
 	/* Send the helicopter to a hangar if needed for replacement */
 	if (v->NeedsAutomaticServicing()) {
-		_current_company = v->owner;
+		Backup<CompanyByte> cur_company(_current_company, v->owner);
 		DoCommand(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
-		_current_company = OWNER_NONE;
+		cur_company.Restore();
 	}
 }
 
@@ -1564,9 +1562,9 @@
 
 	/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
 	if (v->NeedsAutomaticServicing()) {
-		_current_company = v->owner;
+		Backup<CompanyByte> cur_company(_current_company, v->owner);
 		DoCommand(v->tile, v->index, DEPOT_SERVICE, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
-		_current_company = OWNER_NONE;
+		cur_company.Restore();
 	}
 }
 
new file mode 100644
--- /dev/null
+++ b/src/core/backup_type.hpp
@@ -0,0 +1,134 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file backup_type.hpp Class for backupping variables and making sure they are restored later. */
+
+#ifndef BACKUP_TYPE_HPP
+#define BACKUP_TYPE_HPP
+
+/**
+ * Class to backup a specific variable and restore it later.
+ * The variable is not restored automatically, but assertions make sure it is restored.
+ * You have to call either Trash() or Restore() exactly once.
+ */
+template <typename T>
+struct Backup {
+	/**
+	 * Backup variable.
+	 * @param original Variable to backup.
+	 */
+	Backup(T &original) : original(original), valid(true), original_value(original) {}
+
+	/**
+	 * Backup variable and switch to new value.
+	 * @param original Variable to backup.
+	 * @param new_value New value for variable.
+	 */
+	template <typename U>
+	Backup(T &original, const U &new_value) : original(original), valid(true), original_value(original)
+	{
+		/* Note: We use a separate typename U, so type conversions are handled by assignment operator. */
+		original = new_value;
+	}
+
+	/**
+	 * Check whether the variable was restored on object destruction.
+	 */
+	~Backup()
+	{
+		/* Check whether restoration was done */
+		assert(!this->valid);
+	}
+
+	/**
+	 * Checks whether the variable was already restored.
+	 * @return true if variable has already been restored.
+	 */
+	bool IsValid() const
+	{
+		return this->valid;
+	}
+
+	/**
+	 * Returns the backupped value.
+	 * @return value from the backup.
+	 */
+	const T &GetOriginalValue() const
+	{
+		assert(this->valid);
+		return original_value;
+	}
+
+	/**
+	 * Change the value of the variable.
+	 * While this does not touch the backup at all, it ensures that the variable is only modified while backupped.
+	 * @param new_value New value for variable.
+	 */
+	template <typename U>
+	void Change(const U &new_value)
+	{
+		/* Note: We use a separate typename U, so type conversions are handled by assignment operator. */
+		assert(this->valid);
+		original = new_value;
+	}
+
+	/**
+	 * Revert the variable to its original value, but do not mark it as restored.
+	 */
+	void Revert()
+	{
+		assert(this->valid);
+		this->original = this->original_value;
+	}
+
+	/**
+	 * Trash the backup. The variable shall not be restored anymore.
+	 */
+	void Trash()
+	{
+		assert(this->valid);
+		this->valid = false;
+	}
+
+	/**
+	 * Restore the variable.
+	 */
+	void Restore()
+	{
+		this->Revert();
+		this->Trash();
+	}
+
+	/**
+	 * Update the backup.
+	 * That is trash the old value and make the current value of the variable the value to be restored later.
+	 */
+	void Update()
+	{
+		assert(this->valid);
+		this->original_value = this->original;
+	}
+
+	/**
+	 * Check whether the variable is currently equals the backup.
+	 * @return true if equal
+	 */
+	bool Verify() const
+	{
+		assert(this->valid);
+		return this->original_value == this->original;
+	}
+
+private:
+	T &original;
+	bool valid;
+	T original_value;
+};
+
+#endif /* BACKUP_TYPE_HPP */
--- a/src/disaster_cmd.cpp
+++ b/src/disaster_cmd.cpp
@@ -43,6 +43,7 @@
 #include "ai/ai.hpp"
 #include "company_base.h"
 #include "core/random_func.hpp"
+#include "core/backup_type.hpp"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -72,10 +73,9 @@
 	switch (GetTileType(tile)) {
 		case MP_RAILWAY:
 			if (Company::IsHumanID(GetTileOwner(tile))) {
-				CompanyID old_company = _current_company;
-				_current_company = OWNER_WATER;
+				Backup<CompanyByte> cur_company(_current_company, OWNER_WATER);
 				DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
-				_current_company = old_company;
+				cur_company.Restore();
 
 				/* update signals in buffer */
 				UpdateSignalsInBuffer();
@@ -83,10 +83,9 @@
 			break;
 
 		case MP_HOUSE: {
-			CompanyID old_company = _current_company;
-			_current_company = OWNER_NONE;
+			Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
 			DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
-			_current_company = old_company;
+			cur_company.Restore();
 			break;
 		}
 
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -47,6 +47,7 @@
 #include "core/pool_func.hpp"
 #include "newgrf.h"
 #include "engine_base.h"
+#include "core/backup_type.hpp"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -304,7 +305,7 @@
 #endif /* ENABLE_NETWORK */
 
 	Town *t;
-	CompanyID old = _current_company;
+	Backup<CompanyByte> cur_company(_current_company, old_owner);
 
 	assert(old_owner != new_owner);
 
@@ -313,7 +314,6 @@
 		uint i;
 
 		/* See if the old_owner had shares in other companies */
-		_current_company = old_owner;
 		FOR_ALL_COMPANIES(c) {
 			for (i = 0; i < 4; i++) {
 				if (c->share_owners[i] == old_owner) {
@@ -327,9 +327,10 @@
 		}
 
 		/* Sell all the shares that people have on this company */
+		Backup<CompanyByte> cur_company2(_current_company);
 		c = Company::Get(old_owner);
 		for (i = 0; i < 4; i++) {
-			_current_company = c->share_owners[i];
+			cur_company2.Change(c->share_owners[i]);
 			if (_current_company != INVALID_OWNER) {
 				/* Sell the shares */
 				CommandCost res = DoCommand(0, old_owner, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
@@ -338,10 +339,9 @@
 				SubtractMoneyFromCompany(res);
 			}
 		}
+		cur_company2.Restore();
 	}
 
-	_current_company = old_owner;
-
 	/* Temporarily increase the company's money, to be sure that
 	 * removing his/her property doesn't fail because of lack of money.
 	 * Not too drastically though, because it could overflow */
@@ -472,7 +472,7 @@
 	/* Change colour of existing windows */
 	if (new_owner != INVALID_OWNER) ChangeWindowOwner(old_owner, new_owner);
 
-	_current_company = old;
+	cur_company.Restore();
 
 	MarkWholeScreenDirty();
 }
@@ -553,11 +553,13 @@
 	Station *st;
 	Company *c;
 
+	Backup<CompanyByte> cur_company(_current_company);
 	FOR_ALL_STATIONS(st) {
-		_current_company = st->owner;
+		cur_company.Change(st->owner);
 		CommandCost cost(EXPENSES_PROPERTY, _price[PR_STATION_VALUE] >> 1);
 		SubtractMoneyFromCompany(cost);
 	}
+	cur_company.Restore();
 
 	if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month))
 		return;
@@ -686,8 +688,9 @@
 {
 	const Company *c;
 
+	Backup<CompanyByte> cur_company(_current_company);
 	FOR_ALL_COMPANIES(c) {
-		_current_company = c->index;
+		cur_company.Change(c->index);
 
 		/* Over a year the paid interest should be "loan * interest percentage",
 		 * but... as that number is likely not dividable by 12 (pay each month),
@@ -705,6 +708,7 @@
 
 		SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price[PR_STATION_VALUE] >> 2));
 	}
+	cur_company.Restore();
 }
 
 static void HandleEconomyFluctuations()
@@ -1023,8 +1027,7 @@
 
 	if (this->visual_profit == 0) return;
 
-	CompanyID old_company = _current_company;
-	_current_company = this->front->owner;
+	Backup<CompanyByte> cur_company(_current_company, this->front->owner);
 
 	SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit));
 	this->front->profit_this_year += this->visual_profit << 8;
@@ -1039,7 +1042,7 @@
 		ShowFeederIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, this->visual_profit);
 	}
 
-	_current_company = old_company;
+	cur_company.Restore();
 }
 
 /**
@@ -1426,8 +1429,6 @@
 		RecomputePrices();
 	}
 	CompaniesPayInterest();
-	/* Reset the _current_company flag */
-	_current_company = OWNER_NONE;
 	HandleEconomyFluctuations();
 }
 
@@ -1457,14 +1458,14 @@
 	}
 
 	value = CalculateCompanyValue(c) >> 2;
-	CompanyID old_company = _current_company;
+	Backup<CompanyByte> cur_company(_current_company);
 	for (i = 0; i != 4; i++) {
 		if (c->share_owners[i] != COMPANY_SPECTATOR) {
-			_current_company = c->share_owners[i];
+			cur_company.Change(c->share_owners[i]);
 			SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -value));
 		}
 	}
-	_current_company = old_company;
+	cur_company.Restore();
 
 	if (c->is_ai) AI::Stop(c->index);
 
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -43,6 +43,7 @@
 #include "ai/ai.hpp"
 #include "core/pool_func.hpp"
 #include "subsidy_func.h"
+#include "core/backup_type.hpp"
 
 #include "table/strings.h"
 #include "table/industry_land.h"
@@ -1040,17 +1041,17 @@
 static bool SearchLumberMillTrees(TileIndex tile, void *user_data)
 {
 	if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees
-		CompanyID old_company = _current_company;
 		/* found a tree */
 
-		_current_company = OWNER_NONE;
+		Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
+
 		_industry_sound_ctr = 1;
 		_industry_sound_tile = tile;
 		SndPlayTileFx(SND_38_CHAINSAW, tile);
 
 		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
-		_current_company = old_company;
+		cur_company.Restore();
 		return true;
 	}
 	return false;
@@ -1371,10 +1372,9 @@
 				}
 
 				/* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
-				CompanyID old_company = _current_company;
-				_current_company = OWNER_TOWN;
+				Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
 				CommandCost ret = DoCommand(cur_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
-				_current_company = old_company;
+				cur_company.Restore();
 
 				if (ret.Failed()) return ret;
 			} else {
@@ -1484,8 +1484,7 @@
 
 	/* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
 	 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
-	CompanyID old_company = _current_company;
-	_current_company = OWNER_TOWN;
+	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
 
 	TILE_LOOP(tile_walk, size_x, size_y, cur_tile) {
 		curh = TileHeight(tile_walk);
@@ -1493,13 +1492,13 @@
 			/* This tile needs terraforming. Check if we can do that without
 			 *  damaging the surroundings too much. */
 			if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
-				_current_company = old_company;
+				cur_company.Restore();
 				return false;
 			}
 			/* This is not 100% correct check, but the best we can do without modifying the map.
 			 *  What is missing, is if the difference in height is more than 1.. */
 			if (DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND).Failed()) {
-				_current_company = old_company;
+				cur_company.Restore();
 				return false;
 			}
 		}
@@ -1519,7 +1518,7 @@
 		}
 	}
 
-	_current_company = old_company;
+	cur_company.Restore();
 	return true;
 }
 
@@ -1789,8 +1788,7 @@
 	if (_game_mode != GM_EDITOR && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry()) {
 		if (flags & DC_EXEC) {
 			/* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
-			CompanyID founder = _current_company;
-			_current_company = OWNER_TOWN;
+			Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
 			/* Prospecting has a chance to fail, however we cannot guarantee that something can
 			 * be built on the map, so the chance gets lower when the map is fuller, but there
 			 * is nothing we can really do about that. */
@@ -1800,11 +1798,11 @@
 					 * because parameter evaluation order is not guaranteed in the c++ standard
 					 */
 					tile = RandomTile();
-					CommandCost ret = CreateNewIndustryHelper(tile, it, flags, indspec, RandomRange(indspec->num_table), random_var8f, random_initial_bits, founder, &ind);
+					CommandCost ret = CreateNewIndustryHelper(tile, it, flags, indspec, RandomRange(indspec->num_table), random_var8f, random_initial_bits, cur_company.GetOriginalValue(), &ind);
 					if (ret.Succeeded()) break;
 				}
 			}
-			_current_company = founder;
+			cur_company.Restore();
 		}
 	} else {
 		int count = indspec->num_table;
@@ -1892,8 +1890,7 @@
  */
 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
 {
-	CompanyID old_company = _current_company;
-	_current_company = OWNER_NONE;
+	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
 
 	IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
 
@@ -1901,7 +1898,7 @@
 		if (CreateNewIndustry(RandomTile(), type) != NULL) break;
 	}
 
-	_current_company = old_company;
+	cur_company.Restore();
 }
 
 /**
@@ -2417,8 +2414,7 @@
 		return;  // Nothing to do? get out
 	}
 
-	CompanyID old_company = _current_company;
-	_current_company = OWNER_NONE;
+	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
 
 	/* perform the required industry changes for the day */
 	for (uint16 j = 0; j < change_loop; j++) {
@@ -2434,7 +2430,7 @@
 		}
 	}
 
-	_current_company = old_company;
+	cur_company.Restore();
 
 	/* production-change */
 	InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
@@ -2443,8 +2439,7 @@
 void IndustryMonthlyLoop()
 {
 	Industry *i;
-	CompanyID old_company = _current_company;
-	_current_company = OWNER_NONE;
+	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
 
 	FOR_ALL_INDUSTRIES(i) {
 		UpdateIndustryStatistics(i);
@@ -2456,7 +2451,7 @@
 		}
 	}
 
-	_current_company = old_company;
+	cur_company.Restore();
 
 	/* production-change */
 	InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
--- a/src/industry_gui.cpp
+++ b/src/industry_gui.cpp
@@ -33,6 +33,7 @@
 #include "company_base.h"
 #include "core/geometry_func.hpp"
 #include "core/random_func.hpp"
+#include "core/backup_type.hpp"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -522,12 +523,14 @@
 				return;
 			}
 
-			_current_company = OWNER_NONE;
+			Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
 			_generating_world = true;
 			_ignore_restrictions = true;
+
 			DoCommandP(tile, (InteractiveRandomRange(indsp->num_table) << 8) | this->selected_type, seed,
 					CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY), &CcBuildIndustry);
 
+			cur_company.Restore();
 			_ignore_restrictions = false;
 			_generating_world = false;
 		} else {
--- a/src/misc_cmd.cpp
+++ b/src/misc_cmd.cpp
@@ -21,6 +21,7 @@
 #include "company_func.h"
 #include "company_gui.h"
 #include "company_base.h"
+#include "core/backup_type.hpp"
 
 #include "table/strings.h"
 
@@ -228,10 +229,9 @@
 
 	if (flags & DC_EXEC) {
 		/* Add money to company */
-		CompanyID old_company = _current_company;
-		_current_company = (CompanyID)p2;
+		Backup<CompanyByte> cur_company(_current_company, (CompanyID)p2);
 		SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -amount.GetCost()));
-		_current_company = old_company;
+		cur_company.Restore();
 	}
 
 	/* Subtract money from local-company */
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -65,6 +65,7 @@
 #include "engine_func.h"
 #include "core/random_func.hpp"
 #include "rail_gui.h"
+#include "core/backup_type.hpp"
 
 #include "newgrf_commons.h"
 
@@ -1215,8 +1216,7 @@
 
 		/* All these actions has to be done from OWNER_NONE
 		 *  for multiplayer compatibility */
-		CompanyID old_company = _current_company;
-		_current_company = OWNER_NONE;
+		Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
 
 		AnimateAnimatedTiles();
 		IncreaseDate();
@@ -1229,7 +1229,7 @@
 
 		CallWindowTickEvent();
 		NewsLoop();
-		_current_company = old_company;
+		cur_company.Restore();
 	}
 }
 
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -36,6 +36,7 @@
 #include "town.h"
 #include "pbs.h"
 #include "company_base.h"
+#include "core/backup_type.hpp"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -641,9 +642,10 @@
 
 		TrackBits to_remove = lower_track & rail_bits;
 		if (to_remove != 0) {
-			_current_company = OWNER_WATER;
-			if (DoCommand(t, 0, FIND_FIRST_BIT(to_remove), DC_EXEC, CMD_REMOVE_SINGLE_RAIL).Failed()) return flooded; // not yet floodable
-			flooded = true;
+			Backup<CompanyByte> cur_company(_current_company, OWNER_WATER);
+			flooded = DoCommand(t, 0, FIND_FIRST_BIT(to_remove), DC_EXEC, CMD_REMOVE_SINGLE_RAIL).Succeeded();
+			cur_company.Restore();
+			if (!flooded) return flooded; // not yet floodable
 			rail_bits = rail_bits & ~to_remove;
 			if (rail_bits == 0) {
 				MakeShore(t);
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -41,6 +41,7 @@
 #include "engine_base.h"
 #include "company_base.h"
 #include "engine_func.h"
+#include "core/backup_type.hpp"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -1159,12 +1160,11 @@
 static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadBits r)
 {
 	/* The 'current' company is not necessarily the owner of the vehicle. */
-	CompanyID original_company = _current_company;
-	_current_company = c;
+	Backup<CompanyByte> cur_company(_current_company, c);
 
 	CommandCost ret = DoCommand(t, ROADTYPE_TRAM << 4 | r, 0, DC_NONE, CMD_BUILD_ROAD);
 
-	_current_company = original_company;
+	cur_company.Restore();
 	return ret.Succeeded();
 }
 
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -52,6 +52,7 @@
 #include "../engine_base.h"
 #include "../engine_func.h"
 #include "../rail_gui.h"
+#include "../core/backup_type.hpp"
 
 #include "table/strings.h"
 
@@ -1570,8 +1571,9 @@
 			if (IsBuoyTile(t) || IsDriveThroughStopTile(t) || IsTileType(t, MP_WATER)) {
 				Owner o = GetTileOwner(t);
 				if (o < MAX_COMPANIES && !Company::IsValidID(o)) {
-					_current_company = o;
+					Backup<CompanyByte> cur_company(_current_company, o);
 					ChangeTileOwner(t, o, INVALID_OWNER);
+					cur_company.Restore();
 				}
 				if (IsBuoyTile(t)) {
 					/* reset buoy owner to OWNER_NONE in the station struct
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -45,6 +45,7 @@
 #include "townname_func.h"
 #include "townname_type.h"
 #include "core/random_func.hpp"
+#include "core/backup_type.hpp"
 
 #include "table/strings.h"
 #include "table/town_land.h"
@@ -515,7 +516,7 @@
 		}
 	}
 
-	_current_company = OWNER_TOWN;
+	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
 
 	if ((hs->building_flags & BUILDING_HAS_1_TILE) &&
 			HasBit(t->flags, TOWN_IS_FUNDED) &&
@@ -530,7 +531,7 @@
 		if (GB(r, 24, 8) >= 12) BuildTownHouse(t, tile);
 	}
 
-	_current_company = OWNER_NONE;
+	cur_company.Restore();
 }
 
 static CommandCost ClearTile_Town(TileIndex tile, DoCommandFlag flags)
@@ -1296,8 +1297,7 @@
 	};
 
 	/* Current "company" is a town */
-	CompanyID old_company = _current_company;
-	_current_company = OWNER_TOWN;
+	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN);
 
 	TileIndex tile = t->xy; // The tile we are working with ATM
 
@@ -1306,7 +1306,7 @@
 	for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
 		if (GetTownRoadBits(tile) != ROAD_NONE) {
 			int r = GrowTownAtRoad(t, tile);
-			_current_company = old_company;
+			cur_company.Restore();
 			return r != 0;
 		}
 		tile = TILE_ADD(tile, ToTileIndexDiff(*ptr));
@@ -1321,7 +1321,7 @@
 			if (!IsTileType(tile, MP_HOUSE) && GetTileSlope(tile, NULL) == SLOPE_FLAT) {
 				if (DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR).Succeeded()) {
 					DoCommand(tile, GenRandomRoadBits(), t->index, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD);
-					_current_company = old_company;
+					cur_company.Restore();
 					return true;
 				}
 			}
@@ -1329,7 +1329,7 @@
 		}
 	}
 
-	_current_company = old_company;
+	cur_company.Restore();
 	return false;
 }
 
@@ -2383,10 +2383,9 @@
 		return false;
 	}
 
-	CompanyID old = _current_company;
-	_current_company = OWNER_NONE;
+	Backup<CompanyByte> cur_company(_current_company, OWNER_NONE);
 	CommandCost r = DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
-	_current_company = old;
+	cur_company.Restore();
 
 	if (r.Failed()) return false;
 
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -50,6 +50,7 @@
 #include "core/random_func.hpp"
 #include "engine_base.h"
 #include "newgrf.h"
+#include "core/backup_type.hpp"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -772,10 +773,11 @@
 		}
 	}
 
+	Backup<CompanyByte> cur_company(_current_company);
 	for (AutoreplaceMap::iterator it = _vehicles_to_autoreplace.Begin(); it != _vehicles_to_autoreplace.End(); it++) {
 		v = it->first;
 		/* Autoreplace needs the current company set as the vehicle owner */
-		_current_company = v->owner;
+		cur_company.Change(v->owner);
 
 		/* Start vehicle if we stopped them in VehicleEnteredDepotThisTick()
 		 * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that
@@ -816,7 +818,7 @@
 		AddVehicleNewsItem(message, NS_ADVICE, v->index);
 	}
 
-	_current_company = OWNER_NONE;
+	cur_company.Restore();
 }
 
 static void DoDrawVehicle(const Vehicle *v)
@@ -1110,8 +1112,9 @@
 		}
 
 		if (t.IsRefit()) {
-			_current_company = v->owner;
+			Backup<CompanyByte> cur_company(_current_company, v->owner);
 			CommandCost cost = DoCommand(v->tile, v->index, t.GetRefitCargo() | t.GetRefitSubtype() << 8, DC_EXEC, GetCmdRefitVeh(v));
+			cur_company.Restore();
 
 			if (cost.Failed()) {
 				_vehicles_to_autoreplace[v] = false;
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -34,6 +34,7 @@
 #include "station_base.h"
 #include "ai/ai.hpp"
 #include "core/random_func.hpp"
+#include "core/backup_type.hpp"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -881,7 +882,7 @@
 
 	bool flooded = false; // Will be set to true if something is changed.
 
-	_current_company = OWNER_WATER;
+	Backup<CompanyByte> cur_company(_current_company, OWNER_WATER);
 
 	Slope tileh = GetTileSlope(target, NULL);
 	if (tileh != SLOPE_FLAT) {
@@ -933,7 +934,7 @@
 		UpdateSignalsInBuffer();
 	}
 
-	_current_company = OWNER_NONE;
+	cur_company.Restore();
 }
 
 /**
@@ -941,7 +942,7 @@
  */
 static void DoDryUp(TileIndex tile)
 {
-	_current_company = OWNER_WATER;
+	Backup<CompanyByte> cur_company(_current_company, OWNER_WATER);
 
 	switch (GetTileType(tile)) {
 		case MP_RAILWAY:
@@ -977,7 +978,7 @@
 		default: NOT_REACHED();
 	}
 
-	_current_company = OWNER_NONE;
+	cur_company.Restore();
 }
 
 /**