aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/ClientView.API.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/ClientView.API.cs975
1 files changed, 975 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/ClientView.API.cs b/OpenSim/Region/ClientStack/ClientView.API.cs
new file mode 100644
index 0000000..902f3c7
--- /dev/null
+++ b/OpenSim/Region/ClientStack/ClientView.API.cs
@@ -0,0 +1,975 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28using System;
29using System.Collections.Generic;
30using System.Text;
31using OpenSim.Framework.Interfaces;
32using OpenSim.Framework.Inventory;
33using OpenSim.Framework.Types;
34
35using libsecondlife;
36using libsecondlife.Packets;
37
38namespace OpenSim
39{
40 partial class ClientView
41 {
42 public event ChatFromViewer OnChatFromViewer;
43 public event RezObject OnRezObject;
44 public event GenericCall4 OnDeRezObject;
45 public event ModifyTerrain OnModifyTerrain;
46 public event GenericCall OnRegionHandShakeReply;
47 public event GenericCall OnRequestWearables;
48 public event SetAppearance OnSetAppearance;
49 public event GenericCall2 OnCompleteMovementToRegion;
50 public event UpdateAgent OnAgentUpdate;
51 public event StartAnim OnStartAnim;
52 public event GenericCall OnRequestAvatarsData;
53 public event LinkObjects OnLinkObjects;
54 public event UpdateVector OnGrapObject;
55 public event ObjectSelect OnDeGrapObject;
56 public event MoveObject OnGrapUpdate;
57 public event GenericCall4 OnAddPrim;
58 public event UpdateShape OnUpdatePrimShape;
59 public event ObjectSelect OnObjectSelect;
60 public event UpdatePrimFlags OnUpdatePrimFlags;
61 public event UpdatePrimTexture OnUpdatePrimTexture;
62 public event UpdateVector OnUpdatePrimPosition;
63 public event UpdatePrimRotation OnUpdatePrimRotation;
64 public event UpdateVector OnUpdatePrimScale;
65 public event StatusChange OnChildAgentStatus;
66 public event GenericCall2 OnStopMovement;
67 public event NewAvatar OnNewAvatar;
68 public event GenericCall6 OnRemoveAvatar;
69 public event RequestMapBlocks OnRequestMapBlocks;
70 public event TeleportLocationRequest OnTeleportLocationRequest;
71
72 public event ParcelPropertiesRequest OnParcelPropertiesRequest;
73 public event ParcelDivideRequest OnParcelDivideRequest;
74 public event ParcelJoinRequest OnParcelJoinRequest;
75 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
76
77 public event EstateOwnerMessageRequest OnEstateOwnerMessage;
78
79 /// <summary>
80 ///
81 /// </summary>
82 public LLVector3 StartPos
83 {
84 get
85 {
86 return startpos;
87 }
88 set
89 {
90 startpos = value;
91 }
92 }
93
94 /// <summary>
95 ///
96 /// </summary>
97 public LLUUID AgentId
98 {
99 get
100 {
101 return this.AgentID;
102 }
103 }
104
105 /// <summary>
106 ///
107 /// </summary>
108 public string FirstName
109 {
110 get
111 {
112 return this.firstName;
113 }
114
115 }
116
117 /// <summary>
118 ///
119 /// </summary>
120 public string LastName
121 {
122 get
123 {
124 return this.lastName;
125 }
126 }
127
128 #region World/Avatar to Client
129
130 /// <summary>
131 ///
132 /// </summary>
133 /// <param name="regionInfo"></param>
134 public void SendRegionHandshake(RegionInfo regionInfo)
135 {
136 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
137 RegionHandshakePacket handshake = new RegionHandshakePacket();
138
139 handshake.RegionInfo.BillableFactor = regionInfo.estateSettings.billableFactor;
140 handshake.RegionInfo.IsEstateManager = false;
141 handshake.RegionInfo.TerrainHeightRange00 = regionInfo.estateSettings.terrainHeightRange0;
142 handshake.RegionInfo.TerrainHeightRange01 = regionInfo.estateSettings.terrainHeightRange1;
143 handshake.RegionInfo.TerrainHeightRange10 = regionInfo.estateSettings.terrainHeightRange2;
144 handshake.RegionInfo.TerrainHeightRange11 = regionInfo.estateSettings.terrainHeightRange3;
145 handshake.RegionInfo.TerrainStartHeight00 = regionInfo.estateSettings.terrainStartHeight0;
146 handshake.RegionInfo.TerrainStartHeight01 = regionInfo.estateSettings.terrainStartHeight1;
147 handshake.RegionInfo.TerrainStartHeight10 = regionInfo.estateSettings.terrainStartHeight2;
148 handshake.RegionInfo.TerrainStartHeight11 = regionInfo.estateSettings.terrainStartHeight3;
149 handshake.RegionInfo.SimAccess = (byte)regionInfo.estateSettings.simAccess;
150 handshake.RegionInfo.WaterHeight = regionInfo.estateSettings.waterHeight;
151
152
153 handshake.RegionInfo.RegionFlags = (uint)regionInfo.estateSettings.regionFlags;
154
155 handshake.RegionInfo.SimName = _enc.GetBytes(regionInfo.RegionName + "\0");
156 handshake.RegionInfo.SimOwner = regionInfo.MasterAvatarAssignedUUID;
157 handshake.RegionInfo.TerrainBase0 = regionInfo.estateSettings.terrainBase0;
158 handshake.RegionInfo.TerrainBase1 = regionInfo.estateSettings.terrainBase1;
159 handshake.RegionInfo.TerrainBase2 = regionInfo.estateSettings.terrainBase2;
160 handshake.RegionInfo.TerrainBase3 = regionInfo.estateSettings.terrainBase3;
161 handshake.RegionInfo.TerrainDetail0 = regionInfo.estateSettings.terrainDetail0;
162 handshake.RegionInfo.TerrainDetail1 = regionInfo.estateSettings.terrainDetail1;
163 handshake.RegionInfo.TerrainDetail2 = regionInfo.estateSettings.terrainDetail2;
164 handshake.RegionInfo.TerrainDetail3 = regionInfo.estateSettings.terrainDetail3;
165 handshake.RegionInfo.CacheID = LLUUID.Random(); //I guess this is for the client to remember an old setting?
166
167 this.OutPacket(handshake);
168 }
169
170 /// <summary>
171 ///
172 /// </summary>
173 /// <param name="regInfo"></param>
174 public void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look)
175 {
176 AgentMovementCompletePacket mov = new AgentMovementCompletePacket();
177 mov.AgentData.SessionID = this.SessionID;
178 mov.AgentData.AgentID = this.AgentID;
179 mov.Data.RegionHandle = regInfo.RegionHandle;
180 mov.Data.Timestamp = 1172750370; // TODO - dynamicalise this
181
182 if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0))
183 {
184 mov.Data.Position = this.startpos;
185 }
186 else
187 {
188 mov.Data.Position = pos;
189 }
190 mov.Data.LookAt = look;
191
192 OutPacket(mov);
193 }
194
195 /// <summary>
196 ///
197 /// </summary>
198 /// <param name="message"></param>
199 /// <param name="type"></param>
200 /// <param name="fromPos"></param>
201 /// <param name="fromName"></param>
202 /// <param name="fromAgentID"></param>
203 public void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID)
204 {
205 SendChatMessage(Helpers.StringToField(message), type, fromPos, fromName, fromAgentID);
206 }
207
208 /// <summary>
209 ///
210 /// </summary>
211 /// <param name="message"></param>
212 /// <param name="type"></param>
213 /// <param name="fromPos"></param>
214 /// <param name="fromName"></param>
215 /// <param name="fromAgentID"></param>
216 public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID)
217 {
218 System.Text.Encoding enc = System.Text.Encoding.ASCII;
219 libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket();
220 reply.ChatData.Audible = 1;
221 reply.ChatData.Message = message;
222 reply.ChatData.ChatType = type;
223 reply.ChatData.SourceType = 1;
224 reply.ChatData.Position = fromPos;
225 reply.ChatData.FromName = enc.GetBytes(fromName + "\0");
226 reply.ChatData.OwnerID = fromAgentID;
227 reply.ChatData.SourceID = fromAgentID;
228
229 this.OutPacket(reply);
230 }
231
232
233 /// <summary>
234 /// Send the region heightmap to the client
235 /// </summary>
236 /// <param name="map">heightmap</param>
237 public virtual void SendLayerData(float[] map)
238 {
239 try
240 {
241 int[] patches = new int[4];
242
243 for (int y = 0; y < 16; y++)
244 {
245 for (int x = 0; x < 16; x = x + 4)
246 {
247 patches[0] = x + 0 + y * 16;
248 patches[1] = x + 1 + y * 16;
249 patches[2] = x + 2 + y * 16;
250 patches[3] = x + 3 + y * 16;
251
252 Packet layerpack = TerrainManager.CreateLandPacket(map, patches);
253 OutPacket(layerpack);
254 }
255 }
256 }
257 catch (Exception e)
258 {
259 OpenSim.Framework.Console.MainLog.Instance.Warn("ClientView API.cs: SendLayerData() - Failed with exception " + e.ToString());
260 }
261 }
262
263 /// <summary>
264 /// Sends a specified patch to a client
265 /// </summary>
266 /// <param name="px">Patch coordinate (x) 0..16</param>
267 /// <param name="py">Patch coordinate (y) 0..16</param>
268 /// <param name="map">heightmap</param>
269 public void SendLayerData(int px, int py, float[] map)
270 {
271 try
272 {
273 int[] patches = new int[1];
274 int patchx, patchy;
275 patchx = px / 16;
276 patchy = py / 16;
277
278 patches[0] = patchx + 0 + patchy * 16;
279
280 Packet layerpack = TerrainManager.CreateLandPacket(map, patches);
281 OutPacket(layerpack);
282 }
283 catch (Exception e)
284 {
285 OpenSim.Framework.Console.MainLog.Instance.Warn("ClientView API .cs: SendLayerData() - Failed with exception " + e.ToString());
286 }
287 }
288
289 /// <summary>
290 ///
291 /// </summary>
292 /// <param name="neighbourHandle"></param>
293 /// <param name="neighbourIP"></param>
294 /// <param name="neighbourPort"></param>
295 public void InformClientOfNeighbour(ulong neighbourHandle, System.Net.IPAddress neighbourIP, ushort neighbourPort)
296 {
297 EnableSimulatorPacket enablesimpacket = new EnableSimulatorPacket();
298 enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock();
299 enablesimpacket.SimulatorInfo.Handle = neighbourHandle;
300
301 byte[] byteIP = neighbourIP.GetAddressBytes();
302 enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24;
303 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16;
304 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8;
305 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0];
306 enablesimpacket.SimulatorInfo.Port = neighbourPort;
307 OutPacket(enablesimpacket);
308 }
309
310 /// <summary>
311 ///
312 /// </summary>
313 /// <returns></returns>
314 public AgentCircuitData RequestClientInfo()
315 {
316 AgentCircuitData agentData = new AgentCircuitData();
317 agentData.AgentID = this.AgentId;
318 agentData.SessionID = this.SessionID;
319 agentData.SecureSessionID = this.SecureSessionID;
320 agentData.circuitcode = this.CircuitCode;
321 agentData.child = false;
322 agentData.firstname = this.firstName;
323 agentData.lastname = this.lastName;
324
325 return agentData;
326 }
327
328 public void CrossRegion(ulong newRegionHandle, LLVector3 pos, LLVector3 lookAt, System.Net.IPAddress newRegionIP, ushort newRegionPort)
329 {
330 LLVector3 look = new LLVector3(lookAt.X * 10, lookAt.Y * 10, lookAt.Z * 10);
331
332 CrossedRegionPacket newSimPack = new CrossedRegionPacket();
333 newSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock();
334 newSimPack.AgentData.AgentID = this.AgentID;
335 newSimPack.AgentData.SessionID = this.SessionID;
336 newSimPack.Info = new CrossedRegionPacket.InfoBlock();
337 newSimPack.Info.Position = pos;
338 newSimPack.Info.LookAt = look; // new LLVector3(0.0f, 0.0f, 0.0f); // copied from Avatar.cs - SHOULD BE DYNAMIC!!!!!!!!!!
339 newSimPack.RegionData = new libsecondlife.Packets.CrossedRegionPacket.RegionDataBlock();
340 newSimPack.RegionData.RegionHandle = newRegionHandle;
341 byte[] byteIP = newRegionIP.GetAddressBytes();
342 newSimPack.RegionData.SimIP = (uint)byteIP[3] << 24;
343 newSimPack.RegionData.SimIP += (uint)byteIP[2] << 16;
344 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
345 newSimPack.RegionData.SimIP += (uint)byteIP[0];
346 newSimPack.RegionData.SimPort = newRegionPort;
347 newSimPack.RegionData.SeedCapability = new byte[0];
348
349 this.OutPacket(newSimPack);
350 //this.DowngradeClient();
351 }
352
353 public void SendMapBlock(List<MapBlockData> mapBlocks)
354 {
355 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
356
357 MapBlockReplyPacket mapReply = new MapBlockReplyPacket();
358 mapReply.AgentData.AgentID = this.AgentID;
359 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks.Count];
360 mapReply.AgentData.Flags = 0;
361
362 for (int i = 0; i < mapBlocks.Count; i++)
363 {
364 mapReply.Data[i] = new MapBlockReplyPacket.DataBlock();
365 mapReply.Data[i].MapImageID = mapBlocks[i].MapImageId;
366 mapReply.Data[i].X = mapBlocks[i].X;
367 mapReply.Data[i].Y = mapBlocks[i].Y;
368 mapReply.Data[i].WaterHeight = mapBlocks[i].WaterHeight;
369 mapReply.Data[i].Name = _enc.GetBytes(mapBlocks[i].Name);
370 mapReply.Data[i].RegionFlags = mapBlocks[i].RegionFlags;
371 mapReply.Data[i].Access = mapBlocks[i].Access;
372 mapReply.Data[i].Agents = mapBlocks[i].Agents;
373 }
374 this.OutPacket(mapReply);
375 }
376
377 public void SendLocalTeleport(LLVector3 position, LLVector3 lookAt, uint flags)
378 {
379 TeleportLocalPacket tpLocal = new TeleportLocalPacket();
380 tpLocal.Info.AgentID = this.AgentID;
381 tpLocal.Info.TeleportFlags = flags;
382 tpLocal.Info.LocationID = 2;
383 tpLocal.Info.LookAt = lookAt;
384 tpLocal.Info.Position = position;
385 OutPacket(tpLocal);
386 }
387
388 public void SendRegionTeleport(ulong regionHandle, byte simAccess, string ipAddress, ushort ipPort, uint locationID, uint flags)
389 {
390 TeleportFinishPacket teleport = new TeleportFinishPacket();
391 teleport.Info.AgentID = this.AgentID;
392 teleport.Info.RegionHandle = regionHandle;
393 teleport.Info.SimAccess = simAccess;
394 teleport.Info.SeedCapability = new byte[0];
395
396 System.Net.IPAddress oIP = System.Net.IPAddress.Parse(ipAddress);
397 byte[] byteIP = oIP.GetAddressBytes();
398 uint ip = (uint)byteIP[3] << 24;
399 ip += (uint)byteIP[2] << 16;
400 ip += (uint)byteIP[1] << 8;
401 ip += (uint)byteIP[0];
402
403 teleport.Info.SimIP = ip;
404 teleport.Info.SimPort = ipPort;
405 teleport.Info.LocationID = 4;
406 teleport.Info.TeleportFlags = 1 << 4;
407 OutPacket(teleport);
408 }
409
410 /// <summary>
411 ///
412 /// </summary>
413 public void SendTeleportCancel()
414 {
415 TeleportCancelPacket tpCancel = new TeleportCancelPacket();
416 tpCancel.Info.SessionID = this.SessionID;
417 tpCancel.Info.AgentID = this.AgentID;
418
419 OutPacket(tpCancel);
420 }
421
422 /// <summary>
423 ///
424 /// </summary>
425 public void SendTeleportLocationStart()
426 {
427 TeleportStartPacket tpStart = new TeleportStartPacket();
428 tpStart.Info.TeleportFlags = 16; // Teleport via location
429 OutPacket(tpStart);
430 }
431
432 public void SendMoneyBalance(LLUUID transaction, bool success, byte[] description, int balance)
433 {
434 MoneyBalanceReplyPacket money = new MoneyBalanceReplyPacket();
435 money.MoneyData.AgentID = this.AgentID;
436 money.MoneyData.TransactionID = transaction;
437 money.MoneyData.TransactionSuccess = success;
438 money.MoneyData.Description = description;
439 money.MoneyData.MoneyBalance = balance;
440 OutPacket(money);
441 }
442
443 #region Appearance/ Wearables Methods
444
445 /// <summary>
446 ///
447 /// </summary>
448 /// <param name="wearables"></param>
449 public void SendWearables(AvatarWearable[] wearables)
450 {
451 AgentWearablesUpdatePacket aw = new AgentWearablesUpdatePacket();
452 aw.AgentData.AgentID = this.AgentID;
453 aw.AgentData.SerialNum = 0;
454 aw.AgentData.SessionID = this.SessionID;
455
456 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13];
457 AgentWearablesUpdatePacket.WearableDataBlock awb;
458 for (int i = 0; i < wearables.Length; i++)
459 {
460 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
461 awb.WearableType = (byte)i;
462 awb.AssetID = wearables[i].AssetID;
463 awb.ItemID = wearables[i].ItemID;
464 aw.WearableData[i] = awb;
465 }
466
467 this.OutPacket(aw);
468 }
469
470 /// <summary>
471 ///
472 /// </summary>
473 /// <param name="agentID"></param>
474 /// <param name="visualParams"></param>
475 /// <param name="textureEntry"></param>
476 public void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry)
477 {
478 AvatarAppearancePacket avp = new AvatarAppearancePacket();
479 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218];
480 avp.ObjectData.TextureEntry = textureEntry;
481
482 AvatarAppearancePacket.VisualParamBlock avblock = null;
483 for (int i = 0; i < visualParams.Length; i++)
484 {
485 avblock = new AvatarAppearancePacket.VisualParamBlock();
486 avblock.ParamValue = visualParams[i];
487 avp.VisualParam[i] = avblock;
488 }
489
490 avp.Sender.IsTrial = false;
491 avp.Sender.ID = agentID;
492 OutPacket(avp);
493 }
494
495 #endregion
496
497 #region Avatar Packet/data sending Methods
498
499 /// <summary>
500 ///
501 /// </summary>
502 /// <param name="regionInfo"></param>
503 /// <param name="firstName"></param>
504 /// <param name="lastName"></param>
505 /// <param name="avatarID"></param>
506 /// <param name="avatarLocalID"></param>
507 /// <param name="Pos"></param>
508 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID, uint avatarLocalID, LLVector3 Pos, byte[] textureEntry)
509 {
510 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
511 //send a objectupdate packet with information about the clients avatar
512
513 ObjectUpdatePacket objupdate = new ObjectUpdatePacket();
514 objupdate.RegionData.RegionHandle = regionHandle;
515 objupdate.RegionData.TimeDilation = 64096;
516 objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1];
517 objupdate.ObjectData[0] = this.CreateDefaultAvatarPacket(textureEntry);
518 //give this avatar object a local id and assign the user a name
519
520 objupdate.ObjectData[0].ID = avatarLocalID;
521 objupdate.ObjectData[0].FullID = avatarID;
522 objupdate.ObjectData[0].NameValue = _enc.GetBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + " \0");
523 libsecondlife.LLVector3 pos2 = new LLVector3((float)Pos.X, (float)Pos.Y, (float)Pos.Z);
524 byte[] pb = pos2.GetBytes();
525 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
526
527 OutPacket(objupdate);
528
529 }
530
531 /// <summary>
532 ///
533 /// </summary>
534 /// <param name="regionHandle"></param>
535 /// <param name="timeDilation"></param>
536 /// <param name="localID"></param>
537 /// <param name="position"></param>
538 /// <param name="velocity"></param>
539 public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, LLVector3 velocity)
540 {
541 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = this.CreateAvatarImprovedBlock(localID, position, velocity);
542 ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket();
543 terse.RegionData.RegionHandle = regionHandle;
544 terse.RegionData.TimeDilation = timeDilation;
545 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
546 terse.ObjectData[0] = terseBlock;
547
548 this.OutPacket(terse);
549 }
550
551 #endregion
552
553 #region Primitive Packet/data Sending Methods
554
555 /// <summary>
556 ///
557 /// </summary>
558 /// <param name="localID"></param>
559 /// <param name="rotation"></param>
560 /// <param name="attachPoint"></param>
561 public void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint)
562 {
563 ObjectAttachPacket attach = new ObjectAttachPacket();
564 attach.AgentData.AgentID = this.AgentID;
565 attach.AgentData.SessionID = this.SessionID;
566 attach.AgentData.AttachmentPoint = attachPoint;
567 attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
568 attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
569 attach.ObjectData[0].ObjectLocalID = localID;
570 attach.ObjectData[0].Rotation = rotation;
571
572 this.OutPacket(attach);
573 }
574
575 /// <summary>
576 /// Sends a full ObjectUpdatePacket to a client to inform it of a new primitive
577 /// or big changes to a existing primitive.
578 /// </summary>
579 /// <param name="regionHandle"></param>
580 /// <param name="timeDilation"></param>
581 /// <param name="localID"></param>
582 /// <param name="primData"></param>
583 /// <param name="pos"></param>
584 /// <param name="rotation"></param>
585 /// <param name="textureID"></param>
586 public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimData primData, LLVector3 pos, LLQuaternion rotation, LLUUID textureID, uint flags)
587 {
588 ObjectUpdatePacket outPacket = new ObjectUpdatePacket();
589 outPacket.RegionData.RegionHandle = regionHandle;
590 outPacket.RegionData.TimeDilation = timeDilation;
591 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
592 outPacket.ObjectData[0] = this.CreatePrimUpdateBlock(primData, textureID, flags);
593 outPacket.ObjectData[0].ID = localID;
594 outPacket.ObjectData[0].FullID = primData.FullID;
595 byte[] pb = pos.GetBytes();
596 Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length);
597 byte[] rot = rotation.GetBytes();
598 Array.Copy(rot, 0, outPacket.ObjectData[0].ObjectData, 48, rot.Length);
599 OutPacket(outPacket);
600 }
601
602 /// <summary>
603 /// Sends a full ObjectUpdatePacket to a client to inform it of a new primitive
604 /// or big changes to a existing primitive.
605 /// Uses default rotation
606 /// </summary>
607 /// <param name="primData"></param>
608 /// <param name="pos"></param>
609 public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimData primData, LLVector3 pos, LLUUID textureID , uint flags)
610 {
611 ObjectUpdatePacket outPacket = new ObjectUpdatePacket();
612 outPacket.RegionData.RegionHandle = regionHandle;
613 outPacket.RegionData.TimeDilation = timeDilation;
614 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
615 outPacket.ObjectData[0] = this.CreatePrimUpdateBlock(primData, textureID, flags);
616 outPacket.ObjectData[0].ID = localID;
617 outPacket.ObjectData[0].FullID = primData.FullID;
618 byte[] pb = pos.GetBytes();
619 Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length);
620
621 OutPacket(outPacket);
622 }
623
624 /// <summary>
625 ///
626 /// </summary>
627 /// <param name="regionHandle"></param>
628 /// <param name="timeDilation"></param>
629 /// <param name="localID"></param>
630 /// <param name="position"></param>
631 /// <param name="rotation"></param>
632 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, LLQuaternion rotation)
633 {
634 ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket();
635 terse.RegionData.RegionHandle = regionHandle;
636 terse.RegionData.TimeDilation = timeDilation;
637 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
638 terse.ObjectData[0] = this.CreatePrimImprovedBlock(localID, position, rotation);
639
640 this.OutPacket(terse);
641 }
642
643 #endregion
644
645 #endregion
646
647 #region Helper Methods
648
649 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, LLVector3 pos, LLVector3 velocity)
650 {
651 byte[] bytes = new byte[60];
652 int i = 0;
653 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
654
655 dat.TextureEntry = new byte[0];// AvatarTemplate.TextureEntry;
656
657 uint ID = localID;
658
659 bytes[i++] = (byte)(ID % 256);
660 bytes[i++] = (byte)((ID >> 8) % 256);
661 bytes[i++] = (byte)((ID >> 16) % 256);
662 bytes[i++] = (byte)((ID >> 24) % 256);
663 bytes[i++] = 0;
664 bytes[i++] = 1;
665 i += 14;
666 bytes[i++] = 128;
667 bytes[i++] = 63;
668
669 byte[] pb = pos.GetBytes();
670 Array.Copy(pb, 0, bytes, i, pb.Length);
671 i += 12;
672 ushort InternVelocityX;
673 ushort InternVelocityY;
674 ushort InternVelocityZ;
675 Axiom.MathLib.Vector3 internDirec = new Axiom.MathLib.Vector3(0, 0, 0);
676
677 internDirec = new Axiom.MathLib.Vector3(velocity.X, velocity.Y, velocity.Z);
678
679 internDirec = internDirec / 128.0f;
680 internDirec.x += 1;
681 internDirec.y += 1;
682 internDirec.z += 1;
683
684 InternVelocityX = (ushort)(32768 * internDirec.x);
685 InternVelocityY = (ushort)(32768 * internDirec.y);
686 InternVelocityZ = (ushort)(32768 * internDirec.z);
687
688 ushort ac = 32767;
689 bytes[i++] = (byte)(InternVelocityX % 256);
690 bytes[i++] = (byte)((InternVelocityX >> 8) % 256);
691 bytes[i++] = (byte)(InternVelocityY % 256);
692 bytes[i++] = (byte)((InternVelocityY >> 8) % 256);
693 bytes[i++] = (byte)(InternVelocityZ % 256);
694 bytes[i++] = (byte)((InternVelocityZ >> 8) % 256);
695
696 //accel
697 bytes[i++] = (byte)(ac % 256);
698 bytes[i++] = (byte)((ac >> 8) % 256);
699 bytes[i++] = (byte)(ac % 256);
700 bytes[i++] = (byte)((ac >> 8) % 256);
701 bytes[i++] = (byte)(ac % 256);
702 bytes[i++] = (byte)((ac >> 8) % 256);
703
704 //rot
705 bytes[i++] = (byte)(ac % 256);
706 bytes[i++] = (byte)((ac >> 8) % 256);
707 bytes[i++] = (byte)(ac % 256);
708 bytes[i++] = (byte)((ac >> 8) % 256);
709 bytes[i++] = (byte)(ac % 256);
710 bytes[i++] = (byte)((ac >> 8) % 256);
711 bytes[i++] = (byte)(ac % 256);
712 bytes[i++] = (byte)((ac >> 8) % 256);
713
714 //rotation vel
715 bytes[i++] = (byte)(ac % 256);
716 bytes[i++] = (byte)((ac >> 8) % 256);
717 bytes[i++] = (byte)(ac % 256);
718 bytes[i++] = (byte)((ac >> 8) % 256);
719 bytes[i++] = (byte)(ac % 256);
720 bytes[i++] = (byte)((ac >> 8) % 256);
721
722 dat.Data = bytes;
723 return (dat);
724 }
725
726 /// <summary>
727 ///
728 /// </summary>
729 /// <param name="localID"></param>
730 /// <param name="position"></param>
731 /// <param name="rotation"></param>
732 /// <returns></returns>
733 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, LLVector3 position, LLQuaternion rotation)
734 {
735 uint ID = localID;
736 byte[] bytes = new byte[60];
737
738 int i = 0;
739 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
740 dat.TextureEntry = new byte[0];
741 bytes[i++] = (byte)(ID % 256);
742 bytes[i++] = (byte)((ID >> 8) % 256);
743 bytes[i++] = (byte)((ID >> 16) % 256);
744 bytes[i++] = (byte)((ID >> 24) % 256);
745 bytes[i++] = 0;
746 bytes[i++] = 0;
747
748 byte[] pb = position.GetBytes();
749 Array.Copy(pb, 0, bytes, i, pb.Length);
750 i += 12;
751 ushort ac = 32767;
752
753 //vel
754 bytes[i++] = (byte)(ac % 256);
755 bytes[i++] = (byte)((ac >> 8) % 256);
756 bytes[i++] = (byte)(ac % 256);
757 bytes[i++] = (byte)((ac >> 8) % 256);
758 bytes[i++] = (byte)(ac % 256);
759 bytes[i++] = (byte)((ac >> 8) % 256);
760
761 //accel
762 bytes[i++] = (byte)(ac % 256);
763 bytes[i++] = (byte)((ac >> 8) % 256);
764 bytes[i++] = (byte)(ac % 256);
765 bytes[i++] = (byte)((ac >> 8) % 256);
766 bytes[i++] = (byte)(ac % 256);
767 bytes[i++] = (byte)((ac >> 8) % 256);
768
769 ushort rw, rx, ry, rz;
770 rw = (ushort)(32768 * (rotation.W + 1));
771 rx = (ushort)(32768 * (rotation.X + 1));
772 ry = (ushort)(32768 * (rotation.Y + 1));
773 rz = (ushort)(32768 * (rotation.Z + 1));
774
775 //rot
776 bytes[i++] = (byte)(rx % 256);
777 bytes[i++] = (byte)((rx >> 8) % 256);
778 bytes[i++] = (byte)(ry % 256);
779 bytes[i++] = (byte)((ry >> 8) % 256);
780 bytes[i++] = (byte)(rz % 256);
781 bytes[i++] = (byte)((rz >> 8) % 256);
782 bytes[i++] = (byte)(rw % 256);
783 bytes[i++] = (byte)((rw >> 8) % 256);
784
785 //rotation vel
786 bytes[i++] = (byte)(ac % 256);
787 bytes[i++] = (byte)((ac >> 8) % 256);
788 bytes[i++] = (byte)(ac % 256);
789 bytes[i++] = (byte)((ac >> 8) % 256);
790 bytes[i++] = (byte)(ac % 256);
791 bytes[i++] = (byte)((ac >> 8) % 256);
792
793 dat.Data = bytes;
794 return dat;
795 }
796
797
798 /// <summary>
799 /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive)
800 /// </summary>
801 /// <param name="primData"></param>
802 /// <returns></returns>
803 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimData primData, LLUUID textureID, uint flags)
804 {
805 ObjectUpdatePacket.ObjectDataBlock objupdate = new ObjectUpdatePacket.ObjectDataBlock();
806 this.SetDefaultPrimPacketValues(objupdate);
807 objupdate.UpdateFlags = flags;
808 this.SetPrimPacketShapeData(objupdate, primData, textureID);
809
810 return objupdate;
811 }
812
813 /// <summary>
814 /// Copy the data from a PrimData object to a ObjectUpdatePacket
815 /// </summary>
816 /// <param name="objectData"></param>
817 /// <param name="primData"></param>
818 protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimData primData, LLUUID textureID)
819 {
820 LLObject.TextureEntry ntex = new LLObject.TextureEntry(textureID);
821 objectData.TextureEntry = ntex.ToBytes();
822 objectData.OwnerID = primData.OwnerID;
823 objectData.PCode = primData.PCode;
824 objectData.PathBegin = primData.PathBegin;
825 objectData.PathEnd = primData.PathEnd;
826 objectData.PathScaleX = primData.PathScaleX;
827 objectData.PathScaleY = primData.PathScaleY;
828 objectData.PathShearX = primData.PathShearX;
829 objectData.PathShearY = primData.PathShearY;
830 objectData.PathSkew = primData.PathSkew;
831 objectData.ProfileBegin = primData.ProfileBegin;
832 objectData.ProfileEnd = primData.ProfileEnd;
833 objectData.Scale = primData.Scale;
834 objectData.PathCurve = primData.PathCurve;
835 objectData.ProfileCurve = primData.ProfileCurve;
836 objectData.ParentID = primData.ParentID;
837 objectData.ProfileHollow = primData.ProfileHollow;
838 objectData.PathRadiusOffset = primData.PathRadiusOffset;
839 objectData.PathRevolutions = primData.PathRevolutions;
840 objectData.PathTaperX = primData.PathTaperX;
841 objectData.PathTaperY = primData.PathTaperY;
842 objectData.PathTwist = primData.PathTwist;
843 objectData.PathTwistBegin = primData.PathTwistBegin;
844 }
845
846 /// <summary>
847 /// Set some default values in a ObjectUpdatePacket
848 /// </summary>
849 /// <param name="objdata"></param>
850 protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata)
851 {
852 objdata.PSBlock = new byte[0];
853 objdata.ExtraParams = new byte[1];
854 objdata.MediaURL = new byte[0];
855 objdata.NameValue = new byte[0];
856 objdata.Text = new byte[0];
857 objdata.TextColor = new byte[4];
858 objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0);
859 objdata.JointPivot = new LLVector3(0, 0, 0);
860 objdata.Material = 3;
861 objdata.TextureAnim = new byte[0];
862 objdata.Sound = LLUUID.Zero;
863 objdata.State = 0;
864 objdata.Data = new byte[0];
865
866 objdata.ObjectData = new byte[60];
867 objdata.ObjectData[46] = 128;
868 objdata.ObjectData[47] = 63;
869 }
870
871
872 /// <summary>
873 ///
874 /// </summary>
875 /// <returns></returns>
876 protected ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry)
877 {
878 libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock objdata = new ObjectUpdatePacket.ObjectDataBlock(); // new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i);
879
880 SetDefaultAvatarPacketValues(ref objdata);
881 objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24);
882 objdata.PathCurve = 16;
883 objdata.ProfileCurve = 1;
884 objdata.PathScaleX = 100;
885 objdata.PathScaleY = 100;
886 objdata.ParentID = 0;
887 objdata.OwnerID = LLUUID.Zero;
888 objdata.Scale = new LLVector3(1, 1, 1);
889 objdata.PCode = 47;
890 if (textureEntry != null)
891 {
892 objdata.TextureEntry = textureEntry;
893 }
894 System.Text.Encoding enc = System.Text.Encoding.ASCII;
895 libsecondlife.LLVector3 pos = new LLVector3(objdata.ObjectData, 16);
896 pos.X = 100f;
897 objdata.ID = 8880000;
898 objdata.NameValue = enc.GetBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User \0");
899 libsecondlife.LLVector3 pos2 = new LLVector3(100f, 100f, 23f);
900 //objdata.FullID=user.AgentID;
901 byte[] pb = pos.GetBytes();
902 Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length);
903
904 return objdata;
905 }
906
907 /// <summary>
908 ///
909 /// </summary>
910 /// <param name="objdata"></param>
911 protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata)
912 {
913 objdata.PSBlock = new byte[0];
914 objdata.ExtraParams = new byte[1];
915 objdata.MediaURL = new byte[0];
916 objdata.NameValue = new byte[0];
917 objdata.Text = new byte[0];
918 objdata.TextColor = new byte[4];
919 objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0);
920 objdata.JointPivot = new LLVector3(0, 0, 0);
921 objdata.Material = 4;
922 objdata.TextureAnim = new byte[0];
923 objdata.Sound = LLUUID.Zero;
924 LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("00000000-0000-0000-5005-000000000005"));
925 objdata.TextureEntry = ntex.ToBytes();
926 objdata.State = 0;
927 objdata.Data = new byte[0];
928
929 objdata.ObjectData = new byte[76];
930 objdata.ObjectData[15] = 128;
931 objdata.ObjectData[16] = 63;
932 objdata.ObjectData[56] = 128;
933 objdata.ObjectData[61] = 102;
934 objdata.ObjectData[62] = 40;
935 objdata.ObjectData[63] = 61;
936 objdata.ObjectData[64] = 189;
937 }
938
939 /// <summary>
940 ///
941 /// </summary>
942 /// <param name="addPacket"></param>
943 /// <returns></returns>
944 protected PrimData CreatePrimFromObjectAdd(ObjectAddPacket addPacket)
945 {
946 PrimData PData = new PrimData();
947 PData.CreationDate = (Int32)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
948 PData.PCode = addPacket.ObjectData.PCode;
949 PData.PathBegin = addPacket.ObjectData.PathBegin;
950 PData.PathEnd = addPacket.ObjectData.PathEnd;
951 PData.PathScaleX = addPacket.ObjectData.PathScaleX;
952 PData.PathScaleY = addPacket.ObjectData.PathScaleY;
953 PData.PathShearX = addPacket.ObjectData.PathShearX;
954 PData.PathShearY = addPacket.ObjectData.PathShearY;
955 PData.PathSkew = addPacket.ObjectData.PathSkew;
956 PData.ProfileBegin = addPacket.ObjectData.ProfileBegin;
957 PData.ProfileEnd = addPacket.ObjectData.ProfileEnd;
958 PData.Scale = addPacket.ObjectData.Scale;
959 PData.PathCurve = addPacket.ObjectData.PathCurve;
960 PData.ProfileCurve = addPacket.ObjectData.ProfileCurve;
961 PData.ParentID = 0;
962 PData.ProfileHollow = addPacket.ObjectData.ProfileHollow;
963 PData.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset;
964 PData.PathRevolutions = addPacket.ObjectData.PathRevolutions;
965 PData.PathTaperX = addPacket.ObjectData.PathTaperX;
966 PData.PathTaperY = addPacket.ObjectData.PathTaperY;
967 PData.PathTwist = addPacket.ObjectData.PathTwist;
968 PData.PathTwistBegin = addPacket.ObjectData.PathTwistBegin;
969
970 return PData;
971 }
972 #endregion
973
974 }
975}