DutyContent/Tab/DutyForm.cs
2021-04-14 10:02:44 +09:00

1563 lines
36 KiB
C#

using DutyContent.Interface;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Http;
using System.Text;
using System.IO;
using System.Threading;
using System.Net.NetworkInformation;
namespace DutyContent.Tab
{
public partial class DutyForm : Form, Interface.ISuppLocale, Interface.IPacketHandler, Interface.ISuppActPlugin
{
private static DutyForm _self;
public static DutyForm Self => _self;
//
private bool _is_lock_fate;
private bool _is_skirmish_area;
private bool _is_packet_finder;
private DcConfig.PacketConfig _new_packet;
private Overlay.DutyOvForm _overlay;
private System.Timers.Timer _ping_timer;
private long _ping_last;
private Color _ping_color = Color.Transparent;
private Libre.PingGrapher _ping_grpr;
private List<int> _ping_keeps = new List<int>() { 0, 0, };
public DutyForm()
{
_self = this;
InitializeComponent();
_overlay = new Overlay.DutyOvForm();
_ping_grpr = new Libre.PingGrapher(pbxPingGraph);
}
private void DutyTabForm_FormClosing(object sender, FormClosingEventArgs e)
{
}
public void PluginInitialize()
{
//
lblCurrentDataSet.Text = DcContent.Language;
//
var lang = MakeDutyLangList();
foreach (var i in lang)
{
var n = cboDataset.Items.Add(i);
if (i.Equals(DcConfig.Duty.Language))
cboDataset.SelectedIndex = n;
}
//
var font = new Font(DcConfig.Duty.LogFontFamily, DcConfig.Duty.LogFontSize, FontStyle.Regular, GraphicsUnit.Point);
txtContentLog.Font = font;
btnLogFont.Font = font;
btnLogFont.Text = $"{DcConfig.Duty.LogFontFamily}, {DcConfig.Duty.LogFontSize}";
//
chkEnableOverlay.Checked = DcConfig.Duty.EnableOverlay;
progbOverlayTransparent.Enabled = DcConfig.Duty.EnableOverlay;
btnOverlayDimming.Enabled = DcConfig.Duty.EnableOverlay;
chkOverlayClickThru.Checked = DcConfig.Duty.OverlayClickThru;
//
_overlay.SetText(MesgLog.Text(99, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()));
_overlay.Location = DcConfig.Duty.OverlayLocation;
if (DcConfig.Duty.EnableOverlay)
_overlay.Show();
else
_overlay.Hide();
//
chkEnableSound.Checked = DcConfig.Duty.EnableSound;
txtSoundInstance.Text = DcConfig.Duty.SoundInstanceFile;
txtSoundInstance.Enabled = DcConfig.Duty.EnableSound;
btnSoundFindInstance.Enabled = DcConfig.Duty.EnableSound;
btnSoundPlayInstance.Enabled = DcConfig.Duty.EnableSound;
txtSoundFate.Text = DcConfig.Duty.SoundFateFile;
txtSoundFate.Enabled = DcConfig.Duty.EnableSound;
btnSoundFindFate.Enabled = DcConfig.Duty.EnableSound;
btnSoundPlayFate.Enabled = DcConfig.Duty.EnableSound;
//
chkUseNotifyLine.Checked = DcConfig.Duty.UseNotifyLine;
txtLineToken.Text = DcConfig.Duty.NotifyLineToken;
//txtLineToken.Enabled = !DcConfig.Duty.UseNotifyLine;
chkUseNotifyTelegram.Checked = DcConfig.Duty.UseNotifyTelegram;
txtTelegramId.Text = DcConfig.Duty.NotifyTelegramId;
txtTelegramToken.Text = DcConfig.Duty.NotifyTelegramToken;
//txtLineToken.Enabled = !DcConfig.Duty.UseNotifyTelegram;
//txtLineToken.Enabled = !DcConfig.Duty.UseNotifyTelegram;
btnTestNotify.Enabled = DcConfig.Duty.EnableNotify;
//
chkUsePing.Checked = DcConfig.Duty.UsePing;
btnPingColor1.BackColor = DcConfig.Duty.PingColors[0];
btnPingColor2.BackColor = DcConfig.Duty.PingColors[1];
btnPingColor3.BackColor = DcConfig.Duty.PingColors[2];
btnPingColor4.BackColor = DcConfig.Duty.PingColors[3];
chkPingGraph.Checked = DcConfig.Duty.PingGraph;
//
switch (DcConfig.Duty.ActiveFate)
{
case 0: rdoFatePreset1.Checked = true; break;
case 1: rdoFatePreset2.Checked = true; break;
case 2: rdoFatePreset3.Checked = true; break;
case 3: rdoFatePreset4.Checked = true; break;
}
UpdateFates();
//
try
{
var svl = File.ReadAllLines(Path.Combine(DcConfig.DataPath, "ServerList.txt"));
int ssv = -1;
for (var i = 0; i < svl.Length; i++)
{
cboPingDefAddr.Items.Add(svl[i]);
if (svl[i].StartsWith(DcConfig.Duty.PingDefAddr))
ssv = i;
}
if (string.IsNullOrEmpty(DcConfig.Duty.PingDefAddr))
ssv = -1;
cboPingDefAddr.SelectedIndex = ssv > 0 ? ssv : 0;
}
catch
{
cboPingDefAddr.Items.Clear();
cboPingDefAddr.Items.Add(MesgLog.Text(27));
cboPingDefAddr.SelectedIndex = 0;
}
//
_ping_timer = new System.Timers.Timer() { Interval = 5000 };
_ping_timer.Elapsed += (sender, e) => PingOnce();
if (DcConfig.Duty.UsePing)
{
PingOnce(false);
_ping_timer.Start();
}
}
public void PluginDeinitialize()
{
if (_ping_timer != null)
{
_ping_timer.Stop();
_ping_timer = null;
}
_overlay.Hide();
_overlay = null;
}
private void SaveConfig(int interval = 5000)
{
DcControl.Self.RefreshSaveConfig(interval);
}
public static List<string> MakeDutyLangList()
{
List<string> lst = new List<string>();
DirectoryInfo di = new DirectoryInfo(DcConfig.DataPath);
foreach (var fi in di.GetFiles("DcDuty-*.json"))
{
var s = fi.Name.Substring(7, fi.Name.Length - 7 - 5);
lst.Add(s);
}
return lst;
}
public void RefreshLocale()
{
}
public void UpdateUiLocale()
{
tabPageContent.Text = MesgLog.Text(301);
tabPageSetting.Text = MesgLog.Text(302);
tabPagePacket.Text = MesgLog.Text(303);
tabPagePing.Text = MesgLog.Text(327);
lblDataSet.Text = MesgLog.Text(304);
lblLogFont.Text = MesgLog.Text(305);
chkEnableOverlay.Text = MesgLog.Text(306);
lblOverlayTransparent.Text = MesgLog.Text(307);
chkOverlayClickThru.Text = MesgLog.Text(104);
chkEnableSound.Text = MesgLog.Text(308);
lblSoundInstance.Text = MesgLog.Text(309);
lblSoundFate.Text = MesgLog.Text(310);
chkUseNotifyLine.Text = MesgLog.Text(311);
lblLineToken.Text = MesgLog.Text(312);
chkUseNotifyTelegram.Text = MesgLog.Text(313);
lblTelegramId.Text = MesgLog.Text(314);
lblTelegramToken.Text = MesgLog.Text(315);
lblPacketFinder.Text = MesgLog.Text(316);
lblPacketDesc.Text = MesgLog.Text(317);
lblPacketBozja.Text = MesgLog.Text(318);
lstPacketInfo.Columns[0].Text = MesgLog.Text(319);
lstPacketInfo.Columns[1].Text = MesgLog.Text(320);
lstPacketInfo.Columns[2].Text = MesgLog.Text(321);
lstPacketInfo.Columns[3].Text = MesgLog.Text(322);
lstBozjaInfo.Columns[0].Text = MesgLog.Text(323);
lstBozjaInfo.Columns[1].Text = MesgLog.Text(324);
lstBozjaInfo.Columns[2].Text = MesgLog.Text(325);
lstBozjaInfo.Columns[3].Text = MesgLog.Text(326);
btnPacketStart.Text = MesgLog.Text(10007);
btnPacketApply.Text = MesgLog.Text(10009);
chkUsePing.Text = MesgLog.Text(328);
lblPingColors.Text = MesgLog.Text(329);
lblPingStat1.Text = MesgLog.Text(330);
lblPingStat2.Text = MesgLog.Text(331);
lblPingStat3.Text = MesgLog.Text(332);
lblPingStat4.Text = MesgLog.Text(333);
chkPingGraph.Text = MesgLog.Text(334);
lblPingDefAddr.Text = MesgLog.Text(335);
}
public void PacketHandler(string pid, byte[] message)
{
if (_is_packet_finder)
PacketFinderHandler(message);
var opcode = BitConverter.ToUInt16(message, 18);
if (opcode != DcConfig.Packet.OpFate &&
opcode != DcConfig.Packet.OpDuty &&
opcode != DcConfig.Packet.OpMatch &&
opcode != DcConfig.Packet.OpInstance &&
opcode != DcConfig.Packet.OpSouthernBozja)
return;
var data = message.Skip(32).ToArray();
// FATE
if (opcode == DcConfig.Packet.OpFate)
{
if (data[0] == 53)
{
var fcode = BitConverter.ToUInt16(data, 4);
if (fcode > 100)
{
var fate = DcContent.GetFate(fcode);
if (_is_skirmish_area)
LogSkirmish(10001, fate.Name);
else
LogFate(10001, fate.Name);
if (DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate].Selected.Contains(fcode))
{
MesgLog.L("{0} - {1}", DcConfig.Duty.ActiveFate, fcode);
PlayEffectSoundFate();
NotifyFate(fate);
_overlay.PlayFate(fate);
}
}
}
}
// Duty
else if (opcode == DcConfig.Packet.OpDuty)
{
var rcode = data[8];
if (rcode != 0)
{
var roulette = DcContent.GetRoulette(rcode);
LogRoulette(10002, roulette.Name);
_overlay.PlayQueue(roulette.Name);
}
else
{
var insts = new List<int>();
for (var i = 0; i < 5; i++)
{
var icode = BitConverter.ToUInt16(data, 12 + (i * 4));
if (icode == 0)
break;
}
if (insts.Any())
{
LogInstance(10002, string.Join("/", insts.ToArray()));
_overlay.PlayQueue(MesgLog.Text(10006, $"#{insts.Count}"));
}
}
DcContent.Missions.Clear();
}
// match
else if (opcode == DcConfig.Packet.OpMatch)
{
var rcode = BitConverter.ToUInt16(data, 2);
var icode = BitConverter.ToUInt16(data, 20);
string name;
if (icode == 0 && rcode != 0)
{
var roulette = DcContent.GetRoulette(rcode);
LogRoulette(10003, roulette.Name);
name = roulette.Name;
}
else if (icode != 0)
{
var instance = DcContent.GetInstance(icode);
LogInstance(10003, instance.Name);
name = instance.Name;
}
else
{
// ???
name = MesgLog.Text(10003, icode);
}
PlayEffecSoundInstance();
NotifyMatch(name);
_overlay.PlayMatch(name);
}
// instance
else if (opcode == DcConfig.Packet.OpInstance && DcConfig.Packet.OpInstance != 0)
{
// 0[2] instance number
// 2[2] ?
// 4[1] 0=enter, 4=enter, 5=leave
if (data[4] == 0)
{
var icode = BitConverter.ToUInt16(data, 0);
var instance = DcContent.GetInstance(icode);
LogInstance(10004, instance.Name);
_overlay.PlayMatch(MesgLog.Text(10004, instance.Name));
DcContent.Missions.Clear();
}
else if (data[4] != 4)
{
_overlay.PlayNone();
}
}
// southen bozja front critical engagement
else if (opcode == DcConfig.Packet.OpSouthernBozja)
{
// 0[4] timestamp
// 4[2] mmss
// 6[2] ?
// 8[1] code
// 9[1] ?
// 10[1] status 0=end, 1=register, 2=entry, 3=progress
// 12[1] progress percentage
var ce = 30000 + data[8];
var stat = data[10];
if (stat == 0 /* || data[10] == 3 */)
{
if (DcContent.Missions.ContainsKey(ce))
DcContent.Missions.Remove(ce);
}
else if (stat == 1 || stat == 2)
{
if (!DcContent.Missions.ContainsKey(ce))
{
DcContent.Missions.Add(ce, 0);
var fate = DcContent.GetFate(ce);
LogCe(10001, fate.Name);
if (DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate].Selected.Contains(ce))
{
PlayEffectSoundFate();
NotifyFate(fate);
_overlay.PlayFate(fate);
}
}
}
else if (stat == 3)
{
if (DcContent.Missions.ContainsKey(ce))
{
DcContent.Missions.Add(ce, 0);
var fate = DcContent.GetFate(ce);
LogCe(10001, fate.Name);
}
}
}
}
//
public void ZoneChanged(uint zone_id, string zone_name)
{
//_overlay.PlayNone();
_is_skirmish_area =
zone_id == 920; // The Bozjan Southern Front
}
//
private void WriteLog(Color color, string category, string format, params object[] prms)
{
if (txtContentLog == null || txtContentLog.IsDisposed || format == null)
return;
var fmt = string.Format(format, prms);
var dt = DateTime.Now.ToString("HH:mm:ss");
var ms = $"[{dt}/{category}] {fmt}{Environment.NewLine}";
WorkerAct.Invoker(() =>
{
txtContentLog.SelectionColor = color;
txtContentLog.SelectionStart = txtContentLog.TextLength;
txtContentLog.SelectionLength = 0;
txtContentLog.AppendText(ms);
txtContentLog.SelectionColor = txtContentLog.ForeColor;
ThirdParty.NativeMethods.ScrollToBottom(txtContentLog);
});
}
private void WriteLog(Color color, int catkey, int fmtkey, params object[] prms)
{
string catergory = MesgLog.Text(catkey);
string format = MesgLog.Text(fmtkey);
WriteLog(color, catergory, format, prms);
}
//
private void LogRoulette(int key, params object[] prms)
{
WriteLog(Color.Black, 21, key, prms);
}
//
private void LogInstance(int key, params object[] prms)
{
WriteLog(Color.Black, 22, key, prms);
}
//
private void LogFate(int key, params object[] prms)
{
WriteLog(Color.Black, 23, key, prms);
}
//
private void LogSkirmish(int key, params object[] prms)
{
WriteLog(Color.Black, 24, key, prms);
}
//
private void LogCe(int key, params object[] prms)
{
WriteLog(Color.Black, 25, key, prms);
}
//
public void UpdateFates()
{
var fs = DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate];
treeFates.Nodes.Clear();
fs.MakeSelects(true);
_is_lock_fate = true;
foreach (var a in DcContent.Areas)
{
var n = treeFates.Nodes.Add(a.Value.Name);
n.Tag = a.Key + 100000;
if (fs.Selected.Contains((int)n.Tag))
{
n.Checked = true;
n.Expand();
}
foreach (var f in a.Value.Fates)
{
var name = f.Value.Name;
var node = n.Nodes.Add(name);
node.Tag = f.Key;
if (fs.Selected.Contains((int)node.Tag))
{
node.Checked = true;
if (!n.IsExpanded)
n.Expand();
}
}
}
MakeFatesSelection();
_is_lock_fate = false;
}
//
private void MakeFatesSelection(bool makeline = false)
{
var fs = DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate];
fs.Selected.Clear();
FateSelectionMakingLoop(treeFates.Nodes);
if (makeline)
fs.MakeLine();
}
//
private void FateSelectionMakingLoop(TreeNodeCollection nodes)
{
var fs = DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate];
foreach (TreeNode n in nodes)
{
if (n.Checked)
fs.Selected.Add((int)n.Tag);
FateSelectionMakingLoop(n.Nodes);
}
}
private void CboDataset_SelectedIndexChanged(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
var l = (string)cboDataset.SelectedItem;
if (!string.IsNullOrWhiteSpace(l) && !l.Equals(DcConfig.Duty.Language) && DcContent.ReadContent(l))
{
UpdateFates();
lblCurrentDataSet.Text = DcContent.Language;
SaveConfig();
}
}
private void BtnLogFont_Click(object sender, EventArgs e)
{
Font ret = (Font)WorkerAct.Invoker(new WorkerAct.ObjectReturnerDelegate(() =>
{
FontDialog dg = new FontDialog
{
Font = txtContentLog.Font,
FontMustExist = true,
AllowVerticalFonts = false
};
return (dg.ShowDialog() == DialogResult.OK) ? dg.Font : null;
}));
if (ret != null)
{
txtContentLog.Font = ret;
DcConfig.Duty.LogFontFamily = ret.Name;
DcConfig.Duty.LogFontSize = ret.Size;
SaveConfig();
btnLogFont.Font = ret;
btnLogFont.Text = $"{DcConfig.Duty.LogFontFamily}, {DcConfig.Duty.LogFontSize}";
}
}
private void TreeFates_AfterCheck(object sender, TreeViewEventArgs e)
{
if (!DcConfig.PluginEnable)
return;
if (_is_lock_fate)
return;
_is_lock_fate = true;
if (((int)e.Node.Tag) > 100000)
{
foreach (TreeNode n in e.Node.Nodes)
n.Checked = e.Node.Checked;
}
else
{
if (!e.Node.Checked)
e.Node.Parent.Checked = false;
else
{
var f = true;
foreach (TreeNode n in e.Node.Parent.Nodes)
f &= n.Checked;
e.Node.Parent.Checked = f;
}
}
MakeFatesSelection(true);
SaveConfig();
_is_lock_fate = false;
}
//
private void ChangeFatePreset(int index)
{
if (!DcConfig.PluginEnable)
return;
if (index >= 0 && index < 4)
{
DcConfig.Duty.ActiveFate = index;
UpdateFates();
SaveConfig();
}
}
private void RdoFatePreset1_CheckedChanged(object sender, EventArgs e)
{
ChangeFatePreset(0);
}
private void RdoFatePreset2_CheckedChanged(object sender, EventArgs e)
{
ChangeFatePreset(1);
}
private void RdoFatePreset3_CheckedChanged(object sender, EventArgs e)
{
ChangeFatePreset(2);
}
private void RdoFatePreset4_CheckedChanged(object sender, EventArgs e)
{
ChangeFatePreset(3);
}
private void ChkEnableOverlay_CheckedChanged(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
progbOverlayTransparent.Enabled = chkEnableOverlay.Checked;
btnOverlayDimming.Enabled = chkEnableOverlay.Checked;
if (chkEnableOverlay.Checked)
_overlay.Show();
else
_overlay.Hide();
DcConfig.Duty.EnableOverlay = chkEnableOverlay.Checked;
SaveConfig();
}
private void ProgbOverlayTransparent_Click(object sender, EventArgs e)
{
}
private void BtnOverlayDimming_Click(object sender, EventArgs e)
{
_overlay.StartBlink();
}
private void ChkOverlayClickThru_CheckedChanged(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
DcConfig.Duty.OverlayClickThru = chkOverlayClickThru.Checked;
SaveConfig();
}
private void ChkEnableSound_CheckedChanged(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
txtSoundInstance.Enabled = chkEnableSound.Checked;
btnSoundFindInstance.Enabled = chkEnableSound.Checked;
btnSoundPlayInstance.Enabled = chkEnableSound.Checked;
txtSoundFate.Enabled = chkEnableSound.Checked;
btnSoundFindFate.Enabled = chkEnableSound.Checked;
btnSoundPlayFate.Enabled = chkEnableSound.Checked;
DcConfig.Duty.EnableSound = chkEnableSound.Checked;
SaveConfig();
}
//
private void PlayEffectSoundFate()
{
if (DcConfig.Duty.EnableSound)
WorkerAct.PlayEffectSound(DcConfig.Duty.SoundFateFile, DcConfig.Duty.SoundFateVolume);
}
//
private void PlayEffecSoundInstance()
{
if (DcConfig.Duty.EnableSound)
WorkerAct.PlayEffectSound(DcConfig.Duty.SoundInstanceFile, DcConfig.Duty.SoundInstanceVolume);
}
private void BtnSoundPlayInstance_Click(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
PlayEffecSoundInstance();
}
private void BtnSoundPlayFate_Click(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
PlayEffectSoundFate();
}
//
private string SoundFileOpenDialog()
{
string filename = (string)WorkerAct.Invoker(new WorkerAct.ObjectReturnerDelegate(() =>
{
var dg = new OpenFileDialog
{
Title = MesgLog.Text(101),
DefaultExt = "wav",
Filter = MesgLog.Text(102)
};
return (dg.ShowDialog() == DialogResult.OK) ? dg.FileName : null;
}));
return filename;
}
private void BtnSoundFindInstance_Click(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
string filename = SoundFileOpenDialog();
DcConfig.Duty.SoundInstanceFile = string.IsNullOrEmpty(filename) ? string.Empty : filename;
txtSoundInstance.Text = DcConfig.Duty.SoundInstanceFile;
SaveConfig();
}
private void BtnSoundFindFate_Click(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
string filename = SoundFileOpenDialog();
DcConfig.Duty.SoundFateFile = string.IsNullOrEmpty(filename) ? string.Empty : filename;
txtSoundFate.Text = DcConfig.Duty.SoundFateFile;
SaveConfig();
}
private async void BtnTestNotify_Click(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
string s = MesgLog.Text(103);
if (DcConfig.Duty.UseNotifyLine)
await NotifyUsingLine(s);
if (DcConfig.Duty.UseNotifyTelegram)
NotifyUsingTelegram(s);
}
//
private void SendNotify(string s)
{
if (DcConfig.Duty.UseNotifyLine)
NotifyUsingLine(s).Wait();
if (DcConfig.Duty.UseNotifyTelegram)
NotifyUsingTelegram(s);
}
//
private void NotifyFate(DcContent.Fate f)
{
if (!DcConfig.Duty.EnableNotify)
return;
string s = MesgLog.Text(10005, f.Name);
SendNotify(s);
}
//
private void NotifyMatch(string name)
{
if (!DcConfig.Duty.EnableNotify)
return;
string s = MesgLog.Text(10003, name);
SendNotify(s);
}
private void ChkUseNotifyLine_CheckedChanged(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
DcConfig.Duty.UseNotifyLine = chkUseNotifyLine.Checked;
txtLineToken.Enabled = chkUseNotifyLine.Checked;
btnTestNotify.Enabled = DcConfig.Duty.EnableNotify;
SaveConfig();
}
private void LblLineNotifyBotLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if (!DcConfig.PluginEnable)
return;
Process.Start(lblLineNotifyBotLink.Text);
}
private void TxtLineToken_KeyDown(object sender, KeyEventArgs e)
{
if (!DcConfig.PluginEnable)
return;
if (e.KeyCode == Keys.Enter)
{
DcConfig.Duty.NotifyLineToken = txtLineToken.Text;
SaveConfig();
}
}
//
internal async Task NotifyUsingLine(string mesg)
{
if (txtLineToken.TextLength == 0)
return;
if (!txtLineToken.Text.Equals(DcConfig.Duty.NotifyLineToken))
{
DcConfig.Duty.NotifyLineToken = txtLineToken.Text;
SaveConfig();
}
var hc = new HttpClient();
hc.DefaultRequestHeaders.Add("Authorization", $"Bearer {DcConfig.Duty.NotifyLineToken}");
var param = new Dictionary<string, string>
{
{ "message", mesg }
};
await hc.PostAsync("https://notify-api.line.me/api/notify",
new FormUrlEncodedContent(param)).ConfigureAwait(false);
}
//
private void ChkUseNotifyTelegram_CheckedChanged(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
DcConfig.Duty.UseNotifyTelegram = chkUseNotifyTelegram.Checked;
txtTelegramId.Enabled = chkUseNotifyTelegram.Checked;
txtTelegramToken.Enabled = chkUseNotifyTelegram.Checked;
btnTestNotify.Enabled = DcConfig.Duty.EnableNotify;
SaveConfig();
}
private void TxtTelegramId_KeyDown(object sender, KeyEventArgs e)
{
if (!DcConfig.PluginEnable)
return;
if (e.KeyCode == Keys.Enter)
{
DcConfig.Duty.NotifyTelegramId = txtTelegramId.Text;
SaveConfig();
}
}
private void TxtTelegramToken_KeyDown(object sender, KeyEventArgs e)
{
if (!DcConfig.PluginEnable)
return;
if (e.KeyCode == Keys.Enter)
{
DcConfig.Duty.NotifyTelegramToken = txtTelegramToken.Text;
SaveConfig();
}
}
//
private static string EncodeJsonChars(string text)
{
return text.Replace("\b", "\\\b")
.Replace("\f", "\\\f")
.Replace("\n", "\\\n")
.Replace("\r", "\\\r")
.Replace("\t", "\\\t")
.Replace("\"", "\\\"")
.Replace("\\", "\\\\");
}
//
private bool NotifyUsingTelegram(string mesg)
{
if (txtTelegramId.TextLength == 0 || txtTelegramToken.TextLength == 0)
return false;
if (!txtTelegramId.Text.Equals(DcConfig.Duty.NotifyTelegramId))
{
DcConfig.Duty.NotifyTelegramId = txtTelegramId.Text;
SaveConfig();
}
if (!txtTelegramToken.Text.Equals(DcConfig.Duty.NotifyTelegramToken))
{
DcConfig.Duty.NotifyTelegramToken = txtTelegramToken.Text;
SaveConfig();
}
// https://codingman.tistory.com/41
var json = string.Format("{{\"chat_id\":\"{0}\", \"text\":\"{1}\"}}",
DcConfig.Duty.NotifyTelegramId, EncodeJsonChars(mesg));
var jbin = Encoding.UTF8.GetBytes(json);
var url = string.Format("https://api.telegram.org/bot{0}/sendMessage", DcConfig.Duty.NotifyTelegramToken);
HttpWebRequest req = WebRequest.Create(new Uri(url)) as HttpWebRequest;
req.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
req.Timeout = 30 * 1000;
req.Method = "POST";
req.ContentType = "application/json";
using (var st = req.GetRequestStream())
{
st.Write(jbin, 0, jbin.Length);
st.Flush();
}
HttpWebResponse res = null;
try
{
res = req.GetResponse() as HttpWebResponse;
if (res.StatusCode == HttpStatusCode.OK)
{
string ss = null;
using (var st = res.GetResponseStream())
{
using (var rdr = new StreamReader(st, Encoding.UTF8))
ss = rdr.ReadToEnd();
}
if (0 < ss.IndexOf("\"ok\":true"))
return true;
else
return false;
}
else
{
// http status is not ok
return false;
}
}
catch
{
// ???
return false;
}
finally
{
if (res != null)
res.Close();
}
}
//
private void PacketFinderResetUi(bool is_enable)
{
if (!is_enable)
{
btnPacketStart.Text = MesgLog.Text(10007);
btnPacketStart.BackColor = Color.Transparent;
}
else
{
btnPacketStart.Text = MesgLog.Text(10008);
btnPacketStart.BackColor = Color.Salmon;
}
btnPacketApply.Visible = is_enable;
btnPacketApply.Enabled = is_enable;
lstPacketInfo.Enabled = is_enable;
txtPacketInfo.Enabled = is_enable;
txtPacketDescription.Enabled = is_enable;
lstBozjaInfo.Enabled = is_enable;
}
//
private void PacketFindClearUi(DcConfig.PacketConfig newpk)
{
//
txtPacketDescription.Text = DcConfig.Packet.Version;
lstBozjaInfo.Items.Clear();
// FATE
lstPacketInfo.Items[0].SubItems[1].Text = DcConfig.Packet.OpFate.ToString();
lstPacketInfo.Items[0].SubItems[2].Text = "";
lstPacketInfo.Items[0].SubItems[3].Text = newpk.OpFate.ToString();
// Duty
lstPacketInfo.Items[1].SubItems[1].Text = DcConfig.Packet.OpDuty.ToString();
lstPacketInfo.Items[1].SubItems[2].Text = "";
lstPacketInfo.Items[1].SubItems[3].Text = newpk.OpDuty.ToString();
// Match
lstPacketInfo.Items[2].SubItems[1].Text = DcConfig.Packet.OpMatch.ToString();
lstPacketInfo.Items[2].SubItems[2].Text = "";
lstPacketInfo.Items[2].SubItems[3].Text = newpk.OpMatch.ToString();
// Instance
lstPacketInfo.Items[3].SubItems[1].Text = DcConfig.Packet.OpInstance.ToString();
lstPacketInfo.Items[3].SubItems[2].Text = "";
lstPacketInfo.Items[3].SubItems[3].Text = newpk.OpInstance.ToString();
// Bozja
lstPacketInfo.Items[4].SubItems[1].Text = DcConfig.Packet.OpSouthernBozja.ToString();
lstPacketInfo.Items[4].SubItems[2].Text = "";
lstPacketInfo.Items[4].SubItems[3].Text = newpk.OpSouthernBozja.ToString();
}
private void BtnPacketStart_Click(object sender, EventArgs e)
{
if (!_is_packet_finder)
{
_new_packet = new DcConfig.PacketConfig()
{
Version = DcConfig.Packet.Version,
OpFate = 0,
OpDuty = 0,
OpMatch = 0,
OpInstance = 0,
OpSouthernBozja = 0,
};
PacketFindClearUi(_new_packet);
}
_is_packet_finder = !_is_packet_finder;
PacketFinderResetUi(_is_packet_finder);
}
private void BtnPacketApply_Click(object sender, EventArgs e)
{
var ret = (DialogResult)WorkerAct.Invoker(new WorkerAct.ObjectReturnerDelegate(() =>
{
var r = MessageBox.Show(MesgLog.Text(10022), MesgLog.Text(0), MessageBoxButtons.YesNo, MessageBoxIcon.Question);
return r;
}));
if (ret == DialogResult.Yes)
{
_new_packet.Version = txtPacketDescription.Text;
DcConfig.Packet.Version = _new_packet.Version;
DcConfig.Packet.OpFate = _new_packet.OpFate;
DcConfig.Packet.OpDuty = _new_packet.OpDuty;
DcConfig.Packet.OpMatch = _new_packet.OpMatch;
DcConfig.Packet.OpInstance = _new_packet.OpInstance;
DcConfig.Packet.OpSouthernBozja = _new_packet.OpSouthernBozja;
DcConfig.Packet.Save();
_is_packet_finder = false;
PacketFinderResetUi(false);
}
}
private void LstPacketInfo_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstPacketInfo.SelectedIndices.Count != 1)
return;
int m;
switch (lstPacketInfo.SelectedIndices[0])
{
case 0: m = 10010; break;
case 1: m = 10011; break;
case 2: m = 10011; break;
case 3: m = 10011; break;
case 4: m = 10014; break;
default: m = 10015; break;
}
txtPacketInfo.Text = MesgLog.Text(m);
}
private void LstBozjaInfo_MouseDoubleClick(object sender, MouseEventArgs e)
{
}
private void LstBozjaInfo_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstBozjaInfo.SelectedItems.Count != 1)
return;
ushort opcode = (ushort)lstBozjaInfo.SelectedItems[0].Tag;
_new_packet.OpSouthernBozja = opcode;
lstPacketInfo.Items[4].SubItems[2].Text = MesgLog.Text(10023);
lstPacketInfo.Items[4].SubItems[3].Text = _new_packet.OpSouthernBozja.ToString();
}
private static readonly short[] _packet_target_fates =
{
// moddle la noscea
553, 649, 687, 688, 693, 717,
220, 221, 222, 223, 225, 226, 227, 229, 231, 233, 235, 237, 238, 239, 240,
1387,
// southern bozja front
1597, 1598, 1599,
1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609,
1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619,
1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628
};
//
private void PacketFinderHandler(byte[] message)
{
var opcode = BitConverter.ToUInt16(message, 18);
var data = message.Skip(32).ToArray();
// fate
if (_new_packet.OpFate == 0 && data.Length > 4 && data[0] == 0x3E)
{
var cc = BitConverter.ToInt16(data, 4);
if (_packet_target_fates.Contains(cc) && _new_packet.OpFate != opcode)
{
_new_packet.OpFate = opcode;
WorkerAct.Invoker(() =>
{
lstPacketInfo.Items[0].SubItems[2].Text = MesgLog.Text(10016);
lstPacketInfo.Items[0].SubItems[3].Text = _new_packet.OpFate.ToString();
});
return;
}
}
// duty
if (_new_packet.OpDuty == 0 && data.Length > 12)
{
var rcode = data[8];
if (rcode == 0)
{
// The Steps of Fath (83)
short m = BitConverter.ToInt16(data, 12);
if (m == 83 && _new_packet.OpDuty != opcode)
{
_new_packet.OpDuty = opcode;
WorkerAct.Invoker(() =>
{
lstPacketInfo.Items[1].SubItems[2].Text = MesgLog.Text(10016);
lstPacketInfo.Items[1].SubItems[3].Text = _new_packet.OpDuty.ToString();
});
return;
}
}
}
// match
if (_new_packet.OpMatch == 0 && data.Length > 20)
{
var rcode = data[2];
if (rcode == 0)
{
// The Steps of Fath (83)
short m = BitConverter.ToInt16(data, 20);
if (m == 83 && _new_packet.OpMatch != opcode)
{
_new_packet.OpMatch = opcode;
WorkerAct.Invoker(() =>
{
lstPacketInfo.Items[2].SubItems[2].Text = MesgLog.Text(10016);
lstPacketInfo.Items[2].SubItems[3].Text = _new_packet.OpMatch.ToString();
});
return;
}
}
}
// instance
if (_new_packet.OpInstance == 0 && data.Length >= 16)
{
// The Steps of Fath (83)
short m = BitConverter.ToInt16(data, 0);
short u = BitConverter.ToInt16(data, 2);
if (m == 83 && u == 0 && _new_packet.OpInstance != opcode)
{
_new_packet.OpInstance = opcode;
WorkerAct.Invoker(() =>
{
lstPacketInfo.Items[3].SubItems[2].Text = MesgLog.Text(10016);
lstPacketInfo.Items[3].SubItems[3].Text = _new_packet.OpInstance.ToString();
});
return;
}
}
// critical engagement
if (data.Length >= 12)
{
// 0[4] timestamp
// 4[2] mmss
// 6[2] ?
// 8[1] code
// 9[1] members
// 10[1] status 0=end, 1=register, 2=entry, 3=progress
// 12[1] progress percentage
var code = data[8];
if (code < 0 || code > 15)
{
// not ce
return;
}
var stat = data[10];
var prg = data[12];
var mem = data[9];
var ok = false;
/*
if (stat == 0)
{
// end. other conditions unknown
ok = true;
}
else*/
if (stat == 1)
{
// register. progress must be 0
if (mem >= 0 && mem <= 48 && prg == 0)
ok = true;
}
else if (stat == 2)
{
// entry. progress must be 0
if (mem >= 0 && mem <= 48 && prg == 0)
ok = true;
}
else if (stat == 3)
{
// progress. progress must be in 1~99
if (mem > 0 && mem <= 48 && prg >= 1 && prg < 100)
ok = true;
}
if (ok)
{
var ce = DcContent.GetFate(code + 30000);
var li = new ListViewItem(new string[]
{
ce.Name,
DcContent.CeStatusToString(stat),
mem.ToString(),
prg.ToString()
})
{
Tag = opcode
};
WorkerAct.Invoker(() =>
{
lstBozjaInfo.Items.Add(li);
lstBozjaInfo.EnsureVisible(lstBozjaInfo.Items.Count - 1);
});
}
}
}
private void ChkUsePing_CheckedChanged(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
DcConfig.Duty.UsePing = chkUsePing.Checked;
SaveConfig();
if (chkUsePing.Checked)
{
PingOnce();
_ping_timer.Start();
}
else
{
_ping_timer.Stop();
_overlay.ResetStat();
}
}
private void PingColorWorker(int index, Button button)
{
Color color = (Color)WorkerAct.Invoker(new WorkerAct.ObjectReturnerDelegate(() =>
{
var dg = new ColorDialog()
{
AnyColor = true,
Color = DcConfig.Duty.PingColors[index],
};
return dg.ShowDialog() == DialogResult.OK ? dg.Color : DcConfig.Duty.PingColors[index];
}));
if (DcConfig.Duty.PingColors[index] != color)
{
button.BackColor = color;
DcConfig.Duty.PingColors[index] = color;
SaveConfig();
}
}
private void BtnPingColor1_Click(object sender, EventArgs e)
{
PingColorWorker(0, btnPingColor1);
}
private void BtnPingColor2_Click(object sender, EventArgs e)
{
PingColorWorker(1, btnPingColor2);
}
private void BtnPingColor3_Click(object sender, EventArgs e)
{
PingColorWorker(2, btnPingColor3);
}
private void BtnPingColor4_Click(object sender, EventArgs e)
{
PingColorWorker(3, btnPingColor4);
}
private void ChkPingGraph_CheckedChanged(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
DcConfig.Duty.PingGraph = chkPingGraph.Checked;
SaveConfig();
}
private void CboPingDefAddr_SelectedIndexChanged(object sender, EventArgs e)
{
if (!DcConfig.PluginEnable)
return;
var val = cboPingDefAddr.SelectedItem as string;
if (!string.IsNullOrEmpty(val))
{
var ss = val.Split(' ');
if (ss.Length > 0)
{
DcConfig.Duty.PingDefAddr = ss[0].Trim();
SaveConfig();
return;
}
}
DcConfig.Duty.PingDefAddr = string.Empty;
SaveConfig();
}
//
private void PingOnce(bool check_plugin_enable = true)
{
if (!DcConfig.Duty.UsePing)
return;
if (check_plugin_enable && !DcConfig.PluginEnable)
return;
var conns = DcConfig.Connections.CopyConnection();
long rtt = 0;
double loss = 0;
if (conns.Length > 0)
{
foreach (var row in conns)
{
var (r, l) = CalcPing(row.RemoteAddress);
if (rtt < r)
rtt = r;
if (loss < l)
loss = l;
}
}
else
{
if (string.IsNullOrEmpty(DcConfig.Duty.PingDefAddr))
{
_overlay.ResetStat();
return;
}
var defip = ThirdParty.Converter.ToIPAddressFromIPV4(DcConfig.Duty.PingDefAddr);
if (defip == IPAddress.None || defip == IPAddress.IPv6None)
{
_overlay.ResetStat();
return;
}
var (r, l) = CalcPing(defip);
if (rtt < r)
rtt = r;
if (loss < l)
loss = l;
}
//MesgLog.L("Ping: {0}, {1}%", rtt, loss);
Color color;
if (loss > 0.0 || rtt > 150)
color = DcConfig.Duty.PingColors[3];
else if (rtt > 100)
color = DcConfig.Duty.PingColors[2];
else if (rtt > 50)
color = DcConfig.Duty.PingColors[1];
else
color = DcConfig.Duty.PingColors[0];
if (_ping_last != rtt || loss > 0.0 || _ping_color != color)
{
_ping_last = rtt;
_ping_color = color;
_overlay.SetStatPing(color, rtt, loss);
}
//
if (DcConfig.Duty.PingGraph)
{
_ping_keeps.Add((int)rtt);
if (_ping_keeps.Count > 120)
_ping_keeps.RemoveAt(0);
_ping_grpr.Enter();
_ping_grpr.DrawValues(_ping_keeps);
WorkerAct.Invoker(() => _ping_grpr.Leave());
}
}
// http://forum.codecall.net/topic/37643-c-packet-lossping-program/
private static readonly PingOptions _ping_options = new PingOptions { DontFragment = true };
private static readonly byte[] _ping_buffers = Encoding.ASCII.GetBytes("01234567890123456789012345678901");
private static readonly int _ping_timerout = 120;
//
private (long Rtt, double Loss) CalcPing(IPAddress host, int amount = 6)
{
var ps = new Ping();
int failed = 0;
long rtt = 0;
for (var i = 0; i < amount; i++)
{
PingReply pr = ps.Send(host, _ping_timerout, _ping_buffers, _ping_options);
if (pr.Status != IPStatus.Success)
failed++;
if (rtt < pr.RoundtripTime)
rtt = pr.RoundtripTime;
}
double loss = (failed / amount) * 100;
return (rtt, loss);
}
}
}