Changeset - r24482:081733badf2c
[Not reviewed]
master
0 11 0
Pavel Stupnikov - 3 years ago 2020-12-22 13:29:48
dp@dpointer.org
Feature: Set exclusive access to industry from GS (#8115)
11 files changed with 137 insertions and 5 deletions:
0 comments (0 inline, 0 general)
src/economy.cpp
Show inline comments
 
@@ -1039,12 +1039,14 @@ static uint DeliverGoodsToIndustry(const
 
		/* Check if matching cargo has been found */
 
		if (cargo_index >= lengthof(ind->accepts_cargo)) continue;
 

	
 
		/* Check if industry temporarily refuses acceptance */
 
		if (IndustryTemporarilyRefusesCargo(ind, cargo_type)) continue;
 

	
 
		if (ind->exclusive_supplier != INVALID_OWNER && ind->exclusive_supplier != st->owner) continue;
 

	
 
		/* Insert the industry into _cargo_delivery_destinations, if not yet contained */
 
		include(_cargo_delivery_destinations, ind);
 

	
 
		uint amount = min(num_pieces, 0xFFFFU - ind->incoming_cargo_waiting[cargo_index]);
 
		ind->incoming_cargo_waiting[cargo_index] += amount;
 
		ind->last_cargo_accepted_at[cargo_index] = _date;
src/economy_func.h
Show inline comments
 
@@ -26,13 +26,13 @@ extern Economy _economy;
 
extern Prices _price;
 

	
 
int UpdateCompanyRatingAndValue(Company *c, bool update);
 
void StartupIndustryDailyChanges(bool init_counter);
 

	
 
Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type);
 
uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations);
 
uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations, Owner exclusivity = INVALID_OWNER);
 

	
 
void PrepareUnload(Vehicle *front_v);
 
void LoadUnloadStation(Station *st);
 

	
 
Money GetPrice(Price index, uint cost_factor, const struct GRFFile *grf_file, int shift = 0);
 

	
src/industry.h
Show inline comments
 
@@ -87,12 +87,14 @@ struct Industry : IndustryPool::PoolItem
 

	
 
	Owner founder;                 ///< Founder of the industry
 
	Date construction_date;        ///< Date of the construction of the industry
 
	uint8 construction_type;       ///< Way the industry was constructed (@see IndustryConstructionType)
 
	Date last_cargo_accepted_at[INDUSTRY_NUM_INPUTS]; ///< Last day each cargo type was accepted by this industry
 
	byte selected_layout;          ///< Which tile layout was used when creating the industry
 
	Owner exclusive_supplier;      ///< Which company has exclusive rights to deliver cargo (INVALID_OWNER = anyone)
 
	Owner exclusive_consumer;      ///< Which company has exclusive rights to take cargo (INVALID_OWNER = anyone)
 

	
 
	uint16 random;                 ///< Random value used for randomisation of all kinds of things
 

	
 
	PersistentStorage *psa;        ///< Persistent storage for NewGRF industries.
 

	
 
	Industry(TileIndex tile = INVALID_TILE) : location(tile, 0, 0) {}
src/industry_cmd.cpp
Show inline comments
 
@@ -14,12 +14,13 @@
 
#include "landscape.h"
 
#include "viewport_func.h"
 
#include "command_func.h"
 
#include "town.h"
 
#include "news_func.h"
 
#include "cheat_type.h"
 
#include "company_base.h"
 
#include "genworld.h"
 
#include "tree_map.h"
 
#include "newgrf_cargo.h"
 
#include "newgrf_debug.h"
 
#include "newgrf_industrytiles.h"
 
#include "autoslope.h"
 
@@ -536,13 +537,13 @@ static bool TransportIndustryGoods(TileI
 

	
 
			/* fluctuating economy? */
 
			if (EconomyIsInRecession()) cw = (cw + 1) / 2;
 

	
 
			i->this_month_production[j] += cw;
 

	
 
			uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, &i->stations_near);
 
			uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, &i->stations_near, i->exclusive_consumer);
 
			i->this_month_transported[j] += am;
 

	
 
			moved_cargo |= (am != 0);
 
		}
 
	}
 

	
 
@@ -943,12 +944,15 @@ static TrackStatus GetTileTrackStatus_In
 

	
 
static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
 
{
 
	/* If the founder merges, the industry was created by the merged company */
 
	Industry *i = Industry::GetByTile(tile);
 
	if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
 

	
 
	if (i->exclusive_supplier == old_owner) i->exclusive_supplier = new_owner;
 
	if (i->exclusive_consumer == old_owner) i->exclusive_consumer = new_owner;
 
}
 

	
 
/**
 
 * Check whether the tile is a forest.
 
 * @param tile the tile to investigate.
 
 * @return true if and only if the tile is a forest
 
@@ -1761,12 +1765,15 @@ static void DoCreateNewIndustry(Industry
 

	
 
	/* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
 
	 * 0 = created prior of newindustries
 
	 * else, chosen layout + 1 */
 
	i->selected_layout = (byte)(layout_index + 1);
 

	
 
	i->exclusive_supplier = INVALID_OWNER;
 
	i->exclusive_consumer = INVALID_OWNER;
 

	
 
	i->prod_level = PRODLEVEL_DEFAULT;
 

	
 
	/* Call callbacks after the regular fields got initialised. */
 

	
 
	if (HasBit(indspec->callback_mask, CBM_IND_PROD_CHANGE_BUILD)) {
 
		uint16 res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
 
@@ -2055,14 +2062,19 @@ CommandCost CmdBuildIndustry(TileIndex t
 
 * @param tile Unused.
 
 * @param flags Type of operation.
 
 * @param p1 IndustryID
 
 * @param p2 various bitstuffed elements
 
 * - p2 = (bit 0 - 7) - action to perform:
 
 *                      0 = set control flags
 
 *                      1 = set exclusive supplier
 
 *                      2 = set exclusive consumer
 
 * - p2 = (bit 8 - 15) - IndustryControlFlags
 
 *                       (only used with set control flags)
 
 * - p2 = (bit 16 - 23) - CompanyID to set or INVALID_OWNER (available to everyone) or
 
 *                        OWNER_NONE (neutral stations only) or OWNER_DEITY (no one)
 
 *                        (only used with set exclusive supplier / consumer)
 
 * @param text unused
 
 * @return Empty cost or an error.
 
 */
 
CommandCost CmdIndustryCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	if (_current_company != OWNER_DEITY) return CMD_ERROR;
 
@@ -2078,12 +2090,30 @@ CommandCost CmdIndustryCtrl(TileIndex ti
 

	
 
			if (flags & DC_EXEC) ind->ctlflags = ctlflags;
 

	
 
			break;
 
		}
 

	
 
		case 1:
 
		case 2: {
 
			Owner company_id = (Owner)GB(p2, 16, 8);
 

	
 
			if (company_id != OWNER_NONE && company_id != INVALID_OWNER && company_id != OWNER_DEITY
 
				&& !Company::IsValidID(company_id)) return CMD_ERROR;
 

	
 
			if (flags & DC_EXEC) {
 
				if (action == 1) {
 
					ind->exclusive_supplier = company_id;
 
				} else {
 
					ind->exclusive_consumer = company_id;
 
				}
 
			}
 

	
 
			break;
 
		}
 

	
 
		default:
 
			NOT_REACHED();
 
	}
 

	
 
	return CommandCost();
 
}
src/saveload/afterload.cpp
Show inline comments
 
@@ -3122,12 +3122,20 @@ bool AfterLoadGame()
 
			if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) != TRANSPORT_ROAD) {
 
				SetRoadTypes(t, INVALID_ROADTYPE, INVALID_ROADTYPE);
 
			}
 
		}
 
	}
 

	
 
	/* Make sure all industries exclusive supplier/consumer set correctly. */
 
	if (IsSavegameVersionBefore(SLV_GS_INDUSTRY_CONTROL)) {
 
		for (Industry *i : Industry::Iterate()) {
 
			i->exclusive_supplier = INVALID_OWNER;
 
			i->exclusive_consumer = INVALID_OWNER;
 
		}
 
	}
 

	
 
	/* Compute station catchment areas. This is needed here in case UpdateStationAcceptance is called below. */
 
	Station::RecomputeCatchmentForAll();
 

	
 
	/* Station acceptance is some kind of cache */
 
	if (IsSavegameVersionBefore(SLV_127)) {
 
		for (Station *st : Station::Iterate()) UpdateStationAcceptance(st, false);
src/saveload/industry_sl.cpp
Show inline comments
 
@@ -61,12 +61,14 @@ static const SaveLoad _industry_desc[] =
 
	SLE_CONDVAR(Industry, founder,                    SLE_UINT8,                 SLV_70, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, construction_date,          SLE_INT32,                 SLV_70, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, construction_type,          SLE_UINT8,                 SLV_70, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, last_cargo_accepted_at[0],  SLE_INT32,                 SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
 
	SLE_CONDARR(Industry, last_cargo_accepted_at,     SLE_INT32, 16,            SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, selected_layout,            SLE_UINT8,                 SLV_73, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, exclusive_supplier,         SLE_UINT8,                 SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
 
	SLE_CONDVAR(Industry, exclusive_consumer,         SLE_UINT8,                 SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
 

	
 
	SLEG_CONDARR(_old_ind_persistent_storage.storage, SLE_UINT32, 16,            SLV_76, SLV_161),
 
	SLE_CONDREF(Industry, psa,                        REF_STORAGE,              SLV_161, SL_MAX_VERSION),
 

	
 
	SLE_CONDNULL(1, SLV_82, SLV_197), // random_triggers
 
	SLE_CONDVAR(Industry, random,                     SLE_UINT16,                SLV_82, SL_MAX_VERSION),
src/saveload/saveload.h
Show inline comments
 
@@ -317,13 +317,13 @@ enum SaveLoadVersion : uint16 {
 
	 * the version is masked with 0x8000, and the true version is stored in
 
	 * its own chunk with feature toggles.
 
	 */
 
	SLV_START_PATCHPACKS,                   ///< 220  First known patchpack to use a version just above ours.
 
	SLV_END_PATCHPACKS = 286,               ///< 286  Last known patchpack to use a version just above ours.
 

	
 
	SLV_GS_INDUSTRY_CONTROL,                ///< 287  PR#7912 GS industry control.
 
	SLV_GS_INDUSTRY_CONTROL,                ///< 287  PR#7912 and PR#8115 GS industry control.
 

	
 
	SL_MAX_VERSION,                         ///< Highest possible saveload version
 
};
 

	
 
/** Save or load result codes. */
 
enum SaveOrLoadResult {
src/script/api/game_changelog.hpp
Show inline comments
 
@@ -20,14 +20,18 @@
 
 * API additions:
 
 * \li GSEventStoryPageButtonClick
 
 * \li GSEventStoryPageTileSelect
 
 * \li GSEventStoryPageVehicleSelect
 
 * \li GSIndustry::GetCargoLastAcceptedDate
 
 * \li GSIndustry::GetControlFlags
 
 * \li GSIndustry::GetExclusiveConsumer
 
 * \li GSIndustry::GetExclusiveSupplier
 
 * \li GSIndustry::GetLastProductionYear
 
 * \li GSIndustry::SetControlFlags
 
 * \li GSIndustry::SetExclusiveConsumer
 
 * \li GSIndustry::SetExclusiveSupplier
 
 * \li GSStoryPage::MakePushButtonReference
 
 * \li GSStoryPage::MakeTileButtonReference
 
 * \li GSStoryPage::MakeVehicleButtonReference
 
 * \li GSPriorityQueue
 
 *
 
 * \b 1.10.0
src/script/api/script_industry.cpp
Show inline comments
 
@@ -7,13 +7,16 @@
 

	
 
/** @file script_industry.cpp Implementation of ScriptIndustry. */
 

	
 
#include "../../stdafx.h"
 
#include "script_industry.hpp"
 
#include "script_cargo.hpp"
 
#include "script_company.hpp"
 
#include "script_error.hpp"
 
#include "script_map.hpp"
 
#include "../../company_base.h"
 
#include "../../industry.h"
 
#include "../../strings_func.h"
 
#include "../../station_base.h"
 
#include "../../newgrf_industries.h"
 
#include "table/strings.h"
 
#include <numeric>
 
@@ -238,6 +241,44 @@ bool ScriptIndustry::SetControlFlags(Ind
 
{
 
	if (ScriptObject::GetCompany() != OWNER_DEITY) return false;
 
	if (!IsValidIndustry(industry_id)) return false;
 

	
 
	return ScriptObject::DoCommand(0, industry_id, 0 | ((control_flags & ::INDCTL_MASK) << 8), CMD_INDUSTRY_CTRL);
 
}
 

	
 
/* static */ ScriptCompany::CompanyID ScriptIndustry::GetExclusiveSupplier(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return ScriptCompany::COMPANY_INVALID;
 

	
 
	auto company_id = ::Industry::Get(industry_id)->exclusive_supplier;
 
	if (!::Company::IsValidID(company_id)) return ScriptCompany::COMPANY_INVALID;
 

	
 
	return (ScriptCompany::CompanyID)((byte)company_id);
 
}
 

	
 
/* static */ bool ScriptIndustry::SetExclusiveSupplier(IndustryID industry_id, ScriptCompany::CompanyID company_id)
 
{
 
	EnforcePrecondition(false, IsValidIndustry(industry_id));
 

	
 
	auto company = ScriptCompany::ResolveCompanyID(company_id);
 
	::Owner owner = (company == ScriptCompany::COMPANY_INVALID ? ::INVALID_OWNER : (::Owner)company);
 
	return ScriptObject::DoCommand(0, industry_id, 1 | (((uint8)owner) << 16), CMD_INDUSTRY_CTRL);
 
}
 

	
 
/* static */ ScriptCompany::CompanyID ScriptIndustry::GetExclusiveConsumer(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return ScriptCompany::COMPANY_INVALID;
 

	
 
	auto company_id = ::Industry::Get(industry_id)->exclusive_consumer;
 
	if (!::Company::IsValidID(company_id)) return ScriptCompany::COMPANY_INVALID;
 

	
 
	return (ScriptCompany::CompanyID)((byte)company_id);
 
}
 

	
 
/* static */ bool ScriptIndustry::SetExclusiveConsumer(IndustryID industry_id, ScriptCompany::CompanyID company_id)
 
{
 
	EnforcePrecondition(false, IsValidIndustry(industry_id));
 

	
 
	auto company = ScriptCompany::ResolveCompanyID(company_id);
 
	::Owner owner = (company == ScriptCompany::COMPANY_INVALID ? ::INVALID_OWNER : (::Owner)company);
 
	return ScriptObject::DoCommand(0, industry_id, 2 | (((uint8)owner) << 16), CMD_INDUSTRY_CTRL);
 
}
src/script/api/script_industry.hpp
Show inline comments
 
@@ -7,14 +7,15 @@
 

	
 
/** @file script_industry.hpp Everything to query and build industries. */
 

	
 
#ifndef SCRIPT_INDUSTRY_HPP
 
#define SCRIPT_INDUSTRY_HPP
 

	
 
#include "script_company.hpp"
 
#include "script_date.hpp"
 
#include "script_object.hpp"
 
#include "script_date.hpp"
 
#include "../../industry.h"
 

	
 
/**
 
 * Class that handles all industry related functions.
 
 * @api ai game
 
 */
 
@@ -256,9 +257,50 @@ public:
 
	 * @pre IsValidIndustry(industry_id).
 
	 * @pre No ScriptCompanyMode may be in scope.
 
	 * @return True if the action succeeded.
 
	 * @api -ai
 
	 */
 
	static bool SetControlFlags(IndustryID industry_id, uint32 control_flags);
 

	
 
	/**
 
	 * Find out which company currently has the exclusive rights to deliver cargo to the industry.
 
	 * @param industry_id The index of the industry.
 
	 * @pre IsValidIndustry(industry_id).
 
	 * @return The company that has the exclusive rights. The value
 
	 *         ScriptCompany::COMPANY_INVALID means that there are currently no
 
	 *         exclusive rights given out to anyone.
 
	 */
 
	static ScriptCompany::CompanyID GetExclusiveSupplier(IndustryID industry_id);
 

	
 
	/**
 
	 * Sets or resets the company that has exclusive right to deliver cargo to the industry.
 
	 * @param industry_id The index of the industry.
 
	 * @param company_id The company to set (ScriptCompany::COMPANY_INVALID to reset).
 
	 * @pre IsValidIndustry(industry_id).
 
	 * @return True if the action succeeded.
 
	 * @api -ai
 
	 */
 
	static bool SetExclusiveSupplier(IndustryID industry_id, ScriptCompany::CompanyID company_id);
 

	
 
	/**
 
	 * Find out which company currently has the exclusive rights to take cargo from the industry.
 
	 * @param industry_id The index of the industry.
 
	 * @pre IsValidIndustry(industry_id).
 
	 * @return The company that has the exclusive rights. The value
 
	 *         ScriptCompany::COMPANY_SPECTATOR means that there are currently no
 
	 *         exclusive rights given out to anyone.
 
	 */
 
	static ScriptCompany::CompanyID GetExclusiveConsumer(IndustryID industry_id);
 

	
 
	/**
 
	 * Sets or resets the company that has exclusive right to take cargo from the industry.
 
	 * @param industry_id The index of the industry.
 
	 * @param company_id The company to set (ScriptCompany::COMPANY_INVALID to reset).
 
	 * @pre IsValidIndustry(industry_id).
 
	 * @return True if the action succeeded.
 
	 * @api -ai
 
	 */
 
	static bool SetExclusiveConsumer(IndustryID industry_id, ScriptCompany::CompanyID company_id);
 

	
 
};
 

	
 
#endif /* SCRIPT_INDUSTRY_HPP */
src/station_cmd.cpp
Show inline comments
 
@@ -4010,23 +4010,24 @@ static bool CanMoveGoodsToStation(const 
 
		/* Non-passengers are never served by just a bus stop. */
 
		if (st->facilities == FACIL_BUS_STOP) return false;
 
	}
 
	return true;
 
}
 

	
 
uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
 
uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations, Owner exclusivity)
 
{
 
	/* Return if nothing to do. Also the rounding below fails for 0. */
 
	if (all_stations->empty()) return 0;
 
	if (amount == 0) return 0;
 

	
 
	Station *first_station = nullptr;
 
	typedef std::pair<Station *, uint> StationInfo;
 
	std::vector<StationInfo> used_stations;
 

	
 
	for (Station *st : *all_stations) {
 
		if (exclusivity != INVALID_OWNER && exclusivity != st->owner) continue;
 
		if (!CanMoveGoodsToStation(st, type)) continue;
 

	
 
		/* Avoid allocating a vector if there is only one station to significantly
 
		 * improve performance in this common case. */
 
		if (first_station == nullptr) {
 
			first_station = st;
0 comments (0 inline, 0 general)