bany提供一个 API,用于按内容或创意工坊 ID 检查玩家对 DLC 物品和皮肤的所有权
工坊 ID 是您在 Steam 上看到的(例如 https://steamcommunity.com/sharedfiles/filedetails/?id=513329998),大多数皮肤插件将使用工坊 ID
Content ID 是 Rust 自己的付费内容标识符
为什么这个插件有用
我必须这样做是愚蠢的,但 Death from codefling 声称这个插件过于复杂,并且具有昂贵的 API 调用。死神不知道他在说什么,由于我不使用代码,我将在这里发布我对他的主张的反驳
我将谈谈他的陈述中与这个插件相关的两个部分。
原生 CheckSkinOwnership 方法要求你提供要检查的 DLC 的 ID。如果您像大多数插件一样只有工作室 ID,那就没有用了。但假设您确实有 DLC ID。
该函数执行的第一件事是调用 ItemSkinDirectory.FindByInventoryDefinitionId 方法来查找 DLC 信息。该方法使 2 个 Linq 调用都为检查的每个 ID 生成垃圾,Where 和 FirstOrDefault。(参见:https://www.jacksondunstan.com/articles/4840 )
该插件有 2 个 API 方法,可产生与本机函数相同的结果;
CheckContentOwnership,它接受一个 DLC ID,与本机方法相同,但没有垃圾分配。
IsOwnedOrFreeSkin 采用创意工坊 ID 而不是 DLC ID,对于存储创意工坊 ID 的插件非常有用,而且没有垃圾分配
这两种 API 方法都可以通过 Oxides 钩子 API 调用,然后运行原生 CheckSkinOwnership 函数。
以下是一些基准结果,将 3 种方法背靠背 3 次进行比较,针对每种批准的皮肤进行测试
-------------------------------------------------
[API] IsOwnedOrFreeSkin: 5469 iterations
Totals: Time: 7.5846ms | Allocations: 0 bytes
Average: Time: 0.0014ms | Allocations: 0 bytes
-------------------------------------------------
[API] CheckContentOwnership: 5469 iterations
Totals: Time: 6.0259ms | Allocations: 0 bytes
Average: Time: 0.0011ms | Allocations: 0 bytes
-------------------------------------------------
[Native] CheckSkinOwnership: 5469 iterations
Totals: Time: 14.4965ms | Allocations: 143360 bytes
Average: Time: 0.0027ms | Allocations: 26 bytes
-------------------------------------------------
[API] IsOwnedOrFreeSkin: 5469 iterations
Totals: Time: 5.9590ms | Allocations: 0 bytes
Average: Time: 0.0011ms | Allocations: 0 bytes
-------------------------------------------------
[API] CheckContentOwnership: 5469 iterations
Totals: Time: 5.6988ms | Allocations: 0 bytes
Average: Time: 0.0010ms | Allocations: 0 bytes
-------------------------------------------------
[Native] CheckSkinOwnership: 5469 iterations
Totals: Time: 14.4887ms | Allocations: 139264 bytes
Average: Time: 0.0026ms | Allocations: 25 bytes
-------------------------------------------------
[API] IsOwnedOrFreeSkin: 5469 iterations
Totals: Time: 6.3950ms | Allocations: 0 bytes
Average: Time: 0.0012ms | Allocations: 0 bytes
-------------------------------------------------
[API] CheckContentOwnership: 5469 iterations
Totals: Time: 5.5006ms | Allocations: 0 bytes
Average: Time: 0.0010ms | Allocations: 0 bytes
-------------------------------------------------
[Native] CheckSkinOwnership: 5469 iterations
Totals: Time: 14.1449ms | Allocations: 135168 bytes
Average: Time: 0.0026ms | Allocations: 24 bytes
该插件不仅为 DLC ID 和创意工坊 ID 提供了更快的非分配方法,还允许您在一次调用中过滤玩家的整个 dlc/创意工坊 ID 列表,从而留下一个仅包含允许玩家使用的内容的列表。
HasLicense 函数要求您已经创建了项目。然后,它调用steam_api64.dll托管的二进制文件。我们无法从那里访问 C 源代码,但它很可能会向 Steam 发出 API 请求来进行比较。
归根结底,我不在乎其他开发人员是否愿意使用这个插件。我将把它用于我所有的插件,以快速轻松地过滤掉玩家无法使用的内容。
如果有人想自己尝试,我可以发布用于基准测试的插件
应用程序接口
创意工坊/皮肤 ID
// Checks if the specified workshop skin ID is a paid skin.
bool IsPaidSkin(ulong workshopId)
------------------------------------------------------------------------------
// Removes all paid skins from the provided list of workshop skin IDs.
bool FilterPaidSkins(List<ulong> workshopIds)
------------------------------------------------------------------------------
// Filters a list of workshop skin IDs to only include those that the player owns or are unapproved workshop skins.
// Returns false if skin definitions have not yet been initialized
bool FilterOwnedOrFreeSkins(BasePlayer player, List<ulong> workshopIds)
// Example usage:
List<ulong> workshopIds = new List<ulong>
{
491265826,
491250135,
491272870,
491151877
};
bool result = PluginDLCAPI.Call<bool>("FilterOwnedOrFreeSkins", player, workshopIds);
if (result)
{
// The list will now only contain skin IDs that the player is allowed to use
}
------------------------------------------------------------------------------
// Checks whether the specified skin is owned by the player or is an unapproved workshop skin.
// Returns false if skin definitions have not yet been initialized, or if the user does not own the skin
bool IsOwnedOrFreeSkin(BasePlayer player, ulong workshopId)
// Example Usage:
bool result = PluginDLCAPI.Call<bool>("IsOwnedOrFreeSkin", player, 491265826);
if (result)
{
// The player is allowed to use this workshop skin
}
项目
// Checks whether the specified item is owned by the player or free to use.
// Returns false if skin definitions have not yet been initialized, or if the user does not own the item
bool IsOwnedOrFreeItem(BasePlayer player, Item item)
bool IsOwnedOrFreeItem(BasePlayer player, int itemId, ulong skin = 0)
bool IsOwnedOrFreeItem(BasePlayer player, string shortname, ulong skin = 0)
------------------------------------------------------------------------------
// Filters a list items to only include those that the player owns or can use
// Returns false if skin definitions have not yet been initialized
bool FilterOwnedOrFreeItems(BasePlayer player, List<Item> items)
内容 ID (ItemSkinDirectory.Skin.id / SteamDLCItem.dlcAppId)
//Filters a list of content IDs to only include those that the player owns.
//Returns false if skin definitions have not yet been initialized
bool FilterContentOwnership(BasePlayer player, List<int> contentIds)
// Example Usage:
List<int> contentIds = new List<int>();
foreach (ConstructionGrade grade in grade.grades)
{
contentIds.Add((int)grade.gradeBase.skin)
}
bool result = PluginDLCAPI.Call<bool>("FilterContentOwnership", player, contentIds);
if (result)
{
// The list will only contain the ID's of the building grades/skins the player is allowed to use
}
------------------------------------------------------------------------------
// A faster non-allocating implementation of Rusts CheckSkinOwnership method.
// This works for all DLC items.
bool CheckContentOwnership(BasePlayer player, int contentId)
// Example Usage:
int railroadPlanterContentId = 10298;
bool result = PluginDLCAPI.Call<bool>("CheckContentOwnership", player, railroadPlanterContentId);
if (result)
{
// The player is allowed to use the railroad planter
}
重定向的皮肤
// Checks if a item shortname or ID is a redirected skin.
bool IsRedirectedSkin(string shortname)
bool IsRedirectedSkin(int itemId)
------------------------------------------------------------------------------
// Converts a item shortname back to its unskinned definition shortname. (ex. hazmatsuit.spacesuit -> hazmatsuit)
string GetRedirectedShortname(string shortname)
------------------------------------------------------------------------------
// Converts a item ID back to its unskinned definition ID
int GetRedirectedItemId(int itemId)
------------------------------------------------------------------------------
// Takes a redirected item shortname and checks if the player can use it.
// If the player can use the item redirect, the redirect shortname will be returned, else the base item shortname will be returned
string GetRedirectedShortnameIfNotOwned(BasePlayer player, string shortname)
------------------------------------------------------------------------------
// Takes a redirected item shortname and checks if the player can use it.
// If the player can use the item redirect, the redirect item ID will be returned, else the base item ID will be returned
int GetRedirectedItemIdIfNotOwned(BasePlayer player, int itemId)