diff --git a/.gitattributes b/.gitattributes
index bdb0cab..1ff0c42 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,17 +1,63 @@
-# Auto detect text files and perform LF normalization
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
* text=auto
-# Custom for Visual Studio
-*.cs diff=csharp
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
-# Standard to msysgit
-*.doc diff=astextplain
-*.DOC diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot diff=astextplain
-*.DOT diff=astextplain
-*.pdf diff=astextplain
-*.PDF diff=astextplain
-*.rtf diff=astextplain
-*.RTF diff=astextplain
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.github/workflows/rocket-plugin-release.yml b/.github/workflows/rocket-plugin-release.yml
new file mode 100644
index 0000000..fa35591
--- /dev/null
+++ b/.github/workflows/rocket-plugin-release.yml
@@ -0,0 +1,11 @@
+name: Build & Create GitHub Release
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - master
+
+jobs:
+ call-rocket-plugin-release:
+ uses: RestoreMonarchyPlugins/github-actions/.github/workflows/rocket-plugin-release.yml@master
diff --git a/.gitignore b/.gitignore
index 7964536..9491a2f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,45 +1,85 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
+*.rsuser
*.suo
*.user
+*.userosscache
*.sln.docstates
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
+[Rr]eleases/
x64/
-build/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
+[Oo]ut/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
-# Roslyn cache directories
-*.ide/
+# Visual Studio 2017 auto generated files
+Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
-#NUNIT
+# NUnit
*.VisualState.xml
TestResult.xml
+nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
*_i.c
*_p.c
-*_i.h
+*_h.h
*.ilk
*.meta
*.obj
+*.iobj
*.pch
*.pdb
+*.ipdb
*.pgc
*.pgd
*.rsp
@@ -49,6 +89,7 @@ dlldata.c
*.tlh
*.tmp
*.tmp_proj
+*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
@@ -64,14 +105,21 @@ _Chutzpah*
ipch/
*.aps
*.ncb
+*.opendb
*.opensdf
*.sdf
*.cachefile
+*.VC.db
+*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
# TFS 2012 Local Workspace
$tf/
@@ -84,18 +132,29 @@ _ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
-# JustCode is a .NET coding addin-in
-.JustCode
-
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
# NCrunch
_NCrunch_*
.*crunch*.local.xml
+nCrunchTemp_*
# MightyMoose
*.mm.*
@@ -123,42 +182,71 @@ publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
-## TODO: Comment the next line if you want to checkin your
-## web deploy settings but do note that will include unencrypted
-## passwords
-#*.pubxml
-
-# NuGet Packages Directory
-packages/*
-## TODO: If the tool you use requires repositories.config
-## uncomment the next line
-#!packages/repositories.config
-
-# Enable "build/" folder in the NuGet Packages folder since
-# NuGet packages use it for MSBuild targets.
-# This line needs to be after the ignore of the build folder
-# (and the packages folder if the line above has been uncommented)
-!packages/build/
-
-# Windows Azure Build Output
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
csx/
*.build.csdef
-# Windows Store app package directory
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
# Others
-sql/
-*.Cache
ClientBin/
-[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
+*.jfm
*.pfx
*.publishsettings
-node_modules/
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
# RIA/Silverlight projects
Generated_Code/
@@ -170,20 +258,106 @@ _UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
+*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
-# LightSwitch generated files
-GeneratedArtifacts/
-_Pvt_Extensions/
-ModelManifest.xml
\ No newline at end of file
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
\ No newline at end of file
diff --git a/Libraries/I18N.West.dll b/Libraries/I18N.West.dll
deleted file mode 100644
index bf7a5d6..0000000
Binary files a/Libraries/I18N.West.dll and /dev/null differ
diff --git a/Libraries/I18N.dll b/Libraries/I18N.dll
deleted file mode 100644
index 21afd5d..0000000
Binary files a/Libraries/I18N.dll and /dev/null differ
diff --git a/Libraries/MySql.Data.dll b/Libraries/MySql.Data.dll
deleted file mode 100644
index 03fd84a..0000000
Binary files a/Libraries/MySql.Data.dll and /dev/null differ
diff --git a/Libraries/System.Data.dll b/Libraries/System.Data.dll
deleted file mode 100644
index f051b61..0000000
Binary files a/Libraries/System.Data.dll and /dev/null differ
diff --git a/Libraries/System.Management.dll b/Libraries/System.Management.dll
deleted file mode 100644
index 0c04a72..0000000
Binary files a/Libraries/System.Management.dll and /dev/null differ
diff --git a/Libraries/System.Transactions.dll b/Libraries/System.Transactions.dll
deleted file mode 100644
index 0191347..0000000
Binary files a/Libraries/System.Transactions.dll and /dev/null differ
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100644
index 07cbb8f..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("Uconomy")]
-[assembly: AssemblyCompany("unturned.ROCKS")]
-[assembly: AssemblyProduct("Rocket")]
-[assembly: ComVisible(false)]
-[assembly: Guid("34ca52ac-333c-45df-8a77-8c8f7c463faa")]
-[assembly: AssemblyVersion("1.0.4.0")]
diff --git a/Uconomy.csproj b/Uconomy.csproj
deleted file mode 100644
index 5bb9d7c..0000000
--- a/Uconomy.csproj
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {602882B6-F16C-4247-9F5D-21846BC4C09A}
- Library
- Properties
- fr34kyn01535.Uconomy
- Uconomy
- v3.5
- 512
- 12.0.0
- 2.0
-
-
-
- True
- full
- False
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- false
- false
-
-
- none
- True
- bin\Release\
- TRACE
- prompt
- 4
- false
-
-
- ..\..\..\..\Desktop\Unturned\Unturned_Data\Managed\mods\
- false
-
-
-
- False
- lib\Assembly-CSharp.dll
- False
-
-
- False
- lib\Assembly-CSharp-firstpass.dll
- False
-
-
- False
- Libraries\I18N.dll
- False
-
-
- False
- Libraries\I18N.West.dll
- False
-
-
- False
- Libraries\MySql.Data.dll
- False
-
-
- False
- lib\Rocket.API.dll
- False
-
-
- lib\Rocket.Core.dll
- False
-
-
- False
- lib\Rocket.Unturned.dll
- False
-
-
-
-
-
-
-
-
-
- False
- lib\UnityEngine.dll
- False
-
-
-
-
-
-
-
-
-
-
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
- Always
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Uconomy.sln b/Uconomy.sln
index 076c947..77bd2a9 100644
--- a/Uconomy.sln
+++ b/Uconomy.sln
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Uconomy", "Uconomy.csproj", "{602882B6-F16C-4247-9F5D-21846BC4C09A}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Uconomy", "Uconomy/Uconomy.csproj", "{602882B6-F16C-4247-9F5D-21846BC4C09A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/CommandBalance.cs b/Uconomy/Commands/CommandBalance.cs
similarity index 64%
rename from CommandBalance.cs
rename to Uconomy/Commands/CommandBalance.cs
index 745ef82..f58f3a7 100644
--- a/CommandBalance.cs
+++ b/Uconomy/Commands/CommandBalance.cs
@@ -1,11 +1,12 @@
-using Rocket.API;
+using fr34kyn01535.Uconomy.Helpers;
+using Rocket.API;
using Rocket.Core.Logging;
using Rocket.Unturned.Chat;
using Rocket.Unturned.Player;
using System;
using System.Collections.Generic;
-namespace fr34kyn01535.Uconomy
+namespace fr34kyn01535.Uconomy.Commands
{
public class CommandBalance : IRocketCommand
{
@@ -47,8 +48,15 @@ public List Permissions
public void Execute(IRocketPlayer caller, params string[] command)
{
- decimal balance = Uconomy.Instance.Database.GetBalance(caller.Id);
- UnturnedChat.Say(caller, Uconomy.Instance.Translations.Instance.Translate("command_balance_show", balance, Uconomy.Instance.Configuration.Instance.MoneyName));
+ ThreadHelper.RunAsynchronously(() =>
+ {
+ decimal balance = Uconomy.Instance.Database.GetBalance(caller.Id);
+ ThreadHelper.RunSynchronously(() =>
+ {
+ UnturnedChat.Say(caller, Uconomy.Instance.Translations.Instance.Translate("command_balance_show", balance, Uconomy.Instance.Configuration.Instance.MoneyName));
+ });
+ });
+
}
}
}
diff --git a/CommandPay.cs b/Uconomy/Commands/CommandPay.cs
similarity index 50%
rename from CommandPay.cs
rename to Uconomy/Commands/CommandPay.cs
index 85b7e03..50102dc 100644
--- a/CommandPay.cs
+++ b/Uconomy/Commands/CommandPay.cs
@@ -1,11 +1,10 @@
-using Rocket.API;
-using Rocket.Core.Logging;
+using fr34kyn01535.Uconomy.Helpers;
+using Rocket.API;
using Rocket.Unturned.Chat;
using Rocket.Unturned.Player;
-using System;
using System.Collections.Generic;
-namespace fr34kyn01535.Uconomy
+namespace fr34kyn01535.Uconomy.Commands
{
public class CommandPay : IRocketCommand
{
@@ -54,7 +53,7 @@ public void Execute(IRocketPlayer caller, params string[] command)
}
UnturnedPlayer otherPlayer = UnturnedPlayer.FromName(command[0]);
- if (otherPlayer !=null)
+ if (otherPlayer != null)
{
if (caller == otherPlayer)
{
@@ -63,36 +62,47 @@ public void Execute(IRocketPlayer caller, params string[] command)
}
decimal amount = 0;
- if (!Decimal.TryParse(command[1], out amount) || amount <= 0)
+ if (!decimal.TryParse(command[1], out amount) || amount <= 0)
{
UnturnedChat.Say(caller, Uconomy.Instance.Translations.Instance.Translate("command_pay_error_invalid_amount"));
return;
}
- if (caller is ConsolePlayer)
+ ThreadHelper.RunAsynchronously(() =>
{
- Uconomy.Instance.Database.IncreaseBalance(otherPlayer.Id, amount);
- UnturnedChat.Say(otherPlayer.CSteamID, Uconomy.Instance.Translations.Instance.Translate("command_pay_console", amount, Uconomy.Instance.Configuration.Instance.MoneyName));
- }
- else
- {
-
- decimal myBalance = Uconomy.Instance.Database.GetBalance(caller.Id);
- if ((myBalance - amount) <= 0)
+ if (caller is ConsolePlayer)
{
- UnturnedChat.Say(caller, Uconomy.Instance.Translations.Instance.Translate("command_pay_error_cant_afford"));
- return;
+ Uconomy.Instance.Database.IncreaseBalance(otherPlayer.Id, amount);
+ ThreadHelper.RunSynchronously(() =>
+ {
+ UnturnedChat.Say(otherPlayer.CSteamID, Uconomy.Instance.Translations.Instance.Translate("command_pay_console", amount, Uconomy.Instance.Configuration.Instance.MoneyName));
+ });
}
else
{
- Uconomy.Instance.Database.IncreaseBalance(caller.Id, -amount);
- UnturnedChat.Say(caller, Uconomy.Instance.Translations.Instance.Translate("command_pay_private", otherPlayer.CharacterName, amount, Uconomy.Instance.Configuration.Instance.MoneyName));
- Uconomy.Instance.Database.IncreaseBalance(otherPlayer.Id, amount);
- UnturnedChat.Say(otherPlayer.CSteamID, Uconomy.Instance.Translations.Instance.Translate("command_pay_other_private", amount, Uconomy.Instance.Configuration.Instance.MoneyName, caller.DisplayName));
- Uconomy.Instance.HasBeenPayed((UnturnedPlayer)caller, otherPlayer, amount);
- }
- }
+ decimal myBalance = Uconomy.Instance.Database.GetBalance(caller.Id);
+ if (myBalance - amount <= 0)
+ {
+ ThreadHelper.RunSynchronously(() =>
+ {
+ UnturnedChat.Say(caller, Uconomy.Instance.Translations.Instance.Translate("command_pay_error_cant_afford"));
+ });
+ return;
+ }
+ else
+ {
+ Uconomy.Instance.Database.IncreaseBalance(caller.Id, -amount);
+ Uconomy.Instance.Database.IncreaseBalance(otherPlayer.Id, amount);
+ ThreadHelper.RunSynchronously(() =>
+ {
+ UnturnedChat.Say(caller, Uconomy.Instance.Translations.Instance.Translate("command_pay_private", otherPlayer.CharacterName, amount, Uconomy.Instance.Configuration.Instance.MoneyName));
+ UnturnedChat.Say(otherPlayer.CSteamID, Uconomy.Instance.Translations.Instance.Translate("command_pay_other_private", amount, Uconomy.Instance.Configuration.Instance.MoneyName, caller.DisplayName));
+ Uconomy.Instance.HasBeenPayed((UnturnedPlayer)caller, otherPlayer, amount);
+ });
+ }
+ }
+ });
}
else
{
diff --git a/Database.cs b/Uconomy/Database.cs
similarity index 70%
rename from Database.cs
rename to Uconomy/Database.cs
index 4f2f846..a129fb5 100644
--- a/Database.cs
+++ b/Uconomy/Database.cs
@@ -1,6 +1,10 @@
-using MySql.Data.MySqlClient;
+using fr34kyn01535.Uconomy.Helpers;
+using fr34kyn01535.Uconomy.Models;
+using MySql.Data.MySqlClient;
using Rocket.Core.Logging;
using System;
+using System.Collections.Generic;
+using System.Linq;
namespace fr34kyn01535.Uconomy
{
@@ -8,7 +12,6 @@ public class DatabaseManager
{
internal DatabaseManager()
{
- new I18N.West.CP1250(); //Workaround for database encoding issues with mono
CheckSchema();
}
@@ -71,7 +74,10 @@ public decimal IncreaseBalance(string id, decimal increaseBy)
object result = command.ExecuteScalar();
if (result != null) Decimal.TryParse(result.ToString(), out output);
connection.Close();
- Uconomy.Instance.BalanceUpdated(id, increaseBy);
+ ThreadHelper.RunSynchronously(() =>
+ {
+ Uconomy.Instance.BalanceUpdated(id, increaseBy);
+ });
}
catch (Exception ex)
{
@@ -106,7 +112,54 @@ public void CheckSetupAccount(Steamworks.CSteamID id)
{
Logger.LogException(ex);
}
+ }
+
+ public List GetBalances(List ids)
+ {
+ List balances = new List();
+ try
+ {
+ using (MySqlConnection connection = createConnection())
+ {
+ string placeholders = string.Join(",", ids.Select(id => "?id" + id));
+ string query = $"SELECT `steamId`, `balance` FROM `{Uconomy.Instance.Configuration.Instance.DatabaseTableName}` WHERE `steamId` IN ({placeholders})";
+
+ MySqlCommand command = new MySqlCommand(query, connection);
+
+ for (int i = 0; i < ids.Count; i++)
+ {
+ command.Parameters.AddWithValue("?id" + ids[i], ids[i]);
+ }
+
+ connection.Open();
+ using (MySqlDataReader reader = command.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ balances.Add(new PlayerBalance
+ {
+ SteamId = reader.GetString("steamId"),
+ Balance = reader.GetDecimal("balance")
+ });
+ }
+ }
+ }
+
+ ThreadHelper.RunSynchronously(() =>
+ {
+ // Trigger the event for each balance checked
+ foreach (var balance in balances)
+ {
+ Uconomy.Instance.OnBalanceChecked(balance.SteamId, balance.Balance);
+ }
+ });
+ }
+ catch (Exception ex)
+ {
+ Logger.LogException(ex);
+ }
+ return balances;
}
internal void CheckSchema()
@@ -121,7 +174,7 @@ internal void CheckSchema()
if (test == null)
{
- command.CommandText = "CREATE TABLE `" + Uconomy.Instance.Configuration.Instance.DatabaseTableName + "` (`steamId` varchar(32) NOT NULL,`balance` decimal(15,2) NOT NULL DEFAULT '25.00',`lastUpdated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`steamId`)) ";
+ command.CommandText = "CREATE TABLE `" + Uconomy.Instance.Configuration.Instance.DatabaseTableName + "` (`steamId` varchar(32) NOT NULL,`balance` decimal(15,2) NOT NULL DEFAULT '25.00',`lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`steamId`)) ";
command.ExecuteNonQuery();
}
connection.Close();
diff --git a/Uconomy/Helpers/ThreadHelper.cs b/Uconomy/Helpers/ThreadHelper.cs
new file mode 100644
index 0000000..f762aac
--- /dev/null
+++ b/Uconomy/Helpers/ThreadHelper.cs
@@ -0,0 +1,43 @@
+using Rocket.Core.Logging;
+using Rocket.Core.Utils;
+using SDG.Unturned;
+using System;
+using System.Threading;
+
+namespace fr34kyn01535.Uconomy.Helpers
+{
+ internal static class ThreadHelper
+ {
+ internal static void RunAsynchronously(System.Action action, string exceptionMessage = null)
+ {
+ if (Thread.CurrentThread != ThreadUtil.gameThread)
+ {
+ action.Invoke();
+ return;
+ }
+
+ ThreadPool.QueueUserWorkItem((_) =>
+ {
+ try
+ {
+ action.Invoke();
+ }
+ catch (Exception e)
+ {
+ RunSynchronously(() => Logger.LogException(e, exceptionMessage));
+ }
+ });
+ }
+
+ internal static void RunSynchronously(System.Action action, float delaySeconds = 0)
+ {
+ if (Thread.CurrentThread == ThreadUtil.gameThread)
+ {
+ action.Invoke();
+ return;
+ }
+
+ TaskDispatcher.QueueOnMainThread(action, delaySeconds);
+ }
+ }
+}
diff --git a/Uconomy/Models/PlayerBalance.cs b/Uconomy/Models/PlayerBalance.cs
new file mode 100644
index 0000000..1ced609
--- /dev/null
+++ b/Uconomy/Models/PlayerBalance.cs
@@ -0,0 +1,8 @@
+namespace fr34kyn01535.Uconomy.Models
+{
+ public class PlayerBalance
+ {
+ public string SteamId { get; set; }
+ public decimal Balance { get; set; }
+ }
+}
diff --git a/Uconomy/Services/ExperienceService.cs b/Uconomy/Services/ExperienceService.cs
new file mode 100644
index 0000000..80d9bd0
--- /dev/null
+++ b/Uconomy/Services/ExperienceService.cs
@@ -0,0 +1,134 @@
+using fr34kyn01535.Uconomy.Helpers;
+using fr34kyn01535.Uconomy.Models;
+using Rocket.Unturned;
+using Rocket.Unturned.Player;
+using SDG.Unturned;
+using Steamworks;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using Logger = Rocket.Core.Logging.Logger;
+
+namespace fr34kyn01535.Uconomy.Services
+{
+ public class ExperienceService : MonoBehaviour
+ {
+ private Uconomy pluginInstance => Uconomy.Instance;
+ private UconomyConfiguration configuration => pluginInstance.Configuration.Instance;
+
+ private Dictionary ignoreEvent = [];
+ public bool IsSynchronizing { get; private set; } = false;
+
+ void Start()
+ {
+ InvokeRepeating(nameof(SyncPlayersExperience), 0, configuration.SyncIntervalSeconds);
+ U.Events.OnPlayerConnected += OnPlayerConnected;
+ U.Events.OnPlayerDisconnected += OnPlayerDisconnected;
+ PlayerSkills.OnExperienceChanged_Global += OnExperienceChanged;
+ }
+
+ void OnDestroy()
+ {
+ U.Events.OnPlayerConnected -= OnPlayerConnected;
+ U.Events.OnPlayerDisconnected -= OnPlayerDisconnected;
+ PlayerSkills.OnExperienceChanged_Global -= OnExperienceChanged;
+ }
+
+ private void OnPlayerConnected(UnturnedPlayer player)
+ {
+ ignoreEvent[player.CSteamID] = true;
+ player.Experience = 0;
+
+ ThreadHelper.RunAsynchronously(() =>
+ {
+ decimal balance = Uconomy.Instance.Database.GetBalance(player.CSteamID.ToString());
+ ThreadHelper.RunSynchronously(() =>
+ {
+ ignoreEvent[player.CSteamID] = true;
+ player.Experience = (uint)balance;
+ });
+ });
+ }
+
+ private void OnPlayerDisconnected(UnturnedPlayer player)
+ {
+ ignoreEvent.Remove(player.CSteamID);
+ }
+
+ private void OnExperienceChanged(PlayerSkills skills, uint lastKnownExperience)
+ {
+ CSteamID steamID = skills.player.channel.owner.playerID.steamID;
+ uint experience = skills.experience;
+
+ if (!ignoreEvent.TryGetValue(steamID, out bool ignore) || ignore)
+ {
+ ignoreEvent[steamID] = false;
+ } else
+ {
+ int experienceDifference = (int)experience - (int)lastKnownExperience;
+
+ if (experienceDifference != 0)
+ {
+ decimal balanceChange = experienceDifference;
+ ThreadHelper.RunAsynchronously(() =>
+ {
+ Uconomy.Instance.Database.IncreaseBalance(steamID.ToString(), balanceChange);
+ });
+ }
+ }
+ }
+
+ private void SyncPlayersExperience()
+ {
+ if (IsSynchronizing)
+ {
+ pluginInstance.LogDebug("ExperienceService is already synchronizing.");
+ return;
+ }
+
+ SteamPlayer[] players = PlayerTool.getSteamPlayers();
+ if (players.Length == 0)
+ {
+ return;
+ }
+
+ IsSynchronizing = true;
+ List playerIds = players.Select(x => x.playerID.steamID.ToString()).ToList();
+
+ ThreadHelper.RunAsynchronously(() =>
+ {
+ List playerBalances = Uconomy.Instance.Database.GetBalances(playerIds);
+ pluginInstance.LogDebug($"Synchronizing {playerBalances.Count} player experiences.");
+
+ ThreadHelper.RunSynchronously(() =>
+ {
+ try
+ {
+ foreach (PlayerBalance playerBalance in playerBalances)
+ {
+ CSteamID steamID = new(Convert.ToUInt64(playerBalance.SteamId));
+ Player player = PlayerTool.getPlayer(steamID);
+
+ uint experienceBalance = (uint)playerBalance.Balance;
+ if (player.skills.experience == experienceBalance)
+ {
+ continue;
+ }
+
+ ignoreEvent[steamID] = true;
+ player.skills.ServerSetExperience(experienceBalance);
+ }
+
+ IsSynchronizing = false;
+ pluginInstance.LogDebug($"Synchronized {playerBalances.Count} player experiences.");
+ } catch (Exception e)
+ {
+ IsSynchronizing = false;
+ Logger.LogException(e);
+ }
+ });
+ });
+ }
+ }
+}
diff --git a/Uconomy.cs b/Uconomy/Uconomy.cs
similarity index 51%
rename from Uconomy.cs
rename to Uconomy/Uconomy.cs
index d3730aa..9def5ee 100644
--- a/Uconomy.cs
+++ b/Uconomy/Uconomy.cs
@@ -1,11 +1,10 @@
-using Rocket;
+using fr34kyn01535.Uconomy.Helpers;
+using fr34kyn01535.Uconomy.Services;
using Rocket.API.Collections;
+using Rocket.Core.Logging;
using Rocket.Core.Plugins;
using Rocket.Unturned;
-using Rocket.Unturned.Events;
using Rocket.Unturned.Player;
-using Rocket.Unturned.Plugins;
-using SDG;
using Steamworks;
using System;
@@ -15,12 +14,28 @@ public class Uconomy : RocketPlugin
{
public DatabaseManager Database;
public static Uconomy Instance;
+ public ExperienceService ExperienceService;
protected override void Load()
{
Instance = this;
Database = new DatabaseManager();
- U.Events.OnPlayerConnected+=Events_OnPlayerConnected;
+
+ if (Configuration.Instance.SyncExperience)
+ {
+ ExperienceService = gameObject.AddComponent();
+ }
+
+ U.Events.OnPlayerConnected += Events_OnPlayerConnected;
+
+ Logger.Log($"{Name} {Assembly.GetName().Version} has been loaded!", ConsoleColor.Yellow);
+ }
+
+ protected override void Unload()
+ {
+ U.Events.OnPlayerConnected -= Events_OnPlayerConnected;
+
+ Logger.Log($"{Name} has been unloaded!", ConsoleColor.Yellow);
}
public delegate void PlayerBalanceUpdate(UnturnedPlayer player, decimal amt);
@@ -34,16 +49,16 @@ public override TranslationList DefaultTranslations
{
get
{
- return new TranslationList(){
- {"command_balance_show","Your current balance is: {0} {1}"},
- {"command_pay_invalid","Invalid arguments"},
- {"command_pay_error_pay_self","You cant pay yourself"},
- {"command_pay_error_invalid_amount","Invalid amount"},
- {"command_pay_error_cant_afford","Your balance does not allow this payment"},
- {"command_pay_error_player_not_found","Failed to find player"},
- {"command_pay_private","You paid {0} {1} {2}"},
- {"command_pay_console","You received a payment of {0} {1} "},
- {"command_pay_other_private","You received a payment of {0} {1} from {2}"},
+ return new TranslationList() {
+ {"command_balance_show","Your current balance is: {0} {1}"},
+ {"command_pay_invalid","Invalid arguments"},
+ {"command_pay_error_pay_self","You cant pay yourself"},
+ {"command_pay_error_invalid_amount","Invalid amount"},
+ {"command_pay_error_cant_afford","Your balance does not allow this payment"},
+ {"command_pay_error_player_not_found","Failed to find player"},
+ {"command_pay_private","You paid {0} {1} {2}"},
+ {"command_pay_console","You received a payment of {0} {1} "},
+ {"command_pay_other_private","You received a payment of {0} {1} from {2}"},
};
}
}
@@ -72,10 +87,21 @@ internal void OnBalanceChecked(string SteamID, decimal balance)
}
}
+ internal void LogDebug(string message)
+ {
+ if (Configuration.Instance.Debug)
+ {
+ Logger.Log($"Debug >> {message}");
+ }
+ }
+
private void Events_OnPlayerConnected(UnturnedPlayer player)
{
- //setup account
- Database.CheckSetupAccount(player.CSteamID);
+ ThreadHelper.RunAsynchronously(() =>
+ {
+ //setup account
+ Database.CheckSetupAccount(player.CSteamID);
+ });
}
}
}
diff --git a/Uconomy/Uconomy.csproj b/Uconomy/Uconomy.csproj
new file mode 100644
index 0000000..4fd26f4
--- /dev/null
+++ b/Uconomy/Uconomy.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net48
+ latest
+ fr34kyn01535.Uconomy
+ Uconomy
+ 2.0.0
+ Uconomy
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UconomyConfiguration.cs b/Uconomy/UconomyConfiguration.cs
similarity index 74%
rename from UconomyConfiguration.cs
rename to Uconomy/UconomyConfiguration.cs
index 00e1e42..c453c42 100644
--- a/UconomyConfiguration.cs
+++ b/Uconomy/UconomyConfiguration.cs
@@ -1,13 +1,11 @@
using Rocket.API;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace fr34kyn01535.Uconomy
{
public class UconomyConfiguration : IRocketPluginConfiguration
{
+ public bool Debug;
+ public bool ShouldSerializeDebug() => Debug;
public string DatabaseAddress;
public string DatabaseUsername;
public string DatabasePassword;
@@ -17,9 +15,12 @@ public class UconomyConfiguration : IRocketPluginConfiguration
public decimal InitialBalance;
public string MoneyName;
+ public bool SyncExperience = false;
+ public float SyncIntervalSeconds = 5;
public void LoadDefaults()
{
+ Debug = false;
DatabaseAddress = "localhost";
DatabaseUsername = "unturned";
DatabasePassword = "password";
@@ -28,6 +29,8 @@ public void LoadDefaults()
DatabasePort = 3306;
InitialBalance = 30;
MoneyName = "Credits";
+ SyncExperience = false;
+ SyncIntervalSeconds = 5;
}
}
}
diff --git a/lib/Assembly-CSharp-firstpass.dll b/lib/Assembly-CSharp-firstpass.dll
deleted file mode 100644
index dcfc680..0000000
Binary files a/lib/Assembly-CSharp-firstpass.dll and /dev/null differ
diff --git a/lib/Assembly-CSharp.dll b/lib/Assembly-CSharp.dll
deleted file mode 100644
index 64cd121..0000000
Binary files a/lib/Assembly-CSharp.dll and /dev/null differ
diff --git a/lib/Rocket.API.dll b/lib/Rocket.API.dll
deleted file mode 100644
index 7099496..0000000
Binary files a/lib/Rocket.API.dll and /dev/null differ
diff --git a/lib/Rocket.Core.dll b/lib/Rocket.Core.dll
deleted file mode 100644
index b9a678a..0000000
Binary files a/lib/Rocket.Core.dll and /dev/null differ
diff --git a/lib/Rocket.Unturned.dll b/lib/Rocket.Unturned.dll
deleted file mode 100644
index e0ab221..0000000
Binary files a/lib/Rocket.Unturned.dll and /dev/null differ
diff --git a/lib/UnityEngine.dll b/lib/UnityEngine.dll
deleted file mode 100644
index f953314..0000000
Binary files a/lib/UnityEngine.dll and /dev/null differ