Initial Deployment

This commit is contained in:
Patrick Ulrich 2025-01-29 10:43:52 -05:00
commit 29ed11d6c2
3 changed files with 398 additions and 0 deletions

289
DepositBox.cs Normal file
View File

@ -0,0 +1,289 @@
using System;
using System.Collections.Generic;
using System.Globalization; // For CultureInfo
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
namespace Oxide.Plugins
{
[Info("DepositBox", "rustysats", "0.2.0")]
[Description("Drop box that registers drops for admin while removing items from the game.")]
internal class DepositBox : RustPlugin
{
private static DepositBox instance;
// Configuration variables
private int DepositItemID;
private ulong DepositBoxSkinID;
// Permission constants
private const string permPlace = "depositbox.place";
private const string permCheck = "depositbox.check";
private const string permAdminCheck = "depositbox.admincheck";
private DepositLog depositLog;
private Dictionary<Item, BasePlayer> depositTrack = new Dictionary<Item, BasePlayer>(); // Track deposits
#region Oxide Hooks
void Init()
{
instance = this;
LoadConfiguration();
LoadDepositLog();
permission.RegisterPermission(permPlace, this);
permission.RegisterPermission(permCheck, this);
permission.RegisterPermission(permAdminCheck, this);
}
protected override void LoadDefaultConfig()
{
PrintWarning("Creating a new configuration file.");
Config["DepositItemID"] = -1779183908; // Default Item ID for deposits (paper)
Config["DepositBoxSkinID"] = 1641384897; // Default skin ID for the deposit box
SaveConfig();
}
void OnServerInitialized(bool initial)
{
foreach (var entity in BaseNetworkable.serverEntities)
{
if (entity is StorageContainer storageContainer)
{
OnEntitySpawned(storageContainer);
}
}
}
void Unload()
{
foreach (var entity in BaseNetworkable.serverEntities)
{
if (entity is StorageContainer storageContainer && storageContainer.TryGetComponent(out DepositBoxRestriction restriction))
{
restriction.Destroy();
}
}
instance = null;
}
void OnEntitySpawned(StorageContainer container)
{
if (container == null || container.skinID != DepositBoxSkinID) return; // Early return for non-matching containers
if (!container.TryGetComponent(out DepositBoxRestriction mono))
{
mono = container.gameObject.AddComponent<DepositBoxRestriction>();
mono.container = container.inventory; // Assign inventory upon component addition
mono.InitDepositBox();
}
}
#endregion
#region Commands
[ChatCommand("depositbox")]
private void GiveDepositBox(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permPlace))
{
player.ChatMessage(lang.GetMessage("NoPermission", this, player.UserIDString));
return;
}
player.inventory.containerMain.GiveItem(ItemManager.CreateByItemID(833533164, 1, DepositBoxSkinID));
player.ChatMessage(lang.GetMessage("BoxGiven", this, player.UserIDString));
}
[ChatCommand("checkdeposits")]
private void CheckDepositsCommand(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permCheck))
{
player.ChatMessage(lang.GetMessage("NoCheckPermission", this, player.UserIDString));
return;
}
if (depositLog == null || depositLog.Deposits.Count == 0)
{
player.ChatMessage(lang.GetMessage("NoDepositData", this, player.UserIDString));
return;
}
// Group the deposits by SteamID and calculate the total amount deposited for each player
var depositSummary = depositLog.Deposits
.GroupBy(entry => entry.SteamId)
.Select(group => new
{
SteamId = group.Key,
TotalAmount = group.Sum(entry => entry.AmountDeposited)
})
.ToList();
// Calculate the total amount deposited by all players
int totalDeposited = depositSummary.Sum(summary => summary.TotalAmount);
// Find the current player's total deposits
var playerSummary = depositSummary.FirstOrDefault(summary => summary.SteamId == player.UserIDString);
if (playerSummary != null)
{
// Calculate the percentage of total deposits for the current player
double percentageOfTotal = ((double)playerSummary.TotalAmount / totalDeposited) * 100;
player.ChatMessage(lang.GetMessage("PlayerDepositSummary", this, player.UserIDString)
.Replace("{amount}", playerSummary.TotalAmount.ToString(CultureInfo.InvariantCulture))
.Replace("{percentage}", percentageOfTotal.ToString("F2", CultureInfo.InvariantCulture)));
}
else
{
player.ChatMessage(lang.GetMessage("NoPlayerDeposits", this, player.UserIDString));
}
// Admin view if player has both permissions
if (permission.UserHasPermission(player.UserIDString, permAdminCheck))
{
player.ChatMessage(lang.GetMessage("DepositTotals", this, player.UserIDString));
foreach (var summary in depositSummary)
{
double percentage = ((double)summary.TotalAmount / totalDeposited) * 100;
player.ChatMessage(lang.GetMessage("DepositEntrySummary", this, player.UserIDString)
.Replace("{steamid}", summary.SteamId)
.Replace("{amount}", summary.TotalAmount.ToString(CultureInfo.InvariantCulture))
.Replace("{percentage}", percentage.ToString("F2", CultureInfo.InvariantCulture)));
}
}
}
#endregion
#region DepositBoxRestriction Class
public class DepositBoxRestriction : FacepunchBehaviour
{
public ItemContainer container;
public void InitDepositBox()
{
container.canAcceptItem += CanAcceptItem;
container.onItemAddedRemoved += OnItemAddedRemoved;
}
private bool CanAcceptItem(Item item, int targetPos)
{
// Only allow the configured deposit item to be deposited
if (item == null || item.info == null || item.info.itemid != DepositBox.instance.DepositItemID)
{
return false;
}
if (item.GetOwnerPlayer() is BasePlayer player)
{
DepositBox.instance.TrackDeposit(item, player); // Track the item with player reference
}
return true;
}
private void OnItemAddedRemoved(Item item, bool added)
{
// Early exit if item isn't added or isn't the correct deposit item
if (!added || item.info.itemid != DepositBox.instance.DepositItemID) return;
// Try to get the player who deposited the item
if (DepositBox.instance.depositTrack.TryGetValue(item, out BasePlayer player))
{
DepositBox.instance.LogDeposit(player, item.amount); // Log the deposit first
DepositBox.instance.depositTrack.Remove(item); // Remove from tracking
// Now remove the deposited item from the box, after logging is complete
item.Remove();
}
}
public void Destroy()
{
container.canAcceptItem -= CanAcceptItem;
container.onItemAddedRemoved -= OnItemAddedRemoved;
Destroy(this);
}
}
#endregion
#region Logging
private class DepositLog
{
[JsonProperty("deposits")]
public List<DepositEntry> Deposits { get; set; } = new List<DepositEntry>();
}
private class DepositEntry
{
[JsonProperty("steamid")]
public string SteamId { get; set; }
[JsonProperty("timestamp")]
public string Timestamp { get; set; }
[JsonProperty("amount_deposited")]
public int AmountDeposited { get; set; }
}
public void LogDeposit(BasePlayer player, int amount)
{
// Record this deposit
depositLog.Deposits.Add(new DepositEntry
{
SteamId = player.UserIDString,
Timestamp = DateTime.UtcNow.ToString("o"),
AmountDeposited = amount
});
SaveDepositLog(); // Save the log after recording the deposit
// Calculate the player's total deposits
int playerTotalDeposits = depositLog.Deposits
.Where(entry => entry.SteamId == player.UserIDString)
.Sum(entry => entry.AmountDeposited);
// Calculate the total deposits of all players
int totalDepositedByAllPlayers = depositLog.Deposits.Sum(entry => entry.AmountDeposited);
// Calculate the player's percentage of all deposits
double playerPercentageOfTotal = ((double)playerTotalDeposits / totalDepositedByAllPlayers) * 100;
// Send the updated deposit message to the player
player.ChatMessage(lang.GetMessage("DepositRecorded", this, player.UserIDString)
.Replace("{amount}", amount.ToString(CultureInfo.InvariantCulture))
.Replace("{total_amount}", playerTotalDeposits.ToString(CultureInfo.InvariantCulture))
.Replace("{percentage}", playerPercentageOfTotal.ToString("F2", CultureInfo.InvariantCulture)));
}
public void TrackDeposit(Item item, BasePlayer player)
{
if (item != null && player != null)
{
depositTrack[item] = player; // Track the item with its owner
}
}
private void LoadDepositLog()
{
depositLog = Interface.Oxide.DataFileSystem.ReadObject<DepositLog>("DepositBoxLog") ?? new DepositLog();
}
private void SaveDepositLog()
{
Interface.Oxide.DataFileSystem.WriteObject("DepositBoxLog", depositLog);
}
#endregion
#region Configuration
private void LoadConfiguration()
{
DepositItemID = Convert.ToInt32(Config["DepositItemID"], CultureInfo.InvariantCulture); // Specified CultureInfo
DepositBoxSkinID = Convert.ToUInt64(Config["DepositBoxSkinID"], CultureInfo.InvariantCulture); // Specified CultureInfo
}
#endregion
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["NoPermission"] = "You do not have permission to place this box.",
["BoxGiven"] = "You have received a Deposit Box.",
["DepositRecorded"] = "Your deposit of {amount} has been recorded. You have deposited a total of {total_amount} items, which is {percentage}% of all deposits.",
["PlacedNoPerm"] = "You have placed a deposit box but lack permission to place it.",
["NoCheckPermission"] = "You do not have permission to check deposits.",
["NoDepositData"] = "No deposit data found.",
["PlayerDepositSummary"] = "You have deposited a total of {amount} items, which is {percentage}% of all deposits.",
["NoPlayerDeposits"] = "You have not made any deposits.",
["DepositTotals"] = "Deposit Totals:",
["DepositEntrySummary"] = "SteamID: {steamid}, Total Deposited: {amount}, {percentage}% of total."
}, this);
}
#endregion
}
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Patrick Ulrich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

88
README.md Normal file
View File

@ -0,0 +1,88 @@
## Overview
The **DepositBox** plugin allows players to deposit specific items (e.g., paper) into a dropbox, logging the deposits and removing the items from the game. This can be used to create events or competitions, such as a system where players compete to turn in the most items (similar to the Twitch Rust event where players compete for dog tags).
### Features
- Only designated items can be deposited.
- Logs all deposits for tracking.
- Configurable deposit box skin and item type.
- Prevents non-whitelisted items from being deposited.
- Can be used to run events or competitions where players turn in items for rewards.
Once installed players with permission will be able to create a deposit box using /depositbox as a chat command. They can then place this box down allowing players to make deposits into it. All deposits are logged to the data folder.
## Installation
1. Upload the `DepositBox.cs` file to your Rust server under the `/oxide/plugins/` directory.
2. Restart or reload the server for the plugin to initialize:
```bash
oxide.reload DepositBox
```
3. Ensure you grant users permission to use the deposit box:
```bash
oxide.grant user <username> depositbox.place
```
## Configuration
Upon the first run, a default configuration file will be generated at `/oxide/config/DepositBox.json`. The configuration contains the following settings:
```json
{
"DepositItemID": -1779183908, // The item ID for your deposit unit (default: -1779183908)
"DepositBoxSkinID": 1641384897 // The skin ID for the deposit box
}
```
You can edit these values directly in the configuration file if needed.
- **DepositItemID**: The Rust item ID of the item that can be deposited (default: paper with ID `-1779183908`).
- **DepositBoxSkinID**: The Rust skin ID applied to the deposit box (default: `1641384897`).
### Customizing the Configuration:
1. Navigate to `/oxide/config/DepositBox.json`.
2. Modify the values as needed.
3. Save the file and reload the plugin:
```bash
oxide.reload DepositBox
```
### Important Note on Skin IDs:
- The DepositBoxSkinID is used to differentiate between regular storage containers and deposit boxes. Admins should ensure that they select a skin ID that is not actively available in the skin box to avoid confusion or accidental misuse by players. Using a skin that is easily accessible to players could result in unintended behavior where non-deposit boxes are treated as deposit boxes.
## Permissions
- `depositbox.place`: Grants a player permission to place a deposit box.
To assign this permission, use the following command:
```bash
oxide.grant user <username> depositbox.place
```
## Functionality
### Hooks
- **Init()**: Initializes the plugin, loads the configuration, and registers permissions.
- **OnServerInitialized()**: Scans the server for `StorageContainer` entities and applies the plugin's functionality to deposit boxes.
- **Unload()**: Cleans up and removes deposit box restrictions when the plugin is unloaded.
- **OnEntitySpawned()**: When a `StorageContainer` is spawned, the plugin checks if its a deposit box and ensures it follows the required rules.
### Item Handling
- The plugin restricts item deposits to a hardcoded whitelist (currently, only paper can be deposited).
- If an item is not on the whitelist, it will remain in the player's inventory, and only paper will be removed and logged.
- **Logging**: Every time a player deposits paper into the box, the action is logged for administrative tracking.
### Custom Logging
- All paper deposits are logged in the `oxide/data/DepositBoxLog.json` file, structured as follows:
```json
{
"SteamID": "player_steam_id",
"amount_deposited": "amount_deposited",
"Timestamp": "2024-09-22T12:00:00"
}
```
This allows server administrators to keep track of deposits and monitor player activity.