C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using UnityEngine;
namespace Oxide.Plugins {
[Info("CraftUI", "EinTime/Orange", "1.2.7", ResourceId = 2273)]
[Description("A fully customizable custom crafting UI, which allows admins to change item ingredients.")]
public class CraftUI : RustPlugin {
const string ItemInfoListName = "Item List";
const float refreshTime = 0.25f;
[PluginReference]
private Plugin ImageLibrary;
public static CraftUI S;
HashSet<int> customItemCrafts = new HashSet<int>();
static readonly Dictionary<string, string> displaynameToShortname = new Dictionary<string, string>();
const string transparentSprite = "assets/content/textures/generic/fulltransparent.tga";
#region Player Responses
const string Invalid = "Invalid";
const string FormatHelp = "FormatHelp";
const string InvalidFormat = "InvalidFormat";
const string AlreadyBlocked = "AlreadyBlocked";
const string UnknownError = "UnknownError";
const string ItemRateChange = "ItemRateChange";
const string ItemBlocked = "ItemBlocked";
const string ItemNotBlocked = "ItemNotBlocked";
const string AllItemsBlocked = "AllItemsBlocked";
const string AllItemsUnblocked = "AllItemsUnblocked";
const string IngredientsCleared = "IngredientsCleared";
const string IngredientsReset = "IngredientsReset";
const string AddedIngredient = "AddedIngredient";
const string RemovedIngredient = "RemovedIngredient";
const string RemovedAllIngredient = "RemovedAllIngredient";
const string DoesNotContainIngredient = "DoesNotContainIngredient";
const string HasNoIngredients = "HasNoIngredients";
const string IngredientsList = "IngredientsList";
const string ItemRenamed = "ItemRenamed";
const string DescriptionChanged = "DescriptionChanged";
const string IconUrlChanged = "IconURLChanged";
const string CategoryChanged = "CategoryChanged";
const string NotAdmin = "NotAdmin";
const string FacepunchGUIDisabled = "FacepunchGUIDisabled";
const string ItemListLoaded = "ItemListLoaded";
const string ItemListSaved = "ItemListSaved";
const string AddRemoveFormat = "AddRemoveFormat";
const string IngredientsFormat = "IngredientsFormat";
const string CraftrateFormat = "CraftrateFormat";
const string RenameFormat = "RenameFormat";
const string ChangeDescriptionFormat = "ChangeDescriptionFormat";
const string IconFormat = "IconFormat";
const string CategoryFormat = "CategoryFormat";
static readonly Dictionary<string, string> responseDic = new Dictionary<string, string>() {
[Invalid]
= "{0} is an invalid {1}.", [FormatHelp] = "Format is: /{0} {1}.", [InvalidFormat] = "Invalid format for /{0}.Correct format is: /{0} {1}", [AlreadyBlocked] = "'{0}' blocked value is already {1}", [UnknownError] = "An unknown error has occured.", [ItemRateChange] = "Item '{0}' crafting rate is now '{1}'.", [ItemBlocked] = "Item '{0}' is now blocked from crafting.", [ItemNotBlocked] = "Item '{0}' is no longer blocked from crafting.", [AllItemsBlocked] = "All items are blocked from crafting.", [AllItemsUnblocked] = "All items are no longer blocked from crafting", [IngredientsCleared] = "Item '{0}' is now free to craft.", [IngredientsReset] = "Item '{0}' ingredients have been reset to default values.", [AddedIngredient] = "Added {0} {1} to {2} crafting cost.", [RemovedIngredient] = "Removed {0} {1} from {2} crafting cost.", [RemovedAllIngredient] = "Removed all {0} from {1} crafting cost.", [DoesNotContainIngredient] = "Item {0} does not contain the ingredient {1}; cannot remove.", [HasNoIngredients] = "Item {0} has no crafting ingredients", [IngredientsList] = "Item {0} crafting ingredients are:", [ItemRenamed] = "'{0}' name is now '{1}'", [DescriptionChanged] = "'{0}' description is now '{1}'", [IconUrlChanged] = "'{0}' icon URL is now {1}", [CategoryChanged] = "'{0}' category is now '{1}'", [NotAdmin] = "Only admins may use this command.", [FacepunchGUIDisabled] = "Crafting from the FacePunch Crafting GUI is disabled.Please press {0} to open the correct crafting gui.", [ItemListLoaded] = "Item List was loaded successfully", [ItemListSaved] = "Item List was saved successfully", [AddRemoveFormat] = "\"amount\" \"Ingredient Name\" \"Item Name\"", [IngredientsFormat] = "\"Item Name\"", [CraftrateFormat] = "\"Item Name\" rate", [RenameFormat] = "\"Item Name\" \"New Name\"", [ChangeDescriptionFormat] = "\"Item Name\" \"New Description\"", [IconFormat] = "\"Item Name\" \"http://url.com\"", [CategoryFormat] = "\"Item Name\" \"Category Name\"", ["HelpLine1"] = "Welcome to <size=25><b>CraftUI</b></size>! Commands are:", ["HelpLine2"] = "<size=16><b>/craftui.add</b></size> - adds ingredients to an item.", ["HelpLine3"] = "<size=16><b>/craftui.remove</b></size> - removes ingredients from an item", ["HelpLine4"] = "<size=16><b>/craftui.ingredients</b></size> - prints a list of all current ingredients for an item.", ["HelpLine5"] = "<size=16><b>/craftui.clearingredients</b></size> - clears ALL ingredients from an item (free to craft)", ["HelpLine6"] = "<size=16><b>/craftui.resetingredients</b></size> - resets an item's ingredients to their default values.", ["HelpLine7"] = "<size=16><b>/craftui.craftrate</b></size> - sets the craft rate of an item.0 is instant craft, 2 is double craft time.", ["HelpLine8"] = "<size=16><b>/craftui.block</b></size> - blocks an item from being crafted.It will not be displayed in the UI", ["HelpLine9"] = "<size=16><b>/craftui.unblock</b></size> - allows an item to be crafted.", ["HelpLine10"] = "<size=16><b>/craftui.blockall</b></size> - blocks all items from crafting.", ["HelpLine11"] = "<size=16><b>/craftui.unblockall</b></size> - unblocks all items from crafting.", ["HelpLine10"] = "<size=16><b>/craftui.rename</b></size> - renames an item (in the CraftUI only - does not affect inventory)", ["HelpLine11"] = "<size=16><b>/craftui.seticon</b></size> - sets the icon of an item to a given URL address (in CraftUI only)", ["HelpLine12"] = "<size=16><b>/craftui.save</b></size> - saves any changes made to items.", ["HelpLine13"] = "<size=16><b>/craftui.load</b></size> - loads saved item's.NOTE: this will erase any unsaved changes.", ["HelpLine14"] = "Type any command followed by help (ex: /craftui.add help) to see detailed information about their use.",
}
;
#endregion
#region Config Values
bool AllowOldCrafting = false;
string OpenCraftUIBinding = "q";
List<string> CategoryNames = new List<string>() {
ItemCategory.Construction.ToString(), ItemCategory.Items.ToString(), ItemCategory.Resources.ToString(), ItemCategory.Attire.ToString(), ItemCategory.Tool.ToString(), ItemCategory.Medical.ToString(), ItemCategory.Weapon.ToString(), ItemCategory.Ammunition.ToString(), ItemCategory.Traps.ToString(), ItemCategory.Misc.ToString()
}
;
bool IncludeUncraftableItems = false;
int ItemIconSize = 150;
#endregion
#region Oxide Hooks
void OnServerInitialized() {
LoadDefaultMessages();
CloseCraftUI_AllPlayers();
CloseOverlay_AllPlayers();
S = this;
itemInfoDic = new Dictionary<int, ItemInfo>();
customItemCrafts = new HashSet<int>();
playerDic = new Dictionary<ulong, PlayerInfo>();
CreateMissingBlueprints();
displaynameToShortname.Clear();
originalCraftTimes.Clear();
originalIngredients.Clear();
foreach (var itemdef in ItemManager.itemList) {
if (itemdef) {
if(!displaynameToShortname.ContainsKey(itemdef.displayName.english.ToLower())) displaynameToShortname.Add(itemdef.displayName.english.ToLower(), itemdef.shortname);
if (itemdef.Blueprint) {
originalCraftTimes.Add(itemdef.itemid, itemdef.Blueprint.time);
List<ItemIngredient> ingredients = new List<ItemIngredient>();
foreach (var ingredient in itemdef.Blueprint.ingredients) {
ingredients.Add(new ItemIngredient(ingredient.itemid, ingredient.amount));
}
originalIngredients.Add(itemdef.itemid, ingredients);
}
}
}
LoadItemInfoDic();
timer.Repeat(1f, 0, () => {
RefreshCraftQueue();
}
);
foreach (BasePlayer player in BasePlayer.activePlayerList) {
AddPlayer(player);
}
}
void Loaded() {
}
void Unload() {
CloseCraftUI_AllPlayers();
CloseOverlay_AllPlayers();
SaveItemInfoDic();
foreach (var kvp in playerDic) {
ResetBinding(kvp.Value.basePlayer);
}
}
void OnPlayerInit(BasePlayer player) {
AddPlayer(player);
}
void OnPlayerDisconnected(BasePlayer player, string reason) {
ResetBinding(player);
}
void SetBinding(BasePlayer player) {
rust.RunClientCommand(player, "bind f1 consoletoggle;craftui.closeoverlay;craftui.close");
rust.RunClientCommand(player, "bind escape craftui.closeoverlay;craftui.close");
rust.RunClientCommand(player, "bind tab inventory.toggle;craftui.toggleoverlay;craftui.close");
rust.RunClientCommand(player, "bind " + OpenCraftUIBinding + " craftui.toggle");
}
void ResetBinding(BasePlayer player) {
rust.RunClientCommand(player, "bind " + OpenCraftUIBinding + " " + defaultBinds[OpenCraftUIBinding]);
rust.RunClientCommand(player, "bind f1 consoletoggle");
rust.RunClientCommand(player, "bind tab inventory.toggle");
}
object OnItemCraft(ItemCraftTask task, BasePlayer crafter) {
PlayerInfo playerInfo = GetPlayer(crafter);
if (AllowOldCrafting) {
RenderHudPanelDelayed(refreshTime, CraftQueueName, playerInfo);
RenderHudPanelDelayed(refreshTime, CraftQueueTimerName, playerInfo);
return null;
}
if (!customItemCrafts.Contains(task.taskUID)) {
foreach (var ingredient in task.blueprint.ingredients) {
crafter.inventory.GiveItem(ItemManager.CreateByItemID(ingredient.itemid, (int)ingredient.amount * task.amount, 0));
}
PlayerChat(crafter, FacepunchGUIDisabled, "'" + OpenCraftUIBinding + "'");
return false;
}
RenderHudPanelDelayed(refreshTime, CraftQueueName, playerInfo);
RenderHudPanelDelayed(refreshTime, CraftQueueTimerName, playerInfo);
return null;
}
void OnItemCraftFinished(ItemCraftTask task, Item item) {
PlayerInfo playerInfo = GetPlayer(task.owner);
RenderHudPanelDelayed(refreshTime, CraftQueueName, playerInfo);
RenderHudPanelDelayed(refreshTime, CraftQueueTimerName, playerInfo);
}
void OnItemCraftCancelled(ItemCraftTask task) {
if (task.owner == null) return;
PlayerInfo playerInfo = GetPlayer(task.owner);
if (playerInfo == null) return;
if (!playerInfo.uiOpen) return;
RenderHudPanelDelayed(refreshTime, CraftQueueName, playerInfo);
RenderHudPanelDelayed(refreshTime, CraftQueueTimerName, playerInfo);
RenderHudPanelDelayed(refreshTime, ResourceCostName, playerInfo);
}
void OnLootEntity(BasePlayer player, BaseEntity entity) {
PlayerInfo playerInfo = GetPlayer(player);
StorageContainer storage = entity as StorageContainer;
if (storage == null) return;
float columns = Mathf.Max(1, Mathf.CeilToInt((float)storage.inventorySlots / 6f));
if (storage is BaseOven) columns += 1.5f;
else if (storage is RepairBench) columns += 1;
else if (storage is LiquidContainer) columns += 3.5f;
else if (storage is SupplyDrop) columns += 2f;
else if (storage is LootContainer) columns += 2f;
RenderOverlay(playerInfo, true, columns);
}
void RefreshCraftQueue() {
foreach (var kvp in playerDic) {
if (kvp.Value.uiOpen) {
RenderHudPanel(CraftQueueTimerName, kvp.Value);
}
}
}
protected override void LoadDefaultConfig() => PrintWarning("New configuration file created.");
protected override void LoadConfig() {
base.LoadConfig();
AllowOldCrafting = GetConfigValue("_Settings", "Allow Old Crafting", AllowOldCrafting);
var tempBinding = GetConfigValue("_Settings", "Open CraftUI Binding", OpenCraftUIBinding);
if (defaultBinds.ContainsKey(tempBinding)) OpenCraftUIBinding = tempBinding;
CategoryNames = GetConfigValue("_Settings", "Category Names", CategoryNames);
IncludeUncraftableItems = GetConfigValue("_Settings", "Include Uncraftable Items", IncludeUncraftableItems);
ItemIconSize = GetConfigValue("_Settings", "Item Icon Size", ItemIconSize);
}
T GetConfigValue<T>(string category, string name, T defaultValue) {
var catDic = GetConfigCategory(category);
if (!catDic.ContainsKey(name)) {
catDic.Add(name, defaultValue);
SaveConfig();
}
return (T)Convert.ChangeType(catDic[name], typeof(T));
}
List<T> GetConfigValue<T>(string category, string name, List<T> defaultValue) {
var catDic = GetConfigCategory(category);
object value = null;
if (!catDic.TryGetValue(name, out value)) {
catDic[name] = defaultValue;
Config[category] = catDic;
SaveConfig();
return defaultValue;
}
List<object> objectList = value as List<object>;
List<T> ret = new List<T>();
foreach (object o in objectList) {
ret.Add((T)o);
}
return ret;
}
Dictionary<string, object> GetConfigCategory(string category) {
var catDic = Config[category] as Dictionary<string, object>;
if (catDic == null) {
catDic = new Dictionary<string, object>();
Config[category] = catDic;
SaveConfig();
}
return catDic;
}
void LoadDefaultMessages() {
lang.RegisterMessages(responseDic, this);
}
#endregion
#region Players
class PlayerInfo {
public readonly BasePlayer basePlayer;
public bool uiOpen;
public bool overlayOpen;
public bool overlayLooting;
public float overlayLootingColumns;
public string selectedCategory;
public ItemInfo selectedItem;
public int currentCraftAmount;
public PlayerInfo(BasePlayer player) {
basePlayer = player;
uiOpen = false;
selectedCategory = string.Empty;
selectedItem = null;
currentCraftAmount = 1;
}
public class CraftInfo {
public List<string> amounts, itemTypes, totals, haves;
public bool canCraft;
public CraftInfo() {
amounts = new List<string>();
itemTypes = new List<string>();
totals = new List<string>();
haves = new List<string>();
canCraft = true;
}
}
public CraftInfo GetCraftInfo() {
CraftInfo info = new CraftInfo();
if (selectedItem == null || selectedItem.itemID == 0) {
info.canCraft = false;
return info;
}
foreach (ItemIngredient ingredient in selectedItem.ingredients) {
float amountValue = ingredient.amount;
float haveValue = basePlayer.inventory.GetAmount(ingredient.ingredientID);
float totalValue = ingredient.amount * currentCraftAmount;
if (haveValue < totalValue) info.canCraft = false;
info.amounts.Add(amountValue.ToString());
info.itemTypes.Add(ingredient.realName);
info.totals.Add(totalValue.ToString());
info.haves.Add(haveValue.ToString());
}
return info;
}
}
static Dictionary<ulong, PlayerInfo> playerDic = new Dictionary<ulong, PlayerInfo>();
/// <summary>
/// Returns true if the player was successfully added./// </summary>
bool AddPlayer(BasePlayer player) {
if (!playerDic.ContainsKey(player.userID)) {
PlayerInfo playerInfo = new PlayerInfo(player);
playerDic.Add(player.userID, playerInfo);
SetBinding(player);
return true;
}
return false;
}
PlayerInfo GetPlayer(BasePlayer player) {
PlayerInfo playerInfo = null;
if (!playerDic.TryGetValue(player.userID, out playerInfo)) {
playerInfo = new PlayerInfo(player);
playerDic.Add(player.userID, playerInfo);
SetBinding(player);
}
return playerInfo;
}
#endregion
#region Item Customization
class ItemInfo {
public int itemID;
public string realName;
public string customName;
public string customDescription;
public bool blocked;
public float craftRate;
public List<ItemIngredient> ingredients;
public string iconURL;
public string category;
public ItemInfo() {
ingredients = new List<ItemIngredient>();
}
public ItemInfo(ItemDefinition itemDef) {
itemID = itemDef.itemid;
realName = itemDef.displayName.english;
customName = itemDef.displayName.english;
customDescription = itemDef.displayDescription.english;
blocked = false;
craftRate = 1;
ingredients = new List<ItemIngredient>();
if (itemDef.Blueprint != null && itemDef.Blueprint.ingredients != null) {
foreach (var ingredient in itemDef.Blueprint.ingredients) {
ingredients.Add(new ItemIngredient(ingredient.itemid, ingredient.amount));
}
}
iconURL = S.GetItemIconURL(itemDef.shortname);
category = itemDef.category.ToString();
}
public ItemDefinition GetItemDef() {
return ItemManager.FindItemDefinition(itemID);
}
public bool GetCraftable(PlayerInfo playerInfo) {
if (playerInfo == null) return false;
foreach (var ingredient in ingredients) {
if (playerInfo.basePlayer.inventory.GetAmount(ingredient.ingredientID) < ingredient.amount) return false;
}
return true;
}
public int GetCraftCount(PlayerInfo playerInfo) {
if (playerInfo == null) return -1;
int num = -1;
foreach (var ingredient in ingredients) {
num = Mathf.FloorToInt((float)playerInfo.basePlayer.inventory.GetAmount(ingredient.ingredientID) / ingredient.amount);
if (num <= 0) return -1;
}
return num;
}
public string GetFormattedURL() {
return string.Format(iconURL, S.ItemIconSize.ToString());
}
public static ItemInfo FromObject(object obj) {
Dictionary<string, object> dic = obj as Dictionary<string, object>;
if (dic == null) return null;
ItemInfo itemInfo = new ItemInfo();
itemInfo.itemID = (int)dic[nameof(itemID)];
itemInfo.realName = (string)dic[nameof(realName)];
itemInfo.customName = (string)dic[nameof(customName)];
itemInfo.customDescription = (string)dic[nameof(customDescription)];
itemInfo.blocked = (bool)dic[nameof(blocked)];
itemInfo.craftRate = (float)(double)dic[nameof(craftRate)];
itemInfo.iconURL = (string)dic[nameof(iconURL)];
itemInfo.category = (string)dic[nameof(category)];
itemInfo.ingredients = new List<ItemIngredient>();
List<object> ingredientList = dic[nameof(ingredients)] as List<object>;
foreach (var iObj in ingredientList) {
ItemIngredient ingredient = ItemIngredient.FromObject(iObj);
if (ingredient != null) itemInfo.ingredients.Add(ingredient);
}
return itemInfo;
}
}
class ItemIngredient {
public int ingredientID;
public string realName;
public float amount;
public ItemIngredient() {
ingredientID = 0;
realName = "";
amount = 0;
}
public ItemIngredient(int ingredientID, float amount) {
this.ingredientID = ingredientID;
realName = GetItemDef().displayName.english;
this.amount = amount;
}
public ItemDefinition GetItemDef() {
return ItemManager.FindItemDefinition(ingredientID);
}
public ItemAmount GetItemAmount() {
return new ItemAmount(GetItemDef(), amount);
}
public static ItemIngredient FromObject(object obj) {
Dictionary<string, object> dic = obj as Dictionary<string, object>;
if (dic == null) return null;
ItemIngredient ingredient = new ItemIngredient();
ingredient.ingredientID = (int)dic[nameof(ingredientID)];
ingredient.realName = (string)dic[nameof(realName)];
ingredient.amount = (float)(double)dic[nameof(amount)];
return ingredient;
}
}
static Dictionary<int, ItemInfo> itemInfoDic = new Dictionary<int, ItemInfo>();
static Dictionary<int, float> originalCraftTimes = new Dictionary<int, float>();
static Dictionary<int, List<ItemIngredient>> originalIngredients = new Dictionary<int, List<ItemIngredient>>();
static HashSet<int> nullBlueprintSet = new HashSet<int>();
bool CanAddItemInfo(ItemDefinition itemDef) {
if (itemDef == null || itemDef.displayName == null) return false;
if (itemInfoDic.ContainsKey(itemDef.itemid)) return false;
return true;
}
void AddItemInfo(ItemDefinition itemDef, bool forceAdd = false) {
if (forceAdd || CanAddItemInfo(itemDef)) itemInfoDic.Add(itemDef.itemid, new ItemInfo(itemDef));
}
void SaveItemInfoDic() {
Config[ItemInfoListName] = itemInfoDic.Values;
SaveConfig();
}
void LoadItemInfoDic() {
var objList = Config[ItemInfoListName] as List<object>;
if (objList == null) {
objList = new List<object>();
Config[ItemInfoListName] = objList;
SaveConfig();
}
itemInfoDic = new Dictionary<int, ItemInfo>();
foreach (var obj in objList) {
ItemInfo itemInfo = ItemInfo.FromObject(obj);
if (itemInfo == null) continue;
itemInfoDic.Add(itemInfo.itemID, itemInfo);
}
VerifyItemInfoDic();
}
void VerifyItemInfoDic() {
if (ItemManager.itemList == null) {
PrintError("ItemManager item list is null at a crucial stage of initilization.Cannot populate ItemInfoDic");
return;
}
if (itemInfoDic == null) PrintError("Item Info Dic is Null");
bool changeMade = false;
List<ItemInfo> values = new List<ItemInfo>(itemInfoDic.Values);
List<int> toRemove = new List<int>();
foreach (ItemInfo value in values) {
ItemDefinition itemDef = ItemManager.FindItemDefinition(value.itemID);
if (itemDef == null) {
toRemove.Add(value.itemID);
continue;
}
if (value.realName != itemDef.displayName.english) {
value.realName = itemDef.displayName.english;
changeMade = true;
}
if (value.category == null) {
value.category = itemDef.category.ToString();
changeMade = true;
}
if (value.iconURL == "") {
value.iconURL = GetItemIconURL(itemDef.shortname);
changeMade = true;
}
if (value.ingredients == null) value.ingredients = new List<ItemIngredient>();
List<int> ingredientIndicesToRemove = new List<int>();
for (int i = 0; i < value.ingredients.Count; i++) {
ItemDefinition ingredientDef = ItemManager.FindItemDefinition(value.ingredients[i].ingredientID);
if (ingredientDef == null) ingredientIndicesToRemove.Add(i);
else if (value.ingredients[i].realName != ingredientDef.displayName.english) {
value.ingredients[i].realName = ingredientDef.displayName.english;
changeMade = true;
}
}
foreach (int index in ingredientIndicesToRemove) {
value.ingredients.RemoveAt(index);
changeMade = true;
}
}
foreach (int id in toRemove) {
itemInfoDic.Remove(id);
changeMade = true;
}
foreach (var item in ItemManager.bpList) {
if (CanAddItemInfo(item.targetItem)) {
AddItemInfo(item.targetItem, true);
changeMade = true;
}
}
foreach (var item in ItemManager.itemList) {
if (CanAddItemInfo(item)) {
AddItemInfo(item, true);
changeMade = true;
}
}
if (changeMade) SaveItemInfoDic();
}
void CreateMissingBlueprints() {
foreach (ItemDefinition itemDef in ItemManager.itemList) {
if (itemDef == null || itemDef.Blueprint != null) continue;
CreateMissingBlueprint(itemDef);
}
}
ItemBlueprint CreateMissingBlueprint(ItemDefinition itemDef) {
if (itemDef.Blueprint != null) return itemDef.Blueprint;
ItemBlueprint bp = itemDef.gameObject.AddComponent<ItemBlueprint>();
bp.ingredients = new List<ItemAmount>();
bp.userCraftable = false;
bp.isResearchable = false;
bp.rarity = Rarity.None;
bp.NeedsSteamItem = false;
bp.amountToCreate = 1;
bp.time = 30f;
nullBlueprintSet.Add(itemDef.itemid);
return bp;
}
ItemInfo FindItemInfo(ItemDefinition itemDef) {
return FindItemInfo(itemDef.itemid);
}
ItemInfo FindItemInfo(int itemID) {
ItemInfo info = null;
itemInfoDic.TryGetValue(itemID, out info);
return info;
}
#endregion
#region Chat Commands
[ChatCommand("craftui.add")]
void AddIngredient_ChatCommands(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 3, command, AddRemoveFormat)) return;
int ingredientAmount;
if (!int.TryParse(args[0], out ingredientAmount)) {
PlayerChat(player, Invalid, args[0], "ingredient amount");
return;
}
ItemDefinition ingredientDef = DisplayNameToItemDef(player, args[1]);
if (ingredientDef == null) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[2]);
if (itemDef == null) return;
ItemInfo itemInfo = FindItemInfo(itemDef);
if (itemInfo == null) return;
if (itemInfo.ingredients.Any(x => x.ingredientID == ingredientDef.itemid)) {
itemInfo.ingredients.First(x => x.ingredientID == ingredientDef.itemid).amount += ingredientAmount;
}
else itemInfo.ingredients.Add(new ItemIngredient(ingredientDef.itemid, ingredientAmount));
PlayerChat(player, AddedIngredient, ingredientAmount, ingredientDef.displayName.english, itemDef.displayName.english);
Puts("Player '" + player.displayName + "' added " + ingredientAmount + " " + ingredientDef.displayName.english + " to " + itemDef.displayName.english);
}
[ChatCommand("craftui.remove")]
void RemoveIngredient_ChatCommands(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 3, command, AddRemoveFormat)) return;
int ingredientAmount;
if (!int.TryParse(args[0], out ingredientAmount)) {
PlayerChat(player, Invalid, args[0], "ingredient amount");
return;
}
ItemDefinition ingredientDef = DisplayNameToItemDef(player, args[1]);
if (ingredientDef == null) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[2]);
if (itemDef == null) return;
ItemInfo itemInfo = FindItemInfo(itemDef);
if (itemInfo == null) return;
if (!itemInfo.ingredients.Any(x => x.ingredientID == ingredientDef.itemid)) {
PlayerChat(player, DoesNotContainIngredient, itemDef.displayName.english, ingredientDef.displayName.english);
return;
}
ItemIngredient ingredient = itemInfo.ingredients.First(x => x.ingredientID == ingredientDef.itemid);
if (ingredientAmount < ingredient.amount) {
ingredient.amount -= ingredientAmount;
PlayerChat(player, RemovedIngredient, ingredientAmount, ingredientDef.displayName.english, itemDef.displayName.english);
Puts("Player '" + player.displayName + "' removed " + ingredientAmount + " " + ingredientDef.displayName.english + " from " + itemDef.displayName.english);
}
else {
itemInfo.ingredients.Remove(ingredient);
PlayerChat(player, RemovedAllIngredient, ingredientDef.displayName.english, itemDef.displayName.english);
Puts("Player '" + player.displayName + "' removed all " + ingredientDef.displayName.english + " from " + itemDef.displayName.english);
}
}
[ChatCommand("craftui.ingredients")]
void IngredientsList_ChatCommand(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 1, command, IngredientsFormat)) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[0]);
if (itemDef == null) return;
ItemInfo info = FindItemInfo(itemDef);
if (info == null) return;
if (info.ingredients.Count == 0) {
PlayerChat(player, HasNoIngredients, itemDef.displayName.english);
}
else {
PlayerChat(player, IngredientsList, itemDef.displayName.english);
foreach (ItemIngredient ingredient in info.ingredients) {
SendReply(player, ingredient.amount + " " + ingredient.GetItemDef().displayName.english);
}
}
}
[ChatCommand("craftui.clearingredients")]
void ClearIngredients_ChatCommands(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 1, command, IngredientsFormat)) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[0]);
if (itemDef == null) return;
ItemInfo itemInfo = FindItemInfo(itemDef);
if (itemInfo == null) return;
itemInfo.ingredients.Clear();
PlayerChat(player, IngredientsCleared, itemDef.displayName.english);
Puts("Player '" + player.displayName + "' cleared " + itemDef.displayName.english + " crafting ingredients");
}
[ChatCommand("craftui.resetingredients")]
void ResetIngredients_ChatCommands(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 1, command, IngredientsFormat)) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[0]);
if (itemDef == null) return;
ItemBlueprint bp = itemDef.Blueprint;
if (bp == null) return;
ItemInfo itemInfo = FindItemInfo(itemDef);
if (itemInfo == null) return;
itemInfo.ingredients = new List<ItemIngredient>(originalIngredients[itemInfo.itemID]);
PlayerChat(player, IngredientsReset, itemDef.displayName.english);
Puts("Player '" + player.displayName + "' reset " + itemDef.displayName.english + " crafting ingredients");
}
[ChatCommand("craftui.craftrate")]
void CraftRate_ChatCommands(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 2, command, CraftrateFormat)) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[0]);
if (itemDef == null) return;
ItemInfo itemInfo = FindItemInfo(itemDef);
if (itemInfo == null) return;
float rate = 0;
if (!float.TryParse(args[1], out rate)) {
PlayerChat(player, Invalid, args[1], "crafting rate");
return;
}
itemInfo.craftRate = rate;
PlayerChat(player, ItemRateChange, itemDef.displayName.english, rate);
Puts("Player '" + player.displayName + "' changed " + itemDef.displayName.english + " craft rate to " + rate);
}
[ChatCommand("craftui.block")]
void Block_ChatCommands(BasePlayer player, string command, string[] args) {
BlockItem(player, command, args, true);
}
[ChatCommand("craftui.unblock")]
void UnBlock_ChatCommands(BasePlayer player, string command, string[] args) {
BlockItem(player, command, args, false);
}
void BlockItem(BasePlayer player, string command, string[] args, bool block) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 1, command, IngredientsFormat)) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[0]);
if (itemDef == null) return;
ItemInfo info = FindItemInfo(itemDef);
if (info == null) return;
info.blocked = block;
if (block) {
PlayerChat(player, ItemBlocked, itemDef.displayName.english);
Puts("Player '" + player.displayName + "' blocked item " + itemDef.displayName.english);
}
else {
PlayerChat(player, ItemNotBlocked, itemDef.displayName.english);
Puts("Player '" + player.displayName + "' unblocked item " + itemDef.displayName.english);
}
}
[ChatCommand("craftui.blockall")]
void BlockAll(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
foreach (var kvp in itemInfoDic) {
kvp.Value.blocked = true;
}
PlayerChat(player, AllItemsBlocked);
Puts("Player '" + player.displayName + "' blocked all items.");
}
[ChatCommand("craftui.unblockall")]
void UnblockAll(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
foreach (var kvp in itemInfoDic) {
kvp.Value.blocked = false;
}
PlayerChat(player, AllItemsUnblocked);
Puts("Player '" + player.displayName + "' unblocked all items.");
}
[ChatCommand("craftui.rename")]
void Rename_ChatCommand(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 2, command, RenameFormat)) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[0]);
if (itemDef == null) return;
ItemInfo itemInfo = FindItemInfo(itemDef);
if (itemInfo == null) return;
itemInfo.customName = args[1];
PlayerChat(player, ItemRenamed, itemInfo.realName, itemInfo.customName);
Puts("Player '" + player.displayName + "' changed item " + itemInfo.realName + " name to " + itemInfo.customName);
}
[ChatCommand("craftui.description")]
void ChangeDrescription_ChatCommand(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 2, command, ChangeDescriptionFormat)) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[0]);
if (itemDef == null) return;
ItemInfo itemInfo = FindItemInfo(itemDef);
if (itemInfo == null) return;
itemInfo.customDescription = args[1];
PlayerChat(player, DescriptionChanged, itemInfo.realName, itemInfo.customDescription);
Puts("Player '" + player.displayName + "' changed item " + itemInfo.realName + " description to " + itemInfo.customName);
}
[ChatCommand("craftui.category")]
void Category_ChatCommand(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 2, command, CategoryFormat)) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[0]);
if (itemDef == null) return;
ItemInfo itemInfo = FindItemInfo(itemDef);
if (itemInfo == null) return;
string category = "";
foreach (var cat in CategoryNames) {
if (cat.ToLower() == args[1].ToLower()) {
category = cat;
break;
}
}
if (category == "") {
PlayerChat(player, Invalid, "Category Name");
return;
}
itemInfo.category = category;
PlayerChat(player, CategoryChanged, itemDef.displayName.english, itemInfo.category);
}
[ChatCommand("craftui.seticon")]
void SetIcon_ChatCommand(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
if (!ArgsCheck(player, args, 2, command, IconFormat)) return;
ItemDefinition itemDef = DisplayNameToItemDef(player, args[0]);
if (itemDef == null) return;
ItemInfo itemInfo = FindItemInfo(itemDef);
if (itemInfo == null) return;
itemInfo.iconURL = args[1];
PlayerChat(player, itemInfo.realName, itemInfo.iconURL);
Puts("Player '" + player.displayName + "' set " + itemInfo.realName + " icon URL to " + itemInfo.iconURL);
}
[ChatCommand("craftui.load")]
void Load_ChatCommand(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
LoadItemInfoDic();
PlayerChat(player, ItemListLoaded);
}
[ChatCommand("craftui.save")]
void Save_ChatCommand(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
SaveItemInfoDic();
PlayerChat(player, ItemListSaved);
}
[ChatCommand("craftui")]
void CraftUI_ChatCommand(BasePlayer player, string command, string[] args) {
if (!AdminCheck(player)) return;
ShowHelpMessage(player);
}
void ShowHelpMessage(BasePlayer player) {
if (!AdminCheck(player)) return;
for (int i = 0; i < 14; i++) {
PlayerChat(player, "HelpLine" + (i + 1).ToString());
}
}
bool AdminCheck(BasePlayer player) {
if (!player.IsAdmin) {
PlayerChat(player, NotAdmin);
return false;
}
return true;
}
bool ArgsCheck(BasePlayer player, string[] args, int minLength, string command, string formatKey) {
if (args == null || args.Length == 0 || args[0].ToLower() == "help") {
PlayerChat(player, FormatHelp, command, Lang(formatKey, player.UserIDString));
return false;
}
if (args.Length < minLength) {
PlayerChat(player, InvalidFormat, command, Lang(formatKey, player.UserIDString));
return false;
}
return true;
}
#endregion
#region UIRendering
class PanelRect {
public float left, bottom, right, top;
public PanelRect() {
left = 0f;
bottom = 0f;
right = 1f;
top = 1f;
}
public PanelRect(float left, float bottom, float right, float top) {
this.left = left;
this.bottom = bottom;
this.right = right;
this.top = top;
}
public string AnchorMin {
get {
return left + " " + bottom;
}
}
public string AnchorMax {
get {
return right + " " + top;
}
}
public PanelRect RelativeTo(PanelRect other) {
left = other.left + (other.right - other.left) * left;
right = other.left + (other.right - other.left) * right;
top = other.bottom + (other.top - other.bottom) * top;
bottom = other.bottom + (other.top - other.bottom) * bottom;
return this;
}
public PanelRect Copy() {
return new PanelRect(left, bottom, right, top);
}
}
class PanelInfo {
public PanelRect rect;
public string backgroundColor;
public PanelInfo(PanelRect rect, string color) {
this.rect = rect;
this.backgroundColor = color;
}
}
const string CraftUIName = "CraftUI";
const string CategoriesName = "Categories";
const string ItemListName = "ItemList";
const string ItemInfoName = "ItemInfo";
const string ResourceCostName = "ResourceCost";
const string CraftCountName = "CraftCount";
const string CraftQueueName = "CraftQueue";
const string CraftQueueTimerName = "CraftQueueTimer";
const string CraftingButtonOverlayName = "CraftingButtonOverlay";
const string QuickCraftOverlayName = "QuickCraftOverlay";
const string QuickCraftOverlayLootingName = "QuicKCraftOverlayLooting";
static readonly Dictionary<string, PanelInfo> panelAnchors = new Dictionary<string, PanelInfo>() {
{
CraftUIName, new PanelInfo(new PanelRect(0, 0, 1, 1), "0.1 0.1 0.1 0.9")
}
, {
CategoriesName, new PanelInfo(new PanelRect(0.06f, 0.25f, 0.16f, 0.9f), "0.4 0.4 0.4 0.4")
}
, {
ItemListName, new PanelInfo(new PanelRect(0.1625f, 0.25f, 0.55f, 0.9f), "0.4 0.4 0.4 0.4")
}
, {
ItemInfoName, new PanelInfo(new PanelRect(0.5525f, 0.355f, 0.94f, 0.9f), "0.4 0.4 0.4 0.4")
}
, {
ResourceCostName, new PanelInfo(new PanelRect(0.5525f, 0.2f, 0.94f, 0.45f), "0.4 0.4 0.4 0.4")
}
, {
CraftCountName, new PanelInfo(new PanelRect(0.5525f, 0.15f, 0.94f, 0.1975f), "0.4 0.4 0.4 0.4")
}
, {
CraftQueueName, new PanelInfo(new PanelRect(0.06f, 0.15f, 0.55f, 0.246f), "0.4 0.4 0.4 0.4")
}
, {
CraftQueueTimerName, new PanelInfo(new PanelRect(0, 0, 0, 0), "0 0 0 0")
}
}
;
static readonly Dictionary<string, PanelInfo> overlayAnchors = new Dictionary<string, PanelInfo>() {
{
CraftingButtonOverlayName, new PanelInfo(new PanelRect(0.2f, 0.9f, 0.8f, 1f), "0 0 0 0")
}
, {
QuickCraftOverlayName, new PanelInfo(new PanelRect(0.65f, 0.125f, 0.95f, 0.45f), "0.3 0.3 0.3 1")
}
, {
QuickCraftOverlayLootingName, new PanelInfo(new PanelRect(0.65f, 0.475f, 0.95f, 0.8f), "0.3 0.3 0.3 1")
}
}
;
//This dictionary is used for the positiopn of the quick craft overlay.It's position needs to be shifted based on the number of columns on a lootable item.static readonly Dictionary<float, PanelRect> lootableOverlayAnchors = new Dictionary<float, PanelRect>()
{
{
1, new PanelRect(0.65f, 0.325f, 0.95f, 0.65f)
}
, {
2, new PanelRect(0.65f, 0.4f, 0.95f, 0.725f)
}
, {
2.5f, new PanelRect(0.65f, 0.45f, 0.95f, 0.775f)
}
, {
3, new PanelRect(0.65f, 0.5f, 0.95f, 0.825f)
}
, {
4, ne
// ... [Code preview truncated due to length. Full source in attached file] ...