using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace rabi_splitter_WPF
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
private MainContext mainContext;
private DebugContext debugContext;
private static TcpClient tcpclient;
private static NetworkStream networkStream;
private readonly Regex titleReg = new Regex(@"ver.*?(\d+\.?\d+.*)$");
private readonly Thread memoryThread;
private void ReadMemory()
{
var processlist = Process.GetProcessesByName("rabiribi");
if (processlist.Length > 0)
{
Process process = processlist[0];
if (process.MainWindowTitle != mainContext.oldtitle)
{
var result = titleReg.Match(process.MainWindowTitle);
string rabiver;
if (result.Success)
{
rabiver = result.Groups[1].Value;
mainContext.veridx = Array.IndexOf(StaticData.VerNames, rabiver);
if (mainContext.veridx < 0)
{
mainContext.GameVer = rabiver + " Running (not support)";
return;
}
}
else
{
mainContext.veridx = -1;
mainContext.GameVer = "Running (Unknown version)";
return;
}
mainContext.GameVer = rabiver + " Running";
mainContext.oldtitle = process.MainWindowTitle;
}
if (mainContext.veridx < 0) return;
#region read igt
int igt = MemoryHelper.GetMemoryValue(process, StaticData.IGTAddr[mainContext.veridx]);
if (igt > 0 && mainContext.Igt)
{
sendigt((float)igt / 60);
}
#endregion
#region CheckMoney
if (mainContext.Computer)
{
var newmoney = MemoryHelper.GetMemoryValue(process, StaticData.MoneyAddress[mainContext.veridx]);
if (newmoney - mainContext.lastmoney == 17500)
{
sendsplit();
DebugLog("get 17500 en, split");
}
mainContext.lastmoney = newmoney;
}
#endregion
int mapid = MemoryHelper.GetMemoryValue(process, StaticData.MapAddress[mainContext.veridx]);
if (mainContext.lastmapid != mapid)
{
DebugLog("newmap: " + mapid + ":" + StaticData.MapNames[mapid]);
mainContext.lastmapid = mapid;
}
#region checkTM
#endregion
#region Music
int musicaddr = StaticData.MusicAddr[mainContext.veridx];
int musicid = MemoryHelper.GetMemoryValue(process, musicaddr);
if (musicid > 0 && musicid < StaticData.MusicNames.Length)
{
if (mainContext.lastmusicid != musicid)
{
DebugLog("new music:" + musicid + ":" + StaticData.MusicNames[musicid]);
mainContext.GameMusic = StaticData.MusicNames[musicid];
var bossmusicflag = StaticData.BossMusics.Contains(musicid);
if (bossmusicflag)
{
if (mainContext.bossbattle)
{
//直接换boss曲
if (mainContext.MusicStart || mainContext.MusicEnd)
{
sendsplit();
DebugLog("new boss music, split");
}
debugContext.BossEvent = true;
mainContext.lastmusicid = musicid;
return;
}
}
if (!mainContext.bossbattle)
{
if (musicid == 54 && mainContext.AliusI)
{
mainContext.bossbattle = false;
debugContext.BossEvent = false;
mainContext.AliusI = false;
DebugLog("Alius music, ignore once");
}
if (musicid == 42 && mapid == 1 && mainContext.Irisu1)
{
mainContext.bossbattle = false;
debugContext.BossEvent = false;
DebugLog("Irisu P1, ignore");
}
else
{
if (bossmusicflag)
{
if (mapid == 5 && musicid == 44 && mainContext.SideCh)
{
mainContext.bossbattle = false;
debugContext.BossEvent = false;
DebugLog("sidechapter, ignore");
}
else
{
mainContext.bossbattle = true;
debugContext.BossEvent = true;
mainContext.lastbosslist = new List();
mainContext.lastnoah3hp = -1;
if (mainContext.MusicStart)
{
sendsplit();
DebugLog("music start, split");
}
}
}
}
}
else
{
if (!bossmusicflag) //boss music end!
{
mainContext.bossbattle = false;
if (mainContext.MusicEnd)
{
sendsplit();
DebugLog("music end, split");
}
}
}
mainContext.lastmusicid = musicid;
}
}
else
{
mainContext.GameMusic = "N/A";
}
#endregion Music
#region SpecialBOSS
if (mainContext.bossbattle)
{
if (mainContext.MiruDe || false)//todo noah3 option
{
int Noah3HP = -1;
if (mapid >= 0 && mapid < StaticData.MapNames.Length)
{
int ptr = MemoryHelper.GetMemoryValue(process, StaticData.EnenyPtrAddr[mainContext.veridx]);
List bosses = new List();
for (var i = 0; i < 50; i++)
{
ptr = ptr + StaticData.EnenyEntitySize[mainContext.veridx];
var emyid = MemoryHelper.GetMemoryValue(process,
ptr + StaticData.EnenyEnitiyIDOffset[mainContext.veridx], false);
if (StaticData.BossNames.ContainsKey(emyid))
{
bosses.Add(emyid);
if (emyid == 1053)
{
Noah3HP = MemoryHelper.GetMemoryValue(process,
ptr + StaticData.EnenyEnitiyHPOffset[mainContext.veridx], false);
}
}
}
if (mainContext.MiruDe)
{
foreach (var boss in mainContext.lastbosslist)
{
if (boss == 1043)
{
if (!bosses.Contains(boss)) //despawn
{
sendsplit();
DebugLog("miru despawn, split");
mainContext.bossbattle = false;
}
}
}
}
// if (cbBoss3.Checked)
// {
// if (bosses.Contains(1053) && Noah3HP < lastnoah3hp && Noah3HP == 1)
// {
// sendsplit();
// DebugLog("noah3 hp 1, split");
// bossbattle = false;
// }
// }
if (mainContext.Tm2 && musicid == 8)
{
bool f = true;
foreach (var boss in mainContext.lastbosslist)
{
if (boss == 1024)
{
if (!bosses.Contains(boss)) //despawn
{
sendsplit();
DebugLog("nixie despawn, split");
mainContext.bossbattle = false;
f = false;
break;
}
}
}
int newTM = MemoryHelper.GetMemoryValue(process, StaticData.TownMemberAddr[mainContext.veridx]);
if (newTM - mainContext.lastTM == 1 && f) //for after 1.71 , 1.71 isn't TM+2 at once when skip Nixie, it's TM+1 twice
{
if (DateTime.Now - mainContext.LastTMAddTime < TimeSpan.FromSeconds(1))
{
var d = DateTime.Now - mainContext.LastTMAddTime;
mainContext.bossbattle = false;
sendsplit();
DebugLog("TM+2 in " + d.TotalMilliseconds + " ms, split");
}
mainContext.LastTMAddTime = DateTime.Now;
}
else if (newTM - mainContext.lastTM == 2 && f)//for 1.65-1.70
{
mainContext.bossbattle = false;
sendsplit();
DebugLog("TM+2, split");
}
mainContext.lastTM = newTM;
}
mainContext.lastbosslist = bosses;
mainContext.lastnoah3hp = Noah3HP;
}
}
}
#endregion SpecialBOSS
if (mainContext.DebugArea)
{
int ptr = MemoryHelper.GetMemoryValue(process, StaticData.EnenyPtrAddr[mainContext.veridx]);
// List bosses = new List();
// List HPS = new List();
debugContext.BossList.Clear();
// ptr += StaticData.EnenyEntitySize[mainContext.veridx] * 3;
for (var i = 0; i < 50; i++)
{
ptr += StaticData.EnenyEntitySize[mainContext.veridx];
debugContext.BossList.Add(new BossData()
{
BossIdx = i,
BossID = MemoryHelper.GetMemoryValue(process,
ptr + StaticData.EnenyEnitiyIDOffset[mainContext.veridx], false),
BossHP = MemoryHelper.GetMemoryValue(process,
ptr + StaticData.EnenyEnitiyHPOffset[mainContext.veridx], false)
});
// this.Invoke(new Action(() =>
// {
// t1.Text = string.Join("\n", bosses);
// t2.Text = string.Join("\n", HPS);
// }));
}
}
debugContext.BossEvent = mainContext.bossbattle;
}
else
{
mainContext.oldtitle = "";
mainContext.GameVer = "Not Found";
mainContext.GameMusic = "N/A";
}
}
private void DebugLog(string log)
{
this.debugContext.DebugLog += log + "\n";
}
private void sendsplit()
{
if (tcpclient != null && tcpclient.Connected)
{
try
{
var b = Encoding.UTF8.GetBytes("split\r\n");
networkStream.Write(b, 0, b.Length);
}
catch (Exception)
{
disconnect();
}
}
}
private void sendigt(float time)
{
if (tcpclient != null && tcpclient.Connected)
{
try
{
var b = Encoding.UTF8.GetBytes($"setgametime {time}\r\n");
networkStream.Write(b, 0, b.Length);
}
catch (Exception)
{
disconnect();
}
}
}
void disconnect()
{
tcpclient = null;
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
BtnConnect.IsEnabled = true;
}));
}
public MainWindow()
{
InitializeComponent();
mainContext=new MainContext();
debugContext=new DebugContext();
this.DataContext = mainContext;
DebugPanel.DataContext = debugContext;
memoryThread = new Thread(() =>
{
while (true)
{
ReadMemory();
Thread.Sleep(1000 / 60);
}
});
memoryThread.IsBackground = true;
memoryThread.Start();
}
private void BtnConnect_Click(object sender, RoutedEventArgs e)
{
if (tcpclient != null && tcpclient.Connected) return;
try
{
tcpclient = new TcpClient("127.0.0.1", Convert.ToInt32(mainContext.ServerPort));
networkStream = tcpclient.GetStream();
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
BtnConnect.IsEnabled = false;
}));
}
catch (Exception)
{
tcpclient = null;
networkStream = null;
MessageBox.Show(this, "Connect Failed");
}
}
private void TextBlock_MouseUp(object sender, MouseButtonEventArgs e)
{
Process.Start("https://github.com/copyliu/rabiribi_splitter");
}
}
}