C#:
using Network;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using UnityEngine;
/*
* Скачано с дискорд сервера Rust Edit [PRO+]
* discord.gg/9vyTXsJyKR
*/
namespace Oxide.Plugins {
[Info ("StaticTrader", "discord.gg/9vyTXsJyKR", "1.2.6" )]
[Description ("A smart trading system for friends and family." )]
public class StaticTrader : RustPlugin {
public const bool Debug = true;
public static StaticTrader Instance {
get;
set;
}
public List<Trade> ActiveTrades {
get;
set;
}
= new List<Trade> ();
public Dictionary<ulong, float> CooledDownPlayers {
get;
set;
}
= new Dictionary<ulong, float> ();
public Dictionary<ulong, KeyValuePair<string, string>> PlayersSteamInfo {
get;
set;
}
= new Dictionary<ulong, KeyValuePair<string, string>> ();
public Dictionary<ulong, KeyValuePair<int, string>> PlayerTradeListFilter {
get;
set;
}
= new Dictionary<ulong, KeyValuePair<int, string>> ();
public Trade GetTrade (BasePlayer sentBy, BasePlayer sentTo ) {
foreach (var x in ActiveTrades ) {
if (x.Target == sentTo && x.Initiator == sentBy ) return x;
}
return null;
}
public Trade GetTrade (BasePlayer sentTo ) {
foreach (var x in ActiveTrades ) {
if (x.Target == sentTo ) return x;
}
return null;
}
public Trade GetTrade (ShopFront shopFront ) {
foreach (var x in ActiveTrades ) {
if (x.ShopFront == shopFront ) return x;
}
return null;
}
public Trade GetTrade (ItemContainer feeContainer ) {
foreach (var x in ActiveTrades ) {
if (x.FeePaymentContainer == feeContainer ) return x;
}
return null;
}
public bool CanSentTrade (BasePlayer sentBy, BasePlayer sentTo, out string reason ) {
reason = null;
if (!Debug ) {
if (sentBy == sentTo ) {
reason = GetPhrase ("trade_help_noself", sentBy );
return false;
}
}
if (IsCooledDown (sentBy, false ) ) {
reason = $"You're in cooldown.\n<size=12><color=orange>{CooldownSecondsLeft ( sentBy ):0}</color> seconds left.</size>";
return false;
}
if (!sentTo.IsConnected || sentTo.IsDead () || sentTo.IsSleeping () ) {
reason = $"<color=orange>{sentTo.displayName}</color> is dead, sleeping or not online.";
return false;
}
if (GetTrade (sentBy, sentTo ) != null || GetTrade (sentTo, sentBy ) != null ) {
reason = "There's already a trade sent between you two.";
return false;
}
if (!Config.Rules.CanTradeBuildingBlocked && !sentBy.CanBuild () ) {
reason = "You're building-blocked.";
return false;
}
if (!Config.Rules.CanTradeBuildingBlocked && !sentTo.CanBuild () ) {
reason = $"<color=orange>{sentTo.displayName}</color> is building-blocked.";
return false;
}
if (NoEscape != null ) {
if (!Config.Rules.CanTradeCombatBlocked && NoEscape.Call<bool> ("IsCombatBlocked", sentBy ) ) {
reason = "You're combat-blocked.";
return false;
}
if (!Config.Rules.CanTradeRaidBlocked && NoEscape.Call<bool> ("IsRaidBlocked", sentBy ) ) {
reason = "You're raid-blocked.";
return false;
}
if (!Config.Rules.CanTradeCombatBlocked && NoEscape.Call<bool> ("IsCombatBlocked", sentTo ) ) {
reason = $"<color=orange>{sentTo.displayName}</color> is combat-blocked.";
return false;
}
if (!Config.Rules.CanTradeRaidBlocked && NoEscape.Call<bool> ("IsRaidBlocked", sentTo ) ) {
reason = $"<color=orange>{sentTo.displayName}</color> is raid-blocked.";
return false;
}
}
return true;
}
public bool IsTradingShopFront (ShopFront shopFront ) {
foreach (var x in ActiveTrades ) {
if (x.ShopFront == shopFront ) return true;
}
return false;
}
public bool IsCooledDown (BasePlayer player, bool coolDownPlayer = true ) {
foreach (var group in Config.GroupCooldowns ) {
if (permission.UserHasGroup (player.UserIDString, group.Key ) ) {
if (CooledDownPlayers.ContainsKey (player.userID ) ) {
if (Time.realtimeSinceStartup - CooledDownPlayers [player.userID ] > group.Value ) {
if (coolDownPlayer ) {
CooledDownPlayers [player.userID ] = Time.realtimeSinceStartup;
return true;
}
else {
CooledDownPlayers.Remove (player.userID );
return false;
}
}
else {
return true;
}
}
else if (coolDownPlayer ) {
CooledDownPlayers.Add (player.userID, Time.realtimeSinceStartup );
return true;
}
}
}
return false;
}
public float CooldownSecondsLeft (BasePlayer player ) {
if (IsCooledDown (player, false ) ) {
foreach (var group in Config.GroupCooldowns ) {
if (permission.UserHasGroup (player.UserIDString, group.Key ) ) {
return group.Value - (Time.realtimeSinceStartup - CooledDownPlayers [player.userID ] );
}
}
}
return 0f;
}
public const string InviteEffect = "assets/bundled/prefabs/fx/invite_notice.prefab";
public const string SuccessEffect = "assets/prefabs/building/wall.frame.shopfront/effects/metal_transaction_complete.prefab";
public const string OpenEffect = "assets/prefabs/deployable/locker/effects/locker-deploy.prefab";
#region Permissions
public const string UsePerm = "StaticTrader.use";
public void InstallPermissions () {
permission.RegisterPermission (UsePerm, this );
}
private bool HasPermission (BasePlayer player, string perm, bool quiet = false ) {
if (!permission.UserHasPermission (player.UserIDString, perm ) ) {
if (!quiet ) Print ($"You need to have the \"{perm}\" permission.", player );
return false;
}
return true;
}
#endregion
#region Hooks
private void OnServerInitialized () {
Instance = this;
InstallPermissions ();
InstallCommands ();
Loaded ();
RefreshPlugins ();
}
private void Loaded () {
if (Instance == null ) return;
if (ConfigFile == null ) ConfigFile = new Core.Configuration.DynamicConfigFile ($"{Manager.ConfigPath}{Path.DirectorySeparatorChar}{Name}.json" );
if (!ConfigFile.Exists () ) {
ConfigFile.WriteObject (Config = new RootConfig () );
}
else {
try {
Config = ConfigFile.ReadObject<RootConfig> ();
}
catch (Exception exception ) {
Puts ($"Broken configuration: {exception.Message}" );
}
}
foreach (var player in BasePlayer.activePlayerList ) {
FetchProfileInfo (player.userID );
}
}
private void Unload () {
foreach (var player in BasePlayer.activePlayerList ) {
ClearAllUI (player );
}
foreach (var trade in ActiveTrades ) {
trade?.Clear (true );
}
ActiveTrades.Clear ();
}
private void OnPluginLoaded (Plugin name ) {
RefreshPlugins ();
}
private void OnPluginUnloaded (Plugin name ) {
RefreshPlugins ();
}
private object OnShopCompleteTrade (ShopFront entity ) {
if (!IsTradingShopFront (entity ) ) return null;
var trade = GetTrade (entity );
trade.IsSuccessful = true;
TakePlayerCurrency (trade.Target, trade.Fee );
timer.In (1f, () => {
var vendor = entity.vendorPlayer;
if (vendor == null ) return;
var customer = entity.customerPlayer;
if (customer == null ) return;
vendor.inventory.loot.Clear ();
vendor.inventory.loot.SendImmediate ();
customer.inventory.loot.Clear ();
customer.inventory.loot.SendImmediate ();
SendEffectTo (SuccessEffect, trade.Initiator );
SendEffectTo (SuccessEffect, trade.Target );
trade.Clear ();
IsCooledDown (trade.Initiator, true );
IsCooledDown (trade.Target, true );
}
);
return null;
}
private object OnEntityVisibilityCheck (BaseEntity ent, BasePlayer player, uint id, string debugName, float maximumDistance ) {
var shopFront = ent as ShopFront;
if (shopFront == null ) return null;
if (IsTradingShopFront (shopFront ) ) {
return true;
}
return null;
}
private object CanLootPlayer (BasePlayer looted, BasePlayer looter ) {
var trade = GetTrade (looter );
if (trade != null && trade.FeePaymentContainer == looter.inventory.loot.containers [0 ] ) {
return true;
}
return null;
}
private void OnPlayerLootEnd (PlayerLoot playerLoot ) {
if (playerLoot.containers.Count == 0 ) return;
var player = playerLoot.baseEntity;
var trade = GetTrade (playerLoot.containers [0 ] );
if (trade != null ) {
var feeContainer = trade.FeePaymentContainer;
if (feeContainer.itemList.Count == 0 ) {
Print (GetPhrase ("trade_cancelled", trade.Initiator ), trade.Initiator );
Print (GetPhrase ("trade_cancelled", trade.Target ), trade.Target );
trade.Clear (true );
ActiveTrades.Remove (trade );
}
else {
var item = feeContainer.itemList [0 ];
if (item.amount < trade.Fee ) {
Print ($"{GetPhrase ( "trade_failed", player )} {GetPhrase ( "trade_failed_nomoney", player, Config.Fee.GetName () )}", player );
player.GiveItem (item );
trade.Clear (true );
ActiveTrades.Remove (trade );
}
else {
timer.In (0.2f, () => {
Instance.SendEffectTo (OpenEffect, trade.Target );
Instance.SendEffectTo (OpenEffect, trade.Initiator );
trade.Start ();
}
);
}
}
return;
}
var shopFront = playerLoot.containers [0 ]?.entityOwner as ShopFront;
if (shopFront != null && IsTradingShopFront (shopFront ) ) {
trade = GetTrade (shopFront );
if (!trade.IsSuccessful ) {
Print (GetPhrase ("trade_cancelled", trade.Initiator ), trade.Initiator );
Print (GetPhrase ("trade_cancelled", trade.Target ), trade.Target );
if (trade.FeePaymentContainer != null && trade.FeePaymentContainer.itemList.Count != 0 ) player.GiveItem (trade.FeePaymentContainer.itemList [0 ] );
trade.Clear (true );
}
else {
Print (GetPhrase ("trade_successful", trade.Initiator ), trade.Initiator );
Print (GetPhrase ("trade_successful", trade.Target ), trade.Target );
trade.Clear ();
}
ActiveTrades.Remove (trade );
}
}
private void OnServerSave () {
if (Instance == null ) return;
if (Config != null ) ConfigFile.WriteObject (Config );
}
private void OnPlayerConnected (BasePlayer player ) {
FetchProfileInfo (player.userID );
}
#endregion
#region CUI
public const string PendingInviteUI = "HmmThisPluginIsReallyCoolLetsNotLeakIt";
public const string TeamListUI = "HmmThisPluginIsReallyCoolLetsNotLeakItPls";
public const int HeightOffset = 1000;
public void ClearAllUI (BasePlayer player ) {
ClearPendingInviteUI (player );
ClearTeamListUI (player, false );
}
public void ClearPendingInviteUI (BasePlayer player ) {
for (int i = 0; i < 5; i++ ) {
CuiHelper.DestroyUi (player, PendingInviteUI );
}
}
public void DrawPendingInviteUI (BasePlayer player, Trade trade ) {
if (PlayerTradeListFilter.ContainsKey (player.userID ) ) return;
ClearPendingInviteUI (player );
var other = trade.Initiator == player ? trade.Target : trade.Initiator;
var container = new CuiElementContainer ();
var background = container.Add (new CuiPanel {
Image = {
Color = $"0 0 0 0"
}
, RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = $"0 -{HeightOffset}", OffsetMax = $"0 -{HeightOffset}"
}
, CursorEnabled = false
}
, "Hud", PendingInviteUI );
var fee = Config.Fee.CurrencyType == RootConfig.CurrencyTypes.None ? "" : $" (<b>{Config.Fee.GetValueName ( trade.Fee, false )}</b>)";
var panel = container.Add (new CuiPanel {
Image = {
Color = $"0.15 0.15 0.15 0.6", Material = "assets/content/ui/uibackgroundblur.mat"
}
, RectTransform = {
AnchorMin = "0.4 0.175", AnchorMax = "0.6 0.275", OffsetMin = $"{Config.UINoticeXOffset} {HeightOffset + Config.UINoticeYOffset}", OffsetMax = $"{Config.UINoticeXOffset} {HeightOffset + Config.UINoticeYOffset}"
}
}
, background );
panel = container.Add (new CuiPanel {
Image = {
Color = $"0.15 0.15 0.15 0.6"
}
, RectTransform = {
AnchorMin = "0.02 0.1", AnchorMax = "0.975 0.9"
}
}
, panel );
container.Add (new CuiLabel {
Text = {
Text = $"<b>{other.displayName}</b> has sent you a trading invite.", FontSize = 12, Font = "robotocondensed-regular.ttf", Align = TextAnchor.UpperCenter, Color = "1 1 1 0.8"
}
, RectTransform = {
AnchorMin = $"0 0", AnchorMax = $"1 0.85"
}
}
, panel );
container.Add (new CuiButton {
Button = {
Command = $"{Config.AcceptTradeCommand} {trade.Initiator.userID}", Color = "0.3 0.7 0.2 0.8"
}
, RectTransform = {
AnchorMin = $"0.05 0.15", AnchorMax = "0.495 0.5"
}
, Text = {
Text = $"Accept Invite{fee}", Color = "1 1 1 1", Align = TextAnchor.MiddleCenter, FontSize = 10
}
}
, panel );
container.Add (new CuiButton {
Button = {
Command = $"{Config.DeclineTradeCommand} {trade.Initiator.userID}", Color = "0.7 0.3 0.2 0.8"
}
, RectTransform = {
AnchorMin = $"0.505 0.15", AnchorMax = "0.95 0.5"
}
, Text = {
Text = "Decline Invite", Color = "1 1 1 1", Align = TextAnchor.MiddleCenter, FontSize = 10
}
}
, panel );
CuiHelper.AddUi (player, container );
}
public void ClearTeamListUI (BasePlayer player, bool refresh ) {
for (int i = 0; i < 5; i++ ) {
CuiHelper.DestroyUi (player, TeamListUI );
}
if (!refresh ) {
UnlockPlayer (player );
PlayerTradeListFilter.Remove (player.userID );
}
}
public void DrawTeamListUI (BasePlayer player ) {
ClearTeamListUI (player, true );
if (!PlayerTradeListFilter.ContainsKey (player.userID ) ) {
PlayerTradeListFilter.Add (player.userID, new KeyValuePair<int, string> (0, string.Empty ) );
}
var settings = PlayerTradeListFilter [player.userID ];
var container = new CuiElementContainer ();
var teamMembers = player.Team?.members;
var background = container.Add (new CuiPanel {
Image = {
Color = $"0 0 0 0"
}
, RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = $"0 -{HeightOffset}", OffsetMax = $"0 -{HeightOffset}"
}
, CursorEnabled = true
}
, "Hud", TeamListUI );
var panel = container.Add (new CuiPanel {
Image = {
Color = $"0.15 0.15 0.15 0.6", Material = "assets/content/ui/uibackgroundblur.mat"
}
, RectTransform = {
AnchorMin = "0.3 0.175", AnchorMax = "0.7 0.375", OffsetMin = $"{Config.UINoticeXOffset} {HeightOffset + Config.UINoticeYOffset}", OffsetMax = $"{Config.UINoticeXOffset} {HeightOffset + Config.UINoticeYOffset}"
}
}
, background );
panel = container.Add (new CuiPanel {
Image = {
Color = $"0.15 0.15 0.15 0.6"
}
, RectTransform = {
AnchorMin = "0.01 0.05", AnchorMax = "0.9875 0.95"
}
}
, panel );
var buttonOffset = 0f;
var buttonOffsetSpacing = 25f;
container.Add (new CuiLabel {
Text = {
Text = $"SELECT A <b>PLAYER</b> TO <b>TRADE</b> WITH", FontSize = 14, Font = "robotocondensed-regular.ttf", Align = TextAnchor.UpperLeft, Color = "1 1 1 0.8"
}
, RectTransform = {
AnchorMin = $"0.015 0", AnchorMax = $"1 0.925"
}
}
, panel );
container.Add (new CuiButton {
Button = {
Command = $"closeteamlist", Color = "0.9 0.3 0.2 0.8"
}
, RectTransform = {
AnchorMin = $"0.935 0.775", AnchorMax = "0.98 0.93"
}
, Text = {
Text = $"<b>X</b>", Color = "1 1 1 1", Align = TextAnchor.MiddleCenter, FontSize = 10
}
}
, panel );
container.Add (new CuiButton {
Button = {
Command = $"pageteamlist 1", Color = "0.9 0.8 0.3 0.8"
}
, RectTransform = {
AnchorMin = $"0.935 0.775", AnchorMax = "0.98 0.93", OffsetMin = $"{buttonOffset -= buttonOffsetSpacing} 0", OffsetMax = $"{buttonOffset} 1"
}
, Text = {
Text = $"<b>></b>", Color = "0 0 0 1", Align = TextAnchor.MiddleCenter, FontSize = 12
}
}
, panel );
container.Add (new CuiButton {
Button = {
Command = $"pageteamlist -1", Color = "0.9 0.8 0.3 0.8"
}
, RectTransform = {
AnchorMin = $"0.935 0.775", AnchorMax = "0.98 0.93", OffsetMin = $"{buttonOffset -= buttonOffsetSpacing} 0", OffsetMax = $"{buttonOffset} 1"
}
, Text = {
Text = $"<b><</b>", Color = "0 0 0 1", Align = TextAnchor.MiddleCenter, FontSize = 12
}
}
, panel );
var players = Facepunch.Pool.GetList<BasePlayer> ();
if (teamMembers != null ) {
foreach (var member in teamMembers ) {
var p = BasePlayer.FindByID (member );
if (!Debug && p == player ) continue;
if (!p.IsConnected || (!string.IsNullOrEmpty (settings.Value ) && !p.displayName.ToLower ().Contains (settings.Value.ToLower ().Trim () ) ) ) continue;
players.Add (p );
}
}
if (!Config.TeamOnlyTradingList ) {
foreach (var p in BasePlayer.activePlayerList.Where (x => teamMembers == null ? true : !teamMembers.Contains (x.userID ) ).OrderBy (x => x.displayName ) ) {
if (!Debug && (p == player || players.Contains (p ) ) ) continue;
if (!string.IsNullOrEmpty (settings.Value ) && !p.displayName.ToLower ().Contains (settings.Value.ToLower ().Trim () ) ) continue;
players.Add (p );
}
}
var totalPages = (int )Math.Ceiling ((double )players.Count / 5 );
PlayerTradeListFilter [player.userID ] = new KeyValuePair<int, string> (settings.Key < 0 ? totalPages - 1 : settings.Key >= totalPages ? 0 : settings.Key, settings.Value );
settings = PlayerTradeListFilter [player.userID ];
var searchBar = container.Add (new CuiPanel {
Image = {
Color = $"0.15 0.15 0.15 0.85"
}
, RectTransform = {
AnchorMin = $"0.55 0.775", AnchorMax = "0.83 0.93"
}
}
, panel );
container.Add (new CuiLabel {
Text = {
Text = $"Search player...", FontSize = 10, Font = "robotocondensed-regular.ttf", Align = TextAnchor.MiddleLeft, Color = "1 1 1 0.3"
}
, RectTransform = {
AnchorMin = $"0.03 0", AnchorMax = $"1 1"
}
}
, searchBar );
container.Add (new CuiElement {
Parent = searchBar, Components = {
new CuiInputFieldComponent {
Text = "", FontSize = 10, Command = $"filterteamlist", Align = TextAnchor.MiddleLeft, Color = "1 1 1 1", CharsLimit = 20
}
, new CuiRectTransformComponent {
AnchorMin = "0.03 0", AnchorMax = "1 1"
}
}
}
);
var pagePlayers = players.Skip (6 * settings.Key ).Take (6 );
var length = 1f / 3.1f;
var slotXOffset = 5f;
var slotYOffset = -37.5f;
var slotXOffsetSpacing = 165f;
var slotYOffsetSpacing = 50f;
if (pagePlayers.Any () ) {
for (int i = 0; i < 6; i++ ) {
var valid = i <= pagePlayers.Count () - 1;
var slot = container.Add (new CuiPanel {
Image = {
Color = $"0.05 0.05 0.05 {( valid ? 0.6 : 0.3 )}"
}
, RectTransform = {
AnchorMin = "0 0.7", AnchorMax = $"{length} 1", OffsetMin = $"{slotXOffset} {slotYOffset}", OffsetMax = $"{slotXOffset} {slotYOffset + 1}"
}
}
, panel );
if (i <= pagePlayers.Count () - 1 ) {
var p = pagePlayers.ElementAt (i );
var info = FetchProfileInfo (p.userID );
var isTeamMate = teamMembers == null ? false : teamMembers.Contains (p.userID );
container.Add (new CuiElement {
Parent = slot, Components = {
Death.GetRawImage (info.Key, color : $"1 1 1 0.8" ), new CuiRectTransformComponent {
AnchorMin = "0.03 0.15", AnchorMax = "0.2 0.85"
}
}
}
);
container.Add (new CuiLabel {
Text = {
Text = $"<b>{info.Value}</b>", FontSize = 14, Font = "robotocondensed-regular.ttf", Align = TextAnchor.UpperLeft, Color = "1 1 1 0.8"
}
, RectTransform = {
AnchorMin = $"0.25 0", AnchorMax = $"1 0.85"
}
}
, slot );
container.Add (new CuiLabel {
Text = {
Text = isTeamMate ? "Team Member" : $"{p.userID}", FontSize = 10, Font = "robotocondensed-regular.ttf", Align = TextAnchor.LowerLeft, Color = isTeamMate ? "0.3 0.9 0.2 0.5" : "0.75 0.75 0.75 0.5"
}
, RectTransform = {
AnchorMin = $"0.25 0.2", AnchorMax = $"1 1"
}
}
, slot );
container.Add (new CuiButton {
Button = {
Command = $"{Config.TradeCommand} {p.userID}", Color = "0 0 0 0"
}
, RectTransform = {
AnchorMin = $"0 0", AnchorMax = "1 1"
}
, Text = {
Color = "0 0 0 0"
}
}
, slot );
}
slotXOffset += slotXOffsetSpacing;
if (i % 3 == 2 ) {
slotXOffset = 5f;
slotYOffset -= slotYOffsetSpacing - 5f;
}
}
}
else container.Add (new CuiLabel {
Text = {
Text = Config.TeamOnlyTradingList && player.Team == null ? "You're not in a team." : $"No players have been found.", FontSize = 8, Font = "robotocondensed-regular.ttf", Align = TextAnchor.MiddleCenter, Color = "1 1 1 0.2"
}
, RectTransform = {
AnchorMin = $"0 0.05", AnchorMax = $"1 0.75"
}
}
, panel );
CuiHelper.AddUi (player, container );
pagePlayers = null;
Facepunch.Pool.FreeList (ref players );
LockPlayer (player );
}
public class Death {
public static string GetImage (string url, bool isPng = true, ulong skin = 0 ) {
try {
var name = GetStringChecksum (url );
if (string.IsNullOrEmpty (url ) ) return string.Empty;
if ((bool )Instance.ImageLibrary.Call ("HasImage", name, skin ) ) {
var success = Instance.ImageLibrary.Call ("GetImage", name, skin );
return !isPng ? null : (string )success;
}
else {
Instance.ImageLibrary.Call ("AddImage", url, name, skin );
return !isPng ? url : null;
}
}
catch {
}
return string.Empty;
}
public static CuiRawImageComponent GetRawImage (string url, ulong skin = 0, string color = "", float fade = 0.3f ) {
var _url = GetImage (url, isPng : false, skin : skin );
var _png = GetImage (url, skin : skin );
return new CuiRawImageComponent {
Url = _url, Png = _png, Color = color, FadeIn = fade
}
;
}
}
public static string GetStringChecksum (string value ) {
if (value.Length <= 3 ) return null;
using (var md5 = MD5.Create () ) {
var hash = md5.ComputeHash (System.Text.Encoding.UTF8.GetBytes (value ) );
return BitConverter.ToString (hash ).Replace ("-", "" ).ToLowerInvariant ();
}
}
#endregion
#region Lang
protected override void LoadDefaultMessages () {
var defaultMessages = new Dictionary<string, string> () {
["trade_sent" ]
= "You've sent a trade request to <color=orange>{0}</color>.", ["trade_received" ] = "<color=orange>{0}</color> sent you a trade request.", ["trade_payment" ] = "You'll pay a fee of <color=orange>{0}</color> when the trade is successful.", ["trade_notrade" ] = "There's no trade exchanged between you and that player/any player.", ["trade_title" ] = "<b>{0}</b> has sent you a trading invite.", ["trade_accept" ] = "Accept Invite", ["trade_decline" ] = "Decline Invite", ["trade_expired" ] = "The trade between you and <color=orange>{0}</color> has expired.", ["trade_expired2" ] = "The trade between <color=orange>{0}</color> and you has expired.", ["trade_declined" ] = "<color=orange>{0}</color> has <color=red>declined</color> your trade request.", ["trade_declined2" ] = "Trade with <color=orange>{0}</color> has been <color=red>declined</color>.", ["trade_nomoneys" ] = "You don't have enough <color=orange>{0}</color> to pay the trading fee.", ["trade_nomoneys2" ] = "<color=orange>{0}</color> doesn't have enough <color=orange>{1}</color> to pay the trading fee.", ["trade_cancelled" ] = "Trade <color=red>cancelled</color>.", ["trade_successful" ] = "Trade <color=green>successful</color>.", ["trade_failed" ] = "Trade <color=red>failed</color>.", ["trade_failed_nomoney" ] = "Not enough <color=orange>{0}</color> for the processing fee.", ["trade_help_accept" ] = "<size=10>Do <color=green>/atrade</color> or <color=green>/atrade {0}</color> to accept it.Do <color=red>/dtrade</color> to decline.</size>", ["trade_help_noname" ] = "Please enter the player name you'd like to trade with.", ["trade_help_noplayer" ] = "That player doesn't exist.", ["trade_nopermission" ] = "<color=orange>{0}</color> does not have the permission to trade.", ["trade_noself" ] = "You cannot trade with yourself.",
}
;
lang.RegisterMessages (defaultMessages, this, lang : "en" );
// Use: lang.GetMessage ( "trade_sent", this, userID );
}
public string GetPhrase (string key, BasePlayer player, params string [] parameters ) {
try {
return string.Format (lang.GetMessage (key, this, player.UserIDString ), parameters );
}
catch {
return key;
}
}
#endregion
#region Plugins
private Plugin ImageLibrary;
private Plugin NoEscape;
private Plugin ServerRewards;
private Plugin Economics;
private Plugin OtherPlugin;
#endregion
#region Helpers
private readonly Regex RegexAvatar = new Regex (@"<avatarFull><!\[CDATA\[(.*)\]\]></avatarFull>" );
private readonly Regex RegexUsername = new Regex (@"<steamID><!\[CDATA\[(.*)\]\]></steamID>" );
public void Print (object message, BasePlayer player = null ) {
if (player == null ) PrintToChat ($"<color=orange>{Name}</color>: {message}" );
else PrintToChat (player, $"<color=orange>{Name}</color> (OY): {message}" );
}
public float Scale (float oldValue, float oldMin, float oldMax, float newMin, float newMax ) {
var num = oldMax - oldMin;
var num2 = newMax - newMin;
return (oldValue - oldMin ) * num2 / num + newMin;
}
public string Join (string [] array, string separator, string lastSeparator = null ) {
if (string.IsNullOrEmpty (lastSeparator ) ) {
lastSeparator = separator;
}
if (array.Length == 0 ) {
return string.Empty;
}
if (array.Length == 1 ) {
return array [0 ];
}
List<string> list = new List<string> ();
for (int i = 0; i < array.Length - 1; i++ ) {
list.Add (array [i ] );
}
return string.Join (separator, list.ToArray () ) + $"{lastSeparator}{array [ array.Length - 1 ]}";
}
public void EnsurePlayerToPlayer (BasePlayer player, BasePlayer player2 ) {
var connection = player.Connection;
if (Network.Net.sv.write.Start () == false || connection == null ) return;
++connection.validate.entityUpdates;
var saveInfo = new BaseNetworkable.SaveInfo () {
forConnection = connection, forDisk = false
}
;
Network.Net.sv.write.PacketID (Network.Message.Type.Entities );
Network.Net.sv.write.UInt32 (connection.validate.entityUpdates );
player2.ToStreamForNetwork ((Stream )Network.Net.sv.write, saveInfo );
Network.Net.sv.write.Send (new SendInfo (connection ) );
}
public void SendEffectTo (string effect, BasePlayer player ) {
if (player == null ) return;
var effectInstance = new Effect ();
effectInstance.Init (Effect.Type.Generic, player, 0, Vector3.up, Vector3.zero );
effectInstance.pooledstringid = StringPool.Get (effect );
Net.sv.write.Start ();
Net.sv.write.PacketID (Message.Type.Effect );
effectInstance.WriteToStream (Network.Net.sv.write );
Net.sv.write.Send (new SendInfo (player.net.connection ) );
effectInstance.Clear ();
}
public void GetSteamProfileInfo (ulong userId, Action<string, string> callback ) {
if (callback == null ) return;
webrequest.Enqueue ($"http://steamcommunity.com/profiles/{userId}?xml=1", null, (code, response ) => {
try {
if (code != 200 || response == null ) return;
callback.Invoke (RegexAvatar.Match (response ).Groups [1 ].ToString (), RegexUsername.Match (response ).Groups [1 ].ToString () );
}
catch {
}
}
, Instance );
}
public KeyValuePair<string, string> FetchProfileInfo (ulong userId ) {
if (PlayersSteamInfo.ContainsKey (userId ) ) return PlayersSteamInfo [userId ];
GetSteamProfileInfo (userId, (avatar, username ) => {
PlayersSteamInfo.Add (userId, new KeyValuePair<string, string> (avatar, username ) );
}
);
return new KeyValuePair<string, string> ("https://steamuserimages-a.akamaihd.net/ugc/885384897182110030/F095539864AC9E94AE5236E04C8CA7C2725BCEFF/", BasePlayer.FindByID (userId )?.displayName );
}
public void RefreshPlugins () {
if (ImageLibrary == null || !ImageLibrary.IsLoaded ) ImageLibrary = plugins.Find (nameof (ImageLibrary ) );
if (ServerRewards == null || !ServerRewards.IsLoaded ) ServerRewards = plugins.Find (nameof (ServerRewards ) );
if (Economics == null || !Economics.IsLoaded ) Economics = plugins.Find (nameof (Economics ) );
if (NoEscape == null || !NoEscape.IsLoaded ) NoEscape = plugins.Find (nameof (NoEscape ) );
if (Config.Fee.CurrencyType == RootConfig.CurrencyTypes.Other ) {
OtherPlugin = plugins.Find (Config.Fee.OtherSettings.PluginName );
OtherPlugin?.Load ();
}
}
public Dictionary<BasePlayer, BaseMountable> LockedPlayers {
get;
set;
}
= new Dictionary<BasePlayer, BaseMountable> ();
public void LockPlayer (BasePlayer player ) {
if (LockedPlayers.ContainsKey (player ) || player.isMounted ) return;
var position = player.transform.position;
var mountable = GameManager.server.CreateEntity ("assets/prefabs/vehicle/seats/standingdriver.prefab", player.transform.position, player.transform.rotation, true ) as BaseMountable;
mountable.transform.localPosition = Vector3.zero;
mountable.transform.localEulerAngles = Vector3.zero;
mountable.transform.SetPositionAndRotation (position, player.transform.rotation );
mountable.Spawn ();
mountable.EnableGlobalBroadcast (true );
player.EnsureDismounted ();
player.MountObject (mountable );
mountable.MountPlayer (player );
mountable.transform.position = position;
mountable.SendNetworkUpdate ();
LockedPlayers.Add (player, mountable );
}
public void UnlockPlayer (BasePlayer player ) {
try {
if (LockedPlayers == null || !LockedPlayers.ContainsKey (player ) && player.isMounted ) return;
LockedPlayers [player ].Kill ();
player?.EnsureDismounted ();
player?.DismountObject ();
LockedPlayers.Remove (player );
}
catch {
}
}
#endregion
#region Methods
public void InstallCommands () {
cmd.AddChatCommand (Config.TradeCommand, this, (player, command, args ) => SendTrade (player, args ) );
cmd.AddChatCommand (Config.AcceptTradeCommand, this, (player, command, args ) => AcceptTrade (player, args ) );
cmd.AddChatCommand (Config.DeclineTradeCommand, this, (player, command, args ) => DeclineTrade (player, args ) );
cmd.AddChatCommand (Config.TradeListCommand, this, (player, command, args ) => ListTrade (player, args ) );
cmd.AddConsoleCommand (Config.TradeCommand, this, (arg ) => {
SendTrade (arg.Player (), arg.Args );
return true;
}
);
cmd.AddConsoleCommand (Config.AcceptTradeCommand, this, (arg ) => {
AcceptTrade (arg.Player (), arg.Args );
return true;
}
);
cmd.AddConsoleCommand (Config.DeclineTradeCommand, this, (arg ) => {
DeclineTrade (arg.Player (), arg.Args );
return true;
}
);
cmd.AddConsoleCommand (Config.TradeListCommand, this, (arg ) => {
ListTrade (arg.Player (), arg.Args );
return true;
}
);
}
public void SendTrade (BasePlayer player, string [] args ) {
if (player == null || !HasPermission (player, UsePerm ) ) return;
ClearTeamListUI (player, false );
if (args.Length == 0 ) {
Print (GetPhrase ("trade_successful", player ), player );
return;
}
var filter = Join (args, " " ).ToLower ().Trim ();
var targetPlayer = BasePlayer.allPlayerList.FirstOrDefault (x => x.displayName.ToLower ().Trim ().Contains (filter ) || x.UserIDString.Contains (filter ) );
if (targetPlayer == null ) {
Print (GetPhrase ("trade_help_noplayer", player ), player );
return;
}
if (!HasPermission (targetPlayer, UsePerm ) ) {
Print (GetPhrase ("trade_help_nopermission", player, targetPlayer.displayName ), player );
return;
}
var reason = string.Empty;
if (!CanSentTrade (player, targetPlayer, out reason ) ) {
Print ($"<color=orange>{player.displayName}</color> -> <color=orange>{targetPlayer.displayName}</color>: {reason}", player );
return;
}
var trade = new Trade (player, targetPlayer );
trade.Timer = timer.In (Config.Timeout, () => {
Print (GetPhrase ("trade_expired", player, targetPlayer.displayName ), player );
Print (GetPhrase ("trade_expired2", targetPlayer, player.displayName ), targetPlayer );
trade.Clear ();
ActiveTrades.Remove (trade );
}
);
trade.Fee = trade.GetFee ();
ActiveTrades.Add (trade );
Print (GetPhrase ("trade_sent", player, targetPlayer.displayName ), player );
Print ($"{GetPhrase ( "trade_received", targetPlayer, player.displayName )}{( Config.Fee.CurrencyType == RootConfig.CurrencyTypes.None ? "" : $" {
GetPhrase ("trade_payment", targetPlayer, Config.Fee.GetValueName (trade.Fee, true ) )
}
" )}\n{GetPhrase ( "trade_help_accept", targetPlayer, player.displayName )}", targetPlayer );
if (Config.ShowUINotice ) DrawPendingInviteUI (targetPlayer, trade );
SendEffectTo (InviteEffect, trade.Initiator );
SendEffectTo (InviteEffect, trade.Target );
}
public void AcceptTrade (BasePlayer player, string [] args ) {
if (player == null || !HasPermission (player, UsePerm ) ) return;
ClearTeamListUI (player, false );
var trade = (Trade )null;
if (args.Length == 0 ) {
trade = GetTrade (player );
}
else {
var filter = Join (args, " " ).ToLower ().Trim ();
var targetPlayer = BasePlayer.allPlayerList.FirstOrDefault (x => x.displayName.ToLower ().Trim ().Contains (filter ) || x.UserIDString.Contains (filter ) );
if (targetPlayer == null ) {
Print (GetPhrase ("trade_help_noplayer", player ), player );
return;
}
trade = GetTrade (targetPlayer, player );
}
if (trade == null ) {
Print (GetPhrase ("trade_notrade", player ), player );
return;
}
ClearPendingInviteUI (trade.Target );
ClearPendingInviteUI (trade.Initiator );
trade.Fee = trade.GetFee ();
trade.Timer?.Destroy ();
trade.Timer = null;
switch (Config.Fee.CurrencyType ) {
case RootConfig.CurrencyTypes.Item : trade.PlayerLootContainer (player, "generic_resizable", trade.GetFeePaymentContainer () );
break;
default : if (Config.Fee.CurrencyType != RootConfig.CurrencyTypes.None && !PlayerHasCurrency (trade.Target, trade.Fee ) ) {
Print (GetPhrase ("trade_nomoneys", trade.Target, Config.Fee.GetName () ), trade.Target );
Print (GetPhrase ("trade_nomoneys2", trade.Target, trade.Target.displayName, Config.Fee.GetName () ), trade.Initiator );
}
else {
Instance.SendEffectTo (OpenEffect, trade.Target );
Instance.SendEffectTo (OpenEffect, trade.Initiator );
timer.In (0.15f, trade.Start );
}
break;
}
}
public void DeclineTrade (BasePlayer player, string [] args ) {
if (player == null || !HasPermission (player, UsePerm ) ) return;
ClearTeamListUI (player, false );
var trade = (Trade )null;
if (args.Length == 0 ) {
trade = GetTrade (player );
}
else {
var filter = Join (args, " " ).ToLower ().Trim ();
var targetPlayer = BasePlayer.allPlayerList.FirstOrDefault (x => x.displayName.ToLower ().Trim ().Contains (filter ) || x.UserIDString.Contains (filter ) );
if (targetPlayer == null ) {
Print (GetPhrase ("trade_help_noplayer", player ), player );
return;
}
trade = GetTrade (player, targetPlayer );
}
if (trade == null ) {
Print (GetPhrase ("trade_notrade", player ), player );
return;
}
Print (GetPhrase ("trade_declined", trade.Initiator, trade.Target.displayName ), trade.Initiator );
Print (GetPhrase ("trade_declined2", trade.Target, trade.Initiator.displayName ), trade.Target );
ClearPendingInviteUI (trade.Target );
ClearPendingInviteUI (trade.Initiator );
if (Config.TriggerCooldownOnDecline ) {
IsCooledDown (trade.Initiator, true );
}
trade.Clear ();
ActiveTrades.Remove (trade );
}
public void ListTrade (BasePlayer player, string [] args ) {
if (player == null || !HasPermission (player, UsePerm ) ) return;
DrawTeamListUI (player );
}
[ConsoleCommand ("closeteamlist" )]
private void CloseTeamList (ConsoleSystem.Arg arg ) {
var player = arg.Player ();
if (player == null ) return;
ClearTeamListUI (arg.Player (), false );
}
[ConsoleCommand ("filterteamlist" )]
private void FilterTeamList (ConsoleSystem.Arg arg ) {
var player = arg.Player ();
if (player == null ) return;
var old = PlayerTradeListFilter [player.userID ];
PlayerTradeListFilter [player.userID ] = new KeyValuePair<int, string> (old.Key, Join (arg.Args, " " ) );
DrawTeamListUI (player );
}
[ConsoleCommand ("pa
// ... [Code preview truncated due to length. Full source in attached file] ...