diff options
author | Mike Mazur | 2008-08-08 05:57:14 +0000 |
---|---|---|
committer | Mike Mazur | 2008-08-08 05:57:14 +0000 |
commit | 1040f3f454a6f469dcd74f19c45ea67d0584ade1 (patch) | |
tree | 36076b1a16ae66f3451666856e3f52f875e7d8a8 /OpenSim | |
parent | Committing first draft of the universal cache. This is by no means (diff) | |
download | opensim-SC-1040f3f454a6f469dcd74f19c45ea67d0584ade1.zip opensim-SC-1040f3f454a6f469dcd74f19c45ea67d0584ade1.tar.gz opensim-SC-1040f3f454a6f469dcd74f19c45ea67d0584ade1.tar.bz2 opensim-SC-1040f3f454a6f469dcd74f19c45ea67d0584ade1.tar.xz |
Remove FunSL client stack as it's under development and often won't compile.
This effectively undoes commits 5771 and 5769 as well as parts of the
formatting cleanup commits 5774 and 5775.
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Region/ClientStack/FunSLUDP/LLClientStackNetworkHandler.cs | 38 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/FunSLUDP/LLClientView.cs | 6315 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/FunSLUDP/LLPacketHandler.cs | 702 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/FunSLUDP/LLPacketQueue.cs | 567 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/FunSLUDP/LLPacketServer.cs | 150 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/FunSLUDP/LLPacketThrottle.cs | 93 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/FunSLUDP/LLQueItem.cs | 45 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/FunSLUDP/LLUDPServer.cs | 545 |
8 files changed, 0 insertions, 8455 deletions
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLClientStackNetworkHandler.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLClientStackNetworkHandler.cs deleted file mode 100644 index cfa2ce9..0000000 --- a/OpenSim/Region/ClientStack/FunSLUDP/LLClientStackNetworkHandler.cs +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.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.Net.Sockets; | ||
29 | |||
30 | namespace OpenSim.Region.ClientStack.FunSLUDP | ||
31 | { | ||
32 | public interface LLClientStackNetworkHandler | ||
33 | { | ||
34 | void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode); // EndPoint packetSender); | ||
35 | void RemoveClientCircuit(uint circuitcode); | ||
36 | void RegisterPacketServer(LLPacketServer server); | ||
37 | } | ||
38 | } | ||
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLClientView.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLClientView.cs deleted file mode 100644 index 1e73152..0000000 --- a/OpenSim/Region/ClientStack/FunSLUDP/LLClientView.cs +++ /dev/null | |||
@@ -1,6315 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.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.Net; | ||
31 | using System.Net.Sockets; | ||
32 | using System.Reflection; | ||
33 | using System.Text; | ||
34 | using System.Threading; | ||
35 | using System.Timers; | ||
36 | using Axiom.Math; | ||
37 | using libsecondlife; | ||
38 | using libsecondlife.Packets; | ||
39 | using log4net; | ||
40 | using OpenSim.Framework; | ||
41 | using OpenSim.Framework.Communications.Cache; | ||
42 | using OpenSim.Framework.Statistics; | ||
43 | using OpenSim.Region.ClientStack.FunSLUDP; | ||
44 | using OpenSim.Region.Environment.Scenes; | ||
45 | using Timer = System.Timers.Timer; | ||
46 | |||
47 | namespace OpenSim.Region.ClientStack.FunSLUDP | ||
48 | { | ||
49 | public delegate bool PacketMethod(IClientAPI simClient, Packet packet); | ||
50 | |||
51 | |||
52 | /// <summary> | ||
53 | /// Handles new client connections | ||
54 | /// Constructor takes a single Packet and authenticates everything | ||
55 | /// </summary> | ||
56 | public class LLClientView : IClientAPI | ||
57 | { | ||
58 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
59 | |||
60 | // ~ClientView() | ||
61 | // { | ||
62 | // m_log.Info("[CLIENTVIEW]: Destructor called"); | ||
63 | // } | ||
64 | |||
65 | /* static variables */ | ||
66 | public static TerrainManager TerrainManager = new TerrainManager(new SecondLife()); | ||
67 | |||
68 | public static SynchronizeClientHandler SynchronizeClient = null; | ||
69 | /* private variables */ | ||
70 | private readonly LLUUID m_sessionId; | ||
71 | private LLUUID m_secureSessionId = LLUUID.Zero; | ||
72 | //private AgentAssetUpload UploadAssets; | ||
73 | private int m_debug = 0; | ||
74 | private readonly AssetCache m_assetCache; | ||
75 | // private InventoryCache m_inventoryCache; | ||
76 | private int m_cachedTextureSerial = 0; | ||
77 | private Timer m_clientPingTimer; | ||
78 | |||
79 | private bool m_clientBlocked = false; | ||
80 | |||
81 | private int m_probesWithNoIngressPackets = 0; | ||
82 | //private int m_lastPacketsReceived = 0; | ||
83 | private byte[] ZeroOutBuffer = new byte[4096]; | ||
84 | |||
85 | private readonly LLUUID m_agentId; | ||
86 | private readonly uint m_circuitCode; | ||
87 | private int m_moneyBalance; | ||
88 | private IPacketHandler m_PacketHandler; | ||
89 | |||
90 | private int m_animationSequenceNumber = 1; | ||
91 | |||
92 | private byte[] m_channelVersion = Helpers.StringToField("OpenSimulator 0.5"); // Dummy value needed by libSL | ||
93 | |||
94 | private Dictionary<string, LLUUID> m_defaultAnimations = new Dictionary<string, LLUUID>(); | ||
95 | |||
96 | /* protected variables */ | ||
97 | |||
98 | protected static Dictionary<PacketType, PacketMethod> PacketHandlers = | ||
99 | new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients | ||
100 | |||
101 | protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); | ||
102 | |||
103 | protected IScene m_scene; | ||
104 | protected AgentCircuitManager m_authenticateSessionsHandler; | ||
105 | |||
106 | protected LLPacketServer m_networkServer; | ||
107 | |||
108 | /* public variables */ | ||
109 | protected string m_firstName; | ||
110 | protected string m_lastName; | ||
111 | protected Thread m_clientThread; | ||
112 | protected LLVector3 m_startpos; | ||
113 | protected EndPoint m_userEndPoint; | ||
114 | protected EndPoint m_proxyEndPoint; | ||
115 | protected LLUUID m_activeGroupID = LLUUID.Zero; | ||
116 | protected string m_activeGroupName = String.Empty; | ||
117 | protected ulong m_activeGroupPowers = 0; | ||
118 | protected Dictionary<LLUUID,ulong> m_groupPowers = new Dictionary<LLUUID, ulong>(); | ||
119 | |||
120 | /* Instantiated Designated Event Delegates */ | ||
121 | //- used so we don't create new objects for each incoming packet and then toss it out later */ | ||
122 | |||
123 | private RequestAvatarProperties handlerRequestAvatarProperties = null; //OnRequestAvatarProperties; | ||
124 | private UpdateAvatarProperties handlerUpdateAvatarProperties = null; // OnUpdateAvatarProperties; | ||
125 | private ChatMessage handlerChatFromViewer = null; //OnChatFromViewer; | ||
126 | private ChatMessage handlerChatFromViewer2 = null; //OnChatFromViewer; | ||
127 | private ImprovedInstantMessage handlerInstantMessage = null; //OnInstantMessage; | ||
128 | private FriendActionDelegate handlerApproveFriendRequest = null; //OnApproveFriendRequest; | ||
129 | private FriendshipTermination handlerTerminateFriendship = null; //OnTerminateFriendship; | ||
130 | private RezObject handlerRezObject = null; //OnRezObject; | ||
131 | private GenericCall4 handlerDeRezObject = null; //OnDeRezObject; | ||
132 | private ModifyTerrain handlerModifyTerrain = null; | ||
133 | private BakeTerrain handlerBakeTerrain = null; | ||
134 | private EstateChangeInfo handlerEstateChangeInfo = null; | ||
135 | private Action<IClientAPI> handlerRegionHandShakeReply = null; //OnRegionHandShakeReply; | ||
136 | private GenericCall2 handlerRequestWearables = null; //OnRequestWearables; | ||
137 | private Action<IClientAPI> handlerRequestAvatarsData = null; //OnRequestAvatarsData; | ||
138 | private SetAppearance handlerSetAppearance = null; //OnSetAppearance; | ||
139 | private AvatarNowWearing handlerAvatarNowWearing = null; //OnAvatarNowWearing; | ||
140 | private RezSingleAttachmentFromInv handlerRezSingleAttachment = null; //OnRezSingleAttachmentFromInv; | ||
141 | private UUIDNameRequest handlerDetachAttachmentIntoInv = null; // Detach attachment! | ||
142 | private ObjectAttach handlerObjectAttach = null; //OnObjectAttach; | ||
143 | private SetAlwaysRun handlerSetAlwaysRun = null; //OnSetAlwaysRun; | ||
144 | private GenericCall2 handlerCompleteMovementToRegion = null; //OnCompleteMovementToRegion; | ||
145 | private UpdateAgent handlerAgentUpdate = null; //OnAgentUpdate; | ||
146 | private StartAnim handlerStartAnim = null; | ||
147 | private StopAnim handlerStopAnim = null; | ||
148 | private AgentRequestSit handlerAgentRequestSit = null; //OnAgentRequestSit; | ||
149 | private AgentSit handlerAgentSit = null; //OnAgentSit; | ||
150 | private AvatarPickerRequest handlerAvatarPickerRequest = null; //OnAvatarPickerRequest; | ||
151 | private FetchInventory handlerAgentDataUpdateRequest = null; //OnAgentDataUpdateRequest; | ||
152 | private FetchInventory handlerUserInfoRequest = null; //OnUserInfoRequest; | ||
153 | private TeleportLocationRequest handlerSetStartLocationRequest = null; //OnSetStartLocationRequest; | ||
154 | private TeleportLandmarkRequest handlerTeleportLandmarkRequest = null; //OnTeleportLandmarkRequest; | ||
155 | private LinkObjects handlerLinkObjects = null; //OnLinkObjects; | ||
156 | private DelinkObjects handlerDelinkObjects = null; //OnDelinkObjects; | ||
157 | private AddNewPrim handlerAddPrim = null; //OnAddPrim; | ||
158 | private UpdateShape handlerUpdatePrimShape = null; //null; | ||
159 | private ObjectExtraParams handlerUpdateExtraParams = null; //OnUpdateExtraParams; | ||
160 | private ObjectDuplicate handlerObjectDuplicate = null; | ||
161 | private ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null; | ||
162 | private ObjectSelect handlerObjectSelect = null; | ||
163 | private ObjectDeselect handlerObjectDeselect = null; | ||
164 | private ObjectIncludeInSearch handlerObjectIncludeInSearch = null; | ||
165 | private UpdatePrimFlags handlerUpdatePrimFlags = null; //OnUpdatePrimFlags; | ||
166 | private UpdatePrimTexture handlerUpdatePrimTexture = null; | ||
167 | private UpdateVector handlerGrabObject = null; //OnGrabObject; | ||
168 | private MoveObject handlerGrabUpdate = null; //OnGrabUpdate; | ||
169 | private ObjectSelect handlerDeGrabObject = null; //OnDeGrabObject; | ||
170 | private GenericCall7 handlerObjectDescription = null; | ||
171 | private GenericCall7 handlerObjectName = null; | ||
172 | private ObjectPermissions handlerObjectPermissions = null; | ||
173 | private RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = null; //OnRequestObjectPropertiesFamily; | ||
174 | private TextureRequest handlerTextureRequest = null; | ||
175 | private UDPAssetUploadRequest handlerAssetUploadRequest = null; //OnAssetUploadRequest; | ||
176 | private RequestXfer handlerRequestXfer = null; //OnRequestXfer; | ||
177 | private XferReceive handlerXferReceive = null; //OnXferReceive; | ||
178 | private ConfirmXfer handlerConfirmXfer = null; //OnConfirmXfer; | ||
179 | private CreateInventoryFolder handlerCreateInventoryFolder = null; //OnCreateNewInventoryFolder; | ||
180 | private UpdateInventoryFolder handlerUpdateInventoryFolder = null; | ||
181 | private MoveInventoryFolder handlerMoveInventoryFolder = null; | ||
182 | private CreateNewInventoryItem handlerCreateNewInventoryItem = null; //OnCreateNewInventoryItem; | ||
183 | private FetchInventory handlerFetchInventory = null; | ||
184 | private FetchInventoryDescendents handlerFetchInventoryDescendents = null; //OnFetchInventoryDescendents; | ||
185 | private PurgeInventoryDescendents handlerPurgeInventoryDescendents = null; //OnPurgeInventoryDescendents; | ||
186 | private UpdateInventoryItem handlerUpdateInventoryItem = null; | ||
187 | private CopyInventoryItem handlerCopyInventoryItem = null; | ||
188 | private MoveInventoryItem handlerMoveInventoryItem = null; | ||
189 | private RemoveInventoryItem handlerRemoveInventoryItem = null; | ||
190 | private RemoveInventoryFolder handlerRemoveInventoryFolder = null; | ||
191 | private RequestTaskInventory handlerRequestTaskInventory = null; //OnRequestTaskInventory; | ||
192 | private UpdateTaskInventory handlerUpdateTaskInventory = null; //OnUpdateTaskInventory; | ||
193 | private MoveTaskInventory handlerMoveTaskItem = null; | ||
194 | private RemoveTaskInventory handlerRemoveTaskItem = null; //OnRemoveTaskItem; | ||
195 | private RezScript handlerRezScript = null; //OnRezScript; | ||
196 | private RequestMapBlocks handlerRequestMapBlocks = null; //OnRequestMapBlocks; | ||
197 | private RequestMapName handlerMapNameRequest = null; //OnMapNameRequest; | ||
198 | private TeleportLocationRequest handlerTeleportLocationRequest = null; //OnTeleportLocationRequest; | ||
199 | private MoneyBalanceRequest handlerMoneyBalanceRequest = null; //OnMoneyBalanceRequest; | ||
200 | private UUIDNameRequest handlerNameRequest = null; | ||
201 | private ParcelAccessListRequest handlerParcelAccessListRequest = null; //OnParcelAccessListRequest; | ||
202 | private ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = null; //OnParcelAccessListUpdateRequest; | ||
203 | private ParcelPropertiesRequest handlerParcelPropertiesRequest = null; //OnParcelPropertiesRequest; | ||
204 | private ParcelDivideRequest handlerParcelDivideRequest = null; //OnParcelDivideRequest; | ||
205 | private ParcelJoinRequest handlerParcelJoinRequest = null; //OnParcelJoinRequest; | ||
206 | private ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest = null; //OnParcelPropertiesUpdateRequest; | ||
207 | private ParcelSelectObjects handlerParcelSelectObjects = null; //OnParcelSelectObjects; | ||
208 | private ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = null; //OnParcelObjectOwnerRequest; | ||
209 | private ParcelAbandonRequest handlerParcelAbandonRequest = null; | ||
210 | private ParcelReclaim handlerParcelReclaim = null; | ||
211 | private ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest = null; | ||
212 | private RegionInfoRequest handlerRegionInfoRequest = null; //OnRegionInfoRequest; | ||
213 | private EstateCovenantRequest handlerEstateCovenantRequest = null; //OnEstateCovenantRequest; | ||
214 | private RequestGodlikePowers handlerReqGodlikePowers = null; //OnRequestGodlikePowers; | ||
215 | private GodKickUser handlerGodKickUser = null; //OnGodKickUser; | ||
216 | private ViewerEffectEventHandler handlerViewerEffect = null; //OnViewerEffect; | ||
217 | private Action<IClientAPI> handlerLogout = null; //OnLogout; | ||
218 | private MoneyTransferRequest handlerMoneyTransferRequest = null; //OnMoneyTransferRequest; | ||
219 | private ParcelBuy handlerParcelBuy = null; | ||
220 | private EconomyDataRequest handlerEconomoyDataRequest = null; | ||
221 | |||
222 | private UpdateVector handlerUpdatePrimSinglePosition = null; //OnUpdatePrimSinglePosition; | ||
223 | private UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = null; //OnUpdatePrimSingleRotation; | ||
224 | private UpdateVector handlerUpdatePrimScale = null; //OnUpdatePrimScale; | ||
225 | private UpdateVector handlerUpdatePrimGroupScale = null; //OnUpdateGroupScale; | ||
226 | private UpdateVector handlerUpdateVector = null; //OnUpdatePrimGroupPosition; | ||
227 | private UpdatePrimRotation handlerUpdatePrimRotation = null; //OnUpdatePrimGroupRotation; | ||
228 | // private UpdatePrimGroupRotation handlerUpdatePrimGroupRotation = null; //OnUpdatePrimGroupMouseRotation; | ||
229 | // private RequestAsset handlerRequestAsset = null; // OnRequestAsset; | ||
230 | private UUIDNameRequest handlerTeleportHomeRequest = null; | ||
231 | |||
232 | private ScriptAnswer handlerScriptAnswer = null; | ||
233 | private RequestPayPrice handlerRequestPayPrice = null; | ||
234 | private ObjectDeselect handlerObjectDetach = null; | ||
235 | private AgentSit handlerOnUndo = null; | ||
236 | |||
237 | private ForceReleaseControls handlerForceReleaseControls = null; | ||
238 | |||
239 | private GodLandStatRequest handlerLandStatRequest = null; | ||
240 | |||
241 | private UUIDNameRequest handlerUUIDGroupNameRequest = null; | ||
242 | |||
243 | private RequestObjectPropertiesFamily handlerObjectGroupRequest = null; | ||
244 | private ScriptReset handlerScriptReset = null; | ||
245 | private GetScriptRunning handlerGetScriptRunning = null; | ||
246 | private SetScriptRunning handlerSetScriptRunning = null; | ||
247 | private UpdateVector handlerAutoPilotGo = null; | ||
248 | |||
249 | //private TerrainUnacked handlerUnackedTerrain = null; | ||
250 | |||
251 | //** | ||
252 | |||
253 | /* Properties */ | ||
254 | |||
255 | public LLUUID SecureSessionId | ||
256 | { | ||
257 | get { return m_secureSessionId; } | ||
258 | } | ||
259 | |||
260 | public IScene Scene | ||
261 | { | ||
262 | get { return m_scene; } | ||
263 | } | ||
264 | |||
265 | public LLUUID SessionId | ||
266 | { | ||
267 | get { return m_sessionId; } | ||
268 | } | ||
269 | |||
270 | public LLVector3 StartPos | ||
271 | { | ||
272 | get { return m_startpos; } | ||
273 | set { m_startpos = value; } | ||
274 | } | ||
275 | |||
276 | public LLUUID AgentId | ||
277 | { | ||
278 | get { return m_agentId; } | ||
279 | } | ||
280 | |||
281 | public LLUUID ActiveGroupId | ||
282 | { | ||
283 | get { return m_activeGroupID; } | ||
284 | } | ||
285 | |||
286 | public string ActiveGroupName | ||
287 | { | ||
288 | get { return m_activeGroupName; } | ||
289 | } | ||
290 | |||
291 | public ulong ActiveGroupPowers | ||
292 | { | ||
293 | get { return m_activeGroupPowers; } | ||
294 | } | ||
295 | |||
296 | public ulong GetGroupPowers(LLUUID groupID) | ||
297 | { | ||
298 | if (m_groupPowers.ContainsKey(groupID)) | ||
299 | return m_groupPowers[groupID]; | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | /// <summary> | ||
304 | /// This is a utility method used by single states to not duplicate kicks and blue card of death messages. | ||
305 | /// </summary> | ||
306 | public bool ChildAgentStatus() | ||
307 | { | ||
308 | return m_scene.PresenceChildStatus(AgentId); | ||
309 | } | ||
310 | |||
311 | /// <summary> | ||
312 | /// First name of the agent/avatar represented by the client | ||
313 | /// </summary> | ||
314 | public string FirstName | ||
315 | { | ||
316 | get { return m_firstName; } | ||
317 | } | ||
318 | |||
319 | /// <summary> | ||
320 | /// Last name of the agent/avatar represented by the client | ||
321 | /// </summary> | ||
322 | public string LastName | ||
323 | { | ||
324 | get { return m_lastName; } | ||
325 | } | ||
326 | |||
327 | /// <summary> | ||
328 | /// Full name of the client (first name and last name) | ||
329 | /// </summary> | ||
330 | public string Name | ||
331 | { | ||
332 | get { return FirstName + " " + LastName; } | ||
333 | } | ||
334 | |||
335 | public uint CircuitCode | ||
336 | { | ||
337 | get { return m_circuitCode; } | ||
338 | } | ||
339 | |||
340 | public int MoneyBalance | ||
341 | { | ||
342 | get { return m_moneyBalance; } | ||
343 | } | ||
344 | |||
345 | public int NextAnimationSequenceNumber | ||
346 | { | ||
347 | get { return m_animationSequenceNumber++; } | ||
348 | } | ||
349 | |||
350 | public IPacketHandler PacketHandler | ||
351 | { | ||
352 | get { return m_PacketHandler; } | ||
353 | } | ||
354 | |||
355 | bool m_IsActive = true; | ||
356 | |||
357 | public bool IsActive | ||
358 | { | ||
359 | get { return m_IsActive; } | ||
360 | set { m_IsActive = value; } | ||
361 | } | ||
362 | |||
363 | /* METHODS */ | ||
364 | |||
365 | public LLClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer, | ||
366 | AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP) | ||
367 | { | ||
368 | m_moneyBalance = 1000; | ||
369 | |||
370 | m_channelVersion = Helpers.StringToField(scene.GetSimulatorVersion()); | ||
371 | |||
372 | InitDefaultAnimations(); | ||
373 | |||
374 | m_scene = scene; | ||
375 | m_assetCache = assetCache; | ||
376 | |||
377 | m_networkServer = packServer; | ||
378 | // m_inventoryCache = inventoryCache; | ||
379 | m_authenticateSessionsHandler = authenSessions; | ||
380 | |||
381 | m_agentId = agentId; | ||
382 | m_sessionId = sessionId; | ||
383 | m_circuitCode = circuitCode; | ||
384 | |||
385 | m_userEndPoint = remoteEP; | ||
386 | m_proxyEndPoint = proxyEP; | ||
387 | |||
388 | m_startpos = m_authenticateSessionsHandler.GetPosition(circuitCode); | ||
389 | |||
390 | // While working on this, the BlockingQueue had me fooled for a bit. | ||
391 | // The Blocking queue causes the thread to stop until there's something | ||
392 | // in it to process. It's an on-purpose threadlock though because | ||
393 | // without it, the clientloop will suck up all sim resources. | ||
394 | |||
395 | m_PacketHandler = new LLPacketHandler(this); | ||
396 | m_PacketHandler.SynchronizeClient = SynchronizeClient; | ||
397 | |||
398 | RegisterLocalPacketHandlers(); | ||
399 | |||
400 | m_clientThread = new Thread(new ThreadStart(AuthUser)); | ||
401 | m_clientThread.Name = "ClientThread"; | ||
402 | m_clientThread.IsBackground = true; | ||
403 | m_clientThread.Start(); | ||
404 | ThreadTracker.Add(m_clientThread); | ||
405 | |||
406 | m_log.Info("[CLIENT]: Started up new thread to handle client UDP session"); | ||
407 | } | ||
408 | |||
409 | public void SetDebug(int newDebug) | ||
410 | { | ||
411 | m_debug = newDebug; | ||
412 | } | ||
413 | |||
414 | # region Client Methods | ||
415 | |||
416 | private void CloseCleanup(bool shutdownCircuit) | ||
417 | { | ||
418 | m_scene.RemoveClient(AgentId); | ||
419 | |||
420 | //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); | ||
421 | //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); | ||
422 | |||
423 | // Send the STOP packet | ||
424 | DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); | ||
425 | OutPacket(disable, ThrottleOutPacketType.Unknown); | ||
426 | |||
427 | Thread.Sleep(2000); | ||
428 | |||
429 | // Shut down timers | ||
430 | m_clientPingTimer.Stop(); | ||
431 | |||
432 | // This is just to give the client a reasonable chance of | ||
433 | // flushing out all it's packets. There should probably | ||
434 | // be a better mechanism here | ||
435 | |||
436 | // We can't reach into other scenes and close the connection | ||
437 | // We need to do this over grid communications | ||
438 | //m_scene.CloseAllAgents(CircuitCode); | ||
439 | |||
440 | // If we're not shutting down the circuit, then this is the last time we'll go here. | ||
441 | // If we are shutting down the circuit, the UDP Server will come back here with | ||
442 | // ShutDownCircuit = false | ||
443 | if (!(shutdownCircuit)) | ||
444 | { | ||
445 | GC.Collect(); | ||
446 | m_clientThread.Abort(); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | /// <summary> | ||
451 | /// Close down the client view. This *must* be the last method called, since the last # | ||
452 | /// statement of CloseCleanup() aborts the thread. | ||
453 | /// </summary> | ||
454 | /// <param name="shutdownCircuit"></param> | ||
455 | public void Close(bool shutdownCircuit) | ||
456 | { | ||
457 | // Pull Client out of Region | ||
458 | m_log.Info("[CLIENT]: Close has been called"); | ||
459 | m_PacketHandler.Flush(); | ||
460 | |||
461 | //raiseevent on the packet server to Shutdown the circuit | ||
462 | if (shutdownCircuit) | ||
463 | { | ||
464 | OnConnectionClosed(this); | ||
465 | } | ||
466 | |||
467 | CloseCleanup(shutdownCircuit); | ||
468 | } | ||
469 | |||
470 | public void Kick(string message) | ||
471 | { | ||
472 | if (!ChildAgentStatus()) | ||
473 | { | ||
474 | KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser); | ||
475 | kupack.UserInfo.AgentID = AgentId; | ||
476 | kupack.UserInfo.SessionID = SessionId; | ||
477 | kupack.TargetBlock.TargetIP = (uint)0; | ||
478 | kupack.TargetBlock.TargetPort = (ushort)0; | ||
479 | kupack.UserInfo.Reason = Helpers.StringToField(message); | ||
480 | OutPacket(kupack, ThrottleOutPacketType.Task); | ||
481 | // You must sleep here or users get no message! | ||
482 | Thread.Sleep(500); | ||
483 | } | ||
484 | } | ||
485 | |||
486 | public void Stop() | ||
487 | { | ||
488 | // Shut down timers | ||
489 | m_clientPingTimer.Stop(); | ||
490 | } | ||
491 | |||
492 | public void Restart() | ||
493 | { | ||
494 | // re-construct | ||
495 | m_PacketHandler.Clear(); | ||
496 | |||
497 | m_clientPingTimer = new Timer(5000); | ||
498 | m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity); | ||
499 | m_clientPingTimer.Enabled = true; | ||
500 | } | ||
501 | |||
502 | public void Terminate() | ||
503 | { | ||
504 | m_PacketHandler.Stop(); | ||
505 | |||
506 | // wait for thread stoped | ||
507 | m_clientThread.Join(); | ||
508 | |||
509 | // delete circuit code | ||
510 | m_networkServer.CloseClient(this); | ||
511 | } | ||
512 | |||
513 | #endregion | ||
514 | |||
515 | # region Packet Handling | ||
516 | |||
517 | public static bool AddPacketHandler(PacketType packetType, PacketMethod handler) | ||
518 | { | ||
519 | bool result = false; | ||
520 | lock (PacketHandlers) | ||
521 | { | ||
522 | if (!PacketHandlers.ContainsKey(packetType)) | ||
523 | { | ||
524 | PacketHandlers.Add(packetType, handler); | ||
525 | result = true; | ||
526 | } | ||
527 | } | ||
528 | return result; | ||
529 | } | ||
530 | |||
531 | public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler) | ||
532 | { | ||
533 | bool result = false; | ||
534 | lock (m_packetHandlers) | ||
535 | { | ||
536 | if (!m_packetHandlers.ContainsKey(packetType)) | ||
537 | { | ||
538 | m_packetHandlers.Add(packetType, handler); | ||
539 | result = true; | ||
540 | } | ||
541 | } | ||
542 | return result; | ||
543 | } | ||
544 | |||
545 | /// <summary> | ||
546 | /// Try to process a packet using registered packet handlers | ||
547 | /// </summary> | ||
548 | /// <param name="packet"></param> | ||
549 | /// <returns>True if a handler was found which successfully processed the packet.</returns> | ||
550 | protected virtual bool ProcessPacketMethod(Packet packet) | ||
551 | { | ||
552 | bool result = false; | ||
553 | bool found = false; | ||
554 | PacketMethod method; | ||
555 | if (m_packetHandlers.TryGetValue(packet.Type, out method)) | ||
556 | { | ||
557 | //there is a local handler for this packet type | ||
558 | result = method(this, packet); | ||
559 | } | ||
560 | else | ||
561 | { | ||
562 | //there is not a local handler so see if there is a Global handler | ||
563 | lock (PacketHandlers) | ||
564 | { | ||
565 | found = PacketHandlers.TryGetValue(packet.Type, out method); | ||
566 | } | ||
567 | if (found) | ||
568 | { | ||
569 | result = method(this, packet); | ||
570 | } | ||
571 | } | ||
572 | return result; | ||
573 | } | ||
574 | |||
575 | protected void DebugPacket(string direction, Packet packet) | ||
576 | { | ||
577 | if (m_debug > 0) | ||
578 | { | ||
579 | string info = String.Empty; | ||
580 | |||
581 | if (m_debug < 255 && packet.Type == PacketType.AgentUpdate) | ||
582 | return; | ||
583 | if (m_debug < 254 && packet.Type == PacketType.ViewerEffect) | ||
584 | return; | ||
585 | if (m_debug < 253 && ( | ||
586 | packet.Type == PacketType.CompletePingCheck || | ||
587 | packet.Type == PacketType.StartPingCheck | ||
588 | )) | ||
589 | return; | ||
590 | if (m_debug < 252 && packet.Type == PacketType.PacketAck) | ||
591 | return; | ||
592 | |||
593 | if (m_debug > 1) | ||
594 | { | ||
595 | info = packet.ToString(); | ||
596 | } | ||
597 | else | ||
598 | { | ||
599 | info = packet.Type.ToString(); | ||
600 | } | ||
601 | Console.WriteLine(m_circuitCode + ":" + direction + ": " + info); | ||
602 | } | ||
603 | } | ||
604 | |||
605 | protected virtual void ClientLoop() | ||
606 | { | ||
607 | m_log.Info("[CLIENT]: Entered loop"); | ||
608 | while (true) | ||
609 | { | ||
610 | LLQueItem nextPacket = m_PacketHandler.PacketQueue.Dequeue(); | ||
611 | if (nextPacket == null) | ||
612 | { | ||
613 | m_log.Error("Got a NULL packet in Client Loop, bailing out of our client loop"); | ||
614 | break; | ||
615 | } | ||
616 | if (nextPacket.Incoming) | ||
617 | { | ||
618 | DebugPacket("IN", nextPacket.Packet); | ||
619 | m_PacketHandler.ProcessInPacket(nextPacket.Packet); | ||
620 | } | ||
621 | else | ||
622 | { | ||
623 | DebugPacket("OUT", nextPacket.Packet); | ||
624 | ProcessOutPacket(nextPacket.Packet); | ||
625 | } | ||
626 | } | ||
627 | } | ||
628 | |||
629 | # endregion | ||
630 | |||
631 | protected int m_terrainCheckerCount = 0; | ||
632 | /// <summary> | ||
633 | /// Event handler for check client timer | ||
634 | /// checks to ensure that the client is still connected | ||
635 | /// </summary> | ||
636 | /// <param name="sender"></param> | ||
637 | /// <param name="e"></param> | ||
638 | protected void CheckClientConnectivity(object sender, ElapsedEventArgs e) | ||
639 | { | ||
640 | if (m_PacketHandler.PacketsReceived == m_PacketHandler.PacketsReceivedReported) | ||
641 | { | ||
642 | m_probesWithNoIngressPackets++; | ||
643 | if ((m_probesWithNoIngressPackets > 30 && !m_clientBlocked) || (m_probesWithNoIngressPackets > 90 && m_clientBlocked)) | ||
644 | { | ||
645 | |||
646 | if (OnConnectionClosed != null) | ||
647 | { | ||
648 | OnConnectionClosed(this); | ||
649 | } | ||
650 | } | ||
651 | else | ||
652 | { | ||
653 | // this will normally trigger at least one packet (ping response) | ||
654 | SendStartPingCheck(0); | ||
655 | } | ||
656 | } | ||
657 | else | ||
658 | { | ||
659 | // Something received in the meantime - we can reset the counters | ||
660 | m_probesWithNoIngressPackets = 0; | ||
661 | } | ||
662 | |||
663 | } | ||
664 | |||
665 | # region Setup | ||
666 | |||
667 | /// <summary> | ||
668 | /// Starts up the timers to check the client and resend unacked packets | ||
669 | /// Adds the client to the OpenSim.Region.Environment.Scenes.Scene | ||
670 | /// </summary> | ||
671 | protected virtual void InitNewClient() | ||
672 | { | ||
673 | //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache); | ||
674 | |||
675 | // Establish our two timers. We could probably get this down to one | ||
676 | |||
677 | m_clientPingTimer = new Timer(5000); | ||
678 | m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity); | ||
679 | m_clientPingTimer.Enabled = true; | ||
680 | |||
681 | m_scene.AddNewClient(this, true); | ||
682 | } | ||
683 | |||
684 | /// <summary> | ||
685 | /// Authorize an incoming user session. This method lies at the base of the entire client thread. | ||
686 | /// </summary> | ||
687 | protected virtual void AuthUser() | ||
688 | { | ||
689 | |||
690 | //tell this thread we are using the culture set up for the sim (currently hardcoded to en_US) | ||
691 | //otherwise it will override this and use the system default | ||
692 | Culture.SetCurrentCulture(); | ||
693 | |||
694 | try | ||
695 | { | ||
696 | // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(m_cirpack.m_circuitCode.m_sessionId, m_cirpack.m_circuitCode.ID, m_cirpack.m_circuitCode.Code); | ||
697 | AuthenticateResponse sessionInfo = | ||
698 | m_authenticateSessionsHandler.AuthenticateSession(m_sessionId, m_agentId, | ||
699 | m_circuitCode); | ||
700 | if (!sessionInfo.Authorised) | ||
701 | { | ||
702 | //session/circuit not authorised | ||
703 | m_log.WarnFormat( | ||
704 | "[CLIENT]: New user request denied to avatar {0} connecting with circuit code {1} from {2}", | ||
705 | m_agentId, m_circuitCode, m_userEndPoint); | ||
706 | |||
707 | m_PacketHandler.Stop(); | ||
708 | m_clientThread.Abort(); | ||
709 | } | ||
710 | else | ||
711 | { | ||
712 | m_log.Info("[CLIENT]: Got authenticated connection from " + m_userEndPoint.ToString()); | ||
713 | //session is authorised | ||
714 | m_firstName = sessionInfo.LoginInfo.First; | ||
715 | m_lastName = sessionInfo.LoginInfo.Last; | ||
716 | |||
717 | if (sessionInfo.LoginInfo.SecureSession != LLUUID.Zero) | ||
718 | { | ||
719 | m_secureSessionId = sessionInfo.LoginInfo.SecureSession; | ||
720 | } | ||
721 | |||
722 | // This sets up all the timers | ||
723 | InitNewClient(); | ||
724 | |||
725 | ClientLoop(); | ||
726 | } | ||
727 | } | ||
728 | catch (Exception e) | ||
729 | { | ||
730 | if (e is ThreadAbortException) | ||
731 | throw e; | ||
732 | |||
733 | if (StatsManager.SimExtraStats != null) | ||
734 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); | ||
735 | |||
736 | // Don't let a failure in an individual client thread crash the whole sim. | ||
737 | m_log.ErrorFormat("[CLIENT]: Client thread for {0} {1} crashed. Logging them out. Exception {2}", Name, AgentId, e); | ||
738 | |||
739 | try | ||
740 | { | ||
741 | // Make an attempt to alert the user that their session has crashed | ||
742 | AgentAlertMessagePacket packet | ||
743 | = BuildAgentAlertPacket( | ||
744 | "Unfortunately the session for this client on the server has crashed.\n" | ||
745 | + "Any further actions taken will not be processed.\n" | ||
746 | + "Please relog", true); | ||
747 | |||
748 | ProcessOutPacket(packet); | ||
749 | |||
750 | // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to | ||
751 | // listeners yet, though. | ||
752 | Logout(this); | ||
753 | } | ||
754 | catch (Exception e2) | ||
755 | { | ||
756 | if (e2 is ThreadAbortException) | ||
757 | throw e2; | ||
758 | |||
759 | m_log.ErrorFormat("[CLIENT]: Further exception thrown on forced session logout. {0}", e2); | ||
760 | } | ||
761 | } | ||
762 | } | ||
763 | |||
764 | # endregion | ||
765 | |||
766 | // Previously ClientView.API partial class | ||
767 | public event Action<IClientAPI> OnLogout; | ||
768 | public event ObjectPermissions OnObjectPermissions; | ||
769 | public event Action<IClientAPI> OnConnectionClosed; | ||
770 | public event ViewerEffectEventHandler OnViewerEffect; | ||
771 | public event ImprovedInstantMessage OnInstantMessage; | ||
772 | public event ChatMessage OnChatFromViewer; | ||
773 | public event TextureRequest OnRequestTexture; | ||
774 | public event RezObject OnRezObject; | ||
775 | public event GenericCall4 OnDeRezObject; | ||
776 | public event ModifyTerrain OnModifyTerrain; | ||
777 | public event Action<IClientAPI> OnRegionHandShakeReply; | ||
778 | public event GenericCall2 OnRequestWearables; | ||
779 | public event SetAppearance OnSetAppearance; | ||
780 | public event AvatarNowWearing OnAvatarNowWearing; | ||
781 | public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; | ||
782 | public event UUIDNameRequest OnDetachAttachmentIntoInv; | ||
783 | public event ObjectAttach OnObjectAttach; | ||
784 | public event ObjectDeselect OnObjectDetach; | ||
785 | public event GenericCall2 OnCompleteMovementToRegion; | ||
786 | public event UpdateAgent OnAgentUpdate; | ||
787 | public event AgentRequestSit OnAgentRequestSit; | ||
788 | public event AgentSit OnAgentSit; | ||
789 | public event AvatarPickerRequest OnAvatarPickerRequest; | ||
790 | public event StartAnim OnStartAnim; | ||
791 | public event StopAnim OnStopAnim; | ||
792 | public event Action<IClientAPI> OnRequestAvatarsData; | ||
793 | public event LinkObjects OnLinkObjects; | ||
794 | public event DelinkObjects OnDelinkObjects; | ||
795 | public event UpdateVector OnGrabObject; | ||
796 | public event ObjectSelect OnDeGrabObject; | ||
797 | public event ObjectDuplicate OnObjectDuplicate; | ||
798 | public event ObjectDuplicateOnRay OnObjectDuplicateOnRay; | ||
799 | public event MoveObject OnGrabUpdate; | ||
800 | public event AddNewPrim OnAddPrim; | ||
801 | public event RequestGodlikePowers OnRequestGodlikePowers; | ||
802 | public event GodKickUser OnGodKickUser; | ||
803 | public event ObjectExtraParams OnUpdateExtraParams; | ||
804 | public event UpdateShape OnUpdatePrimShape; | ||
805 | public event ObjectSelect OnObjectSelect; | ||
806 | public event ObjectDeselect OnObjectDeselect; | ||
807 | public event GenericCall7 OnObjectDescription; | ||
808 | public event GenericCall7 OnObjectName; | ||
809 | public event ObjectIncludeInSearch OnObjectIncludeInSearch; | ||
810 | public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; | ||
811 | public event UpdatePrimFlags OnUpdatePrimFlags; | ||
812 | public event UpdatePrimTexture OnUpdatePrimTexture; | ||
813 | public event UpdateVector OnUpdatePrimGroupPosition; | ||
814 | public event UpdateVector OnUpdatePrimSinglePosition; | ||
815 | public event UpdatePrimRotation OnUpdatePrimGroupRotation; | ||
816 | public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; | ||
817 | public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; | ||
818 | public event UpdateVector OnUpdatePrimScale; | ||
819 | public event UpdateVector OnUpdatePrimGroupScale; | ||
820 | public event StatusChange OnChildAgentStatus; | ||
821 | public event GenericCall2 OnStopMovement; | ||
822 | public event Action<LLUUID> OnRemoveAvatar; | ||
823 | public event RequestMapBlocks OnRequestMapBlocks; | ||
824 | public event RequestMapName OnMapNameRequest; | ||
825 | public event TeleportLocationRequest OnTeleportLocationRequest; | ||
826 | public event TeleportLandmarkRequest OnTeleportLandmarkRequest; | ||
827 | public event DisconnectUser OnDisconnectUser; | ||
828 | public event RequestAvatarProperties OnRequestAvatarProperties; | ||
829 | public event SetAlwaysRun OnSetAlwaysRun; | ||
830 | public event FetchInventory OnAgentDataUpdateRequest; | ||
831 | public event FetchInventory OnUserInfoRequest; | ||
832 | public event TeleportLocationRequest OnSetStartLocationRequest; | ||
833 | public event UpdateAvatarProperties OnUpdateAvatarProperties; | ||
834 | public event CreateNewInventoryItem OnCreateNewInventoryItem; | ||
835 | public event CreateInventoryFolder OnCreateNewInventoryFolder; | ||
836 | public event UpdateInventoryFolder OnUpdateInventoryFolder; | ||
837 | public event MoveInventoryFolder OnMoveInventoryFolder; | ||
838 | public event FetchInventoryDescendents OnFetchInventoryDescendents; | ||
839 | public event PurgeInventoryDescendents OnPurgeInventoryDescendents; | ||
840 | public event FetchInventory OnFetchInventory; | ||
841 | public event RequestTaskInventory OnRequestTaskInventory; | ||
842 | public event UpdateInventoryItem OnUpdateInventoryItem; | ||
843 | public event CopyInventoryItem OnCopyInventoryItem; | ||
844 | public event MoveInventoryItem OnMoveInventoryItem; | ||
845 | public event RemoveInventoryItem OnRemoveInventoryItem; | ||
846 | public event RemoveInventoryFolder OnRemoveInventoryFolder; | ||
847 | public event UDPAssetUploadRequest OnAssetUploadRequest; | ||
848 | public event XferReceive OnXferReceive; | ||
849 | public event RequestXfer OnRequestXfer; | ||
850 | public event ConfirmXfer OnConfirmXfer; | ||
851 | public event RezScript OnRezScript; | ||
852 | public event UpdateTaskInventory OnUpdateTaskInventory; | ||
853 | public event MoveTaskInventory OnMoveTaskItem; | ||
854 | public event RemoveTaskInventory OnRemoveTaskItem; | ||
855 | public event RequestAsset OnRequestAsset; | ||
856 | public event UUIDNameRequest OnNameFromUUIDRequest; | ||
857 | public event ParcelAccessListRequest OnParcelAccessListRequest; | ||
858 | public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; | ||
859 | public event ParcelPropertiesRequest OnParcelPropertiesRequest; | ||
860 | public event ParcelDivideRequest OnParcelDivideRequest; | ||
861 | public event ParcelJoinRequest OnParcelJoinRequest; | ||
862 | public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; | ||
863 | public event ParcelSelectObjects OnParcelSelectObjects; | ||
864 | public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; | ||
865 | public event ParcelAbandonRequest OnParcelAbandonRequest; | ||
866 | public event ParcelReclaim OnParcelReclaim; | ||
867 | public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest; | ||
868 | public event RegionInfoRequest OnRegionInfoRequest; | ||
869 | public event EstateCovenantRequest OnEstateCovenantRequest; | ||
870 | public event FriendActionDelegate OnApproveFriendRequest; | ||
871 | public event FriendActionDelegate OnDenyFriendRequest; | ||
872 | public event FriendshipTermination OnTerminateFriendship; | ||
873 | public event MoneyTransferRequest OnMoneyTransferRequest; | ||
874 | public event EconomyDataRequest OnEconomyDataRequest; | ||
875 | public event MoneyBalanceRequest OnMoneyBalanceRequest; | ||
876 | public event ParcelBuy OnParcelBuy; | ||
877 | public event UUIDNameRequest OnTeleportHomeRequest; | ||
878 | public event UUIDNameRequest OnUUIDGroupNameRequest; | ||
879 | public event ScriptAnswer OnScriptAnswer; | ||
880 | public event RequestPayPrice OnRequestPayPrice; | ||
881 | public event AgentSit OnUndo; | ||
882 | public event ForceReleaseControls OnForceReleaseControls; | ||
883 | public event GodLandStatRequest OnLandStatRequest; | ||
884 | public event RequestObjectPropertiesFamily OnObjectGroupRequest; | ||
885 | public event DetailedEstateDataRequest OnDetailedEstateDataRequest; | ||
886 | public event SetEstateFlagsRequest OnSetEstateFlagsRequest; | ||
887 | public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture; | ||
888 | public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture; | ||
889 | public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights; | ||
890 | public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest; | ||
891 | public event SetRegionTerrainSettings OnSetRegionTerrainSettings; | ||
892 | public event BakeTerrain OnBakeTerrain; | ||
893 | public event EstateChangeInfo OnEstateChangeInfo; | ||
894 | public event EstateRestartSimRequest OnEstateRestartSimRequest; | ||
895 | public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest; | ||
896 | public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest; | ||
897 | public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest; | ||
898 | public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest; | ||
899 | public event EstateDebugRegionRequest OnEstateDebugRegionRequest; | ||
900 | public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest; | ||
901 | public event ScriptReset OnScriptReset; | ||
902 | public event GetScriptRunning OnGetScriptRunning; | ||
903 | public event SetScriptRunning OnSetScriptRunning; | ||
904 | public event UpdateVector OnAutoPilotGo; | ||
905 | |||
906 | public event TerrainUnacked OnUnackedTerrain; | ||
907 | |||
908 | #region Scene/Avatar to Client | ||
909 | |||
910 | /// <summary> | ||
911 | /// | ||
912 | /// </summary> | ||
913 | /// <param name="regionInfo"></param> | ||
914 | public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) | ||
915 | { | ||
916 | RegionHandshakePacket handshake = (RegionHandshakePacket)PacketPool.Instance.GetPacket(PacketType.RegionHandshake); | ||
917 | |||
918 | handshake.RegionInfo.BillableFactor = args.billableFactor; | ||
919 | handshake.RegionInfo.IsEstateManager = args.isEstateManager; | ||
920 | handshake.RegionInfo.TerrainHeightRange00 = args.terrainHeightRange0; | ||
921 | handshake.RegionInfo.TerrainHeightRange01 = args.terrainHeightRange1; | ||
922 | handshake.RegionInfo.TerrainHeightRange10 = args.terrainHeightRange2; | ||
923 | handshake.RegionInfo.TerrainHeightRange11 = args.terrainHeightRange3; | ||
924 | handshake.RegionInfo.TerrainStartHeight00 = args.terrainStartHeight0; | ||
925 | handshake.RegionInfo.TerrainStartHeight01 = args.terrainStartHeight1; | ||
926 | handshake.RegionInfo.TerrainStartHeight10 = args.terrainStartHeight2; | ||
927 | handshake.RegionInfo.TerrainStartHeight11 = args.terrainStartHeight3; | ||
928 | handshake.RegionInfo.SimAccess = args.simAccess; | ||
929 | handshake.RegionInfo.WaterHeight = args.waterHeight; | ||
930 | |||
931 | handshake.RegionInfo.RegionFlags = args.regionFlags; | ||
932 | handshake.RegionInfo.SimName = Helpers.StringToField(args.regionName); | ||
933 | handshake.RegionInfo.SimOwner = args.SimOwner; | ||
934 | handshake.RegionInfo.TerrainBase0 = args.terrainBase0; | ||
935 | handshake.RegionInfo.TerrainBase1 = args.terrainBase1; | ||
936 | handshake.RegionInfo.TerrainBase2 = args.terrainBase2; | ||
937 | handshake.RegionInfo.TerrainBase3 = args.terrainBase3; | ||
938 | handshake.RegionInfo.TerrainDetail0 = args.terrainDetail0; | ||
939 | handshake.RegionInfo.TerrainDetail1 = args.terrainDetail1; | ||
940 | handshake.RegionInfo.TerrainDetail2 = args.terrainDetail2; | ||
941 | handshake.RegionInfo.TerrainDetail3 = args.terrainDetail3; | ||
942 | handshake.RegionInfo.CacheID = LLUUID.Random(); //I guess this is for the client to remember an old setting? | ||
943 | |||
944 | OutPacket(handshake, ThrottleOutPacketType.Task); | ||
945 | } | ||
946 | |||
947 | /// <summary> | ||
948 | /// | ||
949 | /// </summary> | ||
950 | /// <param name="regInfo"></param> | ||
951 | public void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look) | ||
952 | { | ||
953 | AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); | ||
954 | mov.SimData.ChannelVersion = m_channelVersion; | ||
955 | mov.AgentData.SessionID = m_sessionId; | ||
956 | mov.AgentData.AgentID = AgentId; | ||
957 | mov.Data.RegionHandle = regInfo.RegionHandle; | ||
958 | mov.Data.Timestamp = 1172750370; // TODO - dynamicalise this | ||
959 | |||
960 | if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0)) | ||
961 | { | ||
962 | mov.Data.Position = m_startpos; | ||
963 | } | ||
964 | else | ||
965 | { | ||
966 | mov.Data.Position = pos; | ||
967 | } | ||
968 | mov.Data.LookAt = look; | ||
969 | |||
970 | // Hack to get this out immediately and skip the throttles | ||
971 | OutPacket(mov, ThrottleOutPacketType.Unknown); | ||
972 | } | ||
973 | |||
974 | /// <summary> | ||
975 | /// | ||
976 | /// </summary> | ||
977 | /// <param name="message"></param> | ||
978 | /// <param name="type"></param> | ||
979 | /// <param name="fromPos"></param> | ||
980 | /// <param name="fromName"></param> | ||
981 | /// <param name="fromAgentID"></param> | ||
982 | public void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, | ||
983 | LLUUID fromAgentID, byte source, byte audible) | ||
984 | { | ||
985 | SendChatMessage(Helpers.StringToField(message), type, fromPos, fromName, fromAgentID, source, audible); | ||
986 | } | ||
987 | |||
988 | public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, | ||
989 | LLUUID fromAgentID, byte source, byte audible) | ||
990 | { | ||
991 | ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); | ||
992 | reply.ChatData.Audible = audible; | ||
993 | reply.ChatData.Message = message; | ||
994 | reply.ChatData.ChatType = type; | ||
995 | reply.ChatData.SourceType = source; | ||
996 | reply.ChatData.Position = fromPos; | ||
997 | reply.ChatData.FromName = Helpers.StringToField(fromName); | ||
998 | reply.ChatData.OwnerID = fromAgentID; | ||
999 | reply.ChatData.SourceID = fromAgentID; | ||
1000 | |||
1001 | OutPacket(reply, ThrottleOutPacketType.Task); | ||
1002 | } | ||
1003 | |||
1004 | /// <summary> | ||
1005 | /// Send an instant message to this client | ||
1006 | /// </summary> | ||
1007 | /// <param name="message"></param> | ||
1008 | /// <param name="target"></param> | ||
1009 | public void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent, | ||
1010 | LLUUID imSessionID, string fromName, byte dialog, uint timeStamp) | ||
1011 | { | ||
1012 | SendInstantMessage( | ||
1013 | fromAgent, fromAgentSession, message, toAgent, | ||
1014 | imSessionID, fromName, dialog, timeStamp, new byte[0]); | ||
1015 | } | ||
1016 | |||
1017 | /// <summary> | ||
1018 | /// Send an instant message to this client | ||
1019 | /// </summary> | ||
1020 | /// <param name="message"></param> | ||
1021 | /// <param name="target"></param> | ||
1022 | public void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent, | ||
1023 | LLUUID imSessionID, string fromName, byte dialog, uint timeStamp, | ||
1024 | byte[] binaryBucket) | ||
1025 | { | ||
1026 | if (((Scene)(this.m_scene)).ExternalChecks.ExternalChecksCanInstantMessage(fromAgent, toAgent)) | ||
1027 | { | ||
1028 | ImprovedInstantMessagePacket msg | ||
1029 | = (ImprovedInstantMessagePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedInstantMessage); | ||
1030 | |||
1031 | msg.AgentData.AgentID = fromAgent; | ||
1032 | msg.AgentData.SessionID = fromAgentSession; | ||
1033 | msg.MessageBlock.FromAgentName = Helpers.StringToField(fromName); | ||
1034 | msg.MessageBlock.Dialog = dialog; | ||
1035 | msg.MessageBlock.FromGroup = false; | ||
1036 | msg.MessageBlock.ID = imSessionID; | ||
1037 | msg.MessageBlock.Offline = 0; | ||
1038 | msg.MessageBlock.ParentEstateID = 0; | ||
1039 | msg.MessageBlock.Position = new LLVector3(); | ||
1040 | msg.MessageBlock.RegionID = LLUUID.Random(); | ||
1041 | msg.MessageBlock.Timestamp = timeStamp; | ||
1042 | msg.MessageBlock.ToAgentID = toAgent; | ||
1043 | msg.MessageBlock.Message = Helpers.StringToField(message); | ||
1044 | msg.MessageBlock.BinaryBucket = binaryBucket; | ||
1045 | |||
1046 | OutPacket(msg, ThrottleOutPacketType.Task); | ||
1047 | } | ||
1048 | } | ||
1049 | |||
1050 | /// <summary> | ||
1051 | /// Send the region heightmap to the client | ||
1052 | /// </summary> | ||
1053 | /// <param name="map">heightmap</param> | ||
1054 | public virtual void SendLayerData(float[] map) | ||
1055 | { | ||
1056 | ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendLayerData), (object)map); | ||
1057 | } | ||
1058 | |||
1059 | /// <summary> | ||
1060 | /// Send terrain layer information to the client. | ||
1061 | /// </summary> | ||
1062 | /// <param name="o"></param> | ||
1063 | private void DoSendLayerData(object o) | ||
1064 | { | ||
1065 | float[] map = (float[])o; | ||
1066 | |||
1067 | try | ||
1068 | { | ||
1069 | for (int y = 0; y < 16; y++) | ||
1070 | { | ||
1071 | // For some terrains, sending more than one terrain patch at once results in a libsecondlife exception | ||
1072 | // see http://opensimulator.org/mantis/view.php?id=1662 | ||
1073 | //for (int x = 0; x < 16; x += 4) | ||
1074 | //{ | ||
1075 | // SendLayerPacket(map, y, x); | ||
1076 | // Thread.Sleep(150); | ||
1077 | //} | ||
1078 | for (int x = 0; x < 16; x++) | ||
1079 | { | ||
1080 | SendLayerData(x, y, map); | ||
1081 | Thread.Sleep(35); | ||
1082 | } | ||
1083 | } | ||
1084 | } | ||
1085 | catch (Exception e) | ||
1086 | { | ||
1087 | m_log.Warn("[CLIENT]: ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); | ||
1088 | } | ||
1089 | } | ||
1090 | |||
1091 | /// <summary> | ||
1092 | /// Sends a set of four patches (x, x+1, ..., x+3) to the client | ||
1093 | /// </summary> | ||
1094 | /// <param name="map">heightmap</param> | ||
1095 | /// <param name="px">X coordinate for patches 0..12</param> | ||
1096 | /// <param name="py">Y coordinate for patches 0..15</param> | ||
1097 | // private void SendLayerPacket(float[] map, int y, int x) | ||
1098 | // { | ||
1099 | // int[] patches = new int[4]; | ||
1100 | // patches[0] = x + 0 + y * 16; | ||
1101 | // patches[1] = x + 1 + y * 16; | ||
1102 | // patches[2] = x + 2 + y * 16; | ||
1103 | // patches[3] = x + 3 + y * 16; | ||
1104 | |||
1105 | // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); | ||
1106 | // OutPacket(layerpack, ThrottleOutPacketType.Land); | ||
1107 | // } | ||
1108 | |||
1109 | /// <summary> | ||
1110 | /// Sends a specified patch to a client | ||
1111 | /// </summary> | ||
1112 | /// <param name="px">Patch coordinate (x) 0..15</param> | ||
1113 | /// <param name="py">Patch coordinate (y) 0..15</param> | ||
1114 | /// <param name="map">heightmap</param> | ||
1115 | public void SendLayerData(int px, int py, float[] map) | ||
1116 | { | ||
1117 | try | ||
1118 | { | ||
1119 | int[] patches = new int[1]; | ||
1120 | int patchx, patchy; | ||
1121 | patchx = px; | ||
1122 | patchy = py; | ||
1123 | |||
1124 | patches[0] = patchx + 0 + patchy * 16; | ||
1125 | |||
1126 | LayerDataPacket layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); | ||
1127 | layerpack.Header.Zerocoded = true; | ||
1128 | |||
1129 | OutPacket(layerpack, ThrottleOutPacketType.Land); | ||
1130 | } | ||
1131 | catch (Exception e) | ||
1132 | { | ||
1133 | m_log.Warn("[client]: ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); | ||
1134 | } | ||
1135 | } | ||
1136 | |||
1137 | /// <summary> | ||
1138 | /// Tell the client that the given neighbour region is ready to receive a child agent. | ||
1139 | /// </summary> | ||
1140 | /// <param name="neighbourHandle"></param> | ||
1141 | /// <param name="neighbourIP"></param> | ||
1142 | /// <param name="neighbourPort"></param> | ||
1143 | public void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourEndPoint) | ||
1144 | { | ||
1145 | IPAddress neighbourIP = neighbourEndPoint.Address; | ||
1146 | ushort neighbourPort = (ushort)neighbourEndPoint.Port; | ||
1147 | |||
1148 | EnableSimulatorPacket enablesimpacket = (EnableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.EnableSimulator); | ||
1149 | // TODO: don't create new blocks if recycling an old packet | ||
1150 | enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock(); | ||
1151 | enablesimpacket.SimulatorInfo.Handle = neighbourHandle; | ||
1152 | |||
1153 | byte[] byteIP = neighbourIP.GetAddressBytes(); | ||
1154 | enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24; | ||
1155 | enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16; | ||
1156 | enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8; | ||
1157 | enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0]; | ||
1158 | enablesimpacket.SimulatorInfo.Port = neighbourPort; | ||
1159 | OutPacket(enablesimpacket, ThrottleOutPacketType.Task); | ||
1160 | } | ||
1161 | |||
1162 | /// <summary> | ||
1163 | /// | ||
1164 | /// </summary> | ||
1165 | /// <returns></returns> | ||
1166 | public AgentCircuitData RequestClientInfo() | ||
1167 | { | ||
1168 | AgentCircuitData agentData = new AgentCircuitData(); | ||
1169 | agentData.AgentID = AgentId; | ||
1170 | agentData.SessionID = m_sessionId; | ||
1171 | agentData.SecureSessionID = SecureSessionId; | ||
1172 | agentData.circuitcode = m_circuitCode; | ||
1173 | agentData.child = false; | ||
1174 | agentData.firstname = m_firstName; | ||
1175 | agentData.lastname = m_lastName; | ||
1176 | agentData.CapsPath = m_scene.GetCapsPath(m_agentId); | ||
1177 | return agentData; | ||
1178 | } | ||
1179 | |||
1180 | public void CrossRegion(ulong newRegionHandle, LLVector3 pos, LLVector3 lookAt, IPEndPoint externalIPEndPoint, | ||
1181 | string capsURL) | ||
1182 | { | ||
1183 | LLVector3 look = new LLVector3(lookAt.X * 10, lookAt.Y * 10, lookAt.Z * 10); | ||
1184 | |||
1185 | //CrossedRegionPacket newSimPack = (CrossedRegionPacket)PacketPool.Instance.GetPacket(PacketType.CrossedRegion); | ||
1186 | CrossedRegionPacket newSimPack = new CrossedRegionPacket(); | ||
1187 | // TODO: don't create new blocks if recycling an old packet | ||
1188 | newSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock(); | ||
1189 | newSimPack.AgentData.AgentID = AgentId; | ||
1190 | newSimPack.AgentData.SessionID = m_sessionId; | ||
1191 | newSimPack.Info = new CrossedRegionPacket.InfoBlock(); | ||
1192 | newSimPack.Info.Position = pos; | ||
1193 | newSimPack.Info.LookAt = look; | ||
1194 | newSimPack.RegionData = new CrossedRegionPacket.RegionDataBlock(); | ||
1195 | newSimPack.RegionData.RegionHandle = newRegionHandle; | ||
1196 | byte[] byteIP = externalIPEndPoint.Address.GetAddressBytes(); | ||
1197 | newSimPack.RegionData.SimIP = (uint)byteIP[3] << 24; | ||
1198 | newSimPack.RegionData.SimIP += (uint)byteIP[2] << 16; | ||
1199 | newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8; | ||
1200 | newSimPack.RegionData.SimIP += (uint)byteIP[0]; | ||
1201 | newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port; | ||
1202 | newSimPack.RegionData.SeedCapability = Helpers.StringToField(capsURL); | ||
1203 | |||
1204 | // Hack to get this out immediately and skip throttles | ||
1205 | OutPacket(newSimPack, ThrottleOutPacketType.Unknown); | ||
1206 | } | ||
1207 | |||
1208 | internal void SendMapBlockSplit(List<MapBlockData> mapBlocks, uint flag) | ||
1209 | { | ||
1210 | MapBlockReplyPacket mapReply = (MapBlockReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapBlockReply); | ||
1211 | // TODO: don't create new blocks if recycling an old packet | ||
1212 | |||
1213 | MapBlockData[] mapBlocks2 = mapBlocks.ToArray(); | ||
1214 | |||
1215 | mapReply.AgentData.AgentID = AgentId; | ||
1216 | mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length]; | ||
1217 | mapReply.AgentData.Flags = flag; | ||
1218 | |||
1219 | for (int i = 0; i < mapBlocks2.Length; i++) | ||
1220 | { | ||
1221 | mapReply.Data[i] = new MapBlockReplyPacket.DataBlock(); | ||
1222 | mapReply.Data[i].MapImageID = mapBlocks2[i].MapImageId; | ||
1223 | //m_log.Warn(mapBlocks2[i].MapImageId.ToString()); | ||
1224 | mapReply.Data[i].X = mapBlocks2[i].X; | ||
1225 | mapReply.Data[i].Y = mapBlocks2[i].Y; | ||
1226 | mapReply.Data[i].WaterHeight = mapBlocks2[i].WaterHeight; | ||
1227 | mapReply.Data[i].Name = Helpers.StringToField(mapBlocks2[i].Name); | ||
1228 | mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags; | ||
1229 | mapReply.Data[i].Access = mapBlocks2[i].Access; | ||
1230 | mapReply.Data[i].Agents = mapBlocks2[i].Agents; | ||
1231 | } | ||
1232 | OutPacket(mapReply, ThrottleOutPacketType.Land); | ||
1233 | } | ||
1234 | |||
1235 | public void SendMapBlock(List<MapBlockData> mapBlocks, uint flag) | ||
1236 | { | ||
1237 | |||
1238 | MapBlockData[] mapBlocks2 = mapBlocks.ToArray(); | ||
1239 | |||
1240 | int maxsend = 10; | ||
1241 | |||
1242 | //int packets = Math.Ceiling(mapBlocks2.Length / maxsend); | ||
1243 | |||
1244 | List<MapBlockData> sendingBlocks = new List<MapBlockData>(); | ||
1245 | |||
1246 | for (int i = 0; i < mapBlocks2.Length; i++) | ||
1247 | { | ||
1248 | sendingBlocks.Add(mapBlocks2[i]); | ||
1249 | if (((i + 1) == mapBlocks2.Length) || ((i % maxsend) == 0)) | ||
1250 | { | ||
1251 | SendMapBlockSplit(sendingBlocks, flag); | ||
1252 | sendingBlocks = new List<MapBlockData>(); | ||
1253 | } | ||
1254 | } | ||
1255 | } | ||
1256 | |||
1257 | public void SendLocalTeleport(LLVector3 position, LLVector3 lookAt, uint flags) | ||
1258 | { | ||
1259 | TeleportLocalPacket tpLocal = (TeleportLocalPacket)PacketPool.Instance.GetPacket(PacketType.TeleportLocal); | ||
1260 | tpLocal.Info.AgentID = AgentId; | ||
1261 | tpLocal.Info.TeleportFlags = flags; | ||
1262 | tpLocal.Info.LocationID = 2; | ||
1263 | tpLocal.Info.LookAt = lookAt; | ||
1264 | tpLocal.Info.Position = position; | ||
1265 | |||
1266 | // Hack to get this out immediately and skip throttles | ||
1267 | OutPacket(tpLocal, ThrottleOutPacketType.Unknown); | ||
1268 | } | ||
1269 | |||
1270 | public void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint newRegionEndPoint, uint locationID, | ||
1271 | uint flags, string capsURL) | ||
1272 | { | ||
1273 | //TeleportFinishPacket teleport = (TeleportFinishPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFinish); | ||
1274 | |||
1275 | TeleportFinishPacket teleport = new TeleportFinishPacket(); | ||
1276 | teleport.Info.AgentID = AgentId; | ||
1277 | teleport.Info.RegionHandle = regionHandle; | ||
1278 | teleport.Info.SimAccess = simAccess; | ||
1279 | |||
1280 | teleport.Info.SeedCapability = Helpers.StringToField(capsURL); | ||
1281 | |||
1282 | IPAddress oIP = newRegionEndPoint.Address; | ||
1283 | byte[] byteIP = oIP.GetAddressBytes(); | ||
1284 | uint ip = (uint)byteIP[3] << 24; | ||
1285 | ip += (uint)byteIP[2] << 16; | ||
1286 | ip += (uint)byteIP[1] << 8; | ||
1287 | ip += (uint)byteIP[0]; | ||
1288 | |||
1289 | teleport.Info.SimIP = ip; | ||
1290 | teleport.Info.SimPort = (ushort)newRegionEndPoint.Port; | ||
1291 | teleport.Info.LocationID = 4; | ||
1292 | teleport.Info.TeleportFlags = 1 << 4; | ||
1293 | |||
1294 | // Hack to get this out immediately and skip throttles. | ||
1295 | OutPacket(teleport, ThrottleOutPacketType.Unknown); | ||
1296 | } | ||
1297 | |||
1298 | /// <summary> | ||
1299 | /// | ||
1300 | /// </summary> | ||
1301 | public void SendTeleportFailed(string reason) | ||
1302 | { | ||
1303 | TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed); | ||
1304 | tpFailed.Info.AgentID = AgentId; | ||
1305 | tpFailed.Info.Reason = Helpers.StringToField(reason); | ||
1306 | |||
1307 | // Hack to get this out immediately and skip throttles | ||
1308 | OutPacket(tpFailed, ThrottleOutPacketType.Unknown); | ||
1309 | } | ||
1310 | |||
1311 | /// <summary> | ||
1312 | /// | ||
1313 | /// </summary> | ||
1314 | public void SendTeleportLocationStart() | ||
1315 | { | ||
1316 | //TeleportStartPacket tpStart = (TeleportStartPacket)PacketPool.Instance.GetPacket(PacketType.TeleportStart); | ||
1317 | TeleportStartPacket tpStart = new TeleportStartPacket(); | ||
1318 | tpStart.Info.TeleportFlags = 16; // Teleport via location | ||
1319 | |||
1320 | // Hack to get this out immediately and skip throttles | ||
1321 | OutPacket(tpStart, ThrottleOutPacketType.Unknown); | ||
1322 | } | ||
1323 | |||
1324 | public void SendMoneyBalance(LLUUID transaction, bool success, byte[] description, int balance) | ||
1325 | { | ||
1326 | MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply); | ||
1327 | money.MoneyData.AgentID = AgentId; | ||
1328 | money.MoneyData.TransactionID = transaction; | ||
1329 | money.MoneyData.TransactionSuccess = success; | ||
1330 | money.MoneyData.Description = description; | ||
1331 | money.MoneyData.MoneyBalance = balance; | ||
1332 | OutPacket(money, ThrottleOutPacketType.Task); | ||
1333 | } | ||
1334 | |||
1335 | public void SendPayPrice(LLUUID objectID, int[] payPrice) | ||
1336 | { | ||
1337 | if (payPrice[0] == 0 && | ||
1338 | payPrice[1] == 0 && | ||
1339 | payPrice[2] == 0 && | ||
1340 | payPrice[3] == 0 && | ||
1341 | payPrice[4] == 0) | ||
1342 | return; | ||
1343 | |||
1344 | PayPriceReplyPacket payPriceReply = (PayPriceReplyPacket)PacketPool.Instance.GetPacket(PacketType.PayPriceReply); | ||
1345 | payPriceReply.ObjectData.ObjectID = objectID; | ||
1346 | payPriceReply.ObjectData.DefaultPayPrice = payPrice[0]; | ||
1347 | |||
1348 | payPriceReply.ButtonData = new PayPriceReplyPacket.ButtonDataBlock[4]; | ||
1349 | payPriceReply.ButtonData[0] = new PayPriceReplyPacket.ButtonDataBlock(); | ||
1350 | payPriceReply.ButtonData[0].PayButton = payPrice[1]; | ||
1351 | payPriceReply.ButtonData[1] = new PayPriceReplyPacket.ButtonDataBlock(); | ||
1352 | payPriceReply.ButtonData[1].PayButton = payPrice[2]; | ||
1353 | payPriceReply.ButtonData[2] = new PayPriceReplyPacket.ButtonDataBlock(); | ||
1354 | payPriceReply.ButtonData[2].PayButton = payPrice[3]; | ||
1355 | payPriceReply.ButtonData[3] = new PayPriceReplyPacket.ButtonDataBlock(); | ||
1356 | payPriceReply.ButtonData[3].PayButton = payPrice[4]; | ||
1357 | |||
1358 | OutPacket(payPriceReply, ThrottleOutPacketType.Task); | ||
1359 | } | ||
1360 | |||
1361 | public void SendStartPingCheck(byte seq) | ||
1362 | { | ||
1363 | StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); | ||
1364 | pc.PingID.PingID = seq; | ||
1365 | pc.Header.Reliable = false; | ||
1366 | OutPacket(pc, ThrottleOutPacketType.Unknown); | ||
1367 | } | ||
1368 | |||
1369 | public void SendKillObject(ulong regionHandle, uint localID) | ||
1370 | { | ||
1371 | KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); | ||
1372 | // TODO: don't create new blocks if recycling an old packet | ||
1373 | kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; | ||
1374 | kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); | ||
1375 | kill.ObjectData[0].ID = localID; | ||
1376 | kill.Header.Reliable = false; | ||
1377 | kill.Header.Zerocoded = true; | ||
1378 | OutPacket(kill, ThrottleOutPacketType.Task); | ||
1379 | } | ||
1380 | |||
1381 | /// <summary> | ||
1382 | /// Send information about the items contained in a folder to the client. | ||
1383 | /// | ||
1384 | /// XXX This method needs some refactoring loving | ||
1385 | /// </summary> | ||
1386 | /// <param name="ownerID">The owner of the folder</param> | ||
1387 | /// <param name="folderID">The id of the folder</param> | ||
1388 | /// <param name="items">The items contained in the folder identified by folderID</param> | ||
1389 | /// <param name="fetchFolders">Do we need to send folder information?</param> | ||
1390 | /// <param name="fetchItems">Do we need to send item information?</param> | ||
1391 | public void SendInventoryFolderDetails(LLUUID ownerID, LLUUID folderID, List<InventoryItemBase> items, | ||
1392 | List<InventoryFolderBase> folders, | ||
1393 | bool fetchFolders, bool fetchItems) | ||
1394 | { | ||
1395 | // An inventory descendents packet consists of a single agent section and an inventory details | ||
1396 | // section for each inventory item. The size of each inventory item is approximately 550 bytes. | ||
1397 | // In theory, UDP has a maximum packet size of 64k, so it should be possible to send descendent | ||
1398 | // packets containing metadata for in excess of 100 items. But in practice, there may be other | ||
1399 | // factors (e.g. firewalls) restraining the maximum UDP packet size. See, | ||
1400 | // | ||
1401 | // http://opensimulator.org/mantis/view.php?id=226 | ||
1402 | // | ||
1403 | // for one example of this kind of thing. In fact, the Linden servers appear to only send about | ||
1404 | // 6 to 7 items at a time, so let's stick with 6 | ||
1405 | int MAX_ITEMS_PER_PACKET = 6; | ||
1406 | |||
1407 | //Ckrinke This variable is not used, so comment out to remove the warning from the compiler (3-21-08) | ||
1408 | //Ckrinke uint FULL_MASK_PERMISSIONS = 2147483647; | ||
1409 | |||
1410 | if (fetchItems) | ||
1411 | { | ||
1412 | InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID); | ||
1413 | |||
1414 | if (items.Count < MAX_ITEMS_PER_PACKET) | ||
1415 | { | ||
1416 | descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count]; | ||
1417 | descend.AgentData.Descendents = items.Count; | ||
1418 | } | ||
1419 | else | ||
1420 | { | ||
1421 | descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET]; | ||
1422 | descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET; | ||
1423 | } | ||
1424 | |||
1425 | // Even if we aren't fetching the folders, we still need to include the folder count | ||
1426 | // in the total number of descendents. Failure to do so will cause subtle bugs such | ||
1427 | // as the failure of textures which haven't been expanded in inventory to show up | ||
1428 | // in the texture prim edit selection panel. | ||
1429 | if (!fetchFolders) | ||
1430 | { | ||
1431 | descend.AgentData.Descendents += folders.Count; | ||
1432 | } | ||
1433 | |||
1434 | int count = 0; | ||
1435 | int i = 0; | ||
1436 | foreach (InventoryItemBase item in items) | ||
1437 | { | ||
1438 | descend.ItemData[i] = new InventoryDescendentsPacket.ItemDataBlock(); | ||
1439 | descend.ItemData[i].ItemID = item.ID; | ||
1440 | descend.ItemData[i].AssetID = item.AssetID; | ||
1441 | descend.ItemData[i].CreatorID = item.Creator; | ||
1442 | descend.ItemData[i].BaseMask = item.BasePermissions; | ||
1443 | descend.ItemData[i].Description = Helpers.StringToField(item.Description); | ||
1444 | descend.ItemData[i].EveryoneMask = item.EveryOnePermissions; | ||
1445 | descend.ItemData[i].OwnerMask = item.CurrentPermissions; | ||
1446 | descend.ItemData[i].FolderID = item.Folder; | ||
1447 | descend.ItemData[i].InvType = (sbyte)item.InvType; | ||
1448 | descend.ItemData[i].Name = Helpers.StringToField(item.Name); | ||
1449 | descend.ItemData[i].NextOwnerMask = item.NextPermissions; | ||
1450 | descend.ItemData[i].OwnerID = item.Owner; | ||
1451 | descend.ItemData[i].Type = (sbyte)item.AssetType; | ||
1452 | |||
1453 | //descend.ItemData[i].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); | ||
1454 | descend.ItemData[i].GroupID = item.GroupID; | ||
1455 | descend.ItemData[i].GroupOwned = item.GroupOwned; | ||
1456 | descend.ItemData[i].GroupMask = 0; | ||
1457 | descend.ItemData[i].CreationDate = item.CreationDate; | ||
1458 | descend.ItemData[i].SalePrice = item.SalePrice; | ||
1459 | descend.ItemData[i].SaleType = item.SaleType; | ||
1460 | descend.ItemData[i].Flags = item.Flags; | ||
1461 | |||
1462 | descend.ItemData[i].CRC = | ||
1463 | Helpers.InventoryCRC(descend.ItemData[i].CreationDate, descend.ItemData[i].SaleType, | ||
1464 | descend.ItemData[i].InvType, descend.ItemData[i].Type, | ||
1465 | descend.ItemData[i].AssetID, descend.ItemData[i].GroupID, | ||
1466 | descend.ItemData[i].SalePrice, | ||
1467 | descend.ItemData[i].OwnerID, descend.ItemData[i].CreatorID, | ||
1468 | descend.ItemData[i].ItemID, descend.ItemData[i].FolderID, | ||
1469 | descend.ItemData[i].EveryoneMask, | ||
1470 | descend.ItemData[i].Flags, descend.ItemData[i].OwnerMask, | ||
1471 | descend.ItemData[i].GroupMask, item.CurrentPermissions); | ||
1472 | |||
1473 | i++; | ||
1474 | count++; | ||
1475 | if (i == MAX_ITEMS_PER_PACKET) | ||
1476 | { | ||
1477 | descend.Header.Zerocoded = true; | ||
1478 | OutPacket(descend, ThrottleOutPacketType.Asset); | ||
1479 | |||
1480 | if ((items.Count - count) > 0) | ||
1481 | { | ||
1482 | descend = CreateInventoryDescendentsPacket(ownerID, folderID); | ||
1483 | if ((items.Count - count) < MAX_ITEMS_PER_PACKET) | ||
1484 | { | ||
1485 | descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count - count]; | ||
1486 | descend.AgentData.Descendents = items.Count - count; | ||
1487 | } | ||
1488 | else | ||
1489 | { | ||
1490 | descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET]; | ||
1491 | descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET; | ||
1492 | } | ||
1493 | i = 0; | ||
1494 | } | ||
1495 | } | ||
1496 | } | ||
1497 | |||
1498 | if (i < MAX_ITEMS_PER_PACKET) | ||
1499 | { | ||
1500 | OutPacket(descend, ThrottleOutPacketType.Asset); | ||
1501 | } | ||
1502 | } | ||
1503 | |||
1504 | //send subfolders | ||
1505 | if (fetchFolders) | ||
1506 | { | ||
1507 | InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID); | ||
1508 | |||
1509 | if (folders.Count < MAX_ITEMS_PER_PACKET) | ||
1510 | { | ||
1511 | descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders.Count]; | ||
1512 | descend.AgentData.Descendents = folders.Count; | ||
1513 | } | ||
1514 | else | ||
1515 | { | ||
1516 | descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET]; | ||
1517 | descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET; | ||
1518 | } | ||
1519 | |||
1520 | // Not sure if this scenario ever actually occurs, but nonetheless we include the items | ||
1521 | // count even if we're not sending item data for the same reasons as above. | ||
1522 | if (!fetchItems) | ||
1523 | { | ||
1524 | descend.AgentData.Descendents += items.Count; | ||
1525 | } | ||
1526 | |||
1527 | int i = 0; | ||
1528 | int count = 0; | ||
1529 | foreach (InventoryFolderBase folder in folders) | ||
1530 | { | ||
1531 | descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock(); | ||
1532 | descend.FolderData[i].FolderID = folder.ID; | ||
1533 | descend.FolderData[i].Name = Helpers.StringToField(folder.Name); | ||
1534 | descend.FolderData[i].ParentID = folder.ParentID; | ||
1535 | descend.FolderData[i].Type = (sbyte)folder.Type; | ||
1536 | |||
1537 | i++; | ||
1538 | count++; | ||
1539 | if (i == MAX_ITEMS_PER_PACKET) | ||
1540 | { | ||
1541 | OutPacket(descend, ThrottleOutPacketType.Asset); | ||
1542 | |||
1543 | if ((folders.Count - count) > 0) | ||
1544 | { | ||
1545 | descend = CreateInventoryDescendentsPacket(ownerID, folderID); | ||
1546 | if ((folders.Count - count) < MAX_ITEMS_PER_PACKET) | ||
1547 | { | ||
1548 | descend.FolderData = | ||
1549 | new InventoryDescendentsPacket.FolderDataBlock[folders.Count - count]; | ||
1550 | descend.AgentData.Descendents = folders.Count - count; | ||
1551 | } | ||
1552 | else | ||
1553 | { | ||
1554 | descend.FolderData = | ||
1555 | new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET]; | ||
1556 | descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET; | ||
1557 | } | ||
1558 | i = 0; | ||
1559 | } | ||
1560 | } | ||
1561 | } | ||
1562 | |||
1563 | if (i < MAX_ITEMS_PER_PACKET) | ||
1564 | { | ||
1565 | OutPacket(descend, ThrottleOutPacketType.Asset); | ||
1566 | } | ||
1567 | } | ||
1568 | } | ||
1569 | |||
1570 | private InventoryDescendentsPacket CreateInventoryDescendentsPacket(LLUUID ownerID, LLUUID folderID) | ||
1571 | { | ||
1572 | InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents); | ||
1573 | descend.Header.Zerocoded = true; | ||
1574 | descend.AgentData.AgentID = AgentId; | ||
1575 | descend.AgentData.OwnerID = ownerID; | ||
1576 | descend.AgentData.FolderID = folderID; | ||
1577 | descend.AgentData.Version = 1; | ||
1578 | |||
1579 | return descend; | ||
1580 | } | ||
1581 | |||
1582 | public void SendInventoryItemDetails(LLUUID ownerID, InventoryItemBase item) | ||
1583 | { | ||
1584 | uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; | ||
1585 | FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply); | ||
1586 | // TODO: don't create new blocks if recycling an old packet | ||
1587 | inventoryReply.AgentData.AgentID = AgentId; | ||
1588 | inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1]; | ||
1589 | inventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock(); | ||
1590 | inventoryReply.InventoryData[0].ItemID = item.ID; | ||
1591 | inventoryReply.InventoryData[0].AssetID = item.AssetID; | ||
1592 | inventoryReply.InventoryData[0].CreatorID = item.Creator; | ||
1593 | inventoryReply.InventoryData[0].BaseMask = item.BasePermissions; | ||
1594 | inventoryReply.InventoryData[0].CreationDate = | ||
1595 | (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; | ||
1596 | inventoryReply.InventoryData[0].Description = Helpers.StringToField(item.Description); | ||
1597 | inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions; | ||
1598 | inventoryReply.InventoryData[0].FolderID = item.Folder; | ||
1599 | inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType; | ||
1600 | inventoryReply.InventoryData[0].Name = Helpers.StringToField(item.Name); | ||
1601 | inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions; | ||
1602 | inventoryReply.InventoryData[0].OwnerID = item.Owner; | ||
1603 | inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions; | ||
1604 | inventoryReply.InventoryData[0].Type = (sbyte)item.AssetType; | ||
1605 | |||
1606 | //inventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); | ||
1607 | inventoryReply.InventoryData[0].GroupID = item.GroupID; | ||
1608 | inventoryReply.InventoryData[0].GroupOwned = item.GroupOwned; | ||
1609 | inventoryReply.InventoryData[0].GroupMask = 0; | ||
1610 | inventoryReply.InventoryData[0].Flags = item.Flags; | ||
1611 | inventoryReply.InventoryData[0].SalePrice = item.SalePrice; | ||
1612 | inventoryReply.InventoryData[0].SaleType = item.SaleType; | ||
1613 | |||
1614 | inventoryReply.InventoryData[0].CRC = | ||
1615 | Helpers.InventoryCRC(1000, 0, inventoryReply.InventoryData[0].InvType, | ||
1616 | inventoryReply.InventoryData[0].Type, inventoryReply.InventoryData[0].AssetID, | ||
1617 | inventoryReply.InventoryData[0].GroupID, 100, | ||
1618 | inventoryReply.InventoryData[0].OwnerID, inventoryReply.InventoryData[0].CreatorID, | ||
1619 | inventoryReply.InventoryData[0].ItemID, inventoryReply.InventoryData[0].FolderID, | ||
1620 | FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, | ||
1621 | FULL_MASK_PERMISSIONS); | ||
1622 | inventoryReply.Header.Zerocoded = true; | ||
1623 | OutPacket(inventoryReply, ThrottleOutPacketType.Asset); | ||
1624 | } | ||
1625 | |||
1626 | /// <see>IClientAPI.SendBulkUpdateInventory(InventoryItemBase)</see> | ||
1627 | public void SendBulkUpdateInventory(InventoryItemBase item) | ||
1628 | { | ||
1629 | uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; | ||
1630 | |||
1631 | BulkUpdateInventoryPacket bulkUpdate | ||
1632 | = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory); | ||
1633 | |||
1634 | bulkUpdate.AgentData.AgentID = AgentId; | ||
1635 | bulkUpdate.AgentData.TransactionID = LLUUID.Random(); | ||
1636 | |||
1637 | bulkUpdate.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[1]; | ||
1638 | bulkUpdate.FolderData[0] = new BulkUpdateInventoryPacket.FolderDataBlock(); | ||
1639 | bulkUpdate.FolderData[0].FolderID = LLUUID.Zero; | ||
1640 | bulkUpdate.FolderData[0].ParentID = LLUUID.Zero; | ||
1641 | bulkUpdate.FolderData[0].Type = -1; | ||
1642 | bulkUpdate.FolderData[0].Name = new byte[0]; | ||
1643 | |||
1644 | bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[1]; | ||
1645 | bulkUpdate.ItemData[0] = new BulkUpdateInventoryPacket.ItemDataBlock(); | ||
1646 | bulkUpdate.ItemData[0].ItemID = item.ID; | ||
1647 | bulkUpdate.ItemData[0].AssetID = item.AssetID; | ||
1648 | bulkUpdate.ItemData[0].CreatorID = item.Creator; | ||
1649 | bulkUpdate.ItemData[0].BaseMask = item.BasePermissions; | ||
1650 | bulkUpdate.ItemData[0].CreationDate = 1000; | ||
1651 | bulkUpdate.ItemData[0].Description = Helpers.StringToField(item.Description); | ||
1652 | bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions; | ||
1653 | bulkUpdate.ItemData[0].FolderID = item.Folder; | ||
1654 | bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType; | ||
1655 | bulkUpdate.ItemData[0].Name = Helpers.StringToField(item.Name); | ||
1656 | bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions; | ||
1657 | bulkUpdate.ItemData[0].OwnerID = item.Owner; | ||
1658 | bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions; | ||
1659 | bulkUpdate.ItemData[0].Type = (sbyte)item.AssetType; | ||
1660 | |||
1661 | //bulkUpdate.ItemData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); | ||
1662 | bulkUpdate.ItemData[0].GroupID = item.GroupID; | ||
1663 | bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned; | ||
1664 | bulkUpdate.ItemData[0].GroupMask = 0; | ||
1665 | bulkUpdate.ItemData[0].Flags = item.Flags; | ||
1666 | bulkUpdate.ItemData[0].SalePrice = item.SalePrice; | ||
1667 | bulkUpdate.ItemData[0].SaleType = item.SaleType; | ||
1668 | |||
1669 | bulkUpdate.ItemData[0].CRC = | ||
1670 | Helpers.InventoryCRC(1000, 0, bulkUpdate.ItemData[0].InvType, | ||
1671 | bulkUpdate.ItemData[0].Type, bulkUpdate.ItemData[0].AssetID, | ||
1672 | bulkUpdate.ItemData[0].GroupID, 100, | ||
1673 | bulkUpdate.ItemData[0].OwnerID, bulkUpdate.ItemData[0].CreatorID, | ||
1674 | bulkUpdate.ItemData[0].ItemID, bulkUpdate.ItemData[0].FolderID, | ||
1675 | FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, | ||
1676 | FULL_MASK_PERMISSIONS); | ||
1677 | bulkUpdate.Header.Zerocoded = true; | ||
1678 | OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); | ||
1679 | } | ||
1680 | |||
1681 | /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see> | ||
1682 | public void SendInventoryItemCreateUpdate(InventoryItemBase Item) | ||
1683 | { | ||
1684 | uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; | ||
1685 | |||
1686 | UpdateCreateInventoryItemPacket InventoryReply | ||
1687 | = (UpdateCreateInventoryItemPacket)PacketPool.Instance.GetPacket( | ||
1688 | PacketType.UpdateCreateInventoryItem); | ||
1689 | |||
1690 | // TODO: don't create new blocks if recycling an old packet | ||
1691 | InventoryReply.AgentData.AgentID = AgentId; | ||
1692 | InventoryReply.AgentData.SimApproved = true; | ||
1693 | InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; | ||
1694 | InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); | ||
1695 | InventoryReply.InventoryData[0].ItemID = Item.ID; | ||
1696 | InventoryReply.InventoryData[0].AssetID = Item.AssetID; | ||
1697 | InventoryReply.InventoryData[0].CreatorID = Item.Creator; | ||
1698 | InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions; | ||
1699 | InventoryReply.InventoryData[0].Description = Helpers.StringToField(Item.Description); | ||
1700 | InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions; | ||
1701 | InventoryReply.InventoryData[0].FolderID = Item.Folder; | ||
1702 | InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType; | ||
1703 | InventoryReply.InventoryData[0].Name = Helpers.StringToField(Item.Name); | ||
1704 | InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions; | ||
1705 | InventoryReply.InventoryData[0].OwnerID = Item.Owner; | ||
1706 | InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions; | ||
1707 | InventoryReply.InventoryData[0].Type = (sbyte)Item.AssetType; | ||
1708 | |||
1709 | //InventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); | ||
1710 | InventoryReply.InventoryData[0].GroupID = Item.GroupID; | ||
1711 | InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned; | ||
1712 | InventoryReply.InventoryData[0].GroupMask = 0; | ||
1713 | InventoryReply.InventoryData[0].Flags = Item.Flags; | ||
1714 | InventoryReply.InventoryData[0].SalePrice = Item.SalePrice; | ||
1715 | InventoryReply.InventoryData[0].SaleType = Item.SaleType; | ||
1716 | InventoryReply.InventoryData[0].CreationDate = Item.CreationDate; | ||
1717 | |||
1718 | InventoryReply.InventoryData[0].CRC = | ||
1719 | Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType, | ||
1720 | InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID, | ||
1721 | InventoryReply.InventoryData[0].GroupID, 100, | ||
1722 | InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID, | ||
1723 | InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID, | ||
1724 | FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, | ||
1725 | FULL_MASK_PERMISSIONS); | ||
1726 | InventoryReply.Header.Zerocoded = true; | ||
1727 | OutPacket(InventoryReply, ThrottleOutPacketType.Asset); | ||
1728 | } | ||
1729 | |||
1730 | public void SendRemoveInventoryItem(LLUUID itemID) | ||
1731 | { | ||
1732 | RemoveInventoryItemPacket remove = (RemoveInventoryItemPacket)PacketPool.Instance.GetPacket(PacketType.RemoveInventoryItem); | ||
1733 | // TODO: don't create new blocks if recycling an old packet | ||
1734 | remove.AgentData.AgentID = AgentId; | ||
1735 | remove.AgentData.SessionID = m_sessionId; | ||
1736 | remove.InventoryData = new RemoveInventoryItemPacket.InventoryDataBlock[1]; | ||
1737 | remove.InventoryData[0] = new RemoveInventoryItemPacket.InventoryDataBlock(); | ||
1738 | remove.InventoryData[0].ItemID = itemID; | ||
1739 | remove.Header.Zerocoded = true; | ||
1740 | OutPacket(remove, ThrottleOutPacketType.Asset); | ||
1741 | } | ||
1742 | |||
1743 | public void SendTakeControls(int controls, bool passToAgent, bool TakeControls) | ||
1744 | { | ||
1745 | ScriptControlChangePacket scriptcontrol = (ScriptControlChangePacket)PacketPool.Instance.GetPacket(PacketType.ScriptControlChange); | ||
1746 | ScriptControlChangePacket.DataBlock[] data = new ScriptControlChangePacket.DataBlock[1]; | ||
1747 | ScriptControlChangePacket.DataBlock ddata = new ScriptControlChangePacket.DataBlock(); | ||
1748 | ddata.Controls = (uint)controls; | ||
1749 | ddata.PassToAgent = passToAgent; | ||
1750 | ddata.TakeControls = TakeControls; | ||
1751 | data[0] = ddata; | ||
1752 | scriptcontrol.Data = data; | ||
1753 | OutPacket(scriptcontrol, ThrottleOutPacketType.Task); | ||
1754 | } | ||
1755 | |||
1756 | public void SendTaskInventory(LLUUID taskID, short serial, byte[] fileName) | ||
1757 | { | ||
1758 | ReplyTaskInventoryPacket replytask = (ReplyTaskInventoryPacket)PacketPool.Instance.GetPacket(PacketType.ReplyTaskInventory); | ||
1759 | replytask.InventoryData.TaskID = taskID; | ||
1760 | replytask.InventoryData.Serial = serial; | ||
1761 | replytask.InventoryData.Filename = fileName; | ||
1762 | OutPacket(replytask, ThrottleOutPacketType.Asset); | ||
1763 | } | ||
1764 | |||
1765 | public void SendXferPacket(ulong xferID, uint packet, byte[] data) | ||
1766 | { | ||
1767 | SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); | ||
1768 | sendXfer.XferID.ID = xferID; | ||
1769 | sendXfer.XferID.Packet = packet; | ||
1770 | sendXfer.DataPacket.Data = data; | ||
1771 | OutPacket(sendXfer, ThrottleOutPacketType.Task); | ||
1772 | } | ||
1773 | |||
1774 | public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, | ||
1775 | int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor, | ||
1776 | int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay, | ||
1777 | int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent) | ||
1778 | { | ||
1779 | EconomyDataPacket economyData = (EconomyDataPacket)PacketPool.Instance.GetPacket(PacketType.EconomyData); | ||
1780 | economyData.Info.EnergyEfficiency = EnergyEfficiency; | ||
1781 | economyData.Info.ObjectCapacity = ObjectCapacity; | ||
1782 | economyData.Info.ObjectCount = ObjectCount; | ||
1783 | economyData.Info.PriceEnergyUnit = PriceEnergyUnit; | ||
1784 | economyData.Info.PriceGroupCreate = PriceGroupCreate; | ||
1785 | economyData.Info.PriceObjectClaim = PriceObjectClaim; | ||
1786 | economyData.Info.PriceObjectRent = PriceObjectRent; | ||
1787 | economyData.Info.PriceObjectScaleFactor = PriceObjectScaleFactor; | ||
1788 | economyData.Info.PriceParcelClaim = PriceParcelClaim; | ||
1789 | economyData.Info.PriceParcelClaimFactor = PriceParcelClaimFactor; | ||
1790 | economyData.Info.PriceParcelRent = PriceParcelRent; | ||
1791 | economyData.Info.PricePublicObjectDecay = PricePublicObjectDecay; | ||
1792 | economyData.Info.PricePublicObjectDelete = PricePublicObjectDelete; | ||
1793 | economyData.Info.PriceRentLight = PriceRentLight; | ||
1794 | economyData.Info.PriceUpload = PriceUpload; | ||
1795 | economyData.Info.TeleportMinPrice = TeleportMinPrice; | ||
1796 | economyData.Info.TeleportPriceExponent = TeleportPriceExponent; | ||
1797 | economyData.Header.Reliable = true; | ||
1798 | OutPacket(economyData, ThrottleOutPacketType.Unknown); | ||
1799 | } | ||
1800 | |||
1801 | public void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List<AvatarPickerReplyDataArgs> Data) | ||
1802 | { | ||
1803 | //construct the AvatarPickerReply packet. | ||
1804 | AvatarPickerReplyPacket replyPacket = new AvatarPickerReplyPacket(); | ||
1805 | replyPacket.AgentData.AgentID = AgentData.AgentID; | ||
1806 | replyPacket.AgentData.QueryID = AgentData.QueryID; | ||
1807 | //int i = 0; | ||
1808 | List<AvatarPickerReplyPacket.DataBlock> data_block = new List<AvatarPickerReplyPacket.DataBlock>(); | ||
1809 | foreach (AvatarPickerReplyDataArgs arg in Data) | ||
1810 | { | ||
1811 | AvatarPickerReplyPacket.DataBlock db = new AvatarPickerReplyPacket.DataBlock(); | ||
1812 | db.AvatarID = arg.AvatarID; | ||
1813 | db.FirstName = arg.FirstName; | ||
1814 | db.LastName = arg.LastName; | ||
1815 | data_block.Add(db); | ||
1816 | } | ||
1817 | replyPacket.Data = data_block.ToArray(); | ||
1818 | OutPacket(replyPacket, ThrottleOutPacketType.Task); | ||
1819 | } | ||
1820 | |||
1821 | public void SendAgentDataUpdate(LLUUID agentid, LLUUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle) | ||
1822 | { | ||
1823 | |||
1824 | m_activeGroupID = activegroupid; | ||
1825 | m_activeGroupName = groupname; | ||
1826 | m_activeGroupPowers = grouppowers; | ||
1827 | |||
1828 | AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate); | ||
1829 | sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid; | ||
1830 | sendAgentDataUpdate.AgentData.AgentID = agentid; | ||
1831 | sendAgentDataUpdate.AgentData.FirstName = Helpers.StringToField(firstname); | ||
1832 | sendAgentDataUpdate.AgentData.GroupName = Helpers.StringToField(groupname); | ||
1833 | sendAgentDataUpdate.AgentData.GroupPowers = grouppowers; | ||
1834 | sendAgentDataUpdate.AgentData.GroupTitle = Helpers.StringToField(grouptitle); | ||
1835 | sendAgentDataUpdate.AgentData.LastName = Helpers.StringToField(lastname); | ||
1836 | OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task); | ||
1837 | } | ||
1838 | |||
1839 | /// <summary> | ||
1840 | /// Send an alert message to the client. On the Linden client (tested 1.19.1.4), this pops up a brief duration | ||
1841 | /// blue information box in the bottom right hand corner. | ||
1842 | /// </summary> | ||
1843 | /// <param name="message"></param> | ||
1844 | public void SendAlertMessage(string message) | ||
1845 | { | ||
1846 | AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage); | ||
1847 | alertPack.AlertData.Message = Helpers.StringToField(message); | ||
1848 | OutPacket(alertPack, ThrottleOutPacketType.Task); | ||
1849 | } | ||
1850 | |||
1851 | /// <summary> | ||
1852 | /// Send an agent alert message to the client. | ||
1853 | /// </summary> | ||
1854 | /// <param name="message"></param> | ||
1855 | /// <param name="modal">On the linden client, if this true then it displays a one button text box placed in the | ||
1856 | /// middle of the window. If false, the message is displayed in a brief duration blue information box (as for | ||
1857 | /// the AlertMessage packet).</param> | ||
1858 | public void SendAgentAlertMessage(string message, bool modal) | ||
1859 | { | ||
1860 | OutPacket(BuildAgentAlertPacket(message, modal), ThrottleOutPacketType.Task); | ||
1861 | } | ||
1862 | |||
1863 | /// <summary> | ||
1864 | /// Construct an agent alert packet | ||
1865 | /// </summary> | ||
1866 | /// <param name="message"></param> | ||
1867 | /// <param name="modal"></param> | ||
1868 | /// <returns></returns> | ||
1869 | protected AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) | ||
1870 | { | ||
1871 | AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); | ||
1872 | alertPack.AgentData.AgentID = AgentId; | ||
1873 | alertPack.AlertData.Message = Helpers.StringToField(message); | ||
1874 | alertPack.AlertData.Modal = modal; | ||
1875 | |||
1876 | return alertPack; | ||
1877 | } | ||
1878 | |||
1879 | public void SendLoadURL(string objectname, LLUUID objectID, LLUUID ownerID, bool groupOwned, string message, | ||
1880 | string url) | ||
1881 | { | ||
1882 | LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL); | ||
1883 | loadURL.Data.ObjectName = Helpers.StringToField(objectname); | ||
1884 | loadURL.Data.ObjectID = objectID; | ||
1885 | loadURL.Data.OwnerID = ownerID; | ||
1886 | loadURL.Data.OwnerIsGroup = groupOwned; | ||
1887 | loadURL.Data.Message = Helpers.StringToField(message); | ||
1888 | loadURL.Data.URL = Helpers.StringToField(url); | ||
1889 | OutPacket(loadURL, ThrottleOutPacketType.Task); | ||
1890 | } | ||
1891 | |||
1892 | public void SendDialog(string objectname, LLUUID objectID, LLUUID ownerID, string msg, LLUUID textureID, int ch, string[] buttonlabels) | ||
1893 | { | ||
1894 | ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); | ||
1895 | dialog.Data.ObjectID = objectID; | ||
1896 | dialog.Data.ObjectName = Helpers.StringToField(objectname); | ||
1897 | dialog.Data.FirstName = Helpers.StringToField(this.FirstName); | ||
1898 | dialog.Data.LastName = Helpers.StringToField(this.LastName); | ||
1899 | dialog.Data.Message = Helpers.StringToField(msg); | ||
1900 | dialog.Data.ImageID = textureID; | ||
1901 | dialog.Data.ChatChannel = ch; | ||
1902 | ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length]; | ||
1903 | for (int i = 0; i < buttonlabels.Length; i++) | ||
1904 | { | ||
1905 | buttons[i] = new ScriptDialogPacket.ButtonsBlock(); | ||
1906 | buttons[i].ButtonLabel = Helpers.StringToField(buttonlabels[i]); | ||
1907 | } | ||
1908 | dialog.Buttons = buttons; | ||
1909 | OutPacket(dialog, ThrottleOutPacketType.Task); | ||
1910 | } | ||
1911 | |||
1912 | public void SendPreLoadSound(LLUUID objectID, LLUUID ownerID, LLUUID soundID) | ||
1913 | { | ||
1914 | PreloadSoundPacket preSound = (PreloadSoundPacket)PacketPool.Instance.GetPacket(PacketType.PreloadSound); | ||
1915 | // TODO: don't create new blocks if recycling an old packet | ||
1916 | preSound.DataBlock = new PreloadSoundPacket.DataBlockBlock[1]; | ||
1917 | preSound.DataBlock[0] = new PreloadSoundPacket.DataBlockBlock(); | ||
1918 | preSound.DataBlock[0].ObjectID = objectID; | ||
1919 | preSound.DataBlock[0].OwnerID = ownerID; | ||
1920 | preSound.DataBlock[0].SoundID = soundID; | ||
1921 | preSound.Header.Zerocoded = true; | ||
1922 | OutPacket(preSound, ThrottleOutPacketType.Task); | ||
1923 | } | ||
1924 | |||
1925 | public void SendPlayAttachedSound(LLUUID soundID, LLUUID objectID, LLUUID ownerID, float gain, byte flags) | ||
1926 | { | ||
1927 | AttachedSoundPacket sound = (AttachedSoundPacket)PacketPool.Instance.GetPacket(PacketType.AttachedSound); | ||
1928 | sound.DataBlock.SoundID = soundID; | ||
1929 | sound.DataBlock.ObjectID = objectID; | ||
1930 | sound.DataBlock.OwnerID = ownerID; | ||
1931 | sound.DataBlock.Gain = gain; | ||
1932 | sound.DataBlock.Flags = flags; | ||
1933 | |||
1934 | OutPacket(sound, ThrottleOutPacketType.Task); | ||
1935 | } | ||
1936 | |||
1937 | public void SendTriggeredSound(LLUUID soundID, LLUUID ownerID, LLUUID objectID, LLUUID parentID, ulong handle, LLVector3 position, float gain) | ||
1938 | { | ||
1939 | SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); | ||
1940 | sound.SoundData.SoundID = soundID; | ||
1941 | sound.SoundData.OwnerID = ownerID; | ||
1942 | sound.SoundData.ObjectID = objectID; | ||
1943 | sound.SoundData.ParentID = parentID; | ||
1944 | sound.SoundData.Handle = handle; | ||
1945 | sound.SoundData.Position = position; | ||
1946 | sound.SoundData.Gain = gain; | ||
1947 | |||
1948 | OutPacket(sound, ThrottleOutPacketType.Task); | ||
1949 | } | ||
1950 | |||
1951 | public void SendAttachedSoundGainChange(LLUUID objectID, float gain) | ||
1952 | { | ||
1953 | AttachedSoundGainChangePacket sound = (AttachedSoundGainChangePacket)PacketPool.Instance.GetPacket(PacketType.AttachedSoundGainChange); | ||
1954 | sound.DataBlock.ObjectID = objectID; | ||
1955 | sound.DataBlock.Gain = gain; | ||
1956 | |||
1957 | OutPacket(sound, ThrottleOutPacketType.Task); | ||
1958 | } | ||
1959 | |||
1960 | public void SendSunPos(LLVector3 Position, LLVector3 Velocity, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition) | ||
1961 | { | ||
1962 | SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); | ||
1963 | viewertime.TimeInfo.SunDirection = Position; | ||
1964 | viewertime.TimeInfo.SunAngVelocity = Velocity; | ||
1965 | viewertime.TimeInfo.UsecSinceStart = CurrentTime; | ||
1966 | viewertime.TimeInfo.SecPerDay = SecondsPerSunCycle; | ||
1967 | viewertime.TimeInfo.SecPerYear = SecondsPerYear; | ||
1968 | viewertime.TimeInfo.SunPhase = OrbitalPosition; | ||
1969 | viewertime.Header.Reliable = false; | ||
1970 | viewertime.Header.Zerocoded = true; | ||
1971 | OutPacket(viewertime, ThrottleOutPacketType.Task); | ||
1972 | } | ||
1973 | |||
1974 | // Currently Deprecated | ||
1975 | public void SendViewerTime(int phase) | ||
1976 | { | ||
1977 | /* | ||
1978 | Console.WriteLine("SunPhase: {0}", phase); | ||
1979 | SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); | ||
1980 | //viewertime.TimeInfo.SecPerDay = 86400; | ||
1981 | //viewertime.TimeInfo.SecPerYear = 31536000; | ||
1982 | viewertime.TimeInfo.SecPerDay = 1000; | ||
1983 | viewertime.TimeInfo.SecPerYear = 365000; | ||
1984 | viewertime.TimeInfo.SunPhase = 1; | ||
1985 | int sunPhase = (phase + 2) / 2; | ||
1986 | if ((sunPhase < 6) || (sunPhase > 36)) | ||
1987 | { | ||
1988 | viewertime.TimeInfo.SunDirection = new LLVector3(0f, 0.8f, -0.8f); | ||
1989 | Console.WriteLine("sending night"); | ||
1990 | } | ||
1991 | else | ||
1992 | { | ||
1993 | if (sunPhase < 12) | ||
1994 | { | ||
1995 | sunPhase = 12; | ||
1996 | } | ||
1997 | sunPhase = sunPhase - 12; | ||
1998 | |||
1999 | float yValue = 0.1f * (sunPhase); | ||
2000 | Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue); | ||
2001 | if (yValue > 1.2f) | ||
2002 | { | ||
2003 | yValue = yValue - 1.2f; | ||
2004 | } | ||
2005 | |||
2006 | yValue = Util.Clip(yValue, 0, 1); | ||
2007 | |||
2008 | if (sunPhase < 14) | ||
2009 | { | ||
2010 | yValue = 1 - yValue; | ||
2011 | } | ||
2012 | if (sunPhase < 12) | ||
2013 | { | ||
2014 | yValue *= -1; | ||
2015 | } | ||
2016 | viewertime.TimeInfo.SunDirection = new LLVector3(0f, yValue, 0.3f); | ||
2017 | Console.WriteLine("sending sun update " + yValue); | ||
2018 | } | ||
2019 | viewertime.TimeInfo.SunAngVelocity = new LLVector3(0, 0.0f, 10.0f); | ||
2020 | viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch(); | ||
2021 | viewertime.Header.Reliable = false; | ||
2022 | OutPacket(viewertime, ThrottleOutPacketType.Task); | ||
2023 | */ | ||
2024 | } | ||
2025 | |||
2026 | public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, | ||
2027 | string flAbout, uint flags, LLUUID flImageID, LLUUID imageID, string profileURL, | ||
2028 | LLUUID partnerID) | ||
2029 | { | ||
2030 | AvatarPropertiesReplyPacket avatarReply = (AvatarPropertiesReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPropertiesReply); | ||
2031 | avatarReply.AgentData.AgentID = AgentId; | ||
2032 | avatarReply.AgentData.AvatarID = avatarID; | ||
2033 | if (aboutText != null) | ||
2034 | avatarReply.PropertiesData.AboutText = Helpers.StringToField(aboutText); | ||
2035 | else | ||
2036 | avatarReply.PropertiesData.AboutText = Helpers.StringToField(""); | ||
2037 | avatarReply.PropertiesData.BornOn = Helpers.StringToField(bornOn); | ||
2038 | avatarReply.PropertiesData.CharterMember = Helpers.StringToField(charterMember); | ||
2039 | if (flAbout != null) | ||
2040 | avatarReply.PropertiesData.FLAboutText = Helpers.StringToField(flAbout); | ||
2041 | else | ||
2042 | avatarReply.PropertiesData.FLAboutText = Helpers.StringToField(""); | ||
2043 | avatarReply.PropertiesData.Flags = 0; | ||
2044 | avatarReply.PropertiesData.FLImageID = flImageID; | ||
2045 | avatarReply.PropertiesData.ImageID = imageID; | ||
2046 | avatarReply.PropertiesData.ProfileURL = Helpers.StringToField(profileURL); | ||
2047 | avatarReply.PropertiesData.PartnerID = partnerID; | ||
2048 | OutPacket(avatarReply, ThrottleOutPacketType.Task); | ||
2049 | } | ||
2050 | |||
2051 | #endregion | ||
2052 | |||
2053 | #region Appearance/ Wearables Methods | ||
2054 | |||
2055 | /// <summary> | ||
2056 | /// | ||
2057 | /// </summary> | ||
2058 | /// <param name="wearables"></param> | ||
2059 | public void SendWearables(AvatarWearable[] wearables, int serial) | ||
2060 | { | ||
2061 | AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate); | ||
2062 | aw.AgentData.AgentID = AgentId; | ||
2063 | aw.AgentData.SerialNum = (uint)serial; | ||
2064 | aw.AgentData.SessionID = m_sessionId; | ||
2065 | |||
2066 | // TODO: don't create new blocks if recycling an old packet | ||
2067 | aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; | ||
2068 | AgentWearablesUpdatePacket.WearableDataBlock awb; | ||
2069 | for (int i = 0; i < wearables.Length; i++) | ||
2070 | { | ||
2071 | awb = new AgentWearablesUpdatePacket.WearableDataBlock(); | ||
2072 | awb.WearableType = (byte)i; | ||
2073 | awb.AssetID = wearables[i].AssetID; | ||
2074 | awb.ItemID = wearables[i].ItemID; | ||
2075 | aw.WearableData[i] = awb; | ||
2076 | } | ||
2077 | |||
2078 | OutPacket(aw, ThrottleOutPacketType.Task); | ||
2079 | } | ||
2080 | |||
2081 | /// <summary> | ||
2082 | /// | ||
2083 | /// </summary> | ||
2084 | /// <param name="agentID"></param> | ||
2085 | /// <param name="visualParams"></param> | ||
2086 | /// <param name="textureEntry"></param> | ||
2087 | public void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry) | ||
2088 | { | ||
2089 | AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); | ||
2090 | // TODO: don't create new blocks if recycling an old packet | ||
2091 | avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; | ||
2092 | avp.ObjectData.TextureEntry = textureEntry; | ||
2093 | |||
2094 | AvatarAppearancePacket.VisualParamBlock avblock = null; | ||
2095 | for (int i = 0; i < visualParams.Length; i++) | ||
2096 | { | ||
2097 | avblock = new AvatarAppearancePacket.VisualParamBlock(); | ||
2098 | avblock.ParamValue = visualParams[i]; | ||
2099 | avp.VisualParam[i] = avblock; | ||
2100 | } | ||
2101 | |||
2102 | avp.Sender.IsTrial = false; | ||
2103 | avp.Sender.ID = agentID; | ||
2104 | OutPacket(avp, ThrottleOutPacketType.Task); | ||
2105 | } | ||
2106 | |||
2107 | public void SendAnimations(LLUUID[] animations, int[] seqs, LLUUID sourceAgentId) | ||
2108 | { | ||
2109 | AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); | ||
2110 | // TODO: don't create new blocks if recycling an old packet | ||
2111 | ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1]; | ||
2112 | ani.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock(); | ||
2113 | ani.AnimationSourceList[0].ObjectID = sourceAgentId; | ||
2114 | ani.Sender = new AvatarAnimationPacket.SenderBlock(); | ||
2115 | ani.Sender.ID = sourceAgentId; | ||
2116 | ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; | ||
2117 | |||
2118 | for (int i = 0; i < animations.Length; ++i) | ||
2119 | { | ||
2120 | ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); | ||
2121 | ani.AnimationList[i].AnimID = animations[i]; | ||
2122 | ani.AnimationList[i].AnimSequenceID = seqs[i]; | ||
2123 | } | ||
2124 | ani.Header.Reliable = false; | ||
2125 | OutPacket(ani, ThrottleOutPacketType.Task); | ||
2126 | } | ||
2127 | |||
2128 | #endregion | ||
2129 | |||
2130 | #region Avatar Packet/data sending Methods | ||
2131 | |||
2132 | /// <summary> | ||
2133 | /// send a objectupdate packet with information about the clients avatar | ||
2134 | /// </summary> | ||
2135 | /// <param name="regionInfo"></param> | ||
2136 | /// <param name="firstName"></param> | ||
2137 | /// <param name="lastName"></param> | ||
2138 | /// <param name="avatarID"></param> | ||
2139 | /// <param name="avatarLocalID"></param> | ||
2140 | /// <param name="Pos"></param> | ||
2141 | public void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID, | ||
2142 | uint avatarLocalID, LLVector3 Pos, byte[] textureEntry, uint parentID, LLQuaternion rotation) | ||
2143 | { | ||
2144 | ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); | ||
2145 | // TODO: don't create new blocks if recycling an old packet | ||
2146 | objupdate.RegionData.RegionHandle = regionHandle; | ||
2147 | objupdate.RegionData.TimeDilation = ushort.MaxValue; | ||
2148 | objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; | ||
2149 | objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); | ||
2150 | |||
2151 | //give this avatar object a local id and assign the user a name | ||
2152 | objupdate.ObjectData[0].ID = avatarLocalID; | ||
2153 | objupdate.ObjectData[0].FullID = avatarID; | ||
2154 | objupdate.ObjectData[0].ParentID = parentID; | ||
2155 | objupdate.ObjectData[0].NameValue = | ||
2156 | Helpers.StringToField("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName); | ||
2157 | |||
2158 | LLVector3 pos2 = new LLVector3((float)Pos.X, (float)Pos.Y, (float)Pos.Z); | ||
2159 | byte[] pb = pos2.GetBytes(); | ||
2160 | Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); | ||
2161 | |||
2162 | byte[] rot = rotation.GetBytes(); | ||
2163 | Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); | ||
2164 | |||
2165 | objupdate.Header.Zerocoded = true; | ||
2166 | OutPacket(objupdate, ThrottleOutPacketType.Task); | ||
2167 | } | ||
2168 | |||
2169 | /// <summary> | ||
2170 | /// | ||
2171 | /// </summary> | ||
2172 | /// <param name="regionHandle"></param> | ||
2173 | /// <param name="timeDilation"></param> | ||
2174 | /// <param name="localID"></param> | ||
2175 | /// <param name="position"></param> | ||
2176 | /// <param name="velocity"></param> | ||
2177 | public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, | ||
2178 | LLVector3 velocity, LLQuaternion rotation) | ||
2179 | { | ||
2180 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) | ||
2181 | rotation = LLQuaternion.Identity; | ||
2182 | |||
2183 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = | ||
2184 | CreateAvatarImprovedBlock(localID, position, velocity, rotation); | ||
2185 | ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
2186 | // TODO: don't create new blocks if recycling an old packet | ||
2187 | terse.RegionData.RegionHandle = regionHandle; | ||
2188 | terse.RegionData.TimeDilation = timeDilation; | ||
2189 | terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | ||
2190 | terse.ObjectData[0] = terseBlock; | ||
2191 | |||
2192 | terse.Header.Reliable = false; | ||
2193 | |||
2194 | terse.Header.Zerocoded = true; | ||
2195 | OutPacket(terse, ThrottleOutPacketType.Task); | ||
2196 | } | ||
2197 | |||
2198 | public void SendCoarseLocationUpdate(List<LLVector3> CoarseLocations) | ||
2199 | { | ||
2200 | CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); | ||
2201 | // TODO: don't create new blocks if recycling an old packet | ||
2202 | int total = CoarseLocations.Count; | ||
2203 | CoarseLocationUpdatePacket.IndexBlock ib = | ||
2204 | new CoarseLocationUpdatePacket.IndexBlock(); | ||
2205 | loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; | ||
2206 | for (int i = 0; i < total; i++) | ||
2207 | { | ||
2208 | CoarseLocationUpdatePacket.LocationBlock lb = | ||
2209 | new CoarseLocationUpdatePacket.LocationBlock(); | ||
2210 | lb.X = (byte)CoarseLocations[i].X; | ||
2211 | lb.Y = (byte)CoarseLocations[i].Y; | ||
2212 | lb.Z = (byte)(CoarseLocations[i].Z / 4); | ||
2213 | loc.Location[i] = lb; | ||
2214 | } | ||
2215 | ib.You = -1; | ||
2216 | ib.Prey = -1; | ||
2217 | loc.Index = ib; | ||
2218 | loc.Header.Reliable = false; | ||
2219 | loc.Header.Zerocoded = true; | ||
2220 | OutPacket(loc, ThrottleOutPacketType.Task); | ||
2221 | } | ||
2222 | |||
2223 | #endregion | ||
2224 | |||
2225 | #region Primitive Packet/data Sending Methods | ||
2226 | |||
2227 | /// <summary> | ||
2228 | /// | ||
2229 | /// </summary> | ||
2230 | /// <param name="localID"></param> | ||
2231 | /// <param name="rotation"></param> | ||
2232 | /// <param name="attachPoint"></param> | ||
2233 | public void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint) | ||
2234 | { | ||
2235 | |||
2236 | ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); | ||
2237 | Console.WriteLine("Attach object!"); | ||
2238 | // TODO: don't create new blocks if recycling an old packet | ||
2239 | attach.AgentData.AgentID = AgentId; | ||
2240 | attach.AgentData.SessionID = m_sessionId; | ||
2241 | attach.AgentData.AttachmentPoint = attachPoint; | ||
2242 | attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; | ||
2243 | attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); | ||
2244 | attach.ObjectData[0].ObjectLocalID = localID; | ||
2245 | attach.ObjectData[0].Rotation = rotation; | ||
2246 | attach.Header.Zerocoded = true; | ||
2247 | OutPacket(attach, ThrottleOutPacketType.Task); | ||
2248 | } | ||
2249 | |||
2250 | public void SendPrimitiveToClient( | ||
2251 | ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, | ||
2252 | LLVector3 pos, LLVector3 vel, LLVector3 acc, LLQuaternion rotation, LLVector3 rvel, | ||
2253 | uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, | ||
2254 | uint parentID, byte[] particleSystem, byte clickAction) | ||
2255 | { | ||
2256 | byte[] textureanim = new byte[0]; | ||
2257 | |||
2258 | SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, | ||
2259 | acc, rotation, rvel, flags, | ||
2260 | objectID, ownerID, text, color, parentID, particleSystem, | ||
2261 | clickAction, textureanim, false, (uint)0, LLUUID.Zero, LLUUID.Zero, 0, 0, 0); | ||
2262 | } | ||
2263 | |||
2264 | public void SendPrimitiveToClient( | ||
2265 | ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, | ||
2266 | LLVector3 pos, LLVector3 velocity, LLVector3 acceleration, LLQuaternion rotation, LLVector3 rotational_velocity, | ||
2267 | uint flags, | ||
2268 | LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, | ||
2269 | byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius) | ||
2270 | { | ||
2271 | |||
2272 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) | ||
2273 | rotation = LLQuaternion.Identity; | ||
2274 | |||
2275 | ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); | ||
2276 | |||
2277 | |||
2278 | |||
2279 | // TODO: don't create new blocks if recycling an old packet | ||
2280 | outPacket.RegionData.RegionHandle = regionHandle; | ||
2281 | outPacket.RegionData.TimeDilation = timeDilation; | ||
2282 | outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; | ||
2283 | |||
2284 | outPacket.ObjectData[0] = CreatePrimUpdateBlock(primShape, flags); | ||
2285 | |||
2286 | outPacket.ObjectData[0].ID = localID; | ||
2287 | outPacket.ObjectData[0].FullID = objectID; | ||
2288 | outPacket.ObjectData[0].OwnerID = ownerID; | ||
2289 | |||
2290 | // Anything more than 255 will cause libsecondlife to barf | ||
2291 | if (text.Length > 255) | ||
2292 | { | ||
2293 | text = text.Remove(255); | ||
2294 | } | ||
2295 | |||
2296 | outPacket.ObjectData[0].Text = Helpers.StringToField(text); | ||
2297 | |||
2298 | outPacket.ObjectData[0].TextColor[0] = color[0]; | ||
2299 | outPacket.ObjectData[0].TextColor[1] = color[1]; | ||
2300 | outPacket.ObjectData[0].TextColor[2] = color[2]; | ||
2301 | outPacket.ObjectData[0].TextColor[3] = color[3]; | ||
2302 | outPacket.ObjectData[0].ParentID = parentID; | ||
2303 | outPacket.ObjectData[0].PSBlock = particleSystem; | ||
2304 | outPacket.ObjectData[0].ClickAction = clickAction; | ||
2305 | outPacket.ObjectData[0].Flags = 0; | ||
2306 | |||
2307 | if (attachment) | ||
2308 | { | ||
2309 | // Necessary??? | ||
2310 | outPacket.ObjectData[0].JointAxisOrAnchor = new LLVector3(0, 0, 2); | ||
2311 | outPacket.ObjectData[0].JointPivot = new LLVector3(0, 0, 0); | ||
2312 | |||
2313 | // Item from inventory??? | ||
2314 | outPacket.ObjectData[0].NameValue = | ||
2315 | Helpers.StringToField("AttachItemID STRING RW SV " + AssetId.UUID); | ||
2316 | outPacket.ObjectData[0].State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); | ||
2317 | } | ||
2318 | |||
2319 | // Xantor 20080528: Send sound info as well | ||
2320 | // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again | ||
2321 | outPacket.ObjectData[0].Sound = SoundId; | ||
2322 | if (SoundId == LLUUID.Zero) | ||
2323 | { | ||
2324 | outPacket.ObjectData[0].OwnerID = LLUUID.Zero; | ||
2325 | outPacket.ObjectData[0].Gain = 0.0f; | ||
2326 | outPacket.ObjectData[0].Radius = 0.0f; | ||
2327 | outPacket.ObjectData[0].Flags = 0; | ||
2328 | } | ||
2329 | else | ||
2330 | { | ||
2331 | outPacket.ObjectData[0].OwnerID = ownerID; | ||
2332 | outPacket.ObjectData[0].Gain = (float)SoundGain; | ||
2333 | outPacket.ObjectData[0].Radius = (float)SoundRadius; | ||
2334 | outPacket.ObjectData[0].Flags = SoundFlags; | ||
2335 | } | ||
2336 | |||
2337 | byte[] pb = pos.GetBytes(); | ||
2338 | Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length); | ||
2339 | |||
2340 | byte[] vel = velocity.GetBytes(); | ||
2341 | Array.Copy(vel, 0, outPacket.ObjectData[0].ObjectData, pb.Length, vel.Length); | ||
2342 | |||
2343 | byte[] rot = rotation.GetBytes(); | ||
2344 | Array.Copy(rot, 0, outPacket.ObjectData[0].ObjectData, 36, rot.Length); | ||
2345 | |||
2346 | byte[] rvel = rotational_velocity.GetBytes(); | ||
2347 | Array.Copy(rvel, 0, outPacket.ObjectData[0].ObjectData, 36 + rot.Length, rvel.Length); | ||
2348 | |||
2349 | if (textureanim.Length > 0) | ||
2350 | { | ||
2351 | outPacket.ObjectData[0].TextureAnim = textureanim; | ||
2352 | } | ||
2353 | outPacket.Header.Zerocoded = true; | ||
2354 | |||
2355 | OutPacket(outPacket, ThrottleOutPacketType.LowpriorityTask); | ||
2356 | } | ||
2357 | |||
2358 | /// <summary> | ||
2359 | /// | ||
2360 | /// </summary> | ||
2361 | /// <param name="regionHandle"></param> | ||
2362 | /// <param name="timeDilation"></param> | ||
2363 | /// <param name="localID"></param> | ||
2364 | /// <param name="position"></param> | ||
2365 | /// <param name="rotation"></param> | ||
2366 | public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, | ||
2367 | LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity, byte state, LLUUID AssetId) | ||
2368 | { | ||
2369 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) | ||
2370 | rotation = LLQuaternion.Identity; | ||
2371 | ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
2372 | // TODO: don't create new blocks if recycling an old packet | ||
2373 | terse.RegionData.RegionHandle = regionHandle; | ||
2374 | terse.RegionData.TimeDilation = timeDilation; | ||
2375 | terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | ||
2376 | terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); // AssetID should fall into here probably somehow... | ||
2377 | terse.Header.Reliable = false; | ||
2378 | terse.Header.Zerocoded = true; | ||
2379 | OutPacket(terse, ThrottleOutPacketType.LowpriorityTask); | ||
2380 | } | ||
2381 | |||
2382 | public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, | ||
2383 | LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity) | ||
2384 | { | ||
2385 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) | ||
2386 | rotation = LLQuaternion.Identity; | ||
2387 | ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
2388 | // TODO: don't create new blocks if recycling an old packet | ||
2389 | terse.RegionData.RegionHandle = regionHandle; | ||
2390 | terse.RegionData.TimeDilation = timeDilation; | ||
2391 | terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | ||
2392 | terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, 0); | ||
2393 | terse.Header.Reliable = false; | ||
2394 | terse.Header.Zerocoded = true; | ||
2395 | OutPacket(terse, ThrottleOutPacketType.LowpriorityTask); | ||
2396 | } | ||
2397 | |||
2398 | public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, LLUUID AssetFullID) | ||
2399 | { | ||
2400 | AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); | ||
2401 | newPack.AssetBlock.Type = AssetType; | ||
2402 | newPack.AssetBlock.Success = Success; | ||
2403 | newPack.AssetBlock.UUID = AssetFullID; | ||
2404 | newPack.Header.Zerocoded = true; | ||
2405 | OutPacket(newPack, ThrottleOutPacketType.Asset); | ||
2406 | } | ||
2407 | |||
2408 | public void SendXferRequest(ulong XferID, short AssetType, LLUUID vFileID, byte FilePath, byte[] FileName) | ||
2409 | { | ||
2410 | RequestXferPacket newPack = new RequestXferPacket(); | ||
2411 | newPack.XferID.ID = XferID; | ||
2412 | newPack.XferID.VFileType = AssetType; | ||
2413 | newPack.XferID.VFileID = vFileID; | ||
2414 | newPack.XferID.FilePath = FilePath; | ||
2415 | newPack.XferID.Filename = FileName; | ||
2416 | newPack.Header.Zerocoded = true; | ||
2417 | OutPacket(newPack, ThrottleOutPacketType.Asset); | ||
2418 | } | ||
2419 | |||
2420 | public void SendConfirmXfer(ulong xferID, uint PacketID) | ||
2421 | { | ||
2422 | ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); | ||
2423 | newPack.XferID.ID = xferID; | ||
2424 | newPack.XferID.Packet = PacketID; | ||
2425 | newPack.Header.Zerocoded = true; | ||
2426 | OutPacket(newPack, ThrottleOutPacketType.Asset); | ||
2427 | } | ||
2428 | |||
2429 | public void SendImagePart(ushort numParts, LLUUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) | ||
2430 | { | ||
2431 | ImageDataPacket im = new ImageDataPacket(); | ||
2432 | im.Header.Reliable = false; | ||
2433 | im.ImageID.Packets = numParts; | ||
2434 | im.ImageID.ID = ImageUUID; | ||
2435 | |||
2436 | if (ImageSize > 0) | ||
2437 | im.ImageID.Size = ImageSize; | ||
2438 | |||
2439 | im.ImageData.Data = ImageData; | ||
2440 | im.ImageID.Codec = imageCodec; | ||
2441 | im.Header.Zerocoded = true; | ||
2442 | OutPacket(im, ThrottleOutPacketType.Texture); | ||
2443 | } | ||
2444 | |||
2445 | public void SendShutdownConnectionNotice() | ||
2446 | { | ||
2447 | OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); | ||
2448 | } | ||
2449 | |||
2450 | public void SendSimStats(Packet pack) | ||
2451 | { | ||
2452 | pack.Header.Reliable = false; | ||
2453 | OutPacket(pack, ThrottleOutPacketType.Task); | ||
2454 | } | ||
2455 | |||
2456 | public void SendObjectPropertiesFamilyData(uint RequestFlags, LLUUID ObjectUUID, LLUUID OwnerID, LLUUID GroupID, | ||
2457 | uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, | ||
2458 | uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, | ||
2459 | LLUUID LastOwnerID, string ObjectName, string Description) | ||
2460 | { | ||
2461 | ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); | ||
2462 | // TODO: don't create new blocks if recycling an old packet | ||
2463 | |||
2464 | ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); | ||
2465 | objPropDB.RequestFlags = RequestFlags; | ||
2466 | objPropDB.ObjectID = ObjectUUID; | ||
2467 | objPropDB.OwnerID = OwnerID; | ||
2468 | objPropDB.GroupID = GroupID; | ||
2469 | objPropDB.BaseMask = BaseMask; | ||
2470 | objPropDB.OwnerMask = OwnerMask; | ||
2471 | objPropDB.GroupMask = GroupMask; | ||
2472 | objPropDB.EveryoneMask = EveryoneMask; | ||
2473 | objPropDB.NextOwnerMask = NextOwnerMask; | ||
2474 | |||
2475 | // TODO: More properties are needed in SceneObjectPart! | ||
2476 | objPropDB.OwnershipCost = OwnershipCost; | ||
2477 | objPropDB.SaleType = SaleType; | ||
2478 | objPropDB.SalePrice = SalePrice; | ||
2479 | objPropDB.Category = Category; | ||
2480 | objPropDB.LastOwnerID = LastOwnerID; | ||
2481 | objPropDB.Name = Helpers.StringToField(ObjectName); | ||
2482 | objPropDB.Description = Helpers.StringToField(Description); | ||
2483 | objPropFamilyPack.ObjectData = objPropDB; | ||
2484 | objPropFamilyPack.Header.Zerocoded = true; | ||
2485 | OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); | ||
2486 | } | ||
2487 | |||
2488 | public void SendObjectPropertiesReply(LLUUID ItemID, ulong CreationDate, LLUUID CreatorUUID, LLUUID FolderUUID, LLUUID FromTaskUUID, | ||
2489 | LLUUID GroupUUID, short InventorySerial, LLUUID LastOwnerUUID, LLUUID ObjectUUID, | ||
2490 | LLUUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, | ||
2491 | string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, | ||
2492 | uint BaseMask) | ||
2493 | { | ||
2494 | ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | ||
2495 | // TODO: don't create new blocks if recycling an old packet | ||
2496 | |||
2497 | proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; | ||
2498 | proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); | ||
2499 | proper.ObjectData[0].ItemID = ItemID; | ||
2500 | proper.ObjectData[0].CreationDate = CreationDate; | ||
2501 | proper.ObjectData[0].CreatorID = CreatorUUID; | ||
2502 | proper.ObjectData[0].FolderID = FolderUUID; | ||
2503 | proper.ObjectData[0].FromTaskID = FromTaskUUID; | ||
2504 | proper.ObjectData[0].GroupID = GroupUUID; | ||
2505 | proper.ObjectData[0].InventorySerial = InventorySerial; | ||
2506 | |||
2507 | proper.ObjectData[0].LastOwnerID = LastOwnerUUID; | ||
2508 | // proper.ObjectData[0].LastOwnerID = LLUUID.Zero; | ||
2509 | |||
2510 | proper.ObjectData[0].ObjectID = ObjectUUID; | ||
2511 | proper.ObjectData[0].OwnerID = OwnerUUID; | ||
2512 | proper.ObjectData[0].TouchName = Helpers.StringToField(TouchTitle); | ||
2513 | proper.ObjectData[0].TextureID = TextureID; | ||
2514 | proper.ObjectData[0].SitName = Helpers.StringToField(SitTitle); | ||
2515 | proper.ObjectData[0].Name = Helpers.StringToField(ItemName); | ||
2516 | proper.ObjectData[0].Description = Helpers.StringToField(ItemDescription); | ||
2517 | proper.ObjectData[0].OwnerMask = OwnerMask; | ||
2518 | proper.ObjectData[0].NextOwnerMask = NextOwnerMask; | ||
2519 | proper.ObjectData[0].GroupMask = GroupMask; | ||
2520 | proper.ObjectData[0].EveryoneMask = EveryoneMask; | ||
2521 | proper.ObjectData[0].BaseMask = BaseMask; | ||
2522 | // proper.ObjectData[0].AggregatePerms = 53; | ||
2523 | // proper.ObjectData[0].AggregatePermTextures = 0; | ||
2524 | // proper.ObjectData[0].AggregatePermTexturesOwner = 0; | ||
2525 | proper.Header.Zerocoded = true; | ||
2526 | OutPacket(proper, ThrottleOutPacketType.Task); | ||
2527 | } | ||
2528 | |||
2529 | #endregion | ||
2530 | |||
2531 | #region Estate Data Sending Methods | ||
2532 | |||
2533 | private bool convertParamStringToBool(byte[] field) | ||
2534 | { | ||
2535 | string s = Helpers.FieldToUTF8String(field); | ||
2536 | if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true") | ||
2537 | { | ||
2538 | return true; | ||
2539 | } | ||
2540 | return false; | ||
2541 | } | ||
2542 | |||
2543 | public void SendEstateManagersList(LLUUID invoice, LLUUID[] EstateManagers, uint estateID) | ||
2544 | { | ||
2545 | EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); | ||
2546 | packet.AgentData.TransactionID = LLUUID.Random(); | ||
2547 | packet.AgentData.AgentID = this.AgentId; | ||
2548 | packet.AgentData.SessionID = this.SessionId; | ||
2549 | packet.MethodData.Invoice = invoice; | ||
2550 | packet.MethodData.Method = Helpers.StringToField("setaccess"); | ||
2551 | |||
2552 | EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + EstateManagers.Length]; | ||
2553 | |||
2554 | for (int i = 0; i < (6 + EstateManagers.Length); i++) | ||
2555 | { | ||
2556 | returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); | ||
2557 | } | ||
2558 | int j = 0; | ||
2559 | |||
2560 | returnblock[j].Parameter = Helpers.StringToField(estateID.ToString()); j++; | ||
2561 | returnblock[j].Parameter = Helpers.StringToField(((int)Constants.EstateAccessCodex.EstateManagers).ToString()); j++; | ||
2562 | returnblock[j].Parameter = Helpers.StringToField("0"); j++; | ||
2563 | returnblock[j].Parameter = Helpers.StringToField("0"); j++; | ||
2564 | returnblock[j].Parameter = Helpers.StringToField("0"); j++; | ||
2565 | returnblock[j].Parameter = Helpers.StringToField(EstateManagers.Length.ToString()); j++; | ||
2566 | for (int i = 0; i < EstateManagers.Length; i++) | ||
2567 | { | ||
2568 | returnblock[j].Parameter = EstateManagers[i].GetBytes(); j++; | ||
2569 | } | ||
2570 | packet.ParamList = returnblock; | ||
2571 | packet.Header.Reliable = false; | ||
2572 | this.OutPacket(packet, ThrottleOutPacketType.Task); | ||
2573 | } | ||
2574 | |||
2575 | public void SendBannedUserList(LLUUID invoice, EstateBan[] bl, uint estateID) | ||
2576 | { | ||
2577 | List<LLUUID>BannedUsers = new List<LLUUID>(); | ||
2578 | |||
2579 | for (int i = 0; i < bl.Length; i++) | ||
2580 | { | ||
2581 | if (bl[i] == null) | ||
2582 | continue; | ||
2583 | if (bl[i].bannedUUID == LLUUID.Zero) | ||
2584 | continue; | ||
2585 | BannedUsers.Add(bl[i].bannedUUID); | ||
2586 | } | ||
2587 | |||
2588 | EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); | ||
2589 | packet.AgentData.TransactionID = LLUUID.Random(); | ||
2590 | packet.AgentData.AgentID = this.AgentId; | ||
2591 | packet.AgentData.SessionID = this.SessionId; | ||
2592 | packet.MethodData.Invoice = invoice; | ||
2593 | packet.MethodData.Method = Helpers.StringToField("setaccess"); | ||
2594 | |||
2595 | EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; | ||
2596 | |||
2597 | for (int i = 0; i < (6 + BannedUsers.Count); i++) | ||
2598 | { | ||
2599 | returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); | ||
2600 | } | ||
2601 | int j = 0; | ||
2602 | |||
2603 | returnblock[j].Parameter = Helpers.StringToField(estateID.ToString()); j++; | ||
2604 | returnblock[j].Parameter = Helpers.StringToField(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; | ||
2605 | returnblock[j].Parameter = Helpers.StringToField("0"); j++; | ||
2606 | returnblock[j].Parameter = Helpers.StringToField("0"); j++; | ||
2607 | returnblock[j].Parameter = Helpers.StringToField(BannedUsers.Count.ToString()); j++; | ||
2608 | returnblock[j].Parameter = Helpers.StringToField("0"); j++; | ||
2609 | |||
2610 | foreach (LLUUID banned in BannedUsers) | ||
2611 | { | ||
2612 | returnblock[j].Parameter = banned.GetBytes(); j++; | ||
2613 | } | ||
2614 | packet.ParamList = returnblock; | ||
2615 | packet.Header.Reliable = false; | ||
2616 | this.OutPacket(packet, ThrottleOutPacketType.Task); | ||
2617 | } | ||
2618 | |||
2619 | public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) | ||
2620 | { | ||
2621 | RegionInfoPacket rinfopack = new RegionInfoPacket(); | ||
2622 | RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock(); | ||
2623 | rinfopack.AgentData.AgentID = this.AgentId; | ||
2624 | rinfopack.AgentData.SessionID = this.SessionId; | ||
2625 | rinfoblk.BillableFactor = args.billableFactor; | ||
2626 | rinfoblk.EstateID = args.estateID; | ||
2627 | rinfoblk.MaxAgents = args.maxAgents; | ||
2628 | rinfoblk.ObjectBonusFactor = args.objectBonusFactor; | ||
2629 | rinfoblk.ParentEstateID = args.parentEstateID; | ||
2630 | rinfoblk.PricePerMeter = args.pricePerMeter; | ||
2631 | rinfoblk.RedirectGridX = args.redirectGridX; | ||
2632 | rinfoblk.RedirectGridY = args.redirectGridY; | ||
2633 | rinfoblk.RegionFlags = args.regionFlags; | ||
2634 | rinfoblk.SimAccess = args.simAccess; | ||
2635 | rinfoblk.SunHour = args.sunHour; | ||
2636 | rinfoblk.TerrainLowerLimit = args.terrainLowerLimit; | ||
2637 | rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit; | ||
2638 | rinfoblk.UseEstateSun = args.useEstateSun; | ||
2639 | rinfoblk.WaterHeight = args.waterHeight; | ||
2640 | rinfoblk.SimName = Helpers.StringToField(args.simName); | ||
2641 | |||
2642 | rinfopack.RegionInfo = rinfoblk; | ||
2643 | |||
2644 | this.OutPacket(rinfopack, ThrottleOutPacketType.Task); | ||
2645 | } | ||
2646 | |||
2647 | public void SendEstateCovenantInformation(LLUUID covenant) | ||
2648 | { | ||
2649 | EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); | ||
2650 | EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); | ||
2651 | edata.CovenantID = covenant; | ||
2652 | edata.CovenantTimestamp = 0; | ||
2653 | edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; | ||
2654 | edata.EstateName = | ||
2655 | Helpers.StringToField(m_scene.RegionInfo.MasterAvatarFirstName + " " + m_scene.RegionInfo.MasterAvatarLastName); | ||
2656 | einfopack.Data = edata; | ||
2657 | this.OutPacket(einfopack, ThrottleOutPacketType.Task); | ||
2658 | } | ||
2659 | |||
2660 | public void SendDetailedEstateData(LLUUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, LLUUID covenant, string abuseEmail) | ||
2661 | { | ||
2662 | EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); | ||
2663 | packet.MethodData.Invoice = invoice; | ||
2664 | packet.AgentData.TransactionID = LLUUID.Random(); | ||
2665 | packet.MethodData.Method = Helpers.StringToField("estateupdateinfo"); | ||
2666 | EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10]; | ||
2667 | |||
2668 | for (int i = 0; i < 10; i++) | ||
2669 | { | ||
2670 | returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); | ||
2671 | } | ||
2672 | |||
2673 | //Sending Estate Settings | ||
2674 | returnblock[0].Parameter = Helpers.StringToField(estateName); | ||
2675 | returnblock[1].Parameter = Helpers.StringToField(m_scene.RegionInfo.MasterAvatarAssignedUUID.ToString()); | ||
2676 | returnblock[2].Parameter = Helpers.StringToField(estateID.ToString()); | ||
2677 | |||
2678 | returnblock[3].Parameter = Helpers.StringToField(estateFlags.ToString()); | ||
2679 | returnblock[4].Parameter = Helpers.StringToField(sunPosition.ToString()); | ||
2680 | returnblock[5].Parameter = Helpers.StringToField(parentEstate.ToString()); | ||
2681 | returnblock[6].Parameter = Helpers.StringToField(covenant.ToString()); | ||
2682 | returnblock[7].Parameter = Helpers.StringToField("1160895077"); // what is this? | ||
2683 | returnblock[8].Parameter = Helpers.StringToField("1"); // what is this? | ||
2684 | returnblock[9].Parameter = Helpers.StringToField(abuseEmail); | ||
2685 | |||
2686 | packet.ParamList = returnblock; | ||
2687 | packet.Header.Reliable = false; | ||
2688 | //System.Console.WriteLine("[ESTATE]: SIM--->" + packet.ToString()); | ||
2689 | this.OutPacket(packet, ThrottleOutPacketType.Task); | ||
2690 | } | ||
2691 | |||
2692 | #endregion | ||
2693 | |||
2694 | #region Land Data Sending Methods | ||
2695 | |||
2696 | public void SendLandParcelOverlay(byte[] data, int sequence_id) | ||
2697 | { | ||
2698 | |||
2699 | ParcelOverlayPacket packet; | ||
2700 | packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay); | ||
2701 | packet.ParcelData.Data = data; | ||
2702 | packet.ParcelData.SequenceID = sequence_id; | ||
2703 | packet.Header.Zerocoded = true; | ||
2704 | this.OutPacket(packet, ThrottleOutPacketType.Task); | ||
2705 | } | ||
2706 | |||
2707 | public void SendLandProperties(IClientAPI remote_client, int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) | ||
2708 | { | ||
2709 | ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ParcelProperties); | ||
2710 | // TODO: don't create new blocks if recycling an old packet | ||
2711 | |||
2712 | updatePacket.ParcelData.AABBMax = landData.AABBMax; | ||
2713 | updatePacket.ParcelData.AABBMin = landData.AABBMin; | ||
2714 | updatePacket.ParcelData.Area = landData.Area; | ||
2715 | updatePacket.ParcelData.AuctionID = landData.AuctionID; | ||
2716 | updatePacket.ParcelData.AuthBuyerID = landData.AuthBuyerID; //unemplemented | ||
2717 | |||
2718 | updatePacket.ParcelData.Bitmap = landData.Bitmap; | ||
2719 | |||
2720 | updatePacket.ParcelData.Desc = Helpers.StringToField(landData.Description); | ||
2721 | updatePacket.ParcelData.Category = (byte)landData.Category; | ||
2722 | updatePacket.ParcelData.ClaimDate = landData.ClaimDate; | ||
2723 | updatePacket.ParcelData.ClaimPrice = landData.ClaimPrice; | ||
2724 | updatePacket.ParcelData.GroupID = landData.GroupID; | ||
2725 | updatePacket.ParcelData.GroupPrims = landData.GroupPrims; | ||
2726 | updatePacket.ParcelData.IsGroupOwned = landData.IsGroupOwned; | ||
2727 | updatePacket.ParcelData.LandingType = (byte)landData.LandingType; | ||
2728 | updatePacket.ParcelData.LocalID = landData.LocalID; | ||
2729 | if (landData.Area > 0) | ||
2730 | { | ||
2731 | updatePacket.ParcelData.MaxPrims = parcelObjectCapacity; | ||
2732 | } | ||
2733 | else | ||
2734 | { | ||
2735 | updatePacket.ParcelData.MaxPrims = 0; | ||
2736 | } | ||
2737 | updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale; | ||
2738 | updatePacket.ParcelData.MediaID = landData.MediaID; | ||
2739 | updatePacket.ParcelData.MediaURL = Helpers.StringToField(landData.MediaURL); | ||
2740 | updatePacket.ParcelData.MusicURL = Helpers.StringToField(landData.MusicURL); | ||
2741 | updatePacket.ParcelData.Name = Helpers.StringToField(landData.Name); | ||
2742 | updatePacket.ParcelData.OtherCleanTime = 0; //unemplemented | ||
2743 | updatePacket.ParcelData.OtherCount = 0; //unemplemented | ||
2744 | updatePacket.ParcelData.OtherPrims = landData.OtherPrims; | ||
2745 | updatePacket.ParcelData.OwnerID = landData.OwnerID; | ||
2746 | updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims; | ||
2747 | updatePacket.ParcelData.ParcelFlags = landData.Flags; | ||
2748 | updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor; | ||
2749 | updatePacket.ParcelData.PassHours = landData.PassHours; | ||
2750 | updatePacket.ParcelData.PassPrice = landData.PassPrice; | ||
2751 | updatePacket.ParcelData.PublicCount = 0; //unemplemented | ||
2752 | |||
2753 | updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint)Simulator.RegionFlags.DenyAnonymous) > | ||
2754 | 0); | ||
2755 | updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint)Simulator.RegionFlags.DenyIdentified) > | ||
2756 | 0); | ||
2757 | updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint)Simulator.RegionFlags.DenyTransacted) > | ||
2758 | 0); | ||
2759 | updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint)Simulator.RegionFlags.RestrictPushObject) > | ||
2760 | 0); | ||
2761 | |||
2762 | updatePacket.ParcelData.RentPrice = 0; | ||
2763 | updatePacket.ParcelData.RequestResult = request_result; | ||
2764 | updatePacket.ParcelData.SalePrice = landData.SalePrice; | ||
2765 | updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims; | ||
2766 | updatePacket.ParcelData.SelfCount = 0; //unemplemented | ||
2767 | updatePacket.ParcelData.SequenceID = sequence_id; | ||
2768 | if (landData.SimwideArea > 0) | ||
2769 | { | ||
2770 | updatePacket.ParcelData.SimWideMaxPrims = parcelObjectCapacity; | ||
2771 | } | ||
2772 | else | ||
2773 | { | ||
2774 | updatePacket.ParcelData.SimWideMaxPrims = 0; | ||
2775 | } | ||
2776 | updatePacket.ParcelData.SimWideTotalPrims = landData.SimwidePrims; | ||
2777 | updatePacket.ParcelData.SnapSelection = snap_selection; | ||
2778 | updatePacket.ParcelData.SnapshotID = landData.SnapshotID; | ||
2779 | updatePacket.ParcelData.Status = (byte)landData.Status; | ||
2780 | updatePacket.ParcelData.TotalPrims = landData.OwnerPrims + landData.GroupPrims + landData.OtherPrims + | ||
2781 | landData.SelectedPrims; | ||
2782 | updatePacket.ParcelData.UserLocation = landData.UserLocation; | ||
2783 | updatePacket.ParcelData.UserLookAt = landData.UserLookAt; | ||
2784 | updatePacket.Header.Zerocoded = true; | ||
2785 | remote_client.OutPacket((Packet)updatePacket, ThrottleOutPacketType.Task); | ||
2786 | } | ||
2787 | |||
2788 | public void SendLandAccessListData(List<LLUUID> avatars, uint accessFlag, int localLandID) | ||
2789 | { | ||
2790 | ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); | ||
2791 | replyPacket.Data.AgentID = this.AgentId; | ||
2792 | replyPacket.Data.Flags = accessFlag; | ||
2793 | replyPacket.Data.LocalID = localLandID; | ||
2794 | replyPacket.Data.SequenceID = 0; | ||
2795 | |||
2796 | List<ParcelAccessListReplyPacket.ListBlock> list = new List<ParcelAccessListReplyPacket.ListBlock>(); | ||
2797 | foreach (LLUUID avatar in avatars) | ||
2798 | { | ||
2799 | ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock(); | ||
2800 | block.Flags = accessFlag; | ||
2801 | block.ID = avatar; | ||
2802 | block.Time = 0; | ||
2803 | } | ||
2804 | |||
2805 | replyPacket.List = list.ToArray(); | ||
2806 | replyPacket.Header.Zerocoded = true; | ||
2807 | this.OutPacket((Packet)replyPacket, ThrottleOutPacketType.Task); | ||
2808 | } | ||
2809 | |||
2810 | public void SendForceClientSelectObjects(List<uint> ObjectIDs) | ||
2811 | { | ||
2812 | bool firstCall = true; | ||
2813 | int MAX_OBJECTS_PER_PACKET = 251; | ||
2814 | ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); | ||
2815 | ForceObjectSelectPacket.DataBlock[] data; | ||
2816 | while (ObjectIDs.Count > 0) | ||
2817 | { | ||
2818 | if (firstCall) | ||
2819 | { | ||
2820 | pack._Header.ResetList = true; | ||
2821 | firstCall = false; | ||
2822 | } | ||
2823 | else | ||
2824 | { | ||
2825 | pack._Header.ResetList = false; | ||
2826 | } | ||
2827 | |||
2828 | if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET) | ||
2829 | { | ||
2830 | data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET]; | ||
2831 | } | ||
2832 | else | ||
2833 | { | ||
2834 | data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count]; | ||
2835 | } | ||
2836 | |||
2837 | int i; | ||
2838 | for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++) | ||
2839 | { | ||
2840 | data[i] = new ForceObjectSelectPacket.DataBlock(); | ||
2841 | data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]); | ||
2842 | ObjectIDs.RemoveAt(0); | ||
2843 | } | ||
2844 | pack.Data = data; | ||
2845 | pack.Header.Zerocoded = true; | ||
2846 | this.OutPacket((Packet)pack, ThrottleOutPacketType.Task); | ||
2847 | } | ||
2848 | } | ||
2849 | |||
2850 | public void SendLandObjectOwners(Dictionary<LLUUID, int> ownersAndCount) | ||
2851 | { | ||
2852 | int notifyCount = ownersAndCount.Count; | ||
2853 | ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); | ||
2854 | |||
2855 | if (notifyCount > 0) | ||
2856 | { | ||
2857 | if (notifyCount > 32) | ||
2858 | { | ||
2859 | m_log.InfoFormat( | ||
2860 | "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" | ||
2861 | + " - a developer might want to investigate whether this is a hard limit", 32); | ||
2862 | |||
2863 | notifyCount = 32; | ||
2864 | } | ||
2865 | |||
2866 | ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock | ||
2867 | = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; | ||
2868 | |||
2869 | int num = 0; | ||
2870 | foreach (LLUUID owner in ownersAndCount.Keys) | ||
2871 | { | ||
2872 | dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock(); | ||
2873 | dataBlock[num].Count = ownersAndCount[owner]; | ||
2874 | dataBlock[num].IsGroupOwned = false; //TODO: fix me when group support is added | ||
2875 | dataBlock[num].OnlineStatus = true; //TODO: fix me later | ||
2876 | dataBlock[num].OwnerID = owner; | ||
2877 | |||
2878 | num++; | ||
2879 | |||
2880 | if (num >= notifyCount) | ||
2881 | { | ||
2882 | break; | ||
2883 | } | ||
2884 | } | ||
2885 | |||
2886 | pack.Data = dataBlock; | ||
2887 | } | ||
2888 | pack.Header.Zerocoded = true; | ||
2889 | this.OutPacket(pack, ThrottleOutPacketType.Task); | ||
2890 | } | ||
2891 | |||
2892 | #endregion | ||
2893 | |||
2894 | #region Helper Methods | ||
2895 | |||
2896 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, LLVector3 pos, | ||
2897 | LLVector3 velocity, | ||
2898 | LLQuaternion rotation) | ||
2899 | { | ||
2900 | byte[] bytes = new byte[60]; | ||
2901 | int i = 0; | ||
2902 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); | ||
2903 | |||
2904 | dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; | ||
2905 | |||
2906 | uint ID = localID; | ||
2907 | |||
2908 | bytes[i++] = (byte)(ID % 256); | ||
2909 | bytes[i++] = (byte)((ID >> 8) % 256); | ||
2910 | bytes[i++] = (byte)((ID >> 16) % 256); | ||
2911 | bytes[i++] = (byte)((ID >> 24) % 256); | ||
2912 | bytes[i++] = 0; | ||
2913 | bytes[i++] = 1; | ||
2914 | i += 14; | ||
2915 | bytes[i++] = 128; | ||
2916 | bytes[i++] = 63; | ||
2917 | |||
2918 | byte[] pb = pos.GetBytes(); | ||
2919 | Array.Copy(pb, 0, bytes, i, pb.Length); | ||
2920 | i += 12; | ||
2921 | ushort InternVelocityX; | ||
2922 | ushort InternVelocityY; | ||
2923 | ushort InternVelocityZ; | ||
2924 | Vector3 internDirec = new Vector3(0, 0, 0); | ||
2925 | |||
2926 | internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z); | ||
2927 | |||
2928 | internDirec = internDirec / 128.0f; | ||
2929 | internDirec.x += 1; | ||
2930 | internDirec.y += 1; | ||
2931 | internDirec.z += 1; | ||
2932 | |||
2933 | InternVelocityX = (ushort)(32768 * internDirec.x); | ||
2934 | InternVelocityY = (ushort)(32768 * internDirec.y); | ||
2935 | InternVelocityZ = (ushort)(32768 * internDirec.z); | ||
2936 | |||
2937 | ushort ac = 32767; | ||
2938 | bytes[i++] = (byte)(InternVelocityX % 256); | ||
2939 | bytes[i++] = (byte)((InternVelocityX >> 8) % 256); | ||
2940 | bytes[i++] = (byte)(InternVelocityY % 256); | ||
2941 | bytes[i++] = (byte)((InternVelocityY >> 8) % 256); | ||
2942 | bytes[i++] = (byte)(InternVelocityZ % 256); | ||
2943 | bytes[i++] = (byte)((InternVelocityZ >> 8) % 256); | ||
2944 | |||
2945 | //accel | ||
2946 | bytes[i++] = (byte)(ac % 256); | ||
2947 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
2948 | bytes[i++] = (byte)(ac % 256); | ||
2949 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
2950 | bytes[i++] = (byte)(ac % 256); | ||
2951 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
2952 | |||
2953 | //rotation | ||
2954 | ushort rw, rx, ry, rz; | ||
2955 | rw = (ushort)(32768 * (rotation.W + 1)); | ||
2956 | rx = (ushort)(32768 * (rotation.X + 1)); | ||
2957 | ry = (ushort)(32768 * (rotation.Y + 1)); | ||
2958 | rz = (ushort)(32768 * (rotation.Z + 1)); | ||
2959 | |||
2960 | //rot | ||
2961 | bytes[i++] = (byte)(rx % 256); | ||
2962 | bytes[i++] = (byte)((rx >> 8) % 256); | ||
2963 | bytes[i++] = (byte)(ry % 256); | ||
2964 | bytes[i++] = (byte)((ry >> 8) % 256); | ||
2965 | bytes[i++] = (byte)(rz % 256); | ||
2966 | bytes[i++] = (byte)((rz >> 8) % 256); | ||
2967 | bytes[i++] = (byte)(rw % 256); | ||
2968 | bytes[i++] = (byte)((rw >> 8) % 256); | ||
2969 | |||
2970 | //rotation vel | ||
2971 | bytes[i++] = (byte)(ac % 256); | ||
2972 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
2973 | bytes[i++] = (byte)(ac % 256); | ||
2974 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
2975 | bytes[i++] = (byte)(ac % 256); | ||
2976 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
2977 | |||
2978 | dat.Data = bytes; | ||
2979 | |||
2980 | return (dat); | ||
2981 | } | ||
2982 | |||
2983 | /// <summary> | ||
2984 | /// | ||
2985 | /// </summary> | ||
2986 | /// <param name="localID"></param> | ||
2987 | /// <param name="position"></param> | ||
2988 | /// <param name="rotation"></param> | ||
2989 | /// <returns></returns> | ||
2990 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, | ||
2991 | LLVector3 position, | ||
2992 | LLQuaternion rotation, | ||
2993 | LLVector3 velocity, | ||
2994 | LLVector3 rotationalvelocity, | ||
2995 | byte state) | ||
2996 | { | ||
2997 | uint ID = localID; | ||
2998 | byte[] bytes = new byte[60]; | ||
2999 | |||
3000 | int i = 0; | ||
3001 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); | ||
3002 | dat.TextureEntry = new byte[0]; | ||
3003 | bytes[i++] = (byte)(ID % 256); | ||
3004 | bytes[i++] = (byte)((ID >> 8) % 256); | ||
3005 | bytes[i++] = (byte)((ID >> 16) % 256); | ||
3006 | bytes[i++] = (byte)((ID >> 24) % 256); | ||
3007 | bytes[i++] = state; | ||
3008 | bytes[i++] = 0; | ||
3009 | |||
3010 | byte[] pb = position.GetBytes(); | ||
3011 | Array.Copy(pb, 0, bytes, i, pb.Length); | ||
3012 | i += 12; | ||
3013 | ushort ac = 32767; | ||
3014 | |||
3015 | ushort velx, vely, velz; | ||
3016 | Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z); | ||
3017 | |||
3018 | vel = vel / 128.0f; | ||
3019 | vel.x += 1; | ||
3020 | vel.y += 1; | ||
3021 | vel.z += 1; | ||
3022 | //vel | ||
3023 | velx = (ushort)(32768 * (vel.x)); | ||
3024 | vely = (ushort)(32768 * (vel.y)); | ||
3025 | velz = (ushort)(32768 * (vel.z)); | ||
3026 | |||
3027 | bytes[i++] = (byte)(velx % 256); | ||
3028 | bytes[i++] = (byte)((velx >> 8) % 256); | ||
3029 | bytes[i++] = (byte)(vely % 256); | ||
3030 | bytes[i++] = (byte)((vely >> 8) % 256); | ||
3031 | bytes[i++] = (byte)(velz % 256); | ||
3032 | bytes[i++] = (byte)((velz >> 8) % 256); | ||
3033 | |||
3034 | //accel | ||
3035 | bytes[i++] = (byte)(ac % 256); | ||
3036 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
3037 | bytes[i++] = (byte)(ac % 256); | ||
3038 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
3039 | bytes[i++] = (byte)(ac % 256); | ||
3040 | bytes[i++] = (byte)((ac >> 8) % 256); | ||
3041 | |||
3042 | ushort rw, rx, ry, rz; | ||
3043 | rw = (ushort)(32768 * (rotation.W + 1)); | ||
3044 | rx = (ushort)(32768 * (rotation.X + 1)); | ||
3045 | ry = (ushort)(32768 * (rotation.Y + 1)); | ||
3046 | rz = (ushort)(32768 * (rotation.Z + 1)); | ||
3047 | |||
3048 | //rot | ||
3049 | bytes[i++] = (byte)(rx % 256); | ||
3050 | bytes[i++] = (byte)((rx >> 8) % 256); | ||
3051 | bytes[i++] = (byte)(ry % 256); | ||
3052 | bytes[i++] = (byte)((ry >> 8) % 256); | ||
3053 | bytes[i++] = (byte)(rz % 256); | ||
3054 | bytes[i++] = (byte)((rz >> 8) % 256); | ||
3055 | bytes[i++] = (byte)(rw % 256); | ||
3056 | bytes[i++] = (byte)((rw >> 8) % 256); | ||
3057 | |||
3058 | //rotation vel | ||
3059 | ushort rvelx, rvely, rvelz; | ||
3060 | Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z); | ||
3061 | |||
3062 | rvel = rvel / 128.0f; | ||
3063 | rvel.x += 1; | ||
3064 | rvel.y += 1; | ||
3065 | rvel.z += 1; | ||
3066 | //vel | ||
3067 | rvelx = (ushort)(32768 * (rvel.x)); | ||
3068 | rvely = (ushort)(32768 * (rvel.y)); | ||
3069 | rvelz = (ushort)(32768 * (rvel.z)); | ||
3070 | |||
3071 | bytes[i++] = (byte)(rvelx % 256); | ||
3072 | bytes[i++] = (byte)((rvelx >> 8) % 256); | ||
3073 | bytes[i++] = (byte)(rvely % 256); | ||
3074 | bytes[i++] = (byte)((rvely >> 8) % 256); | ||
3075 | bytes[i++] = (byte)(rvelz % 256); | ||
3076 | bytes[i++] = (byte)((rvelz >> 8) % 256); | ||
3077 | dat.Data = bytes; | ||
3078 | |||
3079 | return dat; | ||
3080 | } | ||
3081 | |||
3082 | /// <summary> | ||
3083 | /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) | ||
3084 | /// </summary> | ||
3085 | /// <param name="primData"></param> | ||
3086 | /// <returns></returns> | ||
3087 | protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) | ||
3088 | { | ||
3089 | ObjectUpdatePacket.ObjectDataBlock objupdate = new ObjectUpdatePacket.ObjectDataBlock(); | ||
3090 | SetDefaultPrimPacketValues(objupdate); | ||
3091 | objupdate.UpdateFlags = flags; | ||
3092 | SetPrimPacketShapeData(objupdate, primShape); | ||
3093 | |||
3094 | if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass)) | ||
3095 | { | ||
3096 | objupdate.Data = new byte[1]; | ||
3097 | objupdate.Data[0] = primShape.State; | ||
3098 | } | ||
3099 | return objupdate; | ||
3100 | } | ||
3101 | |||
3102 | protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData) | ||
3103 | { | ||
3104 | objectData.TextureEntry = primData.TextureEntry; | ||
3105 | objectData.PCode = primData.PCode; | ||
3106 | objectData.State = primData.State; | ||
3107 | objectData.PathBegin = primData.PathBegin; | ||
3108 | objectData.PathEnd = primData.PathEnd; | ||
3109 | objectData.PathScaleX = primData.PathScaleX; | ||
3110 | objectData.PathScaleY = primData.PathScaleY; | ||
3111 | objectData.PathShearX = primData.PathShearX; | ||
3112 | objectData.PathShearY = primData.PathShearY; | ||
3113 | objectData.PathSkew = primData.PathSkew; | ||
3114 | objectData.ProfileBegin = primData.ProfileBegin; | ||
3115 | objectData.ProfileEnd = primData.ProfileEnd; | ||
3116 | objectData.Scale = primData.Scale; | ||
3117 | objectData.PathCurve = primData.PathCurve; | ||
3118 | objectData.ProfileCurve = primData.ProfileCurve; | ||
3119 | objectData.ProfileHollow = primData.ProfileHollow; | ||
3120 | objectData.PathRadiusOffset = primData.PathRadiusOffset; | ||
3121 | objectData.PathRevolutions = primData.PathRevolutions; | ||
3122 | objectData.PathTaperX = primData.PathTaperX; | ||
3123 | objectData.PathTaperY = primData.PathTaperY; | ||
3124 | objectData.PathTwist = primData.PathTwist; | ||
3125 | objectData.PathTwistBegin = primData.PathTwistBegin; | ||
3126 | objectData.ExtraParams = primData.ExtraParams; | ||
3127 | } | ||
3128 | |||
3129 | /// <summary> | ||
3130 | /// Set some default values in a ObjectUpdatePacket | ||
3131 | /// </summary> | ||
3132 | /// <param name="objdata"></param> | ||
3133 | protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) | ||
3134 | { | ||
3135 | objdata.PSBlock = new byte[0]; | ||
3136 | objdata.ExtraParams = new byte[1]; | ||
3137 | objdata.MediaURL = new byte[0]; | ||
3138 | objdata.NameValue = new byte[0]; | ||
3139 | objdata.Text = new byte[0]; | ||
3140 | objdata.TextColor = new byte[4]; | ||
3141 | objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0); | ||
3142 | objdata.JointPivot = new LLVector3(0, 0, 0); | ||
3143 | objdata.Material = 3; | ||
3144 | objdata.TextureAnim = new byte[0]; | ||
3145 | objdata.Sound = LLUUID.Zero; | ||
3146 | objdata.State = 0; | ||
3147 | objdata.Data = new byte[0]; | ||
3148 | |||
3149 | objdata.ObjectData = new byte[60]; | ||
3150 | objdata.ObjectData[46] = 128; | ||
3151 | objdata.ObjectData[47] = 63; | ||
3152 | } | ||
3153 | |||
3154 | /// <summary> | ||
3155 | /// | ||
3156 | /// </summary> | ||
3157 | /// <returns></returns> | ||
3158 | public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) | ||
3159 | { | ||
3160 | ObjectUpdatePacket.ObjectDataBlock objdata = new ObjectUpdatePacket.ObjectDataBlock(); | ||
3161 | // new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); | ||
3162 | |||
3163 | SetDefaultAvatarPacketValues(ref objdata); | ||
3164 | objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); | ||
3165 | objdata.PathCurve = 16; | ||
3166 | objdata.ProfileCurve = 1; | ||
3167 | objdata.PathScaleX = 100; | ||
3168 | objdata.PathScaleY = 100; | ||
3169 | objdata.ParentID = 0; | ||
3170 | objdata.OwnerID = LLUUID.Zero; | ||
3171 | objdata.Scale = new LLVector3(1, 1, 1); | ||
3172 | objdata.PCode = (byte)PCode.Avatar; | ||
3173 | if (textureEntry != null) | ||
3174 | { | ||
3175 | objdata.TextureEntry = textureEntry; | ||
3176 | } | ||
3177 | LLVector3 pos = new LLVector3(objdata.ObjectData, 16); | ||
3178 | pos.X = 100f; | ||
3179 | objdata.ID = 8880000; | ||
3180 | objdata.NameValue = Helpers.StringToField("FirstName STRING RW SV Test \nLastName STRING RW SV User "); | ||
3181 | //LLVector3 pos2 = new LLVector3(100f, 100f, 23f); | ||
3182 | //objdata.FullID=user.AgentId; | ||
3183 | byte[] pb = pos.GetBytes(); | ||
3184 | Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); | ||
3185 | |||
3186 | return objdata; | ||
3187 | } | ||
3188 | |||
3189 | /// <summary> | ||
3190 | /// | ||
3191 | /// </summary> | ||
3192 | /// <param name="objdata"></param> | ||
3193 | protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) | ||
3194 | { | ||
3195 | objdata.PSBlock = new byte[0]; | ||
3196 | objdata.ExtraParams = new byte[1]; | ||
3197 | objdata.MediaURL = new byte[0]; | ||
3198 | objdata.NameValue = new byte[0]; | ||
3199 | objdata.Text = new byte[0]; | ||
3200 | objdata.TextColor = new byte[4]; | ||
3201 | objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0); | ||
3202 | objdata.JointPivot = new LLVector3(0, 0, 0); | ||
3203 | objdata.Material = 4; | ||
3204 | objdata.TextureAnim = new byte[0]; | ||
3205 | objdata.Sound = LLUUID.Zero; | ||
3206 | LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("00000000-0000-0000-5005-000000000005")); | ||
3207 | objdata.TextureEntry = ntex.ToBytes(); | ||
3208 | |||
3209 | objdata.State = 0; | ||
3210 | objdata.Data = new byte[0]; | ||
3211 | |||
3212 | objdata.ObjectData = new byte[76]; | ||
3213 | objdata.ObjectData[15] = 128; | ||
3214 | objdata.ObjectData[16] = 63; | ||
3215 | objdata.ObjectData[56] = 128; | ||
3216 | objdata.ObjectData[61] = 102; | ||
3217 | objdata.ObjectData[62] = 40; | ||
3218 | objdata.ObjectData[63] = 61; | ||
3219 | objdata.ObjectData[64] = 189; | ||
3220 | } | ||
3221 | |||
3222 | public void SendNameReply(LLUUID profileId, string firstname, string lastname) | ||
3223 | { | ||
3224 | UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); | ||
3225 | // TODO: don't create new blocks if recycling an old packet | ||
3226 | packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; | ||
3227 | packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); | ||
3228 | packet.UUIDNameBlock[0].ID = profileId; | ||
3229 | packet.UUIDNameBlock[0].FirstName = Helpers.StringToField(firstname); | ||
3230 | packet.UUIDNameBlock[0].LastName = Helpers.StringToField(lastname); | ||
3231 | |||
3232 | OutPacket(packet, ThrottleOutPacketType.Task); | ||
3233 | } | ||
3234 | |||
3235 | #endregion | ||
3236 | |||
3237 | /// <summary> | ||
3238 | /// This is a different way of processing packets then ProcessInPacket | ||
3239 | /// </summary> | ||
3240 | protected virtual void RegisterLocalPacketHandlers() | ||
3241 | { | ||
3242 | AddLocalPacketHandler(PacketType.LogoutRequest, Logout); | ||
3243 | AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); | ||
3244 | AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); | ||
3245 | AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); | ||
3246 | AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest); | ||
3247 | AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest); | ||
3248 | AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); | ||
3249 | AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); | ||
3250 | } | ||
3251 | |||
3252 | private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) | ||
3253 | { | ||
3254 | MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack; | ||
3255 | // validate the agent owns the agentID and sessionID | ||
3256 | if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && money.AgentData.SessionID == sender.SessionId) | ||
3257 | { | ||
3258 | handlerMoneyTransferRequest = OnMoneyTransferRequest; | ||
3259 | if (handlerMoneyTransferRequest != null) | ||
3260 | { | ||
3261 | handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, | ||
3262 | money.MoneyData.Amount, money.MoneyData.TransactionType, | ||
3263 | Util.FieldToString(money.MoneyData.Description)); | ||
3264 | } | ||
3265 | |||
3266 | return true; | ||
3267 | } | ||
3268 | else | ||
3269 | { | ||
3270 | return false; | ||
3271 | } | ||
3272 | } | ||
3273 | |||
3274 | private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack) | ||
3275 | { | ||
3276 | ParcelBuyPacket parcel = (ParcelBuyPacket)Pack; | ||
3277 | if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == this.SessionId) | ||
3278 | { | ||
3279 | handlerParcelBuy = OnParcelBuy; | ||
3280 | if (handlerParcelBuy != null) | ||
3281 | { | ||
3282 | handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, parcel.Data.IsGroupOwned, | ||
3283 | parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area, parcel.ParcelData.Price, | ||
3284 | false); | ||
3285 | } | ||
3286 | return true; | ||
3287 | } | ||
3288 | else | ||
3289 | { | ||
3290 | return false; | ||
3291 | } | ||
3292 | } | ||
3293 | |||
3294 | private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) | ||
3295 | { | ||
3296 | UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; | ||
3297 | |||
3298 | for (int i = 0; i < upack.UUIDNameBlock.Length; i++) | ||
3299 | { | ||
3300 | handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest; | ||
3301 | if (handlerUUIDGroupNameRequest != null) | ||
3302 | { | ||
3303 | handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this); | ||
3304 | } | ||
3305 | } | ||
3306 | |||
3307 | return true; | ||
3308 | } | ||
3309 | |||
3310 | public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) | ||
3311 | { | ||
3312 | |||
3313 | ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; | ||
3314 | handlerObjectGroupRequest = OnObjectGroupRequest; | ||
3315 | if (handlerObjectGroupRequest != null) | ||
3316 | { | ||
3317 | for (int i = 0; i < ogpack.ObjectData.Length; i++) | ||
3318 | { | ||
3319 | handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, LLUUID.Zero); | ||
3320 | } | ||
3321 | } | ||
3322 | return true; | ||
3323 | } | ||
3324 | |||
3325 | private bool HandleViewerEffect(IClientAPI sender, Packet Pack) | ||
3326 | { | ||
3327 | ViewerEffectPacket viewer = (ViewerEffectPacket)Pack; | ||
3328 | handlerViewerEffect = OnViewerEffect; | ||
3329 | if (handlerViewerEffect != null) | ||
3330 | { | ||
3331 | int length = viewer.Effect.Length; | ||
3332 | List<ViewerEffectEventHandlerArg> args = new List<ViewerEffectEventHandlerArg>(length); | ||
3333 | for (int i = 0; i < length; i++) | ||
3334 | { | ||
3335 | //copy the effects block arguments into the event handler arg. | ||
3336 | ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg(); | ||
3337 | argument.AgentID = viewer.Effect[i].AgentID; | ||
3338 | argument.Color = viewer.Effect[i].Color; | ||
3339 | argument.Duration = viewer.Effect[i].Duration; | ||
3340 | argument.ID = viewer.Effect[i].ID; | ||
3341 | argument.Type = viewer.Effect[i].Type; | ||
3342 | argument.TypeData = viewer.Effect[i].TypeData; | ||
3343 | args.Add(argument); | ||
3344 | } | ||
3345 | |||
3346 | handlerViewerEffect(sender, args); | ||
3347 | } | ||
3348 | |||
3349 | return true; | ||
3350 | } | ||
3351 | |||
3352 | public void SendScriptQuestion(LLUUID taskID, string taskName, string ownerName, LLUUID itemID, int question) | ||
3353 | { | ||
3354 | ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion); | ||
3355 | scriptQuestion.Data = new ScriptQuestionPacket.DataBlock(); | ||
3356 | // TODO: don't create new blocks if recycling an old packet | ||
3357 | scriptQuestion.Data.TaskID = taskID; | ||
3358 | scriptQuestion.Data.ItemID = itemID; | ||
3359 | scriptQuestion.Data.Questions = question; | ||
3360 | scriptQuestion.Data.ObjectName = Helpers.StringToField(taskName); | ||
3361 | scriptQuestion.Data.ObjectOwner = Helpers.StringToField(ownerName); | ||
3362 | |||
3363 | OutPacket(scriptQuestion, ThrottleOutPacketType.Task); | ||
3364 | } | ||
3365 | |||
3366 | private void InitDefaultAnimations() | ||
3367 | { | ||
3368 | } | ||
3369 | |||
3370 | public LLUUID GetDefaultAnimation(string name) | ||
3371 | { | ||
3372 | if (m_defaultAnimations.ContainsKey(name)) | ||
3373 | return m_defaultAnimations[name]; | ||
3374 | return LLUUID.Zero; | ||
3375 | } | ||
3376 | |||
3377 | /// <summary> | ||
3378 | /// Handler called when we receive a logout packet. | ||
3379 | /// </summary> | ||
3380 | /// <param name="client"></param> | ||
3381 | /// <param name="packet"></param> | ||
3382 | /// <returns></returns> | ||
3383 | protected virtual bool Logout(IClientAPI client, Packet packet) | ||
3384 | { | ||
3385 | return Logout(client); | ||
3386 | } | ||
3387 | |||
3388 | /// <summary> | ||
3389 | /// | ||
3390 | /// </summary> | ||
3391 | /// <param name="client"> | ||
3392 | /// A <see cref="IClientAPI"/> | ||
3393 | /// </param> | ||
3394 | /// <returns> | ||
3395 | /// A <see cref="System.Boolean"/> | ||
3396 | /// </returns> | ||
3397 | protected virtual bool Logout(IClientAPI client) | ||
3398 | { | ||
3399 | m_log.Info("[CLIENT]: Got a logout request"); | ||
3400 | |||
3401 | handlerLogout = OnLogout; | ||
3402 | |||
3403 | if (handlerLogout != null) | ||
3404 | { | ||
3405 | handlerLogout(client); | ||
3406 | } | ||
3407 | |||
3408 | return true; | ||
3409 | } | ||
3410 | |||
3411 | /// <summary> | ||
3412 | /// Send a response back to a client when it asks the asset server (via the region server) if it has | ||
3413 | /// its appearance texture cached. | ||
3414 | /// | ||
3415 | /// At the moment, we always reply that there is no cached texture. | ||
3416 | /// </summary> | ||
3417 | /// <param name="simclient"></param> | ||
3418 | /// <param name="packet"></param> | ||
3419 | /// <returns></returns> | ||
3420 | protected bool AgentTextureCached(IClientAPI simclient, Packet packet) | ||
3421 | { | ||
3422 | //Console.WriteLine("texture cached: " + packet.ToString()); | ||
3423 | AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; | ||
3424 | AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); | ||
3425 | // TODO: don't create new blocks if recycling an old packet | ||
3426 | cachedresp.AgentData.AgentID = AgentId; | ||
3427 | cachedresp.AgentData.SessionID = m_sessionId; | ||
3428 | cachedresp.AgentData.SerialNum = m_cachedTextureSerial; | ||
3429 | m_cachedTextureSerial++; | ||
3430 | cachedresp.WearableData = | ||
3431 | new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; | ||
3432 | |||
3433 | for (int i = 0; i < cachedtex.WearableData.Length; i++) | ||
3434 | { | ||
3435 | cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); | ||
3436 | cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; | ||
3437 | cachedresp.WearableData[i].TextureID = LLUUID.Zero; | ||
3438 | cachedresp.WearableData[i].HostName = new byte[0]; | ||
3439 | } | ||
3440 | |||
3441 | // Temporarily throw these packets on to the wind queue, so we can identify whether these | ||
3442 | // are somehow the source of the packet bloat. | ||
3443 | cachedresp.Header.Zerocoded = true; | ||
3444 | OutPacket(cachedresp, ThrottleOutPacketType.Wind); | ||
3445 | return true; | ||
3446 | } | ||
3447 | |||
3448 | protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) | ||
3449 | { | ||
3450 | MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; | ||
3451 | // Console.WriteLine("new multi update packet " + multipleupdate.ToString()); | ||
3452 | Scene tScene = (Scene)m_scene; | ||
3453 | |||
3454 | for (int i = 0; i < multipleupdate.ObjectData.Length; i++) | ||
3455 | { | ||
3456 | MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i]; | ||
3457 | |||
3458 | // Can't act on Null Data | ||
3459 | if (block.Data != null) | ||
3460 | { | ||
3461 | uint localId = block.ObjectLocalID; | ||
3462 | SceneObjectPart part = tScene.GetSceneObjectPart(localId); | ||
3463 | |||
3464 | if (part == null) | ||
3465 | { | ||
3466 | // It's a ghost! tell the client to delete it from view. | ||
3467 | simClient.SendKillObject(Scene.RegionInfo.RegionHandle, | ||
3468 | localId); | ||
3469 | } | ||
3470 | else | ||
3471 | { | ||
3472 | // LLUUID partId = part.UUID; | ||
3473 | UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; | ||
3474 | UpdatePrimGroupRotation handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; | ||
3475 | |||
3476 | switch (block.Type) | ||
3477 | { | ||
3478 | case 1: | ||
3479 | LLVector3 pos1 = new LLVector3(block.Data, 0); | ||
3480 | |||
3481 | handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; | ||
3482 | if (handlerUpdatePrimSinglePosition != null) | ||
3483 | { | ||
3484 | // Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); | ||
3485 | handlerUpdatePrimSinglePosition(localId, pos1, this); | ||
3486 | } | ||
3487 | break; | ||
3488 | case 2: | ||
3489 | LLQuaternion rot1 = new LLQuaternion(block.Data, 0, true); | ||
3490 | |||
3491 | handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; | ||
3492 | if (handlerUpdatePrimSingleRotation != null) | ||
3493 | { | ||
3494 | //Console.WriteLine("new tab rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); | ||
3495 | handlerUpdatePrimSingleRotation(localId, rot1, this); | ||
3496 | } | ||
3497 | break; | ||
3498 | case 3: | ||
3499 | |||
3500 | LLQuaternion rot2 = new LLQuaternion(block.Data, 12, true); | ||
3501 | handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; | ||
3502 | if (handlerUpdatePrimSingleRotation != null) | ||
3503 | { | ||
3504 | //Console.WriteLine("new mouse rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); | ||
3505 | handlerUpdatePrimSingleRotation(localId, rot2, this); | ||
3506 | } | ||
3507 | break; | ||
3508 | case 5: | ||
3509 | |||
3510 | LLVector3 scale1 = new LLVector3(block.Data, 12); | ||
3511 | LLVector3 pos11 = new LLVector3(block.Data, 0); | ||
3512 | |||
3513 | handlerUpdatePrimScale = OnUpdatePrimScale; | ||
3514 | if (handlerUpdatePrimScale != null) | ||
3515 | { | ||
3516 | // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); | ||
3517 | handlerUpdatePrimScale(localId, scale1, this); | ||
3518 | |||
3519 | handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; | ||
3520 | if (handlerUpdatePrimSinglePosition != null) | ||
3521 | { | ||
3522 | handlerUpdatePrimSinglePosition(localId, pos11, this); | ||
3523 | } | ||
3524 | } | ||
3525 | break; | ||
3526 | case 9: | ||
3527 | LLVector3 pos2 = new LLVector3(block.Data, 0); | ||
3528 | |||
3529 | handlerUpdateVector = OnUpdatePrimGroupPosition; | ||
3530 | |||
3531 | if (handlerUpdateVector != null) | ||
3532 | { | ||
3533 | |||
3534 | handlerUpdateVector(localId, pos2, this); | ||
3535 | } | ||
3536 | break; | ||
3537 | case 10: | ||
3538 | LLQuaternion rot3 = new LLQuaternion(block.Data, 0, true); | ||
3539 | |||
3540 | handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; | ||
3541 | if (handlerUpdatePrimRotation != null) | ||
3542 | { | ||
3543 | // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); | ||
3544 | handlerUpdatePrimRotation(localId, rot3, this); | ||
3545 | } | ||
3546 | break; | ||
3547 | case 11: | ||
3548 | LLVector3 pos3 = new LLVector3(block.Data, 0); | ||
3549 | LLQuaternion rot4 = new LLQuaternion(block.Data, 12, true); | ||
3550 | |||
3551 | handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; | ||
3552 | if (handlerUpdatePrimGroupRotation != null) | ||
3553 | { | ||
3554 | //Console.WriteLine("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); | ||
3555 | // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); | ||
3556 | handlerUpdatePrimGroupRotation(localId, pos3, rot4, this); | ||
3557 | } | ||
3558 | break; | ||
3559 | case 13: | ||
3560 | LLVector3 scale2 = new LLVector3(block.Data, 12); | ||
3561 | LLVector3 pos4 = new LLVector3(block.Data, 0); | ||
3562 | |||
3563 | handlerUpdatePrimScale = OnUpdatePrimScale; | ||
3564 | if (handlerUpdatePrimScale != null) | ||
3565 | { | ||
3566 | //Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); | ||
3567 | handlerUpdatePrimScale(localId, scale2, this); | ||
3568 | |||
3569 | // Change the position based on scale (for bug number 246) | ||
3570 | handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; | ||
3571 | // Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); | ||
3572 | if (handlerUpdatePrimSinglePosition != null) | ||
3573 | { | ||
3574 | handlerUpdatePrimSinglePosition(localId, pos4, this); | ||
3575 | } | ||
3576 | } | ||
3577 | break; | ||
3578 | case 29: | ||
3579 | LLVector3 scale5 = new LLVector3(block.Data, 12); | ||
3580 | LLVector3 pos5 = new LLVector3(block.Data, 0); | ||
3581 | |||
3582 | handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; | ||
3583 | if (handlerUpdatePrimGroupScale != null) | ||
3584 | { | ||
3585 | // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); | ||
3586 | handlerUpdatePrimGroupScale(localId, scale5, this); | ||
3587 | handlerUpdateVector = OnUpdatePrimGroupPosition; | ||
3588 | |||
3589 | if (handlerUpdateVector != null) | ||
3590 | { | ||
3591 | handlerUpdateVector(localId, pos5, this); | ||
3592 | } | ||
3593 | } | ||
3594 | break; | ||
3595 | case 21: | ||
3596 | LLVector3 scale6 = new LLVector3(block.Data, 12); | ||
3597 | LLVector3 pos6 = new LLVector3(block.Data, 0); | ||
3598 | |||
3599 | handlerUpdatePrimScale = OnUpdatePrimScale; | ||
3600 | if (handlerUpdatePrimScale != null) | ||
3601 | { | ||
3602 | // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); | ||
3603 | handlerUpdatePrimScale(localId, scale6, this); | ||
3604 | handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; | ||
3605 | if (handlerUpdatePrimSinglePosition != null) | ||
3606 | { | ||
3607 | handlerUpdatePrimSinglePosition(localId, pos6, this); | ||
3608 | } | ||
3609 | } | ||
3610 | break; | ||
3611 | } | ||
3612 | } | ||
3613 | } | ||
3614 | } | ||
3615 | return true; | ||
3616 | } | ||
3617 | |||
3618 | public void RequestMapLayer() | ||
3619 | { | ||
3620 | //should be getting the map layer from the grid server | ||
3621 | //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area) | ||
3622 | MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply); | ||
3623 | // TODO: don't create new blocks if recycling an old packet | ||
3624 | mapReply.AgentData.AgentID = AgentId; | ||
3625 | mapReply.AgentData.Flags = 0; | ||
3626 | mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; | ||
3627 | mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); | ||
3628 | mapReply.LayerData[0].Bottom = 0; | ||
3629 | mapReply.LayerData[0].Left = 0; | ||
3630 | mapReply.LayerData[0].Top = 30000; | ||
3631 | mapReply.LayerData[0].Right = 30000; | ||
3632 | mapReply.LayerData[0].ImageID = new LLUUID("00000000-0000-1111-9999-000000000006"); | ||
3633 | mapReply.Header.Zerocoded = true; | ||
3634 | OutPacket(mapReply, ThrottleOutPacketType.Land); | ||
3635 | } | ||
3636 | |||
3637 | public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY) | ||
3638 | { | ||
3639 | /* | ||
3640 | IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY); | ||
3641 | MapBlockReplyPacket mbReply = new MapBlockReplyPacket(); | ||
3642 | mbReply.AgentData.AgentId = this.AgentId; | ||
3643 | int len; | ||
3644 | if (simMapProfiles == null) | ||
3645 | len = 0; | ||
3646 | else | ||
3647 | len = simMapProfiles.Count; | ||
3648 | |||
3649 | mbReply.Data = new MapBlockReplyPacket.DataBlock[len]; | ||
3650 | int iii; | ||
3651 | for (iii = 0; iii < len; iii++) | ||
3652 | { | ||
3653 | Hashtable mp = (Hashtable)simMapProfiles[iii]; | ||
3654 | mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); | ||
3655 | mbReply.Data[iii].Name = System.Text.Encoding.UTF8.GetBytes((string)mp["name"]); | ||
3656 | mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); | ||
3657 | mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); | ||
3658 | mbReply.Data[iii].MapImageID = new LLUUID((string)mp["map-image-id"]); | ||
3659 | mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]); | ||
3660 | mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]); | ||
3661 | mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]); | ||
3662 | mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]); | ||
3663 | } | ||
3664 | this.OutPacket(mbReply, ThrottleOutPacketType.Land); | ||
3665 | */ | ||
3666 | } | ||
3667 | |||
3668 | /// <summary> | ||
3669 | /// returns a byte array of the client set throttles Gets multiplied by the multiplier | ||
3670 | /// | ||
3671 | /// </summary> | ||
3672 | /// <param name="multiplier">non 1 multiplier for subdividing the throttles between individual regions</param> | ||
3673 | /// <returns></returns> | ||
3674 | public byte[] GetThrottlesPacked(float multiplier) | ||
3675 | { | ||
3676 | return m_PacketHandler.PacketQueue.GetThrottlesPacked(multiplier); | ||
3677 | } | ||
3678 | /// <summary> | ||
3679 | /// sets the throttles from values supplied by the client | ||
3680 | /// </summary> | ||
3681 | /// <param name="throttles"></param> | ||
3682 | public void SetChildAgentThrottle(byte[] throttles) | ||
3683 | { | ||
3684 | m_PacketHandler.PacketQueue.SetThrottleFromClient(throttles); | ||
3685 | } | ||
3686 | |||
3687 | // Previously ClientView.m_packetQueue | ||
3688 | |||
3689 | /// <summary> | ||
3690 | /// Helper routine to prepare the packet for sending to UDP client | ||
3691 | /// This converts it to bytes and puts it on the outgoing buffer | ||
3692 | /// </summary> | ||
3693 | /// <param name="Pack"></param> | ||
3694 | protected virtual void ProcessOutPacket(Packet Pack) | ||
3695 | { | ||
3696 | // Keep track of when this packet was sent out | ||
3697 | Pack.TickCount = System.Environment.TickCount; | ||
3698 | |||
3699 | // Actually make the byte array and send it | ||
3700 | try | ||
3701 | { | ||
3702 | byte[] sendbuffer = Pack.ToBytes(); | ||
3703 | PacketPool.Instance.ReturnPacket(Pack); | ||
3704 | |||
3705 | if (Pack.Header.Zerocoded) | ||
3706 | { | ||
3707 | int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); | ||
3708 | m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, m_circuitCode); | ||
3709 | } | ||
3710 | else | ||
3711 | { | ||
3712 | //Need some extra space in case we need to add proxy information to the message later | ||
3713 | Buffer.BlockCopy(sendbuffer, 0, ZeroOutBuffer, 0, sendbuffer.Length); | ||
3714 | m_networkServer.SendPacketTo(ZeroOutBuffer, sendbuffer.Length, SocketFlags.None, m_circuitCode); | ||
3715 | } | ||
3716 | } | ||
3717 | catch (Exception e) | ||
3718 | { | ||
3719 | m_log.Warn("[client]: " + | ||
3720 | "ClientView.m_packetQueue.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + | ||
3721 | m_userEndPoint.ToString() + " - killing thread"); | ||
3722 | m_log.Error(e.ToString()); | ||
3723 | Close(true); | ||
3724 | } | ||
3725 | } | ||
3726 | |||
3727 | /// <summary> | ||
3728 | /// method gets called when a new packet has arrived from the UDP server. This happens after it's been decoded into a libsl object | ||
3729 | /// </summary> | ||
3730 | /// <param name="NewPack"></param> | ||
3731 | public virtual void InPacket(Packet NewPack) | ||
3732 | { | ||
3733 | m_PacketHandler.InPacket(NewPack); | ||
3734 | } | ||
3735 | |||
3736 | /// <summary> | ||
3737 | /// The dreaded OutPacket. This should only be called from within | ||
3738 | /// the ClientStack itself right now | ||
3739 | /// This is the entry point for simulator packets to go out to | ||
3740 | /// the client. | ||
3741 | /// </summary> | ||
3742 | /// <param name="NewPack"></param> | ||
3743 | /// <param name="throttlePacketType">Corresponds to the type of data that is going out. Enum</param> | ||
3744 | public virtual void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType) | ||
3745 | { | ||
3746 | m_PacketHandler.OutPacket(NewPack, throttlePacketType); | ||
3747 | } | ||
3748 | |||
3749 | public bool AddMoney(int debit) | ||
3750 | { | ||
3751 | if (m_moneyBalance + debit >= 0) | ||
3752 | { | ||
3753 | m_moneyBalance += debit; | ||
3754 | SendMoneyBalance(LLUUID.Zero, true, Helpers.StringToField("Poof Poof!"), m_moneyBalance); | ||
3755 | return true; | ||
3756 | } | ||
3757 | else | ||
3758 | { | ||
3759 | return false; | ||
3760 | } | ||
3761 | } | ||
3762 | |||
3763 | /// <summary> | ||
3764 | /// Breaks down the genericMessagePacket into specific events | ||
3765 | /// </summary> | ||
3766 | /// <param name="gmMethod"></param> | ||
3767 | /// <param name="gmInvoice"></param> | ||
3768 | /// <param name="gmParams"></param> | ||
3769 | public void DecipherGenericMessage(string gmMethod, LLUUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams) | ||
3770 | { | ||
3771 | switch (gmMethod) | ||
3772 | { | ||
3773 | case "autopilot": | ||
3774 | float locx = 0f; | ||
3775 | float locy = 0f; | ||
3776 | float locz = 0f; | ||
3777 | uint regionX = 0; | ||
3778 | uint regionY = 0; | ||
3779 | try | ||
3780 | { | ||
3781 | Helpers.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); | ||
3782 | locx = Convert.ToSingle(Helpers.FieldToUTF8String(gmParams[0].Parameter)) - (float)regionX; | ||
3783 | locy = Convert.ToSingle(Helpers.FieldToUTF8String(gmParams[1].Parameter)) - (float)regionY; | ||
3784 | locz = Convert.ToSingle(Helpers.FieldToUTF8String(gmParams[2].Parameter)); | ||
3785 | } | ||
3786 | catch (InvalidCastException) | ||
3787 | { | ||
3788 | m_log.Error("[CLIENT]: Invalid autopilot request"); | ||
3789 | return; | ||
3790 | } | ||
3791 | |||
3792 | handlerAutoPilotGo = OnAutoPilotGo; | ||
3793 | if (handlerAutoPilotGo != null) | ||
3794 | { | ||
3795 | handlerAutoPilotGo(0, new LLVector3(locx, locy, locz), this); | ||
3796 | } | ||
3797 | m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz); | ||
3798 | |||
3799 | |||
3800 | break; | ||
3801 | default: | ||
3802 | m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice.ToString() + ". Dumping Params:"); | ||
3803 | for (int hi = 0; hi < gmParams.Length; hi++) | ||
3804 | { | ||
3805 | System.Console.WriteLine(gmParams[hi].ToString()); | ||
3806 | } | ||
3807 | //gmpack.MethodData. | ||
3808 | break; | ||
3809 | |||
3810 | } | ||
3811 | } | ||
3812 | |||
3813 | /// <summary> | ||
3814 | /// Entryway from the client to the simulator | ||
3815 | /// all UDP packets from the client will end up here | ||
3816 | /// </summary> | ||
3817 | /// <param name="Pack">libsecondlife.packet</param> | ||
3818 | public void ProcessInPacket(Packet Pack) | ||
3819 | { | ||
3820 | // check if we've got a local packet handler for this packet.type. See RegisterLocalPacketHandlers() | ||
3821 | if (ProcessPacketMethod(Pack)) | ||
3822 | { | ||
3823 | //there is a handler registered that handled this packet type | ||
3824 | return; | ||
3825 | } | ||
3826 | else | ||
3827 | { | ||
3828 | // Main packet processing conditional | ||
3829 | switch (Pack.Type) | ||
3830 | { | ||
3831 | #region Scene/Avatar | ||
3832 | |||
3833 | case PacketType.GenericMessage: | ||
3834 | GenericMessagePacket gmpack = (GenericMessagePacket)Pack; | ||
3835 | |||
3836 | DecipherGenericMessage(Helpers.FieldToUTF8String(gmpack.MethodData.Method), gmpack.MethodData.Invoice, gmpack.ParamList); | ||
3837 | |||
3838 | break; | ||
3839 | case PacketType.AvatarPropertiesRequest: | ||
3840 | AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; | ||
3841 | |||
3842 | handlerRequestAvatarProperties = OnRequestAvatarProperties; | ||
3843 | if (handlerRequestAvatarProperties != null) | ||
3844 | { | ||
3845 | handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); | ||
3846 | } | ||
3847 | |||
3848 | break; | ||
3849 | case PacketType.ChatFromViewer: | ||
3850 | ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; | ||
3851 | |||
3852 | string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname; | ||
3853 | byte[] message = inchatpack.ChatData.Message; | ||
3854 | byte type = inchatpack.ChatData.Type; | ||
3855 | LLVector3 fromPos = new LLVector3(); // ClientAvatar.Pos; | ||
3856 | // LLUUID fromAgentID = AgentId; | ||
3857 | |||
3858 | int channel = inchatpack.ChatData.Channel; | ||
3859 | |||
3860 | if (OnChatFromViewer != null) | ||
3861 | { | ||
3862 | OSChatMessage args = new OSChatMessage(); | ||
3863 | args.Channel = channel; | ||
3864 | args.From = fromName; | ||
3865 | args.Message = Helpers.FieldToUTF8String(message); | ||
3866 | args.Type = (ChatTypeEnum)type; | ||
3867 | args.Position = fromPos; | ||
3868 | |||
3869 | args.Scene = Scene; | ||
3870 | args.Sender = this; | ||
3871 | |||
3872 | handlerChatFromViewer = OnChatFromViewer; | ||
3873 | if (handlerChatFromViewer != null) | ||
3874 | handlerChatFromViewer(this, args); | ||
3875 | } | ||
3876 | break; | ||
3877 | case PacketType.AvatarPropertiesUpdate: | ||
3878 | AvatarPropertiesUpdatePacket Packet = (AvatarPropertiesUpdatePacket)Pack; | ||
3879 | |||
3880 | handlerUpdateAvatarProperties = OnUpdateAvatarProperties; | ||
3881 | if (handlerUpdateAvatarProperties != null) | ||
3882 | { | ||
3883 | AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = Packet.PropertiesData; | ||
3884 | UserProfileData UserProfile = new UserProfileData(); | ||
3885 | UserProfile.ID = AgentId; | ||
3886 | UserProfile.AboutText = Helpers.FieldToUTF8String(Properties.AboutText); | ||
3887 | UserProfile.FirstLifeAboutText = Helpers.FieldToUTF8String(Properties.FLAboutText); | ||
3888 | UserProfile.FirstLifeImage = Properties.FLImageID; | ||
3889 | UserProfile.Image = Properties.ImageID; | ||
3890 | |||
3891 | handlerUpdateAvatarProperties(this, UserProfile); | ||
3892 | } | ||
3893 | break; | ||
3894 | |||
3895 | case PacketType.ScriptDialogReply: | ||
3896 | ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; | ||
3897 | int ch = rdialog.Data.ChatChannel; | ||
3898 | byte[] msg = rdialog.Data.ButtonLabel; | ||
3899 | if (OnChatFromViewer != null) | ||
3900 | { | ||
3901 | OSChatMessage args = new OSChatMessage(); | ||
3902 | args.Channel = ch; | ||
3903 | args.From = String.Empty; | ||
3904 | args.Message = Helpers.FieldToUTF8String(msg); | ||
3905 | args.Type = ChatTypeEnum.Shout; | ||
3906 | args.Position = new LLVector3(); | ||
3907 | args.Scene = Scene; | ||
3908 | args.Sender = this; | ||
3909 | handlerChatFromViewer2 = OnChatFromViewer; | ||
3910 | if (handlerChatFromViewer2 != null) | ||
3911 | handlerChatFromViewer2(this, args); | ||
3912 | } | ||
3913 | |||
3914 | break; | ||
3915 | case PacketType.ImprovedInstantMessage: | ||
3916 | ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack; | ||
3917 | string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); | ||
3918 | string IMmessage = Helpers.FieldToUTF8String(msgpack.MessageBlock.Message); | ||
3919 | handlerInstantMessage = OnInstantMessage; | ||
3920 | |||
3921 | if (handlerInstantMessage != null) | ||
3922 | { | ||
3923 | handlerInstantMessage(this, msgpack.AgentData.AgentID, msgpack.AgentData.SessionID, | ||
3924 | msgpack.MessageBlock.ToAgentID, msgpack.MessageBlock.ID, | ||
3925 | msgpack.MessageBlock.Timestamp, IMfromName, IMmessage, | ||
3926 | msgpack.MessageBlock.Dialog, msgpack.MessageBlock.FromGroup, | ||
3927 | msgpack.MessageBlock.Offline, msgpack.MessageBlock.ParentEstateID, | ||
3928 | msgpack.MessageBlock.Position, msgpack.MessageBlock.RegionID, | ||
3929 | msgpack.MessageBlock.BinaryBucket); | ||
3930 | } | ||
3931 | break; | ||
3932 | |||
3933 | case PacketType.AcceptFriendship: | ||
3934 | AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack; | ||
3935 | |||
3936 | // My guess is this is the folder to stick the calling card into | ||
3937 | List<LLUUID> callingCardFolders = new List<LLUUID>(); | ||
3938 | |||
3939 | LLUUID agentID = afriendpack.AgentData.AgentID; | ||
3940 | LLUUID transactionID = afriendpack.TransactionBlock.TransactionID; | ||
3941 | |||
3942 | for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) | ||
3943 | { | ||
3944 | callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); | ||
3945 | } | ||
3946 | |||
3947 | handlerApproveFriendRequest = OnApproveFriendRequest; | ||
3948 | if (handlerApproveFriendRequest != null) | ||
3949 | { | ||
3950 | handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); | ||
3951 | } | ||
3952 | break; | ||
3953 | case PacketType.TerminateFriendship: | ||
3954 | TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; | ||
3955 | LLUUID listOwnerAgentID = tfriendpack.AgentData.AgentID; | ||
3956 | LLUUID exFriendID = tfriendpack.ExBlock.OtherID; | ||
3957 | |||
3958 | handlerTerminateFriendship = OnTerminateFriendship; | ||
3959 | if (handlerTerminateFriendship != null) | ||
3960 | { | ||
3961 | handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); | ||
3962 | } | ||
3963 | break; | ||
3964 | case PacketType.RezObject: | ||
3965 | RezObjectPacket rezPacket = (RezObjectPacket)Pack; | ||
3966 | |||
3967 | handlerRezObject = OnRezObject; | ||
3968 | if (handlerRezObject != null) | ||
3969 | { | ||
3970 | //rezPacket.RezData.BypassRaycast; | ||
3971 | //rezPacket.RezData.RayEnd; | ||
3972 | //rezPacket.RezData.RayEndIsIntersection; | ||
3973 | //rezPacket.RezData.RayStart; | ||
3974 | //rezPacket.RezData.RayTargetID; | ||
3975 | //rezPacket.RezData.RemoveItem; | ||
3976 | //rezPacket.RezData.RezSelected; | ||
3977 | //rezPacket.RezData.FromTaskID; | ||
3978 | //m_log.Info("[REZData]: " + rezPacket.ToString()); | ||
3979 | |||
3980 | handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd, | ||
3981 | rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID, | ||
3982 | rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection, | ||
3983 | rezPacket.RezData.EveryoneMask, rezPacket.RezData.GroupMask, | ||
3984 | rezPacket.RezData.NextOwnerMask, rezPacket.RezData.ItemFlags, | ||
3985 | rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem, | ||
3986 | rezPacket.RezData.FromTaskID); | ||
3987 | } | ||
3988 | break; | ||
3989 | case PacketType.DeRezObject: | ||
3990 | handlerDeRezObject = OnDeRezObject; | ||
3991 | if (handlerDeRezObject != null) | ||
3992 | { | ||
3993 | handlerDeRezObject(Pack, this); | ||
3994 | } | ||
3995 | break; | ||
3996 | case PacketType.ModifyLand: | ||
3997 | ModifyLandPacket modify = (ModifyLandPacket)Pack; | ||
3998 | //m_log.Info("[LAND]: LAND:" + modify.ToString()); | ||
3999 | if (modify.ParcelData.Length > 0) | ||
4000 | { | ||
4001 | if (OnModifyTerrain != null) | ||
4002 | { | ||
4003 | for (int i = 0; i < modify.ParcelData.Length; i++) | ||
4004 | { | ||
4005 | handlerModifyTerrain = OnModifyTerrain; | ||
4006 | if (handlerModifyTerrain != null) | ||
4007 | { | ||
4008 | handlerModifyTerrain(modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, | ||
4009 | modify.ModifyBlock.BrushSize, | ||
4010 | modify.ModifyBlock.Action, modify.ParcelData[i].North, | ||
4011 | modify.ParcelData[i].West, modify.ParcelData[i].South, | ||
4012 | modify.ParcelData[i].East, this); | ||
4013 | } | ||
4014 | } | ||
4015 | } | ||
4016 | } | ||
4017 | |||
4018 | break; | ||
4019 | case PacketType.RegionHandshakeReply: | ||
4020 | |||
4021 | handlerRegionHandShakeReply = OnRegionHandShakeReply; | ||
4022 | if (handlerRegionHandShakeReply != null) | ||
4023 | { | ||
4024 | handlerRegionHandShakeReply(this); | ||
4025 | } | ||
4026 | |||
4027 | break; | ||
4028 | case PacketType.AgentWearablesRequest: | ||
4029 | handlerRequestWearables = OnRequestWearables; | ||
4030 | |||
4031 | if (handlerRequestWearables != null) | ||
4032 | { | ||
4033 | handlerRequestWearables(); | ||
4034 | } | ||
4035 | |||
4036 | handlerRequestAvatarsData = OnRequestAvatarsData; | ||
4037 | |||
4038 | if (handlerRequestAvatarsData != null) | ||
4039 | { | ||
4040 | handlerRequestAvatarsData(this); | ||
4041 | } | ||
4042 | |||
4043 | break; | ||
4044 | case PacketType.AgentSetAppearance: | ||
4045 | AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack; | ||
4046 | |||
4047 | handlerSetAppearance = OnSetAppearance; | ||
4048 | if (handlerSetAppearance != null) | ||
4049 | { | ||
4050 | // Temporarily protect ourselves from the mantis #951 failure. | ||
4051 | // However, we could do this for several other handlers where a failure isn't terminal | ||
4052 | // for the client session anyway, in order to protect ourselves against bad code in plugins | ||
4053 | try | ||
4054 | { | ||
4055 | List<byte> visualparams = new List<byte>(); | ||
4056 | foreach (AgentSetAppearancePacket.VisualParamBlock x in appear.VisualParam) | ||
4057 | { | ||
4058 | visualparams.Add(x.ParamValue); | ||
4059 | } | ||
4060 | |||
4061 | handlerSetAppearance(appear.ObjectData.TextureEntry, visualparams); | ||
4062 | } | ||
4063 | catch (Exception e) | ||
4064 | { | ||
4065 | m_log.ErrorFormat( | ||
4066 | "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}", | ||
4067 | e); | ||
4068 | } | ||
4069 | } | ||
4070 | |||
4071 | break; | ||
4072 | case PacketType.AgentIsNowWearing: | ||
4073 | if (OnAvatarNowWearing != null) | ||
4074 | { | ||
4075 | AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack; | ||
4076 | AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); | ||
4077 | for (int i = 0; i < nowWearing.WearableData.Length; i++) | ||
4078 | { | ||
4079 | AvatarWearingArgs.Wearable wearable = | ||
4080 | new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID, | ||
4081 | nowWearing.WearableData[i].WearableType); | ||
4082 | wearingArgs.NowWearing.Add(wearable); | ||
4083 | } | ||
4084 | |||
4085 | handlerAvatarNowWearing = OnAvatarNowWearing; | ||
4086 | if (handlerAvatarNowWearing != null) | ||
4087 | { | ||
4088 | handlerAvatarNowWearing(this, wearingArgs); | ||
4089 | } | ||
4090 | } | ||
4091 | break; | ||
4092 | case PacketType.RezSingleAttachmentFromInv: | ||
4093 | handlerRezSingleAttachment = OnRezSingleAttachmentFromInv; | ||
4094 | if (handlerRezSingleAttachment != null) | ||
4095 | { | ||
4096 | RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack; | ||
4097 | handlerRezSingleAttachment(this, rez.ObjectData.ItemID, | ||
4098 | rez.ObjectData.AttachmentPt, rez.ObjectData.ItemFlags, rez.ObjectData.NextOwnerMask); | ||
4099 | } | ||
4100 | |||
4101 | break; | ||
4102 | case PacketType.DetachAttachmentIntoInv: | ||
4103 | handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv; | ||
4104 | if (handlerDetachAttachmentIntoInv != null) | ||
4105 | { | ||
4106 | DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack; | ||
4107 | |||
4108 | LLUUID itemID = detachtoInv.ObjectData.ItemID; | ||
4109 | // LLUUID ATTACH_agentID = detachtoInv.ObjectData.AgentID; | ||
4110 | |||
4111 | handlerDetachAttachmentIntoInv(itemID, this); | ||
4112 | } | ||
4113 | break; | ||
4114 | case PacketType.ObjectAttach: | ||
4115 | if (OnObjectAttach != null) | ||
4116 | { | ||
4117 | ObjectAttachPacket att = (ObjectAttachPacket)Pack; | ||
4118 | |||
4119 | handlerObjectAttach = OnObjectAttach; | ||
4120 | |||
4121 | if (handlerObjectAttach != null) | ||
4122 | { | ||
4123 | if (att.ObjectData.Length > 0) | ||
4124 | { | ||
4125 | handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation); | ||
4126 | } | ||
4127 | } | ||
4128 | } | ||
4129 | |||
4130 | break; | ||
4131 | case PacketType.ObjectDetach: | ||
4132 | |||
4133 | ObjectDetachPacket dett = (ObjectDetachPacket)Pack; | ||
4134 | for (int j = 0; j < dett.ObjectData.Length; j++) | ||
4135 | { | ||
4136 | uint obj = dett.ObjectData[j].ObjectLocalID; | ||
4137 | handlerObjectDetach = OnObjectDetach; | ||
4138 | if (handlerObjectDetach != null) | ||
4139 | { | ||
4140 | handlerObjectDetach(obj, this); | ||
4141 | } | ||
4142 | |||
4143 | } | ||
4144 | |||
4145 | break; | ||
4146 | case PacketType.SetAlwaysRun: | ||
4147 | SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; | ||
4148 | |||
4149 | handlerSetAlwaysRun = OnSetAlwaysRun; | ||
4150 | if (handlerSetAlwaysRun != null) | ||
4151 | handlerSetAlwaysRun(this, run.AgentData.AlwaysRun); | ||
4152 | |||
4153 | break; | ||
4154 | case PacketType.CompleteAgentMovement: | ||
4155 | handlerCompleteMovementToRegion = OnCompleteMovementToRegion; | ||
4156 | if (handlerCompleteMovementToRegion != null) | ||
4157 | { | ||
4158 | handlerCompleteMovementToRegion(); | ||
4159 | } | ||
4160 | handlerCompleteMovementToRegion = null; | ||
4161 | |||
4162 | break; | ||
4163 | case PacketType.AgentUpdate: | ||
4164 | if (OnAgentUpdate != null) | ||
4165 | { | ||
4166 | AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; | ||
4167 | |||
4168 | AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; | ||
4169 | AgentUpdateArgs arg = new AgentUpdateArgs(); | ||
4170 | arg.AgentID = x.AgentID; | ||
4171 | arg.BodyRotation = x.BodyRotation; | ||
4172 | arg.CameraAtAxis = x.CameraAtAxis; | ||
4173 | arg.CameraCenter = x.CameraCenter; | ||
4174 | arg.CameraLeftAxis = x.CameraLeftAxis; | ||
4175 | arg.CameraUpAxis = x.CameraUpAxis; | ||
4176 | arg.ControlFlags = x.ControlFlags; | ||
4177 | arg.Far = x.Far; | ||
4178 | arg.Flags = x.Flags; | ||
4179 | arg.HeadRotation = x.HeadRotation; | ||
4180 | arg.SessionID = x.SessionID; | ||
4181 | arg.State = x.State; | ||
4182 | |||
4183 | handlerAgentUpdate = OnAgentUpdate; | ||
4184 | if (handlerAgentUpdate != null) | ||
4185 | OnAgentUpdate(this, arg); | ||
4186 | |||
4187 | handlerAgentUpdate = null; | ||
4188 | //agenUpdate.AgentData.ControlFlags, agenUpdate.AgentData.BodyRotationa); | ||
4189 | } | ||
4190 | break; | ||
4191 | case PacketType.AgentAnimation: | ||
4192 | AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; | ||
4193 | |||
4194 | handlerStartAnim = null; | ||
4195 | handlerStopAnim = null; | ||
4196 | |||
4197 | for (int i = 0; i < AgentAni.AnimationList.Length; i++) | ||
4198 | { | ||
4199 | if (AgentAni.AnimationList[i].StartAnim) | ||
4200 | { | ||
4201 | handlerStartAnim = OnStartAnim; | ||
4202 | if (handlerStartAnim != null) | ||
4203 | { | ||
4204 | handlerStartAnim(this, AgentAni.AnimationList[i].AnimID); | ||
4205 | } | ||
4206 | } | ||
4207 | else | ||
4208 | { | ||
4209 | handlerStopAnim = OnStopAnim; | ||
4210 | if (handlerStopAnim != null) | ||
4211 | { | ||
4212 | handlerStopAnim(this, AgentAni.AnimationList[i].AnimID); | ||
4213 | } | ||
4214 | } | ||
4215 | } | ||
4216 | break; | ||
4217 | case PacketType.AgentRequestSit: | ||
4218 | if (OnAgentRequestSit != null) | ||
4219 | { | ||
4220 | AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack; | ||
4221 | |||
4222 | handlerAgentRequestSit = OnAgentRequestSit; | ||
4223 | if (handlerAgentRequestSit != null) | ||
4224 | handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, | ||
4225 | agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); | ||
4226 | } | ||
4227 | break; | ||
4228 | case PacketType.AgentSit: | ||
4229 | if (OnAgentSit != null) | ||
4230 | { | ||
4231 | AgentSitPacket agentSit = (AgentSitPacket)Pack; | ||
4232 | |||
4233 | handlerAgentSit = OnAgentSit; | ||
4234 | if (handlerAgentSit != null) | ||
4235 | { | ||
4236 | OnAgentSit(this, agentSit.AgentData.AgentID); | ||
4237 | } | ||
4238 | } | ||
4239 | break; | ||
4240 | case PacketType.AvatarPickerRequest: | ||
4241 | AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; | ||
4242 | AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; | ||
4243 | AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; | ||
4244 | //Console.WriteLine("Agent Sends:" + Helpers.FieldToUTF8String(querydata.Name)); | ||
4245 | |||
4246 | handlerAvatarPickerRequest = OnAvatarPickerRequest; | ||
4247 | if (handlerAvatarPickerRequest != null) | ||
4248 | { | ||
4249 | handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, | ||
4250 | Helpers.FieldToUTF8String(querydata.Name)); | ||
4251 | } | ||
4252 | break; | ||
4253 | case PacketType.AgentDataUpdateRequest: | ||
4254 | AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack; | ||
4255 | |||
4256 | handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest; | ||
4257 | |||
4258 | if (handlerAgentDataUpdateRequest != null) | ||
4259 | { | ||
4260 | handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID); | ||
4261 | } | ||
4262 | |||
4263 | break; | ||
4264 | case PacketType.UserInfoRequest: | ||
4265 | UserInfoRequestPacket avUserInfoRequestPacket = (UserInfoRequestPacket)Pack; | ||
4266 | |||
4267 | handlerUserInfoRequest = OnUserInfoRequest; | ||
4268 | if (handlerUserInfoRequest != null) | ||
4269 | { | ||
4270 | handlerUserInfoRequest(this, avUserInfoRequestPacket.AgentData.AgentID, avUserInfoRequestPacket.AgentData.SessionID); | ||
4271 | } | ||
4272 | break; | ||
4273 | |||
4274 | case PacketType.SetStartLocationRequest: | ||
4275 | SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack; | ||
4276 | |||
4277 | if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId) | ||
4278 | { | ||
4279 | handlerSetStartLocationRequest = OnSetStartLocationRequest; | ||
4280 | if (handlerSetStartLocationRequest != null) | ||
4281 | { | ||
4282 | handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos, | ||
4283 | avSetStartLocationRequestPacket.StartLocationData.LocationLookAt, | ||
4284 | avSetStartLocationRequestPacket.StartLocationData.LocationID); | ||
4285 | } | ||
4286 | } | ||
4287 | break; | ||
4288 | |||
4289 | case PacketType.AgentThrottle: | ||
4290 | AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; | ||
4291 | m_PacketHandler.PacketQueue.SetThrottleFromClient(atpack.Throttle.Throttles); | ||
4292 | break; | ||
4293 | |||
4294 | case PacketType.AgentPause: | ||
4295 | m_probesWithNoIngressPackets = 0; | ||
4296 | m_clientBlocked = true; | ||
4297 | break; | ||
4298 | |||
4299 | case PacketType.AgentResume: | ||
4300 | m_probesWithNoIngressPackets = 0; | ||
4301 | m_clientBlocked = false; | ||
4302 | SendStartPingCheck(0); | ||
4303 | |||
4304 | break; | ||
4305 | |||
4306 | case PacketType.ForceScriptControlRelease: | ||
4307 | handlerForceReleaseControls = OnForceReleaseControls; | ||
4308 | if (handlerForceReleaseControls != null) | ||
4309 | { | ||
4310 | handlerForceReleaseControls(this, AgentId); | ||
4311 | } | ||
4312 | break; | ||
4313 | |||
4314 | #endregion | ||
4315 | |||
4316 | #region Objects/m_sceneObjects | ||
4317 | |||
4318 | case PacketType.ObjectLink: | ||
4319 | ObjectLinkPacket link = (ObjectLinkPacket)Pack; | ||
4320 | uint parentprimid = 0; | ||
4321 | List<uint> childrenprims = new List<uint>(); | ||
4322 | if (link.ObjectData.Length > 1) | ||
4323 | { | ||
4324 | parentprimid = link.ObjectData[0].ObjectLocalID; | ||
4325 | |||
4326 | for (int i = 1; i < link.ObjectData.Length; i++) | ||
4327 | { | ||
4328 | childrenprims.Add(link.ObjectData[i].ObjectLocalID); | ||
4329 | } | ||
4330 | } | ||
4331 | handlerLinkObjects = OnLinkObjects; | ||
4332 | if (handlerLinkObjects != null) | ||
4333 | { | ||
4334 | handlerLinkObjects(this, parentprimid, childrenprims); | ||
4335 | } | ||
4336 | break; | ||
4337 | case PacketType.ObjectDelink: | ||
4338 | ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; | ||
4339 | |||
4340 | // It appears the prim at index 0 is not always the root prim (for | ||
4341 | // instance, when one prim of a link set has been edited independently | ||
4342 | // of the others). Therefore, we'll pass all the ids onto the delink | ||
4343 | // method for it to decide which is the root. | ||
4344 | List<uint> prims = new List<uint>(); | ||
4345 | for (int i = 0; i < delink.ObjectData.Length; i++) | ||
4346 | { | ||
4347 | prims.Add(delink.ObjectData[i].ObjectLocalID); | ||
4348 | } | ||
4349 | handlerDelinkObjects = OnDelinkObjects; | ||
4350 | if (handlerDelinkObjects != null) | ||
4351 | { | ||
4352 | handlerDelinkObjects(prims); | ||
4353 | } | ||
4354 | |||
4355 | break; | ||
4356 | case PacketType.ObjectAdd: | ||
4357 | if (OnAddPrim != null) | ||
4358 | { | ||
4359 | ObjectAddPacket addPacket = (ObjectAddPacket)Pack; | ||
4360 | PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket); | ||
4361 | // m_log.Info("[REZData]: " + addPacket.ToString()); | ||
4362 | //BypassRaycast: 1 | ||
4363 | //RayStart: <69.79469, 158.2652, 98.40343> | ||
4364 | //RayEnd: <61.97724, 141.995, 92.58341> | ||
4365 | //RayTargetID: 00000000-0000-0000-0000-000000000000 | ||
4366 | |||
4367 | //Check to see if adding the prim is allowed; useful for any module wanting to restrict the | ||
4368 | //object from rezing initially | ||
4369 | |||
4370 | handlerAddPrim = OnAddPrim; | ||
4371 | if (handlerAddPrim != null) | ||
4372 | handlerAddPrim(AgentId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); | ||
4373 | } | ||
4374 | break; | ||
4375 | case PacketType.ObjectShape: | ||
4376 | ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; | ||
4377 | handlerUpdatePrimShape = null; | ||
4378 | for (int i = 0; i < shapePacket.ObjectData.Length; i++) | ||
4379 | { | ||
4380 | handlerUpdatePrimShape = OnUpdatePrimShape; | ||
4381 | if (handlerUpdatePrimShape != null) | ||
4382 | { | ||
4383 | UpdateShapeArgs shapeData = new UpdateShapeArgs(); | ||
4384 | shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID; | ||
4385 | shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin; | ||
4386 | shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve; | ||
4387 | shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd; | ||
4388 | shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset; | ||
4389 | shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions; | ||
4390 | shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX; | ||
4391 | shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY; | ||
4392 | shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX; | ||
4393 | shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY; | ||
4394 | shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew; | ||
4395 | shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX; | ||
4396 | shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY; | ||
4397 | shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist; | ||
4398 | shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin; | ||
4399 | shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin; | ||
4400 | shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve; | ||
4401 | shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd; | ||
4402 | shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow; | ||
4403 | |||
4404 | handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID, | ||
4405 | shapeData); | ||
4406 | } | ||
4407 | } | ||
4408 | break; | ||
4409 | case PacketType.ObjectExtraParams: | ||
4410 | ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; | ||
4411 | |||
4412 | handlerUpdateExtraParams = OnUpdateExtraParams; | ||
4413 | if (handlerUpdateExtraParams != null) | ||
4414 | { | ||
4415 | handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[0].ObjectLocalID, | ||
4416 | extraPar.ObjectData[0].ParamType, | ||
4417 | extraPar.ObjectData[0].ParamInUse, extraPar.ObjectData[0].ParamData); | ||
4418 | } | ||
4419 | break; | ||
4420 | case PacketType.ObjectDuplicate: | ||
4421 | ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; | ||
4422 | ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; | ||
4423 | |||
4424 | handlerObjectDuplicate = null; | ||
4425 | |||
4426 | for (int i = 0; i < dupe.ObjectData.Length; i++) | ||
4427 | { | ||
4428 | handlerObjectDuplicate = OnObjectDuplicate; | ||
4429 | if (handlerObjectDuplicate != null) | ||
4430 | { | ||
4431 | handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, | ||
4432 | dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, | ||
4433 | AgentandGroupData.GroupID); | ||
4434 | } | ||
4435 | } | ||
4436 | |||
4437 | break; | ||
4438 | |||
4439 | case PacketType.ObjectSelect: | ||
4440 | ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; | ||
4441 | |||
4442 | handlerObjectSelect = null; | ||
4443 | |||
4444 | for (int i = 0; i < incomingselect.ObjectData.Length; i++) | ||
4445 | { | ||
4446 | handlerObjectSelect = OnObjectSelect; | ||
4447 | if (handlerObjectSelect != null) | ||
4448 | { | ||
4449 | handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); | ||
4450 | } | ||
4451 | } | ||
4452 | break; | ||
4453 | case PacketType.ObjectDeselect: | ||
4454 | ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack; | ||
4455 | |||
4456 | handlerObjectDeselect = null; | ||
4457 | |||
4458 | for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) | ||
4459 | { | ||
4460 | handlerObjectDeselect = OnObjectDeselect; | ||
4461 | if (handlerObjectDeselect != null) | ||
4462 | { | ||
4463 | OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); | ||
4464 | } | ||
4465 | } | ||
4466 | break; | ||
4467 | case PacketType.ObjectPosition: | ||
4468 | // DEPRECATED: but till libsecondlife removes it, people will use it | ||
4469 | ObjectPositionPacket position = (ObjectPositionPacket)Pack; | ||
4470 | |||
4471 | for (int i = 0; i < position.ObjectData.Length; i++) | ||
4472 | { | ||
4473 | handlerUpdateVector = OnUpdatePrimGroupPosition; | ||
4474 | if (handlerUpdateVector != null) | ||
4475 | handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this); | ||
4476 | } | ||
4477 | |||
4478 | break; | ||
4479 | case PacketType.ObjectScale: | ||
4480 | // DEPRECATED: but till libsecondlife removes it, people will use it | ||
4481 | ObjectScalePacket scale = (ObjectScalePacket)Pack; | ||
4482 | |||
4483 | for (int i = 0; i < scale.ObjectData.Length; i++) | ||
4484 | { | ||
4485 | handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; | ||
4486 | if (handlerUpdatePrimGroupScale != null) | ||
4487 | handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this); | ||
4488 | } | ||
4489 | |||
4490 | break; | ||
4491 | case PacketType.ObjectRotation: | ||
4492 | // DEPRECATED: but till libsecondlife removes it, people will use it | ||
4493 | ObjectRotationPacket rotation = (ObjectRotationPacket)Pack; | ||
4494 | |||
4495 | for (int i = 0; i < rotation.ObjectData.Length; i++) | ||
4496 | { | ||
4497 | handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; | ||
4498 | if (handlerUpdatePrimRotation != null) | ||
4499 | handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this); | ||
4500 | } | ||
4501 | |||
4502 | break; | ||
4503 | case PacketType.ObjectFlagUpdate: | ||
4504 | ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack; | ||
4505 | |||
4506 | handlerUpdatePrimFlags = OnUpdatePrimFlags; | ||
4507 | |||
4508 | if (handlerUpdatePrimFlags != null) | ||
4509 | { | ||
4510 | handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, Pack, this); | ||
4511 | } | ||
4512 | break; | ||
4513 | case PacketType.ObjectImage: | ||
4514 | ObjectImagePacket imagePack = (ObjectImagePacket)Pack; | ||
4515 | |||
4516 | handlerUpdatePrimTexture = null; | ||
4517 | for (int i = 0; i < imagePack.ObjectData.Length; i++) | ||
4518 | { | ||
4519 | handlerUpdatePrimTexture = OnUpdatePrimTexture; | ||
4520 | if (handlerUpdatePrimTexture != null) | ||
4521 | { | ||
4522 | handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, | ||
4523 | imagePack.ObjectData[i].TextureEntry, this); | ||
4524 | } | ||
4525 | } | ||
4526 | break; | ||
4527 | case PacketType.ObjectGrab: | ||
4528 | ObjectGrabPacket grab = (ObjectGrabPacket)Pack; | ||
4529 | |||
4530 | handlerGrabObject = OnGrabObject; | ||
4531 | |||
4532 | if (handlerGrabObject != null) | ||
4533 | { | ||
4534 | handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this); | ||
4535 | } | ||
4536 | break; | ||
4537 | case PacketType.ObjectGrabUpdate: | ||
4538 | ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack; | ||
4539 | |||
4540 | handlerGrabUpdate = OnGrabUpdate; | ||
4541 | |||
4542 | if (handlerGrabUpdate != null) | ||
4543 | { | ||
4544 | handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial, | ||
4545 | grabUpdate.ObjectData.GrabPosition, this); | ||
4546 | } | ||
4547 | break; | ||
4548 | case PacketType.ObjectDeGrab: | ||
4549 | ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack; | ||
4550 | |||
4551 | handlerDeGrabObject = OnDeGrabObject; | ||
4552 | if (handlerDeGrabObject != null) | ||
4553 | { | ||
4554 | handlerDeGrabObject(deGrab.ObjectData.LocalID, this); | ||
4555 | } | ||
4556 | break; | ||
4557 | case PacketType.ObjectDescription: | ||
4558 | ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack; | ||
4559 | |||
4560 | handlerObjectDescription = null; | ||
4561 | |||
4562 | for (int i = 0; i < objDes.ObjectData.Length; i++) | ||
4563 | { | ||
4564 | handlerObjectDescription = OnObjectDescription; | ||
4565 | if (handlerObjectDescription != null) | ||
4566 | { | ||
4567 | handlerObjectDescription(this, objDes.ObjectData[i].LocalID, | ||
4568 | Util.FieldToString(objDes.ObjectData[i].Description)); | ||
4569 | } | ||
4570 | } | ||
4571 | break; | ||
4572 | case PacketType.ObjectName: | ||
4573 | ObjectNamePacket objName = (ObjectNamePacket)Pack; | ||
4574 | |||
4575 | handlerObjectName = null; | ||
4576 | for (int i = 0; i < objName.ObjectData.Length; i++) | ||
4577 | { | ||
4578 | handlerObjectName = OnObjectName; | ||
4579 | if (handlerObjectName != null) | ||
4580 | { | ||
4581 | handlerObjectName(this, objName.ObjectData[i].LocalID, | ||
4582 | Util.FieldToString(objName.ObjectData[i].Name)); | ||
4583 | } | ||
4584 | } | ||
4585 | break; | ||
4586 | case PacketType.ObjectPermissions: | ||
4587 | if (OnObjectPermissions != null) | ||
4588 | { | ||
4589 | ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack; | ||
4590 | |||
4591 | LLUUID AgentID = newobjPerms.AgentData.AgentID; | ||
4592 | LLUUID SessionID = newobjPerms.AgentData.SessionID; | ||
4593 | |||
4594 | handlerObjectPermissions = null; | ||
4595 | |||
4596 | for (int i = 0; i < newobjPerms.ObjectData.Length; i++) | ||
4597 | { | ||
4598 | ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i]; | ||
4599 | |||
4600 | byte field = permChanges.Field; | ||
4601 | uint localID = permChanges.ObjectLocalID; | ||
4602 | uint mask = permChanges.Mask; | ||
4603 | byte set = permChanges.Set; | ||
4604 | |||
4605 | handlerObjectPermissions = OnObjectPermissions; | ||
4606 | |||
4607 | if (handlerObjectPermissions != null) | ||
4608 | handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set); | ||
4609 | } | ||
4610 | } | ||
4611 | |||
4612 | // Here's our data, | ||
4613 | // PermField contains the field the info goes into | ||
4614 | // PermField determines which mask we're changing | ||
4615 | // | ||
4616 | // chmask is the mask of the change | ||
4617 | // setTF is whether we're adding it or taking it away | ||
4618 | // | ||
4619 | // objLocalID is the localID of the object. | ||
4620 | |||
4621 | // Unfortunately, we have to pass the event the packet because objData is an array | ||
4622 | // That means multiple object perms may be updated in a single packet. | ||
4623 | |||
4624 | break; | ||
4625 | |||
4626 | case PacketType.Undo: | ||
4627 | UndoPacket undoitem = (UndoPacket)Pack; | ||
4628 | if (undoitem.ObjectData.Length > 0) | ||
4629 | { | ||
4630 | for (int i = 0; i < undoitem.ObjectData.Length; i++) | ||
4631 | { | ||
4632 | LLUUID objiD = undoitem.ObjectData[i].ObjectID; | ||
4633 | handlerOnUndo = OnUndo; | ||
4634 | if (handlerOnUndo != null) | ||
4635 | { | ||
4636 | handlerOnUndo(this, objiD); | ||
4637 | } | ||
4638 | |||
4639 | } | ||
4640 | } | ||
4641 | break; | ||
4642 | case PacketType.ObjectDuplicateOnRay: | ||
4643 | ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack; | ||
4644 | |||
4645 | handlerObjectDuplicateOnRay = null; | ||
4646 | |||
4647 | |||
4648 | for (int i = 0; i < dupeOnRay.ObjectData.Length; i++) | ||
4649 | { | ||
4650 | handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay; | ||
4651 | if (handlerObjectDuplicateOnRay != null) | ||
4652 | { | ||
4653 | handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, | ||
4654 | dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, | ||
4655 | dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, | ||
4656 | dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); | ||
4657 | } | ||
4658 | } | ||
4659 | |||
4660 | break; | ||
4661 | case PacketType.RequestObjectPropertiesFamily: | ||
4662 | //This powers the little tooltip that appears when you move your mouse over an object | ||
4663 | RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack; | ||
4664 | |||
4665 | RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; | ||
4666 | |||
4667 | handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily; | ||
4668 | |||
4669 | if (handlerRequestObjectPropertiesFamily != null) | ||
4670 | { | ||
4671 | handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags, | ||
4672 | packObjBlock.ObjectID); | ||
4673 | } | ||
4674 | |||
4675 | break; | ||
4676 | case PacketType.ObjectIncludeInSearch: | ||
4677 | //This lets us set objects to appear in search (stuff like DataSnapshot, etc) | ||
4678 | ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack; | ||
4679 | handlerObjectIncludeInSearch = null; | ||
4680 | |||
4681 | foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData) | ||
4682 | { | ||
4683 | bool inSearch = objData.IncludeInSearch; | ||
4684 | uint localID = objData.ObjectLocalID; | ||
4685 | |||
4686 | handlerObjectIncludeInSearch = OnObjectIncludeInSearch; | ||
4687 | |||
4688 | if (handlerObjectIncludeInSearch != null) | ||
4689 | { | ||
4690 | handlerObjectIncludeInSearch(this, inSearch, localID); | ||
4691 | } | ||
4692 | } | ||
4693 | break; | ||
4694 | |||
4695 | case PacketType.ScriptAnswerYes: | ||
4696 | ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack; | ||
4697 | |||
4698 | handlerScriptAnswer = OnScriptAnswer; | ||
4699 | if (handlerScriptAnswer != null) | ||
4700 | { | ||
4701 | handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions); | ||
4702 | } | ||
4703 | break; | ||
4704 | |||
4705 | #endregion | ||
4706 | |||
4707 | #region Inventory/Asset/Other related packets | ||
4708 | |||
4709 | case PacketType.RequestImage: | ||
4710 | RequestImagePacket imageRequest = (RequestImagePacket)Pack; | ||
4711 | //Console.WriteLine("image request: " + Pack.ToString()); | ||
4712 | |||
4713 | handlerTextureRequest = null; | ||
4714 | |||
4715 | for (int i = 0; i < imageRequest.RequestImage.Length; i++) | ||
4716 | { | ||
4717 | if (OnRequestTexture != null) | ||
4718 | { | ||
4719 | TextureRequestArgs args = new TextureRequestArgs(); | ||
4720 | args.RequestedAssetID = imageRequest.RequestImage[i].Image; | ||
4721 | args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; | ||
4722 | args.PacketNumber = imageRequest.RequestImage[i].Packet; | ||
4723 | args.Priority = imageRequest.RequestImage[i].DownloadPriority; | ||
4724 | |||
4725 | handlerTextureRequest = OnRequestTexture; | ||
4726 | |||
4727 | if (handlerTextureRequest != null) | ||
4728 | OnRequestTexture(this, args); | ||
4729 | } | ||
4730 | } | ||
4731 | break; | ||
4732 | case PacketType.TransferRequest: | ||
4733 | //Console.WriteLine("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); | ||
4734 | TransferRequestPacket transfer = (TransferRequestPacket)Pack; | ||
4735 | // Validate inventory transfers | ||
4736 | // Has to be done here, because AssetCache can't do it | ||
4737 | // | ||
4738 | if (transfer.TransferInfo.SourceType == 3) | ||
4739 | { | ||
4740 | LLUUID taskID = null; | ||
4741 | LLUUID itemID = null; | ||
4742 | LLUUID requestID = null; | ||
4743 | taskID = new LLUUID(transfer.TransferInfo.Params, 48); | ||
4744 | itemID = new LLUUID(transfer.TransferInfo.Params, 64); | ||
4745 | requestID = new LLUUID(transfer.TransferInfo.Params, 80); | ||
4746 | if (!(((Scene)m_scene).ExternalChecks.ExternalChecksBypassPermissions())) | ||
4747 | { | ||
4748 | if (taskID != LLUUID.Zero) // Prim | ||
4749 | { | ||
4750 | SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); | ||
4751 | if (part == null) | ||
4752 | break; | ||
4753 | |||
4754 | if (part.OwnerID != AgentId) | ||
4755 | break; | ||
4756 | |||
4757 | if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) | ||
4758 | break; | ||
4759 | |||
4760 | TaskInventoryItem ti = part.GetInventoryItem(itemID); | ||
4761 | if (ti == null) | ||
4762 | break; | ||
4763 | |||
4764 | if (ti.OwnerID != AgentId) | ||
4765 | break; | ||
4766 | |||
4767 | if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) | ||
4768 | break; | ||
4769 | |||
4770 | if (ti.AssetID != requestID) | ||
4771 | break; | ||
4772 | } | ||
4773 | else // Agent | ||
4774 | { | ||
4775 | CachedUserInfo userInfo = ((Scene)m_scene).CommsManager.UserProfileCacheService.GetUserDetails(AgentId); | ||
4776 | if (userInfo == null) | ||
4777 | break; | ||
4778 | |||
4779 | if (userInfo.RootFolder == null) | ||
4780 | break; | ||
4781 | |||
4782 | InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(itemID); | ||
4783 | if (assetRequestItem == null) | ||
4784 | { | ||
4785 | assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.libraryRoot.FindItem(itemID); | ||
4786 | if (assetRequestItem == null) | ||
4787 | return; | ||
4788 | } | ||
4789 | |||
4790 | if ((assetRequestItem.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) | ||
4791 | break; | ||
4792 | if (assetRequestItem.AssetID != requestID) | ||
4793 | break; | ||
4794 | } | ||
4795 | } | ||
4796 | } | ||
4797 | |||
4798 | m_assetCache.AddAssetRequest(this, transfer); | ||
4799 | /* RequestAsset = OnRequestAsset; | ||
4800 | if (RequestAsset != null) | ||
4801 | { | ||
4802 | RequestAsset(this, transfer); | ||
4803 | }*/ | ||
4804 | break; | ||
4805 | case PacketType.AssetUploadRequest: | ||
4806 | AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; | ||
4807 | // Console.WriteLine("upload request " + Pack.ToString()); | ||
4808 | // Console.WriteLine("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); | ||
4809 | LLUUID temp = LLUUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); | ||
4810 | |||
4811 | handlerAssetUploadRequest = OnAssetUploadRequest; | ||
4812 | |||
4813 | if (handlerAssetUploadRequest != null) | ||
4814 | { | ||
4815 | handlerAssetUploadRequest(this, temp, | ||
4816 | request.AssetBlock.TransactionID, request.AssetBlock.Type, | ||
4817 | request.AssetBlock.AssetData, request.AssetBlock.StoreLocal, | ||
4818 | request.AssetBlock.Tempfile); | ||
4819 | } | ||
4820 | break; | ||
4821 | case PacketType.RequestXfer: | ||
4822 | RequestXferPacket xferReq = (RequestXferPacket)Pack; | ||
4823 | |||
4824 | handlerRequestXfer = OnRequestXfer; | ||
4825 | |||
4826 | if (handlerRequestXfer != null) | ||
4827 | { | ||
4828 | handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); | ||
4829 | } | ||
4830 | break; | ||
4831 | case PacketType.SendXferPacket: | ||
4832 | SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; | ||
4833 | |||
4834 | handlerXferReceive = OnXferReceive; | ||
4835 | if (handlerXferReceive != null) | ||
4836 | { | ||
4837 | handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); | ||
4838 | } | ||
4839 | break; | ||
4840 | case PacketType.ConfirmXferPacket: | ||
4841 | ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; | ||
4842 | |||
4843 | handlerConfirmXfer = OnConfirmXfer; | ||
4844 | if (handlerConfirmXfer != null) | ||
4845 | { | ||
4846 | handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); | ||
4847 | } | ||
4848 | break; | ||
4849 | case PacketType.CreateInventoryFolder: | ||
4850 | CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack; | ||
4851 | |||
4852 | handlerCreateInventoryFolder = OnCreateNewInventoryFolder; | ||
4853 | if (handlerCreateInventoryFolder != null) | ||
4854 | { | ||
4855 | handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID, | ||
4856 | (ushort)invFolder.FolderData.Type, | ||
4857 | Util.FieldToString(invFolder.FolderData.Name), | ||
4858 | invFolder.FolderData.ParentID); | ||
4859 | } | ||
4860 | break; | ||
4861 | case PacketType.UpdateInventoryFolder: | ||
4862 | if (OnUpdateInventoryFolder != null) | ||
4863 | { | ||
4864 | UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack; | ||
4865 | |||
4866 | handlerUpdateInventoryFolder = null; | ||
4867 | |||
4868 | for (int i = 0; i < invFolderx.FolderData.Length; i++) | ||
4869 | { | ||
4870 | handlerUpdateInventoryFolder = OnUpdateInventoryFolder; | ||
4871 | if (handlerUpdateInventoryFolder != null) | ||
4872 | { | ||
4873 | OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID, | ||
4874 | (ushort)invFolderx.FolderData[i].Type, | ||
4875 | Util.FieldToString(invFolderx.FolderData[i].Name), | ||
4876 | invFolderx.FolderData[i].ParentID); | ||
4877 | } | ||
4878 | } | ||
4879 | } | ||
4880 | break; | ||
4881 | case PacketType.MoveInventoryFolder: | ||
4882 | if (OnMoveInventoryFolder != null) | ||
4883 | { | ||
4884 | MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack; | ||
4885 | |||
4886 | handlerMoveInventoryFolder = null; | ||
4887 | |||
4888 | for (int i = 0; i < invFoldery.InventoryData.Length; i++) | ||
4889 | { | ||
4890 | handlerMoveInventoryFolder = OnMoveInventoryFolder; | ||
4891 | if (handlerMoveInventoryFolder != null) | ||
4892 | { | ||
4893 | OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID, | ||
4894 | invFoldery.InventoryData[i].ParentID); | ||
4895 | } | ||
4896 | } | ||
4897 | } | ||
4898 | break; | ||
4899 | case PacketType.CreateInventoryItem: | ||
4900 | CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; | ||
4901 | |||
4902 | handlerCreateNewInventoryItem = OnCreateNewInventoryItem; | ||
4903 | if (handlerCreateNewInventoryItem != null) | ||
4904 | { | ||
4905 | handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, | ||
4906 | createItem.InventoryBlock.FolderID, | ||
4907 | createItem.InventoryBlock.CallbackID, | ||
4908 | Util.FieldToString(createItem.InventoryBlock.Description), | ||
4909 | Util.FieldToString(createItem.InventoryBlock.Name), | ||
4910 | createItem.InventoryBlock.InvType, | ||
4911 | createItem.InventoryBlock.Type, | ||
4912 | createItem.InventoryBlock.WearableType, | ||
4913 | createItem.InventoryBlock.NextOwnerMask, | ||
4914 | Util.UnixTimeSinceEpoch()); | ||
4915 | } | ||
4916 | break; | ||
4917 | case PacketType.FetchInventory: | ||
4918 | if (OnFetchInventory != null) | ||
4919 | { | ||
4920 | FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack; | ||
4921 | |||
4922 | handlerFetchInventory = null; | ||
4923 | |||
4924 | for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++) | ||
4925 | { | ||
4926 | handlerFetchInventory = OnFetchInventory; | ||
4927 | |||
4928 | if (handlerFetchInventory != null) | ||
4929 | { | ||
4930 | OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID, | ||
4931 | FetchInventoryx.InventoryData[i].OwnerID); | ||
4932 | } | ||
4933 | } | ||
4934 | } | ||
4935 | break; | ||
4936 | case PacketType.FetchInventoryDescendents: | ||
4937 | FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack; | ||
4938 | |||
4939 | handlerFetchInventoryDescendents = OnFetchInventoryDescendents; | ||
4940 | if (handlerFetchInventoryDescendents != null) | ||
4941 | { | ||
4942 | handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, | ||
4943 | Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, | ||
4944 | Fetch.InventoryData.SortOrder); | ||
4945 | } | ||
4946 | break; | ||
4947 | case PacketType.PurgeInventoryDescendents: | ||
4948 | PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack; | ||
4949 | |||
4950 | handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents; | ||
4951 | if (handlerPurgeInventoryDescendents != null) | ||
4952 | { | ||
4953 | handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); | ||
4954 | } | ||
4955 | break; | ||
4956 | case PacketType.UpdateInventoryItem: | ||
4957 | UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)Pack; | ||
4958 | if (OnUpdateInventoryItem != null) | ||
4959 | { | ||
4960 | handlerUpdateInventoryItem = null; | ||
4961 | for (int i = 0; i < update.InventoryData.Length; i++) | ||
4962 | { | ||
4963 | handlerUpdateInventoryItem = OnUpdateInventoryItem; | ||
4964 | |||
4965 | if (handlerUpdateInventoryItem != null) | ||
4966 | { | ||
4967 | InventoryItemBase itemUpd = new InventoryItemBase(); | ||
4968 | itemUpd.ID = update.InventoryData[i].ItemID; | ||
4969 | itemUpd.Name = Util.FieldToString(update.InventoryData[i].Name); | ||
4970 | itemUpd.Description = Util.FieldToString(update.InventoryData[i].Description); | ||
4971 | itemUpd.GroupID = update.InventoryData[i].GroupID; | ||
4972 | itemUpd.GroupOwned = update.InventoryData[i].GroupOwned; | ||
4973 | itemUpd.NextPermissions = update.InventoryData[i].NextOwnerMask; | ||
4974 | itemUpd.EveryOnePermissions = update.InventoryData[i].EveryoneMask; | ||
4975 | itemUpd.CreationDate = update.InventoryData[i].CreationDate; | ||
4976 | itemUpd.Folder = update.InventoryData[i].FolderID; | ||
4977 | itemUpd.InvType = update.InventoryData[i].InvType; | ||
4978 | itemUpd.SalePrice = update.InventoryData[i].SalePrice; | ||
4979 | itemUpd.SaleType = update.InventoryData[i].SaleType; | ||
4980 | itemUpd.Flags = update.InventoryData[i].Flags; | ||
4981 | /* | ||
4982 | OnUpdateInventoryItem(this, update.InventoryData[i].TransactionID, | ||
4983 | update.InventoryData[i].ItemID, | ||
4984 | Util.FieldToString(update.InventoryData[i].Name), | ||
4985 | Util.FieldToString(update.InventoryData[i].Description), | ||
4986 | update.InventoryData[i].NextOwnerMask); | ||
4987 | */ | ||
4988 | OnUpdateInventoryItem(this, update.InventoryData[i].TransactionID, | ||
4989 | update.InventoryData[i].ItemID, | ||
4990 | itemUpd); | ||
4991 | } | ||
4992 | } | ||
4993 | } | ||
4994 | //Console.WriteLine(Pack.ToString()); | ||
4995 | /*for (int i = 0; i < update.InventoryData.Length; i++) | ||
4996 | { | ||
4997 | if (update.InventoryData[i].TransactionID != LLUUID.Zero) | ||
4998 | { | ||
4999 | AssetBase asset = m_assetCache.GetAsset(update.InventoryData[i].TransactionID.Combine(this.SecureSessionId)); | ||
5000 | if (asset != null) | ||
5001 | { | ||
5002 | // Console.WriteLine("updating inventory item, found asset" + asset.FullID.ToString() + " already in cache"); | ||
5003 | m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset); | ||
5004 | } | ||
5005 | else | ||
5006 | { | ||
5007 | asset = this.UploadAssets.AddUploadToAssetCache(update.InventoryData[i].TransactionID); | ||
5008 | if (asset != null) | ||
5009 | { | ||
5010 | //Console.WriteLine("updating inventory item, adding asset" + asset.FullID.ToString() + " to cache"); | ||
5011 | m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset); | ||
5012 | } | ||
5013 | else | ||
5014 | { | ||
5015 | //Console.WriteLine("trying to update inventory item, but asset is null"); | ||
5016 | } | ||
5017 | } | ||
5018 | } | ||
5019 | else | ||
5020 | { | ||
5021 | m_inventoryCache.UpdateInventoryItemDetails(this, update.InventoryData[i].ItemID, update.InventoryData[i]); ; | ||
5022 | } | ||
5023 | }*/ | ||
5024 | break; | ||
5025 | case PacketType.CopyInventoryItem: | ||
5026 | CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; | ||
5027 | |||
5028 | handlerCopyInventoryItem = null; | ||
5029 | if (OnCopyInventoryItem != null) | ||
5030 | { | ||
5031 | foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) | ||
5032 | { | ||
5033 | handlerCopyInventoryItem = OnCopyInventoryItem; | ||
5034 | if (handlerCopyInventoryItem != null) | ||
5035 | { | ||
5036 | handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID, | ||
5037 | datablock.OldItemID, datablock.NewFolderID, | ||
5038 | Util.FieldToString(datablock.NewName)); | ||
5039 | } | ||
5040 | } | ||
5041 | } | ||
5042 | break; | ||
5043 | case PacketType.MoveInventoryItem: | ||
5044 | MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack; | ||
5045 | if (OnMoveInventoryItem != null) | ||
5046 | { | ||
5047 | handlerMoveInventoryItem = null; | ||
5048 | foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData) | ||
5049 | { | ||
5050 | handlerMoveInventoryItem = OnMoveInventoryItem; | ||
5051 | if (handlerMoveInventoryItem != null) | ||
5052 | { | ||
5053 | handlerMoveInventoryItem(this, datablock.FolderID, datablock.ItemID, datablock.Length, | ||
5054 | Util.FieldToString(datablock.NewName)); | ||
5055 | } | ||
5056 | } | ||
5057 | } | ||
5058 | break; | ||
5059 | case PacketType.RemoveInventoryItem: | ||
5060 | RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack; | ||
5061 | if (OnRemoveInventoryItem != null) | ||
5062 | { | ||
5063 | handlerRemoveInventoryItem = null; | ||
5064 | foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData) | ||
5065 | { | ||
5066 | handlerRemoveInventoryItem = OnRemoveInventoryItem; | ||
5067 | if (handlerRemoveInventoryItem != null) | ||
5068 | { | ||
5069 | handlerRemoveInventoryItem(this, datablock.ItemID); | ||
5070 | } | ||
5071 | } | ||
5072 | } | ||
5073 | break; | ||
5074 | case PacketType.RemoveInventoryFolder: | ||
5075 | RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack; | ||
5076 | if (OnRemoveInventoryFolder != null) | ||
5077 | { | ||
5078 | handlerRemoveInventoryFolder = null; | ||
5079 | foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData) | ||
5080 | { | ||
5081 | handlerRemoveInventoryFolder = OnRemoveInventoryFolder; | ||
5082 | |||
5083 | if (handlerRemoveInventoryFolder != null) | ||
5084 | { | ||
5085 | handlerRemoveInventoryFolder(this, datablock.FolderID); | ||
5086 | } | ||
5087 | } | ||
5088 | } | ||
5089 | break; | ||
5090 | case PacketType.RequestTaskInventory: | ||
5091 | RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack; | ||
5092 | |||
5093 | handlerRequestTaskInventory = OnRequestTaskInventory; | ||
5094 | if (handlerRequestTaskInventory != null) | ||
5095 | { | ||
5096 | handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID); | ||
5097 | } | ||
5098 | break; | ||
5099 | case PacketType.UpdateTaskInventory: | ||
5100 | UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack; | ||
5101 | if (OnUpdateTaskInventory != null) | ||
5102 | { | ||
5103 | if (updatetask.UpdateData.Key == 0) | ||
5104 | { | ||
5105 | handlerUpdateTaskInventory = OnUpdateTaskInventory; | ||
5106 | if (handlerUpdateTaskInventory != null) | ||
5107 | { | ||
5108 | TaskInventoryItem newTaskItem = new TaskInventoryItem(); | ||
5109 | newTaskItem.ItemID = updatetask.InventoryData.ItemID; | ||
5110 | newTaskItem.ParentID = updatetask.InventoryData.FolderID; | ||
5111 | newTaskItem.CreatorID = updatetask.InventoryData.CreatorID; | ||
5112 | newTaskItem.OwnerID = updatetask.InventoryData.OwnerID; | ||
5113 | newTaskItem.GroupID = updatetask.InventoryData.GroupID; | ||
5114 | newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask; | ||
5115 | newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask; | ||
5116 | newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; | ||
5117 | newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; | ||
5118 | newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; | ||
5119 | //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; | ||
5120 | newTaskItem.Type = updatetask.InventoryData.Type; | ||
5121 | newTaskItem.InvType = updatetask.InventoryData.InvType; | ||
5122 | newTaskItem.Flags = updatetask.InventoryData.Flags; | ||
5123 | //newTaskItem.SaleType=updatetask.InventoryData.SaleType; | ||
5124 | //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; | ||
5125 | newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); | ||
5126 | newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); | ||
5127 | newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; | ||
5128 | handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID, | ||
5129 | newTaskItem, updatetask.UpdateData.LocalID); | ||
5130 | } | ||
5131 | } | ||
5132 | } | ||
5133 | |||
5134 | break; | ||
5135 | |||
5136 | case PacketType.RemoveTaskInventory: | ||
5137 | |||
5138 | RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack; | ||
5139 | |||
5140 | handlerRemoveTaskItem = OnRemoveTaskItem; | ||
5141 | |||
5142 | if (handlerRemoveTaskItem != null) | ||
5143 | { | ||
5144 | handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); | ||
5145 | } | ||
5146 | |||
5147 | break; | ||
5148 | |||
5149 | case PacketType.MoveTaskInventory: | ||
5150 | |||
5151 | MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack; | ||
5152 | |||
5153 | handlerMoveTaskItem = OnMoveTaskItem; | ||
5154 | |||
5155 | if (handlerMoveTaskItem != null) | ||
5156 | { | ||
5157 | handlerMoveTaskItem( | ||
5158 | this, moveTaskInventoryPacket.AgentData.FolderID, | ||
5159 | moveTaskInventoryPacket.InventoryData.LocalID, | ||
5160 | moveTaskInventoryPacket.InventoryData.ItemID); | ||
5161 | } | ||
5162 | |||
5163 | break; | ||
5164 | |||
5165 | case PacketType.RezScript: | ||
5166 | |||
5167 | //Console.WriteLine(Pack.ToString()); | ||
5168 | RezScriptPacket rezScriptx = (RezScriptPacket)Pack; | ||
5169 | |||
5170 | handlerRezScript = OnRezScript; | ||
5171 | InventoryItemBase item = new InventoryItemBase(); | ||
5172 | item.ID = rezScriptx.InventoryBlock.ItemID; | ||
5173 | item.Folder = rezScriptx.InventoryBlock.FolderID; | ||
5174 | item.Creator = rezScriptx.InventoryBlock.CreatorID; | ||
5175 | item.Owner = rezScriptx.InventoryBlock.OwnerID; | ||
5176 | item.BasePermissions = rezScriptx.InventoryBlock.BaseMask; | ||
5177 | item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask; | ||
5178 | item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask; | ||
5179 | item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask; | ||
5180 | item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned; | ||
5181 | item.GroupID = rezScriptx.InventoryBlock.GroupID; | ||
5182 | item.AssetType = rezScriptx.InventoryBlock.Type; | ||
5183 | item.InvType = rezScriptx.InventoryBlock.InvType; | ||
5184 | item.Flags = rezScriptx.InventoryBlock.Flags; | ||
5185 | item.SaleType = rezScriptx.InventoryBlock.SaleType; | ||
5186 | item.SalePrice = rezScriptx.InventoryBlock.SalePrice; | ||
5187 | item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name); | ||
5188 | item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description); | ||
5189 | item.CreationDate = (int)rezScriptx.InventoryBlock.CreationDate; | ||
5190 | |||
5191 | if (handlerRezScript != null) | ||
5192 | { | ||
5193 | handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID); | ||
5194 | } | ||
5195 | break; | ||
5196 | |||
5197 | case PacketType.MapLayerRequest: | ||
5198 | RequestMapLayer(); | ||
5199 | break; | ||
5200 | case PacketType.MapBlockRequest: | ||
5201 | MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack; | ||
5202 | |||
5203 | handlerRequestMapBlocks = OnRequestMapBlocks; | ||
5204 | if (handlerRequestMapBlocks != null) | ||
5205 | { | ||
5206 | handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, | ||
5207 | MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags); | ||
5208 | } | ||
5209 | break; | ||
5210 | case PacketType.MapNameRequest: | ||
5211 | MapNameRequestPacket map = (MapNameRequestPacket)Pack; | ||
5212 | string mapName = UTF8Encoding.UTF8.GetString(map.NameData.Name, 0, | ||
5213 | map.NameData.Name.Length - 1); | ||
5214 | handlerMapNameRequest = OnMapNameRequest; | ||
5215 | if (handlerMapNameRequest != null) | ||
5216 | { | ||
5217 | handlerMapNameRequest(this, mapName); | ||
5218 | } | ||
5219 | break; | ||
5220 | case PacketType.TeleportLandmarkRequest: | ||
5221 | TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack; | ||
5222 | LLUUID lmid = tpReq.Info.LandmarkID; | ||
5223 | AssetLandmark lm; | ||
5224 | if (lmid != LLUUID.Zero) | ||
5225 | { | ||
5226 | AssetBase lma = m_assetCache.GetAsset(lmid, false); | ||
5227 | |||
5228 | if (lma == null) | ||
5229 | { | ||
5230 | // Failed to find landmark | ||
5231 | TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); | ||
5232 | tpCancel.Info.SessionID = tpReq.Info.SessionID; | ||
5233 | tpCancel.Info.AgentID = tpReq.Info.AgentID; | ||
5234 | OutPacket(tpCancel, ThrottleOutPacketType.Task); | ||
5235 | } | ||
5236 | |||
5237 | try | ||
5238 | { | ||
5239 | lm = new AssetLandmark(lma); | ||
5240 | } | ||
5241 | catch (NullReferenceException) | ||
5242 | { | ||
5243 | // asset not found generates null ref inside the assetlandmark constructor. | ||
5244 | TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); | ||
5245 | tpCancel.Info.SessionID = tpReq.Info.SessionID; | ||
5246 | tpCancel.Info.AgentID = tpReq.Info.AgentID; | ||
5247 | OutPacket(tpCancel, ThrottleOutPacketType.Task); | ||
5248 | break; | ||
5249 | } | ||
5250 | } | ||
5251 | else | ||
5252 | { | ||
5253 | // Teleport home request | ||
5254 | handlerTeleportHomeRequest = OnTeleportHomeRequest; | ||
5255 | if (handlerTeleportHomeRequest != null) | ||
5256 | { | ||
5257 | handlerTeleportHomeRequest(this.AgentId, this); | ||
5258 | } | ||
5259 | break; | ||
5260 | } | ||
5261 | |||
5262 | handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; | ||
5263 | if (handlerTeleportLandmarkRequest != null) | ||
5264 | { | ||
5265 | handlerTeleportLandmarkRequest(this, lm.RegionHandle, lm.Position); | ||
5266 | } | ||
5267 | else | ||
5268 | { | ||
5269 | //no event handler so cancel request | ||
5270 | |||
5271 | |||
5272 | TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); | ||
5273 | tpCancel.Info.AgentID = tpReq.Info.AgentID; | ||
5274 | tpCancel.Info.SessionID = tpReq.Info.SessionID; | ||
5275 | OutPacket(tpCancel, ThrottleOutPacketType.Task); | ||
5276 | |||
5277 | } | ||
5278 | break; | ||
5279 | case PacketType.TeleportLocationRequest: | ||
5280 | TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; | ||
5281 | // Console.WriteLine(tpLocReq.ToString()); | ||
5282 | |||
5283 | handlerTeleportLocationRequest = OnTeleportLocationRequest; | ||
5284 | if (handlerTeleportLocationRequest != null) | ||
5285 | { | ||
5286 | handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, | ||
5287 | tpLocReq.Info.LookAt, 16); | ||
5288 | } | ||
5289 | else | ||
5290 | { | ||
5291 | //no event handler so cancel request | ||
5292 | TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); | ||
5293 | tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID; | ||
5294 | tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID; | ||
5295 | OutPacket(tpCancel, ThrottleOutPacketType.Task); | ||
5296 | } | ||
5297 | break; | ||
5298 | |||
5299 | #endregion | ||
5300 | |||
5301 | case PacketType.UUIDNameRequest: | ||
5302 | UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; | ||
5303 | foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) | ||
5304 | { | ||
5305 | handlerNameRequest = OnNameFromUUIDRequest; | ||
5306 | if (handlerNameRequest != null) | ||
5307 | { | ||
5308 | handlerNameRequest(UUIDBlock.ID, this); | ||
5309 | } | ||
5310 | } | ||
5311 | break; | ||
5312 | |||
5313 | #region Parcel related packets | ||
5314 | |||
5315 | case PacketType.ParcelAccessListRequest: | ||
5316 | ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack; | ||
5317 | |||
5318 | handlerParcelAccessListRequest = OnParcelAccessListRequest; | ||
5319 | |||
5320 | if (handlerParcelAccessListRequest != null) | ||
5321 | { | ||
5322 | handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID, | ||
5323 | requestPacket.Data.Flags, requestPacket.Data.SequenceID, | ||
5324 | requestPacket.Data.LocalID, this); | ||
5325 | } | ||
5326 | break; | ||
5327 | |||
5328 | case PacketType.ParcelAccessListUpdate: | ||
5329 | ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack; | ||
5330 | List<ParcelManager.ParcelAccessEntry> entries = new List<ParcelManager.ParcelAccessEntry>(); | ||
5331 | foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List) | ||
5332 | { | ||
5333 | ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); | ||
5334 | entry.AgentID = block.ID; | ||
5335 | entry.Flags = (ParcelManager.AccessList)block.Flags; | ||
5336 | entry.Time = new DateTime(); | ||
5337 | entries.Add(entry); | ||
5338 | } | ||
5339 | |||
5340 | handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest; | ||
5341 | if (handlerParcelAccessListUpdateRequest != null) | ||
5342 | { | ||
5343 | handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, | ||
5344 | updatePacket.AgentData.SessionID, updatePacket.Data.Flags, | ||
5345 | updatePacket.Data.LocalID, entries, this); | ||
5346 | } | ||
5347 | break; | ||
5348 | case PacketType.ParcelPropertiesRequest: | ||
5349 | |||
5350 | ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack; | ||
5351 | |||
5352 | handlerParcelPropertiesRequest = OnParcelPropertiesRequest; | ||
5353 | if (handlerParcelPropertiesRequest != null) | ||
5354 | { | ||
5355 | handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), | ||
5356 | (int)Math.Round(propertiesRequest.ParcelData.South), | ||
5357 | (int)Math.Round(propertiesRequest.ParcelData.East), | ||
5358 | (int)Math.Round(propertiesRequest.ParcelData.North), | ||
5359 | propertiesRequest.ParcelData.SequenceID, | ||
5360 | propertiesRequest.ParcelData.SnapSelection, this); | ||
5361 | } | ||
5362 | break; | ||
5363 | case PacketType.ParcelDivide: | ||
5364 | ParcelDividePacket landDivide = (ParcelDividePacket)Pack; | ||
5365 | |||
5366 | handlerParcelDivideRequest = OnParcelDivideRequest; | ||
5367 | if (handlerParcelDivideRequest != null) | ||
5368 | { | ||
5369 | handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West), | ||
5370 | (int)Math.Round(landDivide.ParcelData.South), | ||
5371 | (int)Math.Round(landDivide.ParcelData.East), | ||
5372 | (int)Math.Round(landDivide.ParcelData.North), this); | ||
5373 | } | ||
5374 | break; | ||
5375 | case PacketType.ParcelJoin: | ||
5376 | ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack; | ||
5377 | |||
5378 | handlerParcelJoinRequest = OnParcelJoinRequest; | ||
5379 | |||
5380 | if (handlerParcelJoinRequest != null) | ||
5381 | { | ||
5382 | handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West), | ||
5383 | (int)Math.Round(landJoin.ParcelData.South), | ||
5384 | (int)Math.Round(landJoin.ParcelData.East), | ||
5385 | (int)Math.Round(landJoin.ParcelData.North), this); | ||
5386 | } | ||
5387 | break; | ||
5388 | case PacketType.ParcelPropertiesUpdate: | ||
5389 | ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack; | ||
5390 | |||
5391 | handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest; | ||
5392 | |||
5393 | if (handlerParcelPropertiesUpdateRequest != null) | ||
5394 | { | ||
5395 | LandUpdateArgs args = new LandUpdateArgs(); | ||
5396 | |||
5397 | args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID; | ||
5398 | args.Category = (Parcel.ParcelCategory)parcelPropertiesPacket.ParcelData.Category; | ||
5399 | args.Desc = Helpers.FieldToUTF8String(parcelPropertiesPacket.ParcelData.Desc); | ||
5400 | args.GroupID = parcelPropertiesPacket.ParcelData.GroupID; | ||
5401 | args.LandingType = parcelPropertiesPacket.ParcelData.LandingType; | ||
5402 | args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale; | ||
5403 | args.MediaID = parcelPropertiesPacket.ParcelData.MediaID; | ||
5404 | args.MediaURL = Helpers.FieldToUTF8String(parcelPropertiesPacket.ParcelData.MediaURL); | ||
5405 | args.MusicURL = Helpers.FieldToUTF8String(parcelPropertiesPacket.ParcelData.MusicURL); | ||
5406 | args.Name = Helpers.FieldToUTF8String(parcelPropertiesPacket.ParcelData.Name); | ||
5407 | args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags; | ||
5408 | args.PassHours = parcelPropertiesPacket.ParcelData.PassHours; | ||
5409 | args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice; | ||
5410 | args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice; | ||
5411 | args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID; | ||
5412 | args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation; | ||
5413 | args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt; | ||
5414 | handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this); | ||
5415 | } | ||
5416 | break; | ||
5417 | case PacketType.ParcelSelectObjects: | ||
5418 | ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack; | ||
5419 | |||
5420 | handlerParcelSelectObjects = OnParcelSelectObjects; | ||
5421 | |||
5422 | if (handlerParcelSelectObjects != null) | ||
5423 | { | ||
5424 | handlerParcelSelectObjects(selectPacket.ParcelData.LocalID, | ||
5425 | Convert.ToInt32(selectPacket.ParcelData.ReturnType), this); | ||
5426 | } | ||
5427 | break; | ||
5428 | case PacketType.ParcelObjectOwnersRequest: | ||
5429 | //Console.WriteLine(Pack.ToString()); | ||
5430 | ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack; | ||
5431 | |||
5432 | handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest; | ||
5433 | |||
5434 | if (handlerParcelObjectOwnerRequest != null) | ||
5435 | { | ||
5436 | handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); | ||
5437 | } | ||
5438 | break; | ||
5439 | case PacketType.ParcelRelease: | ||
5440 | ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack; | ||
5441 | |||
5442 | handlerParcelAbandonRequest = OnParcelAbandonRequest; | ||
5443 | if (handlerParcelAbandonRequest != null) | ||
5444 | { | ||
5445 | handlerParcelAbandonRequest(releasePacket.Data.LocalID, this); | ||
5446 | } | ||
5447 | break; | ||
5448 | case PacketType.ParcelReclaim: | ||
5449 | ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack; | ||
5450 | |||
5451 | handlerParcelReclaim = OnParcelReclaim; | ||
5452 | if (handlerParcelReclaim != null) | ||
5453 | { | ||
5454 | handlerParcelReclaim(reclaimPacket.Data.LocalID, this); | ||
5455 | } | ||
5456 | break; | ||
5457 | case PacketType.ParcelReturnObjects: | ||
5458 | |||
5459 | |||
5460 | ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack; | ||
5461 | |||
5462 | LLUUID[] puserselectedOwnerIDs = new LLUUID[parcelReturnObjects.OwnerIDs.Length]; | ||
5463 | for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++) | ||
5464 | puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID; | ||
5465 | |||
5466 | LLUUID[] puserselectedTaskIDs = new LLUUID[parcelReturnObjects.TaskIDs.Length]; | ||
5467 | |||
5468 | for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++) | ||
5469 | puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID; | ||
5470 | |||
5471 | handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest; | ||
5472 | if (handlerParcelReturnObjectsRequest != null) | ||
5473 | { | ||
5474 | handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this); | ||
5475 | |||
5476 | } | ||
5477 | break; | ||
5478 | |||
5479 | #endregion | ||
5480 | |||
5481 | #region Estate Packets | ||
5482 | |||
5483 | case PacketType.EstateOwnerMessage: | ||
5484 | EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; | ||
5485 | |||
5486 | switch (Helpers.FieldToUTF8String(messagePacket.MethodData.Method)) | ||
5487 | { | ||
5488 | case "getinfo": | ||
5489 | |||
5490 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5491 | { | ||
5492 | OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice); | ||
5493 | } | ||
5494 | break; | ||
5495 | case "setregioninfo": | ||
5496 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5497 | { | ||
5498 | OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter), | ||
5499 | convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter), | ||
5500 | Convert.ToInt16(Convert.ToDecimal(Helpers.FieldToUTF8String(messagePacket.ParamList[4].Parameter))), | ||
5501 | (float)Convert.ToDecimal(Helpers.FieldToUTF8String(messagePacket.ParamList[5].Parameter)), | ||
5502 | Convert.ToInt16(Helpers.FieldToUTF8String(messagePacket.ParamList[6].Parameter)), | ||
5503 | convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); | ||
5504 | |||
5505 | } | ||
5506 | |||
5507 | break; | ||
5508 | // case "texturebase": | ||
5509 | // if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5510 | // { | ||
5511 | // foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) | ||
5512 | // { | ||
5513 | // string s = Helpers.FieldToUTF8String(block.Parameter); | ||
5514 | // string[] splitField = s.Split(' '); | ||
5515 | // if (splitField.Length == 2) | ||
5516 | // { | ||
5517 | // LLUUID tempUUID = new LLUUID(splitField[1]); | ||
5518 | // OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID); | ||
5519 | // } | ||
5520 | // } | ||
5521 | // } | ||
5522 | // break; | ||
5523 | case "texturedetail": | ||
5524 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5525 | { | ||
5526 | foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) | ||
5527 | { | ||
5528 | string s = Helpers.FieldToUTF8String(block.Parameter); | ||
5529 | string[] splitField = s.Split(' '); | ||
5530 | if (splitField.Length == 2) | ||
5531 | { | ||
5532 | Int16 corner = Convert.ToInt16(splitField[0]); | ||
5533 | LLUUID textureUUID = new LLUUID(splitField[1]); | ||
5534 | |||
5535 | OnSetEstateTerrainDetailTexture(this, corner, textureUUID); | ||
5536 | } | ||
5537 | } | ||
5538 | } | ||
5539 | |||
5540 | break; | ||
5541 | case "textureheights": | ||
5542 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5543 | { | ||
5544 | foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) | ||
5545 | { | ||
5546 | string s = Helpers.FieldToUTF8String(block.Parameter); | ||
5547 | string[] splitField = s.Split(' '); | ||
5548 | if (splitField.Length == 3) | ||
5549 | { | ||
5550 | Int16 corner = Convert.ToInt16(splitField[0]); | ||
5551 | float lowValue = (float)Convert.ToDecimal(splitField[1]); | ||
5552 | float highValue = (float)Convert.ToDecimal(splitField[2]); | ||
5553 | |||
5554 | OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue); | ||
5555 | } | ||
5556 | } | ||
5557 | } | ||
5558 | break; | ||
5559 | case "texturecommit": | ||
5560 | OnCommitEstateTerrainTextureRequest(this); | ||
5561 | break; | ||
5562 | case "setregionterrain": | ||
5563 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5564 | { | ||
5565 | if (messagePacket.ParamList.Length != 9) | ||
5566 | { | ||
5567 | m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length"); | ||
5568 | } | ||
5569 | else | ||
5570 | { | ||
5571 | try | ||
5572 | { | ||
5573 | string tmp; | ||
5574 | tmp = Helpers.FieldToUTF8String(messagePacket.ParamList[0].Parameter); | ||
5575 | if (!tmp.Contains(".")) tmp += ".00"; | ||
5576 | float WaterHeight = (float)Convert.ToDecimal(tmp); | ||
5577 | tmp = Helpers.FieldToUTF8String(messagePacket.ParamList[1].Parameter); | ||
5578 | if (!tmp.Contains(".")) tmp += ".00"; | ||
5579 | float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp); | ||
5580 | tmp = Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter); | ||
5581 | if (!tmp.Contains(".")) tmp += ".00"; | ||
5582 | float TerrainLowerLimit = (float)Convert.ToDecimal(tmp); | ||
5583 | bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter); | ||
5584 | bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter); | ||
5585 | float SunHour = (float)Convert.ToDecimal(Helpers.FieldToUTF8String(messagePacket.ParamList[5].Parameter)); | ||
5586 | bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter); | ||
5587 | bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter); | ||
5588 | float EstateSunHour = (float)Convert.ToDecimal(Helpers.FieldToUTF8String(messagePacket.ParamList[8].Parameter)); | ||
5589 | |||
5590 | OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour); | ||
5591 | |||
5592 | } | ||
5593 | catch (Exception ex) | ||
5594 | { | ||
5595 | m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket.ToString() + "\n" + ex.ToString()); | ||
5596 | } | ||
5597 | } | ||
5598 | } | ||
5599 | |||
5600 | break; | ||
5601 | case "restart": | ||
5602 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5603 | { | ||
5604 | // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart. | ||
5605 | foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) | ||
5606 | { | ||
5607 | float timeSeconds = 0; | ||
5608 | Helpers.TryParse(Helpers.FieldToUTF8String(block.Parameter), out timeSeconds); | ||
5609 | timeSeconds = (int)timeSeconds; | ||
5610 | OnEstateRestartSimRequest(this, (int)timeSeconds); | ||
5611 | |||
5612 | } | ||
5613 | } | ||
5614 | break; | ||
5615 | case "estatechangecovenantid": | ||
5616 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5617 | { | ||
5618 | foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) | ||
5619 | { | ||
5620 | LLUUID newCovenantID = new LLUUID(Helpers.FieldToUTF8String(block.Parameter)); | ||
5621 | OnEstateChangeCovenantRequest(this, newCovenantID); | ||
5622 | } | ||
5623 | } | ||
5624 | break; | ||
5625 | case "estateaccessdelta": // Estate access delta manages the banlist and allow list too. | ||
5626 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5627 | { | ||
5628 | int estateAccessType = Convert.ToInt16(Helpers.FieldToUTF8String(messagePacket.ParamList[1].Parameter)); | ||
5629 | OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new LLUUID(Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter))); | ||
5630 | |||
5631 | } | ||
5632 | break; | ||
5633 | case "simulatormessage": | ||
5634 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5635 | { | ||
5636 | LLUUID invoice = messagePacket.MethodData.Invoice; | ||
5637 | LLUUID SenderID = new LLUUID(Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter)); | ||
5638 | string SenderName = Helpers.FieldToUTF8String(messagePacket.ParamList[3].Parameter); | ||
5639 | string Message = Helpers.FieldToUTF8String(messagePacket.ParamList[4].Parameter); | ||
5640 | LLUUID sessionID = messagePacket.AgentData.SessionID; | ||
5641 | OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); | ||
5642 | } | ||
5643 | break; | ||
5644 | case "instantmessage": | ||
5645 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5646 | { | ||
5647 | if (messagePacket.ParamList.Length < 5) | ||
5648 | break; | ||
5649 | LLUUID invoice = messagePacket.MethodData.Invoice; | ||
5650 | LLUUID SenderID = new LLUUID(Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter)); | ||
5651 | string SenderName = Helpers.FieldToUTF8String(messagePacket.ParamList[3].Parameter); | ||
5652 | string Message = Helpers.FieldToUTF8String(messagePacket.ParamList[4].Parameter); | ||
5653 | LLUUID sessionID = messagePacket.AgentData.SessionID; | ||
5654 | OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); | ||
5655 | } | ||
5656 | break; | ||
5657 | case "setregiondebug": | ||
5658 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5659 | { | ||
5660 | LLUUID invoice = messagePacket.MethodData.Invoice; | ||
5661 | LLUUID SenderID = messagePacket.AgentData.AgentID; | ||
5662 | bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter); | ||
5663 | bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter); | ||
5664 | bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter); | ||
5665 | |||
5666 | OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics); | ||
5667 | } | ||
5668 | break; | ||
5669 | case "teleporthomeuser": | ||
5670 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5671 | { | ||
5672 | LLUUID invoice = messagePacket.MethodData.Invoice; | ||
5673 | LLUUID SenderID = messagePacket.AgentData.AgentID; | ||
5674 | LLUUID Prey = LLUUID.Zero; | ||
5675 | |||
5676 | Helpers.TryParse(Helpers.FieldToUTF8String(messagePacket.ParamList[1].Parameter), out Prey); | ||
5677 | |||
5678 | OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); | ||
5679 | } | ||
5680 | break; | ||
5681 | case "colliders": | ||
5682 | handlerLandStatRequest = OnLandStatRequest; | ||
5683 | if (handlerLandStatRequest != null) | ||
5684 | { | ||
5685 | handlerLandStatRequest(0, 1, 0, "", this); | ||
5686 | } | ||
5687 | break; | ||
5688 | case "scripts": | ||
5689 | handlerLandStatRequest = OnLandStatRequest; | ||
5690 | if (handlerLandStatRequest != null) | ||
5691 | { | ||
5692 | handlerLandStatRequest(0, 0, 0, "", this); | ||
5693 | } | ||
5694 | break; | ||
5695 | case "terrain": | ||
5696 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5697 | { | ||
5698 | handlerBakeTerrain = OnBakeTerrain; | ||
5699 | if (handlerBakeTerrain != null) | ||
5700 | { | ||
5701 | handlerBakeTerrain(this); | ||
5702 | } | ||
5703 | } | ||
5704 | break; | ||
5705 | |||
5706 | case "estatechangeinfo": | ||
5707 | if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId)) | ||
5708 | { | ||
5709 | LLUUID invoice = messagePacket.MethodData.Invoice; | ||
5710 | LLUUID SenderID = messagePacket.AgentData.AgentID; | ||
5711 | UInt32 param1 = Convert.ToUInt32(Helpers.FieldToUTF8String(messagePacket.ParamList[1].Parameter)); | ||
5712 | UInt32 param2 = Convert.ToUInt32(Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter)); | ||
5713 | |||
5714 | handlerEstateChangeInfo = OnEstateChangeInfo; | ||
5715 | if (handlerEstateChangeInfo != null) | ||
5716 | { | ||
5717 | handlerEstateChangeInfo(this, invoice, SenderID, param1, param2); | ||
5718 | } | ||
5719 | } | ||
5720 | break; | ||
5721 | |||
5722 | default: | ||
5723 | m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket.ToString()); | ||
5724 | break; | ||
5725 | } | ||
5726 | break; | ||
5727 | case PacketType.LandStatRequest: | ||
5728 | LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack; | ||
5729 | |||
5730 | handlerLandStatRequest = OnLandStatRequest; | ||
5731 | if (handlerLandStatRequest != null) | ||
5732 | { | ||
5733 | handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Helpers.FieldToUTF8String(lsrp.RequestData.Filter), this); | ||
5734 | } | ||
5735 | //int parcelID, uint reportType, uint requestflags, string filter | ||
5736 | |||
5737 | //lsrp.RequestData.ParcelLocalID; | ||
5738 | //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts | ||
5739 | //lsrp.RequestData.RequestFlags; | ||
5740 | //lsrp.RequestData.Filter; | ||
5741 | |||
5742 | break; | ||
5743 | |||
5744 | case PacketType.RequestRegionInfo: | ||
5745 | // RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData; | ||
5746 | |||
5747 | handlerRegionInfoRequest = OnRegionInfoRequest; | ||
5748 | if (handlerRegionInfoRequest != null) | ||
5749 | { | ||
5750 | handlerRegionInfoRequest(this); | ||
5751 | } | ||
5752 | break; | ||
5753 | case PacketType.EstateCovenantRequest: | ||
5754 | |||
5755 | // EstateCovenantRequestPacket.AgentDataBlock epack = | ||
5756 | // ((EstateCovenantRequestPacket)Pack).AgentData; | ||
5757 | |||
5758 | handlerEstateCovenantRequest = OnEstateCovenantRequest; | ||
5759 | if (handlerEstateCovenantRequest != null) | ||
5760 | { | ||
5761 | handlerEstateCovenantRequest(this); | ||
5762 | } | ||
5763 | break; | ||
5764 | |||
5765 | #endregion | ||
5766 | |||
5767 | #region GodPackets | ||
5768 | |||
5769 | case PacketType.RequestGodlikePowers: | ||
5770 | RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; | ||
5771 | RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; | ||
5772 | LLUUID token = rblock.Token; | ||
5773 | |||
5774 | RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; | ||
5775 | |||
5776 | handlerReqGodlikePowers = OnRequestGodlikePowers; | ||
5777 | |||
5778 | if (handlerReqGodlikePowers != null) | ||
5779 | { | ||
5780 | handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this); | ||
5781 | } | ||
5782 | |||
5783 | break; | ||
5784 | case PacketType.GodKickUser: | ||
5785 | m_log.Warn("[CLIENT]: unhandled GodKickUser packet"); | ||
5786 | |||
5787 | GodKickUserPacket gkupack = (GodKickUserPacket)Pack; | ||
5788 | |||
5789 | if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) | ||
5790 | { | ||
5791 | handlerGodKickUser = OnGodKickUser; | ||
5792 | if (handlerGodKickUser != null) | ||
5793 | { | ||
5794 | handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, | ||
5795 | gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason); | ||
5796 | } | ||
5797 | } | ||
5798 | else | ||
5799 | { | ||
5800 | SendAgentAlertMessage("Kick request denied", false); | ||
5801 | } | ||
5802 | //KickUserPacket kupack = new KickUserPacket(); | ||
5803 | //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo; | ||
5804 | |||
5805 | //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID; | ||
5806 | //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID; | ||
5807 | |||
5808 | //kupack.TargetBlock.TargetIP = (uint)0; | ||
5809 | //kupack.TargetBlock.TargetPort = (ushort)0; | ||
5810 | //kupack.UserInfo.Reason = gkupack.UserInfo.Reason; | ||
5811 | |||
5812 | //OutPacket(kupack, ThrottleOutPacketType.Task); | ||
5813 | break; | ||
5814 | |||
5815 | #endregion | ||
5816 | |||
5817 | #region Economy/Transaction Packets | ||
5818 | |||
5819 | case PacketType.MoneyBalanceRequest: | ||
5820 | MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; | ||
5821 | |||
5822 | handlerMoneyBalanceRequest = OnMoneyBalanceRequest; | ||
5823 | |||
5824 | if (handlerMoneyBalanceRequest != null) | ||
5825 | { | ||
5826 | handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); | ||
5827 | } | ||
5828 | |||
5829 | break; | ||
5830 | case PacketType.EconomyDataRequest: | ||
5831 | |||
5832 | handlerEconomoyDataRequest = OnEconomyDataRequest; | ||
5833 | if (handlerEconomoyDataRequest != null) | ||
5834 | { | ||
5835 | handlerEconomoyDataRequest(AgentId); | ||
5836 | } | ||
5837 | // TODO: handle this packet | ||
5838 | //m_log.Warn("[CLIENT]: unhandled EconomyDataRequest packet"); | ||
5839 | break; | ||
5840 | case PacketType.RequestPayPrice: | ||
5841 | RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; | ||
5842 | handlerRequestPayPrice = OnRequestPayPrice; | ||
5843 | if (handlerRequestPayPrice != null) | ||
5844 | { | ||
5845 | handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); | ||
5846 | } | ||
5847 | break; | ||
5848 | |||
5849 | #endregion | ||
5850 | |||
5851 | #region Script Packets | ||
5852 | |||
5853 | case PacketType.GetScriptRunning: | ||
5854 | GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; | ||
5855 | handlerGetScriptRunning = OnGetScriptRunning; | ||
5856 | if (handlerGetScriptRunning != null) | ||
5857 | { | ||
5858 | handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID); | ||
5859 | } | ||
5860 | break; | ||
5861 | |||
5862 | case PacketType.SetScriptRunning: | ||
5863 | SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack; | ||
5864 | handlerSetScriptRunning = OnSetScriptRunning; | ||
5865 | if (handlerSetScriptRunning != null) | ||
5866 | { | ||
5867 | handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running); | ||
5868 | } | ||
5869 | break; | ||
5870 | |||
5871 | case PacketType.ScriptReset: | ||
5872 | ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack; | ||
5873 | handlerScriptReset = OnScriptReset; | ||
5874 | if (handlerScriptReset != null) | ||
5875 | { | ||
5876 | handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID); | ||
5877 | } | ||
5878 | break; | ||
5879 | |||
5880 | #endregion | ||
5881 | |||
5882 | #region unimplemented handlers | ||
5883 | |||
5884 | case PacketType.StartPingCheck: | ||
5885 | // Send the client the ping response back | ||
5886 | // Pass the same PingID in the matching packet | ||
5887 | // Handled In the packet processing | ||
5888 | //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet"); | ||
5889 | break; | ||
5890 | case PacketType.CompletePingCheck: | ||
5891 | // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client | ||
5892 | //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet"); | ||
5893 | break; | ||
5894 | |||
5895 | case PacketType.ViewerStats: | ||
5896 | // TODO: handle this packet | ||
5897 | m_log.Warn("[CLIENT]: unhandled ViewerStats packet"); | ||
5898 | break; | ||
5899 | |||
5900 | case PacketType.CreateGroupRequest: | ||
5901 | // TODO: handle this packet | ||
5902 | m_log.Warn("[CLIENT]: unhandled CreateGroupRequest packet"); | ||
5903 | break; | ||
5904 | //case PacketType.GenericMessage: | ||
5905 | // TODO: handle this packet | ||
5906 | //m_log.Warn("[CLIENT]: unhandled GenericMessage packet"); | ||
5907 | //break; | ||
5908 | case PacketType.MapItemRequest: | ||
5909 | // TODO: handle this packet | ||
5910 | m_log.Warn("[CLIENT]: unhandled MapItemRequest packet"); | ||
5911 | break; | ||
5912 | case PacketType.TransferAbort: | ||
5913 | // TODO: handle this packet | ||
5914 | m_log.Warn("[CLIENT]: unhandled TransferAbort packet"); | ||
5915 | break; | ||
5916 | case PacketType.MuteListRequest: | ||
5917 | // TODO: handle this packet | ||
5918 | m_log.Warn("[CLIENT]: unhandled MuteListRequest packet"); | ||
5919 | break; | ||
5920 | case PacketType.ParcelDwellRequest: | ||
5921 | // TODO: handle this packet | ||
5922 | m_log.Warn("[CLIENT]: unhandled ParcelDwellRequest packet"); | ||
5923 | break; | ||
5924 | case PacketType.UseCircuitCode: | ||
5925 | // TODO: Don't display this one, we handle it at a lower level | ||
5926 | //m_log.Warn("[CLIENT]: unhandled UseCircuitCode packet"); | ||
5927 | break; | ||
5928 | |||
5929 | case PacketType.AgentHeightWidth: | ||
5930 | // TODO: handle this packet | ||
5931 | m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet"); | ||
5932 | break; | ||
5933 | case PacketType.ObjectSpinStop: | ||
5934 | // TODO: handle this packet | ||
5935 | m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet"); | ||
5936 | break; | ||
5937 | case PacketType.SoundTrigger: | ||
5938 | // TODO: handle this packet | ||
5939 | m_log.Warn("[CLIENT]: unhandled SoundTrigger packet"); | ||
5940 | break; | ||
5941 | case PacketType.InventoryDescendents: | ||
5942 | // TODO: handle this packet | ||
5943 | m_log.Warn("[CLIENT]: unhandled InventoryDescent packet"); | ||
5944 | break; | ||
5945 | default: | ||
5946 | m_log.Warn("[CLIENT]: unhandled packet " + Pack.ToString()); | ||
5947 | break; | ||
5948 | |||
5949 | #endregion | ||
5950 | } | ||
5951 | } | ||
5952 | |||
5953 | PacketPool.Instance.ReturnPacket(Pack); | ||
5954 | } | ||
5955 | |||
5956 | private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) | ||
5957 | { | ||
5958 | PrimitiveBaseShape shape = new PrimitiveBaseShape(); | ||
5959 | |||
5960 | shape.PCode = addPacket.ObjectData.PCode; | ||
5961 | shape.State = addPacket.ObjectData.State; | ||
5962 | shape.PathBegin = addPacket.ObjectData.PathBegin; | ||
5963 | shape.PathEnd = addPacket.ObjectData.PathEnd; | ||
5964 | shape.PathScaleX = addPacket.ObjectData.PathScaleX; | ||
5965 | shape.PathScaleY = addPacket.ObjectData.PathScaleY; | ||
5966 | shape.PathShearX = addPacket.ObjectData.PathShearX; | ||
5967 | shape.PathShearY = addPacket.ObjectData.PathShearY; | ||
5968 | shape.PathSkew = addPacket.ObjectData.PathSkew; | ||
5969 | shape.ProfileBegin = addPacket.ObjectData.ProfileBegin; | ||
5970 | shape.ProfileEnd = addPacket.ObjectData.ProfileEnd; | ||
5971 | shape.Scale = addPacket.ObjectData.Scale; | ||
5972 | shape.PathCurve = addPacket.ObjectData.PathCurve; | ||
5973 | shape.ProfileCurve = addPacket.ObjectData.ProfileCurve; | ||
5974 | shape.ProfileHollow = addPacket.ObjectData.ProfileHollow; | ||
5975 | shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset; | ||
5976 | shape.PathRevolutions = addPacket.ObjectData.PathRevolutions; | ||
5977 | shape.PathTaperX = addPacket.ObjectData.PathTaperX; | ||
5978 | shape.PathTaperY = addPacket.ObjectData.PathTaperY; | ||
5979 | shape.PathTwist = addPacket.ObjectData.PathTwist; | ||
5980 | shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin; | ||
5981 | LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("89556747-24cb-43ed-920b-47caed15465f")); | ||
5982 | shape.TextureEntry = ntex.ToBytes(); | ||
5983 | //shape.Textures = ntex; | ||
5984 | return shape; | ||
5985 | } | ||
5986 | |||
5987 | /// <summary> | ||
5988 | /// Send the client an Estate message blue box pop-down with a single OK button | ||
5989 | /// </summary> | ||
5990 | /// <param name="FromAvatarID"></param> | ||
5991 | /// <param name="fromSessionID"></param> | ||
5992 | /// <param name="FromAvatarName"></param> | ||
5993 | /// <param name="Message"></param> | ||
5994 | public void SendBlueBoxMessage(LLUUID FromAvatarID, LLUUID fromSessionID, String FromAvatarName, String Message) | ||
5995 | { | ||
5996 | if (!ChildAgentStatus()) | ||
5997 | SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)1, (uint)Util.UnixTimeSinceEpoch()); | ||
5998 | |||
5999 | //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); | ||
6000 | } | ||
6001 | |||
6002 | public void SendLogoutPacket() | ||
6003 | { | ||
6004 | LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply); | ||
6005 | // TODO: don't create new blocks if recycling an old packet | ||
6006 | logReply.AgentData.AgentID = AgentId; | ||
6007 | logReply.AgentData.SessionID = SessionId; | ||
6008 | logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; | ||
6009 | logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); | ||
6010 | logReply.InventoryData[0].ItemID = LLUUID.Zero; | ||
6011 | |||
6012 | OutPacket(logReply, ThrottleOutPacketType.Task); | ||
6013 | } | ||
6014 | |||
6015 | public void SendHealth(float health) | ||
6016 | { | ||
6017 | HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage); | ||
6018 | healthpacket.HealthData.Health = health; | ||
6019 | OutPacket(healthpacket, ThrottleOutPacketType.Task); | ||
6020 | } | ||
6021 | |||
6022 | public void SendAgentOnline(LLUUID[] agentIDs) | ||
6023 | { | ||
6024 | OnlineNotificationPacket onp = new OnlineNotificationPacket(); | ||
6025 | OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length]; | ||
6026 | for (int i = 0; i < agentIDs.Length; i++) | ||
6027 | { | ||
6028 | OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); | ||
6029 | onpbl.AgentID = agentIDs[i]; | ||
6030 | onpb[i] = onpbl; | ||
6031 | } | ||
6032 | onp.AgentBlock = onpb; | ||
6033 | onp.Header.Reliable = true; | ||
6034 | OutPacket(onp, ThrottleOutPacketType.Task); | ||
6035 | } | ||
6036 | |||
6037 | public void SendAgentOffline(LLUUID[] agentIDs) | ||
6038 | { | ||
6039 | OfflineNotificationPacket offp = new OfflineNotificationPacket(); | ||
6040 | OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length]; | ||
6041 | for (int i = 0; i < agentIDs.Length; i++) | ||
6042 | { | ||
6043 | OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock(); | ||
6044 | onpbl.AgentID = agentIDs[i]; | ||
6045 | offpb[i] = onpbl; | ||
6046 | } | ||
6047 | offp.AgentBlock = offpb; | ||
6048 | offp.Header.Reliable = true; | ||
6049 | OutPacket(offp, ThrottleOutPacketType.Task); | ||
6050 | } | ||
6051 | |||
6052 | public void SendSitResponse(LLUUID TargetID, LLVector3 OffsetPos, LLQuaternion SitOrientation, bool autopilot, | ||
6053 | LLVector3 CameraAtOffset, LLVector3 CameraEyeOffset, bool ForceMouseLook) | ||
6054 | { | ||
6055 | AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); | ||
6056 | avatarSitResponse.SitObject.ID = TargetID; | ||
6057 | if (CameraAtOffset != LLVector3.Zero) | ||
6058 | { | ||
6059 | avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; | ||
6060 | avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; | ||
6061 | } | ||
6062 | avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; | ||
6063 | avatarSitResponse.SitTransform.AutoPilot = autopilot; | ||
6064 | avatarSitResponse.SitTransform.SitPosition = OffsetPos; | ||
6065 | avatarSitResponse.SitTransform.SitRotation = SitOrientation; | ||
6066 | |||
6067 | OutPacket(avatarSitResponse, ThrottleOutPacketType.Task); | ||
6068 | } | ||
6069 | |||
6070 | public void SendAdminResponse(LLUUID Token, uint AdminLevel) | ||
6071 | { | ||
6072 | GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket(); | ||
6073 | GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock(); | ||
6074 | GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock(); | ||
6075 | |||
6076 | adb.AgentID = AgentId; | ||
6077 | adb.SessionID = SessionId; // More security | ||
6078 | gdb.GodLevel = (byte)AdminLevel; | ||
6079 | gdb.Token = Token; | ||
6080 | //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock; | ||
6081 | respondPacket.GrantData = gdb; | ||
6082 | respondPacket.AgentData = adb; | ||
6083 | OutPacket(respondPacket, ThrottleOutPacketType.Task); | ||
6084 | } | ||
6085 | |||
6086 | public void SendGroupMembership(GroupData[] GroupMembership) | ||
6087 | { | ||
6088 | AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket(); | ||
6089 | AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length]; | ||
6090 | for (int i = 0; i < GroupMembership.Length; i++) | ||
6091 | { | ||
6092 | AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock(); | ||
6093 | Group.AcceptNotices = GroupMembership[i].AcceptNotices; | ||
6094 | Group.Contribution = GroupMembership[i].contribution; | ||
6095 | Group.GroupID = GroupMembership[i].GroupID; | ||
6096 | Group.GroupInsigniaID = GroupMembership[i].GroupPicture; | ||
6097 | Group.GroupName = Helpers.StringToField(GroupMembership[i].groupName); | ||
6098 | Group.GroupPowers = GroupMembership[i].groupPowers; | ||
6099 | Groups[i] = Group; | ||
6100 | Groupupdate.GroupData = Groups; | ||
6101 | |||
6102 | } | ||
6103 | Groupupdate.AgentData.AgentID = AgentId; | ||
6104 | OutPacket(Groupupdate, ThrottleOutPacketType.Task); | ||
6105 | |||
6106 | } | ||
6107 | public void SendGroupNameReply(LLUUID groupLLUID, string GroupName) | ||
6108 | { | ||
6109 | UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket(); | ||
6110 | UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; | ||
6111 | UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); | ||
6112 | uidnamebloc.ID = groupLLUID; | ||
6113 | uidnamebloc.GroupName = Helpers.StringToField(GroupName); | ||
6114 | uidnameblock[0] = uidnamebloc; | ||
6115 | pack.UUIDNameBlock = uidnameblock; | ||
6116 | OutPacket(pack, ThrottleOutPacketType.Task); | ||
6117 | } | ||
6118 | |||
6119 | public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) | ||
6120 | { | ||
6121 | LandStatReplyPacket lsrp = new LandStatReplyPacket(); | ||
6122 | // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock(); | ||
6123 | LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length]; | ||
6124 | //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); | ||
6125 | // lsrepdb. | ||
6126 | lsrp.RequestData.ReportType = reportType; | ||
6127 | lsrp.RequestData.RequestFlags = requestFlags; | ||
6128 | lsrp.RequestData.TotalObjectCount = resultCount; | ||
6129 | for (int i = 0; i < lsrpia.Length; i++) | ||
6130 | { | ||
6131 | LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); | ||
6132 | lsrepdb.LocationX = lsrpia[i].LocationX; | ||
6133 | lsrepdb.LocationY = lsrpia[i].LocationY; | ||
6134 | lsrepdb.LocationZ = lsrpia[i].LocationZ; | ||
6135 | lsrepdb.Score = lsrpia[i].Score; | ||
6136 | lsrepdb.TaskID = lsrpia[i].TaskID; | ||
6137 | lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; | ||
6138 | lsrepdb.TaskName = Helpers.StringToField(lsrpia[i].TaskName); | ||
6139 | lsrepdb.OwnerName = Helpers.StringToField(lsrpia[i].OwnerName); | ||
6140 | lsrepdba[i] = lsrepdb; | ||
6141 | } | ||
6142 | lsrp.ReportData = lsrepdba; | ||
6143 | OutPacket(lsrp, ThrottleOutPacketType.Task); | ||
6144 | } | ||
6145 | |||
6146 | public void SendScriptRunningReply(LLUUID objectID, LLUUID itemID, bool running) | ||
6147 | { | ||
6148 | ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket(); | ||
6149 | scriptRunningReply.Script.ObjectID = objectID; | ||
6150 | scriptRunningReply.Script.ItemID = itemID; | ||
6151 | scriptRunningReply.Script.Running = running; | ||
6152 | |||
6153 | OutPacket(scriptRunningReply, ThrottleOutPacketType.Task); | ||
6154 | } | ||
6155 | |||
6156 | public void SendAsset(AssetRequestToClient req) | ||
6157 | { | ||
6158 | |||
6159 | //Console.WriteLine("sending asset " + req.RequestAssetID); | ||
6160 | TransferInfoPacket Transfer = new TransferInfoPacket(); | ||
6161 | Transfer.TransferInfo.ChannelType = 2; | ||
6162 | Transfer.TransferInfo.Status = 0; | ||
6163 | Transfer.TransferInfo.TargetType = 0; | ||
6164 | if (req.AssetRequestSource == 2) | ||
6165 | { | ||
6166 | Transfer.TransferInfo.Params = new byte[20]; | ||
6167 | Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); | ||
6168 | int assType = (int)req.AssetInf.Type; | ||
6169 | Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); | ||
6170 | } | ||
6171 | else if (req.AssetRequestSource == 3) | ||
6172 | { | ||
6173 | Transfer.TransferInfo.Params = req.Params; | ||
6174 | // Transfer.TransferInfo.Params = new byte[100]; | ||
6175 | //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); | ||
6176 | //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); | ||
6177 | } | ||
6178 | Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length; | ||
6179 | Transfer.TransferInfo.TransferID = req.TransferRequestID; | ||
6180 | Transfer.Header.Zerocoded = true; | ||
6181 | OutPacket(Transfer, ThrottleOutPacketType.Asset); | ||
6182 | |||
6183 | if (req.NumPackets == 1) | ||
6184 | { | ||
6185 | TransferPacketPacket TransferPacket = new TransferPacketPacket(); | ||
6186 | TransferPacket.TransferData.Packet = 0; | ||
6187 | TransferPacket.TransferData.ChannelType = 2; | ||
6188 | TransferPacket.TransferData.TransferID = req.TransferRequestID; | ||
6189 | TransferPacket.TransferData.Data = req.AssetInf.Data; | ||
6190 | TransferPacket.TransferData.Status = 1; | ||
6191 | TransferPacket.Header.Zerocoded = true; | ||
6192 | OutPacket(TransferPacket, ThrottleOutPacketType.Asset); | ||
6193 | } | ||
6194 | else | ||
6195 | { | ||
6196 | int processedLength = 0; | ||
6197 | // libsecondlife hardcodes 1500 as the maximum data chunk size | ||
6198 | int maxChunkSize = 1250; | ||
6199 | int packetNumber = 0; | ||
6200 | |||
6201 | while (processedLength < req.AssetInf.Data.Length) | ||
6202 | { | ||
6203 | TransferPacketPacket TransferPacket = new TransferPacketPacket(); | ||
6204 | TransferPacket.TransferData.Packet = packetNumber; | ||
6205 | TransferPacket.TransferData.ChannelType = 2; | ||
6206 | TransferPacket.TransferData.TransferID = req.TransferRequestID; | ||
6207 | |||
6208 | int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); | ||
6209 | byte[] chunk = new byte[chunkSize]; | ||
6210 | Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); | ||
6211 | |||
6212 | TransferPacket.TransferData.Data = chunk; | ||
6213 | |||
6214 | // 0 indicates more packets to come, 1 indicates last packet | ||
6215 | if (req.AssetInf.Data.Length - processedLength > maxChunkSize) | ||
6216 | { | ||
6217 | TransferPacket.TransferData.Status = 0; | ||
6218 | } | ||
6219 | else | ||
6220 | { | ||
6221 | TransferPacket.TransferData.Status = 1; | ||
6222 | } | ||
6223 | TransferPacket.Header.Zerocoded = true; | ||
6224 | OutPacket(TransferPacket, ThrottleOutPacketType.Asset); | ||
6225 | |||
6226 | processedLength += chunkSize; | ||
6227 | packetNumber++; | ||
6228 | } | ||
6229 | } | ||
6230 | } | ||
6231 | |||
6232 | public void SendTexture(AssetBase TextureAsset) | ||
6233 | { | ||
6234 | |||
6235 | } | ||
6236 | |||
6237 | public ClientInfo GetClientInfo() | ||
6238 | { | ||
6239 | ClientInfo info = m_PacketHandler.GetClientInfo(); | ||
6240 | |||
6241 | info.userEP = this.m_userEndPoint; | ||
6242 | info.proxyEP = this.m_proxyEndPoint; | ||
6243 | info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); | ||
6244 | |||
6245 | return info; | ||
6246 | } | ||
6247 | |||
6248 | public void SetClientInfo(ClientInfo info) | ||
6249 | { | ||
6250 | m_PacketHandler.SetClientInfo(info); | ||
6251 | } | ||
6252 | |||
6253 | #region Media Parcel Members | ||
6254 | |||
6255 | public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) | ||
6256 | { | ||
6257 | ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket(); | ||
6258 | commandMessagePacket.CommandBlock.Flags = (uint) flags; | ||
6259 | commandMessagePacket.CommandBlock.Command =(uint) command; | ||
6260 | commandMessagePacket.CommandBlock.Time = time; | ||
6261 | |||
6262 | OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); | ||
6263 | } | ||
6264 | |||
6265 | public void SendParcelMediaUpdate(string mediaUrl, LLUUID mediaTextureID, | ||
6266 | byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight, | ||
6267 | byte mediaLoop) | ||
6268 | { | ||
6269 | ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); | ||
6270 | updatePacket.DataBlock.MediaURL = Helpers.StringToField(mediaUrl); | ||
6271 | updatePacket.DataBlock.MediaID = mediaTextureID; | ||
6272 | updatePacket.DataBlock.MediaAutoScale = autoScale; | ||
6273 | |||
6274 | updatePacket.DataBlockExtended.MediaType = Helpers.StringToField(mediaType); | ||
6275 | updatePacket.DataBlockExtended.MediaDesc = Helpers.StringToField(mediaDesc); | ||
6276 | updatePacket.DataBlockExtended.MediaWidth = mediaWidth; | ||
6277 | updatePacket.DataBlockExtended.MediaWidth = mediaHeight; | ||
6278 | updatePacket.DataBlockExtended.MediaLoop = mediaLoop; | ||
6279 | |||
6280 | OutPacket(updatePacket, ThrottleOutPacketType.Unknown); | ||
6281 | } | ||
6282 | |||
6283 | #endregion | ||
6284 | |||
6285 | |||
6286 | #region Camera | ||
6287 | |||
6288 | public void SendSetFollowCamProperties (LLUUID objectID, SortedDictionary<int, float> parameters) | ||
6289 | { | ||
6290 | SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties); | ||
6291 | packet.ObjectData.ObjectID = objectID; | ||
6292 | SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count]; | ||
6293 | uint idx = 0; | ||
6294 | foreach (KeyValuePair<int, float> pair in parameters) | ||
6295 | { | ||
6296 | SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock(); | ||
6297 | block.Type = pair.Key; | ||
6298 | block.Value = pair.Value; | ||
6299 | |||
6300 | camPropBlock[idx++] = block; | ||
6301 | } | ||
6302 | packet.CameraProperty = camPropBlock; | ||
6303 | OutPacket(packet, ThrottleOutPacketType.Task); | ||
6304 | } | ||
6305 | |||
6306 | public void SendClearFollowCamProperties (LLUUID objectID) | ||
6307 | { | ||
6308 | ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); | ||
6309 | packet.ObjectData.ObjectID = objectID; | ||
6310 | OutPacket(packet, ThrottleOutPacketType.Task); | ||
6311 | } | ||
6312 | |||
6313 | #endregion | ||
6314 | } | ||
6315 | } | ||
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketHandler.cs deleted file mode 100644 index 342dd5c..0000000 --- a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketHandler.cs +++ /dev/null | |||
@@ -1,702 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.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; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Net; | ||
32 | using System.Net.Sockets; | ||
33 | using System.Timers; | ||
34 | using libsecondlife; | ||
35 | using libsecondlife.Packets; | ||
36 | using Timer = System.Timers.Timer; | ||
37 | using OpenSim.Framework; | ||
38 | |||
39 | namespace OpenSim.Region.ClientStack.FunSLUDP | ||
40 | { | ||
41 | public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes); | ||
42 | public delegate void PacketDrop(Packet pack, Object id); | ||
43 | public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, LLUUID agentID, ThrottleOutPacketType throttlePacketType); | ||
44 | |||
45 | public interface IPacketHandler | ||
46 | { | ||
47 | event PacketStats OnPacketStats; | ||
48 | event PacketDrop OnPacketDrop; | ||
49 | SynchronizeClientHandler SynchronizeClient { set; } | ||
50 | |||
51 | int PacketsReceived { get; } | ||
52 | int PacketsReceivedReported { get; } | ||
53 | uint SilenceLimit { get; set; } | ||
54 | uint DiscardTimeout { get; set; } | ||
55 | uint ResendTimeout { get; set; } | ||
56 | |||
57 | void InPacket(Packet packet); | ||
58 | void ProcessInPacket(Packet packet); | ||
59 | void OutPacket(Packet NewPack, | ||
60 | ThrottleOutPacketType throttlePacketType); | ||
61 | void OutPacket(Packet NewPack, | ||
62 | ThrottleOutPacketType throttlePacketType, Object id); | ||
63 | LLPacketQueue PacketQueue { get; } | ||
64 | void Stop(); | ||
65 | void Flush(); | ||
66 | void Clear(); | ||
67 | ClientInfo GetClientInfo(); | ||
68 | void SetClientInfo(ClientInfo info); | ||
69 | void AddImportantPacket(PacketType type); | ||
70 | void RemoveImportantPacket(PacketType type); | ||
71 | } | ||
72 | |||
73 | public class LLPacketHandler : IPacketHandler | ||
74 | { | ||
75 | // Packet queues | ||
76 | // | ||
77 | LLPacketQueue m_PacketQueue; | ||
78 | |||
79 | public LLPacketQueue PacketQueue | ||
80 | { | ||
81 | get { return m_PacketQueue; } | ||
82 | } | ||
83 | |||
84 | // Timer to run stats and acks on | ||
85 | // | ||
86 | private Timer m_AckTimer = new Timer(250); | ||
87 | |||
88 | // A list of the packets we haven't acked yet | ||
89 | // | ||
90 | private Dictionary<uint,uint> m_PendingAcks = new Dictionary<uint,uint>(); | ||
91 | // Dictionary of the packets that need acks from the client. | ||
92 | // | ||
93 | private class AckData | ||
94 | { | ||
95 | public AckData(Packet packet, Object identifier) | ||
96 | { | ||
97 | Packet = packet; | ||
98 | Identifier = identifier; | ||
99 | } | ||
100 | |||
101 | public Packet Packet; | ||
102 | public Object Identifier; | ||
103 | } | ||
104 | private Dictionary<uint, AckData> m_NeedAck = | ||
105 | new Dictionary<uint, AckData>(); | ||
106 | |||
107 | private uint m_ResendTimeout = 1000; | ||
108 | |||
109 | public uint ResendTimeout | ||
110 | { | ||
111 | get { return m_ResendTimeout; } | ||
112 | set { m_ResendTimeout = value; } | ||
113 | } | ||
114 | |||
115 | private uint m_DiscardTimeout = 8000; | ||
116 | |||
117 | public uint DiscardTimeout | ||
118 | { | ||
119 | get { return m_DiscardTimeout; } | ||
120 | set { m_DiscardTimeout = value; } | ||
121 | } | ||
122 | |||
123 | private uint m_SilenceLimit = 250; | ||
124 | |||
125 | public uint SilenceLimit | ||
126 | { | ||
127 | get { return m_SilenceLimit; } | ||
128 | set { m_SilenceLimit = value; } | ||
129 | } | ||
130 | |||
131 | private int m_LastAck = 0; | ||
132 | |||
133 | // Track duplicated packets. This uses a Dictionary. Both insertion | ||
134 | // and lookup are common operations and need to take advantage of | ||
135 | // the hashing. Expiration is less common and can be allowed the | ||
136 | // time for a linear scan. | ||
137 | // | ||
138 | private Dictionary<uint, int> m_DupeTracker = | ||
139 | new Dictionary<uint, int>(); | ||
140 | //private uint m_DupeTrackerWindow = 30; | ||
141 | |||
142 | // Values for the SimStatsReporter | ||
143 | // | ||
144 | private int m_PacketsReceived = 0; | ||
145 | private int m_PacketsReceivedReported = 0; | ||
146 | private int m_PacketsSent = 0; | ||
147 | private int m_PacketsSentReported = 0; | ||
148 | private int m_UnackedBytes = 0; | ||
149 | |||
150 | public int PacketsReceived | ||
151 | { | ||
152 | get { return m_PacketsReceived; } | ||
153 | } | ||
154 | |||
155 | public int PacketsReceivedReported | ||
156 | { | ||
157 | get { return m_PacketsReceivedReported; } | ||
158 | } | ||
159 | |||
160 | // The client we are working for | ||
161 | // | ||
162 | private IClientAPI m_Client; | ||
163 | |||
164 | // Some events | ||
165 | // | ||
166 | public event PacketStats OnPacketStats; | ||
167 | public event PacketDrop OnPacketDrop; | ||
168 | |||
169 | private SynchronizeClientHandler m_SynchronizeClient = null; | ||
170 | |||
171 | public SynchronizeClientHandler SynchronizeClient | ||
172 | { | ||
173 | set { m_SynchronizeClient = value; } | ||
174 | } | ||
175 | |||
176 | // Packet sequencing | ||
177 | // | ||
178 | private uint m_Sequence = 0; | ||
179 | private object m_SequenceLock = new object(); | ||
180 | private const int MAX_SEQUENCE = 0xFFFFFF; | ||
181 | |||
182 | List<PacketType> m_ImportantPackets = new List<PacketType>(); | ||
183 | |||
184 | //////////////////////////////////////////////////////////////////// | ||
185 | |||
186 | // Constructors | ||
187 | // | ||
188 | public LLPacketHandler(IClientAPI client) | ||
189 | { | ||
190 | m_Client = client; | ||
191 | |||
192 | m_PacketQueue = new LLPacketQueue(client.AgentId); | ||
193 | |||
194 | m_AckTimer.Elapsed += AckTimerElapsed; | ||
195 | m_AckTimer.Start(); | ||
196 | } | ||
197 | |||
198 | public void Stop() | ||
199 | { | ||
200 | m_AckTimer.Stop(); | ||
201 | |||
202 | m_PacketQueue.Enqueue(null); | ||
203 | } | ||
204 | |||
205 | // Send one packet. This actually doesn't send anything, it queues | ||
206 | // it. Designed to be fire-and-forget, but there is an optional | ||
207 | // notifier. | ||
208 | // | ||
209 | public void OutPacket( | ||
210 | Packet packet, ThrottleOutPacketType throttlePacketType) | ||
211 | { | ||
212 | OutPacket(packet, throttlePacketType, null); | ||
213 | } | ||
214 | |||
215 | public void OutPacket( | ||
216 | Packet packet, ThrottleOutPacketType throttlePacketType, | ||
217 | Object id) | ||
218 | { | ||
219 | // Call the load balancer's hook. If this is not active here | ||
220 | // we defer to the sim server this client is actually connected | ||
221 | // to. Packet drop notifies will not be triggered in this | ||
222 | // configuration! | ||
223 | // | ||
224 | if ((m_SynchronizeClient != null) && (!m_Client.IsActive)) | ||
225 | { | ||
226 | if (m_SynchronizeClient(m_Client.Scene, packet, | ||
227 | m_Client.AgentId, throttlePacketType)) | ||
228 | return; | ||
229 | } | ||
230 | |||
231 | packet.Header.Sequence = NextPacketSequenceNumber(); | ||
232 | |||
233 | lock (m_NeedAck) | ||
234 | { | ||
235 | DropResend(id); | ||
236 | |||
237 | AddAcks(ref packet); | ||
238 | QueuePacket(packet, throttlePacketType, id); | ||
239 | |||
240 | // We want to see that packet arrive if it's reliable | ||
241 | if (packet.Header.Reliable) | ||
242 | { | ||
243 | m_UnackedBytes += packet.ToBytes().Length; | ||
244 | m_NeedAck[packet.Header.Sequence] = new AckData(packet, id); | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | |||
249 | private void AddAcks(ref Packet packet) | ||
250 | { | ||
251 | // This packet type has shown to have issues with | ||
252 | // acks being appended to the payload, just don't send | ||
253 | // any with this packet type until libsl is fixed. | ||
254 | // | ||
255 | if (packet is libsecondlife.Packets.ViewerEffectPacket) | ||
256 | return; | ||
257 | |||
258 | // Add acks to outgoing packets | ||
259 | // | ||
260 | if (m_PendingAcks.Count > 0) | ||
261 | { | ||
262 | int count = m_PendingAcks.Count; | ||
263 | if (count > 10) | ||
264 | count = 10; | ||
265 | packet.Header.AckList = new uint[count]; | ||
266 | packet.Header.AppendedAcks = true; | ||
267 | |||
268 | int i = 0; | ||
269 | |||
270 | foreach (uint ack in new List<uint>(m_PendingAcks.Keys)) | ||
271 | { | ||
272 | packet.Header.AckList[i] = ack; | ||
273 | i++; | ||
274 | m_PendingAcks.Remove(ack); | ||
275 | if (i >= count) // That is how much space there is | ||
276 | break; | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | |||
281 | private void QueuePacket( | ||
282 | Packet packet, ThrottleOutPacketType throttlePacketType, | ||
283 | Object id) | ||
284 | { | ||
285 | packet.TickCount = System.Environment.TickCount; | ||
286 | |||
287 | LLQueItem item = new LLQueItem(); | ||
288 | item.Packet = packet; | ||
289 | item.Incoming = false; | ||
290 | item.throttleType = throttlePacketType; | ||
291 | item.Identifier = id; | ||
292 | |||
293 | m_PacketQueue.Enqueue(item); | ||
294 | m_PacketsSent++; | ||
295 | } | ||
296 | |||
297 | private void ResendUnacked() | ||
298 | { | ||
299 | int now = System.Environment.TickCount; | ||
300 | int lastAck = m_LastAck; | ||
301 | |||
302 | // Unless we have received at least one ack, don't bother resending | ||
303 | // anything. There may not be a client there, don't clog up the | ||
304 | // pipes. | ||
305 | // | ||
306 | if (lastAck == 0) | ||
307 | return; | ||
308 | |||
309 | lock (m_NeedAck) | ||
310 | { | ||
311 | // Nothing to do | ||
312 | // | ||
313 | if (m_NeedAck.Count == 0) | ||
314 | return; | ||
315 | |||
316 | // If we have seen no acks in <SilenceLimit> s but are | ||
317 | // waiting for acks, then there may be no one listening. | ||
318 | // No need to resend anything. Keep it until it gets stale, | ||
319 | // then it will be dropped. | ||
320 | // | ||
321 | if ((((now - lastAck) > m_SilenceLimit) && | ||
322 | m_NeedAck.Count > 0) || m_NeedAck.Count == 0) | ||
323 | { | ||
324 | return; | ||
325 | } | ||
326 | |||
327 | foreach (AckData data in new List<AckData>(m_NeedAck.Values)) | ||
328 | { | ||
329 | Packet packet = data.Packet; | ||
330 | |||
331 | // Packets this old get resent | ||
332 | // | ||
333 | if ((now - packet.TickCount) > m_ResendTimeout) | ||
334 | { | ||
335 | // Resend the packet. Set the packet's tick count to | ||
336 | // now, and keep it marked as resent. | ||
337 | // | ||
338 | packet.Header.Resent = true; | ||
339 | QueuePacket(packet, ThrottleOutPacketType.Resend, | ||
340 | data.Identifier); | ||
341 | } | ||
342 | |||
343 | // The discard logic | ||
344 | // If the packet is in the queue for <DiscardTimeout> s | ||
345 | // without having been processed, then we have clogged | ||
346 | // pipes. Most likely, the client is gone | ||
347 | // Drop the packets | ||
348 | // | ||
349 | if ((now - packet.TickCount) > m_DiscardTimeout) | ||
350 | { | ||
351 | if (!m_ImportantPackets.Contains(packet.Type)) | ||
352 | m_NeedAck.Remove(packet.Header.Sequence); | ||
353 | |||
354 | TriggerOnPacketDrop(packet, data.Identifier); | ||
355 | |||
356 | continue; | ||
357 | } | ||
358 | } | ||
359 | } | ||
360 | } | ||
361 | |||
362 | // Send the pending packet acks to the client | ||
363 | // Will send blocks of acks for up to 250 packets | ||
364 | // | ||
365 | private void SendAcks() | ||
366 | { | ||
367 | lock (m_NeedAck) | ||
368 | { | ||
369 | if (m_PendingAcks.Count == 0) | ||
370 | return; | ||
371 | |||
372 | PacketAckPacket acks = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck); | ||
373 | |||
374 | // The case of equality is more common than one might think, | ||
375 | // because this function will be called unconditionally when | ||
376 | // the counter reaches 250. So there is a good chance another | ||
377 | // packet with 250 blocks exists. | ||
378 | // | ||
379 | if (acks.Packets == null || | ||
380 | acks.Packets.Length != m_PendingAcks.Count) | ||
381 | acks.Packets = new PacketAckPacket.PacketsBlock[m_PendingAcks.Count]; | ||
382 | int i = 0; | ||
383 | foreach (uint ack in new List<uint>(m_PendingAcks.Keys)) | ||
384 | { | ||
385 | acks.Packets[i] = new PacketAckPacket.PacketsBlock(); | ||
386 | acks.Packets[i].ID = ack; | ||
387 | |||
388 | m_PendingAcks.Remove(ack); | ||
389 | i++; | ||
390 | } | ||
391 | |||
392 | acks.Header.Reliable = false; | ||
393 | OutPacket(acks, ThrottleOutPacketType.Unknown); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | // Queue a packet ack. It will be sent either after 250 acks are | ||
398 | // queued, or when the timer fires. | ||
399 | // | ||
400 | private void AckPacket(Packet packet) | ||
401 | { | ||
402 | lock (m_NeedAck) | ||
403 | { | ||
404 | if (m_PendingAcks.Count < 250) | ||
405 | { | ||
406 | if (!m_PendingAcks.ContainsKey(packet.Header.Sequence)) | ||
407 | m_PendingAcks.Add(packet.Header.Sequence, | ||
408 | packet.Header.Sequence); | ||
409 | return; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | SendAcks(); | ||
414 | |||
415 | lock (m_NeedAck) | ||
416 | { | ||
417 | // If this is still full we have a truly exceptional | ||
418 | // condition (means, can't happen) | ||
419 | // | ||
420 | if (m_PendingAcks.Count < 250) | ||
421 | { | ||
422 | if (!m_PendingAcks.ContainsKey(packet.Header.Sequence)) | ||
423 | m_PendingAcks.Add(packet.Header.Sequence, | ||
424 | packet.Header.Sequence); | ||
425 | return; | ||
426 | } | ||
427 | } | ||
428 | } | ||
429 | |||
430 | // When the timer elapses, send the pending acks, trigger resends | ||
431 | // and report all the stats. | ||
432 | // | ||
433 | private void AckTimerElapsed(object sender, ElapsedEventArgs ea) | ||
434 | { | ||
435 | SendAcks(); | ||
436 | ResendUnacked(); | ||
437 | SendPacketStats(); | ||
438 | } | ||
439 | |||
440 | // Push out pachet counts for the sim status reporter | ||
441 | // | ||
442 | private void SendPacketStats() | ||
443 | { | ||
444 | PacketStats handlerPacketStats = OnPacketStats; | ||
445 | if (handlerPacketStats != null) | ||
446 | { | ||
447 | handlerPacketStats( | ||
448 | m_PacketsReceived - m_PacketsReceivedReported, | ||
449 | m_PacketsSent - m_PacketsSentReported, | ||
450 | m_UnackedBytes); | ||
451 | |||
452 | m_PacketsReceivedReported = m_PacketsReceived; | ||
453 | m_PacketsSentReported = m_PacketsSent; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | // We can't keep an unlimited record of dupes. This will prune the | ||
458 | // dictionary by age. | ||
459 | // | ||
460 | // private void PruneDupeTracker() | ||
461 | // { | ||
462 | // lock (m_DupeTracker) | ||
463 | // { | ||
464 | // Dictionary<uint, int> packs = | ||
465 | // new Dictionary<uint, int>(m_DupeTracker); | ||
466 | // | ||
467 | // foreach (uint pack in packs.Keys) | ||
468 | // { | ||
469 | // if (Util.UnixTimeSinceEpoch() - m_DupeTracker[pack] > | ||
470 | // m_DupeTrackerWindow) | ||
471 | // m_DupeTracker.Remove(pack); | ||
472 | // } | ||
473 | // } | ||
474 | // } | ||
475 | |||
476 | public void InPacket(Packet packet) | ||
477 | { | ||
478 | if (packet == null) | ||
479 | return; | ||
480 | |||
481 | // If this client is on another partial instance, no need | ||
482 | // to handle packets | ||
483 | // | ||
484 | if (!m_Client.IsActive && packet.Type != PacketType.LogoutRequest) | ||
485 | { | ||
486 | PacketPool.Instance.ReturnPacket(packet); | ||
487 | return; | ||
488 | } | ||
489 | |||
490 | // Any packet can have some packet acks in the header. | ||
491 | // Process them here | ||
492 | // | ||
493 | if (packet.Header.AppendedAcks) | ||
494 | { | ||
495 | foreach (uint id in packet.Header.AckList) | ||
496 | { | ||
497 | ProcessAck(id); | ||
498 | } | ||
499 | } | ||
500 | |||
501 | // When too many acks are needed to be sent, the client sends | ||
502 | // a packet consisting of acks only | ||
503 | // | ||
504 | if (packet.Type == PacketType.PacketAck) | ||
505 | { | ||
506 | PacketAckPacket ackPacket = (PacketAckPacket)packet; | ||
507 | |||
508 | foreach (PacketAckPacket.PacketsBlock block in | ||
509 | ackPacket.Packets) | ||
510 | { | ||
511 | ProcessAck(block.ID); | ||
512 | } | ||
513 | |||
514 | PacketPool.Instance.ReturnPacket(packet); | ||
515 | return; | ||
516 | } | ||
517 | else if (packet.Type == PacketType.StartPingCheck) | ||
518 | { | ||
519 | StartPingCheckPacket startPing = (StartPingCheckPacket)packet; | ||
520 | CompletePingCheckPacket endPing = (CompletePingCheckPacket)PacketPool.Instance.GetPacket(PacketType.CompletePingCheck); | ||
521 | |||
522 | endPing.PingID.PingID = startPing.PingID.PingID; | ||
523 | OutPacket(endPing, ThrottleOutPacketType.Task); | ||
524 | } | ||
525 | else | ||
526 | { | ||
527 | LLQueItem item = new LLQueItem(); | ||
528 | item.Packet = packet; | ||
529 | item.Incoming = true; | ||
530 | m_PacketQueue.Enqueue(item); | ||
531 | } | ||
532 | } | ||
533 | |||
534 | public void ProcessInPacket(Packet packet) | ||
535 | { | ||
536 | // Always ack the packet! | ||
537 | // | ||
538 | if (packet.Header.Reliable) | ||
539 | AckPacket(packet); | ||
540 | |||
541 | if (packet.Type != PacketType.AgentUpdate) | ||
542 | m_PacketsReceived++; | ||
543 | |||
544 | // Check for duplicate packets.. packets that the client is | ||
545 | // resending because it didn't receive our ack | ||
546 | // | ||
547 | lock (m_DupeTracker) | ||
548 | { | ||
549 | if (m_DupeTracker.ContainsKey(packet.Header.Sequence)) | ||
550 | return; | ||
551 | |||
552 | m_DupeTracker.Add(packet.Header.Sequence, | ||
553 | Util.UnixTimeSinceEpoch()); | ||
554 | } | ||
555 | |||
556 | m_Client.ProcessInPacket(packet); | ||
557 | } | ||
558 | |||
559 | public void Flush() | ||
560 | { | ||
561 | m_PacketQueue.Flush(); | ||
562 | } | ||
563 | |||
564 | public void Clear() | ||
565 | { | ||
566 | m_NeedAck.Clear(); | ||
567 | m_PendingAcks.Clear(); | ||
568 | m_Sequence += 1000000; | ||
569 | } | ||
570 | |||
571 | private void ProcessAck(uint id) | ||
572 | { | ||
573 | AckData data; | ||
574 | Packet packet; | ||
575 | |||
576 | lock (m_NeedAck) | ||
577 | { | ||
578 | if (!m_NeedAck.TryGetValue(id, out data)) | ||
579 | return; | ||
580 | |||
581 | packet = data.Packet; | ||
582 | |||
583 | m_NeedAck.Remove(id); | ||
584 | m_UnackedBytes -= packet.ToBytes().Length; | ||
585 | |||
586 | m_LastAck = System.Environment.TickCount; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | // Allocate packet sequence numbers in a threadsave manner | ||
591 | // | ||
592 | protected uint NextPacketSequenceNumber() | ||
593 | { | ||
594 | // Set the sequence number | ||
595 | uint seq = 1; | ||
596 | lock (m_SequenceLock) | ||
597 | { | ||
598 | if (m_Sequence >= MAX_SEQUENCE) | ||
599 | { | ||
600 | m_Sequence = 1; | ||
601 | } | ||
602 | else | ||
603 | { | ||
604 | m_Sequence++; | ||
605 | } | ||
606 | seq = m_Sequence; | ||
607 | } | ||
608 | return seq; | ||
609 | } | ||
610 | |||
611 | public ClientInfo GetClientInfo() | ||
612 | { | ||
613 | ClientInfo info = new ClientInfo(); | ||
614 | info.pendingAcks = m_PendingAcks; | ||
615 | info.needAck = new Dictionary<uint, byte[]>(); | ||
616 | |||
617 | lock (m_NeedAck) | ||
618 | { | ||
619 | foreach (uint key in m_NeedAck.Keys) | ||
620 | info.needAck.Add(key, m_NeedAck[key].Packet.ToBytes()); | ||
621 | } | ||
622 | |||
623 | LLQueItem[] queitems = m_PacketQueue.GetQueueArray(); | ||
624 | |||
625 | for (int i = 0; i < queitems.Length; i++) | ||
626 | { | ||
627 | if (queitems[i].Incoming == false) | ||
628 | info.out_packets.Add(queitems[i].Packet.ToBytes()); | ||
629 | } | ||
630 | |||
631 | info.sequence = m_Sequence; | ||
632 | |||
633 | return info; | ||
634 | } | ||
635 | |||
636 | public void SetClientInfo(ClientInfo info) | ||
637 | { | ||
638 | m_PendingAcks = info.pendingAcks; | ||
639 | m_NeedAck = new Dictionary<uint, AckData>(); | ||
640 | |||
641 | Packet packet = null; | ||
642 | int packetEnd = 0; | ||
643 | byte[] zero = new byte[3000]; | ||
644 | |||
645 | foreach (uint key in info.needAck.Keys) | ||
646 | { | ||
647 | byte[] buff = info.needAck[key]; | ||
648 | packetEnd = buff.Length - 1; | ||
649 | |||
650 | try | ||
651 | { | ||
652 | packet = PacketPool.Instance.GetPacket(buff, ref packetEnd, zero); | ||
653 | } | ||
654 | catch (Exception) | ||
655 | { | ||
656 | } | ||
657 | |||
658 | m_NeedAck.Add(key, new AckData(packet, null)); | ||
659 | } | ||
660 | |||
661 | m_Sequence = info.sequence; | ||
662 | } | ||
663 | |||
664 | public void AddImportantPacket(PacketType type) | ||
665 | { | ||
666 | if (m_ImportantPackets.Contains(type)) | ||
667 | return; | ||
668 | |||
669 | m_ImportantPackets.Add(type); | ||
670 | } | ||
671 | |||
672 | public void RemoveImportantPacket(PacketType type) | ||
673 | { | ||
674 | if (!m_ImportantPackets.Contains(type)) | ||
675 | return; | ||
676 | |||
677 | m_ImportantPackets.Remove(type); | ||
678 | } | ||
679 | |||
680 | private void DropResend(Object id) | ||
681 | { | ||
682 | foreach (AckData data in new List<AckData>(m_NeedAck.Values)) | ||
683 | { | ||
684 | if (data.Identifier != null && data.Identifier == id) | ||
685 | { | ||
686 | m_NeedAck.Remove(data.Packet.Header.Sequence); | ||
687 | return; | ||
688 | } | ||
689 | } | ||
690 | } | ||
691 | |||
692 | private void TriggerOnPacketDrop(Packet packet, Object id) | ||
693 | { | ||
694 | PacketDrop handlerPacketDrop = OnPacketDrop; | ||
695 | |||
696 | if (handlerPacketDrop == null) | ||
697 | return; | ||
698 | |||
699 | handlerPacketDrop(packet, id); | ||
700 | } | ||
701 | } | ||
702 | } | ||
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketQueue.cs deleted file mode 100644 index c3d33e6..0000000 --- a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketQueue.cs +++ /dev/null | |||
@@ -1,567 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.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.Threading; | ||
31 | using System.Timers; | ||
32 | using libsecondlife; | ||
33 | using libsecondlife.Packets; | ||
34 | using OpenSim.Framework; | ||
35 | using OpenSim.Framework.Statistics; | ||
36 | using OpenSim.Framework.Statistics.Interfaces; | ||
37 | using Timer=System.Timers.Timer; | ||
38 | |||
39 | namespace OpenSim.Region.ClientStack.FunSLUDP | ||
40 | { | ||
41 | public class LLPacketQueue : IPullStatsProvider | ||
42 | { | ||
43 | private static readonly log4net.ILog m_log | ||
44 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
45 | |||
46 | private bool m_enabled = true; | ||
47 | |||
48 | private BlockingQueue<LLQueItem> SendQueue; | ||
49 | |||
50 | private Queue<LLQueItem> IncomingPacketQueue; | ||
51 | private Queue<LLQueItem> OutgoingPacketQueue; | ||
52 | private Queue<LLQueItem> ResendOutgoingPacketQueue; | ||
53 | private Queue<LLQueItem> LandOutgoingPacketQueue; | ||
54 | private Queue<LLQueItem> WindOutgoingPacketQueue; | ||
55 | private Queue<LLQueItem> CloudOutgoingPacketQueue; | ||
56 | private Queue<LLQueItem> TaskOutgoingPacketQueue; | ||
57 | private Queue<LLQueItem> TaskLowpriorityPacketQueue; | ||
58 | private Queue<LLQueItem> TextureOutgoingPacketQueue; | ||
59 | private Queue<LLQueItem> AssetOutgoingPacketQueue; | ||
60 | |||
61 | // private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>(); | ||
62 | // private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>(); | ||
63 | |||
64 | // All throttle times and number of bytes are calculated by dividing by this value | ||
65 | // This value also determines how many times per throttletimems the timer will run | ||
66 | // If throttleimems is 1000 ms, then the timer will fire every 1000/7 milliseconds | ||
67 | |||
68 | private int throttleTimeDivisor = 7; | ||
69 | |||
70 | private int throttletimems = 1000; | ||
71 | |||
72 | private LLPacketThrottle ResendThrottle; | ||
73 | private LLPacketThrottle LandThrottle; | ||
74 | private LLPacketThrottle WindThrottle; | ||
75 | private LLPacketThrottle CloudThrottle; | ||
76 | private LLPacketThrottle TaskThrottle; | ||
77 | private LLPacketThrottle AssetThrottle; | ||
78 | private LLPacketThrottle TextureThrottle; | ||
79 | private LLPacketThrottle TotalThrottle; | ||
80 | |||
81 | // private long LastThrottle; | ||
82 | // private long ThrottleInterval; | ||
83 | private Timer throttleTimer; | ||
84 | |||
85 | private LLUUID m_agentId; | ||
86 | |||
87 | public LLPacketQueue(LLUUID agentId) | ||
88 | { | ||
89 | // While working on this, the BlockingQueue had me fooled for a bit. | ||
90 | // The Blocking queue causes the thread to stop until there's something | ||
91 | // in it to process. it's an on-purpose threadlock though because | ||
92 | // without it, the clientloop will suck up all sim resources. | ||
93 | |||
94 | SendQueue = new BlockingQueue<LLQueItem>(); | ||
95 | |||
96 | IncomingPacketQueue = new Queue<LLQueItem>(); | ||
97 | OutgoingPacketQueue = new Queue<LLQueItem>(); | ||
98 | ResendOutgoingPacketQueue = new Queue<LLQueItem>(); | ||
99 | LandOutgoingPacketQueue = new Queue<LLQueItem>(); | ||
100 | WindOutgoingPacketQueue = new Queue<LLQueItem>(); | ||
101 | CloudOutgoingPacketQueue = new Queue<LLQueItem>(); | ||
102 | TaskOutgoingPacketQueue = new Queue<LLQueItem>(); | ||
103 | TaskLowpriorityPacketQueue = new Queue<LLQueItem>(); | ||
104 | TextureOutgoingPacketQueue = new Queue<LLQueItem>(); | ||
105 | AssetOutgoingPacketQueue = new Queue<LLQueItem>(); | ||
106 | |||
107 | |||
108 | // Set up the throttle classes (min, max, current) in bytes | ||
109 | ResendThrottle = new LLPacketThrottle(5000, 100000, 16000); | ||
110 | LandThrottle = new LLPacketThrottle(1000, 100000, 2000); | ||
111 | WindThrottle = new LLPacketThrottle(0, 100000, 0); | ||
112 | CloudThrottle = new LLPacketThrottle(0, 100000, 0); | ||
113 | TaskThrottle = new LLPacketThrottle(1000, 800000, 3000); | ||
114 | AssetThrottle = new LLPacketThrottle(1000, 800000, 1000); | ||
115 | TextureThrottle = new LLPacketThrottle(1000, 800000, 4000); | ||
116 | // Total Throttle trumps all | ||
117 | // Number of bytes allowed to go out per second. (256kbps per client) | ||
118 | TotalThrottle = new LLPacketThrottle(0, 1500000, 28000); | ||
119 | |||
120 | throttleTimer = new Timer((int) (throttletimems/throttleTimeDivisor)); | ||
121 | throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed); | ||
122 | throttleTimer.Start(); | ||
123 | |||
124 | // TIMERS needed for this | ||
125 | // LastThrottle = DateTime.Now.Ticks; | ||
126 | // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor); | ||
127 | |||
128 | m_agentId = agentId; | ||
129 | |||
130 | if (StatsManager.SimExtraStats != null) | ||
131 | { | ||
132 | StatsManager.SimExtraStats.RegisterPacketQueueStatsProvider(m_agentId, this); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | /* STANDARD QUEUE MANIPULATION INTERFACES */ | ||
137 | |||
138 | |||
139 | public void Enqueue(LLQueItem item) | ||
140 | { | ||
141 | if (!m_enabled) | ||
142 | { | ||
143 | return; | ||
144 | } | ||
145 | // We could micro lock, but that will tend to actually | ||
146 | // probably be worse than just synchronizing on SendQueue | ||
147 | |||
148 | if (item == null) | ||
149 | { | ||
150 | SendQueue.Enqueue(item); | ||
151 | return; | ||
152 | } | ||
153 | |||
154 | if (item.Incoming) | ||
155 | { | ||
156 | SendQueue.PriorityEnqueue(item); | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | lock (this) | ||
161 | { | ||
162 | switch (item.throttleType) | ||
163 | { | ||
164 | case ThrottleOutPacketType.Resend: | ||
165 | ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item); | ||
166 | break; | ||
167 | case ThrottleOutPacketType.Texture: | ||
168 | ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item); | ||
169 | break; | ||
170 | case ThrottleOutPacketType.Task: | ||
171 | ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item); | ||
172 | break; | ||
173 | case ThrottleOutPacketType.LowpriorityTask: | ||
174 | ThrottleCheck(ref TaskThrottle, ref TaskLowpriorityPacketQueue, item); | ||
175 | break; | ||
176 | case ThrottleOutPacketType.Land: | ||
177 | ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item); | ||
178 | break; | ||
179 | case ThrottleOutPacketType.Asset: | ||
180 | ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item); | ||
181 | break; | ||
182 | case ThrottleOutPacketType.Cloud: | ||
183 | ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item); | ||
184 | break; | ||
185 | case ThrottleOutPacketType.Wind: | ||
186 | ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item); | ||
187 | break; | ||
188 | |||
189 | default: | ||
190 | // Acknowledgements and other such stuff should go directly to the blocking Queue | ||
191 | // Throttling them may and likely 'will' be problematic | ||
192 | SendQueue.PriorityEnqueue(item); | ||
193 | break; | ||
194 | } | ||
195 | } | ||
196 | } | ||
197 | |||
198 | public LLQueItem Dequeue() | ||
199 | { | ||
200 | return SendQueue.Dequeue(); | ||
201 | } | ||
202 | |||
203 | public void Flush() | ||
204 | { | ||
205 | lock (this) | ||
206 | { | ||
207 | while (PacketsWaiting()) | ||
208 | { | ||
209 | //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up. | ||
210 | if (ResendOutgoingPacketQueue.Count > 0) | ||
211 | { | ||
212 | SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue()); | ||
213 | } | ||
214 | if (LandOutgoingPacketQueue.Count > 0) | ||
215 | { | ||
216 | SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue()); | ||
217 | } | ||
218 | if (WindOutgoingPacketQueue.Count > 0) | ||
219 | { | ||
220 | SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue()); | ||
221 | } | ||
222 | if (CloudOutgoingPacketQueue.Count > 0) | ||
223 | { | ||
224 | SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue()); | ||
225 | } | ||
226 | if (TaskOutgoingPacketQueue.Count > 0) | ||
227 | { | ||
228 | SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue()); | ||
229 | } | ||
230 | if (TaskLowpriorityPacketQueue.Count > 0) | ||
231 | { | ||
232 | SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue()); | ||
233 | } | ||
234 | if (TextureOutgoingPacketQueue.Count > 0) | ||
235 | { | ||
236 | SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue()); | ||
237 | } | ||
238 | if (AssetOutgoingPacketQueue.Count > 0) | ||
239 | { | ||
240 | SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue()); | ||
241 | } | ||
242 | } | ||
243 | // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | public void Close() | ||
248 | { | ||
249 | Flush(); | ||
250 | |||
251 | m_enabled = false; | ||
252 | throttleTimer.Stop(); | ||
253 | |||
254 | if (StatsManager.SimExtraStats != null) | ||
255 | { | ||
256 | StatsManager.SimExtraStats.DeregisterPacketQueueStatsProvider(m_agentId); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | private void ResetCounters() | ||
261 | { | ||
262 | ResendThrottle.Reset(); | ||
263 | LandThrottle.Reset(); | ||
264 | WindThrottle.Reset(); | ||
265 | CloudThrottle.Reset(); | ||
266 | TaskThrottle.Reset(); | ||
267 | AssetThrottle.Reset(); | ||
268 | TextureThrottle.Reset(); | ||
269 | TotalThrottle.Reset(); | ||
270 | } | ||
271 | |||
272 | private bool PacketsWaiting() | ||
273 | { | ||
274 | return (ResendOutgoingPacketQueue.Count > 0 || | ||
275 | LandOutgoingPacketQueue.Count > 0 || | ||
276 | WindOutgoingPacketQueue.Count > 0 || | ||
277 | CloudOutgoingPacketQueue.Count > 0 || | ||
278 | TaskOutgoingPacketQueue.Count > 0 || | ||
279 | TaskLowpriorityPacketQueue.Count > 0 || | ||
280 | AssetOutgoingPacketQueue.Count > 0 || | ||
281 | TextureOutgoingPacketQueue.Count > 0); | ||
282 | } | ||
283 | |||
284 | public void ProcessThrottle() | ||
285 | { | ||
286 | // I was considering this.. Will an event fire if the thread it's on is blocked? | ||
287 | |||
288 | // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long | ||
289 | // The General overhead of the UDP protocol gets sent to the queue un-throttled by this | ||
290 | // so This'll pick up about around the right time. | ||
291 | |||
292 | int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once. | ||
293 | int throttleLoops = 0; | ||
294 | |||
295 | // We're going to dequeue all of the saved up packets until | ||
296 | // we've hit the throttle limit or there's no more packets to send | ||
297 | lock (this) | ||
298 | { | ||
299 | ResetCounters(); | ||
300 | // m_log.Info("[THROTTLE]: Entering Throttle"); | ||
301 | while (TotalThrottle.UnderLimit() && PacketsWaiting() && | ||
302 | (throttleLoops <= MaxThrottleLoops)) | ||
303 | { | ||
304 | throttleLoops++; | ||
305 | //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up. | ||
306 | if (ResendThrottle.UnderLimit() && ResendOutgoingPacketQueue.Count > 0) | ||
307 | { | ||
308 | LLQueItem qpack = ResendOutgoingPacketQueue.Dequeue(); | ||
309 | |||
310 | SendQueue.Enqueue(qpack); | ||
311 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
312 | ResendThrottle.Add(qpack.Packet.ToBytes().Length); | ||
313 | } | ||
314 | if (LandThrottle.UnderLimit() && LandOutgoingPacketQueue.Count > 0) | ||
315 | { | ||
316 | LLQueItem qpack = LandOutgoingPacketQueue.Dequeue(); | ||
317 | |||
318 | SendQueue.Enqueue(qpack); | ||
319 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
320 | LandThrottle.Add(qpack.Packet.ToBytes().Length); | ||
321 | } | ||
322 | if (WindThrottle.UnderLimit() && WindOutgoingPacketQueue.Count > 0) | ||
323 | { | ||
324 | LLQueItem qpack = WindOutgoingPacketQueue.Dequeue(); | ||
325 | |||
326 | SendQueue.Enqueue(qpack); | ||
327 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
328 | WindThrottle.Add(qpack.Packet.ToBytes().Length); | ||
329 | } | ||
330 | if (CloudThrottle.UnderLimit() && CloudOutgoingPacketQueue.Count > 0) | ||
331 | { | ||
332 | LLQueItem qpack = CloudOutgoingPacketQueue.Dequeue(); | ||
333 | |||
334 | SendQueue.Enqueue(qpack); | ||
335 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
336 | CloudThrottle.Add(qpack.Packet.ToBytes().Length); | ||
337 | } | ||
338 | if (TaskThrottle.UnderLimit() && (TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0)) | ||
339 | { | ||
340 | LLQueItem qpack; | ||
341 | if (TaskOutgoingPacketQueue.Count > 0) | ||
342 | { | ||
343 | qpack = TaskOutgoingPacketQueue.Dequeue(); | ||
344 | SendQueue.PriorityEnqueue(qpack); | ||
345 | } | ||
346 | else | ||
347 | { | ||
348 | qpack = TaskLowpriorityPacketQueue.Dequeue(); | ||
349 | SendQueue.Enqueue(qpack); | ||
350 | } | ||
351 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
352 | TaskThrottle.Add(qpack.Packet.ToBytes().Length); | ||
353 | } | ||
354 | if (TextureThrottle.UnderLimit() && TextureOutgoingPacketQueue.Count > 0) | ||
355 | { | ||
356 | LLQueItem qpack = TextureOutgoingPacketQueue.Dequeue(); | ||
357 | |||
358 | SendQueue.Enqueue(qpack); | ||
359 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
360 | TextureThrottle.Add(qpack.Packet.ToBytes().Length); | ||
361 | } | ||
362 | if (AssetThrottle.UnderLimit() && AssetOutgoingPacketQueue.Count > 0) | ||
363 | { | ||
364 | LLQueItem qpack = AssetOutgoingPacketQueue.Dequeue(); | ||
365 | |||
366 | SendQueue.Enqueue(qpack); | ||
367 | TotalThrottle.Add(qpack.Packet.ToBytes().Length); | ||
368 | AssetThrottle.Add(qpack.Packet.ToBytes().Length); | ||
369 | } | ||
370 | } | ||
371 | // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); | ||
372 | } | ||
373 | } | ||
374 | |||
375 | private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) | ||
376 | { | ||
377 | // just to change the signature, and that ProcessThrottle | ||
378 | // will be used elsewhere possibly | ||
379 | ProcessThrottle(); | ||
380 | } | ||
381 | |||
382 | private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item) | ||
383 | { | ||
384 | // The idea.. is if the packet throttle queues are empty | ||
385 | // and the client is under throttle for the type. Queue | ||
386 | // it up directly. This basically short cuts having to | ||
387 | // wait for the timer to fire to put things into the | ||
388 | // output queue | ||
389 | |||
390 | if ((q.Count == 0) && (throttle.UnderLimit())) | ||
391 | { | ||
392 | Monitor.Enter(this); | ||
393 | throttle.Add(item.Packet.ToBytes().Length); | ||
394 | TotalThrottle.Add(item.Packet.ToBytes().Length); | ||
395 | SendQueue.Enqueue(item); | ||
396 | Monitor.Pulse(this); | ||
397 | Monitor.Exit(this); | ||
398 | } | ||
399 | else | ||
400 | { | ||
401 | q.Enqueue(item); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | |||
406 | private static int ScaleThrottle(int value, int curmax, int newmax) | ||
407 | { | ||
408 | return (value / curmax) * newmax; | ||
409 | } | ||
410 | |||
411 | public byte[] GetThrottlesPacked(float multiplier) | ||
412 | { | ||
413 | int singlefloat = 4; | ||
414 | float tResend = ResendThrottle.Throttle*multiplier; | ||
415 | float tLand = LandThrottle.Throttle*multiplier; | ||
416 | float tWind = WindThrottle.Throttle*multiplier; | ||
417 | float tCloud = CloudThrottle.Throttle*multiplier; | ||
418 | float tTask = TaskThrottle.Throttle*multiplier; | ||
419 | float tTexture = TextureThrottle.Throttle*multiplier; | ||
420 | float tAsset = AssetThrottle.Throttle*multiplier; | ||
421 | |||
422 | byte[] throttles = new byte[singlefloat*7]; | ||
423 | int i = 0; | ||
424 | Buffer.BlockCopy(BitConverter.GetBytes(tResend), 0, throttles, singlefloat*i, singlefloat); | ||
425 | i++; | ||
426 | Buffer.BlockCopy(BitConverter.GetBytes(tLand), 0, throttles, singlefloat*i, singlefloat); | ||
427 | i++; | ||
428 | Buffer.BlockCopy(BitConverter.GetBytes(tWind), 0, throttles, singlefloat*i, singlefloat); | ||
429 | i++; | ||
430 | Buffer.BlockCopy(BitConverter.GetBytes(tCloud), 0, throttles, singlefloat*i, singlefloat); | ||
431 | i++; | ||
432 | Buffer.BlockCopy(BitConverter.GetBytes(tTask), 0, throttles, singlefloat*i, singlefloat); | ||
433 | i++; | ||
434 | Buffer.BlockCopy(BitConverter.GetBytes(tTexture), 0, throttles, singlefloat*i, singlefloat); | ||
435 | i++; | ||
436 | Buffer.BlockCopy(BitConverter.GetBytes(tAsset), 0, throttles, singlefloat*i, singlefloat); | ||
437 | |||
438 | return throttles; | ||
439 | } | ||
440 | |||
441 | public void SetThrottleFromClient(byte[] throttle) | ||
442 | { | ||
443 | // From mantis http://opensimulator.org/mantis/view.php?id=1374 | ||
444 | // it appears that sometimes we are receiving empty throttle byte arrays. | ||
445 | // TODO: Investigate this behaviour | ||
446 | if (throttle.Length == 0) | ||
447 | { | ||
448 | m_log.Warn("[PACKET QUEUE]: SetThrottleFromClient unexpectedly received a throttle byte array containing no elements!"); | ||
449 | return; | ||
450 | } | ||
451 | |||
452 | int tResend = -1; | ||
453 | int tLand = -1; | ||
454 | int tWind = -1; | ||
455 | int tCloud = -1; | ||
456 | int tTask = -1; | ||
457 | int tTexture = -1; | ||
458 | int tAsset = -1; | ||
459 | int tall = -1; | ||
460 | int singlefloat = 4; | ||
461 | |||
462 | //Agent Throttle Block contains 7 single floatingpoint values. | ||
463 | int j = 0; | ||
464 | |||
465 | // Some Systems may be big endian... | ||
466 | // it might be smart to do this check more often... | ||
467 | if (!BitConverter.IsLittleEndian) | ||
468 | for (int i = 0; i < 7; i++) | ||
469 | Array.Reverse(throttle, j + i*singlefloat, singlefloat); | ||
470 | |||
471 | // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_ | ||
472 | // bytes | ||
473 | // Convert to integer, since.. the full fp space isn't used. | ||
474 | tResend = (int) BitConverter.ToSingle(throttle, j); | ||
475 | j += singlefloat; | ||
476 | tLand = (int) BitConverter.ToSingle(throttle, j); | ||
477 | j += singlefloat; | ||
478 | tWind = (int) BitConverter.ToSingle(throttle, j); | ||
479 | j += singlefloat; | ||
480 | tCloud = (int) BitConverter.ToSingle(throttle, j); | ||
481 | j += singlefloat; | ||
482 | tTask = (int) BitConverter.ToSingle(throttle, j); | ||
483 | j += singlefloat; | ||
484 | tTexture = (int) BitConverter.ToSingle(throttle, j); | ||
485 | j += singlefloat; | ||
486 | tAsset = (int) BitConverter.ToSingle(throttle, j); | ||
487 | |||
488 | tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset; | ||
489 | /* | ||
490 | m_log.Info("[CLIENT]: Client AgentThrottle - Got throttle:resendbytes=" + tResend + | ||
491 | " landbytes=" + tLand + | ||
492 | " windbytes=" + tWind + | ||
493 | " cloudbytes=" + tCloud + | ||
494 | " taskbytes=" + tTask + | ||
495 | " texturebytes=" + tTexture + | ||
496 | " Assetbytes=" + tAsset + | ||
497 | " Allbytes=" + tall); | ||
498 | */ | ||
499 | |||
500 | // Total Sanity | ||
501 | // Make sure that the client sent sane total values. | ||
502 | |||
503 | // If the client didn't send acceptable values.... | ||
504 | // Scale the clients values down until they are acceptable. | ||
505 | |||
506 | if (tall <= TotalThrottle.Max) | ||
507 | { | ||
508 | ResendThrottle.Throttle = tResend; | ||
509 | LandThrottle.Throttle = tLand; | ||
510 | WindThrottle.Throttle = tWind; | ||
511 | CloudThrottle.Throttle = tCloud; | ||
512 | TaskThrottle.Throttle = tTask; | ||
513 | TextureThrottle.Throttle = tTexture; | ||
514 | AssetThrottle.Throttle = tAsset; | ||
515 | TotalThrottle.Throttle = tall; | ||
516 | } | ||
517 | // else if (tall < 1) | ||
518 | // { | ||
519 | // // client is stupid, penalize him by minning everything | ||
520 | // ResendThrottle.Throttle = ResendThrottle.Min; | ||
521 | // LandThrottle.Throttle = LandThrottle.Min; | ||
522 | // WindThrottle.Throttle = WindThrottle.Min; | ||
523 | // CloudThrottle.Throttle = CloudThrottle.Min; | ||
524 | // TaskThrottle.Throttle = TaskThrottle.Min; | ||
525 | // TextureThrottle.Throttle = TextureThrottle.Min; | ||
526 | // AssetThrottle.Throttle = AssetThrottle.Min; | ||
527 | // TotalThrottle.Throttle = TotalThrottle.Min; | ||
528 | // } | ||
529 | else | ||
530 | { | ||
531 | // we're over so figure out percentages and use those | ||
532 | ResendThrottle.Throttle = tResend; | ||
533 | |||
534 | LandThrottle.Throttle = ScaleThrottle(tLand, tall, TotalThrottle.Max); | ||
535 | WindThrottle.Throttle = ScaleThrottle(tWind, tall, TotalThrottle.Max); | ||
536 | CloudThrottle.Throttle = ScaleThrottle(tCloud, tall, TotalThrottle.Max); | ||
537 | TaskThrottle.Throttle = ScaleThrottle(tTask, tall, TotalThrottle.Max); | ||
538 | TextureThrottle.Throttle = ScaleThrottle(tTexture, tall, TotalThrottle.Max); | ||
539 | AssetThrottle.Throttle = ScaleThrottle(tAsset, tall, TotalThrottle.Max); | ||
540 | TotalThrottle.Throttle = TotalThrottle.Max; | ||
541 | } | ||
542 | // effectively wiggling the slider causes things reset | ||
543 | // ResetCounters(); // DO NOT reset, better to send less for one period than more | ||
544 | } | ||
545 | |||
546 | // See IPullStatsProvider | ||
547 | public string GetStats() | ||
548 | { | ||
549 | return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", | ||
550 | SendQueue.Count(), | ||
551 | IncomingPacketQueue.Count, | ||
552 | OutgoingPacketQueue.Count, | ||
553 | ResendOutgoingPacketQueue.Count, | ||
554 | LandOutgoingPacketQueue.Count, | ||
555 | WindOutgoingPacketQueue.Count, | ||
556 | CloudOutgoingPacketQueue.Count, | ||
557 | TaskOutgoingPacketQueue.Count, | ||
558 | TextureOutgoingPacketQueue.Count, | ||
559 | AssetOutgoingPacketQueue.Count); | ||
560 | } | ||
561 | |||
562 | public LLQueItem[] GetQueueArray() | ||
563 | { | ||
564 | return SendQueue.GetQueueArray(); | ||
565 | } | ||
566 | } | ||
567 | } | ||
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketServer.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketServer.cs deleted file mode 100644 index 08b722c..0000000 --- a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketServer.cs +++ /dev/null | |||
@@ -1,150 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.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.Net; | ||
29 | using System.Net.Sockets; | ||
30 | using libsecondlife; | ||
31 | using libsecondlife.Packets; | ||
32 | using OpenSim.Framework; | ||
33 | using OpenSim.Framework.Communications.Cache; | ||
34 | using OpenSim.Region.ClientStack.FunSLUDP; | ||
35 | |||
36 | namespace OpenSim.Region.ClientStack.FunSLUDP | ||
37 | { | ||
38 | public class LLPacketServer | ||
39 | { | ||
40 | //private static readonly log4net.ILog m_log | ||
41 | // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
42 | |||
43 | private readonly LLClientStackNetworkHandler m_networkHandler; | ||
44 | private IScene m_scene; | ||
45 | |||
46 | //private readonly ClientManager m_clientManager = new ClientManager(); | ||
47 | //public ClientManager ClientManager | ||
48 | //{ | ||
49 | // get { return m_clientManager; } | ||
50 | //} | ||
51 | |||
52 | public LLPacketServer(LLClientStackNetworkHandler networkHandler) | ||
53 | { | ||
54 | m_networkHandler = networkHandler; | ||
55 | m_networkHandler.RegisterPacketServer(this); | ||
56 | } | ||
57 | |||
58 | public IScene LocalScene | ||
59 | { | ||
60 | set { m_scene = value; } | ||
61 | } | ||
62 | |||
63 | /// <summary> | ||
64 | /// | ||
65 | /// </summary> | ||
66 | /// <param name="circuitCode"></param> | ||
67 | /// <param name="packet"></param> | ||
68 | public virtual void InPacket(uint circuitCode, Packet packet) | ||
69 | { | ||
70 | m_scene.ClientManager.InPacket(circuitCode, packet); | ||
71 | } | ||
72 | |||
73 | protected virtual IClientAPI CreateNewClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, | ||
74 | ClientManager clientManager, IScene scene, AssetCache assetCache, | ||
75 | LLPacketServer packServer, AgentCircuitManager authenSessions, | ||
76 | LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP) | ||
77 | { | ||
78 | return | ||
79 | new LLClientView(remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode, proxyEP); | ||
80 | } | ||
81 | |||
82 | public virtual bool AddNewClient(EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache, | ||
83 | AgentCircuitManager authenticateSessionsClass, EndPoint proxyEP) | ||
84 | { | ||
85 | IClientAPI newuser; | ||
86 | |||
87 | if (m_scene.ClientManager.TryGetClient(useCircuit.CircuitCode.Code, out newuser)) | ||
88 | { | ||
89 | return false; | ||
90 | } | ||
91 | else | ||
92 | { | ||
93 | newuser = CreateNewClient(epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this, | ||
94 | authenticateSessionsClass, useCircuit.CircuitCode.ID, | ||
95 | useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code, proxyEP); | ||
96 | |||
97 | m_scene.ClientManager.Add(useCircuit.CircuitCode.Code, newuser); | ||
98 | |||
99 | newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; | ||
100 | newuser.OnLogout += LogoutHandler; | ||
101 | newuser.OnConnectionClosed += CloseClient; | ||
102 | |||
103 | return true; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | public void LogoutHandler(IClientAPI client) | ||
108 | { | ||
109 | client.SendLogoutPacket(); | ||
110 | |||
111 | CloseClient(client); | ||
112 | } | ||
113 | |||
114 | /// <summary> | ||
115 | /// | ||
116 | /// </summary> | ||
117 | /// <param name="buffer"></param> | ||
118 | /// <param name="size"></param> | ||
119 | /// <param name="flags"></param> | ||
120 | /// <param name="circuitcode"></param> | ||
121 | public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) | ||
122 | { | ||
123 | m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode); | ||
124 | } | ||
125 | |||
126 | /// <summary> | ||
127 | /// | ||
128 | /// </summary> | ||
129 | /// <param name="circuitcode"></param> | ||
130 | public virtual void CloseCircuit(uint circuitcode) | ||
131 | { | ||
132 | m_networkHandler.RemoveClientCircuit(circuitcode); | ||
133 | |||
134 | //m_scene.ClientManager.CloseAllAgents(circuitcode); | ||
135 | } | ||
136 | |||
137 | /// <summary> | ||
138 | /// Completely close down the given client. | ||
139 | /// </summary> | ||
140 | /// <param name="client"></param> | ||
141 | public virtual void CloseClient(IClientAPI client) | ||
142 | { | ||
143 | //m_log.Info("PacketServer:CloseClient()"); | ||
144 | |||
145 | CloseCircuit(client.CircuitCode); | ||
146 | m_scene.ClientManager.Remove(client.CircuitCode); | ||
147 | client.Close(false); | ||
148 | } | ||
149 | } | ||
150 | } | ||
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketThrottle.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketThrottle.cs deleted file mode 100644 index 32122fd..0000000 --- a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketThrottle.cs +++ /dev/null | |||
@@ -1,93 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.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 | namespace OpenSim.Region.ClientStack.FunSLUDP | ||
29 | { | ||
30 | public class LLPacketThrottle | ||
31 | { | ||
32 | private readonly int m_maxAllowableThrottle; | ||
33 | private readonly int m_minAllowableThrottle; | ||
34 | private int m_currentThrottle; | ||
35 | private const int m_throttleTimeDivisor = 7; | ||
36 | private int m_currentBytesSent; | ||
37 | |||
38 | public LLPacketThrottle(int Min, int Max, int Throttle) | ||
39 | { | ||
40 | m_maxAllowableThrottle = Max; | ||
41 | m_minAllowableThrottle = Min; | ||
42 | m_currentThrottle = Throttle; | ||
43 | m_currentBytesSent = 0; | ||
44 | } | ||
45 | |||
46 | public void Reset() | ||
47 | { | ||
48 | m_currentBytesSent = 0; | ||
49 | } | ||
50 | |||
51 | public bool UnderLimit() | ||
52 | { | ||
53 | return (m_currentBytesSent < (m_currentThrottle/m_throttleTimeDivisor)); | ||
54 | } | ||
55 | |||
56 | public int Add(int bytes) | ||
57 | { | ||
58 | m_currentBytesSent += bytes; | ||
59 | return m_currentBytesSent; | ||
60 | } | ||
61 | |||
62 | // Properties | ||
63 | public int Max | ||
64 | { | ||
65 | get { return m_maxAllowableThrottle; } | ||
66 | } | ||
67 | |||
68 | public int Min | ||
69 | { | ||
70 | get { return m_minAllowableThrottle; } | ||
71 | } | ||
72 | |||
73 | public int Throttle | ||
74 | { | ||
75 | get { return m_currentThrottle; } | ||
76 | set | ||
77 | { | ||
78 | if (value > m_maxAllowableThrottle) | ||
79 | { | ||
80 | m_currentThrottle = m_maxAllowableThrottle; | ||
81 | } | ||
82 | else if (value < m_minAllowableThrottle) | ||
83 | { | ||
84 | m_currentThrottle = m_minAllowableThrottle; | ||
85 | } | ||
86 | else | ||
87 | { | ||
88 | m_currentThrottle = value; | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | } | ||
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLQueItem.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLQueItem.cs deleted file mode 100644 index c079cec..0000000 --- a/OpenSim/Region/ClientStack/FunSLUDP/LLQueItem.cs +++ /dev/null | |||
@@ -1,45 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.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 libsecondlife.Packets; | ||
30 | using OpenSim.Framework; | ||
31 | |||
32 | namespace OpenSim.Region.ClientStack.FunSLUDP | ||
33 | { | ||
34 | public class LLQueItem | ||
35 | { | ||
36 | public LLQueItem() | ||
37 | { | ||
38 | } | ||
39 | |||
40 | public Packet Packet; | ||
41 | public bool Incoming; | ||
42 | public ThrottleOutPacketType throttleType; | ||
43 | public Object Identifier; | ||
44 | } | ||
45 | } | ||
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLUDPServer.cs deleted file mode 100644 index 2b76c97..0000000 --- a/OpenSim/Region/ClientStack/FunSLUDP/LLUDPServer.cs +++ /dev/null | |||
@@ -1,545 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.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; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Net; | ||
32 | using System.Net.Sockets; | ||
33 | using System.Reflection; | ||
34 | using libsecondlife.Packets; | ||
35 | using log4net; | ||
36 | using OpenSim.Framework; | ||
37 | using OpenSim.Framework.Communications.Cache; | ||
38 | using OpenSim.Region.ClientStack.FunSLUDP; | ||
39 | using OpenSim.Region.Environment.Scenes; | ||
40 | |||
41 | namespace OpenSim.Region.ClientStack.FunSLUDP | ||
42 | { | ||
43 | public class LLUDPServer : LLClientStackNetworkHandler, IClientNetworkServer | ||
44 | { | ||
45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
46 | |||
47 | protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>(); | ||
48 | |||
49 | //public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>(); | ||
50 | public Hashtable clientCircuits_reverse = Hashtable.Synchronized(new Hashtable()); | ||
51 | |||
52 | protected Dictionary<uint, EndPoint> proxyCircuits = new Dictionary<uint, EndPoint>(); | ||
53 | private Socket m_socket; | ||
54 | protected IPEndPoint ServerIncoming; | ||
55 | protected byte[] RecvBuffer = new byte[4096]; | ||
56 | protected byte[] ZeroBuffer = new byte[8192]; | ||
57 | protected IPEndPoint ipeSender; | ||
58 | protected EndPoint epSender; | ||
59 | protected EndPoint epProxy; | ||
60 | protected int proxyPortOffset; | ||
61 | protected AsyncCallback ReceivedData; | ||
62 | protected LLPacketServer m_packetServer; | ||
63 | protected Location m_location; | ||
64 | |||
65 | protected uint listenPort; | ||
66 | protected bool Allow_Alternate_Port; | ||
67 | protected IPAddress listenIP = IPAddress.Parse("0.0.0.0"); | ||
68 | protected IScene m_localScene; | ||
69 | protected AssetCache m_assetCache; | ||
70 | protected AgentCircuitManager m_authenticateSessionsClass; | ||
71 | |||
72 | public LLPacketServer PacketServer | ||
73 | { | ||
74 | get { return m_packetServer; } | ||
75 | set { m_packetServer = value; } | ||
76 | } | ||
77 | |||
78 | public IScene LocalScene | ||
79 | { | ||
80 | set | ||
81 | { | ||
82 | m_localScene = value; | ||
83 | m_packetServer.LocalScene = m_localScene; | ||
84 | m_location = new Location(m_localScene.RegionInfo.RegionHandle); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | public ulong RegionHandle | ||
89 | { | ||
90 | get { return m_location.RegionHandle; } | ||
91 | } | ||
92 | |||
93 | Socket IClientNetworkServer.Server | ||
94 | { | ||
95 | get { return m_socket; } | ||
96 | } | ||
97 | |||
98 | public bool HandlesRegion(Location x) | ||
99 | { | ||
100 | return x == m_location; | ||
101 | } | ||
102 | |||
103 | public void AddScene(Scene x) | ||
104 | { | ||
105 | LocalScene = x; | ||
106 | } | ||
107 | |||
108 | public void Start() | ||
109 | { | ||
110 | ServerListener(); | ||
111 | } | ||
112 | |||
113 | public void Stop() | ||
114 | { | ||
115 | m_socket.Close(); | ||
116 | } | ||
117 | |||
118 | public LLUDPServer() | ||
119 | { | ||
120 | } | ||
121 | |||
122 | public LLUDPServer(IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass) | ||
123 | { | ||
124 | Initialise(_listenIP, ref port, proxyPortOffset, allow_alternate_port, assetCache, authenticateClass); | ||
125 | } | ||
126 | |||
127 | public void Initialise(IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass) | ||
128 | { | ||
129 | this.proxyPortOffset = proxyPortOffset; | ||
130 | listenPort = (uint) (port + proxyPortOffset); | ||
131 | listenIP = _listenIP; | ||
132 | Allow_Alternate_Port = allow_alternate_port; | ||
133 | m_assetCache = assetCache; | ||
134 | m_authenticateSessionsClass = authenticateClass; | ||
135 | CreatePacketServer(); | ||
136 | |||
137 | // Return new port | ||
138 | // This because in Grid mode it is not really important what port the region listens to as long as it is correctly registered. | ||
139 | // So the option allow_alternate_ports="true" was added to default.xml | ||
140 | port = (uint)(listenPort - proxyPortOffset); | ||
141 | } | ||
142 | |||
143 | protected virtual void CreatePacketServer() | ||
144 | { | ||
145 | new LLPacketServer(this); | ||
146 | } | ||
147 | |||
148 | protected virtual void OnReceivedData(IAsyncResult result) | ||
149 | { | ||
150 | ipeSender = new IPEndPoint(listenIP, 0); | ||
151 | epSender = (EndPoint) ipeSender; | ||
152 | Packet packet = null; | ||
153 | |||
154 | int numBytes = 1; | ||
155 | |||
156 | try | ||
157 | { | ||
158 | numBytes = m_socket.EndReceiveFrom(result, ref epSender); | ||
159 | } | ||
160 | catch (SocketException e) | ||
161 | { | ||
162 | // TODO : Actually only handle those states that we have control over, re-throw everything else, | ||
163 | // TODO: implement cases as we encounter them. | ||
164 | //m_log.Error("[UDPSERVER]: Connection Error! - " + e.ToString()); | ||
165 | switch (e.SocketErrorCode) | ||
166 | { | ||
167 | case SocketError.AlreadyInProgress: | ||
168 | case SocketError.NetworkReset: | ||
169 | case SocketError.ConnectionReset: | ||
170 | try | ||
171 | { | ||
172 | CloseEndPoint(epSender); | ||
173 | } | ||
174 | catch (Exception a) | ||
175 | { | ||
176 | m_log.Info("[UDPSERVER]: " + a.ToString()); | ||
177 | } | ||
178 | try | ||
179 | { | ||
180 | m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, | ||
181 | ReceivedData, null); | ||
182 | |||
183 | // Ter: For some stupid reason ConnectionReset basically kills our async event structure.. | ||
184 | // so therefore.. we've got to tell the server to BeginReceiveFrom again. | ||
185 | // This will happen over and over until we've gone through all packets | ||
186 | // sent to and from this particular user. | ||
187 | // Stupid I know.. | ||
188 | // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. | ||
189 | } | ||
190 | catch (SocketException) | ||
191 | { | ||
192 | } | ||
193 | break; | ||
194 | default: | ||
195 | try | ||
196 | { | ||
197 | CloseEndPoint(epSender); | ||
198 | } | ||
199 | catch (Exception) | ||
200 | { | ||
201 | //m_log.Info("[UDPSERVER]" + a.ToString()); | ||
202 | } | ||
203 | try | ||
204 | { | ||
205 | m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, | ||
206 | ReceivedData, null); | ||
207 | |||
208 | // Ter: For some stupid reason ConnectionReset basically kills our async event structure.. | ||
209 | // so therefore.. we've got to tell the server to BeginReceiveFrom again. | ||
210 | // This will happen over and over until we've gone through all packets | ||
211 | // sent to and from this particular user. | ||
212 | // Stupid I know.. | ||
213 | // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. | ||
214 | } | ||
215 | catch (SocketException e2) | ||
216 | { | ||
217 | m_log.Error("[UDPSERVER]: " + e2.ToString()); | ||
218 | } | ||
219 | |||
220 | // Here's some reference code! :D | ||
221 | // Shutdown and restart the UDP listener! hehe | ||
222 | // Shiny | ||
223 | |||
224 | //Server.Shutdown(SocketShutdown.Both); | ||
225 | //CloseEndPoint(epSender); | ||
226 | //ServerListener(); | ||
227 | break; | ||
228 | } | ||
229 | |||
230 | //return; | ||
231 | } | ||
232 | catch (ObjectDisposedException e) | ||
233 | { | ||
234 | m_log.Debug("[UDPSERVER]: " + e.ToString()); | ||
235 | try | ||
236 | { | ||
237 | m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, | ||
238 | ReceivedData, null); | ||
239 | |||
240 | // Ter: For some stupid reason ConnectionReset basically kills our async event structure.. | ||
241 | // so therefore.. we've got to tell the server to BeginReceiveFrom again. | ||
242 | // This will happen over and over until we've gone through all packets | ||
243 | // sent to and from this particular user. | ||
244 | // Stupid I know.. | ||
245 | // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. | ||
246 | } | ||
247 | |||
248 | catch (SocketException e2) | ||
249 | { | ||
250 | m_log.Error("[UDPSERVER]: " + e2.ToString()); | ||
251 | } | ||
252 | catch (ObjectDisposedException) | ||
253 | { | ||
254 | } | ||
255 | //return; | ||
256 | } | ||
257 | |||
258 | //System.Console.WriteLine("UDPServer : recieved message from {0}", epSender.ToString()); | ||
259 | epProxy = epSender; | ||
260 | if (proxyPortOffset != 0) | ||
261 | { | ||
262 | epSender = PacketPool.DecodeProxyMessage(RecvBuffer, ref numBytes); | ||
263 | } | ||
264 | |||
265 | int packetEnd = numBytes - 1; | ||
266 | |||
267 | try | ||
268 | { | ||
269 | packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer); | ||
270 | } | ||
271 | catch (Exception e) | ||
272 | { | ||
273 | m_log.Debug("[UDPSERVER]: " + e.ToString()); | ||
274 | } | ||
275 | |||
276 | try | ||
277 | { | ||
278 | m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); | ||
279 | } | ||
280 | catch (SocketException) | ||
281 | { | ||
282 | try | ||
283 | { | ||
284 | CloseEndPoint(epSender); | ||
285 | } | ||
286 | catch (Exception a) | ||
287 | { | ||
288 | m_log.Info("[UDPSERVER]: " + a.ToString()); | ||
289 | } | ||
290 | try | ||
291 | { | ||
292 | m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, | ||
293 | ReceivedData, null); | ||
294 | |||
295 | // Ter: For some stupid reason ConnectionReset basically kills our async event structure.. | ||
296 | // so therefore.. we've got to tell the server to BeginReceiveFrom again. | ||
297 | // This will happen over and over until we've gone through all packets | ||
298 | // sent to and from this particular user. | ||
299 | // Stupid I know.. | ||
300 | // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. | ||
301 | } | ||
302 | catch (SocketException e5) | ||
303 | { | ||
304 | m_log.Error("[UDPSERVER]: " + e5.ToString()); | ||
305 | } | ||
306 | } | ||
307 | catch (ObjectDisposedException) | ||
308 | { | ||
309 | } | ||
310 | |||
311 | if (packet != null) | ||
312 | { | ||
313 | try | ||
314 | { | ||
315 | // do we already have a circuit for this endpoint | ||
316 | uint circuit; | ||
317 | |||
318 | bool ret = false; | ||
319 | lock (clientCircuits) | ||
320 | { | ||
321 | ret = clientCircuits.TryGetValue(epSender, out circuit); | ||
322 | } | ||
323 | if (ret) | ||
324 | { | ||
325 | //if so then send packet to the packetserver | ||
326 | //m_log.Warn("[UDPSERVER]: ALREADY HAVE Circuit!"); | ||
327 | m_packetServer.InPacket(circuit, packet); | ||
328 | } | ||
329 | else if (packet.Type == PacketType.UseCircuitCode) | ||
330 | { | ||
331 | // new client | ||
332 | m_log.Debug("[UDPSERVER]: Adding New Client"); | ||
333 | AddNewClient(packet); | ||
334 | |||
335 | UseCircuitCodePacket p = (UseCircuitCodePacket)packet; | ||
336 | |||
337 | // Ack the first UseCircuitCode packet | ||
338 | PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck); | ||
339 | // TODO: don't create new blocks if recycling an old packet | ||
340 | ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; | ||
341 | ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); | ||
342 | ack_it.Packets[0].ID = packet.Header.Sequence; | ||
343 | ack_it.Header.Reliable = false; | ||
344 | SendPacketTo(ack_it.ToBytes(),ack_it.ToBytes().Length,SocketFlags.None,p.CircuitCode.Code); | ||
345 | } | ||
346 | } | ||
347 | catch (Exception) | ||
348 | { | ||
349 | m_log.Error("[UDPSERVER]: Exception in processing packet."); | ||
350 | m_log.Debug("[UDPSERVER]: Adding New Client"); | ||
351 | try | ||
352 | { | ||
353 | AddNewClient(packet); | ||
354 | } | ||
355 | catch (Exception e3) | ||
356 | { | ||
357 | m_log.Error("[UDPSERVER]: Adding New Client threw exception " + e3.ToString()); | ||
358 | m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, | ||
359 | ReceivedData, null); | ||
360 | } | ||
361 | } | ||
362 | } | ||
363 | |||
364 | } | ||
365 | |||
366 | private void CloseEndPoint(EndPoint sender) | ||
367 | { | ||
368 | uint circuit; | ||
369 | lock (clientCircuits) | ||
370 | { | ||
371 | if (clientCircuits.TryGetValue(sender, out circuit)) | ||
372 | { | ||
373 | m_packetServer.CloseCircuit(circuit); | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | |||
378 | protected virtual void AddNewClient(Packet packet) | ||
379 | { | ||
380 | //Slave regions don't accept new clients | ||
381 | if (m_localScene.Region_Status != RegionStatus.SlaveScene) | ||
382 | { | ||
383 | if (!(packet is UseCircuitCodePacket)) | ||
384 | return; | ||
385 | |||
386 | UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet; | ||
387 | lock (clientCircuits) | ||
388 | { | ||
389 | if (!clientCircuits.ContainsKey(epSender)) | ||
390 | clientCircuits.Add(epSender, useCircuit.CircuitCode.Code); | ||
391 | else | ||
392 | m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); | ||
393 | } | ||
394 | |||
395 | // This doesn't need locking as it's synchronized data | ||
396 | if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) | ||
397 | clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender); | ||
398 | else | ||
399 | m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); | ||
400 | |||
401 | |||
402 | lock (proxyCircuits) | ||
403 | { | ||
404 | if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code)) | ||
405 | proxyCircuits.Add(useCircuit.CircuitCode.Code, epProxy); | ||
406 | else | ||
407 | m_log.Error("[UDPSERVER]: proxyCircuits already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); | ||
408 | } | ||
409 | |||
410 | PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass, epProxy); | ||
411 | } | ||
412 | PacketPool.Instance.ReturnPacket(packet); | ||
413 | } | ||
414 | |||
415 | public void ServerListener() | ||
416 | { | ||
417 | uint newPort = listenPort; | ||
418 | m_log.Info("[SERVER]: Opening UDP socket on " + listenIP.ToString() + " " + newPort + "."); | ||
419 | |||
420 | ServerIncoming = new IPEndPoint(listenIP, (int)newPort); | ||
421 | m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | ||
422 | m_socket.Bind(ServerIncoming); | ||
423 | // Add flags to the UDP socket to prevent "Socket forcibly closed by host" | ||
424 | // uint IOC_IN = 0x80000000; | ||
425 | // uint IOC_VENDOR = 0x18000000; | ||
426 | // uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; | ||
427 | // TODO: this apparently works in .NET but not in Mono, need to sort out the right flags here. | ||
428 | // m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); | ||
429 | |||
430 | listenPort = newPort; | ||
431 | |||
432 | m_log.Info("[SERVER]: UDP socket bound, getting ready to listen"); | ||
433 | |||
434 | ipeSender = new IPEndPoint(listenIP, 0); | ||
435 | epSender = (EndPoint)ipeSender; | ||
436 | ReceivedData = new AsyncCallback(OnReceivedData); | ||
437 | m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); | ||
438 | |||
439 | m_log.Info("[SERVER]: Listening on port " + newPort); | ||
440 | } | ||
441 | |||
442 | public virtual void RegisterPacketServer(LLPacketServer server) | ||
443 | { | ||
444 | m_packetServer = server; | ||
445 | } | ||
446 | |||
447 | public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) | ||
448 | //EndPoint packetSender) | ||
449 | { | ||
450 | // find the endpoint for this circuit | ||
451 | EndPoint sendto = null; | ||
452 | try { | ||
453 | sendto = (EndPoint)clientCircuits_reverse[circuitcode]; | ||
454 | } catch { | ||
455 | // Exceptions here mean there is no circuit | ||
456 | m_log.Warn("Circuit not found, not sending packet"); | ||
457 | return; | ||
458 | } | ||
459 | |||
460 | if (sendto != null) | ||
461 | { | ||
462 | //we found the endpoint so send the packet to it | ||
463 | if (proxyPortOffset != 0) | ||
464 | { | ||
465 | //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString()); | ||
466 | PacketPool.EncodeProxyMessage(buffer, ref size, sendto); | ||
467 | m_socket.SendTo(buffer, size, flags, proxyCircuits[circuitcode]); | ||
468 | } | ||
469 | else | ||
470 | { | ||
471 | //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString()); | ||
472 | m_socket.SendTo(buffer, size, flags, sendto); | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | |||
477 | public virtual void RemoveClientCircuit(uint circuitcode) | ||
478 | { | ||
479 | EndPoint sendto = null; | ||
480 | if (clientCircuits_reverse.Contains(circuitcode)) | ||
481 | { | ||
482 | sendto = (EndPoint)clientCircuits_reverse[circuitcode]; | ||
483 | |||
484 | clientCircuits_reverse.Remove(circuitcode); | ||
485 | |||
486 | lock (clientCircuits) | ||
487 | { | ||
488 | if (sendto != null) | ||
489 | { | ||
490 | clientCircuits.Remove(sendto); | ||
491 | } | ||
492 | else | ||
493 | { | ||
494 | m_log.DebugFormat( | ||
495 | "[UDPSERVER]: endpoint for circuit code {0} in RemoveClientCircuit() was unexpectedly null!", circuitcode); | ||
496 | } | ||
497 | } | ||
498 | lock (proxyCircuits) | ||
499 | { | ||
500 | proxyCircuits.Remove(circuitcode); | ||
501 | } | ||
502 | } | ||
503 | } | ||
504 | |||
505 | public void RestoreClient(AgentCircuitData circuit, EndPoint userEP, EndPoint proxyEP) | ||
506 | { | ||
507 | //MainLog.Instance.Verbose("UDPSERVER", "RestoreClient"); | ||
508 | |||
509 | UseCircuitCodePacket useCircuit = new UseCircuitCodePacket(); | ||
510 | useCircuit.CircuitCode.Code = circuit.circuitcode; | ||
511 | useCircuit.CircuitCode.ID = circuit.AgentID; | ||
512 | useCircuit.CircuitCode.SessionID = circuit.SessionID; | ||
513 | |||
514 | lock (clientCircuits) | ||
515 | { | ||
516 | if (!clientCircuits.ContainsKey(userEP)) | ||
517 | clientCircuits.Add(userEP, useCircuit.CircuitCode.Code); | ||
518 | else | ||
519 | m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); | ||
520 | } | ||
521 | |||
522 | // This data structure is synchronized, so we don't need the lock | ||
523 | if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) | ||
524 | clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP); | ||
525 | else | ||
526 | m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding."); | ||
527 | |||
528 | lock (proxyCircuits) | ||
529 | { | ||
530 | if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code)) | ||
531 | { | ||
532 | proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP); | ||
533 | } | ||
534 | else | ||
535 | { | ||
536 | // re-set proxy endpoint | ||
537 | proxyCircuits.Remove(useCircuit.CircuitCode.Code); | ||
538 | proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | PacketServer.AddNewClient(userEP, useCircuit, m_assetCache, m_authenticateSessionsClass, proxyEP); | ||
543 | } | ||
544 | } | ||
545 | } | ||