using System;
using System.Collections.Generic;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("LootLogs", "k1lly0u", "0.1.4", ResourceId = 2065)]
[Description("Logs all items deposited and removed from storage, stash and oven containers")]
class LootLogs : RustPlugin
{
#region Fields
Dictionary<uint, StorageType> itemTracker = new Dictionary<uint, StorageType>();
private bool isInit = false;
#endregion
#region Oxide Hooks
void Loaded() => lang.RegisterMessages(Messages, this);
void OnServerInitialized()
{
isInit = true;
}
private void OnEntityDeath(BaseEntity entity, HitInfo hitInfo)
{
try
{
if (isInit)
{
if (entity != null)
{
if (entity is StorageContainer || entity is BaseOven || entity is StashContainer)
{
var killer = "";
if (hitInfo?.InitiatorPlayer != null)
killer = hitInfo.InitiatorPlayer.displayName;
DeathLog(entity.GetType().ToString(), entity.PrefabName, entity.net.ID.ToString(), entity.transform.position.ToString(), killer);
}
}
}
}
catch { }
}
void OnItemAddedToContainer(ItemContainer container, Item item)
{
if (isInit)
{
if (item == null) return;
if (item.uid == 0) return;
if (container.playerOwner != null)
{
if (itemTracker.ContainsKey(item.uid))
{
var player = container.playerOwner;
var data = itemTracker[item.uid];
if (string.IsNullOrEmpty(data.type) || data.type == "BasePlayer") return;
Log(player.displayName, $"{data.itemAmount}x {data.itemName}", data.type, data.entityID, data.entityName, true);
itemTracker.Remove(item.uid);
}
}
else if (container.entityOwner != null)
{
if (itemTracker.ContainsKey(item.uid))
{
var data = itemTracker[item.uid];
string type = "";
if (container.entityOwner is StorageContainer)
type = "StorageContainer";
if (container.entityOwner.GetComponentInParent<BaseOven>())
type = "BaseOven";
if (container.entityOwner is StashContainer)
type = "StashContainer";
if (string.IsNullOrEmpty(type) || type == "BasePlayer") return;
Log(data.entityName, $"{data.itemAmount}x {data.itemName}", type, container.entityOwner.net.ID.ToString(), container.entityOwner.ShortPrefabName, false);
itemTracker.Remove(item.uid);
}
}
}
}
void OnItemRemovedFromContainer(ItemContainer container, Item item)
{
if (isInit)
{
if (item == null) return;
if (item.uid == 0) return;
if (container.entityOwner != null)
{
var entity = container.entityOwner;
var storageData = new StorageType
{
entityName = entity.ShortPrefabName,
entityID = entity.net.ID.ToString(),
itemAmount = item.amount,
itemName = item.info.displayName.english
};
if (entity is StorageContainer)
storageData.type = "StorageContainer";
if (entity.GetComponentInParent<BaseOven>())
storageData.type = "BaseOven";
if (entity is StashContainer)
storageData.type = "StashContainer";
if (string.IsNullOrEmpty(storageData.type)) return;
if (!itemTracker.ContainsKey(item.uid))
{
itemTracker.Add(item.uid, storageData);
timer.Once(5, () =>
{
if (itemTracker.ContainsKey(item.uid))
itemTracker.Remove(item.uid);
});
}
}
else if (container.playerOwner != null)
{
var entity = container.playerOwner;
var storageData = new StorageType
{
entityName = entity.displayName,
entityID = entity.net.ID.ToString(),
itemAmount = item.amount,
itemName = item.info.displayName.english,
type = "BasePlayer"
};
if (!itemTracker.ContainsKey(item.uid))
{
itemTracker.Add(item.uid, storageData);
timer.Once(5, () =>
{
if (itemTracker.ContainsKey(item.uid))
itemTracker.Remove(item.uid);
});
}
}
}
}
class StorageType
{
public string entityName;
public string entityID;
public string itemName;
public int itemAmount;
public string type;
}
#endregion
#region Functions
private BaseEntity FindEntity(BasePlayer player)
{
var currentRot = Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward;
Vector3 eyesAdjust = new Vector3(0f, 1.5f, 0f);
var rayResult = Ray(player.transform.position + eyesAdjust, currentRot);
if (rayResult is BaseEntity)
{
var target = rayResult as BaseEntity;
return target;
}
return null;
}
private object Ray(Vector3 Pos, Vector3 Aim)
{
var hits = Physics.RaycastAll(Pos, Aim);
float distance = 100f;
object target = null;
foreach (var hit in hits)
{
if (hit.collider.GetComponentInParent<BaseEntity>() != null)
{
if (hit.distance < distance)
{
distance = hit.distance;
target = hit.collider.GetComponentInParent<BaseEntity>();
}
}
}
return target;
}
void Log(string playername, string item, string type, string id, string entityname, bool take)
{
var dateTime = DateTime.Now.ToString("yyyy-MM-dd");
var taketype = "looted";
if (!take) taketype = "deposited";
if (!IsValidContainer(entityname)) return;
LogToFile($"{type}-{entityname}-{id}", $"[{dateTime}] {playername} {taketype} {item}", this);
}
void DeathLog(string type, string entityname, string id, string position, string killer)
{
var dateTime = DateTime.Now.ToString("yyyy-MM-dd");
LogToFile($"{type}-deaths", $"[{dateTime}] Name:{entityname} | BoxID:{id} | Position:{position} | Killer: {killer} | LogFile: oxide/logs/LootLogs/lootlogs_{type}-deaths_xxxxxxxx.txt", this);
LogToFile($"{type}-deaths", "-------------------------------------------------------------------------", this);
}
#endregion
#region Chat Commands
[ChatCommand("findid")]
void cmdFindID(BasePlayer player, string command, string[] args)
{
if (!player.IsAdmin) return;
var entity = FindEntity(player);
if (entity == null || ( !(entity is StorageContainer) && !(entity is StashContainer) && !(entity is BaseOven)))
{
SendReply(player, $"<color=orange>{msg("noEntity", player.UserIDString)}</color>");
return;
}
else
{
SendReply(player, string.Format(msg("foundBox", player.UserIDString), entity.GetType(), entity.net.ID, entity.ShortPrefabName, "<color=#939393>", "<color=orange>"));
return;
}
}
#endregion
#region Helpers
private List<string> AllowedContainers = new List<string>
{
"cupboard.tool.deployed",
"box.wooden.large",
"woodbox_deployed",
"campfire",
"bbq.deployed"
};
private bool IsValidContainer(string enttiyName) => AllowedContainers.Contains(enttiyName);
#endregion
#region Messaging
string msg(string key, string id = null) => lang.GetMessage(key, this, id);
Dictionary<string, string> Messages = new Dictionary<string, string>
{
{"noEntity", "You are either not looking at at a entity or you are not looking at the correct type of entity" },
{"foundBox", "{3}The box you are looking at is of the type:</color>{4} {0}</color>{3} with the ID:</color>{4} {1}.</color>{3} You can find the log for this box in </color>{4}'oxide/data/LootLogs/{0}/{2}_{1}_xxdatexx.txt'</color>" }
};
#endregion
}
}
Merged postI got someone to do this, if anyone needs that just replace the original plugin with this code, with the AllowedContainers yo ucan specify which containers should be logged, shoutout for Strobez who did this in no time 💯