diff options
Diffstat (limited to 'OpenSim/OpenSim.RegionServer/ClientView.API.cs')
-rw-r--r-- | OpenSim/OpenSim.RegionServer/ClientView.API.cs | 682 |
1 files changed, 682 insertions, 0 deletions
diff --git a/OpenSim/OpenSim.RegionServer/ClientView.API.cs b/OpenSim/OpenSim.RegionServer/ClientView.API.cs new file mode 100644 index 0000000..b9773c6 --- /dev/null +++ b/OpenSim/OpenSim.RegionServer/ClientView.API.cs | |||
@@ -0,0 +1,682 @@ | |||
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 | */ | ||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Text; | ||
31 | using OpenSim.Framework.Interfaces; | ||
32 | using OpenSim.Framework.Inventory; | ||
33 | using OpenSim.Framework.Types; | ||
34 | |||
35 | using libsecondlife; | ||
36 | using libsecondlife.Packets; | ||
37 | |||
38 | namespace 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 GenericCall3 OnAgentUpdate; | ||
51 | public event StartAnim OnStartAnim; | ||
52 | public event GenericCall OnRequestAvatarsData; | ||
53 | public event LinkObjects OnLinkObjects; | ||
54 | public event GenericCall4 OnAddPrim; | ||
55 | public event UpdateShape OnUpdatePrimShape; | ||
56 | public event ObjectSelect OnObjectSelect; | ||
57 | public event UpdatePrimFlags OnUpdatePrimFlags; | ||
58 | public event UpdatePrimTexture OnUpdatePrimTexture; | ||
59 | public event UpdatePrimVector OnUpdatePrimPosition; | ||
60 | public event UpdatePrimRotation OnUpdatePrimRotation; | ||
61 | public event UpdatePrimVector OnUpdatePrimScale; | ||
62 | public event StatusChange OnChildAgentStatus; | ||
63 | public event GenericCall2 OnStopMovement; | ||
64 | public event NewAvatar OnNewAvatar; | ||
65 | public event GenericCall6 OnRemoveAvatar; | ||
66 | |||
67 | public event ParcelPropertiesRequest OnParcelPropertiesRequest; | ||
68 | public event ParcelDivideRequest OnParcelDivideRequest; | ||
69 | public event ParcelJoinRequest OnParcelJoinRequest; | ||
70 | public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; | ||
71 | |||
72 | public event EstateOwnerMessageRequest OnEstateOwnerMessage; | ||
73 | |||
74 | /// <summary> | ||
75 | /// | ||
76 | /// </summary> | ||
77 | public LLVector3 StartPos | ||
78 | { | ||
79 | get | ||
80 | { | ||
81 | return startpos; | ||
82 | } | ||
83 | set | ||
84 | { | ||
85 | startpos = value; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | /// <summary> | ||
90 | /// | ||
91 | /// </summary> | ||
92 | public LLUUID AgentId | ||
93 | { | ||
94 | get | ||
95 | { | ||
96 | return this.AgentID; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /// <summary> | ||
101 | /// | ||
102 | /// </summary> | ||
103 | public string FirstName | ||
104 | { | ||
105 | get | ||
106 | { | ||
107 | return this.firstName; | ||
108 | } | ||
109 | |||
110 | } | ||
111 | |||
112 | /// <summary> | ||
113 | /// | ||
114 | /// </summary> | ||
115 | public string LastName | ||
116 | { | ||
117 | get | ||
118 | { | ||
119 | return this.lastName; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | #region World/Avatar to Client | ||
124 | |||
125 | /// <summary> | ||
126 | /// | ||
127 | /// </summary> | ||
128 | /// <param name="regionInfo"></param> | ||
129 | public void SendRegionHandshake(RegionInfo regionInfo) | ||
130 | { | ||
131 | System.Text.Encoding _enc = System.Text.Encoding.ASCII; | ||
132 | RegionHandshakePacket handshake = new RegionHandshakePacket(); | ||
133 | |||
134 | handshake.RegionInfo.BillableFactor = regionInfo.estateSettings.billableFactor; | ||
135 | handshake.RegionInfo.IsEstateManager = false; | ||
136 | handshake.RegionInfo.TerrainHeightRange00 = regionInfo.estateSettings.terrainHeightRange0; | ||
137 | handshake.RegionInfo.TerrainHeightRange01 = regionInfo.estateSettings.terrainHeightRange1; | ||
138 | handshake.RegionInfo.TerrainHeightRange10 = regionInfo.estateSettings.terrainHeightRange2; | ||
139 | handshake.RegionInfo.TerrainHeightRange11 = regionInfo.estateSettings.terrainHeightRange3; | ||
140 | handshake.RegionInfo.TerrainStartHeight00 = regionInfo.estateSettings.terrainStartHeight0; | ||
141 | handshake.RegionInfo.TerrainStartHeight01 = regionInfo.estateSettings.terrainStartHeight1; | ||
142 | handshake.RegionInfo.TerrainStartHeight10 = regionInfo.estateSettings.terrainStartHeight2; | ||
143 | handshake.RegionInfo.TerrainStartHeight11 = regionInfo.estateSettings.terrainStartHeight3; | ||
144 | handshake.RegionInfo.SimAccess = (byte)regionInfo.estateSettings.simAccess; | ||
145 | handshake.RegionInfo.WaterHeight = regionInfo.estateSettings.waterHeight; | ||
146 | |||
147 | |||
148 | handshake.RegionInfo.RegionFlags = (uint)regionInfo.estateSettings.regionFlags; | ||
149 | |||
150 | handshake.RegionInfo.SimName = _enc.GetBytes(regionInfo.estateSettings.waterHeight + "\0"); | ||
151 | handshake.RegionInfo.SimOwner = regionInfo.MasterAvatarAssignedUUID; | ||
152 | handshake.RegionInfo.TerrainBase0 = regionInfo.estateSettings.terrainBase0; | ||
153 | handshake.RegionInfo.TerrainBase1 = regionInfo.estateSettings.terrainBase1; | ||
154 | handshake.RegionInfo.TerrainBase2 = regionInfo.estateSettings.terrainBase2; | ||
155 | handshake.RegionInfo.TerrainBase3 = regionInfo.estateSettings.terrainBase3; | ||
156 | handshake.RegionInfo.TerrainDetail0 = regionInfo.estateSettings.terrainDetail0; | ||
157 | handshake.RegionInfo.TerrainDetail1 = regionInfo.estateSettings.terrainDetail1; | ||
158 | handshake.RegionInfo.TerrainDetail2 =regionInfo.estateSettings.terrainDetail2; | ||
159 | handshake.RegionInfo.TerrainDetail3 = regionInfo.estateSettings.terrainDetail3; | ||
160 | handshake.RegionInfo.CacheID = LLUUID.Random(); //I guess this is for the client to remember an old setting? | ||
161 | |||
162 | this.OutPacket(handshake); | ||
163 | } | ||
164 | |||
165 | /// <summary> | ||
166 | /// | ||
167 | /// </summary> | ||
168 | /// <param name="regInfo"></param> | ||
169 | public void MoveAgentIntoRegion(RegionInfo regInfo) | ||
170 | { | ||
171 | AgentMovementCompletePacket mov = new AgentMovementCompletePacket(); | ||
172 | mov.AgentData.SessionID = this.SessionID; | ||
173 | mov.AgentData.AgentID = this.AgentID; | ||
174 | mov.Data.RegionHandle = regInfo.RegionHandle; | ||
175 | // TODO - dynamicalise this stuff | ||
176 | mov.Data.Timestamp = 1172750370; | ||
177 | mov.Data.Position = this.startpos; | ||
178 | mov.Data.LookAt = new LLVector3(0.99f, 0.042f, 0); | ||
179 | |||
180 | OutPacket(mov); | ||
181 | } | ||
182 | |||
183 | public void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID) | ||
184 | { | ||
185 | SendChatMessage( Helpers.StringToField( message ), type, fromPos, fromName, fromAgentID); | ||
186 | } | ||
187 | |||
188 | /// <summary> | ||
189 | /// | ||
190 | /// </summary> | ||
191 | /// <param name="message"></param> | ||
192 | /// <param name="type"></param> | ||
193 | /// <param name="fromPos"></param> | ||
194 | /// <param name="fromName"></param> | ||
195 | /// <param name="fromAgentID"></param> | ||
196 | public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID) | ||
197 | { | ||
198 | System.Text.Encoding enc = System.Text.Encoding.ASCII; | ||
199 | libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); | ||
200 | reply.ChatData.Audible = 1; | ||
201 | reply.ChatData.Message = message; | ||
202 | reply.ChatData.ChatType = type; | ||
203 | reply.ChatData.SourceType = 1; | ||
204 | reply.ChatData.Position = fromPos; | ||
205 | reply.ChatData.FromName = enc.GetBytes(fromName + "\0"); | ||
206 | reply.ChatData.OwnerID = fromAgentID; | ||
207 | reply.ChatData.SourceID = fromAgentID; | ||
208 | |||
209 | this.OutPacket(reply); | ||
210 | } | ||
211 | |||
212 | |||
213 | /// <summary> | ||
214 | /// Send the region heightmap to the client | ||
215 | /// </summary> | ||
216 | /// <param name="map">heightmap</param> | ||
217 | public virtual void SendLayerData(float[] map) | ||
218 | { | ||
219 | try | ||
220 | { | ||
221 | int[] patches = new int[4]; | ||
222 | |||
223 | for (int y = 0; y < 16; y++) | ||
224 | { | ||
225 | for (int x = 0; x < 16; x = x + 4) | ||
226 | { | ||
227 | patches[0] = x + 0 + y * 16; | ||
228 | patches[1] = x + 1 + y * 16; | ||
229 | patches[2] = x + 2 + y * 16; | ||
230 | patches[3] = x + 3 + y * 16; | ||
231 | |||
232 | Packet layerpack = TerrainManager.CreateLandPacket(map, patches); | ||
233 | OutPacket(layerpack); | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | catch (Exception e) | ||
238 | { | ||
239 | OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "ClientView API.cs: SendLayerData() - Failed with exception " + e.ToString()); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | /// <summary> | ||
244 | /// Sends a specified patch to a client | ||
245 | /// </summary> | ||
246 | /// <param name="px">Patch coordinate (x) 0..16</param> | ||
247 | /// <param name="py">Patch coordinate (y) 0..16</param> | ||
248 | /// <param name="map">heightmap</param> | ||
249 | public void SendLayerData(int px, int py, float[] map) | ||
250 | { | ||
251 | try | ||
252 | { | ||
253 | int[] patches = new int[1]; | ||
254 | int patchx, patchy; | ||
255 | patchx = px / 16; | ||
256 | patchy = py / 16; | ||
257 | |||
258 | patches[0] = patchx + 0 + patchy * 16; | ||
259 | |||
260 | Packet layerpack = TerrainManager.CreateLandPacket(map, patches); | ||
261 | OutPacket(layerpack); | ||
262 | } | ||
263 | catch (Exception e) | ||
264 | { | ||
265 | OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "ClientView API .cs: SendLayerData() - Failed with exception " + e.ToString()); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | public void InformClientOfNeighbour(ulong neighbourHandle, System.Net.IPAddress neighbourIP, ushort neighbourPort) | ||
270 | { | ||
271 | EnableSimulatorPacket enablesimpacket = new EnableSimulatorPacket(); | ||
272 | enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock(); | ||
273 | enablesimpacket.SimulatorInfo.Handle = neighbourHandle; | ||
274 | |||
275 | byte[] byteIP = neighbourIP.GetAddressBytes(); | ||
276 | enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24; | ||
277 | enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16; | ||
278 | enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8; | ||
279 | enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0]; | ||
280 | enablesimpacket.SimulatorInfo.Port = neighbourPort; | ||
281 | OutPacket(enablesimpacket); | ||
282 | } | ||
283 | |||
284 | public AgentCircuitData RequestClientInfo() | ||
285 | { | ||
286 | AgentCircuitData agentData = new AgentCircuitData(); | ||
287 | agentData.AgentID = this.AgentId; | ||
288 | agentData.SessionID = this.SessionID; | ||
289 | agentData.SecureSessionID = this.SecureSessionID; | ||
290 | agentData.circuitcode = this.CircuitCode; | ||
291 | agentData.child = false; | ||
292 | agentData.firstname = this.firstName; | ||
293 | agentData.lastname = this.lastName; | ||
294 | |||
295 | return agentData; | ||
296 | } | ||
297 | |||
298 | #region Appearance/ Wearables Methods | ||
299 | |||
300 | /// <summary> | ||
301 | /// | ||
302 | /// </summary> | ||
303 | /// <param name="wearables"></param> | ||
304 | public void SendWearables(AvatarWearable[] wearables) | ||
305 | { | ||
306 | AgentWearablesUpdatePacket aw = new AgentWearablesUpdatePacket(); | ||
307 | aw.AgentData.AgentID = this.AgentID; | ||
308 | aw.AgentData.SerialNum = 0; | ||
309 | aw.AgentData.SessionID = this.SessionID; | ||
310 | |||
311 | aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; | ||
312 | AgentWearablesUpdatePacket.WearableDataBlock awb; | ||
313 | for (int i = 0; i < wearables.Length; i++) | ||
314 | { | ||
315 | awb = new AgentWearablesUpdatePacket.WearableDataBlock(); | ||
316 | awb.WearableType = (byte)i; | ||
317 | awb.AssetID = wearables[i].AssetID; | ||
318 | awb.ItemID = wearables[i].ItemID; | ||
319 | aw.WearableData[i] = awb; | ||
320 | } | ||
321 | |||
322 | this.OutPacket(aw); | ||
323 | } | ||
324 | |||
325 | /// <summary> | ||
326 | /// | ||
327 | /// </summary> | ||
328 | /// <param name="agentID"></param> | ||
329 | /// <param name="visualParams"></param> | ||
330 | /// <param name="textureEntry"></param> | ||
331 | public void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry) | ||
332 | { | ||
333 | AvatarAppearancePacket avp = new AvatarAppearancePacket(); | ||
334 | avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; | ||
335 | avp.ObjectData.TextureEntry = textureEntry; | ||
336 | |||
337 | AvatarAppearancePacket.VisualParamBlock avblock = null; | ||
338 | for (int i = 0; i < visualParams.Length; i++) | ||
339 | { | ||
340 | avblock = new AvatarAppearancePacket.VisualParamBlock(); | ||
341 | avblock.ParamValue = visualParams[i]; | ||
342 | avp.VisualParam[i] = avblock; | ||
343 | } | ||
344 | |||
345 | avp.Sender.IsTrial = false; | ||
346 | avp.Sender.ID = agentID; | ||
347 | OutPacket(avp); | ||
348 | } | ||
349 | |||
350 | #endregion | ||
351 | |||
352 | #region Avatar Packet/data sending Methods | ||
353 | |||
354 | /// <summary> | ||
355 | /// | ||
356 | /// </summary> | ||
357 | /// <param name="regionInfo"></param> | ||
358 | /// <param name="firstName"></param> | ||
359 | /// <param name="lastName"></param> | ||
360 | /// <param name="avatarID"></param> | ||
361 | /// <param name="avatarLocalID"></param> | ||
362 | /// <param name="Pos"></param> | ||
363 | public void SendAvatarData(RegionInfo regionInfo, string firstName, string lastName, LLUUID avatarID, uint avatarLocalID, LLVector3 Pos) | ||
364 | { | ||
365 | System.Text.Encoding _enc = System.Text.Encoding.ASCII; | ||
366 | //send a objectupdate packet with information about the clients avatar | ||
367 | |||
368 | ObjectUpdatePacket objupdate = new ObjectUpdatePacket(); | ||
369 | objupdate.RegionData.RegionHandle = regionInfo.RegionHandle; | ||
370 | objupdate.RegionData.TimeDilation = 64096; | ||
371 | objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1]; | ||
372 | objupdate.ObjectData[0] = this.CreateDefaultAvatarPacket(); | ||
373 | //give this avatar object a local id and assign the user a name | ||
374 | |||
375 | objupdate.ObjectData[0].ID = avatarLocalID; | ||
376 | objupdate.ObjectData[0].FullID = avatarID; | ||
377 | objupdate.ObjectData[0].NameValue = _enc.GetBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + " \0"); | ||
378 | libsecondlife.LLVector3 pos2 = new LLVector3((float)Pos.X, (float)Pos.Y, (float)Pos.Z); | ||
379 | byte[] pb = pos2.GetBytes(); | ||
380 | Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); | ||
381 | |||
382 | OutPacket(objupdate); | ||
383 | |||
384 | } | ||
385 | |||
386 | |||
387 | /// <summary> | ||
388 | /// | ||
389 | /// </summary> | ||
390 | /// <param name="objdata"></param> | ||
391 | protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) | ||
392 | { | ||
393 | objdata.PSBlock = new byte[0]; | ||
394 | objdata.ExtraParams = new byte[1]; | ||
395 | objdata.MediaURL = new byte[0]; | ||
396 | objdata.NameValue = new byte[0]; | ||
397 | objdata.Text = new byte[0]; | ||
398 | objdata.TextColor = new byte[4]; | ||
399 | objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0); | ||
400 | objdata.JointPivot = new LLVector3(0, 0, 0); | ||
401 | objdata.Material = 4; | ||
402 | objdata.TextureAnim = new byte[0]; | ||
403 | objdata.Sound = LLUUID.Zero; | ||
404 | LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("00000000-0000-0000-5005-000000000005")); | ||
405 | objdata.TextureEntry = ntex.ToBytes(); | ||
406 | objdata.State = 0; | ||
407 | objdata.Data = new byte[0]; | ||
408 | |||
409 | objdata.ObjectData = new byte[76]; | ||
410 | objdata.ObjectData[15] = 128; | ||
411 | objdata.ObjectData[16] = 63; | ||
412 | objdata.ObjectData[56] = 128; | ||
413 | objdata.ObjectData[61] = 102; | ||
414 | objdata.ObjectData[62] = 40; | ||
415 | objdata.ObjectData[63] = 61; | ||
416 | objdata.ObjectData[64] = 189; | ||
417 | } | ||
418 | |||
419 | /// <summary> | ||
420 | /// | ||
421 | /// </summary> | ||
422 | /// <returns></returns> | ||
423 | protected ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket() | ||
424 | { | ||
425 | libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock objdata = new ObjectUpdatePacket.ObjectDataBlock(); // new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); | ||
426 | |||
427 | SetDefaultAvatarPacketValues(ref objdata); | ||
428 | objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); | ||
429 | objdata.PathCurve = 16; | ||
430 | objdata.ProfileCurve = 1; | ||
431 | objdata.PathScaleX = 100; | ||
432 | objdata.PathScaleY = 100; | ||
433 | objdata.ParentID = 0; | ||
434 | objdata.OwnerID = LLUUID.Zero; | ||
435 | objdata.Scale = new LLVector3(1, 1, 1); | ||
436 | objdata.PCode = 47; | ||
437 | System.Text.Encoding enc = System.Text.Encoding.ASCII; | ||
438 | libsecondlife.LLVector3 pos = new LLVector3(objdata.ObjectData, 16); | ||
439 | pos.X = 100f; | ||
440 | objdata.ID = 8880000; | ||
441 | objdata.NameValue = enc.GetBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User \0"); | ||
442 | libsecondlife.LLVector3 pos2 = new LLVector3(100f, 100f, 23f); | ||
443 | //objdata.FullID=user.AgentID; | ||
444 | byte[] pb = pos.GetBytes(); | ||
445 | Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); | ||
446 | |||
447 | return objdata; | ||
448 | } | ||
449 | |||
450 | #endregion | ||
451 | |||
452 | #region Primitive Packet/data Sending Methods | ||
453 | |||
454 | /// <summary> | ||
455 | /// | ||
456 | /// </summary> | ||
457 | /// <param name="localID"></param> | ||
458 | /// <param name="rotation"></param> | ||
459 | /// <param name="attachPoint"></param> | ||
460 | public void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint) | ||
461 | { | ||
462 | ObjectAttachPacket attach = new ObjectAttachPacket(); | ||
463 | attach.AgentData.AgentID = this.AgentID; | ||
464 | attach.AgentData.SessionID = this.SessionID; | ||
465 | attach.AgentData.AttachmentPoint = attachPoint; | ||
466 | attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; | ||
467 | attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); | ||
468 | attach.ObjectData[0].ObjectLocalID = localID; | ||
469 | attach.ObjectData[0].Rotation = rotation; | ||
470 | |||
471 | this.OutPacket(attach); | ||
472 | } | ||
473 | |||
474 | /// <summary> | ||
475 | /// Sends a full ObjectUpdatePacket to a client to inform it of a new primitive | ||
476 | /// or big changes to a existing primitive. | ||
477 | /// </summary> | ||
478 | /// <param name="regionHandle"></param> | ||
479 | /// <param name="timeDilation"></param> | ||
480 | /// <param name="localID"></param> | ||
481 | /// <param name="primData"></param> | ||
482 | /// <param name="pos"></param> | ||
483 | /// <param name="rotation"></param> | ||
484 | /// <param name="textureID"></param> | ||
485 | public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimData primData, LLVector3 pos, LLQuaternion rotation, LLUUID textureID) | ||
486 | { | ||
487 | ObjectUpdatePacket outPacket = new ObjectUpdatePacket(); | ||
488 | outPacket.RegionData.RegionHandle = regionHandle; | ||
489 | outPacket.RegionData.TimeDilation = timeDilation; | ||
490 | outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; | ||
491 | outPacket.ObjectData[0] = this.CreatePrimUpdateBlock(primData, textureID); | ||
492 | outPacket.ObjectData[0].ID = localID; | ||
493 | outPacket.ObjectData[0].FullID = primData.FullID; | ||
494 | byte[] pb = pos.GetBytes(); | ||
495 | Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length); | ||
496 | byte[] rot = rotation.GetBytes(); | ||
497 | Array.Copy(rot, 0, outPacket.ObjectData[0].ObjectData, 48, rot.Length); | ||
498 | OutPacket(outPacket); | ||
499 | } | ||
500 | |||
501 | /// <summary> | ||
502 | /// Sends a full ObjectUpdatePacket to a client to inform it of a new primitive | ||
503 | /// or big changes to a existing primitive. | ||
504 | /// uses default rotation | ||
505 | /// </summary> | ||
506 | /// <param name="primData"></param> | ||
507 | /// <param name="pos"></param> | ||
508 | public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimData primData, LLVector3 pos, LLUUID textureID) | ||
509 | { | ||
510 | ObjectUpdatePacket outPacket = new ObjectUpdatePacket(); | ||
511 | outPacket.RegionData.RegionHandle = regionHandle; | ||
512 | outPacket.RegionData.TimeDilation = timeDilation; | ||
513 | outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; | ||
514 | outPacket.ObjectData[0] = this.CreatePrimUpdateBlock(primData, textureID); | ||
515 | outPacket.ObjectData[0].ID = localID; | ||
516 | outPacket.ObjectData[0].FullID = primData.FullID; | ||
517 | byte[] pb = pos.GetBytes(); | ||
518 | Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length); | ||
519 | |||
520 | OutPacket(outPacket); | ||
521 | } | ||
522 | |||
523 | /// <summary> | ||
524 | /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) | ||
525 | /// </summary> | ||
526 | /// <param name="primData"></param> | ||
527 | /// <returns></returns> | ||
528 | protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimData primData, LLUUID textureID) | ||
529 | { | ||
530 | ObjectUpdatePacket.ObjectDataBlock objupdate = new ObjectUpdatePacket.ObjectDataBlock(); | ||
531 | this.SetDefaultPrimPacketValues(objupdate); | ||
532 | objupdate.UpdateFlags = 32 + 65536 + 131072 + 256 + 4 + 8 + 2048 + 524288 + 268435456; | ||
533 | this.SetPrimPacketShapeData(objupdate, primData, textureID); | ||
534 | |||
535 | return objupdate; | ||
536 | } | ||
537 | |||
538 | /// <summary> | ||
539 | /// Set some default values in a ObjectUpdatePacket | ||
540 | /// </summary> | ||
541 | /// <param name="objdata"></param> | ||
542 | protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) | ||
543 | { | ||
544 | objdata.PSBlock = new byte[0]; | ||
545 | objdata.ExtraParams = new byte[1]; | ||
546 | objdata.MediaURL = new byte[0]; | ||
547 | objdata.NameValue = new byte[0]; | ||
548 | objdata.Text = new byte[0]; | ||
549 | objdata.TextColor = new byte[4]; | ||
550 | objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0); | ||
551 | objdata.JointPivot = new LLVector3(0, 0, 0); | ||
552 | objdata.Material = 3; | ||
553 | objdata.TextureAnim = new byte[0]; | ||
554 | objdata.Sound = LLUUID.Zero; | ||
555 | objdata.State = 0; | ||
556 | objdata.Data = new byte[0]; | ||
557 | |||
558 | objdata.ObjectData = new byte[60]; | ||
559 | objdata.ObjectData[46] = 128; | ||
560 | objdata.ObjectData[47] = 63; | ||
561 | } | ||
562 | |||
563 | /// <summary> | ||
564 | /// Copy the data from a PrimData object to a ObjectUpdatePacket | ||
565 | /// </summary> | ||
566 | /// <param name="objectData"></param> | ||
567 | /// <param name="primData"></param> | ||
568 | protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimData primData, LLUUID textureID) | ||
569 | { | ||
570 | LLObject.TextureEntry ntex = new LLObject.TextureEntry(textureID); | ||
571 | objectData.TextureEntry = ntex.ToBytes(); | ||
572 | objectData.OwnerID = primData.OwnerID; | ||
573 | objectData.PCode = primData.PCode; | ||
574 | objectData.PathBegin =primData.PathBegin; | ||
575 | objectData.PathEnd = primData.PathEnd; | ||
576 | objectData.PathScaleX = primData.PathScaleX; | ||
577 | objectData.PathScaleY = primData.PathScaleY; | ||
578 | objectData.PathShearX = primData.PathShearX; | ||
579 | objectData.PathShearY = primData.PathShearY; | ||
580 | objectData.PathSkew = primData.PathSkew; | ||
581 | objectData.ProfileBegin = primData.ProfileBegin; | ||
582 | objectData.ProfileEnd = primData.ProfileEnd; | ||
583 | objectData.Scale = primData.Scale; | ||
584 | objectData.PathCurve = primData.PathCurve; | ||
585 | objectData.ProfileCurve = primData.ProfileCurve; | ||
586 | objectData.ParentID = primData.ParentID; | ||
587 | objectData.ProfileHollow = primData.ProfileHollow; | ||
588 | objectData.PathRadiusOffset = primData.PathRadiusOffset; | ||
589 | objectData.PathRevolutions = primData.PathRevolutions; | ||
590 | objectData.PathTaperX = primData.PathTaperX; | ||
591 | objectData.PathTaperY = primData.PathTaperY; | ||
592 | objectData.PathTwist = primData.PathTwist; | ||
593 | objectData.PathTwistBegin = primData.PathTwistBegin; | ||
594 | } | ||
595 | |||
596 | public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, LLQuaternion rotation) | ||
597 | { | ||
598 | ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket(); | ||
599 | terse.RegionData.RegionHandle = regionHandle; | ||
600 | terse.RegionData.TimeDilation = timeDilation; | ||
601 | terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | ||
602 | terse.ObjectData[0] = this.CreatePrimImprovedBlock(localID, position, rotation); | ||
603 | |||
604 | this.OutPacket(terse); | ||
605 | } | ||
606 | |||
607 | /// <summary> | ||
608 | /// | ||
609 | /// </summary> | ||
610 | /// <param name="localID"></param> | ||
611 | /// <param name="position"></param> | ||
612 | /// <param name="rotation"></param> | ||
613 | /// <returns></returns> | ||
614 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, LLVector3 position, LLQuaternion rotation) | ||
615 | { | ||
616 | uint ID = localID; | ||
617 | byte[] bytes = new byte[60]; | ||
618 | |||
619 | int i = 0; | ||
620 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); | ||
621 | dat.TextureEntry = new byte[0]; | ||
622 | bytes[i++] = (byte)(ID % 256); | ||
623 | bytes[i++] = (byte)((ID >> 8) % 256); | ||
624 | bytes[i++] = (byte)((ID >> 16) % 256); | ||
625 | bytes[i++] = (byte)((ID >> 24) % 256); | ||
626 | bytes[i++] = 0; | ||
627 | bytes[i++] = 0; | ||
628 | |||
629 | byte[] pb = position.GetBytes(); | ||
630 | Array.Copy(pb, 0, bytes, i, pb.Length); | ||
631 | i += 12; | ||
632 | ushort ac = 32767; | ||
633 | |||
634 | //vel | ||
635 | bytes[i++] = (byte)(ac % 256); | ||
636 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
637 | bytes[i++] = (byte)(ac % 256); | ||
638 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
639 | bytes[i++] = (byte)(ac % 256); | ||
640 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
641 | |||
642 | //accel | ||
643 | bytes[i++] = (byte)(ac % 256); | ||
644 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
645 | bytes[i++] = (byte)(ac % 256); | ||
646 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
647 | bytes[i++] = (byte)(ac % 256); | ||
648 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
649 | |||
650 | ushort rw, rx, ry, rz; | ||
651 | rw = (ushort)(32768 * (rotation.W + 1)); | ||
652 | rx = (ushort)(32768 * (rotation.X + 1)); | ||
653 | ry = (ushort)(32768 * (rotation.Y + 1)); | ||
654 | rz = (ushort)(32768 * (rotation.Z + 1)); | ||
655 | |||
656 | //rot | ||
657 | bytes[i++] = (byte)(rx % 256); | ||
658 | bytes[i++] = (byte)((rx >> 8) % 256); | ||
659 | bytes[i++] = (byte)(ry % 256); | ||
660 | bytes[i++] = (byte)((ry >> 8) % 256); | ||
661 | bytes[i++] = (byte)(rz % 256); | ||
662 | bytes[i++] = (byte)((rz >> 8) % 256); | ||
663 | bytes[i++] = (byte)(rw % 256); | ||
664 | bytes[i++] = (byte)((rw >> 8) % 256); | ||
665 | |||
666 | //rotation vel | ||
667 | bytes[i++] = (byte)(ac % 256); | ||
668 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
669 | bytes[i++] = (byte)(ac % 256); | ||
670 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
671 | bytes[i++] = (byte)(ac % 256); | ||
672 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
673 | |||
674 | dat.Data = bytes; | ||
675 | return dat; | ||
676 | } | ||
677 | #endregion | ||
678 | |||
679 | #endregion | ||
680 | |||
681 | } | ||
682 | } | ||