欢迎加入!

注册后,您将能够与我们社区的其他成员进行讨论、分享和私信。

无论您是想寻求帮助、分享经验,还是结识志同道合的朋友,我们都期待您的参与!一起探索更多精彩内容吧。

立即注册! 加入群聊
  • 所有的免费插件都是同步外网更新,所有都是最新版!
项目检索器

项目检索器 同步更新

没有下载权限
购买会员

特征

  • 允许玩家使用来自外部来源的资源(包括原版背包)进行建造、制作、重新加载等
  • 支持建造、升级、制作、修理、重新加载、打开钥匙锁、从自动售货机购买、从车辆供应商处购买以及通过科技树解锁蓝图
  • 支持许多调用 vanilla 函数来查找和获取资源的插件
  • 充当消耗资源的插件和提供资源的插件之间的路由器

运作方式

如果你自己安装这个插件,它将允许玩家使用他们装备的原版背包中的资源进行建造/制作/等。此功能不需要任何权限或配置。

当您拥有与之兼容的其他插件时,此插件将变得更加有用,包括以下示例。

  • 安装 Backpacks 插件后,如果玩家有权限并且打开了 Retrieve 模式(这是每个背包页面的设置),他们将能够使用背包中的资源进行构建/制作/等。backpacks.retrieve
  • 安装 Bag of Holding 插件后,玩家将能够使用袋子内的资源进行构建/制作/等。
  • 安装虚拟物品插件后,玩家将能够根据该插件中的配置和权限,完全不使用任何资源进行构建/制作/等。

概念

  • Item Consumers-- 任何从玩家物品栏中获取或删除物品的插件或原版函数。
    • 原版功能示例:建造、升级、制作、重新加载、打开钥匙锁、从自动售货机购买、从车辆供应商处购买以及通过科技树解锁蓝图。
    • 示例插件:自定义自动售货机
  • Item Suppliers-- 挂接到 Item Retriever 中以为 Item Consumers 按需提供项目的任何插件。允许按需加载或创建项目。
  • Container Suppliers-- 向 Item Retriever 注册容器的任何插件。Item Retriever 将代表 Item Consumers 按需搜索这些容器。例如,插件可以向存储容器添加 UI 按钮,允许玩家单独切换是否可以远程使用这些容器的内容。
    • 示例插件:目前无。
除了明确的 Item Suppliers 和 Container Suppliers 之外,一些物品还可以隐式充当 Item Suppliers,包括原版背包和由 Bag of Holding 插件管理的袋子。

不兼容的插件

任何将玩家物品栏空间减少到小于 24 的插件都是不兼容的。例如,Clothing Slots。

开发人员应如何与此插件集成

项目使用者

如果你的插件需要从玩家物品栏中获取物品,并且只关心物品 ID,那么只需使用该类中的原版 Rust 方法,这将调用 Item Retriever 已经拦截的钩子。PlayerInventory

如果您的插件需要从玩家物品栏中获取物品,并且您关心的不仅仅是物品 ID,请执行以下操作。

  • 加载 Item Retriever 时,通过 和 求和并获取玩家物品。请勿自行搜索项目。API_SumPlayerItemsAPI_TakePlayerItems
  • 当 Item Retriever 未加载时,实现自定义逻辑以求和并获取这些项目。

Item 供应商

如果你的插件在外部存储玩家的物品,比如在数据文件中,特别是如果这些数据是延迟加载的,那么你可能想成为物品供应商。用于向 Item Retriever 注册回调,当 Item Consumer 想要对项目求和或获取项目时,将按需调用该回调。您的回调将传递给物品所针对的播放器,以及描述要搜索的物品的查询。API_AddSupplier

在某些情况下,您可能不需要创建实际实例。Item

  • 对项求和时,只需枚举数据文件的内容并返回结果即可。如果这些项目在任何地方都不存在,例如免费项目,那么您可以简单地返回您想要的任何总和。
  • 在获取项目时,如果列表为 ,则表示另一个插件只想删除项目,因此您可以简单地更新表示项目的数据层,而无需创建任何实例。如果这些项目在任何地方都不存在,例如免费项目,那么您只需创建新项目即可。collectnullItem

集装箱供应商

如果你的插件只处理驻留在 Rust 物理世界中的容器(没有外部数据),你可能想成为容器供应商。使用 和 将特定容器与特定玩家关联和取消关联。当 Item Consumer 想要对项目求和或获取项目时,Item Retriever 将按需搜索这些容器。API_AddContainerAPI_RemoveContainer

开发人员 API

API_GetApi

Dictionary<string, object> API_GetApi()
返回用于高性能 API 操作的委托字典。与委托交互可避免垃圾分配和 Oxide 开销。

例:

[PluginReference]
private readonly Plugin ItemRetriever;

private ItemRetrieverApi _itemRetrieverApi;
private Dictionary<string, object> _itemQuery;

// (Hook) When all plugins load, call ItemRetriever to cache its API.
private void OnServerInitialized()
{
if (ItemRetriever != null)
{
CacheItemRetrieverApi();
}
}

// (Hook) In case ItemRetriever reloads or loads late, refresh its API.
private void OnPluginLoaded(Plugin plugin)
{
if (plugin.Name == nameof(ItemRetriever))
{
CacheItemRetrieverApi();
}
}

// (Helper method) Call ItemRetriever via Oxide to get its API.
private void CacheItemRetrieverApi()
{
_itemRetrieverApi = new ItemRetrieverApi(ItemRetriever.Call("API_GetApi") as Dictionary<string, object>);
}

// (Helper class) This abstraction allows you to call ItemRetriever API methods with low CPU/memory overhead.
private class ItemRetrieverApi
{
// All available API methods are defined here, but you can shorten this list for brevity if you only use select APIs.
public Action<Plugin, Dictionary<string, object>> AddSupplier { get; }
public Action<Plugin> RemoveSupplier { get; }
public Func<BasePlayer, ItemContainer, bool> HasContainer { get; }
public Action<Plugin, BasePlayer, IItemContainerEntity, ItemContainer, Func<Plugin, BasePlayer, ItemContainer, bool>> AddContainer { get; }
public Action<Plugin, BasePlayer, ItemContainer> RemoveContainer { get; }
public Action<Plugin, BasePlayer> RemoveAllContainersForPlayer { get; }
public Action<Plugin> RemoveAllContainersForPlugin { get; }
public Action<BasePlayer, Dictionary<string, object>, List<Item>> FindPlayerItems { get; }
public Func<BasePlayer, Dictionary<string, object>, int> SumPlayerItems { get; }
public Func<BasePlayer, Dictionary<string, object>, int, List<Item>, int> TakePlayerItems { get; }
public Action<BasePlayer, AmmoTypes, List<Item>> FindPlayerAmmo { get; }

public ItemRetrieverApi(Dictionary<string, object> apiDict)
{
AddSupplier = apiDict[nameof(AddSupplier)] as Action<Plugin, Dictionary<string, object>>;
RemoveSupplier = apiDict[nameof(RemoveSupplier)] as Action<Plugin>;
HasContainer = apiDict[nameof(HasContainer)] as Func<BasePlayer, ItemContainer, bool>;
AddContainer = apiDict[nameof(AddContainer)] as Action<Plugin, BasePlayer, IItemContainerEntity, ItemContainer, Func<Plugin, BasePlayer, ItemContainer, bool>;
RemoveContainer = apiDict[nameof(RemoveContainer)] as Action<Plugin, BasePlayer, ItemContainer>;
RemoveAllContainersForPlayer = apiDict[nameof(RemoveAllContainersForPlayer)] as Action<Plugin, BasePlayer>;
RemoveAllContainersForPlugin = apiDict[nameof(RemoveAllContainersForPlugin)] as Action<Plugin>;
FindPlayerItems = apiDict[nameof(FindPlayerItems)] as Action<BasePlayer, Dictionary<string, object>, List<Item>>;
SumPlayerItems = apiDict[nameof(SumPlayerItems)] as Func<BasePlayer, Dictionary<string, object>, int>;
TakePlayerItems = apiDict[nameof(TakePlayerItems)] as Func<BasePlayer, Dictionary<string, object>, int, List<Item>, int>;
FindPlayerAmmo = apiDict[nameof(FindPlayerAmmo)] as Action<BasePlayer, AmmoTypes, List<Item>>;
}
}

// (Helper method) When ItemRetriever's API is not available, you'll need a method to find items in the player inventory.
// If you only need to find items by id (don't need to check skin, blueprint, etc.), then you can use a vanilla method.
private int SumContainerItems(ItemContainer container, int itemId, ulong skinId = 0)
{
var sum = 0;

foreach (var item in container.itemList)
{
if (item.info.itemid != itemId)
continue;

if (skinId != 0 && item.skin != skinId)
continue;

sum = item.amount;
}

return sum;
}

// (Helper method) Create or update your item query. Reuses the dictionary to reduce garbage generation.
// Recommended to also use an object cache for item ids and skin ids to avoid generating garbage when assigning them to the item query dictionary.
private Dictionary<string, object> SetupItemQuery(int itemId, ulong skinId = 0)
{
if (_itemQuery == null)
{
_itemQuery = new Dictionary<string, object>();
}

_itemQuery.Clear();
_itemQuery["ItemId"] = itemId;

if (skinId != 0)
{
_itemQuery["SkinId"] = skinId;
}

return _itemQuery;
}

// (Helper method) Example business logic.
private int GetPlayerEpicScrapAmount(BasePlayer player)
{
var itemId = -932201673;
var skinId = 1234567890uL;

// If ItemRetriever is available, call it, else simply find items in the player inventory.
return _itemRetrieverApi?.SumPlayerItems?.Invoke(player, SetupItemQuery(itemId, skinId))
?? SumContainerItems(player.inventory.containerMain, itemId, skinId)
SumContainerItems(player.inventory.containerBelt, itemId, skinId);
}

API_AddSupplier

void API_AddSupplier(Plugin plugin, Dictionary<string, object> spec)
将插件注册为 Item Supplier。Supplier 基本上是一组钩子,Item Retriever 可以调用这些钩子来为玩家查找、求和或获取物品。

支持的字段(均为可选字段):

  • "Priority"-- 确定“供应商”相对于其他供应商的优先级。数字越小,优先级越高。在搜索玩家物品库之前处理负数。如果两个 Supplier 具有相同的优先级,则将根据其插件名称按字母顺序处理它们。默认优先级为 。0
  • "FindPlayerItems": -- 当插件或原版函数想要获取特定玩家的特定物品列表时,将调用此函数。如果你正在实现一个插件,为玩家提供按需创建的免费物品,请不要实现此功能,因为不能保证请求者会使用这些物品,因此实现此功能可能会导致物品泄露。Action<BasePlayer, Dictionary<string, object>, List<Item>>
  • "SumPlayerItems": -- 当插件或原版函数想知道特定玩家是否有足够的特定物品数量时,将调用此函数。Func<BasePlayer, Dictionary<string, object>, int>
  • "TakePlayerItems": -- 当插件或原版函数已经确定特定玩家拥有足够数量的特定物品,并且现在想要拿走这些物品时,将调用此函数。Func<BasePlayer, Dictionary<string, object>, int, List<Item>, int>
  • "TakePlayerItemsV2": -- 类似于 ,但传递参数。如果参数为非 null,则正在为工艺任务请求项目。这对于生成物品(例如虚拟物品)的插件来说是有用的信息,因为它允许它们简单地返回成分数量,而不是实际生成/收集成分,这样如果工艺任务被取消,成分就不会退还。Func<BasePlayer, Dictionary<string, object>, int, List<Item>, ItemCraftTask, int>TakePlayerItemsItemCraftTaskItemCraftTask
  • "FindPlayerAmmo": -- 当插件或原版函数想要查找与特定玩家的特定类型匹配的所有弹药物品时,将调用此函数。Action<BasePlayer, AmmoTypes, List<Item>>
  • "SerializeForNetwork": -- 当插件或原版函数想要向玩家发送玩家物品栏的快照时,将调用此函数。当您实现此挂钩并将项目添加到提供的列表中时,这些项目将包含在发送给玩家的快照中,从而导致该玩家的游戏客户端认为它拥有这些项目,即使它们在库存中不可见。Action<BasePlayer, List<ProtoBuf.Item>>
无限供应木材的示例:

private const int WoodItemId = -151838493;
private const int WoodAmount = 1000000;

[PluginReference]
private readonly Plugin ItemRetriever;

private void OnServerInitialized()
{
AddSupplier();
}

private void OnPluginLoaded(Plugin plugin)
{
if (plugin.Name == nameof(ItemRetriever))
{
AddSupplier();
}
}

private void AddSupplier()
{
ItemRetriever?.Call("API_AddSupplier", this, new Dictionary<string, object>
{
["SumPlayerItems"] = new Func<BasePlayer, Dictionary<string, object>, int>((player, rawItemQuery) =>
{
object itemIdObj;
if (!rawItemQuery.TryGetValue("ItemId", out itemIdObj))
return 0;

var itemId = Convert.ToInt32(itemIdObj);
if (itemId != WoodItemId)
return 0;

return WoodAmount;
}),

["TakePlayerItems"] = new Func<BasePlayer, Dictionary<string, object>, int, List<Item>, int>((player, rawItemQuery, amount, collect) =>
{
object itemIdObj;
if (!rawItemQuery.TryGetValue("ItemId", out itemIdObj))
return 0;

var itemId = Convert.ToInt32(itemIdObj);
if (itemId != WoodItemId)
return 0;

collect?.Add(ItemManager.CreateByItemID(WoodItemId, amount));

// Return the full amount, so ItemRetriever will stop looking for more items.
return amount;
}),

["SerializeForNetwork"] = new Action<BasePlayer, List<ProtoBuf.Item>>((player, itemList) =>
{
// Make the client think it has an additional wood.
var itemData = Facepunch.Pool.Get<ProtoBuf.Item>();
itemData.itemid = WoodItemId;
itemData.amount = WoodAmount;
itemList.Add(itemData);
}),
});
}

API_RemoveSupplier

void API_RemoveSupplier(Plugin plugin)
删除指定的物料供应商。一旦供应商被移除,玩家将无法再访问该供应商的物品。现有玩家可能暂时拥有过时的物品栏快照,表明这些物品仍然可用,但当玩家的库存下次发生变化时,它会自动自行解决。

注意: 当你的插件卸载时,没有必要调用这个函数,因为 Item Retriever 会检测到你的插件卸载并自动取消注册它。

API_HasContainer

bool API_HasContainer(BasePlayer player, ItemContainer container)
如果指定的播放器具有与其关联的指定容器,则返回 ,否则返回 。truefalse

API_AddContainer

void API_AddContainer(Plugin plugin, BasePlayer player, IItemContainerEntity containerEntity, ItemContainer container, Func<Plugin, BasePlayer, ItemContainer, bool> canUseContainer = null)
  • 将指定的容器添加到指定的播放器中,在指定的插件下
  • 提供容器实体后,容器关联将在该实体被销毁时自动清理,因此您不必调用API_RemoveContainer
  • 如果提供了委托,插件将在每次想要使用容器时调用它,以评估是否可以计算项目或从该容器中拉取项目canUseContainer

API_RemoveContainer

void API_RemoveContainer(Plugin plugin, BasePlayer player, ItemContainer container)
从目标播放器中删除指定的容器。

API_RemoveAllContainersForPlayer

void API_RemoveAllContainersForPlayer(Plugin plugin, BasePlayer player, ItemContainer container)
删除由指定插件为目标播放器注册的所有容器。

API_RemoveAllContainersForPlugin

void API_RemoveAllContainersForPlugin(Plugin plugin)
删除指定插件注册的所有容器。注意: 插件在卸载时不需要调用此函数,因为 Item Retriever 已经监视插件的 unload 事件,以便自动注销其容器。

API_FindPlayerItems

void API_FindPlayerItems(BasePlayer player, Dictionary<string, object> itemQuery, List<Item> collect)
搜索玩家物品库和额外容器,将所有物品添加到匹配的列表中。collectitemQuery

API_SumPlayerItems

int API_SumPlayerItems(BasePlayer player, Dictionary<string, object> itemQuery)
搜索玩家物品库和额外容器,返回匹配的所有项目的总和。itemQuery

API_TakePlayerItems

int API_TakePlayerItems(BasePlayer player, Dictionary<string, object> itemQuery, int amount, List<Item> collect)
搜索玩家物品库和额外的容器,获取匹配的项目,如果为非 null,则可选择将这些项目添加到列表中。amountitemQuerycollect

API_FindPlayerAmmo

void API_FindPlayerAmmo(BasePlayer player, AmmoTypes ammoType, List<Item> collect)
搜索玩家物品库和额外容器,将匹配指定 的所有项目添加到列表中。collectammoType

项查询

和 API 都接受具有以下可选字段的项目查询。此外,该方法将在调用 supplier hook 时提供具有相同字段的字典。API_FindPlayerItemsAPI_SumPlayerItemsAPI_TakePlayerItemsDictionary<string, object>API_AddSupplier

  • "BlueprintId": -- 对应于 。intitem.blueprintTarget
  • "DisplayName": -- 对应于 。stringitem.name
  • "DataInt": -- 对应于 。intitem.instanceData.dataInt
  • "FlagsContain": -- 对应于 。即使项的位掩码包含其他标志,也可能被视为匹配项。Item.Flagitem.flagsitem.flags
  • "FlagsEqual": -- 对应于 。如果项的位掩码包含其他标志,则不会将其视为匹配项。Item.Flagitem.flagsitem.flags
  • "ItemId": -- 对应于 。intitem.info.itemid
  • "MinCondition": -- 对应于 。floatitem.conditionNormalized
  • "RequireEmpty": -- 对应于 。而 ,包含内容物的项目(例如,带有附件的武器)将不匹配。如果包含内容的项是堆叠的,则堆栈中除一个项之外的所有项都可能被视为匹配项。boolitem.contents.itemList.Counttrue
  • "SkinId": -- 对应于 。ulongitem.skin
注意: 请勿提供对战不需要的字段。例如,如果您提供 SkinId ,则只有具有 SkinId 的项目才会被视为匹配项。00

如果未提供任何字段,则所有项目都将被视为匹配项。

抽象出字典访问的示例代码:

private struct ItemQuery
{
public static ItemQuery Parse(Dictionary<string, object> raw)
{
var itemQuery = new ItemQuery();

GetOption(raw, "BlueprintId", out itemQuery.BlueprintId);
GetOption(raw, "DisplayName", out itemQuery.DisplayName);
GetOption(raw, "DataInt", out itemQuery.DataInt);
GetOption(raw, "FlagsContain", out itemQuery.FlagsContain);
GetOption(raw, "FlagsEqual", out itemQuery.FlagsEqual);
GetOption(raw, "ItemId", out itemQuery.ItemId);
GetOption(raw, "MinCondition", out itemQuery.MinCondition);
GetOption(raw, "RequireEmpty", out itemQuery.RequireEmpty);
GetOption(raw, "SkinId", out itemQuery.SkinId);

return itemQuery;
}

private static void GetOption<T>(Dictionary<string, object> dict, string key, out T result)
{
object value;
result = dict.TryGetValue(key, out value) && value is T
? (T)value
: default(T);
}

public int? BlueprintId;
public int? DataInt;
public string DisplayName;
public Item.Flag? FlagsContain;
public Item.Flag? FlagsEqual;
public int? ItemId;
public float MinCondition;
public bool RequireEmpty;
public ulong? SkinId;
}

作者
xiaoguan
下载
0
查看
10
首次发布
最后更新

评分

0.00 星 0 星

来自xiaoguan的更多资源

后退
顶部