Advertisement
Guest User

Untitled

a guest
Feb 2nd, 2016
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 91.11 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.IO;
  7. using System.Net;
  8. using System.Net.Sockets;
  9. using System.Text.RegularExpressions;
  10. using Oxide_kIRC;
  11. using Oxide;
  12. using Oxide.Core;
  13. using Oxide.Game.Rust;
  14. using UnityEngine;
  15. using Newtonsoft.Json;
  16. using Oxide.Plugins;
  17.  
  18. namespace Oxide.Plugins
  19. {
  20. [Info("kirc", "Kirollos", 1.0)]
  21. public class Kirc : RustPlugin
  22. {
  23. public kIRCCore irc = null;
  24. public Thread ircthread;
  25. public static Kirc dis = null;
  26.  
  27. public void _NextTick(Action ac)
  28. {
  29. this.NextTick(ac);
  30. }
  31.  
  32. public Oxide.Core.Libraries.Lang _lang
  33. {
  34. get { return this.lang; }
  35. set { this.lang = _lang; }
  36. }
  37.  
  38. public Oxide.Core.Libraries.Permission _permission
  39. {
  40. get { return this.permission; }
  41. set { this.permission = _permission; }
  42. }
  43.  
  44. public Oxide.Game.Rust.Libraries.Rust _rust
  45. {
  46. get { return this.rust; }
  47. set { this.rust = _rust; }
  48. }
  49.  
  50. void Init()
  51. {
  52. dis = this;
  53. Puts("plugin loaded");
  54. irc = new kIRCCore((string)Config["server"], (int)Config["port"], (string)Config["nick"], (string)Config["ident"], (string)Config["real"], (string)Config["channel"], (string)Config["password"], (string)Config["spassword"]);
  55. irc.SetAllowAdminOwner(true);
  56. irc.SetCommandPrefix(Convert.ToChar(Config["command_prefix"]));
  57. irc.SetParameterDelimiter(Convert.ToChar(Config["parameter_delimiter"]));
  58. ircthread = new Thread(() => irc.loopparsing(this));
  59. ircthread.Start();
  60. DeathNotes._Loaded();
  61. }
  62. void Loaded()
  63. {
  64. //DedNotes._Loaded();
  65. }
  66. void Unload()
  67. {
  68. Puts("plugin unloaded");
  69. irc.Destruct();
  70. /*if (ircthread.IsAlive)
  71. ircthread.Abort();*/
  72. }
  73.  
  74. protected override void LoadDefaultConfig()
  75. {
  76. PrintWarning("Creating a new config file");
  77. Config.Clear();
  78. Config["server"] = "irc.cncirc.net";
  79. Config["port"] = 6667;
  80. Config["spassword"] = "";
  81. Config["nick"] = "rustirc";
  82. Config["ident"] = "rustirc";
  83. Config["real"] = "rustirc";
  84. Config["password"] = "";
  85. Config["channel"] = "#rustirc";
  86. Config["command_prefix"] = "!";
  87. Config["parameter_delimiter"] = "/";
  88. Config["allow_adminowner"] = true;
  89. }
  90.  
  91. protected override void LoadConfig()
  92. {
  93. //DedNotes._LoadConfig();
  94. }
  95.  
  96. void OnEntityDeath(BaseCombatEntity victim, HitInfo info)
  97. {
  98. DeathNotes._OnEntityDeath(victim, info);
  99. }
  100.  
  101. void OnEntityTakeDamage(BaseCombatEntity victim, HitInfo info)
  102. {
  103. DeathNotes._OnEntityTakeDamage(victim, info);
  104. }
  105.  
  106. public void Log(string message)
  107. {
  108. Puts(message);
  109. }
  110.  
  111. public void SendToChat(string message)
  112. {
  113. PrintToChat(message);
  114. }
  115.  
  116. public void SendToChat(BasePlayer p, string message)
  117. {
  118. PrintToChat(p, message);
  119. }
  120.  
  121. void OnPlayerChat(ConsoleSystem.Arg arg)
  122. {
  123. //BasePlayer p = arg.connection.player;
  124. irc.Say((string)Config["channel"], arg.Player().displayName + ": " + arg.ArgsStr);
  125. }
  126.  
  127. void OnPlayerInit(BasePlayer player)
  128. {
  129. DeathNotes._OnPlayerInit(player);
  130. irc.Say((string)Config["channel"], "[CONNECT] " + player.displayName + " has connected!");
  131. }
  132.  
  133. void OnPlayerDisconnected(BasePlayer player, string reason)
  134. {
  135. irc.Say((string)Config["channel"], "[DISCONNECT] " + player.displayName + " has disconnected (" + reason + ")!");
  136. }
  137. public void _SaveConfig()
  138. {
  139. this.SaveConfig();
  140. }
  141. }
  142. }
  143.  
  144. namespace Oxide_kIRC
  145. {
  146. public class kIRCCore
  147. {
  148. public string _host;
  149. public int _port;
  150. public string _nick;
  151. public string _user;
  152. public string _realname;
  153. public string _password;
  154. public string _channel;
  155. public char _command_prefix;
  156. public char _parameter_delimiter;
  157. public string _spassword;
  158. public bool Registered = false;
  159. private TcpClient ircsock;
  160. private Stream mystream;
  161. private UTF8Encoding _encoding;
  162. public List<string[]> userlist = new List<string[]>();
  163.  
  164. public bool allow_adminowner;
  165.  
  166. private bool __NAMES = false;
  167.  
  168. public bool isConnected = false;
  169.  
  170. //public List<CPerform> cperform;
  171. //public List<kIRC_Commands> custom_commands;
  172.  
  173. public kIRCCore(string host, int port, string nick, string user, string realname, string channel, string password, string spassword)
  174. {
  175. ircsock = new TcpClient();
  176. ircsock.Connect(host, port);
  177. mystream = ircsock.GetStream();
  178. ircsock.NoDelay = true;
  179. _encoding = new UTF8Encoding();
  180. isConnected = true;
  181. _nick = nick;
  182. _host = host;
  183. _port = port;
  184. _user = user;
  185. _spassword = spassword;
  186. _realname = realname;
  187. _password = password;
  188. _channel = channel;
  189. this.Send("NICK " + this._nick);
  190. if (!String.IsNullOrEmpty(_spassword))
  191. this.Send("PASS " + _spassword);
  192. this.Send("USER " + this._user + " - - :" + this._realname);
  193. }
  194. public bool Disconnect(string reason = "Bye!")
  195. {
  196. try
  197. {
  198. this.Send("QUIT :" + reason);
  199. ircsock.Close();
  200. return true;
  201. }
  202. catch
  203. {
  204. return false;
  205. }
  206. }
  207. public void Destruct(bool disconnect = true)
  208. {
  209. if (!isConnected) return;
  210.  
  211. if (disconnect)
  212. this.Disconnect();
  213. else
  214. ircsock.Close();
  215. isConnected = false;
  216. }
  217.  
  218. public void Send(string data)
  219. {
  220. if (!this.isConnected) return;
  221. if (!data.Contains("\n"))
  222. data += "\r\n";
  223. byte[] _data = _encoding.GetBytes(data);
  224.  
  225. try
  226. {
  227. mystream.Write(_data, 0, _data.Length);
  228. //if (kIRC.dis.Configuration.Instance.Debug)
  229. {
  230. Kirc.dis.Log("[kIRC DEBUG]: {" + DateTime.Now + "} << " + data);
  231. }
  232. }
  233. catch(Exception e)
  234. {
  235. Kirc.dis.Log("kIRC Error: Send() has failed, therefore destructing. cause: " + e.ToString());
  236. Kirc.dis.Log("kIRC Error: You can reload the plugin using `rocket reload kIRC`");
  237. this.Destruct(false);
  238. }
  239. }
  240. public String Read()
  241. {
  242. if (!this.isConnected) return "";
  243. string data = "";
  244. byte[] _data = new byte[1];
  245. while (true)
  246. {
  247. try
  248. {
  249. int k = mystream.Read(_data, 0, 1);
  250. if (k == 0)
  251. {
  252. this.Destruct();
  253. return "";
  254. }
  255. char kk = Convert.ToChar(_data[0]);
  256. data += kk;
  257. if (kk == '\n')
  258. break;
  259. }
  260. catch
  261. {
  262. Kirc.dis.Log("kIRC Error: Read() has failed, therefore destructing.");
  263. Kirc.dis.Log("kIRC Error: You can reload the plugin using `rocket reload kIRC`");
  264. this.Destruct(false);
  265. return "";
  266. }
  267. }
  268.  
  269. return data;
  270. }
  271.  
  272. public void Say(string target, string text)
  273. {
  274. string[] splitted_text = text.Split(new string[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  275. for (int i = 0; i < splitted_text.Length; i++)
  276. this.Send("PRIVMSG " + target + " :" + /*text*/splitted_text[i]);
  277. return;
  278. }
  279.  
  280. public void Notice(string target, string text)
  281. {
  282. string[] splitted_text = text.Split(new string[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
  283. for (int i = 0; i < splitted_text.Length; i++)
  284. this.Send("NOTICE " + target + " :" + /*text*/splitted_text[i]);
  285. return;
  286. }
  287.  
  288. public void parse(string data, Kirc unturnedclass)
  289. {
  290. if (data == "") return;
  291. //if (kIRC.dis.Configuration.Instance.Debug)
  292. {
  293. Kirc.dis.Log("[kIRC DEBUG]: {" + DateTime.Now + "} >> " + data);
  294. }
  295. if (data.Substring(0, 6) == "ERROR ")
  296. {
  297. Kirc.dis.Log("Error: IRC socket has closed. Reload the plugin for reconnection.");
  298. this.Destruct();
  299. }
  300. // Regex taken from (http://calebdelnay.com/blog/2010/11/parsing-the-irc-message-format-as-a-client)
  301. string
  302. prefix = "",
  303. command = "",
  304. //parameters,
  305. trailing = ""
  306. ;
  307. string[] parameters = new string[] { };
  308. Regex parsingRegex = new Regex(@"^(:(?<prefix>\S+) )?(?<command>\S+)( (?!:)(?<params>.+?))?( :(?<trail>.+))?$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
  309. Match messageMatch = parsingRegex.Match(data);
  310.  
  311. if (messageMatch.Success)
  312. {
  313. prefix = messageMatch.Groups["prefix"].Value;
  314. command = messageMatch.Groups["command"].Value;
  315. parameters = messageMatch.Groups["params"].Value.Split(' ');
  316. trailing = messageMatch.Groups["trail"].Value;
  317.  
  318. if (!String.IsNullOrEmpty(trailing))
  319. parameters = parameters.Concat(new string[] { trailing }).ToArray();
  320. }
  321.  
  322. if (command == "PING")
  323. {
  324. this.Send("PONG :" + trailing);
  325. this.Send("NAMES " + this._channel);
  326. }
  327.  
  328. if (command == "001")
  329. {
  330. this.Registered = true;
  331. //}
  332. //if (command == "005")
  333. //{
  334. if (!String.IsNullOrEmpty(this._password))
  335. this.Say("NickServ", "IDENTIFY " + this._password);
  336. this.Send("JOIN " + _channel);
  337. // Perform
  338. //for (int i = 0; i < this.cperform.Count; i++)
  339. //{
  340. // this.Send(this.cperform[i].pcommand);
  341. //}
  342. // -------
  343. //kIRCVersionChecker.CheckUpdate(this, this._channel); // Update checker
  344. }
  345. if (command == "353")
  346. {
  347. // Names list
  348.  
  349. if (!this.__NAMES)
  350. {
  351. this.__NAMES = true;
  352. this.userlist.Clear();
  353. }
  354.  
  355. string[] _userlist = trailing.Trim().Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
  356. for (int i = 0; i < _userlist.Length; i++)
  357. {
  358. string lerank = Convert.ToString(_userlist[i][0]);
  359. string lename = _userlist[i].Remove(0, 1);
  360. if (lerank == "~" || lerank == "&" || lerank == "@" || lerank == "%" || lerank == "+")
  361. {
  362. lename = _userlist[i].Remove(0, 1);
  363. }
  364. else
  365. {
  366. lename = _userlist[i];
  367. lerank = "";
  368. }
  369.  
  370. this.userlist.Add(new[] { lename, lerank });
  371. }
  372. }
  373. if (command == "433")
  374. {
  375. Kirc.dis.Log("Error: Nickname taken. Reload the plugin for reconnection.");
  376. this.Destruct();
  377. }
  378. if (command == "JOIN")
  379. {
  380. string user = prefix.Split('!')[0];
  381. string ident = prefix.Split('!')[1].Split('@')[0];
  382. string host = prefix.Split('@')[1];
  383. //RocketChat.Say("[IRC JOIN] "+ user +" has joined IRC channel.", Color.gray);
  384. /*kIRCTranslate.Rocket_ChatSay("game_ircjoin", Color.gray, new Dictionary<string, string>()
  385. {
  386. {"time", DateTime.Now.ToString()},
  387. {"irc_usernick", user},
  388. {"irc_userident", ident},
  389. {"irc_userhost", host},
  390. {"irc_channel", this._channel}
  391. });*/
  392.  
  393. this.userlist.Add(new[] { user, "" });
  394. }
  395. else if (command == "PART")
  396. {
  397. string user = prefix.Split('!')[0];
  398. string ident = prefix.Split('!')[1].Split('@')[0];
  399. string host = prefix.Split('@')[1];
  400. //RocketChat.Say("[IRC PART] " + user + " has left IRC channel.", Color.gray);
  401. /*kIRCTranslate.Rocket_ChatSay("game_ircpart", Color.gray, new Dictionary<string, string>()
  402. {
  403. {"time", DateTime.Now.ToString()},
  404. {"irc_usernick", user},
  405. {"irc_userident", ident},
  406. {"irc_userhost", host},
  407. {"irc_channel", this._channel},
  408. {"irc_partreason", trailing.Trim()}
  409. });*/
  410.  
  411. for (int i = 0; i < this.userlist.Count; i++)
  412. {
  413. if (this.userlist[i][0] == user)
  414. {
  415. this.userlist.Remove(new[] { user, this.userlist[i][1] });
  416. break;
  417. }
  418. }
  419. }
  420. if (command == "366")
  421. { // End of /NAMES
  422. this.__NAMES = false;
  423. }
  424. if (command == "MODE")
  425. {
  426. if (String.IsNullOrEmpty(trailing))
  427. {
  428. this.Send("NAMES " + this._channel);
  429. }
  430. }
  431. if (command == "NICK")
  432. {
  433. if (this.Registered)
  434. {
  435. string user = prefix.Split('!')[0];
  436. if (this._nick == user)
  437. this._nick = trailing.Trim();
  438. for (int i = 0; i < this.userlist.Count; i++)
  439. {
  440. if (this.userlist[i][0] == user)
  441. {
  442. this.userlist[i][0] = trailing.Trim();
  443. break;
  444. }
  445. }
  446. }
  447. }
  448. if (command == "PRIVMSG")
  449. {
  450. if (trailing[0] == this._command_prefix)
  451. {
  452. string cmd;
  453. try
  454. {
  455. cmd = trailing.Split(' ')[0].ToLower();
  456. if (String.IsNullOrEmpty(cmd.Trim()))
  457. cmd = trailing.Trim().ToLower();
  458. }
  459. catch
  460. {
  461. cmd = trailing.Trim().ToLower();
  462. }
  463. string msg = "";
  464. string user = prefix.Split('!')[0];
  465. string ident = prefix.Split('!')[1].Split('@')[0];
  466. string host = prefix.Split('@')[1];
  467. cmd = cmd.Remove(0, 1); // remove the prefix pls
  468.  
  469. msg = trailing.Remove(0, 1 + cmd.Length).Trim();
  470. cmd = cmd.Trim();
  471.  
  472. if(cmd == "say")
  473. {
  474. if (String.IsNullOrEmpty(msg))
  475. {
  476. string[] ParamSyntax = { "text" };
  477. this.SendSyntax(this._channel, cmd, ParamSyntax);
  478. return;
  479. }
  480. Kirc.dis.SendToChat("[IRC] " + user + ": " + msg);
  481. }
  482.  
  483. if(cmd == "players")
  484. {
  485. string listStr = "";
  486. BaseEntity[] uh = BaseEntity.Util.FindTargets("", true);
  487. BasePlayer[] ps = uh.Select(x => x.ToPlayer()).ToArray();
  488. int count = uh.Where(x => x.ToPlayer().isConnected == true).Count();
  489. int i = 0;
  490. foreach (BasePlayer u in ps)
  491. {
  492. if (!u.isConnected) continue;
  493. listStr += u.displayName;
  494. if(++i != count)
  495. listStr += ", ";
  496. }
  497. this.Say(this._channel, "Connected Players [" + count + "]: " + listStr);
  498. }
  499.  
  500. if(cmd == "give" && IsOp(user, false))
  501. {
  502. // not done
  503. }
  504.  
  505. /*if (cmd == "help")
  506. {
  507. if (!IsVoice(user, false))
  508. {
  509. this.Say(this._channel, "Error: You need voice to use the commands.");
  510. return;
  511. }
  512. this.Say(this._channel, "====Unturned IRC Commands====");
  513. this.Say(this._channel, "- " + this._command_prefix + "help => This command");
  514. this.Say(this._channel, "- " + this._command_prefix + "say <text> => Send a message to ingame users");
  515. this.Say(this._channel, "- " + this._command_prefix + "players => Shows a list of online players");
  516. this.Say(this._channel, "- " + this._command_prefix + "pm => Sends a personal message to a specific player");
  517. // Custom commands
  518. for (int i = 0; i < this.custom_commands.Count; i++)
  519. {
  520. if (this.custom_commands[i].FlagNeeded == "v" || this.custom_commands[i].FlagNeeded == "")
  521. {
  522. this.Say(this._channel, "+ " + this._command_prefix + this.custom_commands[i].BotCommand + " " + this.custom_commands[i].BotSyntax);
  523. }
  524. }
  525. // ---------------
  526. if (IsHalfOp(user, false))
  527. {
  528. this.Say(this._channel, "- " + this._command_prefix + "info <player name> => Show information about given username");
  529. this.Say(this._channel, "- " + this._command_prefix + "broadcast <text> => Sends a broadcast to the players");
  530. // Custom commands
  531. for (int i = 0; i < this.custom_commands.Count; i++)
  532. {
  533. if (this.custom_commands[i].FlagNeeded == "h")
  534. {
  535. this.Say(this._channel, "+ " + this._command_prefix + this.custom_commands[i].BotCommand + " " + this.custom_commands[i].BotSyntax);
  536. }
  537. }
  538. // ---------------
  539. }
  540. if (IsOp(user, false))
  541. {
  542. this.Say(this._channel, "- " + this._command_prefix + "kick <player name> <reason> => Kicks a player from the server with a given reason");
  543. // Custom commands
  544. for (int i = 0; i < this.custom_commands.Count; i++)
  545. {
  546. if (this.custom_commands[i].FlagNeeded == "o")
  547. {
  548. this.Say(this._channel, "+ " + this._command_prefix + this.custom_commands[i].BotCommand + " " + this.custom_commands[i].BotSyntax);
  549. }
  550. }
  551. // ---------------
  552. }
  553. if (IsAdmin(user, false))
  554. {
  555. this.Say(this._channel, "- " + this._command_prefix + "ban <player name|SteamID> <duration in seconds> <reason> => Bans a player from the server with a given duration and reason");
  556. this.Say(this._channel, "- " + this._command_prefix + "unban <SteamID> => Unbans a player from the server with a given SteamID");
  557. this.Say(this._channel, "- " + this._command_prefix + "bans => Shows ban list");
  558. this.Say(this._channel, "- " + this._command_prefix + "save => Saves the game data.");
  559. this.Say(this._channel, "- " + this._command_prefix + "shutdown => shuts down the server.");
  560. // Custom commands
  561. for (int i = 0; i < this.custom_commands.Count; i++)
  562. {
  563. if (this.custom_commands[i].FlagNeeded == "a")
  564. {
  565. this.Say(this._channel, "+ " + this._command_prefix + this.custom_commands[i].BotCommand + " " + this.custom_commands[i].BotSyntax);
  566. }
  567. }
  568. // ---------------
  569. }
  570. if (IsOwner(user, false))
  571. {
  572. // Custom commands
  573. for (int i = 0; i < this.custom_commands.Count; i++)
  574. {
  575. if (this.custom_commands[i].FlagNeeded == "q")
  576. {
  577. this.Say(this._channel, "+ " + this._command_prefix + this.custom_commands[i].BotCommand + " " + this.custom_commands[i].BotSyntax);
  578. }
  579. }
  580. // ---------------
  581. }
  582. this.Say(this._channel, "=============================");
  583. }
  584. else if (cmd == "say" && IsVoice(user, false))
  585. {
  586. if (String.IsNullOrEmpty(msg))
  587. {
  588. string[] ParamSyntax = { "text" };
  589. this.SendSyntax(this._channel, cmd, ParamSyntax);
  590. return;
  591. }
  592. //RocketChat.Say("[IRC] " + user + ": " + msg, Color.yellow);
  593. kIRCTranslate.Rocket_ChatSay("game_ircsay", Color.yellow, new Dictionary<string, string>()
  594. {
  595. {"irc_usernick", user},
  596. {"irc_userident", ident},
  597. {"irc_userhost", host},
  598. {"irc_channel", this._channel},
  599. {"irc_message", msg}
  600. });
  601.  
  602. }
  603. else if (cmd == "players" && IsVoice(user, false))
  604. {
  605. string playerlist = "";
  606. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_playerslist", new Dictionary<string, string>()
  607. {
  608. {"time", DateTime.Now.ToString()},
  609. {"irc_usernick", user},
  610. {"irc_userident", ident},
  611. {"irc_userhost", host},
  612. {"players_amount", Provider.Players.Count.ToString()},
  613. {"players_max", Provider.MaxPlayers.ToString()},
  614. {"players_list", playerlist}
  615. });
  616. }
  617. else if (cmd == "pm" && IsVoice(user, false))
  618. {
  619. if (msg.Split(this._parameter_delimiter).Length < 2)
  620. {
  621. string[] ParamSyntax = { "Player Name", "Message" };
  622. this.SendSyntax(this._channel, cmd, ParamSyntax);
  623. return;
  624. }
  625. else
  626. {
  627. string pname = msg.Split(this._parameter_delimiter)[0];
  628. string message = msg.Split(this._parameter_delimiter)[1];
  629.  
  630. UnturnedPlayer pPointer = UnturnedPlayer.FromName(pname);
  631. if (pPointer == null || pPointer.CharacterName != pname)
  632. this.Say(this._channel, "[ERROR] Player " + pname + " not found.");
  633. else
  634. {
  635. //RocketChat.Say(pPointer, "[IRC PM] " + user + ": " + message, Color.magenta);
  636. kIRCTranslate.Rocket_ChatSay("game_ircpm", Color.magenta, new Dictionary<string, string>()
  637. {
  638. {"time", DateTime.Now.ToString()},
  639. {"irc_usernick", user},
  640. {"irc_userident", ident},
  641. {"irc_userhost", host},
  642. {"irc_channel", this._channel},
  643. {"irc_message", message}
  644. }, pPointer);
  645. }
  646. }
  647. }
  648. else if (cmd == "info" && IsHalfOp(user, false))
  649. {
  650. if (String.IsNullOrEmpty(msg))
  651. {
  652. string[] ParamSyntax = { "Player Name" };
  653. this.SendSyntax(this._channel, cmd, ParamSyntax);
  654. }
  655. else
  656. {
  657. string pname = msg.Trim();
  658. UnturnedPlayer pPointer = UnturnedPlayer.FromName(pname);
  659.  
  660. if (pPointer == null || pPointer.CharacterName != pname)
  661. {
  662. this.Say(this._channel, "[ERROR] Player " + pname + " not found.");
  663. return;
  664. }
  665. this.Notice(user, "Info about {" + pname + "}");
  666. this.Notice(user, "Character name: " + pPointer.CharacterName);
  667. this.Notice(user, "Steam name: " + pPointer.SteamName);
  668. this.Notice(user, "SteamID: " + pPointer.CSteamID.ToString());
  669. //this.Notice(user, "Health: " + pPointer.Health + "%"); // pPointer.Health ALWAYS returns zero for some reason..
  670. // Therefore using another method to update player health
  671. // on each health update event.
  672. this.Notice(user, "Health: " + pPointer.Health); // Fixed in Rocket v4.6.0.0
  673. this.Notice(user, "Hunger: " + pPointer.Hunger + "%");
  674. this.Notice(user, "Thirst: " + pPointer.Thirst + "%");
  675. this.Notice(user, "Infection: " + pPointer.Infection + "%");
  676. this.Notice(user, "Stamina: " + pPointer.Stamina + "%");
  677. this.Notice(user, "Experience: " + pPointer.Experience);
  678. this.Notice(user, "Admin: " + (pPointer.IsAdmin == true ? "Yes" : "No"));
  679. this.Notice(user, "Dead: " + (pPointer.Dead == true ? "Yes" : "No"));
  680. this.Notice(user, "Godmode: " + (pPointer.Features.GodMode == true ? "Enabled" : "Disabled"));
  681. this.Notice(user, "Position: X:" + pPointer.Position.x + ", Y:" + pPointer.Position.y + ", Z:" + pPointer.Position.z);
  682.  
  683. }
  684. }
  685. else if (cmd == "broadcast" && IsHalfOp(user, false))
  686. {
  687. if (String.IsNullOrEmpty(msg))
  688. {
  689. string[] ParamSyntax = { "text" };
  690. this.SendSyntax(this._channel, cmd, ParamSyntax);
  691. return;
  692. }
  693. //RocketChat.Say("[IRC Broadcast]: " + msg, Color.red);
  694. kIRCTranslate.Rocket_ChatSay("game_ircbroadcast", Color.red, new Dictionary<string, string>()
  695. {
  696. {"time", DateTime.Now.ToString()},
  697. {"irc_usernick", user},
  698. {"irc_userident", ident},
  699. {"irc_userhost", host},
  700. {"irc_channel", this._channel},
  701. {"irc_message", msg}
  702. });
  703. }
  704. else if (cmd == "kick" && IsOp(user, false))
  705. {
  706. if (msg.Split(this._parameter_delimiter).Length < 2)
  707. {
  708. string[] ParamSyntax = { "Player Name", "Reason" };
  709. this.SendSyntax(this._channel, cmd, ParamSyntax);
  710. }
  711. else
  712. {
  713. string pname = msg.Split(this._parameter_delimiter)[0];
  714. string reason = msg.Split(this._parameter_delimiter)[1];
  715. UnturnedPlayer pPointer = UnturnedPlayer.FromName(pname);
  716. if (pPointer == null || pPointer.CharacterName != pname)
  717. this.Say(this._channel, "[ERROR] Player " + pname + " not found.");
  718. else
  719. {
  720.  
  721. kIRC_PushCommand pcmd = new kIRC_PushCommand();
  722. pcmd.command = "__kick";
  723. pcmd.parameters = new string[] { pname, reason };
  724. pcmd.extradata.Add("Syntax", "");
  725. pcmd.onfire(() => { });
  726. pcmd.onexec((string response) =>
  727. {
  728. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_kicksuccess", new Dictionary<string, string>()
  729. {
  730. {"time", DateTime.Now.ToString()},
  731. {"irc_usernick", user},
  732. {"irc_userident", ident},
  733. {"irc_userhost", host},
  734. {"irc_channel", this._channel},
  735. {"irc_targetnick", pname},
  736. {"irc_kickreason", reason}
  737. });
  738. });
  739.  
  740. pcmd.execute = true;
  741.  
  742. pcmd.push(unturnedclass); // Sends it to the main unturned thread
  743. }
  744. }
  745. }
  746. else if (cmd == "ban" && IsAdmin(user, false))
  747. {
  748. if (msg.Split(this._parameter_delimiter).Length < 3)
  749. {
  750. string[] ParamSyntax = { "Player Name|SteamID", "Duration in seconds", "Reason" };
  751. this.SendSyntax(this._channel, cmd, ParamSyntax);
  752. }
  753. else
  754. {
  755. string pname = msg.Split(this._parameter_delimiter)[0];
  756. string durationstr = msg.Split(this._parameter_delimiter)[1];
  757. int duration = 0;
  758. if (!int.TryParse(durationstr, out duration))
  759. {
  760. this.Say(this._channel, "[ERROR] duration \"" + durationstr + "\" is not valid.");
  761. return;
  762. }
  763.  
  764. if (!Regex.IsMatch(pname, @"^\d+$")) // If not SteamID
  765. {
  766. UnturnedPlayer pPointer = UnturnedPlayer.FromName(pname);
  767. if (pPointer == null || pPointer.CharacterName != pname)
  768. {
  769. this.Say(this._channel, "[ERROR] Player " + pname + " not found.");
  770. return;
  771. }
  772. else
  773. {
  774. // pPointer.Ban(reason, (uint) duration); // Doesn't work (https://github.com/RocketFoundation/Rocket/issues/173)
  775. //this.Say(this._channel, "[SUCCESS] Player " + pname + " is banned!");
  776. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_pbansuccess", new Dictionary<string, string>()
  777. {
  778. {"time", DateTime.Now.ToString()},
  779. {"irc_usernick", user},
  780. {"irc_userident", ident},
  781. {"irc_userhost", host},
  782. {"irc_channel", this._channel},
  783. {"irc_targetnick", pname},
  784. {"irc_banreason", reason},
  785. {"irc_banduration", durationstr}
  786. });
  787. }
  788. }
  789. else
  790. {
  791. //this.Say(this._channel, "[SUCCESS] SteamID "+pname+" is banned.");
  792. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_sbansuccess", new Dictionary<string, string>()
  793. {
  794. {"time", DateTime.Now.ToString()},
  795. {"irc_usernick", user},
  796. {"irc_userident", ident},
  797. {"irc_userhost", host},
  798. {"irc_channel", this._channel},
  799. {"irc_targetsteamid", pname},
  800. {"irc_banreason", reason},
  801. {"irc_banduration", durationstr}
  802. });
  803. }
  804.  
  805. kIRC_PushCommand pcmd = new kIRC_PushCommand();
  806. pcmd.command = "ban {0}/{1}/{2}";
  807. pcmd.parameters = new string[] { pname, reason, durationstr };
  808. pcmd.onfire(() => { });
  809. pcmd.onexec((string response) => { });
  810.  
  811. pcmd.execute = true;
  812.  
  813. pcmd.push(unturnedclass); // Sends it to the main unturned thread
  814. }
  815. }
  816. else if (cmd == "unban" && IsAdmin(user, false))
  817. {
  818. if (String.IsNullOrEmpty(msg))
  819. {
  820. string[] ParamSyntax = { "SteamID" };
  821. this.SendSyntax(this._channel, cmd, ParamSyntax);
  822. return;
  823. }
  824. else
  825. {
  826.  
  827. kIRC_PushCommand pcmd = new kIRC_PushCommand();
  828. pcmd.command = "unban {0}";
  829. pcmd.parameters = new string[] { msg };
  830. pcmd.onfire(() => { });
  831. pcmd.onexec((string response) => {
  832. //this.Say(this._channel, "Unban response: " + response);
  833. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_unbanresponse", new Dictionary<string, string>()
  834. {
  835. {"time", DateTime.Now.ToString()},
  836. {"irc_usernick", user},
  837. {"irc_userident", ident},
  838. {"irc_userhost", host},
  839. {"irc_channel", this._channel},
  840. {"irc_targetsteamid", msg},
  841. {"irc_response", response}
  842. });
  843. });
  844.  
  845. pcmd.execute = true;
  846.  
  847. pcmd.push(unturnedclass); // Sends it to the main unturned thread
  848. }
  849. }
  850. else if (cmd == "bans" && IsAdmin(user, false))
  851. {
  852. kIRC_PushCommand pcmd = new kIRC_PushCommand();
  853. pcmd.command = "bans";
  854. pcmd.parameters = new string[] { };
  855. pcmd.onfire(() =>
  856. {
  857. this.Say(this._channel, user + ": Response is sent to your query.");
  858. });
  859. pcmd.onexec((string response) =>
  860. {
  861. this.Say(user, "Response from bans:");
  862. string[] bans = response.Split('\n');
  863. for (int i = 0; i < bans.Length; i++)
  864. {
  865. this.Say(user, bans[i]);
  866. }
  867. });
  868.  
  869. pcmd.execute = true;
  870.  
  871. pcmd.push(unturnedclass); // Sends it to the main unturned thread
  872. }
  873. else if (cmd == "save" && IsAdmin(user, false))
  874. {
  875. kIRC_PushCommand pcmd = new kIRC_PushCommand();
  876. pcmd.command = "save";
  877. pcmd.parameters = new string[] { };
  878. pcmd.onfire(() => {
  879. //this.Say(this._channel, "Saving server settings...");
  880. //RocketChat.Say("[IRC] Saving server settings...");
  881. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_onsave", new Dictionary<string, string>()
  882. {
  883. {"time", DateTime.Now.ToString()},
  884. {"irc_usernick", user},
  885. {"irc_userident", ident},
  886. {"irc_userhost", host},
  887. {"irc_channel", this._channel}
  888. });
  889. kIRCTranslate.Rocket_ChatSay("game_onsave", new Dictionary<string, string>()
  890. {
  891. {"time", DateTime.Now.ToString()},
  892. {"irc_usernick", user},
  893. {"irc_userident", ident},
  894. {"irc_userhost", host},
  895. {"irc_channel", this._channel}
  896. });
  897. });
  898. pcmd.onexec((string response) => {
  899. //this.Say(this._channel, "Save response: " + response);
  900. //RocketChat.Say("[IRC] Server settings, Player items saved!");
  901. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_saveexec", new Dictionary<string, string>()
  902. {
  903. {"time", DateTime.Now.ToString()},
  904. {"irc_usernick", user},
  905. {"irc_userident", ident},
  906. {"irc_userhost", host},
  907. {"irc_channel", this._channel},
  908. {"irc_response", response}
  909. });
  910. kIRCTranslate.Rocket_ChatSay("game_saveexec", new Dictionary<string, string>()
  911. {
  912. {"time", DateTime.Now.ToString()},
  913. {"irc_usernick", user},
  914. {"irc_userident", ident},
  915. {"irc_userhost", host},
  916. {"irc_channel", this._channel},
  917. {"irc_response", response}
  918. });
  919. });
  920.  
  921. pcmd.execute = true;
  922.  
  923. pcmd.push(unturnedclass); // Sends it to the main unturned thread
  924. }
  925. else if (cmd == "shutdown" && IsAdmin(user, false))
  926. {
  927. kIRC_PushCommand pcmd = new kIRC_PushCommand();
  928. pcmd.command = "save";
  929. pcmd.parameters = new string[] { };
  930. pcmd.onfire(() =>
  931. {
  932. //RocketChat.Say("[IRC WARNING]: SERVER IS SHUTTING DOWN IN 5 SECONDS!", Color.red);
  933. //this.Say(this._channel, "Shutting down in 5 seconds");
  934. kIRCTranslate.Rocket_ChatSay("game_shutdownwarning", new Dictionary<string, string>()
  935. {
  936. {"time", DateTime.Now.ToString()},
  937. {"irc_usernick", user},
  938. {"irc_userident", ident},
  939. {"irc_userhost", host},
  940. {"irc_channel", this._channel},
  941. {"shutdown_secs", "5"}
  942. });
  943. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_shutdownwarning", new Dictionary<string, string>()
  944. {
  945. {"time", DateTime.Now.ToString()},
  946. {"irc_usernick", user},
  947. {"irc_userident", ident},
  948. {"irc_userhost", host},
  949. {"irc_channel", this._channel},
  950. {"shutdown_secs", "5"}
  951. });
  952. Thread.Sleep(1000);
  953. });
  954. pcmd.onexec((string response) =>
  955. {
  956. //RocketChat.Say("[IRC] Server settings, Player items saved!");
  957. kIRCTranslate.Rocket_ChatSay("game_saveexec", new Dictionary<string, string>()
  958. {
  959. {"time", DateTime.Now.ToString()},
  960. {"irc_usernick", user},
  961. {"irc_userident", ident},
  962. {"irc_userhost", host},
  963. {"irc_channel", this._channel},
  964. {"irc_response", response}
  965. });
  966.  
  967. kIRC_PushCommand pcmd2 = new kIRC_PushCommand();
  968. pcmd2.command = "shutdown";
  969. pcmd2.parameters = new string[] { };
  970.  
  971. pcmd2.onfire(() =>
  972. {
  973.  
  974. kIRCTranslate.Rocket_ChatSay("game_shutdownwarning", new Dictionary<string, string>()
  975. {
  976. {"time", DateTime.Now.ToString()},
  977. {"irc_usernick", user},
  978. {"irc_userident", ident},
  979. {"irc_userhost", host},
  980. {"irc_channel", this._channel},
  981. {"shutdown_secs", "4"}
  982. });
  983. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_shutdownwarning", new Dictionary<string, string>()
  984. {
  985. {"time", DateTime.Now.ToString()},
  986. {"irc_usernick", user},
  987. {"irc_userident", ident},
  988. {"irc_userhost", host},
  989. {"irc_channel", this._channel},
  990. {"shutdown_secs", "4"}
  991. });
  992. Thread.Sleep(1000);
  993. kIRCTranslate.Rocket_ChatSay("game_shutdownwarning", new Dictionary<string, string>()
  994. {
  995. {"time", DateTime.Now.ToString()},
  996. {"irc_usernick", user},
  997. {"irc_userident", ident},
  998. {"irc_userhost", host},
  999. {"irc_channel", this._channel},
  1000. {"shutdown_secs", "3"}
  1001. });
  1002. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_shutdownwarning", new Dictionary<string, string>()
  1003. {
  1004. {"time", DateTime.Now.ToString()},
  1005. {"irc_usernick", user},
  1006. {"irc_userident", ident},
  1007. {"irc_userhost", host},
  1008. {"irc_channel", this._channel},
  1009. {"shutdown_secs", "3"}
  1010. });
  1011. Thread.Sleep(1000);
  1012. kIRCTranslate.Rocket_ChatSay("game_shutdownwarning", new Dictionary<string, string>()
  1013. {
  1014. {"time", DateTime.Now.ToString()},
  1015. {"irc_usernick", user},
  1016. {"irc_userident", ident},
  1017. {"irc_userhost", host},
  1018. {"irc_channel", this._channel},
  1019. {"shutdown_secs", "2"}
  1020. });
  1021. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_shutdownwarning", new Dictionary<string, string>()
  1022. {
  1023. {"time", DateTime.Now.ToString()},
  1024. {"irc_usernick", user},
  1025. {"irc_userident", ident},
  1026. {"irc_userhost", host},
  1027. {"irc_channel", this._channel},
  1028. {"shutdown_secs", "2"}
  1029. });
  1030. Thread.Sleep(1000);
  1031. kIRCTranslate.Rocket_ChatSay("game_shutdownwarning", new Dictionary<string, string>()
  1032. {
  1033. {"time", DateTime.Now.ToString()},
  1034. {"irc_usernick", user},
  1035. {"irc_userident", ident},
  1036. {"irc_userhost", host},
  1037. {"irc_channel", this._channel},
  1038. {"shutdown_secs", "1"}
  1039. });
  1040. kIRCTranslate.IRC_SayTranslation(this, this._channel, "irc_shutdownwarning", new Dictionary<string, string>()
  1041. {
  1042. {"time", DateTime.Now.ToString()},
  1043. {"irc_usernick", user},
  1044. {"irc_userident", ident},
  1045. {"irc_userhost", host},
  1046. {"irc_channel", this._channel},
  1047. {"shutdown_secs", "1"}
  1048. });
  1049. Thread.Sleep(1000);
  1050. });
  1051.  
  1052. pcmd2.onexec((string response2) => { });
  1053.  
  1054. pcmd2.execute = true;
  1055. pcmd2.push(unturnedclass);
  1056.  
  1057. });
  1058.  
  1059. pcmd.execute = true;
  1060.  
  1061. pcmd.push(unturnedclass); // Sends it to the main unturned thread
  1062. }
  1063. else
  1064. {
  1065. for (int i = 0; i < this.custom_commands.Count; i++)
  1066. {
  1067. kIRC_Commands refer = this.custom_commands[i];
  1068.  
  1069. if (refer.BotCommand.ToLower().Trim() == cmd)
  1070. {
  1071. bool hasperms = false;
  1072. if (refer.FlagNeeded == "q")
  1073. hasperms = IsOwner(user);
  1074. else if (refer.FlagNeeded == "a")
  1075. hasperms = IsAdmin(user);
  1076. else if (refer.FlagNeeded == "o")
  1077. hasperms = IsOp(user);
  1078. else if (refer.FlagNeeded == "h")
  1079. hasperms = IsHalfOp(user);
  1080. else if (refer.FlagNeeded == "v")
  1081. hasperms = IsVoice(user);
  1082. else
  1083. hasperms = false;
  1084.  
  1085. if (hasperms)
  1086. {
  1087. kIRC_PushCommand pcmd = new kIRC_PushCommand();
  1088. pcmd.command = refer.ConsoleCommand;
  1089. pcmd.parameters = (!String.IsNullOrEmpty(msg) && msg.Split(this._parameter_delimiter).Length > 0) ? msg.Split(this._parameter_delimiter) : new string[] { };
  1090. pcmd.extradata.Add("Syntax", refer.BotSyntax);
  1091. pcmd.onfire(() =>
  1092. {
  1093. if (!String.IsNullOrEmpty(refer.IRCmsg_onfire.Trim()))
  1094. {
  1095. this.Say(this._channel, refer.IRCmsg_onfire);
  1096. }
  1097. if (!String.IsNullOrEmpty(refer.GAMEmsg_onfire.Trim()))
  1098. {
  1099. UnturnedChat.Say(refer.GAMEmsg_onfire);
  1100. }
  1101. });
  1102. pcmd.onexec((string response) =>
  1103. {
  1104. if (!String.IsNullOrEmpty(refer.IRCmsg_onexec.Trim()))
  1105. {
  1106. this.Say(this._channel, refer.IRCmsg_onexec);
  1107. }
  1108. if (!String.IsNullOrEmpty(refer.GAMEmsg_onexec.Trim()))
  1109. {
  1110. UnturnedChat.Say(refer.GAMEmsg_onexec);
  1111. }
  1112.  
  1113. if (refer.printresponse == true)
  1114. this.Say(this._channel, "Response from (" + cmd + "): " + response);
  1115. });
  1116.  
  1117. pcmd.execute = true;
  1118.  
  1119. pcmd.push(unturnedclass); // Sends it to the main unturned thread
  1120.  
  1121. }
  1122.  
  1123. break;
  1124. }
  1125. }
  1126. }*/
  1127. }
  1128. }
  1129. }
  1130.  
  1131. public bool IsOwner(string name, bool actualrank = true)
  1132. {
  1133. for (int i = 0; i < this.userlist.Count; i++)
  1134. {
  1135. if (this.userlist[i][0] == name)
  1136. {
  1137. if (this.allow_adminowner || actualrank)
  1138. return userlist[i][1] == "~";
  1139. else
  1140. return userlist[i][1] == "@";
  1141. }
  1142. }
  1143. return false;
  1144. }
  1145.  
  1146. public bool IsAdmin(string name, bool actualrank = true)
  1147. {
  1148. for (int i = 0; i < this.userlist.Count; i++)
  1149. {
  1150. if (this.userlist[i][0] == name)
  1151. {
  1152. if (this.allow_adminowner || actualrank)
  1153. return userlist[i][1] == "&" || userlist[i][1] == "~";
  1154. else
  1155. return userlist[i][1] == "@";
  1156. }
  1157. }
  1158. return false;
  1159. }
  1160.  
  1161. public bool IsOp(string name, bool actualrank = true)
  1162. {
  1163. for (int i = 0; i < this.userlist.Count; i++)
  1164. {
  1165. if (this.userlist[i][0] == name)
  1166. {
  1167. if (this.allow_adminowner || actualrank)
  1168. return userlist[i][1] == "@" || userlist[i][1] == "&" || userlist[i][1] == "~";
  1169. else
  1170. return userlist[i][1] == "%" || userlist[i][1] == "@";
  1171. }
  1172. }
  1173. return false;
  1174. }
  1175.  
  1176. public bool IsHalfOp(string name, bool actualrank = true)
  1177. {
  1178. for (int i = 0; i < this.userlist.Count; i++)
  1179. {
  1180. if (this.userlist[i][0] == name)
  1181. {
  1182. if (this.allow_adminowner || actualrank)
  1183. return userlist[i][1] == "%" || userlist[i][1] == "@" || userlist[i][1] == "&" || userlist[i][1] == "~";
  1184. else
  1185. return userlist[i][1] == "%" || userlist[i][1] == "@";
  1186. }
  1187. }
  1188. return false;
  1189. }
  1190.  
  1191. public bool IsVoice(string name, bool actualrank = true)
  1192. {
  1193. for (int i = 0; i < this.userlist.Count; i++)
  1194. {
  1195. if (this.userlist[i][0] == name)
  1196. {
  1197. if (this.allow_adminowner || actualrank)
  1198. return userlist[i][1] == "+" || userlist[i][1] == "%" || userlist[i][1] == "@" || userlist[i][1] == "&" || userlist[i][1] == "~";
  1199. else
  1200. return userlist[i][1] == "+" || userlist[i][1] == "%" || userlist[i][1] == "@";
  1201. }
  1202. }
  1203. return false;
  1204. }
  1205.  
  1206. public void SetCommandPrefix(char prefix)
  1207. {
  1208. this._command_prefix = prefix;
  1209. }
  1210.  
  1211. public void SetParameterDelimiter(char delimiter)
  1212. {
  1213. this._parameter_delimiter = delimiter;
  1214. }
  1215.  
  1216. public void SetAllowAdminOwner(bool allow)
  1217. {
  1218. this.allow_adminowner = allow;
  1219. }
  1220.  
  1221. //public void SetCustomCommands(List<kIRC_Commands> cc)
  1222. //{
  1223. // this.custom_commands = cc;
  1224. //}
  1225.  
  1226. public void SendSyntax(string channel, string command, string[] parameters)
  1227. {
  1228. string _parameters = "";
  1229. for (int i = 0; i < parameters.Length; i++)
  1230. {
  1231. _parameters += "<" + parameters[i] + ">";
  1232. if (i != (parameters.Length - 1))
  1233. _parameters += this._parameter_delimiter;
  1234. }
  1235.  
  1236. this.Say(channel, "Syntax: " + this._command_prefix + command + " " + _parameters);
  1237. return;
  1238. }
  1239.  
  1240. public void loopparsing(Kirc uclass)
  1241. {
  1242. while (isConnected)
  1243. {
  1244. try {
  1245. this.parse(this.Read(), uclass);
  1246. }
  1247. catch
  1248. {
  1249. isConnected = false;
  1250. }
  1251. }
  1252. }
  1253. }
  1254.  
  1255. class DeathNotes //: RustPlugin
  1256. {
  1257. static bool debug = false;
  1258.  
  1259. static Dictionary<ulong, bool> canRead = new Dictionary<ulong, bool>();
  1260. static Dictionary<ulong, HitInfo> LastWounded = new Dictionary<ulong, HitInfo>();
  1261.  
  1262. static public Oxide.Core.Configuration.DynamicConfigFile _Config
  1263. {
  1264. get
  1265. {
  1266. return Kirc.dis.Config;
  1267. }
  1268. }
  1269.  
  1270. ////////////////////////////////////////
  1271. /// Classes
  1272. ////////////////////////////////////////
  1273.  
  1274. class Attacker
  1275. {
  1276. public string name = string.Empty;
  1277. [JsonIgnore]
  1278. public BaseCombatEntity entity = new BaseCombatEntity();
  1279. public AttackerType type = AttackerType.Invalid;
  1280.  
  1281. public string TryGetName()
  1282. {
  1283. if (type == AttackerType.Player)
  1284. return entity?.ToPlayer().displayName;
  1285. else if (type == AttackerType.Helicopter)
  1286. return "Patrol Helicopter";
  1287. else if (type == AttackerType.Turret)
  1288. return "Auto Turret";
  1289. else if (type == AttackerType.Self)
  1290. return "himself";
  1291. else if (type == AttackerType.Animal)
  1292. {
  1293. if ((bool)entity?.name?.Contains("boar"))
  1294. return "Boar";
  1295. else if ((bool)entity?.name?.Contains("horse"))
  1296. return "Horse";
  1297. else if ((bool)entity?.name?.Contains("wolf"))
  1298. return "Wolf";
  1299. else if ((bool)entity?.name?.Contains("stag"))
  1300. return "Stag";
  1301. else if ((bool)entity?.name?.Contains("chicken"))
  1302. return "Chicken";
  1303. else if ((bool)entity?.name?.Contains("bear"))
  1304. return "Bear";
  1305. }
  1306. else if (type == AttackerType.Structure)
  1307. {
  1308. if ((bool)entity?.name?.Contains("barricade.wood.prefab"))
  1309. return "Wooden Barricade";
  1310. else if ((bool)entity?.name?.Contains("barricade.woodwire.prefab"))
  1311. return "Barbed Wooden Barricade";
  1312. else if ((bool)entity?.name?.Contains("barricade.metal.prefab"))
  1313. return "Metal Barricade";
  1314. else if ((bool)entity?.name?.Contains("wall.external.high.wood.prefab"))
  1315. return "High External Wooden Wall";
  1316. else if ((bool)entity?.name?.Contains("wall.external.high.stone.prefab"))
  1317. return "High External Stone Wall";
  1318. else if ((bool)entity?.name?.Contains("gate.external.high.wood.prefab"))
  1319. return "High External Wooden Gate";
  1320. else if ((bool)entity?.name?.Contains("gate.external.high.wood.prefab"))
  1321. return "High External Stone Gate";
  1322. }
  1323. else if (type == AttackerType.Trap)
  1324. {
  1325. if ((bool)entity?.name?.Contains("beartrap.prefab"))
  1326. return "Snap Trap";
  1327. else if ((bool)entity?.name?.Contains("landmine.prefab"))
  1328. return "Land Mine";
  1329. else if ((bool)entity?.name?.Contains("spikes.floor.prefab"))
  1330. return "Wooden Floor Spikes";
  1331. }
  1332.  
  1333. return "No Attacker";
  1334. }
  1335.  
  1336. public AttackerType TryGetType()
  1337. {
  1338. if (entity == null)
  1339. return AttackerType.Invalid;
  1340. else if (entity?.ToPlayer() != null)
  1341. return AttackerType.Player;
  1342. else if ((bool)entity?.name?.Contains("patrolhelicopter.prefab"))
  1343. return AttackerType.Helicopter;
  1344. else if ((bool)entity?.name?.Contains("animals/"))
  1345. return AttackerType.Animal;
  1346. else if ((bool)entity?.name?.Contains("barricades/") || (bool)entity?.name?.Contains("wall.external.high"))
  1347. return AttackerType.Structure;
  1348. else if ((bool)entity?.name?.Contains("beartrap.prefab") || (bool)entity?.name?.Contains("landmine.prefab") || (bool)entity?.name?.Contains("spikes.floor.prefab"))
  1349. return AttackerType.Trap;
  1350. else if ((bool)entity?.name?.Contains("autoturret_deployed.prefab"))
  1351. return AttackerType.Turret;
  1352.  
  1353. return AttackerType.Invalid;
  1354. }
  1355. }
  1356.  
  1357. class Victim
  1358. {
  1359. public string name = string.Empty;
  1360. [JsonIgnore]
  1361. public BaseCombatEntity entity = new BaseCombatEntity();
  1362. public VictimType type = VictimType.Invalid;
  1363.  
  1364. public string TryGetName()
  1365. {
  1366. if (type == VictimType.Player)
  1367. return entity?.ToPlayer().displayName;
  1368. else if (type == VictimType.Helicopter)
  1369. return "Patrol Helicopter";
  1370. else if (type == VictimType.Animal)
  1371. {
  1372. if ((bool)entity?.name?.Contains("boar"))
  1373. return "Boar";
  1374. else if ((bool)entity?.name?.Contains("horse"))
  1375. return "Horse";
  1376. else if ((bool)entity?.name?.Contains("wolf"))
  1377. return "Wolf";
  1378. else if ((bool)entity?.name?.Contains("stag"))
  1379. return "Stag";
  1380. else if ((bool)entity?.name?.Contains("chicken"))
  1381. return "Chicken";
  1382. else if ((bool)entity?.name?.Contains("bear"))
  1383. return "Bear";
  1384.  
  1385. }
  1386.  
  1387. return "No Victim";
  1388. }
  1389.  
  1390. public VictimType TryGetType()
  1391. {
  1392. if (entity?.ToPlayer() != null)
  1393. return VictimType.Player;
  1394. else if ((bool)entity?.name?.Contains("patrolhelicopter.prefab"))
  1395. return VictimType.Helicopter;
  1396. else if ((bool)entity?.name?.Contains("animals/"))
  1397. return VictimType.Animal;
  1398.  
  1399. return VictimType.Invalid;
  1400. }
  1401. }
  1402.  
  1403. class DeathData
  1404. {
  1405. public Victim victim = new Victim();
  1406. public Attacker attacker = new Attacker();
  1407. public DeathReason reason = DeathReason.Unknown;
  1408. public string damageType = string.Empty;
  1409. public string weapon = string.Empty;
  1410. public List<string> attachments = new List<string>();
  1411. public string bodypart = string.Empty;
  1412.  
  1413. public float distance
  1414. {
  1415. get
  1416. {
  1417. try
  1418. {
  1419. foreach (string death in new List<string> { "Cold", "Drowned", "Heat", "Suicide", "Generic", "Posion", "Radiation", "Thirst", "Hunger", "Fall" })
  1420. {
  1421. if (reason == GetDeathReason(death))
  1422. attacker.entity = victim.entity;
  1423. }
  1424.  
  1425. return victim.entity.Distance(attacker.entity.transform.position);
  1426. }
  1427. catch (Exception)
  1428. {
  1429. return 0f;
  1430. }
  1431. }
  1432. }
  1433.  
  1434. public DeathReason TryGetReason()
  1435. {
  1436. if (victim.type == VictimType.Helicopter)
  1437. return DeathReason.HelicopterDeath;
  1438. else if (attacker.type == AttackerType.Helicopter)
  1439. return DeathReason.Helicopter;
  1440. else if (attacker.type == AttackerType.Turret)
  1441. return DeathReason.Turret;
  1442. else if (attacker.type == AttackerType.Trap)
  1443. return DeathReason.Trap;
  1444. else if (attacker.type == AttackerType.Structure)
  1445. return DeathReason.Structure;
  1446. else if (attacker.type == AttackerType.Animal)
  1447. return DeathReason.Animal;
  1448. else if (victim.type == VictimType.Animal)
  1449. return DeathReason.AnimalDeath;
  1450. else if (weapon == "F1 Grenade")
  1451. return DeathReason.Explosion;
  1452. else if (victim.type == VictimType.Player)
  1453. return GetDeathReason(damageType);
  1454.  
  1455. return DeathReason.Unknown;
  1456. }
  1457.  
  1458. public DeathReason GetDeathReason(string damage)
  1459. {
  1460. //Interface.Oxide.RootPluginManager.GetPlugin("DeathNotes").Call("BroadcastChat", "GetDeathReason");
  1461. List<DeathReason> Reason = (from DeathReason current in Enum.GetValues(typeof(DeathReason)) where current.ToString() == damage select current).ToList();
  1462.  
  1463. if (Reason.Count == 0)
  1464. return DeathReason.Unknown;
  1465.  
  1466. return Reason[0];
  1467. }
  1468.  
  1469. [JsonIgnore]
  1470. internal string JSON
  1471. {
  1472. get
  1473. {
  1474. return JsonConvert.SerializeObject(this, Formatting.Indented);
  1475. }
  1476. }
  1477. }
  1478.  
  1479. ////////////////////////////////////////
  1480. /// Enums / Types
  1481. ////////////////////////////////////////
  1482.  
  1483. enum VictimType
  1484. {
  1485. Player,
  1486. Helicopter,
  1487. Animal,
  1488. Invalid
  1489. }
  1490.  
  1491. enum AttackerType
  1492. {
  1493. Player,
  1494. Helicopter,
  1495. Animal,
  1496. Turret,
  1497. Structure,
  1498. Trap,
  1499. Self,
  1500. Invalid
  1501. }
  1502.  
  1503. enum DeathReason
  1504. {
  1505. Turret,
  1506. Helicopter,
  1507. HelicopterDeath,
  1508. Structure,
  1509. Trap,
  1510. Animal,
  1511. AnimalDeath,
  1512. Generic,
  1513. Hunger,
  1514. Thirst,
  1515. Cold,
  1516. Drowned,
  1517. Heat,
  1518. Bleeding,
  1519. Poison,
  1520. Suicide,
  1521. Bullet,
  1522. Slash,
  1523. Blunt,
  1524. Fall,
  1525. Radiation,
  1526. Stab,
  1527. Explosion,
  1528. Unknown
  1529. }
  1530.  
  1531. ////////////////////////////////////////
  1532. /// Plugin Related Hooks
  1533. ////////////////////////////////////////
  1534.  
  1535. static public void _Loaded()
  1536. {
  1537. RegisterPerm("see");
  1538.  
  1539. _LoadConfig();
  1540. _LoadData();
  1541. _LoadMessages();
  1542.  
  1543. foreach (BasePlayer player in BasePlayer.activePlayerList)
  1544. if (!canRead.ContainsKey(player.userID) && HasPerm(player.userID, "see"))
  1545. canRead.Add(player.userID, true);
  1546. }
  1547.  
  1548. static public void _OnPlayerInit(BasePlayer player)
  1549. {
  1550. if (!canRead.ContainsKey(player.userID))
  1551. {
  1552. canRead.Add(player.userID, true);
  1553. _SaveData();
  1554. }
  1555. }
  1556.  
  1557. ////////////////////////////////////////
  1558. /// Plugin Related Methods
  1559. ////////////////////////////////////////
  1560.  
  1561. static public void _LoadData()
  1562. {
  1563. canRead = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, bool>>("DeathNotes");
  1564. }
  1565.  
  1566. static public void _SaveData()
  1567. {
  1568. Interface.Oxide.DataFileSystem.WriteObject("DeathNotes", canRead);
  1569. }
  1570.  
  1571. static public void _LoadConfig()
  1572. {
  1573. SetConfig("Settings", "Chat Icon (SteamID)", "76561198077847390");
  1574.  
  1575. SetConfig("Settings", "Message Radius Enabled", false);
  1576. SetConfig("Settings", "Message Radius", 300f);
  1577.  
  1578. SetConfig("Settings", "Log to File", false);
  1579. SetConfig("Settings", "Write to Console", true);
  1580. SetConfig("Settings", "Use Popup Notifications", false);
  1581.  
  1582. SetConfig("Settings", "Title", "Death Notes");
  1583. SetConfig("Settings", "Formatting", "[{Title}]: {Message}");
  1584. SetConfig("Settings", "Console Formatting", "{Message}");
  1585.  
  1586. SetConfig("Settings", "Attachments Split", " | ");
  1587. SetConfig("Settings", "Attachments Formatting", " ({attachments})");
  1588.  
  1589. SetConfig("Settings", "Title Color", "#80D000");
  1590. SetConfig("Settings", "Victim Color", "#C4FF00");
  1591. SetConfig("Settings", "Attacker Color", "#C4FF00");
  1592. SetConfig("Settings", "Weapon Color", "#C4FF00");
  1593. SetConfig("Settings", "Attachments Color", "#C4FF00");
  1594. SetConfig("Settings", "Distance Color", "#C4FF00");
  1595. SetConfig("Settings", "Bodypart Color", "#C4FF00");
  1596. SetConfig("Settings", "Message Color", "#696969");
  1597.  
  1598. SetConfig("Names", new Dictionary<string, object> { });
  1599. SetConfig("Bodyparts", new Dictionary<string, object> { });
  1600. SetConfig("Weapons", new Dictionary<string, object> { });
  1601. SetConfig("Attachments", new Dictionary<string, object> { });
  1602.  
  1603. SetConfig("Messages", "Bleeding", new List<string> { "{victim} bled out." });
  1604. SetConfig("Messages", "Blunt", new List<string> { "{attacker} used a {weapon} to knock {victim} out." });
  1605. SetConfig("Messages", "Bullet", new List<string> { "{victim} was shot in the {bodypart} by {attacker} with a {weapon}{attachments} from {distance}m." });
  1606. SetConfig("Messages", "Cold", new List<string> { "{victim} became an iceblock." });
  1607. SetConfig("Messages", "Drowned", new List<string> { "{victim} tried to swim." });
  1608. SetConfig("Messages", "Explosion", new List<string> { "{victim} was shredded by {attacker}'s {weapon}" });
  1609. SetConfig("Messages", "Fall", new List<string> { "{victim} did a header into the ground." });
  1610. SetConfig("Messages", "Generic", new List<string> { "The death took {victim} with him." });
  1611. SetConfig("Messages", "Heat", new List<string> { "{victim} burned to ashes." });
  1612. SetConfig("Messages", "Helicopter", new List<string> { "{victim} was shot to pieces by a {attacker}." });
  1613. SetConfig("Messages", "HelicopterDeath", new List<string> { "The {victim} was taken down." });
  1614. SetConfig("Messages", "Animal", new List<string> { "A {attacker} followed {victim} until it finally caught him." });
  1615. SetConfig("Messages", "AnimalDeath", new List<string> { "{attacker} killed a {victim} with a {weapon}{attachments} from {distance}m." });
  1616. SetConfig("Messages", "Hunger", new List<string> { "{victim} forgot to eat." });
  1617. SetConfig("Messages", "Poison", new List<string> { "{victim} died after being poisoned." });
  1618. SetConfig("Messages", "Radiation", new List<string> { "{victim} became a bit too radioactive." });
  1619. SetConfig("Messages", "Slash", new List<string> { "{attacker} slashed {victim} in half." });
  1620. SetConfig("Messages", "Stab", new List<string> { "{victim} was stabbed to death by {attacker} using a {weapon}." });
  1621. SetConfig("Messages", "Structure", new List<string> { "A {attacker} impaled {victim}." });
  1622. SetConfig("Messages", "Suicide", new List<string> { "{victim} had enough of life." });
  1623. SetConfig("Messages", "Thirst", new List<string> { "{victim} dried internally." });
  1624. SetConfig("Messages", "Trap", new List<string> { "{victim} ran into a {attacker}" });
  1625. SetConfig("Messages", "Turret", new List<string> { "A {attacker} defended its home against {victim}." });
  1626. SetConfig("Messages", "Unknown", new List<string> { "{victim} died. Nobody knows why, it just happened." });
  1627.  
  1628. Kirc.dis._SaveConfig();
  1629. }
  1630.  
  1631. static public void _LoadMessages()
  1632. {
  1633. Kirc.dis._lang.RegisterMessages(new Dictionary<string, string>
  1634. {
  1635. {"No Permission", "You don't have permission to use this command."},
  1636. {"Hidden", "You do no longer see death messages."},
  1637. {"Unhidden", "You will now see death messages."}
  1638. }, Kirc.dis);
  1639. }
  1640.  
  1641. ////////////////////////////////////////
  1642. /// DeathNotes Information
  1643. ////////////////////////////////////////
  1644.  
  1645. static public void _GetInfo(BasePlayer player)
  1646. {
  1647. /*webrequest.EnqueueGet("http://oxidemod.org/plugins/819/", (code, response) => {
  1648. if (code != 200)
  1649. {
  1650. PrintWarning("Failed to get information!");
  1651. return;
  1652. }
  1653.  
  1654. string version_published = "0.0.0";
  1655. string version_installed = this.Version.ToString();
  1656.  
  1657. Match version = new Regex(@"<h3>Version (\d{1,2}\.\d{1,2}(\.\d{1,2})?)<\/h3>").Match(response);
  1658. if (version.Success)
  1659. {
  1660. version_published = version.Groups[1].ToString();
  1661. }
  1662.  
  1663. SendChatMessage(player, $"<size=25><color=#C4FF00>DeathNotes</color></size> <size=20><color=#696969>by LaserHydra</color>{Environment.NewLine}<color=#696969>Latest <color=#C4FF00>{version_published}</color>{Environment.NewLine}Installed <color=#C4FF00>{version_installed}</color></color></size>");
  1664. }, this);*/
  1665. }
  1666.  
  1667. ////////////////////////////////////////
  1668. /// Death Related
  1669. ////////////////////////////////////////
  1670.  
  1671. static public HitInfo TryGetLastWounded(ulong uid, HitInfo info)
  1672. {
  1673. if (LastWounded.ContainsKey(uid))
  1674. {
  1675. HitInfo output = LastWounded[uid];
  1676. LastWounded.Remove(uid);
  1677. return output;
  1678. }
  1679.  
  1680. return info;
  1681. }
  1682.  
  1683. static public void _OnEntityTakeDamage(BaseCombatEntity victim, HitInfo info)
  1684. {
  1685. if (victim != null && victim.ToPlayer() != null && info != null && info?.Initiator != null && info?.Initiator?.ToPlayer() != null)
  1686. {
  1687. Kirc.dis._NextTick(() =>
  1688. {
  1689. if (victim.ToPlayer().IsWounded())
  1690. LastWounded[victim.ToPlayer().userID] = info;
  1691. });
  1692. }
  1693. }
  1694.  
  1695. static public void _OnEntityDeath(BaseCombatEntity victim, HitInfo info)
  1696. {
  1697. if (victim == null)
  1698. return;
  1699.  
  1700. if (victim.ToPlayer() != null)
  1701. {
  1702. if (victim.ToPlayer().IsWounded())
  1703. info = TryGetLastWounded(victim.ToPlayer().userID, info);
  1704. }
  1705.  
  1706. if (info?.Initiator?.ToPlayer() == null && (bool)victim?.name?.Contains("autospawn"))
  1707. return;
  1708.  
  1709. DeathData data = new DeathData();
  1710. data.victim.entity = victim;
  1711. data.victim.type = data.victim.TryGetType();
  1712.  
  1713. if (data.victim.type == VictimType.Invalid)
  1714. return;
  1715.  
  1716. data.victim.name = data.victim.TryGetName();
  1717.  
  1718. if (info?.Initiator != null)
  1719. data.attacker.entity = info?.Initiator as BaseCombatEntity;
  1720. else
  1721. data.attacker.entity = victim.lastAttacker as BaseCombatEntity;
  1722.  
  1723. data.attacker.type = data.attacker.TryGetType();
  1724. data.attacker.name = data.attacker.TryGetName();
  1725. data.weapon = info?.Weapon?.GetItem()?.info?.displayName?.english ?? FormatThrownWeapon(info?.WeaponPrefab?.name ?? "No Weapon");
  1726. data.attachments = GetAttachments(info);
  1727. data.damageType = FirstUpper(victim.lastDamage.ToString());
  1728.  
  1729. if (data.weapon == "Heli Rocket")
  1730. {
  1731. data.attacker.name = "Patrol Helicopter";
  1732. data.reason = DeathReason.Helicopter;
  1733. }
  1734.  
  1735. if (info?.HitBone != null)
  1736. data.bodypart = FirstUpper(GetBoneName(victim, ((uint)info?.HitBone)) ?? string.Empty);
  1737. else
  1738. data.bodypart = FirstUpper("Body") ?? string.Empty;
  1739.  
  1740. data.reason = data.TryGetReason();
  1741.  
  1742. DeathData newData = UpdateData(data);
  1743.  
  1744. if (string.IsNullOrEmpty(GetDeathMessage(newData, false)))
  1745. return;
  1746.  
  1747. foreach (BasePlayer player in BasePlayer.activePlayerList)
  1748. {
  1749. if (!canRead.ContainsKey(player.userID) && HasPerm(player.userID, "see"))
  1750. canRead.Add(player.userID, true);
  1751.  
  1752. if (HasPerm(player.userID, "see") && InRadius(player, data.attacker.entity) && canRead.ContainsKey(player.userID) && canRead[player.userID])
  1753. //SendChatMessage(player, GetDeathMessage(newData, false), null, GetConfig("76561198077847390", "Settings", "Chat Icon (SteamID)"));
  1754. Kirc.dis.irc.Say((string)Kirc.dis.Config["channel"], GetDeathMessage(newData, false));
  1755. }
  1756.  
  1757. if (GetConfig(true, "Settings", "Write to Console"))
  1758. Kirc.dis.Log(StripTags(GetDeathMessage(newData, true)));
  1759.  
  1760. if (GetConfig(false, "Settings", "Log to File"))
  1761. ConVar.Server.Log("oxide/logs/Kills.txt", StripTags(GetDeathMessage(newData, true)));
  1762.  
  1763. if (debug)
  1764. {
  1765. Kirc.dis.Log("DATA: " + Environment.NewLine + data.JSON);
  1766. Kirc.dis.Log("UPDATED DATA: " + Environment.NewLine + newData.JSON);
  1767. }
  1768. }
  1769.  
  1770. ////////////////////////////////////////
  1771. /// Formatting Methods
  1772. ////////////////////////////////////////
  1773.  
  1774. static string FormatThrownWeapon(string unformatted)
  1775. {
  1776. if (unformatted == string.Empty)
  1777. return string.Empty;
  1778.  
  1779. string formatted = FirstUpper(unformatted.Split('/').Last().Replace(".prefab", "").Replace(".entity", ""));
  1780.  
  1781. if (formatted == "Knife Bone")
  1782. formatted = "Bone Knife";
  1783. else if (formatted == "Spear Wooden")
  1784. formatted = "Wooden Spear";
  1785. else if (formatted == "Spear Stone")
  1786. formatted = "Stone Spear";
  1787. else if (formatted == "Axe Salvaged")
  1788. formatted = "Salvaged Axe";
  1789. else if (formatted == "Hammer Salvaged")
  1790. formatted = "Salvaged Hammer";
  1791. else if (formatted == "Icepick Salvaged")
  1792. formatted = "Salvaged Icepick";
  1793. else if (formatted == "Stonehatchet")
  1794. formatted = "Stone Hatchet";
  1795. else if (formatted == "Explosive Timed")
  1796. formatted = "Timed Explosive Charge";
  1797. else if (formatted == "Grenade F1")
  1798. formatted = "F1 Grenade";
  1799. else if (formatted == "Rocket Heli")
  1800. formatted = "Heli Rocket";
  1801. else if (formatted == "Rocket Hv")
  1802. formatted = "HV-Rocket";
  1803. else if (formatted == "Rocket basic")
  1804. formatted = "Rocket";
  1805. else if (formatted == "Rocket Fire")
  1806. formatted = "Incendiary Rocket";
  1807.  
  1808. return formatted;
  1809. }
  1810.  
  1811. static string StripTags(string original)
  1812. {
  1813. List<string> regexTags = new List<string>
  1814. {
  1815. @"<color=.+?>",
  1816. @"<size=.+?>"
  1817. };
  1818.  
  1819. List<string> tags = new List<string>
  1820. {
  1821. "</color>",
  1822. "</size>",
  1823. "<i>",
  1824. "</i>",
  1825. "<b>",
  1826. "</b>"
  1827. };
  1828.  
  1829. foreach (string tag in tags)
  1830. original = original.Replace(tag, "");
  1831.  
  1832. foreach (string regexTag in regexTags)
  1833. original = new Regex(regexTag).Replace(original, "");
  1834.  
  1835. return original;
  1836. }
  1837.  
  1838. static string FirstUpper(string original)
  1839. {
  1840. if (original == string.Empty)
  1841. return string.Empty;
  1842.  
  1843. List<string> output = new List<string>();
  1844. foreach (string word in original.Split(' '))
  1845. output.Add(word.Substring(0, 1).ToUpper() + word.Substring(1, word.Length - 1));
  1846.  
  1847. return ListToString(output, 0, " ");
  1848. }
  1849.  
  1850. ////////////////////////////////////////
  1851. /// Death Variables Methods
  1852. ////////////////////////////////////////
  1853.  
  1854. static List<string> GetAttachments(HitInfo info)
  1855. {
  1856. List<string> attachments = new List<string>();
  1857.  
  1858. if (info?.Weapon?.GetItem()?.contents?.itemList != null)
  1859. {
  1860. foreach (var content in info?.Weapon?.GetItem().contents?.itemList as List<Item>)
  1861. {
  1862. attachments.Add(content?.info?.displayName?.english);
  1863. }
  1864. }
  1865.  
  1866. return attachments;
  1867. }
  1868.  
  1869. static string GetBoneName(BaseCombatEntity entity, uint boneId)
  1870. {
  1871. return entity?.skeletonProperties?.FindBone(boneId)?.name?.english ?? "Body";
  1872. }
  1873.  
  1874. static bool InRadius(BasePlayer player, BaseCombatEntity attacker)
  1875. {
  1876. if (GetConfig(false, "Settings", "Message Radius Enabled"))
  1877. {
  1878. try
  1879. {
  1880. if (player.Distance(attacker) <= GetConfig(300f, "Settings", "Message Radius"))
  1881. return true;
  1882. else
  1883. return false;
  1884. }
  1885. catch (Exception)
  1886. {
  1887. return false;
  1888. }
  1889. }
  1890.  
  1891. return true;
  1892. }
  1893.  
  1894. static string GetDeathMessage(DeathData data, bool console)
  1895. {
  1896. string message = string.Empty;
  1897. List<string> messages = new List<string>();
  1898.  
  1899. try
  1900. {
  1901. messages = GetConfig(new List<string>(), "Messages", data.reason.ToString());
  1902. }
  1903. catch (InvalidCastException)
  1904. {
  1905. messages = (from msg in GetConfig(new List<object>(), "Messages", data.reason.ToString()) select msg.ToString()).ToList();
  1906. }
  1907.  
  1908. if (messages.Count == 0)
  1909. return message;
  1910.  
  1911. string attachmentsString = data.attachments.Count == 0 ? string.Empty : GetConfig(" ({attachments})", "Settings", "Attachments Formatting").Replace("{attachments}", ListToString(data.attachments, 0, GetConfig(" | ", "Settings", "Attachments Split")));
  1912.  
  1913. if (console)
  1914. message = GetConfig("{Message}", "Settings", "Console Formatting").Replace("{Title}", $"<color={GetConfig("#80D000", "Settings", "Title Color")}>{GetConfig("Death Notes", "Settings", "Title")}</color>").Replace("{Message}", $"<color={GetConfig("#696969", "Settings", "Message Color")}>{messages[UnityEngine.Random.Range(0, messages.Count - 1)].ToString()}</color>");
  1915. else
  1916. message = GetConfig("[{Title}]: {Message}", "Settings", "Formatting").Replace("{Title}", $"<color={GetConfig("#80D000", "Settings", "Title Color")}>{GetConfig("Death Notes", "Settings", "Title")}</color>").Replace("{Message}", $"<color={GetConfig("#696969", "Settings", "Message Color")}>{messages[UnityEngine.Random.Range(0, messages.Count - 1)].ToString()}</color>");
  1917.  
  1918. message = message.Replace("{attacker}", $"<color={GetConfig("#C4FF00", "Settings", "Attacker Color")}>{data.attacker.name}</color>");
  1919. message = message.Replace("{victim}", $"<color={GetConfig("#C4FF00", "Settings", "Victim Color")}>{data.victim.name}</color>");
  1920. message = message.Replace("{distance}", $"<color={GetConfig("#C4FF00", "Settings", "Distance Color")}>{Math.Round(data.distance, 2).ToString()}</color>");
  1921. message = message.Replace("{weapon}", $"<color={GetConfig("#C4FF00", "Settings", "Weapon Color")}>{data.weapon}</color>");
  1922. message = message.Replace("{bodypart}", $"<color={GetConfig("#C4FF00", "Settings", "Bodypart Color")}>{data.bodypart}</color>");
  1923. message = message.Replace("{attachments}", $"<color={GetConfig("#C4FF00", "Settings", "Attachments Color")}>{attachmentsString}</color>");
  1924.  
  1925. return message;
  1926. }
  1927.  
  1928. static DeathData UpdateData(DeathData data)
  1929. {
  1930. bool configUpdated = false;
  1931.  
  1932. if (data.victim.type != VictimType.Player)
  1933. {
  1934. if (_Config.Get("Names", data.victim.name) == null)
  1935. {
  1936. SetConfig("Names", data.victim.name, data.victim.name);
  1937. configUpdated = true;
  1938. }
  1939. else
  1940. data.victim.name = GetConfig(data.victim.name, "Names", data.victim.name);
  1941. }
  1942.  
  1943. if (data.attacker.type != AttackerType.Player)
  1944. {
  1945. if (_Config.Get("Names", data.attacker.name) == null)
  1946. {
  1947. SetConfig("Names", data.attacker.name, data.attacker.name);
  1948. configUpdated = true;
  1949. }
  1950. else
  1951. data.attacker.name = GetConfig(data.attacker.name, "Names", data.attacker.name);
  1952. }
  1953.  
  1954. if (_Config.Get("Bodyparts", data.bodypart) == null)
  1955. {
  1956. SetConfig("Bodyparts", data.bodypart, data.bodypart);
  1957. configUpdated = true;
  1958. }
  1959. else
  1960. data.bodypart = GetConfig(data.bodypart, "Bodyparts", data.bodypart);
  1961.  
  1962. if (_Config.Get("Weapons", data.weapon) == null)
  1963. {
  1964. SetConfig("Weapons", data.weapon, data.weapon);
  1965. configUpdated = true;
  1966. }
  1967. else
  1968. data.weapon = GetConfig(data.weapon, "Weapons", data.weapon);
  1969.  
  1970. string[] attachmentsCopy = new string[data.attachments.Count];
  1971. data.attachments.CopyTo(attachmentsCopy);
  1972.  
  1973. foreach (string attachment in attachmentsCopy)
  1974. {
  1975. if (_Config.Get("Attachments", attachment) == null)
  1976. {
  1977. SetConfig("Attachments", attachment, attachment);
  1978. configUpdated = true;
  1979. }
  1980. else
  1981. {
  1982. data.attachments.Remove(attachment);
  1983. data.attachments.Add(GetConfig(attachment, "Attachments", attachment));
  1984. }
  1985. }
  1986.  
  1987. if (configUpdated)
  1988. Kirc.dis._SaveConfig();
  1989.  
  1990. return data;
  1991. }
  1992.  
  1993. ////////////////////////////////////////
  1994. /// Converting
  1995. ////////////////////////////////////////
  1996.  
  1997. static string ListToString(List<string> list, int first, string seperator)
  1998. {
  1999. return String.Join(seperator, list.Skip(first).ToArray());
  2000. }
  2001.  
  2002. ////////////////////////////////////////
  2003. /// Config & Message Related
  2004. ////////////////////////////////////////
  2005.  
  2006. static void SetConfig(params object[] args)
  2007. {
  2008. List<string> stringArgs = (from arg in args select arg.ToString()).ToList<string>();
  2009. stringArgs.RemoveAt(args.Length - 1);
  2010.  
  2011. if (_Config.Get(stringArgs.ToArray()) == null) _Config.Set(args);
  2012. }
  2013.  
  2014. static T GetConfig<T>(T defaultVal, params object[] args)
  2015. {
  2016. List<string> stringArgs = (from arg in args select arg.ToString()).ToList<string>();
  2017. if (_Config.Get(stringArgs.ToArray()) == null)
  2018. {
  2019. Kirc.dis.Log($"The plugin failed to read something from the config: {ListToString(stringArgs, 0, "/")}{Environment.NewLine}Please reload the plugin and see if this message is still showing. If so, please post this into the support thread of this plugin.");
  2020. return defaultVal;
  2021. }
  2022.  
  2023. return (T)Convert.ChangeType(_Config.Get(stringArgs.ToArray()), typeof(T));
  2024. }
  2025.  
  2026. static string GetMsg(string key, object userID = null)
  2027. {
  2028. return Kirc.dis._lang.GetMessage(key, Kirc.dis, userID.ToString());
  2029. }
  2030.  
  2031. ////////////////////////////////////////
  2032. /// Permission Related
  2033. ////////////////////////////////////////
  2034.  
  2035. static void RegisterPerm(params string[] permArray)
  2036. {
  2037. string perm = ListToString(permArray.ToList(), 0, ".");
  2038.  
  2039. Kirc.dis._permission.RegisterPermission($"{PermissionPrefix}.{perm}", Kirc.dis);
  2040. }
  2041.  
  2042. static bool HasPerm(object uid, params string[] permArray)
  2043. {
  2044. uid = uid.ToString();
  2045. string perm = ListToString(permArray.ToList(), 0, ".");
  2046.  
  2047. return Kirc.dis._permission.UserHasPermission(uid.ToString(), $"{PermissionPrefix}.{perm}");
  2048. }
  2049.  
  2050. static string PermissionPrefix
  2051. {
  2052. get
  2053. {
  2054. return Kirc.dis.Title.Replace(" ", "").ToLower();
  2055. }
  2056. }
  2057.  
  2058. ////////////////////////////////////////
  2059. /// Chat Handling
  2060. ////////////////////////////////////////
  2061.  
  2062. static public void BroadcastChat(string prefix, string msg = null) => Kirc.dis._rust.BroadcastChat(msg == null ? prefix : "<color=#C4FF00>" + prefix + "</color>: " + msg);
  2063.  
  2064. static public void SendChatMessage(BasePlayer player, string prefix, string msg = null, object uid = null) => Kirc.dis._rust.SendChatMessage(player, msg == null ? prefix : "<color=#C4FF00>" + prefix + "</color>: " + msg, null, uid?.ToString() ?? "0");
  2065. }
  2066. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement