Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
486
Scripts/SubSystem/VitaNex/Core/Modules/AutoDonate/AutoDonate.cs
Normal file
486
Scripts/SubSystem/VitaNex/Core/Modules/AutoDonate/AutoDonate.cs
Normal file
@@ -0,0 +1,486 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
|
||||
using VitaNex.IO;
|
||||
using VitaNex.SuperGumps;
|
||||
using VitaNex.Web;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
public static partial class AutoDonate
|
||||
{
|
||||
public const AccessLevel Access = AccessLevel.Owner;
|
||||
|
||||
public static DonationOptions CMOptions { get; private set; }
|
||||
|
||||
public static BinaryDataStore<string, DonationTransaction> Transactions { get; private set; }
|
||||
|
||||
public static BinaryDirectoryDataStore<IAccount, DonationProfile> Profiles { get; private set; }
|
||||
|
||||
private static readonly string[] _AcceptedTypes =
|
||||
{"cart", "express_checkout", "recurring_payment", "send_money", "subscr_payment", "virtual_terminal", "web_accept"};
|
||||
|
||||
private static void OnLogin(LoginEventArgs e)
|
||||
{
|
||||
SpotCheck(e.Mobile);
|
||||
}
|
||||
|
||||
public static void SpotCheck(IAccount a)
|
||||
{
|
||||
if (a != null)
|
||||
{
|
||||
SpotCheck(a.FindMobiles().FirstOrDefault(p => p.IsOnline()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void SpotCheck(Mobile user)
|
||||
{
|
||||
if (user == null || user.Deleted || !user.Alive || !user.IsOnline() || Profiles.Status != DataStoreStatus.Idle ||
|
||||
!CMOptions.ModuleEnabled || CMOptions.CurrencyType == null || CMOptions.CurrencyPrice <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var profile = FindProfile(user.Account);
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (profile.Processed.Any())
|
||||
{
|
||||
var message = String.Format("Hey, {0}!\nYou have unclaimed donation credit!", user.RawName);
|
||||
|
||||
user.SendNotification(
|
||||
message,
|
||||
false,
|
||||
1.0,
|
||||
3.0,
|
||||
Color.LawnGreen,
|
||||
ui =>
|
||||
{
|
||||
ui.CanClose = false;
|
||||
ui.CanDispose = false;
|
||||
|
||||
ui.AddOption(
|
||||
"Claim!",
|
||||
b =>
|
||||
{
|
||||
CheckDonate(user);
|
||||
ui.Close();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleWebForm(WebAPIContext context)
|
||||
{
|
||||
if (!CMOptions.WebForm.Enabled)
|
||||
{
|
||||
context.Response.Data = String.Empty;
|
||||
context.Response.Status = HttpStatusCode.NoContent;
|
||||
return;
|
||||
}
|
||||
|
||||
context.Response.Data = CMOptions.WebForm.Generate();
|
||||
context.Response.ContentType = "html";
|
||||
}
|
||||
|
||||
private static void HandleAccountCheck(WebAPIContext context)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(context.Request.Queries["username"]))
|
||||
{
|
||||
var acc = Accounts.GetAccount(context.Request.Queries["username"]);
|
||||
|
||||
context.Response.Data = acc != null ? "VALID" : "INVALID";
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.Data = "INVALID";
|
||||
}
|
||||
|
||||
context.Response.ContentType = "txt";
|
||||
}
|
||||
|
||||
private static void HandleIPN(WebAPIContext context)
|
||||
{
|
||||
var test = context.Request.Queries["test"] != null || Insensitive.Contains(context.Request.Data, "test_ipn=1");
|
||||
|
||||
var endpoint = test ? "ipnpb.sandbox." : "ipnpb.";
|
||||
|
||||
var paypal = String.Format("https://{0}paypal.com/cgi-bin/webscr", endpoint);
|
||||
|
||||
WebAPI.BeginRequest(paypal, "cmd=_notify-validate&" + context.Request.Data, BeginVerification, EndVerification);
|
||||
}
|
||||
|
||||
private static void BeginVerification(HttpWebRequest webReq, string state)
|
||||
{
|
||||
webReq.Method = "POST";
|
||||
webReq.ContentType = "application/x-www-form-urlencoded";
|
||||
webReq.SetContent(state, ResolveEncoding(state));
|
||||
}
|
||||
|
||||
private static void EndVerification(HttpWebRequest webReq, string state, HttpWebResponse webRes)
|
||||
{
|
||||
var content = webRes.GetContent();
|
||||
|
||||
File.AppendAllLines("IPN.log", new[] { "\n\nREQUEST:\n", state, "\n\nRESPONSE:\n", content });
|
||||
|
||||
if (Insensitive.Contains(content, "VERIFIED"))
|
||||
{
|
||||
using (var queries = new WebAPIQueries(state))
|
||||
{
|
||||
ProcessTransaction(queries);
|
||||
}
|
||||
|
||||
RefreshAdminUI();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessTransaction(WebAPIQueries queries)
|
||||
{
|
||||
var id = queries["txn_id"];
|
||||
|
||||
if (String.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var type = queries["txn_type"];
|
||||
|
||||
if (String.IsNullOrWhiteSpace(type) || !type.EqualsAny(true, _AcceptedTypes))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var status = queries["payment_status"];
|
||||
|
||||
if (String.IsNullOrWhiteSpace(status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TransactionState state;
|
||||
|
||||
switch (status.Trim().ToUpper())
|
||||
{
|
||||
case "PENDING":
|
||||
case "PROCESSED":
|
||||
case "CREATED":
|
||||
state = TransactionState.Pending;
|
||||
break;
|
||||
case "COMPLETED":
|
||||
state = TransactionState.Processed;
|
||||
break;
|
||||
default:
|
||||
state = TransactionState.Voided;
|
||||
break;
|
||||
}
|
||||
|
||||
ExtractCart(queries, out var credit, out var value);
|
||||
|
||||
var custom = queries["custom"] ?? String.Empty;
|
||||
|
||||
var trans = Transactions.GetValue(id);
|
||||
|
||||
var create = trans == null;
|
||||
|
||||
if (create)
|
||||
{
|
||||
var email = queries["payer_email"] ?? String.Empty;
|
||||
var notes = queries["payer_note"] ?? String.Empty;
|
||||
var extra = queries["extra_info"] ?? String.Empty;
|
||||
|
||||
var a = Accounts.GetAccount(custom) ?? CMOptions.FallbackAccount;
|
||||
|
||||
Transactions[id] = trans = new DonationTransaction(id, a, email, value, credit, notes, extra);
|
||||
|
||||
var profile = EnsureProfile(a);
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
state = TransactionState.Voided;
|
||||
trans.Extra += "{VOID: NO PROFILE}";
|
||||
}
|
||||
else
|
||||
{
|
||||
profile.Add(trans);
|
||||
}
|
||||
}
|
||||
|
||||
if (!VerifyValue(queries, "business", CMOptions.Business) &&
|
||||
!VerifyValue(queries, "receiver_email", CMOptions.Business) &&
|
||||
!VerifyValue(queries, "receiver_id", CMOptions.Business))
|
||||
{
|
||||
state = TransactionState.Voided;
|
||||
trans.Extra += "{VOID: UNEXPECTED BUSINESS}";
|
||||
}
|
||||
|
||||
if (trans.Total != value)
|
||||
{
|
||||
state = TransactionState.Voided;
|
||||
trans.Extra += "{VOID: TOTAL CHANGED}";
|
||||
}
|
||||
|
||||
if (queries["test"] != null || queries["test_ipn"] != null)
|
||||
{
|
||||
state = TransactionState.Voided;
|
||||
trans.Extra += "{VOID: TESTING}";
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case TransactionState.Processed:
|
||||
trans.Process();
|
||||
break;
|
||||
case TransactionState.Voided:
|
||||
trans.Void();
|
||||
break;
|
||||
}
|
||||
|
||||
if (create && trans.IsPending)
|
||||
{
|
||||
DonationEvents.InvokeTransPending(trans);
|
||||
}
|
||||
|
||||
SpotCheck(trans.Account);
|
||||
}
|
||||
|
||||
private static bool VerifyValue(WebAPIQueries queries, string key, string val)
|
||||
{
|
||||
return !String.IsNullOrWhiteSpace(queries[key]) && Insensitive.Equals(queries[key], val);
|
||||
}
|
||||
|
||||
private static void ExtractCart(WebAPIQueries queries, out long credit, out double value)
|
||||
{
|
||||
var isCart = Insensitive.Equals(queries["txn_type"], "cart");
|
||||
|
||||
const string totalKey = "quantity";
|
||||
|
||||
var grossKey = "mc_gross";
|
||||
|
||||
if (isCart)
|
||||
{
|
||||
grossKey += '_';
|
||||
}
|
||||
|
||||
credit = 0;
|
||||
value = 0;
|
||||
|
||||
foreach (var kv in queries)
|
||||
{
|
||||
var i = kv.Key.IndexOf("item_number", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (i < 0 || !Insensitive.Equals(kv.Value, CMOptions.CurrencyType.TypeName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var k = "0";
|
||||
|
||||
if (i + 11 < kv.Key.Length)
|
||||
{
|
||||
k = kv.Key.Substring(i + 11);
|
||||
}
|
||||
|
||||
if (String.IsNullOrWhiteSpace(k))
|
||||
{
|
||||
k = "0";
|
||||
}
|
||||
|
||||
if (!Int32.TryParse(k, out i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var subTotal = Math.Max(0, Int64.Parse(queries[totalKey + i.ToString("#")] ?? "0"));
|
||||
var subGross = Math.Max(0, Double.Parse(queries[grossKey + i.ToString("#")] ?? "0", CultureInfo.InvariantCulture));
|
||||
|
||||
if (subTotal <= (isCart ? 0 : 1))
|
||||
{
|
||||
subTotal = (long)(subGross / CMOptions.CurrencyPrice);
|
||||
}
|
||||
else
|
||||
{
|
||||
var expGross = subTotal * CMOptions.CurrencyPrice;
|
||||
|
||||
if (Math.Abs(expGross - subGross) > CMOptions.CurrencyPrice)
|
||||
{
|
||||
subGross = expGross;
|
||||
}
|
||||
}
|
||||
|
||||
credit += subTotal;
|
||||
value += subGross;
|
||||
}
|
||||
}
|
||||
|
||||
private static Encoding ResolveEncoding(string state)
|
||||
{
|
||||
Encoding enc = null;
|
||||
|
||||
var efb = Encoding.UTF8.EncoderFallback;
|
||||
var dfb = Encoding.UTF8.DecoderFallback;
|
||||
|
||||
try
|
||||
{
|
||||
if (Insensitive.Contains(state, "charset="))
|
||||
{
|
||||
var start = state.IndexOf("charset=", StringComparison.OrdinalIgnoreCase) + 8;
|
||||
var count = state.IndexOf('&', start) - start;
|
||||
var value = state.Substring(start, count);
|
||||
|
||||
if (Insensitive.StartsWith(value, "windows-"))
|
||||
{
|
||||
if (Int32.TryParse(value.Substring(8), out var id))
|
||||
{
|
||||
enc = Encoding.GetEncoding(id, efb, dfb);
|
||||
}
|
||||
}
|
||||
|
||||
if (enc == null)
|
||||
{
|
||||
enc = Encoding.GetEncoding(value, efb, dfb);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
enc = null;
|
||||
}
|
||||
|
||||
return enc ?? Encoding.UTF8;
|
||||
}
|
||||
|
||||
public static DonationProfile FindProfile(IAccount a)
|
||||
{
|
||||
return Profiles.GetValue(a);
|
||||
}
|
||||
|
||||
public static DonationProfile EnsureProfile(IAccount a)
|
||||
{
|
||||
var p = Profiles.GetValue(a);
|
||||
|
||||
if (p == null && a != null)
|
||||
{
|
||||
Profiles[a] = p = new DonationProfile(a);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
public static void CheckDonate(Mobile user, bool message = true)
|
||||
{
|
||||
if (user == null || user.Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CMOptions.ModuleEnabled)
|
||||
{
|
||||
if (message)
|
||||
{
|
||||
user.SendMessage("The donation exchange is currently unavailable, please try again later.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!user.Alive)
|
||||
{
|
||||
if (message)
|
||||
{
|
||||
user.SendMessage("You must be alive to do that!");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Profiles.Status != DataStoreStatus.Idle)
|
||||
{
|
||||
if (message)
|
||||
{
|
||||
user.SendMessage("The donation exchange is busy, please try again in a few moments.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (CMOptions.CurrencyType == null || CMOptions.CurrencyPrice <= 0)
|
||||
{
|
||||
if (message)
|
||||
{
|
||||
user.SendMessage("Currency conversion is currently disabled, contact a member of staff to handle your donations.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var profile = FindProfile(user.Account);
|
||||
|
||||
if (profile != null)
|
||||
{
|
||||
var count = profile.Visible.Count();
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
if (message)
|
||||
{
|
||||
user.SendMessage("There are no current donation records for your account.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (message)
|
||||
{
|
||||
user.SendMessage("Thank you for your donation{0}, {1}!", count != 1 ? "s" : "", user.RawName);
|
||||
}
|
||||
|
||||
DonationProfileUI.DisplayTo(user, profile, profile.Visible.FirstOrDefault());
|
||||
}
|
||||
}
|
||||
else if (message)
|
||||
{
|
||||
user.SendMessage("There are no current donation records for your account.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void CheckConfig(Mobile user)
|
||||
{
|
||||
if (user != null && !user.Deleted && user.AccessLevel >= Access)
|
||||
{
|
||||
(SuperGump.GetInstance<DonationAdminUI>(user) ?? new DonationAdminUI(user)).Refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RefreshAdminUI()
|
||||
{
|
||||
foreach (var g in SuperGump.GlobalInstances.Values.OfType<DonationAdminUI>())
|
||||
{
|
||||
g.Refresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
|
||||
using VitaNex.IO;
|
||||
using VitaNex.Web;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
[CoreModule("Auto Donate", "3.1.0.0", true, TaskPriority.Highest)]
|
||||
public static partial class AutoDonate
|
||||
{
|
||||
static AutoDonate()
|
||||
{
|
||||
CMOptions = new DonationOptions();
|
||||
|
||||
Transactions = new BinaryDataStore<string, DonationTransaction>(
|
||||
VitaNexCore.SavesDirectory + "/AutoDonate",
|
||||
"Transactions")
|
||||
{
|
||||
OnSerialize = SerializeTransactions,
|
||||
OnDeserialize = DeserializeTransactions
|
||||
};
|
||||
|
||||
Profiles = new BinaryDirectoryDataStore<IAccount, DonationProfile>(
|
||||
VitaNexCore.SavesDirectory + "/AutoDonate",
|
||||
"Profiles",
|
||||
"pro")
|
||||
{
|
||||
OnSerialize = SerializeProfile,
|
||||
OnDeserialize = DeserializeProfile
|
||||
};
|
||||
}
|
||||
|
||||
private static void CMConfig()
|
||||
{
|
||||
CommandUtility.Register("CheckDonate", AccessLevel.Player, e => CheckDonate(e.Mobile));
|
||||
CommandUtility.Register("DonateConfig", Access, e => CheckConfig(e.Mobile));
|
||||
|
||||
CommandUtility.RegisterAlias("DonateConfig", "DonateAdmin");
|
||||
|
||||
EventSink.Login += OnLogin;
|
||||
|
||||
WebAPI.Register("/donate/ipn", HandleIPN);
|
||||
WebAPI.Register("/donate/acc", HandleAccountCheck);
|
||||
WebAPI.Register("/donate/form", HandleWebForm);
|
||||
}
|
||||
|
||||
private static void CMEnabled()
|
||||
{
|
||||
WebAPI.Register("/donate/ipn", HandleIPN);
|
||||
WebAPI.Register("/donate/acc", HandleAccountCheck);
|
||||
WebAPI.Register("/donate/form", HandleWebForm);
|
||||
}
|
||||
|
||||
private static void CMDisabled()
|
||||
{
|
||||
WebAPI.Unregister("/donate/ipn");
|
||||
WebAPI.Unregister("/donate/acc");
|
||||
WebAPI.Unregister("/donate/form");
|
||||
}
|
||||
|
||||
private static void CMSave()
|
||||
{
|
||||
Transactions.Export();
|
||||
Profiles.Export();
|
||||
}
|
||||
|
||||
private static void CMLoad()
|
||||
{
|
||||
Transactions.Import();
|
||||
Profiles.Import();
|
||||
}
|
||||
|
||||
private static void CMInvoke()
|
||||
{
|
||||
var owner = Accounts.GetAccounts().FirstOrDefault(ac => ac.AccessLevel == AccessLevel.Owner);
|
||||
|
||||
foreach (var trans in Transactions.Values)
|
||||
{
|
||||
if (trans.Account == null && owner != null)
|
||||
{
|
||||
trans.SetAccount(owner);
|
||||
}
|
||||
|
||||
if (trans.Account == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var p = EnsureProfile(trans.Account);
|
||||
|
||||
if (p != null)
|
||||
{
|
||||
p.Transactions[trans.ID] = trans;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool SerializeTransactions(GenericWriter writer)
|
||||
{
|
||||
writer.SetVersion(0);
|
||||
|
||||
writer.WriteBlockDictionary(Transactions, (w, k, v) => v.Serialize(w));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool DeserializeTransactions(GenericReader reader)
|
||||
{
|
||||
reader.GetVersion();
|
||||
|
||||
reader.ReadBlockDictionary(
|
||||
r =>
|
||||
{
|
||||
var t = new DonationTransaction(r);
|
||||
|
||||
return new KeyValuePair<string, DonationTransaction>(t.ID, t);
|
||||
},
|
||||
Transactions);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool SerializeProfile(GenericWriter writer, IAccount key, DonationProfile val)
|
||||
{
|
||||
var version = writer.SetVersion(1);
|
||||
|
||||
writer.WriteBlock(
|
||||
w =>
|
||||
{
|
||||
w.Write(key);
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
val.Serialize(w);
|
||||
break;
|
||||
case 0:
|
||||
w.WriteType(val, t => val.Serialize(w));
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Tuple<IAccount, DonationProfile> DeserializeProfile(GenericReader reader)
|
||||
{
|
||||
var version = reader.GetVersion();
|
||||
|
||||
return reader.ReadBlock(r =>
|
||||
{
|
||||
var key = r.ReadAccount();
|
||||
|
||||
DonationProfile val = null;
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
val = new DonationProfile(r);
|
||||
break;
|
||||
case 0:
|
||||
val = r.ReadTypeCreate<DonationProfile>(r);
|
||||
break;
|
||||
}
|
||||
|
||||
if (key == null && val != null && val.Account != null)
|
||||
{
|
||||
key = val.Account;
|
||||
}
|
||||
|
||||
return Tuple.Create(key, val);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System.Text;
|
||||
|
||||
using Server;
|
||||
using Server.Items;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
public class DonationGiftBook : RedBook
|
||||
{
|
||||
[Constructable]
|
||||
public DonationGiftBook(Mobile author, string text)
|
||||
: base("A Gift", author.RawName, GetPageCount(text), false)
|
||||
{
|
||||
Hue = 0x89B;
|
||||
SetText(text);
|
||||
}
|
||||
|
||||
public DonationGiftBook(Serial serial)
|
||||
: base(serial)
|
||||
{ }
|
||||
|
||||
private static int GetPageCount(string text)
|
||||
{
|
||||
ParseFactors(text.Split(' '), out var wordCount, out var wordsPerLine, out var linesPerPage, out var index, out var pageCount);
|
||||
|
||||
return pageCount;
|
||||
}
|
||||
|
||||
private void SetText(string text)
|
||||
{
|
||||
var words = text.Split(' ');
|
||||
|
||||
ParseFactors(words, out var wordCount, out var wordsPerLine, out var linesPerPage, out var index, out var pageCount);
|
||||
|
||||
for (var currentPage = 0; currentPage < pageCount; currentPage++)
|
||||
{
|
||||
for (var currentLine = 0; currentLine < linesPerPage; currentLine++)
|
||||
{
|
||||
Pages[currentPage] = new BookPageInfo(new string[linesPerPage]);
|
||||
var line = new StringBuilder();
|
||||
|
||||
for (var currentWord = 0; currentWord < wordsPerLine; currentWord++)
|
||||
{
|
||||
if (index >= wordCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
line.AppendFormat(" {0}", words[index]);
|
||||
index++;
|
||||
}
|
||||
|
||||
Pages[currentPage].Lines[currentLine] = line.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseFactors(
|
||||
string[] words,
|
||||
out int wordCount,
|
||||
out int wordsPerLine,
|
||||
out int linesPerPage,
|
||||
out int index,
|
||||
out int pageCount)
|
||||
{
|
||||
wordCount = words.Length;
|
||||
wordsPerLine = 5;
|
||||
linesPerPage = 8;
|
||||
index = 0;
|
||||
pageCount = wordCount / (wordsPerLine * linesPerPage);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
var version = writer.SetVersion(0);
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.GetVersion();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
|
||||
using VitaNex.Crypto;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
public sealed class DonationProfile : IEnumerable<DonationTransaction>, IEquatable<DonationProfile>
|
||||
{
|
||||
public delegate double TierCalculation(DonationProfile p, int tier, double factor);
|
||||
|
||||
public static TierCalculation ComputeNextTier = (p, t, f) => (t + 1) * f;
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public CryptoHashCode UID { get; private set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public IAccount Account { get; private set; }
|
||||
|
||||
public Dictionary<string, DonationTransaction> Transactions { get; private set; }
|
||||
|
||||
public DonationTransaction this[string id] => Transactions.GetValue(id);
|
||||
|
||||
public IEnumerable<DonationTransaction> Pending => Find(TransactionState.Pending);
|
||||
public IEnumerable<DonationTransaction> Processed => Find(TransactionState.Processed);
|
||||
public IEnumerable<DonationTransaction> Claimed => Find(TransactionState.Claimed);
|
||||
public IEnumerable<DonationTransaction> Voided => Find(TransactionState.Voided);
|
||||
|
||||
public IEnumerable<DonationTransaction> Visible => Transactions.Values.Where(t => !t.Hidden);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public long TotalCredit => Claimed.Aggregate(0L, (c, t) => c + t.CreditTotal);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double TotalValue => Claimed.Aggregate(0.0, (c, t) => c + t.Total);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public int Tier
|
||||
{
|
||||
get
|
||||
{
|
||||
var tier = 0;
|
||||
|
||||
if (AutoDonate.CMOptions.TierFactor <= 0.0)
|
||||
{
|
||||
return tier;
|
||||
}
|
||||
|
||||
double total = TotalValue, factor = AutoDonate.CMOptions.TierFactor, req;
|
||||
|
||||
while (total > 0)
|
||||
{
|
||||
req = ComputeNextTier(this, tier, factor);
|
||||
|
||||
if (req <= 0 || total < req)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
total -= req;
|
||||
|
||||
++tier;
|
||||
}
|
||||
|
||||
return tier;
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public long Credit { get; set; }
|
||||
|
||||
public DonationProfile(IAccount account)
|
||||
{
|
||||
Transactions = new Dictionary<string, DonationTransaction>();
|
||||
|
||||
Account = account;
|
||||
|
||||
UID = new CryptoHashCode(CryptoHashType.MD5, Account.Username);
|
||||
}
|
||||
|
||||
public DonationProfile(GenericReader reader)
|
||||
{
|
||||
Deserialize(reader);
|
||||
}
|
||||
|
||||
public IEnumerable<DonationTransaction> Find(TransactionState state)
|
||||
{
|
||||
return Transactions.Values.Where(trans => trans != null && trans.State == state);
|
||||
}
|
||||
|
||||
public DonationTransaction Find(string id)
|
||||
{
|
||||
return Transactions.GetValue(id);
|
||||
}
|
||||
|
||||
public bool Contains(DonationTransaction trans)
|
||||
{
|
||||
return Transactions.ContainsKey(trans.ID);
|
||||
}
|
||||
|
||||
public void Add(DonationTransaction trans)
|
||||
{
|
||||
if (trans != null)
|
||||
{
|
||||
AutoDonate.Transactions[trans.ID] = Transactions[trans.ID] = trans;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(DonationTransaction trans)
|
||||
{
|
||||
return Transactions.Remove(trans.ID);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return Transactions.Values.GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<DonationTransaction> GetEnumerator()
|
||||
{
|
||||
return Transactions.Values.GetEnumerator();
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return UID.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is DonationProfile && Equals((DonationProfile)obj);
|
||||
}
|
||||
|
||||
public bool Equals(DonationProfile other)
|
||||
{
|
||||
return !ReferenceEquals(other, null) && (ReferenceEquals(other, this) || UID.Equals(other.UID));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return UID.ToString();
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
var version = writer.SetVersion(1);
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
case 0:
|
||||
{
|
||||
writer.Write(Account);
|
||||
writer.Write(Credit);
|
||||
|
||||
writer.WriteDictionary(
|
||||
Transactions,
|
||||
(w, k, v) =>
|
||||
{
|
||||
if (v == null)
|
||||
{
|
||||
w.Write(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
w.Write(true);
|
||||
|
||||
if (version > 0)
|
||||
{
|
||||
w.Write(v.ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.Serialize(w);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Deserialize(GenericReader reader)
|
||||
{
|
||||
var version = reader.GetVersion();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
case 0:
|
||||
{
|
||||
Account = reader.ReadAccount();
|
||||
Credit = reader.ReadLong();
|
||||
|
||||
Transactions = reader.ReadDictionary(
|
||||
r =>
|
||||
{
|
||||
string k = null;
|
||||
DonationTransaction v = null;
|
||||
|
||||
if (r.ReadBool())
|
||||
{
|
||||
if (version > 0)
|
||||
{
|
||||
k = r.ReadString();
|
||||
v = AutoDonate.Transactions.GetValue(k);
|
||||
}
|
||||
else
|
||||
{
|
||||
v = new DonationTransaction(r);
|
||||
k = v.ID;
|
||||
|
||||
AutoDonate.Transactions[k] = v;
|
||||
}
|
||||
}
|
||||
|
||||
return new KeyValuePair<string, DonationTransaction>(k, v);
|
||||
},
|
||||
Transactions);
|
||||
|
||||
if (version < 1) // Gifts
|
||||
{
|
||||
reader.ReadDictionary(
|
||||
() =>
|
||||
{
|
||||
var k = reader.ReadString();
|
||||
var v = reader.ReadString();
|
||||
return new KeyValuePair<string, string>(k, v);
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator ==(DonationProfile l, DonationProfile r)
|
||||
{
|
||||
return ReferenceEquals(l, null) ? ReferenceEquals(r, null) : l.Equals(r);
|
||||
}
|
||||
|
||||
public static bool operator !=(DonationProfile l, DonationProfile r)
|
||||
{
|
||||
return ReferenceEquals(l, null) ? !ReferenceEquals(r, null) : !l.Equals(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,566 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
using Server.Misc;
|
||||
|
||||
using VitaNex.IO;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
[PropertyObject]
|
||||
public sealed class DonationTransaction : IEquatable<DonationTransaction>, IComparable<DonationTransaction>
|
||||
{
|
||||
private static void Protect(Item item)
|
||||
{
|
||||
var flags = ScriptCompiler.FindTypeByFullName("Server.Items.ItemFlags");
|
||||
|
||||
if (flags != null)
|
||||
{
|
||||
flags.InvokeMethod("SetStealable", item, false);
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public string ID { get; private set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public IAccount Account { get; private set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public bool Deleted { get; private set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public int Version { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public TimeStamp Time { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public string Email { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public double Total { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access, true)]
|
||||
public long Bonus { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public long Credit { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string Notes { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string Extra { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public TimeStamp DeliveryTime { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string DeliveredTo { get; set; }
|
||||
|
||||
private TransactionState _State;
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public TransactionState State
|
||||
{
|
||||
get => _State;
|
||||
set
|
||||
{
|
||||
if (_State == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var old = _State;
|
||||
|
||||
_State = value;
|
||||
|
||||
OnStateChanged(old);
|
||||
}
|
||||
}
|
||||
|
||||
public TransactionState InternalState { get => State; set => _State = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public bool Hidden => (IsClaimed || IsVoided) && !AutoDonate.CMOptions.ShowHistory;
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public long CreditTotal => Credit + Bonus;
|
||||
|
||||
public bool IsClaimed => State == TransactionState.Claimed;
|
||||
public bool IsPending => State == TransactionState.Pending;
|
||||
public bool IsProcessed => State == TransactionState.Processed;
|
||||
public bool IsVoided => State == TransactionState.Voided;
|
||||
|
||||
public string FullPath => String.Format("{0}|{1}|{2}", Time.Value.Year, Time.Value.GetMonth(), ID);
|
||||
|
||||
public DonationTransaction(
|
||||
string id,
|
||||
IAccount account,
|
||||
string email,
|
||||
double total,
|
||||
long credit,
|
||||
string notes,
|
||||
string extra)
|
||||
{
|
||||
Version = 0;
|
||||
Time = TimeStamp.Now;
|
||||
|
||||
ID = id;
|
||||
|
||||
Account = account;
|
||||
Email = email;
|
||||
Total = total;
|
||||
|
||||
Credit = credit;
|
||||
Bonus = 0;
|
||||
|
||||
Notes = notes;
|
||||
Extra = extra;
|
||||
|
||||
_State = TransactionState.Pending;
|
||||
}
|
||||
|
||||
public DonationTransaction(GenericReader reader)
|
||||
{
|
||||
Deserialize(reader);
|
||||
}
|
||||
|
||||
private void OnStateChanged(TransactionState oldState)
|
||||
{
|
||||
DonationEvents.InvokeStateChanged(this, oldState);
|
||||
}
|
||||
|
||||
public bool Void()
|
||||
{
|
||||
if (State == TransactionState.Voided)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((State = TransactionState.Voided) == TransactionState.Voided)
|
||||
{
|
||||
++Version;
|
||||
|
||||
DonationEvents.InvokeTransVoided(this);
|
||||
|
||||
LogToFile();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Process()
|
||||
{
|
||||
if (State == TransactionState.Processed)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (State != TransactionState.Pending)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((State = TransactionState.Processed) == TransactionState.Processed)
|
||||
{
|
||||
++Version;
|
||||
|
||||
DonationEvents.InvokeTransProcessed(this);
|
||||
|
||||
LogToFile();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Claim(Mobile m)
|
||||
{
|
||||
if (State == TransactionState.Claimed)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (State != TransactionState.Processed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((State = TransactionState.Claimed) == TransactionState.Claimed)
|
||||
{
|
||||
Deliver(m);
|
||||
DeliveredTo = m.RawName;
|
||||
DeliveryTime = TimeStamp.Now;
|
||||
|
||||
Extra += "{SHARD: " + ServerList.ServerName + "}";
|
||||
|
||||
++Version;
|
||||
|
||||
DonationEvents.InvokeTransClaimed(this, m);
|
||||
|
||||
LogToFile();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public long GetCredit(DonationProfile dp, out long credit, out long bonus)
|
||||
{
|
||||
return GetCredit(dp, false, out credit, out bonus);
|
||||
}
|
||||
|
||||
private long GetCredit(DonationProfile dp, bool delivering, out long credit, out long bonus)
|
||||
{
|
||||
if (!delivering && State != TransactionState.Processed)
|
||||
{
|
||||
return (credit = Credit) + (bonus = Bonus);
|
||||
}
|
||||
|
||||
var total = DonationEvents.InvokeTransExchange(this, dp);
|
||||
|
||||
if (AutoDonate.CMOptions.CreditBonus > 0)
|
||||
{
|
||||
total += (long)Math.Floor(Credit * AutoDonate.CMOptions.CreditBonus);
|
||||
}
|
||||
|
||||
bonus = Math.Max(0, total - Credit);
|
||||
credit = Math.Max(0, total - bonus);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
private void Deliver(Mobile m)
|
||||
{
|
||||
if (m == null || m.Account == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Account != m.Account)
|
||||
{
|
||||
SetAccount(m.Account);
|
||||
}
|
||||
|
||||
var dp = AutoDonate.EnsureProfile(Account);
|
||||
|
||||
if (dp == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var total = GetCredit(dp, true, out var credit, out var bonus);
|
||||
|
||||
Credit = credit;
|
||||
Bonus = bonus;
|
||||
|
||||
var bag = DonationEvents.InvokeTransPack(this, dp);
|
||||
|
||||
if (bag == null || bag.Deleted)
|
||||
{
|
||||
dp.Credit += total;
|
||||
return;
|
||||
}
|
||||
|
||||
Protect(bag);
|
||||
|
||||
while (credit > 0)
|
||||
{
|
||||
var cur = AutoDonate.CMOptions.CurrencyType.CreateInstance();
|
||||
|
||||
if (cur == null)
|
||||
{
|
||||
bag.Delete();
|
||||
break;
|
||||
}
|
||||
|
||||
Protect(cur);
|
||||
|
||||
if (cur.Stackable)
|
||||
{
|
||||
cur.Amount = (int)Math.Min(credit, 60000);
|
||||
}
|
||||
|
||||
credit -= cur.Amount;
|
||||
|
||||
bag.DropItem(cur);
|
||||
}
|
||||
|
||||
if (bag.Deleted)
|
||||
{
|
||||
dp.Credit += total;
|
||||
return;
|
||||
}
|
||||
|
||||
while (bonus > 0)
|
||||
{
|
||||
var cur = AutoDonate.CMOptions.CurrencyType.CreateInstance();
|
||||
|
||||
if (cur == null)
|
||||
{
|
||||
bag.Delete();
|
||||
break;
|
||||
}
|
||||
|
||||
Protect(cur);
|
||||
|
||||
cur.Name = String.Format("{0} [Bonus]", cur.ResolveName(m));
|
||||
|
||||
if (cur.Stackable)
|
||||
{
|
||||
cur.Amount = (int)Math.Min(bonus, 60000);
|
||||
}
|
||||
|
||||
bonus -= cur.Amount;
|
||||
|
||||
bag.DropItem(cur);
|
||||
}
|
||||
|
||||
if (bag.Deleted || bag.GiveTo(m, GiveFlags.PackBankDelete) == GiveFlags.Delete)
|
||||
{
|
||||
dp.Credit += total;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAccount(IAccount acc)
|
||||
{
|
||||
if (Account == acc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
++Version;
|
||||
|
||||
Extra += "{ACCOUNT CHANGED FROM '" + Account + "' TO '" + acc + "'}";
|
||||
|
||||
var profile = AutoDonate.FindProfile(Account);
|
||||
|
||||
if (profile != null)
|
||||
{
|
||||
profile.Remove(this);
|
||||
}
|
||||
|
||||
Account = acc;
|
||||
|
||||
profile = AutoDonate.EnsureProfile(Account);
|
||||
|
||||
if (profile != null)
|
||||
{
|
||||
profile.Add(this);
|
||||
}
|
||||
|
||||
LogToFile();
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Deleted = true;
|
||||
|
||||
AutoDonate.Transactions.Remove(ID);
|
||||
|
||||
DonationEvents.InvokeTransactionDeleted(this);
|
||||
|
||||
DeliveredTo = null;
|
||||
SetAccount(null);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ID.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is DonationTransaction && Equals((DonationTransaction)obj);
|
||||
}
|
||||
|
||||
public bool Equals(DonationTransaction other)
|
||||
{
|
||||
return other != null && String.Equals(ID, other.ID);
|
||||
}
|
||||
|
||||
public int CompareTo(DonationTransaction other)
|
||||
{
|
||||
var res = 0;
|
||||
|
||||
if (this.CompareNull(other, ref res))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
return TimeStamp.Compare(Time, other.Time);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void LogToFile()
|
||||
{
|
||||
var file = IOUtility.EnsureFile(VitaNexCore.LogsDirectory + "/Donations/" + ID + ".log");
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(new string('*', 80));
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("{0}: {1}", file.Exists ? "UPDATED" : "CREATED", DateTime.Now);
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("ID: {0}", ID);
|
||||
sb.AppendLine("State: {0}", State);
|
||||
sb.AppendLine("Time: {0}", Time.Value);
|
||||
sb.AppendLine("Version: {0:#,0}", Version);
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Account: {0}", Account);
|
||||
sb.AppendLine("Email: {0}", Email);
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Total: {0}{1} {2}", AutoDonate.CMOptions.MoneySymbol, Total, AutoDonate.CMOptions.MoneyAbbr);
|
||||
sb.AppendLine("Credit: {0:#,0} {1}", Credit, AutoDonate.CMOptions.CurrencyName);
|
||||
sb.AppendLine("Bonus: {0:#,0} {1}", Bonus, AutoDonate.CMOptions.CurrencyName);
|
||||
|
||||
if (DeliveredTo != null)
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Delivered: {0}", DeliveryTime.Value);
|
||||
sb.AppendLine("Recipient: {0}", DeliveredTo);
|
||||
}
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(Notes))
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Notes:");
|
||||
sb.AppendLine(Notes);
|
||||
}
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(Extra))
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Extra:");
|
||||
sb.AppendLine(Extra);
|
||||
}
|
||||
|
||||
sb.Log(file);
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
var version = writer.SetVersion(3);
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 3:
|
||||
writer.Write(Deleted);
|
||||
goto case 2;
|
||||
case 2:
|
||||
case 1:
|
||||
writer.Write(Bonus);
|
||||
goto case 0;
|
||||
case 0:
|
||||
{
|
||||
writer.Write(ID);
|
||||
writer.WriteFlag(_State);
|
||||
writer.Write(Account);
|
||||
writer.Write(Email);
|
||||
writer.Write(Total);
|
||||
writer.Write(Credit);
|
||||
writer.Write(Time);
|
||||
writer.Write(Version);
|
||||
|
||||
writer.Write(Notes);
|
||||
writer.Write(Extra);
|
||||
|
||||
writer.Write(DeliveredTo);
|
||||
writer.Write(DeliveryTime);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Deserialize(GenericReader reader)
|
||||
{
|
||||
var version = reader.GetVersion();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 3:
|
||||
Deleted = reader.ReadBool();
|
||||
goto case 2;
|
||||
case 2:
|
||||
case 1:
|
||||
Bonus = reader.ReadLong();
|
||||
goto case 0;
|
||||
case 0:
|
||||
{
|
||||
ID = reader.ReadString();
|
||||
_State = reader.ReadFlag<TransactionState>();
|
||||
Account = reader.ReadAccount();
|
||||
Email = reader.ReadString();
|
||||
Total = reader.ReadDouble();
|
||||
Credit = reader.ReadLong();
|
||||
|
||||
Time = version > 0 ? reader.ReadTimeStamp() : reader.ReadDouble();
|
||||
|
||||
Version = reader.ReadInt();
|
||||
|
||||
if (version < 1)
|
||||
{
|
||||
reader.ReadInt(); // InternalVersion
|
||||
}
|
||||
|
||||
Notes = reader.ReadString();
|
||||
Extra = reader.ReadString();
|
||||
|
||||
if (version > 1)
|
||||
{
|
||||
DeliveredTo = reader.ReadString();
|
||||
DeliveryTime = reader.ReadTimeStamp();
|
||||
}
|
||||
else if (version > 0)
|
||||
{
|
||||
var m = reader.ReadMobile();
|
||||
|
||||
DeliveredTo = m != null ? m.RawName : null;
|
||||
DeliveryTime = reader.ReadTimeStamp();
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.ReadMobile(); // DeliverFrom
|
||||
|
||||
var m = reader.ReadMobile();
|
||||
|
||||
DeliveredTo = m != null ? m.RawName : null;
|
||||
DeliveryTime = reader.ReadDouble();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
public enum TransactionState
|
||||
{
|
||||
Voided = 0,
|
||||
Pending,
|
||||
Processed,
|
||||
Claimed
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System.Linq;
|
||||
|
||||
using Server;
|
||||
|
||||
using VitaNex.IO;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
[PropertyObject]
|
||||
public sealed class DonationStatistics
|
||||
{
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public DataStoreStatus ProfileStatus => AutoDonate.Profiles.Status;
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public int ProfileCount => AutoDonate.Profiles.Count;
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double TotalIncome => ProfileCount <= 0 ? 0 : AutoDonate.Profiles.Values.Sum(p => p.TotalValue);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public long TotalCredit => ProfileCount <= 0 ? 0 : AutoDonate.Profiles.Values.Sum(p => p.TotalCredit);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public int TierMin => ProfileCount <= 0 ? 0 : AutoDonate.Profiles.Values.Min(p => p.Tier);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public int TierMax => ProfileCount <= 0 ? 0 : AutoDonate.Profiles.Values.Max(p => p.Tier);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double TierAverage => ProfileCount <= 0 ? 0 : AutoDonate.Profiles.Values.Average(p => p.Tier);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public DataStoreStatus TransStatus => AutoDonate.Transactions.Status;
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public int TransCount => AutoDonate.Transactions.Count;
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double TransMin => TransCount <= 0 ? 0 : AutoDonate.Transactions.Values.Min(p => p.Total);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double TransMax => TransCount <= 0 ? 0 : AutoDonate.Transactions.Values.Max(p => p.Total);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double TransAverage => TransCount <= 0 ? 0 : AutoDonate.Transactions.Values.Average(t => t.Total);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public long CreditMin => TransCount <= 0 ? 0 : AutoDonate.Transactions.Values.Min(p => p.Credit);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public long CreditMax => TransCount <= 0 ? 0 : AutoDonate.Transactions.Values.Max(p => p.Credit);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double CreditAverage => TransCount <= 0 ? 0 : AutoDonate.Transactions.Values.Average(t => t.Credit);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Donation Statistics";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
public sealed class DonationOptions : CoreModuleOptions
|
||||
{
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public DonationStatistics Info { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public bool ShowHistory { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public char MoneySymbol { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double TierFactor { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double CreditBonus { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public DonationWebFormOptions WebForm { get; set; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string Business { get => WebForm.Business; set => WebForm.Business = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string MoneyAbbr { get => WebForm.Currency; set => WebForm.Currency = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double CurrencyPrice { get => WebForm.ItemValue; set => WebForm.ItemValue = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string CurrencyName { get => WebForm.ItemName; set => WebForm.ItemName = value; }
|
||||
|
||||
private ItemTypeSelectProperty _CurrencyType = new ItemTypeSelectProperty();
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public ItemTypeSelectProperty CurrencyType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_CurrencyType.TypeName != WebForm.ItemType)
|
||||
{
|
||||
_CurrencyType.TypeName = WebForm.ItemType;
|
||||
}
|
||||
|
||||
return _CurrencyType;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
_CurrencyType = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_CurrencyType.TypeName = String.Empty;
|
||||
}
|
||||
|
||||
WebForm.ItemType = _CurrencyType.TypeName;
|
||||
}
|
||||
}
|
||||
|
||||
private IAccount _FallbackAccount;
|
||||
|
||||
public IAccount FallbackAccount
|
||||
{
|
||||
get
|
||||
{
|
||||
ValidateFallbackAccount(ref _FallbackAccount);
|
||||
return _FallbackAccount;
|
||||
}
|
||||
set
|
||||
{
|
||||
_FallbackAccount = value;
|
||||
ValidateFallbackAccount(ref _FallbackAccount);
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string FallbackUsername
|
||||
{
|
||||
get => FallbackAccount.Username;
|
||||
set => FallbackAccount = Accounts.GetAccount(value);
|
||||
}
|
||||
|
||||
private static void ValidateFallbackAccount(ref IAccount acc)
|
||||
{
|
||||
if (acc == null)
|
||||
{
|
||||
acc = Accounts.GetAccounts().FirstOrDefault(a => a.AccessLevel == AccessLevel.Owner);
|
||||
}
|
||||
}
|
||||
|
||||
public DonationOptions()
|
||||
: base(typeof(AutoDonate))
|
||||
{
|
||||
WebForm = new DonationWebFormOptions();
|
||||
|
||||
MoneySymbol = '$';
|
||||
ShowHistory = false;
|
||||
TierFactor = 0.0;
|
||||
CreditBonus = 0.0;
|
||||
|
||||
Info = new DonationStatistics();
|
||||
}
|
||||
|
||||
public DonationOptions(GenericReader reader)
|
||||
: base(reader)
|
||||
{ }
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
base.Clear();
|
||||
|
||||
MoneySymbol = ' ';
|
||||
ShowHistory = false;
|
||||
TierFactor = 0.0;
|
||||
CreditBonus = 0.0;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
MoneySymbol = '$';
|
||||
ShowHistory = false;
|
||||
TierFactor = 100.0;
|
||||
CreditBonus = 0.0;
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
var version = writer.SetVersion(4);
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 4:
|
||||
writer.Write(FallbackAccount);
|
||||
goto case 3;
|
||||
case 3:
|
||||
writer.Write(CreditBonus);
|
||||
goto case 2;
|
||||
case 2:
|
||||
WebForm.Serialize(writer);
|
||||
goto case 1;
|
||||
case 1:
|
||||
writer.Write(TierFactor);
|
||||
goto case 0;
|
||||
case 0:
|
||||
{
|
||||
writer.Write(ShowHistory);
|
||||
writer.Write(MoneySymbol);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.GetVersion();
|
||||
|
||||
if (version < 2)
|
||||
{
|
||||
WebForm = new DonationWebFormOptions();
|
||||
}
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 4:
|
||||
FallbackAccount = reader.ReadAccount();
|
||||
goto case 3;
|
||||
case 3:
|
||||
CreditBonus = reader.ReadDouble();
|
||||
goto case 2;
|
||||
case 2:
|
||||
WebForm = new DonationWebFormOptions(reader);
|
||||
goto case 1;
|
||||
case 1:
|
||||
TierFactor = reader.ReadDouble();
|
||||
goto case 0;
|
||||
case 0:
|
||||
{
|
||||
if (version < 2)
|
||||
{
|
||||
#region MySQL
|
||||
reader.ReadInt();
|
||||
reader.ReadInt();
|
||||
reader.ReadString();
|
||||
reader.ReadShort();
|
||||
reader.ReadString();
|
||||
reader.ReadString();
|
||||
reader.ReadString();
|
||||
reader.ReadByte();
|
||||
reader.ReadInt();
|
||||
reader.ReadString();
|
||||
reader.ReadString();
|
||||
#endregion
|
||||
|
||||
_CurrencyType = new ItemTypeSelectProperty(reader); // CurrencyType
|
||||
|
||||
reader.ReadString(); // TableName
|
||||
}
|
||||
|
||||
ShowHistory = reader.ReadBool();
|
||||
|
||||
if (version < 2)
|
||||
{
|
||||
CurrencyPrice = reader.ReadDouble(); // UnitPrice
|
||||
}
|
||||
|
||||
MoneySymbol = reader.ReadChar();
|
||||
|
||||
if (version < 2)
|
||||
{
|
||||
MoneyAbbr = reader.ReadString(); // MoneyAbbr
|
||||
reader.ReadBool(); // GiftingEnabled
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Info = new DonationStatistics();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using Server;
|
||||
|
||||
using VitaNex.Text;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
public sealed class DonationWebFormOptions : PropertyObject
|
||||
{
|
||||
private static readonly Dictionary<string, object> _DefOptions = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{"test", false},
|
||||
{"command", "_donations"},
|
||||
{"business", String.Empty},
|
||||
{"notifyUrl", String.Empty},
|
||||
{"returnUrl", String.Empty},
|
||||
{"verifyUrl", String.Empty},
|
||||
{"currency", "USD"},
|
||||
{"itemName", "Gold Coins"},
|
||||
{"itemType", "Gold"},
|
||||
{"itemValue", 1.00},
|
||||
{"amountDef", 25.00},
|
||||
{"amountMin", 5.00},
|
||||
{"amountMax", 500.00},
|
||||
{"amountInc", 1.00},
|
||||
{"buttonName", "Donate"},
|
||||
{"bannerUrl", String.Empty},
|
||||
{"bannerImg", String.Empty},
|
||||
{"shard", String.Empty}
|
||||
};
|
||||
|
||||
private readonly Dictionary<string, object> _Options = new Dictionary<string, object>(_DefOptions, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public bool Test { get => (bool)_Options["test"]; set => _Options["test"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string Command { get => (string)_Options["command"]; set => _Options["command"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string Business { get => (string)_Options["business"]; set => _Options["business"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string NotifyUrl { get => (string)_Options["notifyUrl"]; set => _Options["notifyUrl"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string ReturnUrl { get => (string)_Options["returnUrl"]; set => _Options["returnUrl"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string VerifyUrl { get => (string)_Options["verifyUrl"]; set => _Options["verifyUrl"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string Currency { get => (string)_Options["currency"]; set => _Options["currency"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string ItemName { get => (string)_Options["itemName"]; set => _Options["itemName"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string ItemType { get => (string)_Options["itemType"]; set => _Options["itemType"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double ItemValue { get => (double)_Options["itemValue"]; set => _Options["itemValue"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double AmountDef { get => (double)_Options["amountDef"]; set => _Options["amountDef"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double AmountMin { get => (double)_Options["amountMin"]; set => _Options["amountMin"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double AmountMax { get => (double)_Options["amountMax"]; set => _Options["amountMax"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public double AmountInc { get => (double)_Options["amountInc"]; set => _Options["amountInc"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string ButtonName { get => (string)_Options["buttonName"]; set => _Options["buttonName"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string BannerUrl { get => (string)_Options["bannerUrl"]; set => _Options["bannerUrl"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string BannerImg { get => (string)_Options["bannerImg"]; set => _Options["bannerImg"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public string Shard { get => (string)_Options["shard"]; set => _Options["shard"] = value; }
|
||||
|
||||
[CommandProperty(AutoDonate.Access)]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public Action<StringBuilder> GenerationHandler { get; set; }
|
||||
|
||||
public DonationWebFormOptions()
|
||||
{ }
|
||||
|
||||
public DonationWebFormOptions(GenericReader reader)
|
||||
: base(reader)
|
||||
{ }
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
Enabled = false;
|
||||
|
||||
foreach (var kv in _DefOptions)
|
||||
{
|
||||
_Options[kv.Key] = kv.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Enabled = false;
|
||||
|
||||
foreach (var kv in _DefOptions)
|
||||
{
|
||||
_Options[kv.Key] = kv.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetJsonOptions()
|
||||
{
|
||||
return Json.Encode(_Options);
|
||||
}
|
||||
|
||||
public void SetJsonOptions(string json)
|
||||
{
|
||||
if (!Json.Decode(json, out var obj, out var e))
|
||||
{
|
||||
e.ToConsole();
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj is Dictionary<string, object>)
|
||||
{
|
||||
foreach (var kv in (Dictionary<string, object>)obj)
|
||||
{
|
||||
_Options[kv.Key] = kv.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Generate()
|
||||
{
|
||||
var html = new StringBuilder();
|
||||
|
||||
html.AppendLine("<!DOCTYPE html>");
|
||||
html.AppendLine("<html>");
|
||||
html.AppendLine("\t<head>");
|
||||
html.AppendLine("\t\t<title>{0} - Donate</title>", Shard);
|
||||
html.AppendLine("\t\t<link rel='stylesheet' type='text/css' href='http://www.vita-nex.com/js/inc/index.css' />");
|
||||
html.AppendLine("\t\t<script type='text/javascript' src='http://www.vita-nex.com/js/mod/donateForm.js'></script>");
|
||||
html.AppendLine("\t</head>");
|
||||
html.AppendLine("\t<body>");
|
||||
html.AppendLine("\t\t<div id='index'>");
|
||||
html.AppendLine("\t\t\t<form class='donate-form' data-options='{0}'></form>", GetJsonOptions());
|
||||
html.AppendLine("\t\t</div>");
|
||||
html.AppendLine("\t</body>");
|
||||
html.AppendLine("</html>");
|
||||
|
||||
if (GenerationHandler != null)
|
||||
{
|
||||
GenerationHandler(html);
|
||||
}
|
||||
|
||||
return html.ToString();
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.SetVersion(0);
|
||||
|
||||
writer.Write(Enabled);
|
||||
|
||||
writer.Write(GetJsonOptions());
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
reader.GetVersion();
|
||||
|
||||
Enabled = reader.ReadBool();
|
||||
|
||||
SetJsonOptions(reader.ReadString());
|
||||
}
|
||||
}
|
||||
}
|
||||
1893
Scripts/SubSystem/VitaNex/Core/Modules/AutoDonate/UI/AdminUI.cs
Normal file
1893
Scripts/SubSystem/VitaNex/Core/Modules/AutoDonate/UI/AdminUI.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,825 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
using Server.Gumps;
|
||||
|
||||
using VitaNex.Collections;
|
||||
using VitaNex.SuperGumps;
|
||||
using VitaNex.SuperGumps.UI;
|
||||
using VitaNex.Text;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
public class DonationProfileUI : TreeGump
|
||||
{
|
||||
public static void DisplayTo(Mobile user, DonationProfile profile, DonationTransaction trans)
|
||||
{
|
||||
DisplayTo(user, profile, false, trans);
|
||||
}
|
||||
|
||||
public static void DisplayTo(Mobile user, DonationProfile profile, bool refreshOnly, DonationTransaction trans)
|
||||
{
|
||||
var node = trans.IsPending
|
||||
? ("Transactions|Pending|" + trans.ID)
|
||||
: trans.IsProcessed //
|
||||
? ("Transactions|Claim|" + trans.ID)
|
||||
: !trans.Hidden //
|
||||
? ("History|" + trans.FullPath)
|
||||
: "History";
|
||||
|
||||
DisplayTo(user, profile, refreshOnly, node);
|
||||
}
|
||||
|
||||
public static void DisplayTo(Mobile user)
|
||||
{
|
||||
DisplayTo(user, null);
|
||||
}
|
||||
|
||||
public static void DisplayTo(Mobile user, DonationProfile profile)
|
||||
{
|
||||
DisplayTo(user, profile, String.Empty);
|
||||
}
|
||||
|
||||
public static void DisplayTo(Mobile user, DonationProfile profile, string node)
|
||||
{
|
||||
DisplayTo(user, profile, false, node);
|
||||
}
|
||||
|
||||
public static void DisplayTo(Mobile user, DonationProfile profile, bool refreshOnly)
|
||||
{
|
||||
DisplayTo(user, profile, refreshOnly, String.Empty);
|
||||
}
|
||||
|
||||
public static void DisplayTo(Mobile user, DonationProfile profile, bool refreshOnly, string node)
|
||||
{
|
||||
var info = EnumerateInstances<DonationProfileUI>(user).FirstOrDefault(g => g != null && !g.IsDisposed && g.IsOpen);
|
||||
|
||||
if (info == null)
|
||||
{
|
||||
if (refreshOnly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
info = new DonationProfileUI(user, profile);
|
||||
}
|
||||
else if (profile != null)
|
||||
{
|
||||
info.Profile = profile;
|
||||
}
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(node))
|
||||
{
|
||||
info.SelectedNode = node;
|
||||
}
|
||||
|
||||
info.Refresh(true);
|
||||
}
|
||||
|
||||
private bool _Admin;
|
||||
|
||||
private int _DonationTier;
|
||||
private int _DonationCount;
|
||||
private double _DonationValue;
|
||||
private long _DonationCredit;
|
||||
|
||||
private int[,] _Indicies;
|
||||
private List<DonationTransaction> _Transactions;
|
||||
|
||||
public DonationProfile Profile { get; set; }
|
||||
|
||||
public DonationProfileUI(Mobile user, DonationProfile profile = null)
|
||||
: base(user, null, null, null, null, null, "Donations")
|
||||
{
|
||||
_Indicies = new int[6, 2];
|
||||
|
||||
Profile = profile;
|
||||
|
||||
CanMove = true;
|
||||
CanClose = true;
|
||||
CanDispose = true;
|
||||
CanResize = false;
|
||||
|
||||
Width = 900;
|
||||
Height = 500;
|
||||
|
||||
ForceRecompile = true;
|
||||
}
|
||||
|
||||
public override void AssignCollections()
|
||||
{
|
||||
base.AssignCollections();
|
||||
|
||||
if (_Transactions == null)
|
||||
{
|
||||
ObjectPool.Acquire(out _Transactions);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void MainButtonHandler(GumpButton b)
|
||||
{
|
||||
if (_Admin)
|
||||
{
|
||||
new DonationAdminUI(User, Hide()).Send();
|
||||
return;
|
||||
}
|
||||
|
||||
base.MainButtonHandler(b);
|
||||
}
|
||||
|
||||
protected override void Compile()
|
||||
{
|
||||
_Admin = User.AccessLevel >= AutoDonate.Access;
|
||||
|
||||
if (Profile == null || Profile.Account == null || (!_Admin && User.AccessLevel <= Profile.Account.AccessLevel &&
|
||||
!Profile.Account.IsSharedWith(User.Account)))
|
||||
{
|
||||
Profile = AutoDonate.EnsureProfile(User.Account);
|
||||
}
|
||||
|
||||
if (Profile != null)
|
||||
{
|
||||
_DonationTier = Profile.Tier;
|
||||
_DonationValue = Profile.TotalValue;
|
||||
_DonationCredit = Profile.TotalCredit;
|
||||
_DonationCount = _Admin ? Profile.Transactions.Count : Profile.Visible.Count();
|
||||
|
||||
Title = "Donations: " + Profile.Account;
|
||||
}
|
||||
|
||||
base.Compile();
|
||||
}
|
||||
|
||||
protected override void CompileNodes(Dictionary<TreeGumpNode, Action<Rectangle, int, TreeGumpNode>> list)
|
||||
{
|
||||
list.Clear();
|
||||
|
||||
list["Transactions"] = CompileTransactions;
|
||||
list["Transactions|Pending"] = CompileTransactions;
|
||||
list["Transactions|Claim"] = CompileTransactions;
|
||||
|
||||
var trans = _Admin ? Profile.Transactions.Values : Profile.Visible;
|
||||
|
||||
foreach (var t in trans)
|
||||
{
|
||||
if (t.IsPending)
|
||||
{
|
||||
list["Transactions|Pending|" + t.ID] = CompileTransaction;
|
||||
}
|
||||
else if (t.IsProcessed)
|
||||
{
|
||||
list["Transactions|Claim|" + t.ID] = CompileTransaction;
|
||||
}
|
||||
|
||||
TreeGumpNode n = t.FullPath;
|
||||
|
||||
list["History|" + n.FullName] = CompileTransaction;
|
||||
|
||||
foreach (var p in n.GetParents())
|
||||
{
|
||||
list["History|" + p] = CompileTransactions;
|
||||
}
|
||||
}
|
||||
|
||||
base.CompileNodes(list);
|
||||
}
|
||||
|
||||
protected override void CompileNodeLayout(
|
||||
SuperGumpLayout layout,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h,
|
||||
int index,
|
||||
TreeGumpNode node)
|
||||
{
|
||||
base.CompileNodeLayout(layout, x, y, w, h, index, node);
|
||||
|
||||
if (Nodes == null || !Nodes.ContainsKey(node))
|
||||
{
|
||||
CompileEmptyNodeLayout(layout, x, y, w, h, index, node);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CompileEmptyNodeLayout(
|
||||
SuperGumpLayout layout,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h,
|
||||
int index,
|
||||
TreeGumpNode node)
|
||||
{
|
||||
base.CompileEmptyNodeLayout(layout, x, y, w, h, index, node);
|
||||
|
||||
layout.Add("node/page/" + index, () => CompileOverview(new Rectangle(x, y, w, h), index, node));
|
||||
}
|
||||
|
||||
protected virtual void CompileOverview(Rectangle bounds, int index, TreeGumpNode node)
|
||||
{
|
||||
var info = new StringBuilder();
|
||||
|
||||
info.AppendLine(
|
||||
"Welcome to the Donation Exchange, {0}!",
|
||||
User.RawName.WrapUOHtmlColor(User.GetNotorietyColor(), HtmlColor));
|
||||
info.AppendLine();
|
||||
info.AppendLine("Select a category on the left to browse your transactions.");
|
||||
info.AppendLine();
|
||||
info.AppendLine("MY EXCHANGE".WrapUOHtmlBold().WrapUOHtmlColor(Color.Gold, false));
|
||||
info.AppendLine();
|
||||
|
||||
GetProfileOverview(info);
|
||||
|
||||
AddHtml(
|
||||
bounds.X + 5,
|
||||
bounds.Y,
|
||||
bounds.Width - 5,
|
||||
bounds.Height,
|
||||
info.ToString().WrapUOHtmlColor(HtmlColor),
|
||||
false,
|
||||
true);
|
||||
}
|
||||
|
||||
protected virtual void CompileTransactions(Rectangle b, int index, TreeGumpNode node)
|
||||
{
|
||||
_Transactions.Clear();
|
||||
|
||||
int idx;
|
||||
|
||||
var trans = _Admin ? Profile.Transactions.Values : Profile.Visible;
|
||||
|
||||
switch (node.Name)
|
||||
{
|
||||
case "Transactions":
|
||||
idx = 0;
|
||||
break;
|
||||
case "Claim":
|
||||
{
|
||||
trans = trans.Where(t => t.IsProcessed);
|
||||
|
||||
idx = 1;
|
||||
}
|
||||
break;
|
||||
case "Pending":
|
||||
{
|
||||
trans = trans.Where(t => t.IsPending);
|
||||
|
||||
idx = 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
switch (node.Depth)
|
||||
{
|
||||
default: // History
|
||||
idx = 3;
|
||||
break;
|
||||
case 1: // Year
|
||||
{
|
||||
var y = Utility.ToInt32(node.Name);
|
||||
|
||||
trans = trans.Where(t => t.Time.Value.Year == y);
|
||||
|
||||
idx = 4;
|
||||
}
|
||||
break;
|
||||
case 2: // Month
|
||||
{
|
||||
var y = Utility.ToInt32(node.Parent.Name);
|
||||
var m = (Months)Enum.Parse(typeof(Months), node.Name);
|
||||
|
||||
trans = trans.Where(t => t.Time.Value.Year == y);
|
||||
trans = trans.Where(t => t.Time.Value.GetMonth() == m);
|
||||
|
||||
idx = 5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
_Transactions.AddRange(trans);
|
||||
_Transactions.Sort();
|
||||
|
||||
_Indicies[idx, 1] = _Transactions.Count;
|
||||
_Indicies[idx, 0] = Math.Max(0, Math.Min(_Indicies[idx, 1] - 1, _Indicies[idx, 0]));
|
||||
|
||||
_Transactions.TrimStart(_Indicies[idx, 0]);
|
||||
_Transactions.TrimEndTo((b.Height / 24) - 1);
|
||||
|
||||
// ID | Date | Recipient | Value | Credit | State
|
||||
var cols = new[] { -1, -1, -1, 80, 80, 80 };
|
||||
|
||||
AddTable(b.X, b.Y, b.Width - 25, b.Height, true, cols, _Transactions, 24, Color.Empty, 0, RenderTransaction);
|
||||
|
||||
_Transactions.Clear();
|
||||
|
||||
AddBackground(b.X + (b.Width - 25), b.Y, 28, b.Height, SupportsUltimaStore ? 40000 : 9260);
|
||||
|
||||
AddScrollbarV(
|
||||
b.X + (b.Width - 24),
|
||||
b.Y,
|
||||
b.Height,
|
||||
_Indicies[idx, 1],
|
||||
_Indicies[idx, 0],
|
||||
p =>
|
||||
{
|
||||
--_Indicies[idx, 0];
|
||||
Refresh(true);
|
||||
},
|
||||
n =>
|
||||
{
|
||||
++_Indicies[idx, 0];
|
||||
Refresh(true);
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual void RenderTransaction(int x, int y, int w, int h, DonationTransaction t, int r, int c)
|
||||
{
|
||||
var bgCol = r % 2 != 0 ? Color.DarkSlateGray : Color.Black;
|
||||
var fgCol = r % 2 != 0 ? Color.White : Color.WhiteSmoke;
|
||||
|
||||
ApplyPadding(ref x, ref y, ref w, ref h, 2);
|
||||
|
||||
if (r < 0) // headers
|
||||
{
|
||||
var label = String.Empty;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case -1:
|
||||
AddHtml(x, y, w, h, label, fgCol, bgCol);
|
||||
break;
|
||||
case 0:
|
||||
label = "ID";
|
||||
goto case -1;
|
||||
case 1:
|
||||
label = "Date";
|
||||
goto case -1;
|
||||
case 2:
|
||||
label = "Recipient";
|
||||
goto case -1;
|
||||
case 3:
|
||||
label = AutoDonate.CMOptions.MoneySymbol + AutoDonate.CMOptions.MoneyAbbr;
|
||||
goto case -1;
|
||||
case 4:
|
||||
label = AutoDonate.CMOptions.CurrencyName;
|
||||
goto case -1;
|
||||
case 5:
|
||||
label = "Status";
|
||||
goto case -1;
|
||||
}
|
||||
}
|
||||
else if (t != null)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 0: // ID
|
||||
AddHtml(x, y, w, h, t.ID, fgCol, bgCol);
|
||||
break;
|
||||
case 1: // Date
|
||||
{
|
||||
AddHtml(x, y, w, h, t.Time.Value.ToSimpleString("m/d/y"), fgCol, bgCol);
|
||||
AddTooltip(t.Time.Value.ToSimpleString());
|
||||
}
|
||||
break;
|
||||
case 2: // Recipient
|
||||
{
|
||||
AddHtml(x, y, w, h, t.DeliveredTo ?? String.Empty, fgCol, bgCol);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(t.DeliveredTo))
|
||||
{
|
||||
AddTooltip(t.DeliveryTime.Value.ToSimpleString());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3: // Value
|
||||
AddHtml(x, y, w, h, AutoDonate.CMOptions.MoneySymbol + t.Total.ToString("#,0.00"), fgCol, bgCol);
|
||||
break;
|
||||
case 4: // Credit
|
||||
{
|
||||
if (t.Bonus > 0)
|
||||
{
|
||||
AddHtml(x, y, w, h, String.Format("{0:#,0} +{1:#,0}", t.Credit, t.Bonus), fgCol, bgCol);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddHtml(x, y, w, h, t.Credit.ToString("#,0"), fgCol, bgCol);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5: // Status
|
||||
{
|
||||
string node;
|
||||
|
||||
if (t.IsPending)
|
||||
{
|
||||
node = "Transactions|Pending|" + t.ID;
|
||||
}
|
||||
else if (t.IsProcessed)
|
||||
{
|
||||
node = "Transactions|Claim|" + t.ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = "History|" + t.FullPath;
|
||||
}
|
||||
|
||||
var label = String.Empty;
|
||||
var color = fgCol;
|
||||
|
||||
switch (t.State)
|
||||
{
|
||||
case TransactionState.Voided:
|
||||
{
|
||||
label = UniGlyph.CircleX.ToString();
|
||||
color = Color.IndianRed;
|
||||
}
|
||||
break;
|
||||
case TransactionState.Pending:
|
||||
{
|
||||
label = UniGlyph.Coffee.ToString();
|
||||
color = Color.Yellow;
|
||||
}
|
||||
break;
|
||||
case TransactionState.Processed:
|
||||
{
|
||||
label = UniGlyph.StarEmpty.ToString();
|
||||
color = Color.SkyBlue;
|
||||
}
|
||||
break;
|
||||
case TransactionState.Claimed:
|
||||
{
|
||||
label = UniGlyph.StarFill.ToString();
|
||||
color = Color.LawnGreen;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
label = label.WrapUOHtmlColor(color, fgCol);
|
||||
label += " " + t.State.ToString(true);
|
||||
|
||||
AddHtmlButton(x, y, w, h, b => SelectNode(node), label, fgCol, bgCol);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CompileTransaction(Rectangle b, int index, TreeGumpNode node)
|
||||
{
|
||||
var trans = Profile[node.Name];
|
||||
|
||||
if (trans == null)
|
||||
{
|
||||
CompileOverview(b, index, node);
|
||||
return;
|
||||
}
|
||||
|
||||
var cpHeight = _Admin ? 60 : 30;
|
||||
|
||||
var html = new StringBuilder();
|
||||
|
||||
GetTransactionOverview(trans, html, true, true, true);
|
||||
|
||||
AddHtml(
|
||||
b.X + 5,
|
||||
b.Y,
|
||||
b.Width - 5,
|
||||
b.Height - cpHeight,
|
||||
html.ToString().WrapUOHtmlColor(Color.White, false),
|
||||
false,
|
||||
true);
|
||||
|
||||
var bw = b.Width;
|
||||
var bh = cpHeight;
|
||||
|
||||
if (_Admin)
|
||||
{
|
||||
bh /= 2;
|
||||
}
|
||||
|
||||
switch (trans.State)
|
||||
{
|
||||
case TransactionState.Voided:
|
||||
{
|
||||
AddHtmlButton(
|
||||
b.X,
|
||||
b.Y + (b.Height - bh),
|
||||
bw,
|
||||
bh,
|
||||
o => OnVoidedTransaction(trans),
|
||||
"[VOIDED]",
|
||||
Color.OrangeRed,
|
||||
Color.Black,
|
||||
Color.OrangeRed,
|
||||
2);
|
||||
}
|
||||
break;
|
||||
case TransactionState.Pending:
|
||||
{
|
||||
AddHtmlButton(
|
||||
b.X,
|
||||
b.Y + (b.Height - bh),
|
||||
bw,
|
||||
bh,
|
||||
o => OnPendingTransaction(trans),
|
||||
"[PENDING]",
|
||||
Color.Yellow,
|
||||
Color.Black,
|
||||
Color.Yellow,
|
||||
2);
|
||||
}
|
||||
break;
|
||||
case TransactionState.Processed:
|
||||
{
|
||||
AddHtmlButton(
|
||||
b.X,
|
||||
b.Y + (b.Height - bh),
|
||||
bw,
|
||||
bh,
|
||||
o => OnClaimTransaction(trans),
|
||||
"[CLAIM]",
|
||||
Color.SkyBlue,
|
||||
Color.Black,
|
||||
Color.SkyBlue,
|
||||
2);
|
||||
}
|
||||
break;
|
||||
case TransactionState.Claimed:
|
||||
{
|
||||
AddHtmlButton(
|
||||
b.X,
|
||||
b.Y + (b.Height - bh),
|
||||
bw,
|
||||
bh,
|
||||
o => OnClaimedTransaction(trans),
|
||||
"[CLAIMED]",
|
||||
Color.LawnGreen,
|
||||
Color.Black,
|
||||
Color.LawnGreen,
|
||||
2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (_Admin)
|
||||
{
|
||||
bw /= 2;
|
||||
|
||||
AddHtmlButton(
|
||||
b.X,
|
||||
b.Y + (b.Height - (bh * 2)),
|
||||
bw,
|
||||
bh,
|
||||
o => OnTransactionEdit(trans),
|
||||
"[EDIT]",
|
||||
Color.Gold,
|
||||
Color.Black,
|
||||
Color.Gold,
|
||||
2);
|
||||
|
||||
AddHtmlButton(
|
||||
b.X + bw,
|
||||
b.Y + (b.Height - (bh * 2)),
|
||||
bw,
|
||||
bh,
|
||||
o => OnTransactionTransfer(trans),
|
||||
"[TRANSFER]",
|
||||
Color.Gold,
|
||||
Color.Black,
|
||||
Color.Gold,
|
||||
2);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void GetTransactionOverview(
|
||||
DonationTransaction trans,
|
||||
StringBuilder info,
|
||||
bool details,
|
||||
bool exchange,
|
||||
bool status)
|
||||
{
|
||||
if (details)
|
||||
{
|
||||
info.AppendLine();
|
||||
info.AppendLine("Details");
|
||||
info.AppendLine();
|
||||
info.AppendLine("ID: {0}", trans.ID);
|
||||
info.AppendLine("Date: {0}", trans.Time.Value);
|
||||
|
||||
if (_Admin)
|
||||
{
|
||||
info.AppendLine();
|
||||
info.AppendLine("Notes: {0}", trans.Notes);
|
||||
info.AppendLine();
|
||||
info.AppendLine("Extra: {0}", trans.Extra);
|
||||
}
|
||||
}
|
||||
|
||||
if (exchange)
|
||||
{
|
||||
info.AppendLine();
|
||||
info.AppendLine("Exchange");
|
||||
info.AppendLine();
|
||||
info.AppendLine(
|
||||
"Value: {0}{1:#,0.00} {2}",
|
||||
AutoDonate.CMOptions.MoneySymbol,
|
||||
trans.Total,
|
||||
AutoDonate.CMOptions.MoneyAbbr);
|
||||
|
||||
var total = trans.GetCredit(Profile, out var credit, out var bonus);
|
||||
|
||||
info.AppendLine("Credit: {0:#,0} {1}", credit, AutoDonate.CMOptions.CurrencyName);
|
||||
info.AppendLine("Bonus: {0:#,0} {1}", bonus, AutoDonate.CMOptions.CurrencyName);
|
||||
info.AppendLine("Total: {0:#,0} {1}", total, AutoDonate.CMOptions.CurrencyName);
|
||||
}
|
||||
|
||||
if (status)
|
||||
{
|
||||
info.AppendLine();
|
||||
info.AppendLine("Status");
|
||||
info.AppendLine();
|
||||
info.AppendLine("State: {0}", trans.State);
|
||||
|
||||
switch (trans.State)
|
||||
{
|
||||
case TransactionState.Voided:
|
||||
info.AppendLine("Transaction has been voided.");
|
||||
break;
|
||||
case TransactionState.Pending:
|
||||
info.AppendLine("Transaction is pending verification.");
|
||||
break;
|
||||
case TransactionState.Processed:
|
||||
info.AppendLine("Transaction is complete and can be claimed.");
|
||||
break;
|
||||
case TransactionState.Claimed:
|
||||
{
|
||||
info.AppendLine("Transaction has been delivered.");
|
||||
info.AppendLine();
|
||||
info.AppendLine("Date: {0}", trans.DeliveryTime.Value);
|
||||
|
||||
if (trans.DeliveredTo != null)
|
||||
{
|
||||
info.AppendLine("Recipient: {0}", trans.DeliveredTo);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GetProfileOverview(StringBuilder info)
|
||||
{
|
||||
var ms = AutoDonate.CMOptions.MoneySymbol;
|
||||
var ma = AutoDonate.CMOptions.MoneyAbbr;
|
||||
var cn = AutoDonate.CMOptions.CurrencyName;
|
||||
|
||||
var val = _DonationTier.ToString("#,0").WrapUOHtmlColor(Color.LawnGreen, HtmlColor);
|
||||
info.AppendLine("Donation Tier: {0}", val);
|
||||
|
||||
val = _DonationValue.ToString("#,0.00").WrapUOHtmlColor(Color.LawnGreen, HtmlColor);
|
||||
info.AppendLine("Donations Total: {0}{1} {2}", ms, val, ma);
|
||||
|
||||
val = _DonationCredit.ToString("#,0").WrapUOHtmlColor(Color.LawnGreen, HtmlColor);
|
||||
info.AppendLine("Donations Claimed: {0} {1}", val, cn);
|
||||
}
|
||||
|
||||
protected virtual void OnTransactionEdit(DonationTransaction trans)
|
||||
{
|
||||
Refresh();
|
||||
|
||||
if (_Admin)
|
||||
{
|
||||
User.SendGump(new PropertiesGump(User, trans));
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnTransactionTransfer(DonationTransaction trans)
|
||||
{
|
||||
new InputDialogGump(User, Refresh())
|
||||
{
|
||||
Title = "Transfer Transaction",
|
||||
Html = "Enter the account name of the recipient for the transfer.",
|
||||
InputText = trans.Account != null ? trans.Account.Username : String.Empty,
|
||||
Callback = (b, a) =>
|
||||
{
|
||||
if (User.AccessLevel >= AutoDonate.Access)
|
||||
{
|
||||
var acc = Accounts.GetAccount(a);
|
||||
|
||||
if (acc == null)
|
||||
{
|
||||
User.SendMessage(34, "The account '{0}' does not exist.", a);
|
||||
}
|
||||
else if (trans.Account == acc)
|
||||
{
|
||||
User.SendMessage(34, "The transaction is already bound to '{0}'", a);
|
||||
}
|
||||
else
|
||||
{
|
||||
trans.SetAccount(acc);
|
||||
User.SendMessage(85, "The transaction has been transferred to '{0}'", a);
|
||||
}
|
||||
}
|
||||
|
||||
Refresh(true);
|
||||
}
|
||||
}.Send();
|
||||
}
|
||||
|
||||
protected virtual void OnVoidedTransaction(DonationTransaction trans)
|
||||
{
|
||||
var html = new StringBuilder();
|
||||
|
||||
GetTransactionOverview(trans, html, false, false, true);
|
||||
|
||||
new NoticeDialogGump(User, Refresh())
|
||||
{
|
||||
Title = "Transaction Voided",
|
||||
Html = html.ToString()
|
||||
}.Send();
|
||||
}
|
||||
|
||||
protected virtual void OnPendingTransaction(DonationTransaction trans)
|
||||
{
|
||||
var html = new StringBuilder();
|
||||
|
||||
GetTransactionOverview(trans, html, false, false, true);
|
||||
|
||||
new NoticeDialogGump(User, Refresh())
|
||||
{
|
||||
Title = "Transaction Pending",
|
||||
Html = html.ToString()
|
||||
}.Send();
|
||||
}
|
||||
|
||||
protected virtual void OnClaimTransaction(DonationTransaction trans)
|
||||
{
|
||||
var html = new StringBuilder();
|
||||
|
||||
GetTransactionOverview(trans, html, false, true, false);
|
||||
|
||||
html.AppendLine();
|
||||
html.AppendLine("Click OK to claim this transaction!");
|
||||
|
||||
new ConfirmDialogGump(User, Refresh())
|
||||
{
|
||||
Title = "Reward Claim",
|
||||
Html = html.ToString(),
|
||||
AcceptHandler = b =>
|
||||
{
|
||||
if (trans.Claim(User))
|
||||
{
|
||||
SelectedNode = "Transactions|" + trans.FullPath;
|
||||
|
||||
User.SendMessage(85, "You claimed the transaction!");
|
||||
}
|
||||
|
||||
Refresh(true);
|
||||
}
|
||||
}.Send();
|
||||
}
|
||||
|
||||
protected virtual void OnClaimedTransaction(DonationTransaction trans)
|
||||
{
|
||||
var info = new StringBuilder();
|
||||
|
||||
GetTransactionOverview(trans, info, false, false, true);
|
||||
|
||||
new NoticeDialogGump(User, Refresh())
|
||||
{
|
||||
Title = "Reward Delivered",
|
||||
Html = info.ToString()
|
||||
}.Send();
|
||||
}
|
||||
|
||||
protected override void OnDisposed()
|
||||
{
|
||||
_Indicies = null;
|
||||
|
||||
ObjectPool.Free(ref _Transactions);
|
||||
|
||||
base.OnDisposed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Misc;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Modules.AutoDonate
|
||||
{
|
||||
public static class DonationEvents
|
||||
{
|
||||
#region TransPending
|
||||
public delegate void TransPending(TransPendingEventArgs e);
|
||||
|
||||
public static event TransPending OnTransPending;
|
||||
|
||||
public static void InvokeTransPending(DonationTransaction trans)
|
||||
{
|
||||
if (OnTransPending != null)
|
||||
{
|
||||
OnTransPending(new TransPendingEventArgs(trans));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TransPendingEventArgs : EventArgs
|
||||
{
|
||||
public DonationTransaction Transaction { get; private set; }
|
||||
|
||||
public TransPendingEventArgs(DonationTransaction trans)
|
||||
{
|
||||
Transaction = trans;
|
||||
}
|
||||
}
|
||||
#endregion TransPending
|
||||
|
||||
#region TransVoided
|
||||
public delegate void TransVoided(TransVoidedEventArgs e);
|
||||
|
||||
public static event TransVoided OnTransVoided;
|
||||
|
||||
public static void InvokeTransVoided(DonationTransaction trans)
|
||||
{
|
||||
if (OnTransVoided != null)
|
||||
{
|
||||
OnTransVoided(new TransVoidedEventArgs(trans));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TransVoidedEventArgs : EventArgs
|
||||
{
|
||||
public DonationTransaction Transaction { get; private set; }
|
||||
|
||||
public TransVoidedEventArgs(DonationTransaction trans)
|
||||
{
|
||||
Transaction = trans;
|
||||
}
|
||||
}
|
||||
#endregion TransVoided
|
||||
|
||||
#region TransClaimed
|
||||
public delegate void TransClaimed(TransClaimedEventArgs e);
|
||||
|
||||
public static event TransClaimed OnTransClaimed;
|
||||
|
||||
public static void InvokeTransClaimed(DonationTransaction trans, Mobile deliverTo)
|
||||
{
|
||||
if (OnTransClaimed != null)
|
||||
{
|
||||
OnTransClaimed(new TransClaimedEventArgs(trans, deliverTo));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TransClaimedEventArgs : EventArgs
|
||||
{
|
||||
public DonationTransaction Transaction { get; private set; }
|
||||
|
||||
public Mobile DeliverTo { get; set; }
|
||||
|
||||
public TransClaimedEventArgs(DonationTransaction trans, Mobile deliverTo)
|
||||
{
|
||||
Transaction = trans;
|
||||
DeliverTo = deliverTo;
|
||||
}
|
||||
}
|
||||
#endregion TransClaimed
|
||||
|
||||
#region TransProcessed
|
||||
public delegate void TransProcessed(TransProcessedEventArgs e);
|
||||
|
||||
public static event TransProcessed OnTransProcessed;
|
||||
|
||||
public static void InvokeTransProcessed(DonationTransaction trans)
|
||||
{
|
||||
if (OnTransProcessed != null)
|
||||
{
|
||||
OnTransProcessed(new TransProcessedEventArgs(trans));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TransProcessedEventArgs : EventArgs
|
||||
{
|
||||
public DonationTransaction Transaction { get; private set; }
|
||||
|
||||
public TransProcessedEventArgs(DonationTransaction trans)
|
||||
{
|
||||
Transaction = trans;
|
||||
}
|
||||
}
|
||||
#endregion TransProcessed
|
||||
|
||||
#region StateChanged
|
||||
public delegate void StateChanged(StateChangedEventArgs e);
|
||||
|
||||
public static event StateChanged OnStateChanged;
|
||||
|
||||
public static void InvokeStateChanged(DonationTransaction trans, TransactionState oldState)
|
||||
{
|
||||
if (OnStateChanged != null)
|
||||
{
|
||||
OnStateChanged(new StateChangedEventArgs(trans, oldState));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class StateChangedEventArgs : EventArgs
|
||||
{
|
||||
public DonationTransaction Transaction { get; private set; }
|
||||
public TransactionState OldState { get; private set; }
|
||||
|
||||
public StateChangedEventArgs(DonationTransaction trans, TransactionState oldState)
|
||||
{
|
||||
Transaction = trans;
|
||||
OldState = oldState;
|
||||
}
|
||||
}
|
||||
#endregion StateChanged
|
||||
|
||||
#region TransactionExchange
|
||||
public delegate void TransExchanger(TransExchangeEventArgs e);
|
||||
|
||||
public static event TransExchanger OnTransExchange;
|
||||
|
||||
public static long InvokeTransExchange(DonationTransaction trans, DonationProfile dp)
|
||||
{
|
||||
var e = new TransExchangeEventArgs(trans, dp);
|
||||
|
||||
if (OnTransExchange != null)
|
||||
{
|
||||
OnTransExchange(e);
|
||||
}
|
||||
|
||||
return e.Exchanged;
|
||||
}
|
||||
|
||||
public sealed class TransExchangeEventArgs : EventArgs
|
||||
{
|
||||
public DonationTransaction Transaction { get; private set; }
|
||||
public DonationProfile Profile { get; private set; }
|
||||
|
||||
public long Exchanged { get; set; }
|
||||
|
||||
public ulong Flags { get; set; }
|
||||
|
||||
public TransExchangeEventArgs(DonationTransaction trans, DonationProfile dp)
|
||||
{
|
||||
Transaction = trans;
|
||||
Profile = dp;
|
||||
|
||||
Exchanged = Transaction.Credit;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TransactionPack
|
||||
public delegate void TransPacker(TransPackEventArgs e);
|
||||
|
||||
public static event TransPacker OnTransPack;
|
||||
|
||||
public static Container InvokeTransPack(DonationTransaction trans, DonationProfile dp)
|
||||
{
|
||||
var cont = new Bag
|
||||
{
|
||||
Name = ServerList.ServerName + " Donation Rewards",
|
||||
Hue = 1152
|
||||
};
|
||||
|
||||
var e = new TransPackEventArgs(trans, dp, cont);
|
||||
|
||||
OnTransPack?.Invoke(e);
|
||||
|
||||
return e.Container;
|
||||
}
|
||||
|
||||
public sealed class TransPackEventArgs : EventArgs
|
||||
{
|
||||
public DonationTransaction Transaction { get; private set; }
|
||||
public DonationProfile Profile { get; private set; }
|
||||
|
||||
public Container Container { get; set; }
|
||||
|
||||
public ulong Flags { get; set; }
|
||||
|
||||
public TransPackEventArgs(DonationTransaction trans, DonationProfile dp, Container cont)
|
||||
{
|
||||
Transaction = trans;
|
||||
Profile = dp;
|
||||
|
||||
Container = cont;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TransactionDeleted
|
||||
public delegate void TransactionDeleted(TransactionDeletedEventArgs e);
|
||||
|
||||
public static event TransactionDeleted OnTransactionDeleted;
|
||||
|
||||
public static void InvokeTransactionDeleted(DonationTransaction trans)
|
||||
{
|
||||
if (OnTransactionDeleted != null)
|
||||
{
|
||||
OnTransactionDeleted(new TransactionDeletedEventArgs(trans));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TransactionDeletedEventArgs : EventArgs
|
||||
{
|
||||
public DonationTransaction Transaction { get; private set; }
|
||||
|
||||
public TransactionDeletedEventArgs(DonationTransaction trans)
|
||||
{
|
||||
Transaction = trans;
|
||||
}
|
||||
}
|
||||
#endregion StateChanged
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user