-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathFilterCore.cs
150 lines (140 loc) · 5.99 KB
/
FilterCore.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using ACManager.StateMachine;
using ACManager.StateMachine.States;
using Decal.Adapter;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace ACManager
{
[FriendlyName("ACManager")]
public class FilterCore : FilterBase
{
public Machine Machine { get; set; }
private Timer LogonTimer { get; set; } = new Timer();
public static List<string> AccountCharacters { get; set; } = new List<string>();
public static int NextCharacterIndex;
public uint TotalSlots { get; set; }
/// <summary>
/// Called as soon as the client is launched.
/// </summary>
protected override void Startup()
{
ServerDispatch += FilterCore_ServerDispatch;
ClientDispatch += FilterCore_ClientDispatch;
LogonTimer.Interval = 1000;
LogonTimer.Tick += LogonTimer_Tick;
Debug.Init(Path);
}
/// <summary>
/// Called only when the client is completely closed (exited out of the character selection screen even).
/// </summary>
protected override void Shutdown()
{
ServerDispatch -= FilterCore_ServerDispatch;
CommandLineText -= Machine.Interpreter.Command;
ClientDispatch -= FilterCore_ClientDispatch;
LogonTimer.Tick -= LogonTimer_Tick;
LogonTimer?.Dispose();
Machine.BotManagerView?.Dispose();
}
/// <summary>
/// Parses server messages.
/// Protocols known at time of creation:
/// http://skunkworks.sourceforge.net/protocol/Protocol.php
/// https://acemulator.github.io/protocol/
/// </summary>
private void FilterCore_ServerDispatch(object sender, NetworkMessageEventArgs e)
{
switch (e.Message.Type)
{
case 0xf653: // End 3D Mode and return to character screen
Machine.Logout();
CommandLineText -= Machine.Interpreter.Command;
Core.RenderFrame -= Machine.Clock;
Core.WorldFilter.ChangeObject -= Machine.WorldFilter_ChangeObject;
break;
case 0xf658: // Received the character list from the server
AccountCharacters.Clear();
TotalSlots = e.Message.Value<uint>("slotCount");
for (int i = 0; i < e.Message.Value<uint>("characterCount"); i++)
{
AccountCharacters.Add(e.Message.Struct("characters").Struct(i).Value<string>("name"));
}
AccountCharacters.Sort((a, b) => String.Compare(a, b, StringComparison.Ordinal));
break;
case 0xf746: // Character login request
LogonTimer.Stop();
break;
case 0xf7b0: // Game events
switch (e.Message.Value<uint>("event"))
{
case 0x01c7: // Ready, previous action complete
Machine.CastCompleted = true;
break;
case 0x028a: // Status message
switch (e.Message.Value<uint>("type"))
{
case 0x0402:
Machine.Fizzled = true;
break;
}
break;
}
break;
case 0xf7e1:
if (Machine.CurrentState == SwitchingCharacters.GetInstance)
{
LogonTimer.Start();
}
break;
}
}
/// <summary>
/// Parses the client messages.
/// </summary>
private void FilterCore_ClientDispatch(object sender, NetworkMessageEventArgs e)
{
switch (e.Message.Type)
{
case 0xf7b1:
switch (e.Message.Value<uint>("action"))
{
case 0x00a1: // Character materializes (including exiting portal space)
if (Machine == null)
{
Utility.Init(Path);
Machine = new Machine();
}
if (!Machine.LoggedIn)
{
Debug.ToChat($"ACManager {Utility.Version}. Check out the latest on the project at https://github.com/patri0t86/ACManager.");
CommandLineText += Machine.Interpreter.Command;
Core.RenderFrame += Machine.Clock;
Core.WorldFilter.ChangeObject += Machine.WorldFilter_ChangeObject;
Machine.Login();
}
break;
case 0x004a: // Started casting
Machine.CastStarted = true;
break;
}
break;
}
}
/// <summary>
/// On every timer tick, this will run the LoginNextCharacter method.
/// </summary>
private void LogonTimer_Tick(object sender, EventArgs e)
{
int XPixelOffset = 121;
int YTopOfBox = 209;
int YBottomOfBox = 532;
float characterNameSize = (YBottomOfBox - YTopOfBox) / (float)TotalSlots;
int yOffset = (int)(YTopOfBox + (characterNameSize / 2) + (characterNameSize * NextCharacterIndex));
// Select the character
Simulate.MouseClick(Core.Decal.Hwnd, XPixelOffset, yOffset);
// Click the Enter button
Simulate.MouseClick(Core.Decal.Hwnd, 0x015C, 0x0185);
}
}
}