// TODO: dataファイルに時間を取り日付が変わったタイミングでカウント0 #region 更新履歴 // 1.2.0 // * コンフィグ変更 // * コンフィグ変更後に変更した値を読み込めない問題の修正 // #endregion using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Oxide.Core; using Oxide.Core.Configuration; using Oxide.Core.Plugins; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Oxide.Plugins { [Info("DeathPenalty", "babu77", "1.2.0")] [Description("Dead players will be deprived of their property.")] public class DeathPenalty : RustPlugin { [PluginReference] private Plugin Economics, ServerRewards;//, ZoneManeger; #region Variables const string pName = "[DeathPenalty]:"; const string perm_use = "deathpenalty.use"; const string perm_admin = "deathpenalty.admin"; private DynamicConfigFile DATA_PLAYER_LOST_CR;//コインとRPのロスト分集計用データファイル private Dictionary LOST_DATA; private Dictionary DATA_CONFIG; //List loadedTime; #endregion #region Classes private class PlayerDataCR { public double Coins { get; set; } public int RP { get; set; } } #endregion #region Configurations private bool Changed; // private double MinRateEconomics; private double MaxRateEconomics; private double MinRateRP; private double MaxRateRP; private string ReceiverSteamID; private bool ReceiverFlag; private bool UseEconomics; private bool UseServerRewards; private void LoadVariables() { MinRateEconomics = Convert.ToDouble(GetConfig("Config", "Min_Rate_Economics(0.00 - 1.00)", 0.01)); MaxRateEconomics = Convert.ToDouble(GetConfig("Config", "Max_Rate_Economics(0.00 - 1.00)", 0.1)); MinRateRP = Convert.ToDouble(GetConfig("Config", "Min_Rate_RP(0.00 - 1.00)", 0.01)); MaxRateRP = Convert.ToDouble(GetConfig("Config", "Max_Rate_RP(0.00 - 1.00)", 0.1)); ReceiverFlag = Convert.ToBoolean(GetConfig("Config", "Receiver", false)); ReceiverSteamID = Convert.ToString(GetConfig("Config", "Receiver_Player_steamID", "0")); UseEconomics = Convert.ToBoolean(GetConfig("Config", "Use_Economics", false)); UseServerRewards = Convert.ToBoolean(GetConfig("Config", "Use_ServerRewards", false)); } private object GetConfig(string menu, string dataValue, object defaultValue) { Dictionary data = Config[menu] as Dictionary; if (data == null) { data = new Dictionary(); Config[menu] = data; Changed = true; } object value; if (!data.TryGetValue(dataValue, out value)) { value = defaultValue; data[dataValue] = value; Changed = true; } return value; } private void DPLoadConfig() { DATA_CONFIG = Config["Config"] as Dictionary; LoadVariables(); } #endregion #region OxideHook private void Init() { lang.RegisterMessages(new Dictionary { {"NoPerm", "You don't have a permission."}, {"NoEconomics", "Can't find Economics Plugin."}, {"InternalError", "A serious error has occurred in the plugin. Please report this to the administrator." }, {"NotRun", "Plugin is not running." }, {"PlayerLostCoins", "You have lost {reduce} of your Economics balance."}, {"PlayerLostRP", "You have lost {reduce} RP."}, {"CheckBalance", "The balance you've lost so far.\n Economics: {amountEconomics}\n RP: {amountRP}" } }, this); } protected override void LoadDefaultConfig() { Config.Clear(); LoadVariables(); } private void Loaded() { permission.RegisterPermission(perm_admin, this); permission.RegisterPermission(perm_use, this); //コインとRPロスト分 DATA_PLAYER_LOST_CR = GetFile(nameof(DeathPenalty)); LOST_DATA = DATA_PLAYER_LOST_CR.ReadObject>(); DPLoadConfig(); //Puts($"{MinRateEconomics}, {MaxRateEconomics}, {MinRateRP}, {MaxRateRP}, {ReceiverFlag}, {ReceiverSteamID}, {UseEconomics}. {UseServerRewards}"); } private object OnPlayerDeath(BasePlayer player, HitInfo info) { if(!permission.UserHasPermission(player.UserIDString, perm_use)) { return null; } /** 追記 ここから **/ //BasePlayer attacker = player.lastAttacker?.ToPlayer(); /** 追記 ここまで **/ ChangeEconomicsOrRp(player); return null; } private void OnServerSave() { SaveLostData(); } private void OnServerShutdown() => OnServerSave(); private void Unload() => OnServerSave(); private void SaveLostData() { if (LOST_DATA == null) return; DATA_PLAYER_LOST_CR.WriteObject(LOST_DATA); } private void OnNewSave() { DATA_PLAYER_LOST_CR.Clear(); } #endregion #region Functions private DynamicConfigFile GetFile(string name) { var file = Interface.Oxide.DataFileSystem.GetFile(name); file.Settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; file.Settings.Converters = new JsonConverter[] { new UnityVector3Converter(), new CustomComparerDictionaryCreationConverter(StringComparer.OrdinalIgnoreCase) }; return file; } /// /// コインとRPの変更(メイン) /// /// プレイヤー private void ChangeEconomicsOrRp(BasePlayer player) { bool checker = true; bool _bool; //Puts($"Economics: {UseEconomics}, Server Rewards: {UseServerRewards}"); if (UseEconomics && UseServerRewards) { if (Economics != null && ServerRewards != null)//正常系 { SqueezeSelector(player); } else { SendMessage(player, lang.GetMessage("InternalError", this)); Puts("Can not find Economics and ServerRewards."); } } else if(UseEconomics && !UseServerRewards) { if (Economics != null)//ServerRewardsなし { _bool = ChangeEconomics(player); } else { SendMessage(player, lang.GetMessage("InternalError", this)); Puts("Can not find Economics."); } } else if (!UseEconomics && UseServerRewards) { Puts("OK"); if (ServerRewards != null) //Economicsなし { _bool = ChangeRp(player); } else { SendMessage(player, lang.GetMessage("InternalError", this)); Puts("Can not find ServerRewards."); } } else { Puts("DeathPenalty is not active."); } return; //if (Economics == null && ServerRewards == null)//全部だめ //{ // SendMessage(player, lang.GetMessage("InternalError", this)); // Puts("Can not find Economics and ServerRewards."); // return; //} //else if(Economics != null && ServerRewards == null)//ServerRewardsなし //{ // _bool = ChangeEconomics(player); // return; //} //else if (Economics == null && ServerRewards != null)//Economicsなし //{ // _bool = ChangeRp(player); // return; //} //else if (Economics != null && ServerRewards != null)//正常系 //{ // SqueezeSelector(player); // return; //} //else //{ // SendMessage(player, lang.GetMessage("InternalError", this)); // Puts("Can not find Economics and ServerRewards."); // return; //} } private void SqueezeSelector(BasePlayer player) { double rateRandom = (double)UnityEngine.Random.Range(0, 1.0f); rateRandom = Math.Round(rateRandom, 1, MidpointRounding.AwayFromZero); bool _bool; if (0.5 <= rateRandom) { _bool = ChangeEconomics(player); } else { _bool = ChangeRp(player); } return; } private bool ChangeEconomics(BasePlayer player) { double playerCoins = (double)Economics.CallHook("Balance", player.UserIDString); if (playerCoins == 0) { return true; } double rateRandom = UnityEngine.Random.Range(Convert.ToSingle(MinRateEconomics), Convert.ToSingle(MaxRateEconomics)); double reduce = Math.Round(playerCoins * rateRandom, 1, MidpointRounding.AwayFromZero); object tmp_economics; if (ReceiverFlag && ReceiverSteamID != "0") { tmp_economics = Economics.CallHook("Transfer", player.UserIDString, ReceiverSteamID, reduce); } else { tmp_economics = Economics.CallHook("Withdraw", player.UserIDString, reduce); } if (tmp_economics == null || !(tmp_economics is bool) && !(bool)tmp_economics) { SendMessage(player, lang.GetMessage("NotRun", this)); Puts("Plugin is not running.:Economics"); return false; } playerCoins = (double)Economics.CallHook("Balance", player.UserIDString); LoggingDeathData(player, reduce, "COINS"); return true; } private bool ChangeRp(BasePlayer player) { int? NplayerRP = (int)ServerRewards?.Call("CheckPoints", player.userID); int playerRP; if (NplayerRP == null || NplayerRP == 0) { return true; } else { playerRP = Convert.ToInt32(NplayerRP); } double rateRandom = UnityEngine.Random.Range(Convert.ToSingle(MinRateRP), Convert.ToSingle(MaxRateRP)); int reduce = (int)Math.Round(playerRP * rateRandom, 0, MidpointRounding.AwayFromZero); object tmp_RP; object tmp_RP_T; if (ReceiverFlag && ReceiverSteamID != "0") { tmp_RP = ServerRewards?.Call("TakePoints", player.userID, reduce); tmp_RP_T = ServerRewards?.Call("AddPoints", Convert.ToUInt64(ReceiverSteamID), reduce); } else { tmp_RP = ServerRewards?.Call("TakePoints", player.userID, reduce); } if (tmp_RP == null || tmp_RP is bool && !(bool)tmp_RP) { SendMessage(player, lang.GetMessage("NotRun", this)); Puts("Plugin is not running.:ServerRewards"); return false; } playerRP = (int)ServerRewards?.Call("CheckPoints", player.userID); LoggingDeathData(player, reduce, "RP"); return true; } /// /// ログ吐き出し /// /// プレイヤー /// 値 private void LoggingDeathData(BasePlayer player,double reduce, string type) { //double currentDouble; //int currentInt; PlayerDataCR currentPlayerData; if (!LOST_DATA.TryGetValue(player.userID, out currentPlayerData)) { currentPlayerData = new PlayerDataCR(); LOST_DATA.Add(player.userID, currentPlayerData); } if (type.Equals("COINS")) { Log(player + " lost " + reduce + " coins"); currentPlayerData.Coins += reduce; SendMessage(player, lang.GetMessage("PlayerLostCoins", this).Replace("{reduce}", reduce.ToString())); Puts(player.displayName + "[" + player.UserIDString + "] lost " + reduce + " coins."); return; } if (type.Equals("RP")) { Log(player + " lost " + reduce + " RP"); currentPlayerData.RP += (int)reduce; SendMessage(player, lang.GetMessage("PlayerLostRP", this).Replace("{reduce}", reduce.ToString())); Puts(player.displayName + "[" + player.UserIDString + "] lost " + reduce + " RP."); return; } LOST_DATA[player.userID] = currentPlayerData; return; } #endregion #region Commands //[ConsoleCommand("deathpenalty.convert")] //private void DataConvert() //{ // Puts("Data convert START"); // DynamicConfigFile dataPlayerLostCoins;//コインロスト分集計用データファイル // DynamicConfigFile dataPlayerLostRP;//RPロスト分集計用データファイル // Dictionary LostCoinData; // Dictionary LostRPData; // //コインロスト分集計 // dataPlayerLostCoins = GetFile(nameof(DeathPenalty) + "_LostCoins"); // LostCoinData = dataPlayerLostCoins.ReadObject>(); // //RPロスト分集計 // dataPlayerLostRP = GetFile(nameof(DeathPenalty) + "_LostRP"); // LostRPData = dataPlayerLostRP.ReadObject>(); // Puts("Coins Data convert START"); // if (LostCoinData != null) // { // foreach (var playerOldCoinData in LostCoinData) // { // //Puts($"COINS OLD DATA: {playerOldCoinData.Key}:{playerOldCoinData.Value}"); // PlayerDataCR playerNewData; // if (!LOST_DATA.TryGetValue(playerOldCoinData.Key, out playerNewData)) // { // playerNewData = new PlayerDataCR(); // playerNewData.Coins += playerOldCoinData.Value; // LOST_DATA.Add(playerOldCoinData.Key, playerNewData); // } // else // { // playerNewData.Coins += playerOldCoinData.Value; // } // LOST_DATA[playerOldCoinData.Key] = playerNewData; // } // } // Puts("Coins Data convert END"); // SaveLostData(); // Puts("RP Data convert START"); // if (LostRPData != null) // { // foreach (var playerOldRPData in LostRPData) // { // PlayerDataCR playerNewData; // //Puts($"RP OLD DATA: {playerOldRPData.Key}:{playerOldRPData.Value}"); // if (!LOST_DATA.TryGetValue(playerOldRPData.Key, out playerNewData)) // { // playerNewData = new PlayerDataCR(); // playerNewData.RP += playerOldRPData.Value; // LOST_DATA.Add(playerOldRPData.Key, playerNewData); // } // else // { // playerNewData.RP += playerOldRPData.Value; // } // LOST_DATA[playerOldRPData.Key] = playerNewData; // } // } // Puts("RP Data convert END"); // SaveLostData(); // Puts("Data convert END"); //} [ChatCommand("dp")] private void DpCmd(BasePlayer player, string command, string[] args) { PlayerDataCR playerData; if(!LOST_DATA.TryGetValue(player.userID, out playerData)) { playerData = new PlayerDataCR(); LOST_DATA.Add(player.userID, playerData); } //SendMessage(player, lang.GetMessage("CPlayerLostCoins", this).Replace("{amount}", playerData.Coins.ToString())); //SendMessage(player, lang.GetMessage("CPlayerLostRP", this).Replace("{amount}", playerData.RP.ToString())); SendMessage(player, lang.GetMessage("CheckBalance", this).Replace("{amountEconomics}", playerData.Coins.ToString()).Replace("{amountRP}", playerData.RP.ToString())); } #endregion #region Helper private class UnityVector3Converter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var vector = (Vector3)value; writer.WriteValue($"{vector.x} {vector.y} {vector.z}"); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { var values = reader.Value.ToString().Trim().Split(' '); return new Vector3(Convert.ToSingle(values[0]), Convert.ToSingle(values[1]), Convert.ToSingle(values[2])); } var o = JObject.Load(reader); return new Vector3(Convert.ToSingle(o["x"]), Convert.ToSingle(o["y"]), Convert.ToSingle(o["z"])); } public override bool CanConvert(Type objectType) { return objectType == typeof(Vector3); } } private class CustomComparerDictionaryCreationConverter : CustomCreationConverter { private readonly IEqualityComparer comparer; public CustomComparerDictionaryCreationConverter(IEqualityComparer comparer) { if (comparer == null) throw new ArgumentNullException(nameof(comparer)); this.comparer = comparer; } public override bool CanConvert(Type objectType) { return HasCompatibleInterface(objectType) && HasCompatibleConstructor(objectType); } private static bool HasCompatibleInterface(Type objectType) { return objectType.GetInterfaces().Where(i => HasGenericTypeDefinition(i, typeof(IDictionary<,>))).Any(i => typeof(T).IsAssignableFrom(i.GetGenericArguments().First())); } private static bool HasGenericTypeDefinition(Type objectType, Type typeDefinition) { return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeDefinition; } private static bool HasCompatibleConstructor(Type objectType) { return objectType.GetConstructor(new[] { typeof(IEqualityComparer) }) != null; } public override IDictionary Create(Type objectType) { return Activator.CreateInstance(objectType, comparer) as IDictionary; } } void SendMessage(BasePlayer player, string message, params object[] args) => PrintToChat(player, pName + message, args); private void Log(string text) => LogToFile("death", $"[{DateTime.Now}] {text}", this); #endregion } }