corrade-vassal – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | using System; |
2 | using System.Collections.Generic; |
||
3 | using System.Threading; |
||
4 | using System.Reflection; |
||
5 | using System.Xml; |
||
6 | using OpenMetaverse; |
||
7 | using OpenMetaverse.Packets; |
||
8 | using OpenMetaverse.Utilities; |
||
9 | |||
10 | namespace OpenMetaverse.TestClient |
||
11 | { |
||
12 | public class TestClient : GridClient |
||
13 | { |
||
14 | public UUID GroupID = UUID.Zero; |
||
15 | public Dictionary<UUID, GroupMember> GroupMembers; |
||
16 | public Dictionary<UUID, AvatarAppearancePacket> Appearances = new Dictionary<UUID, AvatarAppearancePacket>(); |
||
17 | public Dictionary<string, Command> Commands = new Dictionary<string, Command>(); |
||
18 | public bool Running = true; |
||
19 | public bool GroupCommands = false; |
||
20 | public string MasterName = String.Empty; |
||
21 | public UUID MasterKey = UUID.Zero; |
||
22 | public bool AllowObjectMaster = false; |
||
23 | public ClientManager ClientManager; |
||
24 | public VoiceManager VoiceManager; |
||
25 | // Shell-like inventory commands need to be aware of the 'current' inventory folder. |
||
26 | public InventoryFolder CurrentDirectory = null; |
||
27 | |||
28 | private System.Timers.Timer updateTimer; |
||
29 | private UUID GroupMembersRequestID; |
||
30 | public Dictionary<UUID, Group> GroupsCache = null; |
||
31 | private ManualResetEvent GroupsEvent = new ManualResetEvent(false); |
||
32 | |||
33 | /// <summary> |
||
34 | /// |
||
35 | /// </summary> |
||
36 | public TestClient(ClientManager manager) |
||
37 | { |
||
38 | ClientManager = manager; |
||
39 | |||
40 | updateTimer = new System.Timers.Timer(500); |
||
41 | updateTimer.Elapsed += new System.Timers.ElapsedEventHandler(updateTimer_Elapsed); |
||
42 | |||
43 | RegisterAllCommands(Assembly.GetExecutingAssembly()); |
||
44 | |||
45 | Settings.LOG_LEVEL = Helpers.LogLevel.Debug; |
||
46 | Settings.LOG_RESENDS = false; |
||
47 | Settings.STORE_LAND_PATCHES = true; |
||
48 | Settings.ALWAYS_DECODE_OBJECTS = true; |
||
49 | Settings.ALWAYS_REQUEST_OBJECTS = true; |
||
50 | Settings.SEND_AGENT_UPDATES = true; |
||
51 | Settings.USE_ASSET_CACHE = true; |
||
52 | |||
53 | Network.RegisterCallback(PacketType.AgentDataUpdate, AgentDataUpdateHandler); |
||
54 | Network.LoginProgress += LoginHandler; |
||
55 | Objects.AvatarUpdate += new EventHandler<AvatarUpdateEventArgs>(Objects_AvatarUpdate); |
||
56 | Objects.TerseObjectUpdate += new EventHandler<TerseObjectUpdateEventArgs>(Objects_TerseObjectUpdate); |
||
57 | Network.SimChanged += new EventHandler<SimChangedEventArgs>(Network_SimChanged); |
||
58 | Self.IM += Self_IM; |
||
59 | Groups.GroupMembersReply += GroupMembersHandler; |
||
60 | Inventory.InventoryObjectOffered += Inventory_OnInventoryObjectReceived; |
||
61 | |||
62 | Network.RegisterCallback(PacketType.AvatarAppearance, AvatarAppearanceHandler); |
||
63 | Network.RegisterCallback(PacketType.AlertMessage, AlertMessageHandler); |
||
64 | |||
65 | VoiceManager = new VoiceManager(this); |
||
66 | |||
67 | updateTimer.Start(); |
||
68 | } |
||
69 | |||
70 | void Objects_TerseObjectUpdate(object sender, TerseObjectUpdateEventArgs e) |
||
71 | { |
||
72 | if (e.Prim.LocalID == Self.LocalID) |
||
73 | { |
||
74 | SetDefaultCamera(); |
||
75 | } |
||
76 | } |
||
77 | |||
78 | void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e) |
||
79 | { |
||
80 | if (e.Avatar.LocalID == Self.LocalID) |
||
81 | { |
||
82 | SetDefaultCamera(); |
||
83 | } |
||
84 | } |
||
85 | |||
86 | void Network_SimChanged(object sender, SimChangedEventArgs e) |
||
87 | { |
||
88 | Self.Movement.SetFOVVerticalAngle(Utils.TWO_PI - 0.05f); |
||
89 | } |
||
90 | |||
91 | public void SetDefaultCamera() |
||
92 | { |
||
93 | // SetCamera 5m behind the avatar |
||
94 | Self.Movement.Camera.LookAt( |
||
95 | Self.SimPosition + new Vector3(-5, 0, 0) * Self.Movement.BodyRotation, |
||
96 | Self.SimPosition |
||
97 | ); |
||
98 | } |
||
99 | |||
100 | |||
101 | void Self_IM(object sender, InstantMessageEventArgs e) |
||
102 | { |
||
103 | bool groupIM = e.IM.GroupIM && GroupMembers != null && GroupMembers.ContainsKey(e.IM.FromAgentID) ? true : false; |
||
104 | |||
105 | if (e.IM.FromAgentID == MasterKey || (GroupCommands && groupIM)) |
||
106 | { |
||
107 | // Received an IM from someone that is authenticated |
||
108 | Console.WriteLine("<{0} ({1})> {2}: {3} (@{4}:{5})", e.IM.GroupIM ? "GroupIM" : "IM", e.IM.Dialog, e.IM.FromAgentName, e.IM.Message, |
||
109 | e.IM.RegionID, e.IM.Position); |
||
110 | |||
111 | if (e.IM.Dialog == InstantMessageDialog.RequestTeleport) |
||
112 | { |
||
113 | Console.WriteLine("Accepting teleport lure."); |
||
114 | Self.TeleportLureRespond(e.IM.FromAgentID, e.IM.IMSessionID, true); |
||
115 | } |
||
116 | else if ( |
||
117 | e.IM.Dialog == InstantMessageDialog.MessageFromAgent || |
||
118 | e.IM.Dialog == InstantMessageDialog.MessageFromObject) |
||
119 | { |
||
120 | ClientManager.Instance.DoCommandAll(e.IM.Message, e.IM.FromAgentID); |
||
121 | } |
||
122 | } |
||
123 | else |
||
124 | { |
||
125 | // Received an IM from someone that is not the bot's master, ignore |
||
126 | Console.WriteLine("<{0} ({1})> {2} (not master): {3} (@{4}:{5})", e.IM.GroupIM ? "GroupIM" : "IM", e.IM.Dialog, e.IM.FromAgentName, e.IM.Message, |
||
127 | e.IM.RegionID, e.IM.Position); |
||
128 | return; |
||
129 | } |
||
130 | } |
||
131 | |||
132 | /// <summary> |
||
133 | /// Initialize everything that needs to be initialized once we're logged in. |
||
134 | /// </summary> |
||
135 | /// <param name="login">The status of the login</param> |
||
136 | /// <param name="message">Error message on failure, MOTD on success.</param> |
||
137 | public void LoginHandler(object sender, LoginProgressEventArgs e) |
||
138 | { |
||
139 | if (e.Status == LoginStatus.Success) |
||
140 | { |
||
141 | // Start in the inventory root folder. |
||
142 | CurrentDirectory = Inventory.Store.RootFolder; |
||
143 | } |
||
144 | } |
||
145 | |||
146 | public void RegisterAllCommands(Assembly assembly) |
||
147 | { |
||
148 | foreach (Type t in assembly.GetTypes()) |
||
149 | { |
||
150 | try |
||
151 | { |
||
152 | if (t.IsSubclassOf(typeof(Command))) |
||
153 | { |
||
154 | ConstructorInfo info = t.GetConstructor(new Type[] { typeof(TestClient) }); |
||
155 | Command command = (Command)info.Invoke(new object[] { this }); |
||
156 | RegisterCommand(command); |
||
157 | } |
||
158 | } |
||
159 | catch (Exception e) |
||
160 | { |
||
161 | Console.WriteLine(e.ToString()); |
||
162 | } |
||
163 | } |
||
164 | } |
||
165 | |||
166 | public void RegisterCommand(Command command) |
||
167 | { |
||
168 | command.Client = this; |
||
169 | if (!Commands.ContainsKey(command.Name.ToLower())) |
||
170 | { |
||
171 | Commands.Add(command.Name.ToLower(), command); |
||
172 | } |
||
173 | } |
||
174 | |||
175 | public void ReloadGroupsCache() |
||
176 | { |
||
177 | Groups.CurrentGroups += Groups_CurrentGroups; |
||
178 | Groups.RequestCurrentGroups(); |
||
179 | GroupsEvent.WaitOne(10000, false); |
||
180 | Groups.CurrentGroups -= Groups_CurrentGroups; |
||
181 | GroupsEvent.Reset(); |
||
182 | } |
||
183 | |||
184 | void Groups_CurrentGroups(object sender, CurrentGroupsEventArgs e) |
||
185 | { |
||
186 | if (null == GroupsCache) |
||
187 | GroupsCache = e.Groups; |
||
188 | else |
||
189 | lock (GroupsCache) { GroupsCache = e.Groups; } |
||
190 | GroupsEvent.Set(); |
||
191 | } |
||
192 | |||
193 | public UUID GroupName2UUID(String groupName) |
||
194 | { |
||
195 | UUID tryUUID; |
||
196 | if (UUID.TryParse(groupName,out tryUUID)) |
||
197 | return tryUUID; |
||
198 | if (null == GroupsCache) { |
||
199 | ReloadGroupsCache(); |
||
200 | if (null == GroupsCache) |
||
201 | return UUID.Zero; |
||
202 | } |
||
203 | lock(GroupsCache) { |
||
204 | if (GroupsCache.Count > 0) { |
||
205 | foreach (Group currentGroup in GroupsCache.Values) |
||
206 | if (currentGroup.Name.ToLower() == groupName.ToLower()) |
||
207 | return currentGroup.ID; |
||
208 | } |
||
209 | } |
||
210 | return UUID.Zero; |
||
211 | } |
||
212 | |||
213 | private void updateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) |
||
214 | { |
||
215 | foreach (Command c in Commands.Values) |
||
216 | if (c.Active) |
||
217 | c.Think(); |
||
218 | } |
||
219 | |||
220 | private void AgentDataUpdateHandler(object sender, PacketReceivedEventArgs e) |
||
221 | { |
||
222 | AgentDataUpdatePacket p = (AgentDataUpdatePacket)e.Packet; |
||
223 | if (p.AgentData.AgentID == e.Simulator.Client.Self.AgentID && p.AgentData.ActiveGroupID != UUID.Zero) |
||
224 | { |
||
225 | GroupID = p.AgentData.ActiveGroupID; |
||
226 | |||
227 | GroupMembersRequestID = e.Simulator.Client.Groups.RequestGroupMembers(GroupID); |
||
228 | } |
||
229 | } |
||
230 | |||
231 | private void GroupMembersHandler(object sender, GroupMembersReplyEventArgs e) |
||
232 | { |
||
233 | if (e.RequestID != GroupMembersRequestID) return; |
||
234 | |||
235 | GroupMembers = e.Members; |
||
236 | } |
||
237 | |||
238 | private void AvatarAppearanceHandler(object sender, PacketReceivedEventArgs e) |
||
239 | { |
||
240 | Packet packet = e.Packet; |
||
241 | |||
242 | AvatarAppearancePacket appearance = (AvatarAppearancePacket)packet; |
||
243 | |||
244 | lock (Appearances) Appearances[appearance.Sender.ID] = appearance; |
||
245 | } |
||
246 | |||
247 | private void AlertMessageHandler(object sender, PacketReceivedEventArgs e) |
||
248 | { |
||
249 | Packet packet = e.Packet; |
||
250 | |||
251 | AlertMessagePacket message = (AlertMessagePacket)packet; |
||
252 | |||
253 | Logger.Log("[AlertMessage] " + Utils.BytesToString(message.AlertData.Message), Helpers.LogLevel.Info, this); |
||
254 | } |
||
255 | |||
256 | private void Inventory_OnInventoryObjectReceived(object sender, InventoryObjectOfferedEventArgs e) |
||
257 | { |
||
258 | if (MasterKey != UUID.Zero) |
||
259 | { |
||
260 | if (e.Offer.FromAgentID != MasterKey) |
||
261 | return; |
||
262 | } |
||
263 | else if (GroupMembers != null && !GroupMembers.ContainsKey(e.Offer.FromAgentID)) |
||
264 | { |
||
265 | return; |
||
266 | } |
||
267 | |||
268 | e.Accept = true; |
||
269 | return; |
||
270 | } |
||
271 | } |
||
272 | } |