当前位置: 首页>>代码示例>>C++>>正文


C++ CommandCost函数代码示例

本文整理汇总了C++中CommandCost函数的典型用法代码示例。如果您正苦于以下问题:C++ CommandCost函数的具体用法?C++ CommandCost怎么用?C++ CommandCost使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。


在下文中一共展示了CommandCost函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: GetNewEngineType

/**
 * Get the EngineID of the replacement for a vehicle
 * @param v The vehicle to find a replacement for
 * @param c The vehicle's owner (it's faster to forward the pointer than refinding it)
 * @param [out] e the EngineID of the replacement. INVALID_ENGINE if no replacement is found
 * @return Error if the engine to build is not available
 */
static CommandCost GetNewEngineType(const Vehicle *v, const Company *c, EngineID &e)
{
	assert(v->type != VEH_TRAIN || !v->IsArticulatedPart());

	e = INVALID_ENGINE;

	if (v->type == VEH_TRAIN && Train::From(v)->IsRearDualheaded()) {
		/* we build the rear ends of multiheaded trains with the front ones */
		return CommandCost();
	}

	e = EngineReplacementForCompany(c, v->engine_type, v->group_id);

	/* Autoreplace, if engine is available */
	if (e != INVALID_ENGINE && IsEngineBuildable(e, v->type, _current_company)) {
		return CommandCost();
	}

	/* Autorenew if needed */
	if (v->NeedsAutorenewing(c)) e = v->engine_type;

	/* Nothing to do or all is fine? */
	if (e == INVALID_ENGINE || IsEngineBuildable(e, v->type, _current_company)) return CommandCost();

	/* The engine we need is not available. Report error to user */
	return CommandCost(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + v->type);
}
开发者ID:benjeffery,项目名称:openttd,代码行数:34,代码来源:autoreplace_cmd.cpp

示例2: FinalizePasting

/**
 * Finish a paste process.
 * @return Total cost.
 */
static CommandCost FinalizePasting()
{
	/* Set error string parameters */
	CopyInDParam(0, _current_pasting->err_params, lengthof(_current_pasting->err_params));
	/* Set error summary message (see COPY_PASTE_ERR_SUMMARY_PARAM for details). */
	SetDParam(COPY_PASTE_ERR_SUMMARY_PARAM, _current_pasting->err_summary);
	/* Store the error tile so the GUI (CcPaste) can highlight it. */
	_paste_err_tile = _current_pasting->err_tile;

	CommandCost ret;
	if (_current_pasting->had_success) {
		/* Return overal cost of the operation */
		ret = CommandCost(EXPENSES_CONSTRUCTION, _current_pasting->overal_cost);
		/* Here we are about to return a success. However, there could occured some meaningful
		 * errors (those except "already built", "already leveled" etc.) and we should inform
		 * the user that not everything went right. Show the message now. */
		if ((_current_pasting->dc_flags & DC_EXEC) && IsLocalCompany() && GetPasteErrorImportance(_current_pasting->err_message) > GetPasteErrorImportance(STR_ERROR_NOTHING_TO_DO)) {
			ShowErrorMessage(_current_pasting->err_summary, _current_pasting->err_message, WL_INFO);
		} else {
			/* If we are not showing error message then clear the error tile to prevent GUI
			 * (CcPaste) from higlighting it. */
			_paste_err_tile = INVALID_TILE;
		}
	} else {
		/* Return an error if we didn't have any success. */
		ret = CommandCost(_current_pasting->err_message);
	}

	/* cleanup */
	delete _current_pasting;
	_current_pasting = NULL;

	return ret;
}
开发者ID:koreapyj,项目名称:openttd-yapp,代码行数:38,代码来源:copypaste_cmd.cpp

示例3: AddEngineReplacement

/**
 * Add an engine replacement to the given renewlist.
 * @param erl The renewlist to add to.
 * @param old_engine The original engine type.
 * @param new_engine The replacement engine type.
 * @param group The group related to this replacement.
 * @param replace_when_old Replace when old or always?
 * @param flags The calling command flags.
 * @return 0 on success, CMD_ERROR on failure.
 */
CommandCost AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, GroupID group, bool replace_when_old, DoCommandFlag flags)
{
	/* Check if the old vehicle is already in the list */
	EngineRenew *er = GetEngineReplacement(*erl, old_engine, group);
	if (er != NULL) {
		if (flags & DC_EXEC) {
			er->to = new_engine;
			er->replace_when_old = replace_when_old;
		}
		return CommandCost();
	}

	if (!EngineRenew::CanAllocateItem()) return CMD_ERROR;

	if (flags & DC_EXEC) {
		er = new EngineRenew(old_engine, new_engine);
		er->group_id = group;
		er->replace_when_old = replace_when_old;

		/* Insert before the first element */
		er->next = (EngineRenew *)(*erl);
		*erl = (EngineRenewList)er;
	}

	return CommandCost();
}
开发者ID:Ayutac,项目名称:OpenTTD,代码行数:36,代码来源:autoreplace.cpp

示例4: CmdCustomNewsItem

/**
 * Create a new custom news item.
 * @param tile unused
 * @param flags type of operation
 * @param p1 various bitstuffed elements
 * - p1 = (bit  0 -  7) - NewsType of the message.
 * - p1 = (bit  8 - 15) - NewsReferenceType of first reference.
 * - p1 = (bit 16 - 23) - Company this news message is for.
 * @param p2 First reference of the news message.
 * @param text The text of the news message.
 * @return the cost of this operation or an error
 */
CommandCost CmdCustomNewsItem(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	if (_current_company != OWNER_DEITY) return CMD_ERROR;

	NewsType type = (NewsType)GB(p1, 0, 8);
	NewsReferenceType reftype1 = (NewsReferenceType)GB(p1, 8, 8);
	CompanyID company = (CompanyID)GB(p1, 16, 8);

	if (company != INVALID_OWNER && !Company::IsValidID(company)) return CMD_ERROR;
	if (type >= NT_END) return CMD_ERROR;
	if (StrEmpty(text)) return CMD_ERROR;

	switch (reftype1) {
		case NR_NONE: break;
		case NR_TILE:
			if (!IsValidTile(p2)) return CMD_ERROR;
			break;

		case NR_VEHICLE:
			if (!Vehicle::IsValidID(p2)) return CMD_ERROR;
			break;

		case NR_STATION:
			if (!Station::IsValidID(p2)) return CMD_ERROR;
			break;

		case NR_INDUSTRY:
			if (!Industry::IsValidID(p2)) return CMD_ERROR;
			break;

		case NR_TOWN:
			if (!Town::IsValidID(p2)) return CMD_ERROR;
			break;

		case NR_ENGINE:
			if (!Engine::IsValidID(p2)) return CMD_ERROR;
			break;

		default: return CMD_ERROR;
	}

	if (company != INVALID_OWNER && company != _local_company) return CommandCost();

	if (flags & DC_EXEC) {
		char *news = stredup(text);
		SetDParamStr(0, news);
		AddNewsItem(STR_NEWS_CUSTOM_ITEM, type, NF_NORMAL, reftype1, p2, NR_NONE, UINT32_MAX, news);
	}

	return CommandCost();
}
开发者ID:andythenorth,项目名称:NotRoadTypes,代码行数:63,代码来源:news_gui.cpp

示例5: RemoveShipDepot

static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlag flags)
{
	if (!IsShipDepot(tile)) return CMD_ERROR;

	CommandCost ret = CheckTileOwnership(tile);
	if (ret.Failed()) return ret;

	TileIndex tile2 = GetOtherShipDepotTile(tile);

	/* do not check for ship on tile when company goes bankrupt */
	if (!(flags & DC_BANKRUPT)) {
		CommandCost ret = EnsureNoVehicleOnGround(tile);
		if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
		if (ret.Failed()) return ret;
	}

	if (flags & DC_EXEC) {
		delete Depot::GetByTile(tile);

		Company *c = Company::GetIfValid(GetTileOwner(tile));
		if (c != NULL) {
			c->infrastructure.water -= 2 * LOCK_DEPOT_TILE_FACTOR;
			DirtyCompanyInfrastructureWindows(c->index);
		}

		MakeWaterKeepingClass(tile,  GetTileOwner(tile));
		MakeWaterKeepingClass(tile2, GetTileOwner(tile2));
	}

	return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_SHIP]);
}
开发者ID:J0anJosep,项目名称:OpenTTD,代码行数:31,代码来源:water_cmd.cpp

示例6: GetRefitCost

/** Learn the price of refitting a certain engine
 * @param engine_type Which engine to refit
 * @return Price for refitting
 */
static CommandCost GetRefitCost(EngineID engine_type)
{
    ExpensesType expense_type;
    const Engine *e = Engine::Get(engine_type);
    Price base_price;
    uint cost_factor = e->info.refit_cost;
    switch (e->type) {
    case VEH_SHIP:
        base_price = PR_BUILD_VEHICLE_SHIP;
        expense_type = EXPENSES_SHIP_RUN;
        break;

    case VEH_ROAD:
        base_price = PR_BUILD_VEHICLE_ROAD;
        expense_type = EXPENSES_ROADVEH_RUN;
        break;

    case VEH_AIRCRAFT:
        base_price = PR_BUILD_VEHICLE_AIRCRAFT;
        expense_type = EXPENSES_AIRCRAFT_RUN;
        break;

    case VEH_TRAIN:
        base_price = (e->u.rail.railveh_type == RAILVEH_WAGON) ? PR_BUILD_VEHICLE_WAGON : PR_BUILD_VEHICLE_TRAIN;
        cost_factor <<= 1;
        expense_type = EXPENSES_TRAIN_RUN;
        break;

    default:
        NOT_REACHED();
    }
    return CommandCost(expense_type, GetPrice(base_price, cost_factor, e->grffile, -10));
}
开发者ID:Voxar,项目名称:OpenTTD,代码行数:37,代码来源:vehicle_cmd.cpp

示例7: CmdRenameDepot

/**
 * Rename a depot.
 * @param tile unused
 * @param flags type of operation
 * @param p1 id of depot
 * @param p2 unused
 * @param text the new name or an empty string when resetting to the default
 * @return the cost of this operation or an error
 */
CommandCost CmdRenameDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	Depot *d = Depot::GetIfValid(p1);
	if (d == NULL) return CMD_ERROR;

	CommandCost ret = CheckTileOwnership(d->xy);
	if (ret.Failed()) return ret;

	bool reset = StrEmpty(text);

	if (!reset) {
		if (Utf8StringLength(text) >= MAX_LENGTH_DEPOT_NAME_CHARS) return CMD_ERROR;
		if (!IsUniqueDepotName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
	}

	if (flags & DC_EXEC) {
		free(d->name);

		if (reset) {
			d->name = NULL;
			MakeDefaultName(d);
		} else {
			d->name = strdup(text);
		}

		/* Update the orders and depot */
		SetWindowClassesDirty(WC_VEHICLE_ORDERS);
		SetWindowDirty(WC_VEHICLE_DEPOT, d->xy);

		/* Update the depot list */
		VehicleType vt = GetDepotVehicleType(d->xy);
		SetWindowDirty(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_DEPOT_LIST, vt, GetTileOwner(d->xy), d->index).Pack());
	}
	return CommandCost();
}
开发者ID:ComLock,项目名称:OpenTTD,代码行数:44,代码来源:depot_cmd.cpp

示例8: RemoveLock

/**
 * Remove a lock.
 * @param tile Central tile of the lock.
 * @param flags Operation to perform.
 * @return The cost in case of success, or an error code if it failed.
 */
static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags)
{
	if (GetTileOwner(tile) != OWNER_NONE) {
		CommandCost ret = CheckTileOwnership(tile);
		if (ret.Failed()) return ret;
	}

	TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile));

	/* make sure no vehicle is on the tile. */
	CommandCost ret = EnsureNoVehicleOnGround(tile);
	if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
	if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
	if (ret.Failed()) return ret;

	if (flags & DC_EXEC) {
		DoClearSquare(tile);
		MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta));
		MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta));
		MarkCanalsAndRiversAroundDirty(tile - delta);
		MarkCanalsAndRiversAroundDirty(tile + delta);
	}

	return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_LOCK]);
}
开发者ID:ShaunOfTheLive,项目名称:OpenCoasterTycoon,代码行数:31,代码来源:water_cmd.cpp

示例9: RemoveShipDepot

static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlag flags)
{
	if (!IsShipDepot(tile)) return CMD_ERROR;

	CommandCost ret = CheckTileOwnership(tile);
	if (ret.Failed()) return ret;

	TileIndex tile2 = GetOtherShipDepotTile(tile);

	/* do not check for ship on tile when company goes bankrupt */
	if (!(flags & DC_BANKRUPT)) {
		CommandCost ret = EnsureNoVehicleOnGround(tile);
		if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
		if (ret.Failed()) return ret;
	}

	if (flags & DC_EXEC) {
		delete Depot::GetByTile(tile);

		MakeWaterKeepingClass(tile,  GetTileOwner(tile));
		MakeWaterKeepingClass(tile2, GetTileOwner(tile2));
	}

	return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_SHIP]);
}
开发者ID:ShaunOfTheLive,项目名称:OpenCoasterTycoon,代码行数:25,代码来源:water_cmd.cpp

示例10: TerraformPasteTiles

/**
 * Terraform tiles as a part of a pasting process.
 * @param iter iterator to use when terraforming
 */
static void TerraformPasteTiles(TerraformingIterator *iter)
{
	TileIndex start_tile = *iter;

	/* Do actual terraforming. */
	TerraformTilesResult ret = TerraformTiles(iter, _current_pasting->dc_flags | DC_ALL_TILES, _current_pasting->GetAvailableMoney());

	/* When copy-pasting, we want to higlight error tiles more frequently. TerraformTiles
	 * doesn't always set the _terraform_err_tile (on some errors it's just INVALID_TILE).
	 * We will assume the start tile in these cases. This will give a better overview on
	 * what area failed to paste. */
	if (_terraform_err_tile == INVALID_TILE) _terraform_err_tile = start_tile;

	/* Collect overal cost of the operation. */
	if (ret.had_success) {
		_current_pasting->CollectCost(CommandCost(EXPENSES_CONSTRUCTION, ret.cost), _terraform_err_tile, STR_ERROR_CAN_T_LEVEL_LAND_HERE);
	}

	/* Handle _additional_cash_required */
	if ((_current_pasting->dc_flags & DC_EXEC) && _additional_cash_required > 0) {
		SetDParam(0, _additional_cash_required);
		_current_pasting->CollectError(_terraform_err_tile, STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY, STR_ERROR_CAN_T_LEVEL_LAND_HERE);
	}

	/* Collect last error, if any. */
	if (ret.last_error != STR_NULL) {
		_current_pasting->CollectError(_terraform_err_tile, ret.last_error, STR_ERROR_CAN_T_LEVEL_LAND_HERE);
	}
}
开发者ID:koreapyj,项目名称:openttd-yapp,代码行数:33,代码来源:terraform_cmd.cpp

示例11: RemoveEngineReplacement

/**
 * Remove an engine replacement from a given renewlist.
 * @param erl The renewlist from which to remove the replacement
 * @param engine The original engine type.
 * @param group The group related to this replacement.
 * @param flags The calling command flags.
 * @return 0 on success, CMD_ERROR on failure.
 */
CommandCost RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, GroupID group, DoCommandFlag flags)
{
	EngineRenew *er = (EngineRenew *)(*erl);
	EngineRenew *prev = NULL;

	while (er != NULL) {
		if (er->from == engine && er->group_id == group) {
			if (flags & DC_EXEC) {
				if (prev == NULL) { // First element
					/* The second becomes the new first element */
					*erl = (EngineRenewList)er->next;
				} else {
					/* Cut this element out */
					prev->next = er->next;
				}
				delete er;
			}
			return CommandCost();
		}
		prev = er;
		er = er->next;
	}

	return CMD_ERROR;
}
开发者ID:Ayutac,项目名称:OpenTTD,代码行数:33,代码来源:autoreplace.cpp

示例12: CmdMassStartStopVehicle

/**
 * Starts or stops a lot of vehicles
 * @param tile Tile of the depot where the vehicles are started/stopped (only used for depots)
 * @param flags type of operation
 * @param p1 bitmask
 *   - bit 0 set = start vehicles, unset = stop vehicles
 *   - bit 1 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case
 * @param p2 packed VehicleListIdentifier
 * @param text unused
 * @return the cost of this operation or an error
 */
CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	VehicleList list;
	bool do_start = HasBit(p1, 0);
	bool vehicle_list_window = HasBit(p1, 1);

	VehicleListIdentifier vli;
	if (!vli.Unpack(p2)) return CMD_ERROR;
	if (!IsCompanyBuildableVehicleType(vli.vtype)) return CMD_ERROR;

	if (vehicle_list_window) {
		if (!GenerateVehicleSortList(&list, vli)) return CMD_ERROR;
	} else {
		/* Get the list of vehicles in the depot */
		BuildDepotVehicleList(vli.vtype, tile, &list, NULL);
	}

	for (uint i = 0; i < list.Length(); i++) {
		const Vehicle *v = list[i];

		if (!!(v->vehstatus & VS_STOPPED) != do_start) continue;

		if (!vehicle_list_window && !v->IsChainInDepot()) continue;

		/* Just try and don't care if some vehicle's can't be stopped. */
		DoCommand(tile, v->index, 0, flags, CMD_START_STOP_VEHICLE);
	}

	return CommandCost();
}
开发者ID:fonsinchen,项目名称:openttd-cargodist,代码行数:41,代码来源:vehicle_cmd.cpp

示例13: CmdRenamePresident

/**
 * Change the name of the president.
 * @param tile unused
 * @param flags operation to perform
 * @param p1 unused
 * @param p2 unused
 * @param text the new name or an empty string when resetting to the default
 * @return the cost of this operation or an error
 */
CommandCost CmdRenamePresident(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	bool reset = StrEmpty(text);

	if (!reset) {
		if (Utf8StringLength(text) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) return CMD_ERROR;
		if (!IsUniquePresidentName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
	}

	if (flags & DC_EXEC) {
		Company *c = Company::Get(_current_company);
		free(c->president_name);

		if (reset) {
			c->president_name = NULL;
		} else {
			c->president_name = strdup(text);

			if (c->name_1 == STR_SV_UNNAMED && c->name == NULL) {
				char buf[80];

				snprintf(buf, lengthof(buf), "%s Transport", text);
				DoCommand(0, 0, 0, DC_EXEC, CMD_RENAME_COMPANY, buf);
			}
		}

		MarkWholeScreenDirty();
		CompanyAdminUpdate(c);
	}

	return CommandCost();
}
开发者ID:habnabit,项目名称:openttd-cargodist,代码行数:41,代码来源:company_cmd.cpp

示例14: CopyHeadSpecificThings

/**
 * Copy head specific things to the new vehicle chain after it was successfully constructed
 * @param old_head The old front vehicle (no wagons attached anymore)
 * @param new_head The new head of the completely replaced vehicle chain
 * @param flags the command flags to use
 */
static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head, DoCommandFlag flags)
{
	CommandCost cost = CommandCost();

	/* Share orders */
	if (cost.Succeeded() && old_head != new_head) cost.AddCost(DoCommand(0, new_head->index | CO_SHARE << 30, old_head->index, DC_EXEC, CMD_CLONE_ORDER));

	/* Copy group membership */
	if (cost.Succeeded() && old_head != new_head) cost.AddCost(DoCommand(0, old_head->group_id, new_head->index, DC_EXEC, CMD_ADD_VEHICLE_GROUP));

	/* Perform start/stop check whether the new vehicle suits newgrf restrictions etc. */
	if (cost.Succeeded()) {
		/* Start the vehicle, might be denied by certain things */
		assert((new_head->vehstatus & VS_STOPPED) != 0);
		cost.AddCost(CmdStartStopVehicle(new_head, true));

		/* Stop the vehicle again, but do not care about evil newgrfs allowing starting but not stopping :p */
		if (cost.Succeeded()) cost.AddCost(CmdStartStopVehicle(new_head, false));
	}

	/* Last do those things which do never fail (resp. we do not care about), but which are not undo-able */
	if (cost.Succeeded() && old_head != new_head && (flags & DC_EXEC) != 0) {
		/* Copy other things which cannot be copied by a command and which shall not stay resetted from the build vehicle command */
		new_head->CopyVehicleConfigAndStatistics(old_head);

		/* Switch vehicle windows/news to the new vehicle, so they are not closed/deleted when the old vehicle is sold */
		ChangeVehicleViewports(old_head->index, new_head->index);
		ChangeVehicleViewWindow(old_head->index, new_head->index);
		ChangeVehicleNews(old_head->index, new_head->index);
	}

	return cost;
}
开发者ID:gfarfl,项目名称:openttd-cargodist,代码行数:39,代码来源:autoreplace_cmd.cpp

示例15: SendAllVehiclesToDepot

/**
 * Send all vehicles of type to depots
 * @param flags   the flags used for DoCommand()
 * @param service should the vehicles only get service in the depots
 * @param vli     identifier of the vehicle list
 * @return 0 for success and CMD_ERROR if no vehicle is able to go to depot
 */
static CommandCost SendAllVehiclesToDepot(DoCommandFlag flags, bool service, const VehicleListIdentifier &vli)
{
	VehicleList list;

	if (!GenerateVehicleSortList(&list, vli)) return CMD_ERROR;

	/* Send all the vehicles to a depot */
	bool had_success = false;
	for (uint i = 0; i < list.Length(); i++) {
		const Vehicle *v = list[i];
		CommandCost ret = DoCommand(v->tile, v->index | (service ? DEPOT_SERVICE : 0U) | DEPOT_DONT_CANCEL, 0, flags, GetCmdSendToDepot(vli.vtype));

		if (ret.Succeeded()) {
			had_success = true;

			/* Return 0 if DC_EXEC is not set this is a valid goto depot command)
			 * In this case we know that at least one vehicle can be sent to a depot
			 * and we will issue the command. We can now safely quit the loop, knowing
			 * it will succeed at least once. With DC_EXEC we really need to send them to the depot */
			if (!(flags & DC_EXEC)) break;
		}
	}

	return had_success ? CommandCost() : CMD_ERROR;
}
开发者ID:fonsinchen,项目名称:openttd-cargodist,代码行数:32,代码来源:vehicle_cmd.cpp


注:本文中的CommandCost函数示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。