Compare commits

...

462 Commits
master ... dsg

Author SHA1 Message Date
Dan Lake bcd7f30089 Fixed RegionSyncAvatar changed definition for SendTextBoxRequest in IClientAPI 2012-01-24 17:26:37 -08:00
Dan Lake 0b60cb84ea Merge branch 'dev' into dsg 2011-07-25 16:08:32 -07:00
Dan Lake 1091001cf6 Merge branch 'master' into dev
Conflicts:
	OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
2011-07-25 16:08:00 -07:00
Dan Lake d0c5d592c2 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-07-25 16:04:15 -07:00
Dan Lake b844abf852 Merge branch 'dev' into dsg 2011-07-25 10:14:57 -07:00
Dan Lake 2aaad3c91a Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-07-25 10:14:22 -07:00
Dan Lake a8a31616f4 Remove BulletSim.dll 2011-07-25 10:13:40 -07:00
Huaiyu (Kitty) Liu a08bf6a12c Updated SOP.GetTerseUpdateProperties(), remove Scale and add PA_Acceleration 2011-07-20 16:12:20 -07:00
Dan Lake 191ef5daf1 Merge branch 'dev' into dsg 2011-07-20 14:55:35 -07:00
Dan Lake d0dd597351 Initialized localID for new PEPrim in AddPrimShape 2011-07-20 14:55:15 -07:00
Dan Lake cc7f04ea47 Merge branch 'dev' into dsg 2011-07-20 14:45:25 -07:00
Dan Lake 5171f3adf7 made localID fix to AddPrimShape in PEScene.cs 2011-07-20 14:43:19 -07:00
Dan Lake 90562f0735 Merge branch 'master' into dev 2011-07-20 14:40:39 -07:00
Dan Lake a311ba0483 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-07-20 14:37:46 -07:00
Dan Lake 30a9cee425 Merge branch 'master' into dev
Conflicts:
	OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
	OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
	OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
	OpenSim/Region/Framework/Scenes/UndoState.cs
2011-07-20 14:35:06 -07:00
Dan Lake 19678da2ec Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-07-19 10:46:58 -07:00
Dan Lake 396f4408cd Merge branch 'dev' into dsg 2011-07-15 15:34:33 -07:00
Dan Lake eb95762769 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-07-15 15:34:00 -07:00
Dan Lake 7447765f4d Merge branch 'master' into dev
Conflicts:
	OpenSim/Region/Framework/Scenes/Scene.cs
	OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
	OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
2011-07-15 15:32:42 -07:00
Dan Lake 333fa2f072 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-07-14 10:11:19 -07:00
Robert Adams 5a78c715ea reorder the lookup of physics actor since looking up a SOG by UUID is VERY slow if the SOG does not exist 2011-07-13 10:42:25 -07:00
Huaiyu (Kitty) Liu aa5208b78f Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-07-06 14:00:15 -07:00
Huaiyu (Kitty) Liu f029bd7782 Reimplement AddNewSceneObjectBySync in SceneGraph.cs and DeleteSceneObjectBySync in Scene.cs,
so that they are eventually calling OpenSim's implementation of AddSceneObject and DeleteSceneObject.

Also, fixed a bug in syncing position of attachments.
2011-06-30 16:44:01 -07:00
Dan Lake c06d9569d2 Merge branch 'dev' into dsg 2011-06-30 14:33:04 -07:00
Robert Adams 6574690c7b Add FullPartID dictonary entry into AddNewSceneObjectBySync 2011-06-30 14:10:00 -07:00
BlueWall 60798f77a8 Small fix to prebuild.xml for Monodevelop build system 2011-06-30 15:46:02 -04:00
Dan Lake 7127910b3d Merge branch 'dev' into dsg 2011-06-30 11:03:59 -07:00
Huaiyu (Kitty) Liu 5e8f24a44a Remove some debug messages for syncing property shape. 2011-06-29 16:07:38 -07:00
Huaiyu (Kitty) Liu 1da0f6e9d9 Changed object type of the copy of SOP property "Shape" from string to PrimitiveBaseShape,
in RegionSyncModule's cache of each SOP (see PropertySyncInfo.ToOSDMap(), FromOSDMap()).
2011-06-29 11:41:46 -07:00
Huaiyu (Kitty) Liu 64b39bf0f3 Added some debug messages. 2011-06-29 10:11:21 -07:00
Huaiyu (Kitty) Liu 981ac91393 Changed the writer/reader access functions to m_primsInSync in PrimSyncInfoManager. 2011-06-28 14:47:56 -07:00
Huaiyu (Kitty) Liu 9817734adf Line ending conversions. 2011-06-28 10:59:51 -07:00
Robert Adams 664f1ad2be Fix avatars pushing other avatars in ODE 2011-06-23 12:25:44 -07:00
Dan Lake c90c94e788 Merge branch 'master' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dsg 2011-06-21 16:59:22 -07:00
Dan Lake f5eb2ffe93 Merge branch 'master' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-06-21 16:58:34 -07:00
Dan Lake b71b7b2f7c Updated CacheUserName to work without circuit data on non-client manager actors. I need to fix this long term by creating a circuit data on non-cm actors and synchronizing properties across using sync layer. 2011-06-21 16:55:31 -07:00
Dan Lake 7573d3a1ac Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-06-21 10:44:54 -07:00
Dan Lake 974292996a * Switched Intel license for OpenSim contributors in DSG files
* Added Intel Corporation copyright for DSG to contributors.txt file
* Removed non-DSG bullet development files
2011-06-17 15:21:54 -07:00
Dan Lake e6141db0dc * Switched Intel license for OpenSim contributors in DSG files
* Added Intel Corporation copyright for DSG to contributors.txt file
* Removed non-DSG bullet development files
2011-06-17 15:18:31 -07:00
Huaiyu (Kitty) Liu c46f8ab291 Line ending conversion. 2011-06-16 14:19:46 -07:00
Huaiyu (Kitty) Liu 492d684911 Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-06-16 09:51:40 -07:00
Dan Lake 2c27067dec Fixed typo in merge 2011-06-15 15:38:16 -07:00
Dan Lake b6d93d0c40 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev
Conflicts:
	OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
	OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/GridDialogModule.cs
2011-06-15 15:26:17 -07:00
Dan Lake 66f905b09c Fixed up merge conflicts from master due to changes in sending IMs
between DSG regions
2011-06-15 15:05:17 -07:00
Dan Lake 327f30e6d1 Merge branch 'master' into dev
Conflicts:
	OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
	OpenSim/Region/Physics/Manager/PhysicsActor.cs
	OpenSim/Region/Physics/Manager/PhysicsScene.cs
2011-06-15 14:13:58 -07:00
Dan Lake 97ea994a4b Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-06-15 13:43:57 -07:00
Dan Lake 8791e5dac0 Working out merge errors with master 2011-06-15 13:43:02 -07:00
Huaiyu (Kitty) Liu c0c9a1d9da Line ending convertion. 2011-06-15 09:55:52 -07:00
Dan Lake 9c15c8897e Merge branch 'master' into dev 2011-06-14 23:16:48 -07:00
Dan Lake fc67a9212e Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-06-14 23:16:02 -07:00
Dan Lake 32ddcefaca Merge branch 'master' into dev
Conflicts:
	OpenSim/Region/Framework/Scenes/EventManager.cs
	OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
	OpenSim/Region/Framework/Scenes/Scene.cs
	OpenSim/Region/Framework/Scenes/SceneGraph.cs
	OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
	OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
2011-06-14 23:15:34 -07:00
Huaiyu (Kitty) Liu 941cec5548 Added code to propagate ScriptLandCollidingStart, ScriptLandColliding, and
ScriptLandCollidingEnd events.
2011-06-14 16:48:21 -07:00
Huaiyu (Kitty) Liu 57a42508ec Added AbsolutePosition as another SOP property to sync across, yet made
it a group property, so that only RootPart will trigger a sync message
for this property. An optimization to avoid sending many position updates
for linkset objects.
2011-06-14 14:53:12 -07:00
Dan Lake 0bd24d1f14 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-06-10 12:55:27 -07:00
Robert Adams 6dc15dcb0c Tweek to BSCharacter to not send avatar updates continuiously. Newest version of 64 bit BulletSim.dll 2011-06-08 16:14:11 -07:00
Robert Adams 16aa0f73e5 Upgrade to 64 bit version of BulletSim 2011-06-08 09:45:42 -07:00
Huaiyu (Kitty) Liu 7c542be833 When TaskInventory value is synced across, each receiver will also call
Inventory.ForceInventoryPersistence, so that PSA will see HasInventoryChanged
set to true and do proper persistence backup.

Also, added ScheduleSyncUpdate in UpdateInventoryItem, so that the new
TaskInventory item will be propagated to all actors.
2011-06-06 15:22:23 -07:00
Huaiyu (Kitty) Liu d28c857232 Added code to also propagate ScriptColliding and ScriptCollidingEnd events. 2011-06-06 11:39:22 -07:00
Huaiyu (Kitty) Liu 90abbe26d3 Added code in SyncDebug to debug the save-and-refire of collision_start event. 2011-06-05 11:18:35 -07:00
Huaiyu (Kitty) Liu fb716dbd68 Added code to save and refire collision_start event if the colliders are not found in
local scene yet.
2011-06-04 23:17:56 -07:00
Dan Lake 71d991fe8a Added a cache to message transfer module for UUID->GridRegion data 2011-06-04 19:56:36 -07:00
Huaiyu (Kitty) Liu 0319807820 Only ScriptCollidingStart is propogated from PE now. Code added to sync that event. 2011-06-04 15:09:41 -07:00
Huaiyu (Kitty) Liu a48511ee30 Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-06-03 13:35:19 -07:00
Huaiyu (Kitty) Liu 7b8db83bd3 Edited a few debug messages. 2011-06-03 13:34:18 -07:00
Huaiyu (Kitty) Liu 22f5f7962c Added code so that collision events are only forwarded from PSA to script engines. 2011-06-03 13:17:44 -07:00
Dan Lake 3eb13b6664 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-06-03 13:13:23 -07:00
Dan Lake 6b31808f49 Added back the 32bit ODE dll as ode.32bit.dll in case someone wants to use it 2011-06-03 13:12:59 -07:00
Dan Lake ef8b2f4711 Replaced ode.dll with 64 bit version 2011-06-03 13:10:00 -07:00
Huaiyu (Kitty) Liu 8ab8969d82 Fixed the problem of non-recoganized localID in PhysicsCollision -- if it is 0,
it means it's land collision, not errors.
2011-06-03 12:06:58 -07:00
Huaiyu (Kitty) Liu 06d002cc3b On handling UpdatePrimProperties, if the properties updated are all in the terse-update
list, only trigger SOP.ScheduleTerseUpdate; otherwise, trigger ScheduleFullUpdate.
This is to prevent client managers to send big updates to clients, especially when a link-set
object moves around.
2011-06-03 11:35:37 -07:00
Huaiyu (Kitty) Liu fa892e4afb Fixed bug(s) in CompareAndUpdateSOPGroupPosition and CompareAndUpdateSOPPosition
that may cause script engine to crash.
2011-06-02 16:37:01 -07:00
Huaiyu (Kitty) Liu fdb4e92dc3 Added/edited a few debug messeges to provide more info for debugging. 2011-06-02 13:35:20 -07:00
Huaiyu (Kitty) Liu fd99eea0af Added lock(m_syncRoot) in handling NewAvatar messages, so that adding/removing
from RemoveAvatars list are serialized.
2011-06-02 12:00:03 -07:00
Huaiyu (Kitty) Liu ee7b965bf9 Commented out debug messages for VolumnDetect sync and collisions.
Took out the warning message when reported collided SOP/SP is no
longer is local Scene.
2011-06-02 10:58:39 -07:00
Huaiyu (Kitty) Liu b03ecf24c4 Added catching exceptions other than WebException in doIMSending, so that
it won't crash script engine and will report what exception it is.
2011-06-01 15:37:14 -07:00
Huaiyu (Kitty) Liu 1cbbb010b0 Edited a warning message in collision event sync, to be more informational. 2011-06-01 14:19:27 -07:00
Huaiyu (Kitty) Liu e2b6c5d199 Added a new RegionSyncMessage, AvatarTeleportSameRegion, for PSA to inform PE to
update avatar positon after teleporting within the same region, and the logic
to send/receive the message. Teleporting within the same region seems working now
with remote PE.
2011-06-01 11:34:42 -07:00
Huaiyu (Kitty) Liu 3c58a1c244 Merge branch 'dev' into dev_demo_debug 2011-06-01 10:06:42 -07:00
Huaiyu (Kitty) Liu 8dc3b85828 Marked ChangingActorID in PECharacter constructor, so that PEScene.Simulate()
will catch the update (pos, etc) and trigger RouteUpdate.
2011-06-01 10:02:50 -07:00
Dan Lake 3a582a4cec TEMP: commented out agent limits in scene as a workaround for DSG demos 2011-06-01 10:01:04 -07:00
Robert Adams b3efab2bbd Add ChangingActorID setting for value changes from physics engine. Works much better distributed 2011-05-31 17:48:37 -07:00
Robert Adams bfb1068eca Fix for avatar jiggling in place and scooting after stop 2011-05-31 17:14:24 -07:00
Huaiyu (Kitty) Liu a17f0a0ea1 Fixed the problem that notecard updating was not propagated -- now syned
across actors, bit viewers may not always get the correct update.
2011-05-31 16:23:06 -07:00
Huaiyu (Kitty) Liu 0be7f9d804 Fixed bug in GridDialogModule that sends infinite Dialog messages.
Added ScheduleFullUpdate to llSetObjectName, so that the property change is captured by sync module.
2011-05-31 12:54:22 -07:00
Huaiyu (Kitty) Liu dc572c770c Added files GridDialogModule.cs and IGridDialogModule.cs to git repository. 2011-05-27 15:07:02 -07:00
Huaiyu (Kitty) Liu 83e3a6a59a Added display of script compilation errors on ScriptEngine's concole (log),
as temp solution for getting the errors.
2011-05-27 14:43:04 -07:00
Huaiyu (Kitty) Liu d375491142 Fixed bugs in GridDialogModule.cs, llDialog now works in DSG mode in preliminary tests. 2011-05-27 14:10:36 -07:00
Huaiyu (Kitty) Liu 40809775dd Added IGridDialogModule and GridDialogModule to support dialog in DSG mode. 2011-05-27 10:54:31 -07:00
Huaiyu (Kitty) Liu 67eaa574a3 started to add functions to support llDialog in DSG mode. 2011-05-27 09:56:41 -07:00
Huaiyu (Kitty) Liu 1cca4a978d In propagating PhysicsCollision event across actors, sending the list of UUIDs
of collision objects, instead of localIDs.
llVolumeDetect() now seems working, at least with integrated physics.
2011-05-26 14:54:03 -07:00
Huaiyu (Kitty) Liu c3c566cd24 Added synchronization of SOP property VolumnDetectActive, and proper actions following
its setting to true.
2011-05-26 14:15:23 -07:00
Huaiyu (Kitty) Liu 486497331c When Flags is updated on a prim, call UpdatePrimFlagsBySync to trigger appropriate
actions when flags are changed.
2011-05-26 12:17:17 -07:00
Huaiyu (Kitty) Liu d79a37e0ca Added reporting of LocalFlags property update in a few more spaces. 2011-05-25 16:27:32 -07:00
Huaiyu (Kitty) Liu 8fa03afb5c Added forwarding of teleport request, if the teleport is within the same region,
from CM to PSA. Both the hosting CM and PSA will trigger the same region
teleport code, PSA will then sync the new position to other CMs.
2011-05-25 15:47:00 -07:00
Huaiyu (Kitty) Liu 384e39f225 Merge branch 'dev_IM' into dev 2011-05-25 13:16:26 -07:00
Huaiyu (Kitty) Liu 4a68faf243 Some line ending inconsistency caused this commit in RegionSyncAvatar.cs 2011-05-25 13:15:51 -07:00
Huaiyu (Kitty) Liu a664835b03 Added implementation of SendInstantMessage() in RegionSyncAvatar, and
SendGridInstantMessageViaXMLRPC to IMessageTransferModule to enable
proper forwarding of instance messages.
2011-05-25 13:11:55 -07:00
Robert Adams 53fa87ad76 new BulletSPlugin and version of BulletSim.dll 2011-05-24 17:09:45 -07:00
Dan Lake 080db3019e Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-05-20 17:13:18 -07:00
Dan Lake 17cc7563ad Fix setting of ChangingActorID when physics is changing attributes. 2011-05-20 17:12:51 -07:00
Huaiyu (Kitty) Liu 41317dda8e Added AttachObjectBySync and calling it from AddNewSceneObjectBySync to
link avatar and attachments, and to update viewers properly.
2011-05-20 16:30:19 -07:00
Huaiyu (Kitty) Liu f1800824eb Set ScenePresence.IsSyncedAvatar to true in right places, so that only the client manager
that has the client connection will trigger agent crossing.
2011-05-19 16:31:02 -07:00
Huaiyu (Kitty) Liu ef4caa2c75 Merge branch 'dev' into dev_attachment 2011-05-19 13:46:35 -07:00
Huaiyu (Kitty) Liu ab0630ed81 Fixed code in handling setting attachedAvatar when its UUID.Zero.
Removed some obselete and debug code.
2011-05-19 13:44:15 -07:00
Robert Adams 95ce0caa76 Add ConvexDecompositionDotNet 2011-05-19 13:36:01 -07:00
Dan Lake 973d0fcdaa Prevent checking for border crossings for synced avatars. This causes border crossings to happen only on the client manager where the real client is connected and the result is synced to other actors. 2011-05-19 13:32:27 -07:00
Dan Lake cfee54ffa0 Added execute permission to runprebuild2010.bat 2011-05-19 13:31:21 -07:00
Robert Adams 105e5913f6 Add the BulletSim.dll to the OpenSim binaries 2011-05-19 12:58:03 -07:00
Robert Adams 05dbf31567 Adding BulletSim module 2011-05-19 12:50:29 -07:00
Robert Adams b0173de7ec Add localID to prim and avatar physics creation calls 2011-05-19 12:10:53 -07:00
Robert Adams 83d67391f1 Fix physical actor update by passing additional attributes when physics terse update happens 2011-05-18 08:30:59 -07:00
Huaiyu (Kitty) Liu 2f7ecf359b Merge branch 'dev' into dev_attachment 2011-05-17 10:49:35 -07:00
Huaiyu (Kitty) Liu 0e1efc3250 Added some debug messages for avatar border crossing. 2011-05-17 10:33:58 -07:00
Dan Lake a0a8654c07 Fix check for vanilla opensim. Should not check for border crossing on non-CM actors. 2011-05-17 10:31:35 -07:00
Huaiyu (Kitty) Liu 6ec6fe6745 Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-05-16 09:32:08 -07:00
Huaiyu (Kitty) Liu 3f07bf204b Commented out a line of code in RegionSyncServerModule so that on CM, SE and other actors,
scene.RegionSyncEnabled will be set and kept as "true" as desired.
2011-05-16 09:30:03 -07:00
Dan Lake cd6f261d11 Merge branch 'master' into dev 2011-05-13 15:59:40 -07:00
Dan Lake 7b94264798 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-05-13 15:58:41 -07:00
Huaiyu (Kitty) Liu d04c298c0b Removed code for handling UpdatedObject sync messages. We no longer send this message. 2011-05-12 15:47:04 -07:00
Huaiyu (Kitty) Liu cf6c9e77a0 Removed old code in RegionSyncServer/Client that were used for object syncing in the asymmetric sync era. 2011-05-12 14:36:55 -07:00
Huaiyu (Kitty) Liu 33fe1e9f76 Removed RegionSyncMessages that are no longer in use, and some other code that have been commented out. 2011-05-12 09:38:03 -07:00
Huaiyu (Kitty) Liu ef66b29e95 Removed Bucket Sync code from SceneObjectPart. Bucket Sync should be gone now. 2011-05-11 16:42:38 -07:00
Huaiyu (Kitty) Liu 6c945ae38f Removed calling of AddOrUpdateObjectBySynchronization from Scene and SceneGraph.
Removed Bucket Sync related code from SceneObjectGroup.
2011-05-11 16:23:31 -07:00
Huaiyu (Kitty) Liu 4fc36b0748 Rewrote sender and receiver of SymmetricSyncMessage.MsgType.NewScript, where
per property encoding is used.
2011-05-11 15:56:55 -07:00
Huaiyu (Kitty) Liu ba948251fe Removed BucketSync code from RegionSyncModule. 2011-05-11 14:45:01 -07:00
Huaiyu (Kitty) Liu 7aaacbc4a6 Removed IScriptEngineToSceneConnectorModule interface.
Removed SendNewObject, SendDeleteObject, SendLinkObject, and SendDelinkObject that used Bucket Sync info.
2011-05-11 14:25:22 -07:00
Huaiyu (Kitty) Liu ff5c86c90a More code cleaning following last commit (removed code that was commented out). 2011-05-11 14:11:35 -07:00
Huaiyu (Kitty) Liu a7d7ca9b0f Removed ScriptEngine to Scene asymmetric sync code, and LocX,LocY in SOG.
Also, removed QuickInfo related code from RegionSyncUtil.cs.
2011-05-11 14:04:34 -07:00
Huaiyu (Kitty) Liu 9b955d8e95 Removed code in SceneGraph, SceneObjectGroup and SceneObjectPart that were either commented
out before, or no longer in use.

Base for removing BucketSyncInfo.
2011-05-11 12:03:02 -07:00
Huaiyu (Kitty) Liu 8497ecd28d Removed DSG added code for some properties that were not included in legacy SceneObjectSerializer implementation.
The file now is almost back to its legacy shape, with a few DSG edits.
2011-05-11 11:37:32 -07:00
Huaiyu (Kitty) Liu c979fdd3cb Added checking if PhysActor is null or not in passing list of updated properties, especially for code (e.g. ScheduleGroupForTerseUpdate) that
pass SceneObjectPartSyncProperties.Orientation as an updated property.
2011-05-11 11:27:51 -07:00
Huaiyu (Kitty) Liu 9f6c0e7622 Added code to handle the case where attachement objects are received, but the avatar they
attach to is not created locally yet.
2011-05-10 16:27:25 -07:00
Dan Lake 9556e0079b Merge branch 'master' into dev
Conflicts:
	OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
	OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
	OpenSim/Region/Framework/Scenes/Scene.cs
2011-05-05 14:24:27 -07:00
Dan Lake ee16ca551d Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-05-05 13:21:29 -07:00
Huaiyu (Kitty) Liu 75c97acab8 Added a few "try, catch" phrases to help catch errors when sync'ing new objects or updating prim properties. 2011-05-05 12:23:37 -07:00
Huaiyu (Kitty) Liu f5e648f54a Added AddNewSceneObjectByRez, which when called, won't trigger RegionSyncModule.SyncNewObject.
The caller of AddNewSceneObjectByRez will trigger that later when all object properties have
been set.
Also, added calling aggregateScriptEventSubscriptions() after AddNewSceneObjectBySync(), so that
collision events in PhysActor, after it is created, are subscribed.
2011-05-05 10:22:16 -07:00
Huaiyu (Kitty) Liu 854cb58d6d Revised SetSOPPropertyValue in RegionSyncModule.cs:
added calling aggregateScriptEventSubscriptions() after SOP.AggregateScriptEvents is set.
        for properties AttachedAvatar and AttachmentPoint, do extra work besides copying the property values.
Propogation of colission event and attachment (attached after avatar login) both working now.
2011-05-04 14:36:18 -07:00
Huaiyu (Kitty) Liu cd70c3ff56 Merge branch 'dev_perPropertyTS' into dev
Conflicts:
	OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
2011-05-03 16:55:23 -07:00
Huaiyu (Kitty) Liu 04d406a7c8 Added code to sync each SOP's LocalFlags property. Also, in DeselectPrim, feed the list of updated properties as FullUpdate,
instead of only the IsSelected property, since SOP's Name, Description and some other properties might just have been edited
by a user.
2011-05-03 14:48:14 -07:00
Huaiyu (Kitty) Liu 4afd3f6602 Commented out some debug messages. 2011-05-03 14:38:21 -07:00
Huaiyu (Kitty) Liu 4acd23f0f9 In SyncOutPrimUpdates(), calling UpdatePrimSyncInfoByLocal again before calling
SendPrimPropertyUpdates, to make sure local updates are sync'ed into
RegionSyncModule's cache.
2011-05-03 14:25:05 -07:00
Huaiyu (Kitty) Liu eeb09f33e3 Add locking on m_primSyncInfoLock in InitPropertiesBySync and InitPropertiesSyncInfoFromOSDMap. 2011-05-03 13:54:59 -07:00
Huaiyu (Kitty) Liu f8bf6c2cc4 Removed a few debug messages from previous commit, then the problem shows up again. It seems due to the script
engine, after rezzing the pebbles and changing their shapes, the cached values in RegionSyncModule not properly
sync'ed with SOP's data.
2011-05-03 13:37:55 -07:00
Huaiyu (Kitty) Liu 54ba7a61f8 Added back some debug messages, seems now shapes are sync'ed properly again. 2011-05-03 13:16:39 -07:00
Huaiyu (Kitty) Liu c07c46c147 For debugging shape not sync'ed properly problem: adding back debug messages in
CompareHashedValue_UpdateByLocal
       	HandleUpdatedPrimProperties
2011-05-02 16:48:25 -07:00
Huaiyu (Kitty) Liu 7157398d77 For debugging shape not sync'ed properly problem: adding back debug messages in
CompareHashedValue_UpdateByLocal
	SetSOPPropertyValue
2011-05-02 16:39:03 -07:00
Huaiyu (Kitty) Liu bceafb4291 removed a bunch of debug messages, which were added to debug why shape was not synchronizing properly. 2011-05-02 15:17:17 -07:00
Huaiyu (Kitty) Liu 49139f53bb Replaced all calling to SendLinkObject to SyncLinkObject.
Added a bunch of debugging message to keep track of Shape updates synchronization.
2011-04-29 16:49:53 -07:00
Dan Lake c9b0a79f88 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-04-29 15:51:28 -07:00
Dan Lake 5aaccf793d Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-04-29 15:30:01 -07:00
Dan Lake 3e74a72d2e Merge branch 'master' into dev
Conflicts:
	OpenSim/Client/MXP/ClientStack/MXPClientView.cs
	OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
	OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
	OpenSim/Region/Framework/Scenes/ScenePresence.cs
2011-04-28 16:31:40 -07:00
Dan Lake c7fa637f0d Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-04-28 16:15:04 -07:00
Huaiyu (Kitty) Liu cb6630aa35 For functions in PrimSyncInfo that access per property sync info, adding checking
of if m_propertiesSyncInfo[property] exists before accessing it.
2011-04-22 16:57:22 -07:00
Huaiyu (Kitty) Liu 3076761d77 For group properties, only trigger SendPrimPropertyUpdates for the rootpart,
to avoid multiple updates (each through a different part in the SOG) to
update the same property.

Also, change m_log in PrimSyncInfo and PropertySyncInfo to a class static
variable, to reduce initiation cost.
2011-04-22 10:39:36 -07:00
Huaiyu (Kitty) Liu 68375822cd Fixed code so that when GroupPosition or Position is synced between PrimSyncInfoManager
and SOP, the other will be udpated properly as well.
Also, in SOP.aggregateScriptEvents, add AggregateScriptEvents as one property that has changed.
2011-04-21 17:44:07 -07:00
Huaiyu (Kitty) Liu b182e3bf30 In SyncLinkObject and SyncDelinkObject, copy property values from linked/delinked SOP
values to those in PrimSyncInfo, before sending out sync messages.
2011-04-20 17:34:55 -07:00
Huaiyu (Kitty) Liu 1c1d3893fc DelinkFromGroup now calls AddNewSceneObjectByDelink, to avoid calling SyncNewObject later.
Also, replace all "SYMMETRIC SYNC" with "DSG SYNC" in comments.
2011-04-20 14:59:06 -07:00
opensim 4319d974b2 Added DSG to version string 2011-04-19 16:02:38 -07:00
Huaiyu (Kitty) Liu a5ebd04d9d Fixed code in SyncDeLinkObject and HandleSyncDelinkObject. Delinking a few linked objects seems working. 2011-04-19 15:55:04 -07:00
Huaiyu (Kitty) Liu 3676b5fbef 1. Replaced SendLinkObject and SendDeLinkObject with SyncLinkObject and SyncDeLinkObject
2. Replaced HandleLinkObject and HandleDelinkObject with HandleSyncLinkObject and HandleSyncDelinkObject.
LinkObject seems sync'ed well across actors.
2011-04-19 14:49:47 -07:00
Dan Lake da6044b6be Merge branch 'master' into dev
Conflicts:
	OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs
	OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
	OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
	OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
	OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
2011-04-19 11:52:25 -07:00
Huaiyu (Kitty) Liu 3d7cece491 Include serialization of Scale in SOP.Shape (it's a sub property in Shape, and also a seperate SOP property,
both pointing to the same copy), so that now serialization of Shape has all its sub properties.
2011-04-19 11:11:14 -07:00
Huaiyu (Kitty) Liu 85085977ac Fixed a bug in ScheduleTerseUpdate, and added a few debug lines. 2011-04-19 09:52:55 -07:00
Dan Lake f47d1c84cb Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2011-04-18 22:14:35 -07:00
Huaiyu (Kitty) Liu 28f401d95a Added RegionSyncModule.ProcessAndEnqueuePrimUpdatesBySync, and revised functions relavant
to processing and forwarding prim updates. Code good for 2 CM and PSA to sync on NewObject
and UpdatedPrimProperties.
2011-04-18 15:54:24 -07:00
Huaiyu (Kitty) Liu 8b08e4b176 Added sync message type UpdatedPrimProperties, to send prim property updates.
Sender/receiver functions most in place, need more testing.
2011-04-15 17:13:56 -07:00
Huaiyu (Kitty) Liu e84a7157b4 Added SyncDeleteObject to replace calling to SendDeleteObject. 2011-04-15 15:00:02 -07:00
Huaiyu (Kitty) Liu 21c48088d8 Added SyncNewObject() to IRegionSyncModule, to be called when new object is
added to local SceneObject (by local operation, not by receiving sync message).
Code seems good for initial sync when one CM connects to PSA.
2011-04-15 12:15:28 -07:00
Huaiyu (Kitty) Liu 9dfc0e92b8 Changed Enum type SceneObjectPartProperties to SceneObjectPartSyncProperties,
to indicate they are the properties synchronzed by the sync protocol.
Also, added UUID to PrimSyncInfo.
Encode/Decode SOP to/from OSDmap seems working fine now.
2011-04-15 10:42:57 -07:00
Huaiyu (Kitty) Liu d0938f57eb Added PrimSyncInfo.SetSOPPropertyValue(), and fixed bugs in decoding SOP (PhysActor properties). 2011-04-14 17:09:50 -07:00
Huaiyu (Kitty) Liu b9bfe6ba51 Fixed bugs in encoding/decoding SOG and SOPs, with per property sync info. 2011-04-13 13:43:25 -07:00
Huaiyu (Kitty) Liu c244bbe143 Majority of SOP encoding/decoding (per property and SyncInfo based) functions are in place. Need testing. 2011-04-12 15:05:51 -07:00
Huaiyu (Kitty) Liu 9d3de471a5 SyncOutPrimUpdates linked with EncodePrimProperties and SendPrimUpdateToRelevantSyncConnectors. 2011-04-11 15:43:58 -07:00
Huaiyu (Kitty) Liu a06dad37fd Added ProcessAndEnqueuePrimUpdateByLocal and SyncOutPrimUpdates to
RegionSyncModule, and PrimSyncInfo.PropertyToOSD.
2011-04-11 14:36:38 -07:00
Huaiyu (Kitty) Liu a06ddb9e88 Started to link RegionSyncModule.RecordPrimUpdatesByLocal with functions
in PrimSyncInfoManager. To to finished.
2011-04-08 17:10:09 -07:00
Huaiyu (Kitty) Liu 2f41b216d3 Updated PrimSyncInfo.CompareAndUpdateHashedValueByLocal, to overwrite SOP's
properties Shape and TaskInventory if PrimSyncInfo's value has newer timestamp.
2011-04-08 15:55:40 -07:00
Huaiyu (Kitty) Liu 7c033f9d08 Added calling ScheduleFullUpdate() after SendFullUpdateToAllClients() is called in
several places in LSL_Api.cs.
2011-04-08 15:16:39 -07:00
Huaiyu (Kitty) Liu 2dccc3205d Implemente PrimSyncInfo.CompareAndUpdateHashedValueByLocal, updated UpdatePropertiesByLocal
and a few update related functions in PrimSyncInfo.
2011-04-08 15:08:56 -07:00
Huaiyu (Kitty) Liu 2f17a9d224 Added more functions to PrimSyncInfo, and added class PrimSyncInfoManager.
Also, commented out a few not sync-relavent properties from SceneObjectPartProperties.
2011-04-07 15:34:09 -07:00
Huaiyu (Kitty) Liu fe3d4ec9a8 Re-implemented SOP.ScheduleFullUpdate and SOP.ScheduleTerseUpdate, calling RecordPrimUpdatesByLocal
to record updated values and timestamp of SOP's updated properties.

Also, removed some code that had been commented out before.
2011-04-06 14:38:14 -07:00
Huaiyu (Kitty) Liu 2bea8bb4bc Added class PropertySyncInfo and PrimSyncInfo in RegionSyncModule. 2011-04-06 12:23:04 -07:00
Robert Adams e5a022c8d7 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-04-04 11:26:50 -07:00
Robert Adams d71b49c2a4 Force HandleTerrainUpdate message to set the terrain no matter what the timestamp. This temp fix allows the initial terrain update to be set. 2011-04-04 11:26:10 -07:00
Dan Lake 2d775f9a52 Disabled queue logging by default 2011-04-01 10:37:39 -07:00
Huaiyu (Kitty) Liu 2abffd867f Fixed more bugs while merging in the functions from commit 5b79e15285. 2011-03-31 16:45:12 -07:00
Huaiyu (Kitty) Liu 8df517454d Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-03-31 11:41:01 -07:00
Robert Adams fa7a8fb9c1 Move event count from per connection to per event 2011-03-31 10:22:46 -07:00
Huaiyu (Kitty) Liu 170a230e51 Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-03-29 17:13:15 -07:00
Huaiyu (Kitty) Liu cce9a12dbe Fixed a few bugs introduced by my last commit. 2011-03-29 17:11:58 -07:00
Dan Lake ecee306d3c Merge branch 'master' into dev 2011-03-29 16:46:35 -07:00
Dan Lake a0be3e2c5f Merge branch 'master' of git://opensimulator.org/git/opensim 2011-03-29 16:45:30 -07:00
Dan Lake fe623f0900 Updated dev code to work with latest changes in opensim master 2011-03-29 16:29:00 -07:00
Dan Lake f89ae8700d Merge branch 'master' into dev 2011-03-29 16:04:55 -07:00
Dan Lake 8e6425dad7 Merge branch 'master' of git://opensimulator.org/git/opensim 2011-03-29 16:04:06 -07:00
Dan Lake 396ea3ba65 Merge branch 'master' of git://opensimulator.org/git/opensim 2011-03-29 14:58:23 -07:00
Huaiyu (Kitty) Liu 5b79e15285 Checked in Functions that encode/decode sync messages based on object/prim properties.
These functions will convert the GroupPosition or Postiion properties into/out of the encoding.
	NewObjectMessageEncoder
	GeneralBucketPropertiesEncoder
	PhysicsBucketPropertiesEncoder
	NewObjectMessageDecoder
	GeneralBucketPropertiesDecoder
	PhysicsBucketPropertiesDecoder

Also checked some changes to SendXXXToRelevantSyncConnectors functions.
2011-03-29 14:55:21 -07:00
Dan Lake 13057c3751 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-03-29 14:16:29 -07:00
Dan Lake 0445e6e251 Merge branch 'master' of git://opensimulator.org/git/opensim into dev 2011-03-29 13:42:01 -07:00
Huaiyu (Kitty) Liu eed53e8a56 Fixed terrain synchroniztion to work properly when clients edit the terrain via viewer. 2011-03-28 17:22:24 -07:00
Huaiyu (Kitty) Liu 0ad9366abb In InventoryAccessModule.RezObject, move the calling of AddNewSceneObject to the later part of
the function, so that the object's most properties have values already set when AddNewSceneObject
is called, which will trigger RegionSyncModule.SendNewObject to sync across scene copies.
2011-03-23 10:23:13 -07:00
Dan Lake 71566e31c2 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into sceneapi 2011-03-21 15:22:52 -07:00
Dan Lake 6e13ddf072 Added Mic's update logging patch 2011-03-21 15:21:55 -07:00
Huaiyu (Kitty) Liu fb8a91bc8d Removed some debug logs, and changed some from Debug to DebugFormat. 2011-03-21 14:51:03 -07:00
Huaiyu (Kitty) Liu 83b4d4121e Added CopyRight disclaimers in RegionSyncModule files. 2011-03-18 13:59:33 -07:00
Dan Lake 9704793a1c Refreshed from dev, fixed merge problems with packet category logging. (by removing the debug feature) 2011-03-18 12:36:09 -07:00
Huaiyu (Kitty) Liu b7dc2af5e6 Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-03-17 17:20:58 -07:00
Huaiyu (Kitty) Liu 4076cb4a3c Fixed a bug in RegionSyncModule.SendSceneUpdates: if there are no SyncConnectors in connection,
clear the update list before return.
Also, if a SyncConnector receives a request GetObject, only sends back NewObject to that SyncConnector.
2011-03-17 17:18:16 -07:00
Dan Lake ab6b9e5812 Changed warning to debug message for outgoing packet queues 2011-03-17 14:10:01 -07:00
Robert Adams 6e251b13c4 Merge branch 'dev' into collisionevent 2011-03-17 10:31:16 -07:00
Robert Adams 74903876eb Collision events generated by physics engine and processed by script engine. 2011-03-17 10:29:03 -07:00
Huaiyu (Kitty) Liu 0df0e92ff0 In RegionSyncModule.DoInitialSync(), calling DeleteAllSceneObjectsBySync() instead of DeleteAllSceneObjects(). 2011-03-16 16:36:54 -07:00
Huaiyu (Kitty) Liu 271f460bae Handler of SymmetricSyncMessage.MsgType.UpdatedObject changed to HandleUpdateObjectBySynchronization,
that is, since we add objects in scene by sending around NewObject, we no longer "add" objects after
receiving UpdateObject.
Also, ProcessBackup is now only executed by Persistece Actor (ScenePersistenceSyncModule, if configured
to run, will set each SOG's ToPersistObjectState to true).
2011-03-16 11:32:26 -07:00
Huaiyu (Kitty) Liu a8c722bead Added code to encode and decode all object properties, including those in Physics bucket,
to sending and handling received NewObject sync message.
Also, NewObject, RemoveObject, and LinkObject are now all sent out via
SendSceneEventToRelevantSyncConnectors, that is, they are sent out on wire right away,
not enqueue first.
2011-03-16 09:32:27 -07:00
Huaiyu (Kitty) Liu 04ef2366c2 Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev
Conflicts:
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
2011-03-15 11:26:46 -07:00
Huaiyu (Kitty) Liu 3d17bd5654 Reimplement logic in RegionSyncModule so that a SyncRelay node (e.g. PSA) only sends out updates for a bucket
that has properties updated in the last update interval: the previous implemenation has some flaws in design.
2011-03-15 11:21:46 -07:00
Dan Lake afca24acbe Added some debugging for queues. Temporary change 2011-03-14 22:37:09 -07:00
Dan Lake 10e405704a Added some debugging for queues. Temporary change 2011-03-14 22:17:51 -07:00
Dan Lake 7bcab8e975 Added some debugging for queues. Temporary change 2011-03-14 21:41:47 -07:00
Dan Lake 7a89cf5a68 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-03-14 12:52:52 -07:00
Dan Lake 3bdc04acf3 Added some debugging for queues. Temporary change 2011-03-14 12:52:10 -07:00
Robert Adams d5acb9a214 Merge branch 'dev' into syncstats 2011-03-11 16:34:50 -08:00
Huaiyu (Kitty) Liu 4803745c0d Added logic in RegionSyncModule so that a SyncRelay node (e.g. PSA) only sends out updates for a bucket
that has properties updated in the last update interval.
2011-03-11 16:29:10 -08:00
Robert Adams d70deaaa64 Merge branch 'dev' into syncstats
Conflicts:
	OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
2011-03-11 16:02:00 -08:00
Robert Adams e72f08e02a Default physics logging to off 2011-03-11 15:56:33 -08:00
Robert Adams 9edbbf2728 sync logging added to RegionSyncModule 2011-03-11 15:42:39 -08:00
Huaiyu (Kitty) Liu 37dd39fd5d Added SendNewObject to explicitly send out NewObject sync message when new objects are added. 2011-03-11 15:39:06 -08:00
Huaiyu (Kitty) Liu 48ad2010e5 removed some debug message. 2011-03-11 13:54:09 -08:00
Huaiyu (Kitty) Liu 1ab4df9954 In RegionSyncModule.PrimUpdatesPhysicsBucketSender, if no PhysicsActor for the SOP, still sending out
"GroupPosition" and a few other properties in physics bucket. Sync'ing of phantom objects now seems working fine.
2011-03-11 11:50:46 -08:00
Huaiyu (Kitty) Liu 13798f9f7d Fixed bugs in llCreateLink to sync LinkObject properly.
Also, added logs for debug purposes.
2011-03-11 09:22:32 -08:00
Robert Adams 7f6529af4e Merge branch 'dev' into syncstats 2011-03-10 14:13:41 -08:00
Robert Adams a1fa5c28c3 Add sync statistics collector class 2011-03-10 14:05:59 -08:00
Robert Adams cc2a679121 Sync statistics to a file 2011-03-10 14:04:10 -08:00
Huaiyu (Kitty) Liu b848df2a3a In LSL_Api.cs, no special checking of if ScriptEngineToSceneConnectorModule exist anymore --
async model is no longer used and we get rid of the old code.
2011-03-09 17:16:03 -08:00
Huaiyu (Kitty) Liu e4bdaaaa83 Added SyncStateReport function in RegionSyncModule to do some preliminary sync state comparison. 2011-03-09 16:31:53 -08:00
Robert Adams d514c31cc2 Merge branch 'dev' into syncstats 2011-03-08 14:23:41 -08:00
Robert Adams e0f28ac5ba Basic SyncConnector status for ssync status 2011-03-08 12:59:46 -08:00
Huaiyu (Kitty) Liu ae258a21e4 Added code to propogate event OnChatBroadcast (llOwnerSay is handled by this), and consolidate code
with events OnChatFromClient and OnChatFromWorld.
2011-03-08 11:00:52 -08:00
Huaiyu (Kitty) Liu 052af34a52 Added Shape as one of the properties just updated in MoapModule.SetMediaEntry. 2011-03-07 16:24:48 -08:00
Dan Lake b1114dcb98 Merge branch 'master' of git://opensimulator.org/git/opensim into dev
Conflicts:
	OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
2011-03-07 16:03:50 -08:00
Dan Lake e21176f974 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-03-07 15:58:36 -08:00
Dan Lake 7210b7f517 Merge branch 'master' of git://opensimulator.org/git/opensim into dev
Conflicts:
	OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
	OpenSim/Region/Framework/Scenes/Scene.cs
	OpenSim/Region/Framework/Scenes/ScenePresence.cs
2011-03-07 15:57:31 -08:00
Huaiyu (Kitty) Liu 3fe31ad457 Added back the LocalFlags as one of the SOP properties to be synced, so that script events such as touch is propogated properly.
Also removed some debug messages.
2011-03-07 15:51:59 -08:00
Robert Adams 59fbb9cbef Restore physics bucket serialization that was lost in previous commit 2011-03-03 11:37:24 -08:00
Robert Adams b76c233db3 Merge branch 'dev_kitty' into physbucket
Conflicts:
	OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs
2011-03-03 08:54:01 -08:00
Huaiyu (Kitty) Liu 91e8fc50d3 Change Constants.RegionSize back to 256. 2011-03-01 14:50:33 -08:00
Robert Adams 6b9d58b99b Make PECharacter sync PhysActor info back to physics actor. Remove some chatty debug messages. Add checks to warn if PhysicsActor synchronization is acting on a prim rather than a character. 2011-03-01 12:42:05 -08:00
Robert Adams 400c9b5293 Using PhysActor sync for avatars and bucket sync for prims. Working with avatars kicking physical objects 2011-02-28 14:09:19 -08:00
Robert Adams 11db34313d Restore old PhysicsActor sync code. Not tested yet 2011-02-25 16:54:04 -08:00
Robert Adams 319c48f112 Restore old PhysActor synchronization routines 2011-02-25 16:30:52 -08:00
Huaiyu (Kitty) Liu a5c55a19ef Merge branch 'dev' into dev_kitty 2011-02-25 16:23:57 -08:00
Huaiyu (Kitty) Liu f7de4f37ce Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-02-25 16:22:51 -08:00
Huaiyu (Kitty) Liu 9d613a20c0 Relocate functions within RegionSyncModule.cs: the IRegionSyncModule region now
only contains functions defined in IRegionSyncModule.
2011-02-25 16:20:58 -08:00
Robert Adams 153fd02f0f Add SimianGridServiceConnector::LookupEndpoint to get info on a particular sync server endpoint 2011-02-25 16:03:35 -08:00
unknown 784cb6c95c Changed some less important messages from Warn to Debug 2011-02-25 15:21:07 -08:00
Robert Adams f212a60067 Merge branch 'dev_kitty' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into physbucket
Conflicts:
	OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncAvatar.cs
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
2011-02-24 14:48:11 -08:00
Robert Adams 2335968271 Adding SOG/SOP to ScenePresence working more but confusion on UUID of presence vs SOG 2011-02-24 14:41:16 -08:00
Robert Adams 1ff16c93a3 Another attempt to add SOG/SOP to ScenePresence so it can be handled by bucket update code 2011-02-18 17:16:57 -08:00
Huaiyu (Kitty) Liu 513ca97eb0 Added code to propogate event OnAttach. 2011-02-18 17:05:25 -08:00
Huaiyu (Kitty) Liu 1d2a25689a RegionSyncServer and RegionSyncClient will not trigger RezAttachment anymore. Attachments
are synced via object sync protocol.
2011-02-18 16:08:12 -08:00
Huaiyu (Kitty) Liu 10a41ad5b5 Added code in SceneGraph.AddSceneObjectByStateSynch to handle attachment objects. 2011-02-18 15:49:01 -08:00
Robert Adams a25eac0a40 Remove old physics sync code. Attempt to fake ScenePresence in physics bucket sync 2011-02-18 08:11:29 -08:00
Robert Adams c9c94a5f23 Physics bucket packing and unpacking 2011-02-16 17:11:16 -08:00
Huaiyu (Kitty) Liu 3d1048f1e2 In SOG.UpdateGroupPosition, added AttachedPos as an updated property is the object is an attachment. 2011-02-16 16:57:47 -08:00
Huaiyu (Kitty) Liu 7b9bd89a5c Made sure IsAttachment is set only after AttachedAvatar is set. Also, in GroupPosition get, added checking of "if m_parentGroup==null". 2011-02-16 15:42:10 -08:00
Huaiyu (Kitty) Liu f99b516eec Added serialization/deserilaization of Attachment related SOP properties to sync AttachObject. 2011-02-16 14:29:08 -08:00
Huaiyu (Kitty) Liu e66668ad7e Some conflict, probably due to line ending at LocalGridServiceConnector.cs. Just commit the difference to move on. 2011-02-15 15:07:43 -08:00
Huaiyu (Kitty) Liu 21a1000da6 Physics bucket properties (a partial list implemented) seem be synchronized fine with simple tests (less than 10 prims, scripts running, link/delink). 2011-02-15 14:38:43 -08:00
Huaiyu (Kitty) Liu 94e433315e Added code to send and receive SymmetricSyncMessage.MsgType.UpdatedBucketProperties sync message. 2011-02-15 14:02:53 -08:00
Huaiyu (Kitty) Liu 7229aa204e In RegionSyncModule, now each property bucket has its own list of updated-prims.
An SOP will be inserted (now it's still its parent group will be inserted) into a bucket
if that bucket has been tained as updated.

Also, added Tainted property to BucketSyncInfo.
2011-02-14 17:08:49 -08:00
Huaiyu (Kitty) Liu f05502f3fe Merge branch 'dev' into dev_kitty 2011-02-14 14:56:48 -08:00
Huaiyu (Kitty) Liu 41c85d9fd1 Changed interface of ScheduleFullUpdate and ScheduleTerseUpdate, and pass a list of updatedProperties as the argument. 2011-02-14 13:54:34 -08:00
Dan Lake 1837778cf9 Merge branch 'master' into dev
Conflicts:
	OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
	OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
2011-02-14 13:39:27 -08:00
Dan Lake 4be96bc3d2 Merge branch 'master' of git://opensimulator.org/git/opensim 2011-02-14 13:27:59 -08:00
Huaiyu (Kitty) Liu 2b2eb4dbe3 Merge branch 'dev_kitty' into dev 2011-02-14 11:36:57 -08:00
Huaiyu (Kitty) Liu b31fa7d8fe Merge branch 'dev' of ssh://sceneapi@island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-02-14 11:36:25 -08:00
Huaiyu (Kitty) Liu 411fa60b2b RegionSyncModule.SendLinkObject and SendLinkObject now call BucketSyncInfoUpdate() for the linked/delinked
objects, to make sure they have updated timestamp information for synchronization purpose.
2011-02-14 11:33:57 -08:00
Robert Adams 4d343d0fea Move actor registration to actor modules. Add physics registation 2011-02-14 09:37:36 -08:00
Huaiyu (Kitty) Liu 63e35d53f7 Added implementation of GeneralBucketUpdateProcessor and PhysicsBucketUpdateProcessor 2011-02-11 16:51:38 -08:00
Huaiyu (Kitty) Liu f47c301a56 Added SOP.HasPropertyUpdatedLocally() to help enqueue the right set of objects that have properties updated locally.
Also, in RegionSyncModule.SendSceneUpdates, added calling sog.UpdateTaintedBucketSyncInfo() to update timestamp of a tainted property bucket.
2011-02-11 16:23:03 -08:00
Robert Adams 9970677ed8 Quark/Endpoint registration and lookup for three table database 2011-02-11 15:50:25 -08:00
Huaiyu (Kitty) Liu 7a331b6a8f Switched to use ScheduleFullUpdates() and ScheduleTerseUpdates() as the funnel to catch any property updates, so as to update bucket's sync
timestamp correctly. Code good for compilation, runtime not tested yet.
2011-02-11 15:31:13 -08:00
Huaiyu (Kitty) Liu 5ef659520e Access to sop.Shape.Scale replaced by sop.Scale. 2011-02-10 17:06:15 -08:00
Huaiyu (Kitty) Liu 88e42011af In current SOP class, overrode functions in SOPBase that modified values of Shape or properties of Shape. 2011-02-10 15:32:59 -08:00
Huaiyu (Kitty) Liu 1da933041c Started to added new access functions of SOP properties. 2011-02-10 11:37:34 -08:00
Robert Adams 4fe0bd32d4 Actor/Quark registration for Simian backend 2011-02-09 17:17:50 -08:00
Huaiyu (Kitty) Liu 3cd1ec8752 Renamed SOP and SOPInventory as SOPBase and SOPInventoryBase, and define new SOP and SOPInventory. The latters
will invoke UpdateBucketSyncInfo the set functions of their properties, while the base classes won't.
2011-02-09 17:17:16 -08:00
Huaiyu (Kitty) Liu a9ebb3ebae Merge branch 'dev_kitty_debug' into dev_kitty 2011-02-08 15:55:45 -08:00
Huaiyu (Kitty) Liu 2dc857b31d Added code to serialization/deserialize LocalFlags. Need further testing to see if it's necessary. 2011-02-08 15:55:00 -08:00
Huaiyu (Kitty) Liu e8e9a0fb43 Enabled all synchronized properties to be updated by calling through SetXXX() to set values. 2011-02-08 15:33:54 -08:00
Huaiyu (Kitty) Liu 29053b19d8 Added set functions for the last a few properties. For some property assignments
in SOP, changed from "m_xxx=" to "Xxx=" to trigger UpdateBucketSyncInfo() as desired.
2011-02-08 10:08:09 -08:00
Huaiyu (Kitty) Liu 9ee4a7e9f3 Merge branch 'dev_kitty_debug' into dev_kitty 2011-02-07 17:20:50 -08:00
Huaiyu (Kitty) Liu e9b831b8f4 1. Updated SOP.InventorySerial and SOP.TaskInventory set functions, to make sure only local write accesses trigger
UpdateBucketSyncInfo().
2. LinkObjectsBySync(), DelinkObjectsBySync(), and functions they call into, all updated to set properties via calling SetXXX instead of by "XXX=", so that the set operations won't trigger UpdateBucketSyncInfo().
2011-02-07 17:16:26 -08:00
Huaiyu (Kitty) Liu 6cb8b01bef Added m_syncEnabled in SceneObjectPart to guard again modifying any syncinfo (timestamp, etc) while
deserializing and building SOP/SOG out of sync message.
2011-02-07 14:15:33 -08:00
Huaiyu (Kitty) Liu 396486a93b Added set functions for the last a few properties in SOP. 2011-02-07 09:45:16 -08:00
Huaiyu (Kitty) Liu c929348668 Majority of SOP properties have set functions added. 2011-02-04 17:05:08 -08:00
Huaiyu (Kitty) Liu 2ae8917c2e Modified/added set functions for SOP properties: "AllowedDrop" to "Material", as listed in SceneObjectSerializer(). 2011-02-04 15:01:38 -08:00
Huaiyu (Kitty) Liu 4fe0c6d0d2 Fixed a few bugs. Code now good for updating the physics properties implemented in SOG. Events
propagation also seems working fine (chat, link/delink objects, delete, etc).
2011-02-04 11:09:00 -08:00
Robert Adams f5870a1e23 slight optimization in the actor registration code 2011-02-04 09:25:54 -08:00
Huaiyu (Kitty) Liu 62a9e0b7c4 No longer calling SyncInfoUpdate to update timestamp. Bucket based concurrency control now in place for a few physics properties
whose SetXXX() functions have been implemented in SceneObjectPart.
2011-02-03 17:21:00 -08:00
Huaiyu (Kitty) Liu 3cff68340f Implemented several SetXXXProperty functions. Set operation ("=") for these properties now first calls SetXXXProperty and then triggers UpdateBucketSyncInfo(). 2011-02-03 14:24:15 -08:00
Huaiyu (Kitty) Liu 97b01dcf75 check in updates in enabling bucket based synchronization. 2011-02-03 12:01:08 -08:00
Robert Adams 4a4ecb1cde Initial stubs and code for quark/actor registration and lookup 2011-02-02 17:34:53 -08:00
Huaiyu (Kitty) Liu c84551ae2c Serialization/deserialization with BucketSyncInfoList works fine with a single object. Haven't tested with multi objects/linksets yet. 2011-02-02 16:44:05 -08:00
Huaiyu (Kitty) Liu 9ca061b25a Starting add SetXXX() functions to SceneObjectPart, where XXX is each property's name. Also fixed some bugs in InitializeBucketSyncInfo 2011-02-02 15:46:12 -08:00
Huaiyu (Kitty) Liu ce4c8e4b6f Added code to include serialization/deserialization of BucketSyncInfoList in each SceneObjectPart. 2011-02-01 14:20:09 -08:00
Huaiyu (Kitty) Liu f36f1010b7 Started to add code for concurrency control of updating objec properties on per bucket base. Added code to
process to PrimPropertyBucketMap in RegionSyncModule and BucketSyncInfo in SceneObjectPart.
2011-02-01 10:07:20 -08:00
Dan Lake a7d4c974dd Added checks for null circuit data in AddNewClient2. In the case of RegionSyncAvatars being added to the scene, there will be no circuit data, no appearance data, and no teleport flags. 2011-01-31 14:32:34 -08:00
Dan Lake e709b55f01 Fixed compilation errors due to merge conflicts. AddNewAgent2 has been greatly reduced in complexity. We need to validate that it's going to do the right thing for the REGION SYNC cases. 2011-01-30 04:27:59 -08:00
Dan Lake a23ffa2262 Merge branch 'master' from git://opensimulator.org/git/opensim into dev
Conflicts:
	OpenSim/Region/Framework/Scenes/Scene.cs
2011-01-30 04:13:20 -08:00
Dan Lake ee10e23fc3 Merge branch 'master' of git://opensimulator.org/git/opensim 2011-01-30 04:04:04 -08:00
Robert Adams af29f4083f move logging to central module. Fix orientation bug. Fix message echo bug. 2011-01-28 13:59:04 -08:00
Huaiyu (Kitty) Liu 2ffa91d72a Commented out some debug messages. 2011-01-28 13:39:05 -08:00
Huaiyu (Kitty) Liu 1252df6f1e Added code to receive and process DelinkObject sync message. Preliminary delink tests seems running fine. 2011-01-28 12:11:42 -08:00
Huaiyu (Kitty) Liu 1b99c33e6c Added code to send out DelinkObject message at the actor that initiates the operation. 2011-01-27 16:19:36 -08:00
Robert Adams 270f7e653a Add rotationalVelocity and acceleration to variables that are synced in PhysicsActor. Remove unused Prop class. 2011-01-27 11:05:26 -08:00
Robert Adams 8d87d9e42d Add locking to prim and avatar lists to fix enumeration errors 2011-01-27 11:03:23 -08:00
Robert Adams cfab010b10 Add IClientCore to RegionSyncAvatar to fix cast error on teleport 2011-01-27 11:01:48 -08:00
Huaiyu (Kitty) Liu 85b7bb916f Added some if condition in RegionSyncModule.SendSceneUpdates, so that if no updates to send, no thread is assigned to send updates. 2011-01-26 17:17:03 -08:00
Huaiyu (Kitty) Liu 441551e7c6 Commented out debug messages in enabling LinkObject synchronization. 2011-01-26 16:39:18 -08:00
Huaiyu (Kitty) Liu 101d67c45b Enabled LinkObject to synchronize across actors. 2011-01-26 16:01:54 -08:00
Huaiyu (Kitty) Liu 4860eba0ba In SceneGraph.LinkObjects, call RegionSyncModule.SendLinkObject before parentGroup.LinkToGroup is called,
so that the actors who receive LinkObject message will get it before the soft-delete messages of the linked-in
parts.
2011-01-26 11:54:51 -08:00
Huaiyu (Kitty) Liu ea2dc04bac Merge branch 'dev_kitty' into dev 2011-01-25 11:15:13 -08:00
Dan Lake cf15fc0b97 Merge branch 'master' of git://opensimulator.org/git/opensim into dev
Conflicts:
	OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
2011-01-24 20:03:20 -08:00
Huaiyu (Kitty) Liu 65c4889474 Added SceneObjectPart.UpdateCollisionSound w/o calling CollisionSound set function, so that
not to trigger aggregateScriptEvent if not necessary (so as not to change LastUpdatedTimeStamp and
LastUpdatedActorID to local actor if CollisionSound is not changed).
2011-01-24 17:20:16 -08:00
Huaiyu (Kitty) Liu 005c743fae Added event SceneGraph.OnObjectCreateBySync, which will be triggered in AddSceneObjectByStateSynch.
ScriptEngineSyncModule now subscribes to this new event to create new script instances.
2011-01-24 16:25:33 -08:00
Robert Adams 3123671651 Configuration of PhysicsSyncServerAddress and port in regions file 2011-01-21 12:28:12 -08:00
Huaiyu (Kitty) Liu 677889d3b6 Get rid of SymSync in OpenSim.ini, old way of object sync no longer works (via RegionSyncServer).
SyncListenerAddress/Port renamed as SyncServerAddress/Port.
2011-01-20 16:19:51 -08:00
Huaiyu (Kitty) Liu e39d2ab14f Added DelinkFromGroupBySync and supporting functions to handle delink operations. 2011-01-20 15:58:48 -08:00
Huaiyu (Kitty) Liu 67858f0dcd Merge branch 'dev_kitty' into dev 2011-01-20 12:08:15 -08:00
Huaiyu (Kitty) Liu 43edf89a34 Changes names in Regions.ini, and added one more config item: SyncQuarkLocation. 2011-01-20 12:05:10 -08:00
Huaiyu (Kitty) Liu a0eddfcf61 Added AddNewPart for synchronization of linked objects. 2011-01-19 17:34:28 -08:00
Huaiyu (Kitty) Liu d874e4338f Added softDelete parameter to SendDeleteObject in object synch. 2011-01-19 17:17:16 -08:00
Dan Lake af07881a9f Add asset ID to simian request URLs 2011-01-19 13:44:07 -08:00
Dan Lake e9e36e2964 Merge branch 'prephysics' into dev 2011-01-19 13:06:28 -08:00
Dan Lake 7a1a21cd15 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-01-19 13:04:09 -08:00
Dan Lake b02d3090b3 Merge branch 'prephysics' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into prephysics 2011-01-19 13:02:50 -08:00
Dan Lake f09f74c224 Patches to appearance and inter-region comms 2011-01-19 13:02:08 -08:00
Huaiyu (Kitty) Liu b3179d34da reimplement SceneObjectGroup.UpdateObjectAllProperties to do parts updating differently, as
an attemp to make linkset updates correct, and rename the function UpdateObjectGroupBySync.
2011-01-19 10:52:06 -08:00
Robert Adams 8256caad3f Remove setting of localID on newly created avatar. This solves the case of later viewers in other regions not seeing position updates for other avatars. 2011-01-19 08:50:41 -08:00
Robert Adams c541b42f7e Converted PhysicsActor identification from localID to UUID 2011-01-18 16:52:37 -08:00
Robert Adams 42563e77fa Merge branch 'prephysics' into dev
Conflicts:
	OpenSim/Region/Framework/Scenes/SceneGraph.cs
2011-01-18 09:31:33 -08:00
Huaiyu (Kitty) Liu c8dc14fb01 Configuration of SyncListenerIPAddress, SyncListenerPort, ServerIPAddress, and
ServerPort is moved to Regions.ini.
2011-01-17 17:13:15 -08:00
Huaiyu (Kitty) Liu 719f59db3f Added code to propagate OnNewScript event, when client sends in RezScript request (e.g. add new script to a prim). 2011-01-14 16:58:06 -08:00
Huaiyu (Kitty) Liu 69476339df Merge branch 'prephysics_kitty' into prephysics 2011-01-14 09:56:43 -08:00
Huaiyu (Kitty) Liu 0be2fe7f13 Changed the way RemoveObject is handled: now Scene.DeleteSceneObject() calls RegionSyncModule to
send RemovedObject message to other actors for synchronization.
2011-01-13 15:36:44 -08:00
Huaiyu (Kitty) Liu c1e19ead74 Added ScheduleFullUpdate() in SceneObjectPart.AddInventoryItem(), to enable synchronization across actors. 2011-01-12 17:20:17 -08:00
Dan Lake e7e2a62641 Merge branch 'prephysics' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into prephysics 2011-01-11 19:19:44 -08:00
Dan Lake 039d919284 RefreshAppearance now tries to find the local avatar a few times before it gives up. 2011-01-11 19:19:15 -08:00
Huaiyu (Kitty) Liu 9e08ede0bd Commented out DeleteAllSceneObjects in RegionSyncClient, and fixed a bug in "ssync stop". 2011-01-11 16:00:14 -08:00
Huaiyu (Kitty) Liu 95be9c1f7d Fixed a bug so that "ssync start" won't start new connections if a region is already synced. 2011-01-11 14:25:33 -08:00
Huaiyu (Kitty) Liu b5f1137a7d Merge branch 'prephysics_kitty' into prephysics 2011-01-11 12:35:58 -08:00
Huaiyu (Kitty) Liu b29e7c6e5e Let RegionSyncModule to automatically start synchronization when all region loading is done. 2011-01-11 12:33:32 -08:00
Dan Lake 86235e200e Merge branch 'prephysics' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into prephysics 2011-01-11 12:25:10 -08:00
Dan Lake 217b28195c TEMP: Disable saving of appearance to Simian for demonstration purposed only. 2011-01-11 12:21:58 -08:00
Dan Lake 9d5888e0f6 Fixed typo in Region Sync Module debug message Log Headers. 2011-01-11 12:21:04 -08:00
Dan Lake b5463e042c Workaround for NaN in rotation update from PSA to CM. 2011-01-11 12:20:06 -08:00
Dan Lake ed380196ea Only AvatarFactory module should be calling ScenePresence.SendAppearanceToAllOtherAgents(). 2011-01-11 11:49:05 -08:00
Dan Lake 6a24d0eb2d Added missing lock in EventQueue Enqueue. 2011-01-11 11:40:14 -08:00
Huaiyu (Kitty) Liu f8a0de591d Handling RemovedObject as event, instead of as object-update as in the previous approach. 2011-01-10 16:30:42 -08:00
Huaiyu (Kitty) Liu 5c31e0bdd3 Enabled touch events (ObjectGrab, ObjectGrabbing, ObjectDeGrab) to be propagated to script engine and triggers script. 2011-01-10 14:14:40 -08:00
Huaiyu (Kitty) Liu 7eb9affbd3 Enabled chats from scripted objects to be propogated to other objects and avatars. 2011-01-07 15:08:12 -08:00
Huaiyu (Kitty) Liu 4bb99b3df5 Merge branch 'dev_kitty' into prephysics 2011-01-07 12:02:22 -08:00
Huaiyu (Kitty) Liu 739bb1dc43 Fixed a bug in deserialization during rezzing objects out of inventory: SceneObjecPart.SyncInfoUpdate() fixed. 2011-01-07 12:00:00 -08:00
Dan Lake 4f45dcf711 Commenting out verbose debug in SceneGraph.cs 2011-01-07 11:37:03 -08:00
Dan Lake 9d7fd472c0 Fixed a problem with PhysEngineToSceneConnectorModule.cs disabling regionsync when physics syncing is disabled. 2011-01-07 08:27:06 -08:00
Dan Lake 046ec22924 Modified debug messages 2011-01-06 19:26:35 -08:00
Dan Lake a7ec095063 Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-01-06 17:56:18 -08:00
Robert Adams ce4b095a1a Merge branch 'physics' into dev 2011-01-06 17:43:41 -08:00
Dan Lake 17504fcccb Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-01-06 17:33:13 -08:00
Dan Lake a339598bad Added scene name to config options 2011-01-06 17:32:10 -08:00
Huaiyu (Kitty) Liu 9ecf1c21aa Enabled chats (avatar to avatar, avatar to object) to work under the new EventManager (Dan's old way of
propagating chats is disabled by not subscribing to OnChatFromClientRaw in RegionSyncClient and
not subscribing to OnChatFromClientRaw/OnChatFromClientRaw in RegionSyncClientView.

Also, fixed a few minor bugs:
1. GetRemoteSyncListenerInfo() in RegionSyncModule fixed.
2. ActorID sent out when an actor connects to ScenePersistence actor.
2011-01-06 17:02:46 -08:00
Huaiyu (Kitty) Liu e4ab31e004 merged in Kitty's code on propogating events and handling remote events 2011-01-06 10:46:06 -08:00
Dan Lake 247bed199f Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev 2011-01-06 09:21:21 -08:00
Dan Lake f2013d3c93 Updates for appearance and attachments 2011-01-06 09:20:59 -08:00
Robert Adams 2152a5ab7b Merge branch 'dev' into physics 2011-01-05 16:49:28 -08:00
Robert Adams 9669aa93f8 Added region specification to configuration of SyncListenerIPAddress and SyncListenerPort 2011-01-05 16:45:08 -08:00
Huaiyu (Kitty) Liu 731a09bf95 Added symc sync handlers for event ScriptReset. 2011-01-05 16:39:53 -08:00
Robert Adams 251592e54a Code cleanup for better exception processing when looking for a scenePresence when routing a physics event 2011-01-05 16:22:27 -08:00
Huaiyu (Kitty) Liu 837a77b24a Abandoned the previous temporary solution of propogating events. Instead, rename legacy (Scene)EventManager
as EventManagerBase, and implement a new EventManager, to enable handling local/remote events differently.
Handlers for UpdateScript has been implemented as a sample case.
2011-01-05 15:32:43 -08:00
Huaiyu (Kitty) Liu 9b34d50643 Tried a temporary solution for propogating events across actors. See OnUpdateScript handlers. 2011-01-05 13:46:48 -08:00
Robert Adams 254436e914 Cause PhysicsterseUpdate event to happen in the persistance actor when the attributes are changed by the physics actor 2011-01-04 16:15:55 -08:00
Huaiyu (Kitty) Liu 42645acab9 Fix a bug and link-set objects can now be synched correctly. 2011-01-04 14:19:44 -08:00
Robert Adams 7441fbfa3a Merge branch 'dev' into physics
Conflicts:
	OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncServerModule.cs
2011-01-04 10:28:26 -08:00
Robert Adams 0dbd96a12f Modify remote physics configuration to work with new object sync. Remove some chatty debug messages 2011-01-04 10:19:21 -08:00
Huaiyu (Kitty) Liu d84e69fefe Added SymSync in config file. If SymSync = true, then code in the old sync module (asym sync) that handle object updates
are disabled. Then we effectively have new ways (RegionSyncModule) of handle object updates, and old ways of handling
avatar updates working together.
2011-01-04 10:12:35 -08:00
Robert Adams 7da71bd30d Merge branch 'dev' into physics 2011-01-03 15:42:17 -08:00
Huaiyu (Kitty) Liu f5df61162f Added a missing file: IRegionSyncModule.cs. 2011-01-03 15:35:16 -08:00
Robert Adams e68d9a25b1 Merge branch 'dev' into physics 2011-01-03 15:25:31 -08:00
Dan Lake 0b164072b3 Merge branch 'danmerge_symsync' into dev 2011-01-03 15:13:04 -08:00
Robert Adams ae8f8d60a6 remove some load balancing routine invocations to eliminate build breaks. Remove chatty grab debug messages 2011-01-03 12:21:38 -08:00
Dan Lake 7bec1f71cf Prevent position updates from being sent to remote simulation service. 2011-01-03 12:10:29 -08:00
Robert Adams be2af26231 Merge branch 'dev' into physics
Conflicts:
	OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
	OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClient.cs
	OpenSim/Region/Framework/Scenes/Scene.cs
	OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
2011-01-03 10:47:19 -08:00
Dan Lake a34e152e9b Additional debug text in ScenePresence.cs for appearance 2011-01-03 09:37:31 -08:00
Robert Adams 8aded5bdd0 Debug message in ODEPrim on object creation. Less restrictive on changed test when routing updates in ODEScene 2011-01-03 09:13:44 -08:00
Dan Lake f0c2fe6569 Fixed build problem from merge. Needed to add 2 new functions to RegionSyncAvatar.cs as part of IClientAPI interface. 2011-01-02 18:56:59 -08:00
Dan Lake adeab48e7e Merge branch 'master' into danmerge 2011-01-02 18:38:58 -08:00
Dan Lake 9df74cf726 The "show" command on scene does not ever seem to be called anywhere. Commenting out the implementation for now and everything still builds. Might be a patch for master or needs a way to call it. 2011-01-02 18:28:42 -08:00
Dan Lake a5c321a548 Added region name to RegionSync debug messages for cases when there are multiple regions being synced by a single simulator. 2011-01-02 18:27:45 -08:00
Huaiyu (Kitty) Liu 5acaba2974 Added basic implementation for ClientManagerSyncModule and PhysicsEngineSyncModule. 2010-12-29 17:01:45 -08:00
Huaiyu (Kitty) Liu 2ce7d982fa Added functions to sync terrain updates. Either script engine or Scene can update terrain
and the other will be updated.
2010-12-29 13:41:51 -08:00
Huaiyu (Kitty) Liu 994d70f9d8 Code good for script engine and Scene to sync on majority object operations:
e.g. script execution, editing objects, reloading
oar file on Scene (but terrian not updated correctly to the debugging viewer of script engine),
rezing objects by scripts, deleting objects.
2010-12-28 17:11:30 -08:00
Huaiyu (Kitty) Liu 821f80bf3f Add funtions in RegionSyncModule and (Actor)SyncModules to correctly process SyncStop.
E.g. script engine will save script states and delete objects in local scene copy;
ScenePersistence still maintains object copies, though.
2010-12-28 15:58:16 -08:00
Huaiyu (Kitty) Liu 130915f669 Added functions to sync on RemoveObject event. Object can now be removed from either script-engine
or Scene and can be synced.
Problem: there is significant delay form when an object is removed on one actor, to the time it also
disappears from the viewer attaching to the other actor.
2010-12-28 14:54:40 -08:00
Huaiyu (Kitty) Liu 384895cbdd Added synchronization functions to RegionSyncModule, Scene, SceneGraph, SceneObjectGroup and
SceneObjectPart: examples:
HandleAddOrUpdateObjectBySynchronization
QueueSceneObjectPartForUpdate
SceneObjectGroup.UpdateObjectAllProperties
SceneObjectPart.UpdateAllProperties

Now script engine and Scene can sync on script updating or Scene editing objects.
2010-12-28 12:09:17 -08:00
Huaiyu (Kitty) Liu f10059ccd9 1. Added ActorID to IDSGActorSyncModule and the modules that implements this interface.
2. Added LastUpdateTimeStamp and LastUpdateActorID to SceneObjectPart. Also added functions to
serialize and de-serialize the two new members.
2010-12-27 12:15:39 -08:00
Huaiyu (Kitty) Liu e68a8f7710 Added handlers to SceneGraph.OnObjectCreate event in both ScenePersistenceSyncModule
and ScriptEngineSyncModule, so that they can apply actor specific operations once
an object is added to the local Scene.
2010-12-23 15:42:05 -08:00
Huaiyu (Kitty) Liu d0b429c186 Added SymmetricSyncMessage.cs to git index.
Added ScriptEngineSyncModule.cs with basic implementation. Code now good for script engine
to initilaize local scene by synch'ing with ScenePersistence's copy.

Fixed a bug in SyncStart(), so that it won't read in remote listeners' config info every time
SyncStart() is called.
2010-12-23 14:36:02 -08:00
Huaiyu (Kitty) Liu d63e3db533 Added event OnPostSceneCreation to OpenSim/Region/Framework/Scenes/EventManager.cs, and TriggerOnPostSceneCreation. Reason: to emulate what PostInitialise() used to do for IRegionsModules, which is no longer included in INonSharedRegionModule.
Added OnPostSceneCreation() in RegionSynModule.cs, to gain ActorType information from the
loaded Scene.ActorSyncModule. OpenSim, when configured as ScenePersistence, can start normally now.
2010-12-23 14:07:05 -08:00
Huaiyu (Kitty) Liu 650b0bfe54 1. Restored SceneObjectSerializer.SOGToXml2() as in opensim trunk (master), so that objects
are serialized properly.
2. Added code to pass ActorType from a particular ActorSyncModule to RegionSyncModule.
2010-12-23 14:06:33 -08:00
Huaiyu (Kitty) Liu 0a9a8cc680 Restored SceneObjectSerializer.SOGToXml2() as in opensim trunk (master). 2010-12-23 10:29:12 -08:00
Huaiyu (Kitty) Liu dc6964444e Two SyncConnectors now exchange RegionName and Terrian (Scene and Scriptengine tested). 2010-12-22 16:56:34 -08:00
Robert Adams bdeeead120 Add physics actor taint setting after receiveing update values 2010-12-22 15:35:26 -08:00
Huaiyu (Kitty) Liu f97fe18648 Code good for an actor (script engine tested) to connect to ScenePersistence for synchronization.
Need to work on data transmission along the connection as next step.
2010-12-22 11:41:31 -08:00
Huaiyu (Kitty) Liu c1af982ff4 Added code to initiate listener or start connecting to remote listeners. 2010-12-21 17:15:30 -08:00
Huaiyu (Kitty) Liu cb49cfe6c5 Added "[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")]" to
SymmetricSync modules that implement INonSharedRegionModule. They now start running as a region is loaded.
2010-12-21 13:23:52 -08:00
Robert Adams a2ca47d7eb Add parameter and code for AgentID to track bucket changes. Added ground collision so walking now works 2010-12-21 13:19:09 -08:00
Huaiyu (Kitty) Liu e96625c8ca Started to implement Symmetric Sync between all actors. Reserved all old code for asym-sync implemented.
Created a subdir, SymmetricSync/ under OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/. Newly
added files are kept here.
See SymmetricSyncDesign.pptx for the high level SW arch design. Available at \\jfea1pub303\PlanetLAB\vwi\sceneapi.
Added implementation of RegionSyncModule, SyncConnector, and ScenePersistenceSyncModule (this is ScenePersistence specific actions, e.g. message/event subscription).
2010-12-21 10:48:34 -08:00
Robert Adams e1c3650634 Remove chatty debug messages. Damp update value checking. Physics sync message logging. 2010-12-20 14:06:14 -08:00
Robert Adams 420aeb9b6a remove debug statements. Pass terrain to physics engine 2010-12-15 15:05:40 -08:00
Robert Adams 7c6bca1668 physics messages sync'ing both ways. Value change not happening 2010-12-14 15:31:00 -08:00
Dan Lake 2b390f2436 Fixed issues with save and retrieve appearance from grid. 2010-12-14 15:06:31 -08:00
Dan Lake c7923338bc Merge branch 'master' into danmerge
Conflicts:
	OpenSim/Region/Framework/Scenes/ScenePresence.cs
	bin/OpenSim.exe.config
2010-12-09 15:49:40 -08:00
Dan Lake dc86adbd17 Fixing up Appearance handling in Region Sync modules and connectors. 2010-12-09 15:07:42 -08:00
Robert Adams a036426f18 PhysActor update messages working. Avatar and prim neither move nor position correctly 2010-12-08 17:19:06 -08:00
Robert Adams 5c6f0878a1 Add interfaces for physEngine connectors 2010-12-06 10:58:54 -08:00
Robert Adams 24bef963c7 Initial connection of phys actor 2010-12-06 10:57:39 -08:00
Robert Adams b56b0c3086 Initial plumbing for connectors and PhysActor discovery 2010-12-01 09:36:48 -08:00
Dan Lake 681190f682 Merge branch 'master' into danmerge
Conflicts:
	.nant/local.include
	OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs
	OpenSim/Framework/AvatarAppearance.cs
	OpenSim/Framework/IClientAPI.cs
	OpenSim/Region/Application/OpenSim.cs
	OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
	OpenSim/Region/Framework/Scenes/EventManager.cs
	OpenSim/Region/Framework/Scenes/Scene.cs
	OpenSim/Region/Framework/Scenes/SceneGraph.cs
	OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
	OpenSim/Region/Framework/Scenes/ScenePresence.cs
	OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
	OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
	OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
	bin/config-include/SimianGrid.ini
	prebuild.xml
2010-11-30 17:36:36 -08:00
Robert Adams 9e68de6b8f PE physics plugin stubs 2010-11-23 13:32:46 -08:00
Huaiyu (Kitty) Liu f8ccfaf046 Fixed a few conflicts with Dan's code (earlier conflict resolution by Dan broke
remote script engine's execution) to make remote script engine execute as it did in
    the implementation in Country Fair 2010 demo.
2010-11-12 15:50:21 -08:00
Huaiyu (Kitty) Liu bca02499dc Fixed some code in Initialise() in both RegionSyncClientModule and ScriptEngineToSceneConnectorModule, so that OpenSim will not crach if [RegionSyncModule] is not specified or under it, "Enabled" is set. 2010-11-04 15:22:11 -07:00
Robert Adams 49d7ff0307 Avatars no longer snap to middle of target sim when border crossing in a CM 2010-10-26 16:57:47 -07:00
Robert Adams 46a01d9550 Animations to multiple CMs (including idle anims) are working 2010-10-26 12:22:09 -07:00
Robert Adams 9f515cb623 Partial passing of StartAnim and StopAnim through CM 2010-10-25 15:52:41 -07:00
Robert Adams 838ffc27ed Create full updates for making sit complete 2010-10-25 13:32:53 -07:00
Robert Adams 5eca61585d SendAnimations from SIM->CM->client 2010-10-19 15:47:06 -07:00
Robert Adams 3b9a6a565f touch and world chat working 2010-10-19 14:06:59 -07:00
Robert Adams 62fbd2ef08 Undo SetAppearance supression. Debug statements 2010-10-15 14:54:01 -07:00
Robert Adams cf5aeb9a68 Merge branch 'sceneapi' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into sceneapi 2010-10-14 14:35:14 -07:00
Robert Adams de9427e545 Border crossing in multi-region CMs and many debug messages for appearance 2010-10-14 14:31:28 -07:00
hliu19 a9608ba49a Fixed an unwanted warning that a point in space is not covered by any script engine,
when there is no remote script engine running but that the main Scene is running a
    script engine locally.

    Fixed BroadcastToCM in RegionSyncServer.cs.
2010-10-05 11:27:36 -07:00
Dan Lake 32b9a8d78d Added missing files to git 2010-09-27 16:00:29 -07:00
Dan Lake f5d25981ac Merged with Kitty's Script engine code. 2010-09-23 16:32:38 -07:00
Dan Lake 1c93854b47 Some little changes to clean up refresh to 0719 2010-09-23 11:51:34 -07:00
Dan Lake 188a2db02a Added a couple of files for client manager support 2010-08-16 10:54:17 -07:00
Dan Lake 8f8ef75034 Merged with main AND partial implementation of teleport based load balancing. Did not intend to combine the merge with these changes. 2010-08-16 10:23:50 -07:00
Dan Lake ae4964050b Merge branch 'master' of git://opensimulator.org/git/opensim 2010-07-19 13:05:36 -07:00
Dan Lake 9ada2a1f34 Client manager changes as of R@I 2010-07-19 13:03:04 -07:00
Dan Lake 9afa8b990d Merged from master 2010-06-02 14:40:10 -07:00
Dan Lake 7f9bb06b03 Merge branch 'master' of git://opensimulator.org/git/opensim 2010-06-01 16:17:54 -07:00
Dan Lake 6818427f1c More Scene API changes 2010-06-01 16:13:38 -07:00
Dan Lake 82a71fb7e2 Adding appearance and animations 2010-05-18 09:05:13 -07:00
Dan Lake 2283b85bcf Some updates for client manager 2010-04-30 08:13:02 -07:00
Dan Lake 79327a6299 Merge branch 'master' into sceneapi 2010-04-20 11:43:03 -07:00
Dan Lake 031bc35c06 Merge branch 'master' of git://opensimulator.org/git/opensim 2010-04-20 11:42:47 -07:00
Dan Lake bcce66ad1f Eliminate region archive passing 2010-04-20 11:42:23 -07:00
Dan Lake 6236d24d14 Added required SceneAPI messages 2010-04-20 11:40:25 -07:00
Dan Lake 9eee902637 Adding region sync interfaces 2010-03-31 13:15:17 -07:00
Dan Lake bba803e39d Merged from master 2010-03-31 13:13:24 -07:00
Dan Lake d2fd36b2a5 Fixed mixed line endings 2010-03-31 13:06:48 -07:00
Dan Lake 8027b7c1a5 Merged from master 2010-03-24 10:50:42 -07:00
Dan Lake 4216eacd6c Some work on sceneapi 2010-03-23 16:30:56 -07:00
122 changed files with 23918 additions and 545 deletions

3
.gitignore vendored
View File

@ -9,8 +9,6 @@
*.pdb
*.pidb
*.dll.build
*.dll
*.VisualState.xml
*/*/obj
*/*/*/obj
*/*/*/*/obj
@ -53,7 +51,6 @@ bin/OpenSim.Grid.InventoryServer.log
bin/OpenSim.Grid.MessagingServer.log
bin/OpenSim.Grid.UserServer.log
bin/OpenSim.log
bin/*.manifest
bin/crashes/
Examples/*.dll
OpenSim.build

View File

@ -10,7 +10,7 @@ people that make the day to day of OpenSim happen.
* dahlia
* Melanie Thielker
* Diva (Crista Lopes, University of California, Irvine)
* Dan Lake (Intel)
* dslake (Dan Lake, Intel)
* Marck
* Mic Bowman (Intel)
* BlueWall (James Hughes)
@ -75,7 +75,7 @@ what it is today.
* daTwitch
* devalnor-#708
* dmiles (Daxtron Labs)
* dslake (Intel)
* dslake (Dan Lake, Intel)
* FredoChaplin
* Gerhard
* Godfrey
@ -184,6 +184,10 @@ Some plugins are based on Cable Beach
Cable Beach is Copyright (c) 2008 Intel Corporation
see http://forge.opensimulator.org/gf/project/assetserver/
Some plugins are based on Distributed Scene Graph (DSG)
Distributed Scene Graph is Copyright (c) 2011 Intel Corporation
In addition, we would like to thank:
* The Mono Project
* The NANT Developers

View File

@ -2077,5 +2077,12 @@ VALUES
#endregion
#endregion
#region REGION SYNC
public List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY)
{
return null;
}
#endregion REGION SYNC
}
}

View File

@ -540,6 +540,148 @@ namespace OpenSim.Data.MySQL
return new List<SceneObjectGroup>(objects.Values);
}
#region REGION SYNC
public List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY)
{
const int ROWS_PER_QUERY = 5000;
Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>(ROWS_PER_QUERY);
Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>();
int count = 0;
#region Prim Loading
lock (m_dbLock)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{
//cmd.CommandText =
// "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID";
cmd.CommandText = "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID " +
"and GroupPositionX>=?lowerX " +
"and GroupPositionX<=?upperX and GroupPositionY>=?lowerY and GroupPositionY<=?upperY ";
cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
cmd.Parameters.AddWithValue("lowerX", lowerX);
cmd.Parameters.AddWithValue("lowerY", lowerY);
cmd.Parameters.AddWithValue("upperX", upperX);
cmd.Parameters.AddWithValue("upperY", upperY);
using (IDataReader reader = ExecuteReader(cmd))
{
while (reader.Read())
{
SceneObjectPart prim = BuildPrim(reader);
if (reader["Shape"] is DBNull)
prim.Shape = PrimitiveBaseShape.Default;
else
prim.Shape = BuildShape(reader);
UUID parentID = DBGuid.FromDB(reader["SceneGroupID"].ToString());
if (parentID != prim.UUID)
prim.ParentUUID = parentID;
prims[prim.UUID] = prim;
++count;
if (count % ROWS_PER_QUERY == 0)
m_log.Debug("[REGION DB]: Loaded " + count + " prims...");
}
}
}
}
}
#endregion Prim Loading
#region SceneObjectGroup Creation
// Create all of the SOGs from the root prims first
foreach (SceneObjectPart prim in prims.Values)
{
if (prim.ParentUUID == UUID.Zero)
objects[prim.UUID] = new SceneObjectGroup(prim);
}
// Add all of the children objects to the SOGs
foreach (SceneObjectPart prim in prims.Values)
{
SceneObjectGroup sog;
if (prim.UUID != prim.ParentUUID)
{
if (objects.TryGetValue(prim.ParentUUID, out sog))
{
int originalLinkNum = prim.LinkNum;
sog.AddPart(prim);
// SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum.
// We override that here
if (originalLinkNum != 0)
prim.LinkNum = originalLinkNum;
}
else
{
m_log.WarnFormat(
"[REGION DB]: Database contains an orphan child prim {0} {1} in region {2} pointing to missing parent {3}. This prim will not be loaded.",
prim.Name, prim.UUID, regionID, prim.ParentUUID);
}
}
}
#endregion SceneObjectGroup Creation
m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count);
#region Prim Inventory Loading
// Instead of attempting to LoadItems on every prim,
// most of which probably have no items... get a
// list from DB of all prims which have items and
// LoadItems only on those
List<SceneObjectPart> primsWithInventory = new List<SceneObjectPart>();
lock (m_dbLock)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand itemCmd = dbcon.CreateCommand())
{
itemCmd.CommandText = "SELECT DISTINCT primID FROM primitems";
using (IDataReader itemReader = ExecuteReader(itemCmd))
{
while (itemReader.Read())
{
if (!(itemReader["primID"] is DBNull))
{
UUID primID = DBGuid.FromDB(itemReader["primID"].ToString());
if (prims.ContainsKey(primID))
primsWithInventory.Add(prims[primID]);
}
}
}
}
}
}
foreach (SceneObjectPart prim in primsWithInventory)
{
LoadItems(prim);
}
#endregion Prim Inventory Loading
m_log.DebugFormat("[REGION DB]: Loaded inventory from {0} objects", primsWithInventory.Count);
return new List<SceneObjectGroup>(objects.Values);
}
#endregion REGION SYNC
/// <summary>
/// Load in a prim's persisted inventory.
/// </summary>

View File

@ -127,5 +127,12 @@ namespace OpenSim.Data.Null
public void Shutdown()
{
}
#region REGION SYNC
public List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY)
{
return null;
}
#endregion REGION SYNC
}
}

View File

@ -2363,5 +2363,11 @@ namespace OpenSim.Data.SQLite
}
}
#region REGION SYNC
public List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY)
{
return null;
}
#endregion REGION SYNC
}
}

View File

@ -38,6 +38,7 @@ namespace OpenSim.Framework
public delegate void ViewerEffectEventHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args);
public delegate void ChatMessage(Object sender, OSChatMessage e);
public delegate void ChatMessageRaw(Object sender, byte[] chatData);
public delegate void GenericMessage(Object sender, string method, List<String> args);
@ -82,6 +83,9 @@ namespace OpenSim.Framework
public delegate void TeleportLocationRequest(
IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags);
//DSG:
public delegate void SameRegionTeleportlRequest(IClientAPI remoteClient, byte[] tpLocReq);
public delegate void TeleportLandmarkRequest(
IClientAPI remoteClient, AssetLandmark lm);
@ -149,6 +153,7 @@ namespace OpenSim.Framework
public delegate void NewAvatar(IClientAPI remoteClient, UUID agentID, bool status);
public delegate void UpdateAgent(IClientAPI remoteClient, AgentUpdateArgs agentData);
public delegate void UpdateAgentRaw(IClientAPI remoteClient, byte[] agentData);
public delegate void AgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset);
@ -748,12 +753,15 @@ namespace OpenSim.Framework
IPEndPoint RemoteEndPoint { get; }
uint MaxCoarseLocations { get; }
event GenericMessage OnGenericMessage;
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")]
event ImprovedInstantMessage OnInstantMessage;
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments. Rename OnChat.")]
event ChatMessage OnChatFromClient;
event ChatMessageRaw OnChatFromClientRaw;
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")]
event TextureRequest OnRequestTexture;
// [Obsolete("LLClientView Specific - Remove bitbuckets. Adam, can you be more specific here.. as I don't see any bit buckets.")]
@ -779,6 +787,9 @@ namespace OpenSim.Framework
event RequestMapBlocks OnRequestMapBlocks;
event RequestMapName OnMapNameRequest;
event TeleportLocationRequest OnTeleportLocationRequest;
//DSG:
event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
//end of DSG
event DisconnectUser OnDisconnectUser;
event RequestAvatarProperties OnRequestAvatarProperties;
event SetAlwaysRun OnSetAlwaysRun;
@ -789,6 +800,7 @@ namespace OpenSim.Framework
event GenericCall1 OnCompleteMovementToRegion;
event UpdateAgent OnPreAgentUpdate;
event UpdateAgent OnAgentUpdate;
event UpdateAgentRaw OnAgentUpdateRaw;
event AgentRequestSit OnAgentRequestSit;
event AgentSit OnAgentSit;
event AvatarPickerRequest OnAvatarPickerRequest;

View File

@ -141,6 +141,19 @@ namespace OpenSim.Framework
public string RemotingAddress;
public UUID ScopeID = UUID.Zero;
//DSG SYNC
//IP:port for the symmetric sync listener this actor is configured to connect to
private string m_syncServerAddr = String.Empty;
private int m_syncServerPort;
//IP:port for the avatar sync server this actor is configured to connect to
private string m_avatarSyncServerAddr = String.Empty;
private int m_avatarSyncServerPort;
//IP:port for the physics sync server this actor is configured to connect to
private string m_physicsSyncServerAddr = String.Empty;
private int m_physicsSyncServerPort;
private uint m_quarkLocX;
private uint m_quarkLocY;
//end of DSG SYNC
// Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
@ -436,6 +449,45 @@ namespace OpenSim.Framework
get { return Util.UIntsToLong((RegionLocX * (uint) Constants.RegionSize), (RegionLocY * (uint) Constants.RegionSize)); }
}
//DSG SYNC
public string SyncServerAddress
{
get { return m_syncServerAddr; }
}
public int SyncServerPort
{
get { return m_syncServerPort; }
}
public string AvatarSyncServerAddress
{
get { return m_avatarSyncServerAddr; }
}
public int AvatarSyncServerPort
{
get { return m_avatarSyncServerPort; }
}
public string PhysicsSyncServerAddress
{
get { return m_physicsSyncServerAddr; }
}
public int PhysicsSyncServerPort
{
get { return m_physicsSyncServerPort; }
}
public uint SyncQuarkLocationX
{
get { return m_quarkLocX; }
set { m_quarkLocX = value; }
}
public uint SyncQuarkLocationY
{
get { return m_quarkLocY; }
set { m_quarkLocY = value; }
}
//end of DSG SYNC
public void SetEndPoint(string ipaddr, int port)
{
IPAddress tmpIP = IPAddress.Parse(ipaddr);
@ -588,6 +640,34 @@ namespace OpenSim.Framework
// Multi-tenancy
//
ScopeID = new UUID(config.GetString("ScopeID", UUID.Zero.ToString()));
// DSG SYNC
m_syncServerAddr = config.GetString("SyncServerAddress", String.Empty);
m_syncServerPort = config.GetInt("SyncServerPort", -1);
//if either IP or port is not configured, we set IP to empty to raise warning later
if (m_syncServerPort == -1)
m_syncServerAddr = String.Empty;
m_avatarSyncServerAddr = config.GetString("AvatarSyncServerAddress", String.Empty);
m_avatarSyncServerPort = config.GetInt("AvatarSyncServerPort", -1);
if (m_avatarSyncServerPort == -1)
m_avatarSyncServerAddr = String.Empty;
m_physicsSyncServerAddr = config.GetString("PhysicsSyncServerAddress", String.Empty);
m_physicsSyncServerPort = config.GetInt("PhysicsSyncServerPort", -1);
if (m_physicsSyncServerPort == -1)
m_physicsSyncServerAddr = String.Empty;
string quarkLocation = config.GetString("SyncQuarkLocation", "1000,1000");
string[] quarkLocElements = quarkLocation.Split(new char[] { ',' });
m_quarkLocX = Convert.ToUInt32(quarkLocElements[0]);
m_quarkLocY = Convert.ToUInt32(quarkLocElements[1]);
// end of DSG SYNC
}
private void WriteNiniConfig(IConfigSource source)

View File

@ -49,7 +49,7 @@ namespace OpenSim
public static string GetVersionString(string versionNumber, Flavour flavour)
{
string versionString = "OpenSim " + versionNumber + " " + flavour;
string versionString = "OpenSim DSG " + versionNumber + " " + flavour;
return versionString.PadRight(VERSIONINFO_VERSION_LENGTH);
}

View File

@ -388,8 +388,58 @@ namespace OpenSim
"kill uuid <UUID>",
"Kill an object by UUID", KillUUID);
//REGION SYNC
//Add one more command handler for "sync start", to pass simulator-wise information to one valide Scene.
//A trick to enable Script Engine to run scripts in several adjacent regions (all objects and their scripts
//exisited in the valid region, but all regions have their Scene data structure up and hold the RegionInfo.
m_console.Commands.AddCommand("region", false, "sync start",
"sync start",
"start synchronization with the authoratative Scene", SyncStart);
//End REGION SYNC
}
#region REGION SYNC
protected void SyncStart(string module, string[] cmdparams)
{
m_log.Debug("OpenSim: receives sync start command, do something");
//string validLocalScene = m_config.
IConfig regionSyncConfig = m_config.Source.Configs["RegionSyncModule"];
if (regionSyncConfig == null || regionSyncConfig.GetString("Enabled", "").ToLower() != "true")
{
m_log.Warn("[OpenSim] Not in sync mode. Ignore cmmand.");
return;
}
if (regionSyncConfig.GetString("Mode", "").ToLower() == "server")
{
m_log.Warn("[OpenSim] In server mode. Should not initiate sync start. Ignore command.");
return;
}
if (regionSyncConfig.GetString("Mode", "").ToLower() == "script_engine")
{
//if this is a remote script engine, proceed with following actions
string validSceneName = regionSyncConfig.GetString("ValidScriptEngineScene", "");
if (!validSceneName.Equals(""))
{
Scene validScene;
m_sceneManager.TryGetScene(validSceneName, out validScene);
List<Scene> localScenes = m_sceneManager.Scenes;
//First, let the valid scene's SEToSceneConnector be aware of all local scenes.
//The SEToSceneConnector will also pass a reference to all other scenes, so that they can
//call the appropriate IsBorderCrossing().
validScene.EventManager.TriggerPopulateLocalSceneList(localScenes); //TO BE FINISHED
//validScene.EventManager.TriggerPopulateLocalSceneList(localScenes, cmdparams);
}
}
}
#endregion REGION SYNC
public override void ShutdownSpecific()
{
if (m_shutdownCommandsFile != String.Empty)

View File

@ -411,6 +411,12 @@ namespace OpenSim
scene.StartTimer();
//DSG SYNC
//For INonSharedRegionModule, there is no more PostInitialise(). So we trigger OnPostSceneCreation event here
//to let the Sync modules to do their work once all modules are loaded and scene has interfaces to all of them.
scene.EventManager.TriggerOnPostSceneCreation(scene);
//end of DSG SYNC
return clientServer;
}

View File

@ -179,8 +179,13 @@ namespace OpenSim.Region.ClientStack.Linden
{
Queue<OSD> queue = GetQueue(avatarID);
if (queue != null)
{
lock (queue)
{
queue.Enqueue(ev);
}
}
}
catch(NullReferenceException e)
{
m_log.Error("[EVENTQUEUE] Caught exception: " + e);

View File

@ -48,6 +48,7 @@ using OSD = OpenMetaverse.StructuredData.OSD;
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
using OpenSim.Framework.Capabilities;
using ExtraParamType = OpenMetaverse.ExtraParamType;
using System.Collections.Generic;
namespace OpenSim.Region.ClientStack.Linden
{
@ -350,7 +351,8 @@ namespace OpenSim.Region.ClientStack.Linden
rootGroup.LinkToGroup(allparts[j]);
}
rootGroup.ScheduleGroupForFullUpdate();
//rootGroup.ScheduleGroupForFullUpdate();
rootGroup.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate}); //seems like new object
pos
= m_scene.GetNewRezLocation(
Vector3.Zero, rootpos, UUID.Zero, rot, (byte)1, 1, true, allparts[0].GroupScale, false);

View File

@ -28,6 +28,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;
@ -48,6 +49,7 @@ using OpenSim.Services.Interfaces;
using Timer = System.Timers.Timer;
using AssetLandmark = OpenSim.Framework.AssetLandmark;
using Nini.Config;
using System.Linq;
using System.IO;
@ -76,6 +78,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public event ViewerEffectEventHandler OnViewerEffect;
public event ImprovedInstantMessage OnInstantMessage;
public event ChatMessage OnChatFromClient;
public event ChatMessageRaw OnChatFromClientRaw;
public event TextureRequest OnRequestTexture;
public event RezObject OnRezObject;
public event DeRezObject OnDeRezObject;
@ -93,6 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public event GenericCall1 OnCompleteMovementToRegion;
public event UpdateAgent OnPreAgentUpdate;
public event UpdateAgent OnAgentUpdate;
public event UpdateAgentRaw OnAgentUpdateRaw;
public event AgentRequestSit OnAgentRequestSit;
public event AgentSit OnAgentSit;
public event AvatarPickerRequest OnAvatarPickerRequest;
@ -139,6 +143,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public event RequestMapBlocks OnRequestMapBlocks;
public event RequestMapName OnMapNameRequest;
public event TeleportLocationRequest OnTeleportLocationRequest;
//DSG:
public event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
//end of DSG
public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
public event DisconnectUser OnDisconnectUser;
public event RequestAvatarProperties OnRequestAvatarProperties;
@ -300,6 +307,73 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
// First log file or time has expired, start writing to a new log file
//<MIC>
// -----------------------------------------------------------------
// -----------------------------------------------------------------
// -----------------------------------------------------------------
// -----------------------------------------------------------------
public class QueueLogger
{
public Int32 start = 0;
public StreamWriter Log = null;
private Dictionary<UUID,int> m_idMap = new Dictionary<UUID,int>();
public QueueLogger()
{
DateTime now = DateTime.Now;
String fname = String.Format("queue-{0}.log", now.ToString("yyyyMMddHHmmss"));
Log = new StreamWriter(fname);
start = Util.EnvironmentTickCount();
}
public int LookupID(UUID uuid)
{
int localid;
if (! m_idMap.TryGetValue(uuid,out localid))
{
localid = m_idMap.Count + 1;
m_idMap[uuid] = localid;
}
return localid;
}
}
public static QueueLogger QueueLog = null;
// -----------------------------------------------------------------
public void LogAvatarUpdateEvent(UUID client, UUID avatar)
{
if (QueueLog == null)
QueueLog = new QueueLogger();
Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
lock(QueueLog)
{
int cid = QueueLog.LookupID(client);
int aid = QueueLog.LookupID(avatar);
QueueLog.Log.WriteLine("{0},AU,AV{1:D4},AV{2:D4}",ticks,cid,aid);
}
}
// -----------------------------------------------------------------
public void LogQueueProcessEvent(UUID client, PriorityQueue queue, uint maxup)
{
if (QueueLog == null)
QueueLog = new QueueLogger();
Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
lock(QueueLog)
{
int cid = QueueLog.LookupID(client);
QueueLog.Log.WriteLine("{0},PQ,AV{1:D4},{2},{3}",ticks,cid,queue.Count,maxup);
}
}
//</MIC>
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
@ -340,7 +414,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_moneyBalance;
private int m_animationSequenceNumber = 1;
private bool m_SendLogoutPacketWhenClosing = true;
private AgentUpdateArgs lastarg;
private byte[] m_lastAgentUpdate;
private bool m_IsActive = true;
private bool m_IsLoggingOut = false;
@ -426,6 +500,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
public uint MaxCoarseLocations { get { return 60; } }
#endregion Properties
// ~LLClientView()
@ -3433,6 +3509,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendWearables(AvatarWearable[] wearables, int serial)
{
//m_log.WarnFormat("[LLCLIENTVIEW] Sending wearables to {0}", Name);
AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate);
aw.AgentData.AgentID = AgentId;
aw.AgentData.SerialNum = (uint)serial;
@ -3552,7 +3629,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Each packet can only hold around 60 avatar positions and the client clears the mini-map each time
// a CoarseLocationUpdate packet is received. Oh well.
int total = Math.Min(CoarseLocations.Count, 60);
int total = Math.Min(CoarseLocations.Count, (int)MaxCoarseLocations);
CoarseLocationUpdatePacket.IndexBlock ib = new CoarseLocationUpdatePacket.IndexBlock();
@ -3659,6 +3736,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
int updatesThisCall = 0;
//LogQueueProcessEvent(this.m_agentId,m_entityUpdates,m_maxUpdates);
// We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
// condition where a kill can be processed before an out-of-date update for the same object.
lock (m_killRecord)
@ -3763,6 +3842,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Block Construction
//if (update.Entity is ScenePresence)
//LogAvatarUpdateEvent(this.m_agentId,update.Entity.UUID);
// TODO: Remove this once we can build compressed updates
canUseCompressed = false;
@ -5274,9 +5356,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private bool HandleAgentUpdate(IClientAPI sener, Packet Pack)
{
if (OnAgentUpdate != null)
if (OnAgentUpdate != null || OnAgentUpdateRaw != null)
{
bool update = false;
AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
#region Packet Session and User Check
@ -5285,37 +5366,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion
AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
byte[] xb = new byte[x.Length];
int i = 0;
x.ToBytes(xb, ref i);
// We can only check when we have something to check
// against.
if (lastarg != null)
// If there was a previous update and this update is exactly the same, skip it
if (m_scene.IsSyncedClient() && m_lastAgentUpdate != null && Enumerable.SequenceEqual(xb, m_lastAgentUpdate))
{
update =
(
(x.BodyRotation != lastarg.BodyRotation) ||
(x.CameraAtAxis != lastarg.CameraAtAxis) ||
(x.CameraCenter != lastarg.CameraCenter) ||
(x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
(x.CameraUpAxis != lastarg.CameraUpAxis) ||
(x.ControlFlags != lastarg.ControlFlags) ||
(x.Far != lastarg.Far) ||
(x.Flags != lastarg.Flags) ||
(x.State != lastarg.State) ||
(x.HeadRotation != lastarg.HeadRotation) ||
(x.SessionID != lastarg.SessionID) ||
(x.AgentID != lastarg.AgentID)
);
//m_log.Warn("LLClientView: HandleAgentUpdate (IDENTICAL TO LAST)");
return true;
}
else
update = true;
// These should be ordered from most-likely to
// least likely to change. I've made an initial
// guess at that.
if (update)
// What is different?? (only interesting for client managers)
/*
if(m_scene.IsSyncedClient() && m_lastAgentUpdate != null)
{
AgentUpdatePacket.AgentDataBlock lastarg = new AgentUpdatePacket.AgentDataBlock();
i = 0;
lastarg.FromBytes(m_lastAgentUpdate, ref i);
m_log.WarnFormat("LLClientView: HandleAgentUpdate |{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}|",
(x.BodyRotation != lastarg.BodyRotation) ? "X" : " ",
(x.CameraAtAxis != lastarg.CameraAtAxis) ? "X" : " ",
(x.CameraCenter != lastarg.CameraCenter) ? "X" : " ",
(x.CameraLeftAxis != lastarg.CameraLeftAxis) ? "X" : " ",
(x.CameraUpAxis != lastarg.CameraUpAxis) ? "X" : " ",
(x.ControlFlags != lastarg.ControlFlags) ? "X" : " ",
(x.Far != lastarg.Far) ? "X" : " ",
(x.Flags != lastarg.Flags) ? "X" : " ",
(x.State != lastarg.State) ? "X" : " ",
(x.HeadRotation != lastarg.HeadRotation) ? "X" : " ",
(x.SessionID != lastarg.SessionID) ? "X" : " ",
(x.AgentID != lastarg.AgentID) ? "X" : " ");
}
* */
// save this set of arguments for next time
m_lastAgentUpdate = xb;
// If we have a raw handler, call it
UpdateAgentRaw handlerAgentUpdateRaw = OnAgentUpdateRaw;
if (handlerAgentUpdateRaw != null)
{
handlerAgentUpdateRaw(this, xb);
handlerAgentUpdateRaw = null;
return true;
}
AgentUpdateArgs arg = new AgentUpdateArgs();
arg.AgentID = x.AgentID;
arg.BodyRotation = x.BodyRotation;
@ -5329,17 +5426,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
arg.HeadRotation = x.HeadRotation;
arg.SessionID = x.SessionID;
arg.State = x.State;
UpdateAgent handlerAgentUpdate = OnAgentUpdate;
UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
lastarg = arg; // save this set of arguments for nexttime
UpdateAgent handlerAgentUpdate = OnAgentUpdate;
if (handlerPreAgentUpdate != null)
OnPreAgentUpdate(this, arg);
if (handlerAgentUpdate != null)
OnAgentUpdate(this, arg);
handlerAgentUpdate = null;
handlerPreAgentUpdate = null;
}
handlerAgentUpdate = null;
}
return true;
@ -5596,6 +5692,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
int channel = inchatpack.ChatData.Channel;
// If we have a raw handler, call it
ChatMessageRaw handlerChatFromClientRaw = OnChatFromClientRaw;
if (handlerChatFromClientRaw != null)
{
ChatFromViewerPacket.ChatDataBlock x = inchatpack.ChatData;
byte[] xb = new byte[x.Length];
int i = 0;
x.ToBytes(xb, ref i);
handlerChatFromClientRaw(this, xb);
handlerChatFromClientRaw = null;
return true;
}
if (OnChatFromClient != null)
{
OSChatMessage args = new OSChatMessage();
@ -5970,14 +6079,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion
SetAppearance handlerSetAppearance = OnSetAppearance;
if (handlerSetAppearance != null)
//if (handlerSetAppearance != null)
{
// Temporarily protect ourselves from the mantis #951 failure.
// However, we could do this for several other handlers where a failure isn't terminal
// for the client session anyway, in order to protect ourselves against bad code in plugins
try
{
byte[] visualparams = new byte[appear.VisualParam.Length];
for (int i = 0; i < appear.VisualParam.Length; i++)
visualparams[i] = appear.VisualParam[i].ParamValue;
@ -8415,6 +8523,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion
TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
//DSG: KittyL -- added to support same region teleport
if (tpLocReq.Info.RegionHandle == m_scene.RegionInfo.RegionHandle)
{
SameRegionTeleportlRequest handlerSameRegionTeleportlRequest = OnSameRegionTeleportlRequest;
if (handlerSameRegionTeleportlRequest != null)
{
byte[] xb = new byte[tpLocReq.Length];
int i = 0;
xb = tpLocReq.ToBytes();
handlerSameRegionTeleportlRequest(this, xb);
//return true;
}
}
if (handlerTeleportLocationRequest != null)
{
handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,

View File

@ -924,6 +924,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
{
// REGION SYNC (Load Balancing)
//ScenePresence presence;
//m_scene.TryGetScenePresence(agentID, out presence);
//bool syncedAvatar = (presence != null && presence.IsSyncedAvatar);
// In priciple there shouldn't be more than one thread here, ever.
// But in case that happens, we need to synchronize this piece of code
// because it's too important

View File

@ -28,6 +28,7 @@
using System;
using OpenSim.Framework;
using OpenMetaverse;
using System.Threading;
namespace OpenSim.Region.ClientStack.LindenUDP
{

View File

@ -475,6 +475,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
group.HasGroupChanged = true;
UpdateKnownItem(remoteClient, group, group.GetFromItemID(), group.OwnerID);
m_scene.DeleteSceneObject(group, false);
return;
}
@ -609,7 +610,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
}
so.IsSelected = false; // fudge....
so.ScheduleGroupForFullUpdate();
//so.ScheduleGroupForFullUpdate();
so.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate}); //just force it to sychronize all properties
}
// In case it is later dropped again, don't let

View File

@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
{
m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
// m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
m_log.WarnFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
}
}
@ -261,8 +261,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
/// </summary>
public void QueueAppearanceSend(UUID agentid)
{
// m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
// 10000 ticks per millisecond, 1000 milliseconds per second
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
lock (m_sendqueue)
@ -270,6 +268,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
m_sendqueue[agentid] = timestamp;
m_updateTimer.Start();
}
//m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0} at {1} (now is {2})", agentid, timestamp,DateTime.Now.Ticks);
}
public void QueueAppearanceSave(UUID agentid)
@ -285,6 +284,58 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
}
}
public void RefreshAppearance(UUID agentid)
{
m_log.DebugFormat("[AVFACTORY]: FireAndForget called for RefreshAppearance on agentid {0}", agentid);
Util.FireAndForget(delegate(object o)
{
int maxtries = 10;
int trycount = maxtries;
int interval = 5000;
ScenePresence sp;
while (!m_scene.TryGetScenePresence(agentid, out sp))
{
//m_log.WarnFormat("[AVFACTORY]: RefreshAppearance unable to find presence for {0}", agentid);
Thread.Sleep(interval);
if (trycount-- <= 0)
{
m_log.ErrorFormat("[AVFACTORY]: RefreshAppearance unable to find presence for {0} after {1} attempts at {2}ms intervals", agentid, maxtries, interval);
return;
}
}
trycount = maxtries;
AvatarAppearance appearance = null;
while (appearance == null)
{
try
{
appearance = m_scene.AvatarService.GetAppearance(agentid);
}
catch (System.Net.WebException e)
{
if (trycount-- <= 0)
{
m_log.WarnFormat("[AVFACTORY]: RefreshAppearance unable to get appearance from AvatarService for {0} after {1} attempts at {2}ms intervals: {3}", agentid, maxtries, interval, e.Message);
return;
}
}
Thread.Sleep(interval);
}
if (appearance.Texture != null && appearance.VisualParams != null)
{
sp.Appearance = appearance;
if (sp.Appearance.AvatarHeight > 0)
sp.SetHeight(sp.Appearance.AvatarHeight);
QueueAppearanceSend(agentid);
}
else
{
m_log.WarnFormat("[AVFACTORY]: RefreshAppearance received null appearance data from grid for {0}", agentid);
}
}, null);
}
private void HandleAppearanceSend(UUID agentid)
{
ScenePresence sp = m_scene.GetScenePresence(agentid);
@ -311,10 +362,18 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
return;
}
if (sp.IsSyncedAvatar)
return;
// m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
// Disable saving of appearance for demonstrations
// m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
// REGION SYNC
// If this is a client manager, we have received new appearance from a client and saved
// it to the avatar service. Now let's tell the parent scene about it.
if (m_scene.IsSyncedClient())
m_scene.RegionSyncClientModule.SendAppearanceToScene(agentid);
}
private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
@ -328,6 +387,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
{
if (kvp.Value < now)
{
m_log.DebugFormat("[AVFACTORY]: send appearance for {0} at time {1}", kvp.Key, now);
Util.FireAndForget(delegate(object o) { HandleAppearanceSend(kvp.Key); });
m_sendqueue.Remove(kvp.Key);
}

View File

@ -37,6 +37,13 @@ using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
//DSG
using Nwc.XmlRpc;
using System.Net;
using System.Collections;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
namespace OpenSim.Region.CoreModules.Avatar.Dialog
{
public class DialogModule : IRegionModule, IDialogModule

View File

@ -224,6 +224,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
return;
}
//DSG: make this function public, so that we can call from outside to
//use the Grid Service to send the instant message.
public virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
{
}
protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID)
{
bool successful = false;

View File

@ -446,7 +446,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
}
protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
//protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
//DSG: make this function public, so that we can call from outside to
//use the Grid Service to send the instant message.
public virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
{
GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync;
@ -533,8 +536,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
if (upd != null)
{
GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID,
upd.RegionID);
GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID);
// If we found the reginfo, send the IM to the region
if (reginfo != null)
{
Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
@ -623,6 +627,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
{
m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), reginfo.ServerURI.ToString());
}
catch (Exception e)
{
m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error doIMSending to {0}, Error Message -- {1} ", reginfo.ServerURI.ToString(), e.ToString());
}
return false;
}

View File

@ -1363,6 +1363,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
protected List<GridRegion> RequestNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
{
Scene pScene = avatar.Scene;
m_log.DebugFormat("[ENTITY TRANSFER MODULE] Request neighbors for {0} at {1}/{2}",
pScene.RegionInfo.RegionName, pRegionLocX, pRegionLocY);
RegionInfo m_regionInfo = pScene.RegionInfo;
Border[] northBorders = pScene.NorthBorders.ToArray();
@ -1682,7 +1684,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (destination != null && !CrossPrimGroupIntoNewRegion(destination, grp, silent))
{
grp.OffsetForNewRegion(oldGroupPosition);
grp.ScheduleGroupForFullUpdate();
//grp.ScheduleGroupForFullUpdate();
grp.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.GroupPosition});
}
}

View File

@ -692,7 +692,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
{
// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
@ -783,10 +783,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
string rawX = el.GetAttribute("offsetx");
string rawY = el.GetAttribute("offsety");
string rawZ = el.GetAttribute("offsetz");
//
// m_log.DebugFormat(
// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
// g.Name, rawX, rawY, rawZ);
//
// m_log.DebugFormat(
// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
// g.Name, rawX, rawY, rawZ);
float x = Convert.ToSingle(rawX);
float y = Convert.ToSingle(rawY);
@ -814,7 +814,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
return null;
}
for (int i = 0 ; i < objlist.Count; i++)
for (int i = 0; i < objlist.Count; i++)
{
group = objlist[i];
@ -850,13 +850,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// one full update during the attachment
// process causes some clients to fail to display the
// attachment properly.
m_Scene.AddNewSceneObject(group, true, false);
//m_Scene.AddNewSceneObject(group, true, false);
//DSG SYNC: tell RegionSyncModule not to call SyncNewObject
// yet, as not all properties have been set yet
bool triggerSyncNewObject = false;
m_Scene.AddNewSceneObjectByRez(group, true, false, triggerSyncNewObject);
// if attachment we set it's asset id so object updates
// can reflect that, if not, we set it's position in world.
if (!attachment)
{
group.ScheduleGroupForFullUpdate();
group.ScheduleGroupForFullUpdate(null);
group.AbsolutePosition = pos + veclist[i];
}
@ -943,8 +947,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// Fire on_rez
group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
rootPart.ParentGroup.ResumeScripts();
rootPart.ScheduleFullUpdate();
rootPart.ScheduleFullUpdate(null);
}
}
@ -963,6 +966,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
}
}
}
//DSG SYNC: now all properties have been set, sending NewObject message,
if (m_Scene.RegionSyncModule != null)
{
m_Scene.RegionSyncModule.SyncNewObject(group);
}
}
return group;
}
@ -970,6 +979,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
return null;
}
protected void AddUserData(SceneObjectGroup sog)
{
UserManagementModule.AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData);

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using System.Text;
using OpenMetaverse;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
// Class queues updates for UUID's.
// The updates could be JSON, serialized object data, or any string.
// Updates are queued to the end and dequeued from the front of the queue
// Enqueuing an update with the same UUID will replace the previous update
// so it will not lose its place.
class BlockingUpdateQueue
{
private object m_syncRoot = new object();
private Queue<UUID> m_queue = new Queue<UUID>();
private Dictionary<UUID, byte[]> m_updates = new Dictionary<UUID, byte[]>();
// Enqueue an update
public void Enqueue(UUID id, byte[] update)
{
lock(m_syncRoot)
{
if (!m_updates.ContainsKey(id))
m_queue.Enqueue(id);
m_updates[id] = update;
Monitor.Pulse(m_syncRoot);
}
}
// Dequeue an update
public byte[] Dequeue()
{
lock (m_syncRoot)
{
// If the queue is empty, wait for it to contain something
while (m_queue.Count == 0)
Monitor.Wait(m_syncRoot);
UUID id = m_queue.Dequeue();
byte[] update = m_updates[id];
m_updates.Remove(id);
return update;
}
}
// Count of number of items currently queued
public int Count
{
get
{
lock (m_syncRoot)
return m_queue.Count;
}
}
}
}

View File

@ -0,0 +1,179 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
class DSGClientManagerLoadBalancer
{
private List<RegionSyncClientView> m_cvs = new List<RegionSyncClientView>();
private ILog m_log;
private int m_maxClientsPerClientManager;
private Scene m_scene;
// The list of clients and the threads handling IO for each client
// The list is read most of the time and only updated when a new client manager
// connects, so we just replace the list when it changes. Iterators on this
// list need to be able to handle if an element is shutting down.
private object m_clientview_lock = new object();
private HashSet<RegionSyncClientView> m_client_views = new HashSet<RegionSyncClientView>();
public int Count
{
get
{
return m_client_views.Count;
}
}
public void ReportStats(System.IO.TextWriter tw)
{
}
public DSGClientManagerLoadBalancer(int maxClientsPerClientManager, Scene scene)
{
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
m_maxClientsPerClientManager = maxClientsPerClientManager;
m_scene = scene;
}
// Add the client view to the list and increment synced client counter
public void AddSyncedClient(RegionSyncClientView rscv)
{
lock (m_clientview_lock)
{
HashSet<RegionSyncClientView> currentlist = m_client_views;
HashSet<RegionSyncClientView> newlist = new HashSet<RegionSyncClientView>(currentlist);
newlist.Add(rscv);
// Anyone holding the previous version of the list can keep using it since
// they will not hold it for long and get a new copy next time they need to iterate
m_client_views = newlist;
}
}
// A CV is essentially requesting to be shut down.
// Other than a hard disconnect, this is the only way a CV will close its connection to CM
// Making this request prompts the balancer to shift all connected clients on that CM to another CM if one exists
// Remove the client view from the list and decrement synced client counter
public void RemoveSyncedClient(RegionSyncClientView rscv)
{
lock (m_clientview_lock)
{
HashSet<RegionSyncClientView> currentlist = m_client_views;
HashSet<RegionSyncClientView> newlist = new HashSet<RegionSyncClientView>(currentlist);
newlist.Remove(rscv);
// Anyone holding the previous version of the list can keep using it since
// they will not hold it for long and get a new copy next time they need to iterate
m_client_views = newlist;
}
}
public void ForEachClientManager(Action<RegionSyncClientView> action)
{
foreach (RegionSyncClientView cv in m_client_views)
{
action(cv);
}
}
public void BalanceLoad()
{
// If we have 1 - 10 agents connected, we are just testing things all. Move all of them to another region
if (m_scene.SceneGraph.GetRootAgentCount() > 0 && m_scene.SceneGraph.GetRootAgentCount() < 10)
{
SpecialRebalance();
return;
}
Dictionary<RegionSyncClientView, int> avSourceRegionCounts = new Dictionary<RegionSyncClientView, int>();
KeyValuePair<RegionSyncClientView, int> destinationRegionCount = new KeyValuePair<RegionSyncClientView,int>(null, m_maxClientsPerClientManager);
foreach (RegionSyncClientView client in m_client_views)
{
int clientCount = client.SyncedAvCount;
if (clientCount > m_maxClientsPerClientManager)
{
avSourceRegionCounts.Add(client, clientCount);
}
else if (clientCount < destinationRegionCount.Value)
{
destinationRegionCount = new KeyValuePair<RegionSyncClientView, int>(client, clientCount);
}
}
// Now we should have a list of regions over the limit and a target region with the lowest number of clients
// Find average load of overloaded and least loaded regions
int currentLoad = 0;
foreach (KeyValuePair<RegionSyncClientView, int> kvp in avSourceRegionCounts)
currentLoad += kvp.Value;
currentLoad += destinationRegionCount.Value;
int targetLoad = (int)(currentLoad/(avSourceRegionCounts.Count + 1));
foreach (KeyValuePair<RegionSyncClientView, int> kvp in avSourceRegionCounts)
{
kvp.Key.BalanceClients(targetLoad, destinationRegionCount.Key.Name);
}
}
private void SpecialRebalance()
{
m_log.Warn("[CLIENT LOAD BALANCER] Begin special rebalance.");
if (m_client_views.Count < 2)
{
m_log.Error("[CLIENT LOAD BALANCER] Could not special balance because there are not at least 2 client managers.");
return;
}
RegionSyncClientView src = null;
RegionSyncClientView dst = null;
// Find the one client
foreach (RegionSyncClientView client in m_client_views)
{
//m_log.WarnFormat("[CLIENT LOAD BALANCER] Client RSCV {0} SyncedAvCount = {1}.", client.Name, client.SyncedAvCount);
if (src != null && dst != null)
break;
// Find a src region with some avatars
if (src == null && client.SyncedAvCount > 0)
src = client;
// Find a dst region with no avatars
else if (dst == null && client.SyncedAvCount == 0)
dst = client;
}
if (src == null || dst == null)
{
m_log.Error("[CLIENT LOAD BALANCER] Could not special balance because a src and dst client manager region could not be identified.");
return;
}
// Send all clients from src to dst
m_log.WarnFormat("[CLIENT LOAD BALANCER] Moving all clients from client manager region {0} to region {1}", src.Name, dst.Name);
src.BalanceClients(0, dst.Name);
}
}
}

View File

@ -0,0 +1,526 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.Client;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes.Types;
using log4net;
using Nini.Config;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
// The RegionSyncPhysEngine has a receive thread to process messages from the RegionSyncServer.
// It is the client side of the synchronization channel, and send to and receive updates from the
// Auth. Scene. The server side thread handling the sync channel is implemented in RegionSyncScriptAPI.cs.
//
// The current implementation is very similar to RegionSyncClient.
// TODO: eventually the same RegionSyncSceneAPI should handle all traffic from different actors, e.g.
// using a pub/sub model.
public class PhysEngineToSceneConnector
{
#region PhysEngineToSceneConnector members
// Set the addr and port of RegionSyncServer
private IPAddress m_addr;
private string m_addrString;
private Int32 m_port;
// A reference to the local scene
private Scene m_validLocalScene;
// The avatars added to this client manager for clients on other client managers
object m_syncRoot = new object();
// The logfile
private ILog m_log;
private string LogHeader = "[PHYSICS ENGINE TO SCENE CONNECTOR]";
// The listener and the thread which listens for connections from client managers
private Thread m_rcvLoop;
// The client connection to the RegionSyncServer
private TcpClient m_client = new TcpClient();
// The queue of incoming messages which need handling
//private Queue<string> m_inQ = new Queue<string>();
//KittyL: added to identify different actors
private ActorType m_actorType = ActorType.PhysicsEngine;
private bool m_debugWithViewer = false;
private long m_messagesSent = 0;
private long m_messagesReceived = 0;
private IConfig m_sysConfig;
//members for load balancing purpose
//private TcpClient m_loadMigrationSouceEnd = null;
//private LoadMigrationEndPoint m_loadMigrationSouceEnd = null;
private Thread m_loadMigrationSrcRcvLoop;
//private LoadMigrationListener m_loadMigrationListener = null;
//List of queued messages, when the space that the updated object is located is being migrated
private List<RegionSyncMessage> m_updateMsgQueue = new List<RegionSyncMessage>();
#endregion
// Constructor
public PhysEngineToSceneConnector(Scene validLocalScene, string addr, int port, bool debugWithViewer,
IConfig sysConfig)
{
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
m_validLocalScene = validLocalScene;
m_addr = IPAddress.Parse(addr);
m_addrString = addr;
m_port = port;
m_debugWithViewer = debugWithViewer;
m_sysConfig = sysConfig;
SceneToPhysEngineSyncServer.logEnabled = m_sysConfig.GetBoolean("PhysLogEnabled", false);
SceneToPhysEngineSyncServer.logDir = m_sysConfig.GetString("PhysLogDir", ".");
}
// Start the RegionSyncPhysEngine client thread
public bool Start()
{
if (EstablishConnection())
{
StartStateSync();
return true;
}
else
{
return false;
}
}
private bool EstablishConnection()
{
if (m_client.Connected)
{
m_log.Warn(LogHeader + ": already connected");
return false;
}
try
{
m_client.Connect(m_addr, m_port);
}
catch (Exception e)
{
m_log.WarnFormat("{0} [Start] Could not connect to SceneToPhysEngineSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
m_log.Warn(e.Message);
return false;
}
m_log.WarnFormat("{0} Connected to SceneToPhysEngineSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
m_rcvLoop = new Thread(new ThreadStart(ReceiveLoop));
m_rcvLoop.Name = "PhysEngineToSceneConnector ReceiveLoop";
m_log.WarnFormat("{0} Starting {1} thread", LogHeader, m_rcvLoop.Name);
m_rcvLoop.Start();
return true;
}
private void StartStateSync()
{
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStatus, Convert.ToString((int)ActorStatus.Sync));
Send(msg);
Thread.Sleep(100);
DoInitialSync();
}
public void RegisterIdle()
{
EstablishConnection();
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStatus, Convert.ToString((int)ActorStatus.Idle));
Send(msg);
}
private void DoInitialSync()
{
}
// Disconnect from the RegionSyncServer and close client thread
public void Stop()
{
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStop, "stop"));
// The remote scene will remove the SceneToPhysEngineConnector when we disconnect
m_rcvLoop.Abort();
ShutdownClient();
//stop the migration connections
//ShutdownClient(m_loadMigrationSouceEnd);
//if (m_loadMigrationListener != null)
// m_loadMigrationListener.Shutdown();
}
public void ReportStatus()
{
m_log.WarnFormat("{0} Synchronized to RegionSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
m_log.WarnFormat("{0} Received={1}, Sent={2}", LogHeader, m_messagesReceived, m_messagesSent);
lock (m_syncRoot)
{
//TODO: should be reporting about the information of the objects/scripts
}
}
private void ShutdownClient()
{
m_log.WarnFormat("{0} Disconnected from RegionSyncServer. Shutting down.", LogHeader);
//TODO: remove the objects and scripts
//lock (m_syncRoot)
//{
//}
if (m_client != null)
{
// Close the connection
m_client.Client.Close();
m_client.Close();
}
SceneToPhysEngineSyncServer.PhysLogMessageClose();
}
// Listen for messages from a RegionSyncServer
// *** This is the main thread loop for each connected client
private void ReceiveLoop()
{
m_log.WarnFormat("{0} Thread running: {1}", LogHeader, m_rcvLoop.Name);
while (true && m_client.Connected)
{
RegionSyncMessage msg;
// Try to get the message from the network stream
try
{
msg = new RegionSyncMessage(m_client.GetStream());
//m_log.WarnFormat("{0} Received: {1}", LogHeader, msg.ToString());
}
// If there is a problem reading from the client, shut 'er down.
catch
{
ShutdownClient();
return;
}
// Try handling the message
try
{
//lock (m_syncRoot) -- KittyL: why do we need to lock here? We could lock inside HandleMessage if necessary, and lock on different objects for better performance
m_messagesReceived++;
HandleMessage(msg);
}
catch (Exception e)
{
m_log.WarnFormat("{0} Encountered an exception: {1} (MSGTYPE = {2})", LogHeader, e.Message, msg.ToString());
}
}
}
#region SEND
//DSG-TODO: for Scene based DSG, Send() also needs to figure out which Scene to send to, e.g. needs a switching function based on object position
// Send a message to a single connected RegionSyncServer
private void Send(string msg)
{
byte[] bmsg = System.Text.Encoding.ASCII.GetBytes(msg + System.Environment.NewLine);
Send(bmsg);
}
private void Send(RegionSyncMessage msg)
{
Send(msg.ToBytes());
//m_log.WarnFormat("{0} Sent {1}", LogHeader, msg.ToString());
}
private void Send(byte[] data)
{
if (m_client.Connected)
{
try
{
m_client.GetStream().Write(data, 0, data.Length);
m_messagesSent++;
}
// If there is a problem reading from the client, shut 'er down.
// *** Still need to alert the module that it's no longer connected!
catch
{
ShutdownClient();
}
}
}
#endregion SEND
//KittyL: Has to define SendCoarseLocations() here, since it's defined in IRegionSyncClientModule.
// But should not do much as being PhysEngine, not ClientManager
public void SendCoarseLocations()
{
}
// Handle an incoming message
// Dan-TODO: This should not be synchronous with the receive!
// Instead, handle messages from an incoming Queue so server doesn't block sending
//
// KittyL: This is the function that PhysEngine and ClientManager have the most different implementations
private void HandleMessage(RegionSyncMessage msg)
{
//TO FINISH:
SceneToPhysEngineSyncServer.PhysLogMessage(false, msg);
switch (msg.Type)
{
case RegionSyncMessage.MsgType.RegionName:
{
return;
}
case RegionSyncMessage.MsgType.PhysUpdateAttributes:
{
HandlePhysUpdateAttributes(msg);
return;
}
default:
{
RegionSyncMessage.HandleError(LogHeader, msg, String.Format("{0} Unsupported message type: {1}", LogHeader, ((int)msg.Type).ToString()));
return;
}
}
}
/// <summary>
/// The physics engine has some updates to the attributes. Unpack the parameters, find the
/// correct PhysicsActor and plug in the new values;
/// </summary>
/// <param name="msg"></param>
private void HandlePhysUpdateAttributes(RegionSyncMessage msg)
{
// TODO:
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
try
{
UUID uuid = data["uuid"].AsUUID();
string actorID = data["actorID"].AsString();
// m_log.DebugFormat("{0}: HandlPhysUpdateAttributes for {1}", LogHeader, uuid);
PhysicsActor pa = FindPhysicsActor(uuid);
if (pa != null)
{
if (pa.PhysicsActorType == (int)ActorTypes.Prim)
{
m_log.WarnFormat("{0}: HandlePhysUpdateAttributes for an prim: {1}", LogHeader, pa.UUID);
}
// pa.Size = data["size"].AsVector3();
pa.Position = data["position"].AsVector3();
pa.Force = data["force"].AsVector3();
// m_log.DebugFormat("{0}: HandlePhysUpdateAttributes: receiving velocity = {1}", LogHeader, data["velocity"].AsVector3());
pa.Velocity = data["velocity"].AsVector3();
pa.RotationalVelocity = data["rotationalVelocity"].AsVector3();
pa.Acceleration = data["acceleration"].AsVector3();
pa.Torque = data["torque"].AsVector3();
pa.Orientation = data["orientation"].AsQuaternion();
pa.IsPhysical = data["isPhysical"].AsBoolean(); // receive??
pa.Flying = data["flying"].AsBoolean(); // receive??
pa.Kinematic = data["kinematic"].AsBoolean(); // receive??
pa.Buoyancy = (float)(data["buoyancy"].AsReal());
SceneObjectPart sop = m_validLocalScene.GetSceneObjectPart(uuid);
if (sop != null)
{
pa.Shape = sop.Shape;
}
pa.ChangingActorID = actorID;
m_validLocalScene.PhysicsScene.AddPhysicsActorTaint(pa);
//m_log.DebugFormat("HandlePhysUpdateAttributes, ChangingActorID = {0}, PA pos = {1}, data.position={2}", pa.ChangingActorID, pa.Position, data["position"].AsVector3().ToString());
}
else
{
m_log.WarnFormat("{0}: attribute update for unknown uuid {1}", LogHeader, uuid);
return;
}
}
catch (Exception e)
{
m_log.WarnFormat("{0}: EXCEPTION processing UpdateAttributes: {1}", LogHeader, e);
return;
}
return;
}
// Find the physics actor whether it is an object or a scene presence
private PhysicsActor FindPhysicsActor(UUID uuid)
{
ScenePresence sp = m_validLocalScene.GetScenePresence(uuid);
if (sp != null)
{
return sp.PhysicsActor;
}
SceneObjectPart sop = m_validLocalScene.GetSceneObjectPart(uuid);
if (sop != null)
{
return sop.PhysActor;
}
return null;
}
public void SendPhysUpdateAttributes(PhysicsActor pa)
{
// m_log.DebugFormat("{0}: SendPhysUpdateAttributes for {1}", LogHeader, pa.UUID);
if (pa.PhysicsActorType == (int)ActorTypes.Prim)
{
m_log.WarnFormat("{0}: SendPhysUpdateAttributes for an prim: {1}", LogHeader, pa.UUID);
}
OSDMap data = new OSDMap(17);
data["time"] = OSD.FromString(DateTime.Now.ToString("yyyyMMddHHmmssfff"));
data["localID"] = OSD.FromUInteger(pa.LocalID);
data["uuid"] = OSD.FromUUID(pa.UUID);
data["actorID"] = OSD.FromString(RegionSyncServerModule.ActorID);
data["size"] = OSD.FromVector3(pa.Size);
data["position"] = OSD.FromVector3(pa.Position);
data["force"] = OSD.FromVector3(pa.Force);
data["velocity"] = OSD.FromVector3(pa.Velocity);
// m_log.DebugFormat("{0}: HandlePhysUpdateAttributes: sending velocity = {1}", LogHeader, data["velocity"].AsVector3());
data["rotationalVelocity"] = OSD.FromVector3(pa.RotationalVelocity);
data["acceleration"] = OSD.FromVector3(pa.Acceleration);
data["torque"] = OSD.FromVector3(pa.Torque);
data["orientation"] = OSD.FromQuaternion(pa.Orientation);
data["isPhysical"] = OSD.FromBoolean(pa.IsPhysical);
data["flying"] = OSD.FromBoolean(pa.Flying);
data["buoyancy"] = OSD.FromReal(pa.Buoyancy);
data["isColliding"] = OSD.FromBoolean(pa.IsColliding);
data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround);
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,
OSDParser.SerializeJsonString(data));
Send(rsm);
return;
}
#region Utility functions
private OSDMap GetOSDMap(string strdata)
{
OSDMap args = null;
OSD buffer = OSDParser.DeserializeJson(strdata);
if (buffer.Type == OSDType.Map)
{
args = (OSDMap)buffer;
return args;
}
return null;
}
HashSet<string> exceptions = new HashSet<string>();
private OSDMap DeserializeMessage(RegionSyncMessage msg)
{
OSDMap data = null;
try
{
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
}
catch (Exception e)
{
lock (exceptions)
// If this is a new message, then print the underlying data that caused it
if (!exceptions.Contains(e.Message))
m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
data = null;
}
return data;
}
public string GetServerAddressAndPort()
{
return m_addr.ToString() + ":" + m_port.ToString();
}
#endregion Utility functions
#region Handlers for Scene events
private void HandleAddOrUpdateObjectInLocalScene(RegionSyncMessage msg)
{
// TODO: modify for physics
OSDMap data = DeserializeMessage(msg);
uint locX = data["locX"].AsUInteger();
uint locY = data["locY"].AsUInteger();
string sogxml = data["sogXml"].AsString();
SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml);
}
#endregion Handlers for events/updates from Scene
public string StatisticIdentifier()
{
return "PhysEngineToSceneConnector";
}
public string StatisticLine(bool clearFlag)
{
string ret = "";
/*
lock (stats)
{
ret = String.Format("{0},{1},{2},{3},{4},{5}",
msgsIn, msgsOut, bytesIn, bytesOut
);
if (clearFlag)
msgsIn = msgsOut = bytesIn = bytesOut = 0;
}
*/
return ret;
}
public string StatisticTitle()
{
return "msgsIn,msgsOut,bytesIn,bytesOut";
}
}
}

View File

@ -0,0 +1,432 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Physics.Manager;
using OpenSim.Services.Interfaces;
using log4net;
using System.Net;
using System.Net.Sockets;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
//The connector that connects the local Scene (cache) and remote authoratative Scene
public class PhysEngineToSceneConnectorModule : IRegionModule, IPhysEngineToSceneConnectorModule, ICommandableModule
{
#region PhysEngineToSceneConnectorModule members and functions
private static int m_activeActors = 0;
private bool m_active = false;
private string m_serveraddr;
private int m_serverport;
private Scene m_scene;
private static List<Scene> m_allScenes = new List<Scene>();
private ILog m_log;
private Object m_client_lock = new Object();
//private PhysEngineToSceneConnector m_scriptEngineToSceneConnector = null;
private IConfig m_syncConfig = null;
public IConfig SyncConfig { get { return m_syncConfig; } }
private bool m_debugWithViewer = false;
public bool DebugWithViewer { get { return m_debugWithViewer; } }
private string m_regionSyncMode = "";
//Variables relavant for multi-scene subscription.
private Dictionary<string, PhysEngineToSceneConnector> m_PEToSceneConnectors = new Dictionary<string, PhysEngineToSceneConnector>(); //connector for each auth. scene
private string LogHeader = "[PhysEngineToSceneConnectorModule]";
private PhysEngineToSceneConnector m_idlePEToSceneConnector = null;
private PhysEngineToSceneConnector m_physEngineToSceneConnector = null;
private string m_subscriptionSpaceString;
#endregion PhysEngineToSceneConnectorModule members and functions
#region IRegionModule Members
public void Initialise(Scene scene, IConfigSource config)
{
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
m_active = false; //set to false unless this is the valid local scene
//Read in configuration
IConfig syncConfig = config.Configs["RegionSyncModule"];
if (syncConfig != null
&& syncConfig.GetBoolean("Enabled", false)
// && syncConfig.GetString("Mode", "").ToLower() == "client"
&& syncConfig.GetBoolean("PhysEngineClient", false)
)
{
//scene.RegionSyncEnabled = true;
}
else
{
//scene.RegionSyncEnabled = false;
m_log.Warn(LogHeader + ": Not in physics engine client mode. Shutting down.");
return;
}
m_active = true;
m_activeActors++;
m_log.Debug(LogHeader + " Init PEToSceneConnectorModule, for local scene " + scene.RegionInfo.RegionName);
m_scene = scene;
m_scene.RegisterModuleInterface<IPhysEngineToSceneConnectorModule>(this);
m_syncConfig = syncConfig;
m_debugWithViewer = syncConfig.GetBoolean("PhysEngineDebugWithViewer", false);
m_subscriptionSpaceString = syncConfig.GetString("InitSubscriptionSpace", "0_0,256_256");
// Setup the command line interface
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
InstallInterfaces();
m_log.Warn(LogHeader + " Initialised");
// collect all the scenes for later routing
if (!m_allScenes.Contains(scene))
{
m_allScenes.Add(scene);
}
}
public void PostInitialise()
{
if (!m_active)
return;
Start(); // fake a 'phys start' to get things going
//m_log.Warn(LogHeader + " Post-Initialised");
}
public void Close()
{
if (m_active)
{
}
m_scene = null;
m_active = false;
m_activeActors--;
}
public string Name
{
get { return "RegionSyncPhysEngineModule"; }
}
public bool IsSharedModule
{
get { return false; }
}
#endregion
#region ICommandableModule Members
private readonly Commander m_commander = new Commander("phys");
public ICommander CommandInterface
{
get { return m_commander; }
}
#endregion
#region IPhysEngineToSceneConnectorModule members
public bool Active
{
get { return m_active; }
}
public bool Synced
{
get
{
lock(m_client_lock)
{
return (m_PEToSceneConnectors.Count > 0);
}
}
}
bool IPhysEngineToSceneConnectorModule.IsPhysEngineActor()
{
return PhysEngineToSceneConnectorModule.IsPhysEngineActorS;
}
bool IPhysEngineToSceneConnectorModule.IsPhysEngineScene()
{
return PhysEngineToSceneConnectorModule.IsPhysEngineSceneS;
}
bool IPhysEngineToSceneConnectorModule.IsActivePhysEngineScene()
{
return PhysEngineToSceneConnectorModule.IsActivePhysEngineSceneS;
}
public static bool IsPhysEngineSceneS
{
get { return SceneToPhysEngineSyncServer.IsPhysEngineScene2S(); }
}
public static bool IsActivePhysEngineSceneS
{
get { return SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S(); }
}
public static bool IsPhysEngineActorS
{
get { return (m_activeActors != 0); }
}
/// <summary>
/// The scene is unknown by ODE so we have to look through the scenes to
/// find the one with this PhysicsActor so we can send the update.
/// </summary>
/// <param name="pa"></param>
public static void RouteUpdate(PhysicsActor pa)
{
SceneObjectPart sop;
ScenePresence sp;
Scene s = null;
foreach (Scene ss in m_allScenes)
{
try
{
sop = ss.GetSceneObjectPart(pa.UUID);
}
catch
{
sop = null;
}
if (sop != null)
{
s = ss;
break;
}
try
{
sp = ss.GetScenePresence(pa.UUID);
}
catch
{
sp = null;
}
if (sp != null)
{
s = ss;
break;
}
}
if (s != null)
{
if (s.PhysEngineToSceneConnectorModule != null)
{
s.PhysEngineToSceneConnectorModule.SendUpdate(pa);
}
else
{
Console.WriteLine("RouteUpdate: PhysEngineToSceneConnectorModule is null");
}
}
else
{
Console.WriteLine("RouteUpdate: no SOP found for {0}", pa.UUID);
}
return;
}
#endregion
#region Event Handlers
#endregion
private void DebugSceneStats()
{
return;
/*
List<ScenePresence> avatars = m_scene.GetAvatars();
List<EntityBase> entities = m_scene.GetEntities();
m_log.WarnFormat("{0} There are {1} avatars and {2} entities in the scene", LogHeader, avatars.Count, entities.Count);
*/
}
public void SendUpdate(PhysicsActor pa)
{
if (this.m_physEngineToSceneConnector != null)
{
this.m_physEngineToSceneConnector.SendPhysUpdateAttributes(pa);
}
}
#region Console Command Interface
//IMPORTANT: these functions should only be actived for the PhysEngineToSceneConnectorModule that is associated with the valid local scene
private void InstallInterfaces()
{
Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer.");
//cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer.");
//cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
//cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status.");
m_commander.RegisterCommand("start", cmdSyncStart);
m_commander.RegisterCommand("stop", cmdSyncStop);
m_commander.RegisterCommand("status", cmdSyncStatus);
lock (m_scene)
{
// Add this to our scene so scripts can call these functions
m_scene.RegisterModuleCommander(m_commander);
}
}
/// <summary>
/// Processes commandline input. Do not call directly.
/// </summary>
/// <param name="args">Commandline arguments</param>
private void EventManager_OnPluginConsole(string[] args)
{
if (args[0] == "phys")
{
if (args.Length == 1)
{
m_commander.ProcessConsoleCommand("help", new string[0]);
return;
}
string[] tmpArgs = new string[args.Length - 2];
int i;
for (i = 2; i < args.Length; i++)
tmpArgs[i - 2] = args[i];
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
}
}
private void SyncStart(Object[] args)
{
Start();
}
private void Start()
{
m_serveraddr = m_scene.RegionInfo.PhysicsSyncServerAddress;
m_serverport = m_scene.RegionInfo.PhysicsSyncServerPort;
lock (m_client_lock)
{
//m_log.Warn(LogHeader + " Starting synchronization");
m_log.Warn(LogHeader + ": Starting RegionSyncPhysEngine");
InitPhysEngineToSceneConnector(m_subscriptionSpaceString);
}
}
private void InitPhysEngineToSceneConnector(string space)
{
m_physEngineToSceneConnector = new PhysEngineToSceneConnector(m_scene,
m_serveraddr, m_serverport, m_debugWithViewer, /* space,*/ m_syncConfig);
if (m_physEngineToSceneConnector.Start())
{
m_PEToSceneConnectors.Add(m_scene.RegionInfo.RegionName, m_physEngineToSceneConnector);
}
}
private void SyncStop(Object[] args)
{
lock (m_client_lock)
{
//if (m_scriptEngineToSceneConnector == null)
if(m_PEToSceneConnectors.Count==0 && m_idlePEToSceneConnector==null)
{
m_log.Warn(LogHeader + " Already stopped");
return;
}
if (m_PEToSceneConnectors.Count > 0)
{
foreach (KeyValuePair<string, PhysEngineToSceneConnector> valPair in m_PEToSceneConnectors)
{
PhysEngineToSceneConnector connector = valPair.Value;
if (connector == null)
{
continue;
}
connector.Stop();
}
m_PEToSceneConnectors.Clear();
}
else if (m_idlePEToSceneConnector != null)
{
m_idlePEToSceneConnector.Stop();
m_idlePEToSceneConnector = null;
}
//m_scriptEngineToSceneConnector.Stop();
//m_scriptEngineToSceneConnector = null;
m_log.Warn(LogHeader+": Stopping synchronization");
}
//save script state and stop script instances
// TODO: Load balancing. next line commented out to compile
// m_scene.EventManager.TriggerPhysEngineSyncStop();
//remove all objects
m_scene.DeleteAllSceneObjects();
}
private void SyncStatus(Object[] args)
{
lock (m_client_lock)
{
if (m_PEToSceneConnectors.Count == 0)
{
m_log.Warn(LogHeader + " Not currently synchronized");
return;
}
foreach (KeyValuePair<string, PhysEngineToSceneConnector> pair in m_PEToSceneConnectors)
{
PhysEngineToSceneConnector sceneConnector = pair.Value;
sceneConnector.ReportStatus();
}
}
}
#endregion
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.Reflection;
using System.Runtime.InteropServices;
// General information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenSim.Region.Examples.RegionSyncModule")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("http://opensimulator.org")]
[assembly: AssemblyProduct("OpenSim.Region.Examples.RegionSyncModule")]
[assembly: AssemblyCopyright("Copyright (c) 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f0caca77-7818-4a43-9200-0a8548009a05")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("0.6.4.*")]
[assembly: AssemblyVersion("0.6.4.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,290 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
using System.Net;
using System.Net.Sockets;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
public class RegionSyncClientModule : IRegionModule, IRegionSyncClientModule, ICommandableModule
{
#region IRegionModule Members
public void Initialise(Scene scene, IConfigSource config)
{
/* This config parsing pattern should be used in each of these files:
OpenSim.cs
RegionSyncServerModule.cs
RegionSyncClientModule.cs
*/
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
IConfig syncConfig = config.Configs["RegionSyncModule"];
m_active = false;
if (syncConfig == null)
m_log.Warn("[REGION SYNC CLIENT MODULE] No RegionSyncModule config section found. Shutting down.");
else if (!syncConfig.GetBoolean("Enabled", false))
m_log.Warn("[REGION SYNC CLIENT MODULE] RegionSyncModule is not enabled. Shutting down.");
else if (!syncConfig.GetString("Mode", "").ToLower().Equals("client"))
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] RegionSyncModule is not in client mode. Shutting down.");
else
{
m_scene = scene;
m_active = true;
m_scene.RegionSyncEnabled = true;
m_scene.RegionSyncMode = "client";
//string serverAddrDefault = syncConfig.GetString("ServerIPAddress", "127.0.0.1");
//m_serveraddr = syncConfig.GetString(scene.RegionInfo.RegionName+"_ServerIPAddress", serverAddrDefault);
//int serverPortDefault = syncConfig.GetInt("ServerPort", 13000);
//m_serverport = syncConfig.GetInt(scene.RegionInfo.RegionName+"_ServerPort", serverPortDefault);
m_scene.RegisterModuleInterface<IRegionSyncClientModule>(this);
//m_symsync = syncConfig.GetBoolean("SymSync", false);
// Setup the command line interface
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
InstallInterfaces();
m_log.Warn("[REGION SYNC CLIENT MODULE] Initialised");
}
}
public void PostInitialise()
{
if (!m_active)
return;
// Go ahead and try to sync right away
Start();
}
public void Close()
{
m_scene = null;
}
public string Name
{
get { return "RegionSyncModule"; }
}
public bool IsSharedModule
{
get { return false; }
}
#endregion
#region ICommandableModule Members
private readonly Commander m_commander = new Commander("sync");
public ICommander CommandInterface
{
get { return m_commander; }
}
#endregion
#region IRegionSyncClientModule members
public void SendCoarseLocations()
{
m_client.SendCoarseLocations();
}
public void SendAppearanceToScene(UUID agentID)
{
m_client.SendAppearanceToScene(agentID);
}
public void IncomingLoadBalanceConnection(ScenePresence presence)
{
m_client.IncomingLoadBalanceConnection(presence);
}
public bool Active
{
get { return m_active; }
}
public bool Synced
{
get
{
lock(m_client_lock)
{
return (m_client != null);
}
}
}
#endregion
#region RegionSyncClientModule members
private bool m_active = true;
private string m_serveraddr;
private int m_serverport;
private Scene m_scene;
private ILog m_log;
private Object m_client_lock = new Object();
private RegionSyncClient m_client = null;
//private bool m_symsync = false;
#endregion
#region Event Handlers
#endregion
private void DebugSceneStats()
{
return;
/*
List<ScenePresence> avatars = m_scene.GetAvatars();
List<EntityBase> entities = m_scene.GetEntities();
m_log.WarnFormat("There are {0} avatars and {1} entities in the scene", avatars.Count, entities.Count);
*/
}
#region Console Command Interface
private void InstallInterfaces()
{
Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer.");
//cmdSyncStart.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
//cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer.");
//cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
//cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status.");
m_commander.RegisterCommand("start", cmdSyncStart);
m_commander.RegisterCommand("stop", cmdSyncStop);
m_commander.RegisterCommand("status", cmdSyncStatus);
lock (m_scene)
{
// Add this to our scene so scripts can call these functions
m_scene.RegisterModuleCommander(m_commander);
}
}
/// <summary>
/// Processes commandline input. Do not call directly.
/// </summary>
/// <param name="args">Commandline arguments</param>
private void EventManager_OnPluginConsole(string[] args)
{
if (args[0] == "sync")
{
if (args.Length == 1)
{
m_commander.ProcessConsoleCommand("help", new string[0]);
return;
}
string[] tmpArgs = new string[args.Length - 2];
int i;
for (i = 2; i < args.Length; i++)
tmpArgs[i - 2] = args[i];
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
}
}
private void SyncStart(Object[] args)
{
Start();
}
private void Start()
{
m_serveraddr = m_scene.RegionInfo.AvatarSyncServerAddress;
m_serverport = m_scene.RegionInfo.AvatarSyncServerPort;
if (m_serveraddr.Equals(String.Empty) || m_serverport == -1)
{
m_log.Warn("[REGION SYNC CLIENT MODULE] No IP or port of RegionSyncServer has been configured. Shut down.");
m_active = false;
return;
}
lock (m_client_lock)
{
if (m_client != null)
{
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] Already synchronizing to {0}", m_client.GetServerAddressAndPort());
return;
}
//m_log.Warn("[REGION SYNC CLIENT MODULE] Starting synchronization");
m_log.Warn("[REGION SYNC CLIENT MODULE] Starting RegionSyncClient");
m_client = new RegionSyncClient(m_scene, m_serveraddr, m_serverport);
m_client.Start();
}
}
private void SyncStop(Object[] args)
{
lock(m_client_lock)
{
if (m_client == null)
{
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] Already stopped");
return;
}
m_log.Warn("[REGION SYNC CLIENT MODULE] Stopping synchronization");
m_client.Stop();
m_client = null;
}
}
private void SyncStatus(Object[] args)
{
lock (m_client_lock)
{
if (m_client == null)
{
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] Not currently synchronized");
return;
}
m_log.WarnFormat("[REGION SYNC CLIENT MODULE] Synchronized");
m_client.ReportStatus();
}
}
#endregion
}
}

View File

@ -0,0 +1,898 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Region.Framework.Interfaces;
using log4net;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
#region MsgHandlerStatus Enum
public enum MsgHandlerStatus
{
Success, // Everything went as expected
Trivial, // Minor issue, nothing to worry about
Warning, // Something went wrong, we can continue
Error // This should certainly not have happened! (A bug)
}
#endregion
// The RegionSyncClientView acts as a thread on the RegionSyncServer to handle incoming
// messages from RegionSyncClients.
public class RegionSyncClientView
{
#region RegionSyncClientView members
object stats = new object();
private DateTime lastStatTime;
private long queuedUpdates;
private long dequeuedUpdates;
private long msgsIn;
private long msgsOut;
private long bytesIn;
private long bytesOut;
private long pollBlocks;
private int lastTotalCount;
private int lastLocalCount;
private int lastRemoteCount;
private int msgCount = 0;
// The TcpClient this view uses to communicate with its RegionSyncClient
private TcpClient m_tcpclient;
// Set the addr and port for TcpListener
private IPAddress m_addr;
private Int32 m_port;
private int m_connection_number;
private Scene m_scene;
object m_syncRoot = new object();
Dictionary<UUID, RegionSyncAvatar> m_syncedAvatars = new Dictionary<UUID, RegionSyncAvatar>();
// A queue for incoming and outgoing traffic
//private OpenMetaverse.BlockingQueue<RegionSyncMessage> inbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
//private OpenMetaverse.BlockingQueue<RegionSyncMessage> outbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
private BlockingUpdateQueue m_outQ = new BlockingUpdateQueue();
private ILog m_log;
private Thread m_receive_loop;
private Thread m_send_loop;
private string m_regionName;
public string Name
{
get { return m_regionName; }
}
// A string of the format [REGION SYNC CLIENT VIEW (regionname)] for use in log headers
private string LogHeader
{
get
{
if(m_regionName == null)
return String.Format("[REGION SYNC CLIENT VIEW #{0}]", m_connection_number);
return String.Format("[REGION SYNC CLIENT VIEW #{0} ({1:10})]", m_connection_number, m_regionName);
}
}
// A string of the format "RegionSyncClientView #X" for use in describing the object itself
public string Description
{
get
{
if(m_regionName == null)
return String.Format("RegionSyncClientView #{0}", m_connection_number);
return String.Format("RegionSyncClientView #{0} ({1:10})", m_connection_number, m_regionName);
}
}
public string GetStats()
{
int syncedAvCount = SyncedAvCount; ;
string ret;
lock (stats)
{
double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds;
lastStatTime = DateTime.Now;
int totalAvCount = m_scene.SceneGraph.GetRootAgentCount();
ret = String.Format("[{0,4}/{1,4}], [{2,4}/{3,4}], [{4,4}/{5,4}], [{6,4} ({7,4})], [{8,8} ({9,8:00.00})], [{10,4} ({11,4})], [{12,8} ({13,8:00.00})], [{14,8},{15,8},{16,8}]",
lastTotalCount, totalAvCount, // TOTAL AVATARS
lastLocalCount, syncedAvCount, // LOCAL TO THIS CLIENT VIEW
lastRemoteCount, totalAvCount - syncedAvCount, // REMOTE (SHOULD = TOTAL - LOCAL)
msgsIn, (int)(msgsIn / secondsSinceLastStats),
bytesIn, 8 * (bytesIn / secondsSinceLastStats / 1000000), // IN
msgsOut, (int)(msgsOut / secondsSinceLastStats),
bytesOut, 8 * (bytesOut / secondsSinceLastStats / 1000000), // OUT
m_outQ.Count, (int)(queuedUpdates / secondsSinceLastStats), (int)(dequeuedUpdates/secondsSinceLastStats)); // QUEUE ACTIVITY
msgsIn = msgsOut = bytesIn = bytesOut = pollBlocks = queuedUpdates = dequeuedUpdates = 0;
}
return ret;
}
// Check if the client is connected
public bool Connected
{ get { return m_tcpclient.Connected; } }
#endregion
// Constructor
public RegionSyncClientView(int num, Scene scene, TcpClient client)
{
m_connection_number = num;
m_scene = scene;
m_tcpclient = client;
m_addr = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
m_port = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//m_log.WarnFormat("{0} Constructed", LogHeader);
// Create a thread for the receive loop
m_receive_loop = new Thread(new ThreadStart(delegate() { ReceiveLoop(); }));
m_receive_loop.Name = Description + " (ReceiveLoop)";
//m_log.WarnFormat("{0} Started thread: {1}", LogHeader, m_receive_loop.Name);
m_receive_loop.Start();
m_send_loop = new Thread(new ThreadStart(delegate() { SendLoop(); }));
m_send_loop.Name = Description + " (SendLoop)";
m_send_loop.Start();
}
// Stop the RegionSyncClientView, disconnecting the RegionSyncClient
public void Shutdown()
{
m_scene.EventManager.OnChatFromClient -= EventManager_OnChatFromClient;
m_tcpclient.Client.Close();
m_tcpclient.Close();
//Logout any synced avatars
lock (m_syncRoot)
{
foreach (UUID agentID in m_syncedAvatars.Keys)
{
ScenePresence presence;
if (m_scene.TryGetScenePresence(agentID, out presence))
{
string name = presence.Name;
m_scene.RemoveClient(agentID);
m_log.WarnFormat("{0} Agent \"{1}\" ({2}) was removed from scene.", LogHeader, name, agentID);
}
else
{
m_log.WarnFormat("{0} Agent {1} not found in the scene.", LogHeader, agentID);
}
}
}
}
// Listen for messages from a RegionSyncClient
// *** This is the main receive loop thread for each connected client
private void ReceiveLoop()
{
//DSG SYNC: commenting out the code for handling chats
// m_scene.EventManager.OnChatFromClient += new EventManager.ChatFromClientEvent(EventManager_OnChatFromClient);
// m_scene.EventManager.OnChatFromWorld += new EventManager.ChatFromWorldEvent(EventManager_OnChatFromClient);
//end of DSG SYNC
// Reset stats and time
lastStatTime = DateTime.Now;
msgsIn = msgsOut = bytesIn = bytesOut = 0;
try
{
while (true)
{
RegionSyncMessage msg = GetMessage();
lock (stats)
{
msgsIn++;
bytesIn += msg.Length;
}
try
{
lock (m_syncRoot)
HandleMessage(msg);
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception in HandleMessage({1}) (ReceiveLoop):{2}", LogHeader, msg.Type.ToString(), e.Message);
}
}
}
catch (Exception e)
{
m_log.ErrorFormat("{0} RegionSyncClient has disconnected: {1} (ReceiveLoop)", LogHeader, e.Message);
}
Shutdown();
// Thread exits here
}
// Send messages from the update Q as fast as we can DeQueue them
// *** This is the main send loop thread for each connected client
private void SendLoop()
{
try
{
while (true)
{
// Dequeue is thread safe
byte[] update = m_outQ.Dequeue();
lock (stats)
dequeuedUpdates++;
Send(update);
}
}
catch (Exception e)
{
m_log.ErrorFormat("{0} RegionSyncClient has disconnected: {1} (SendLoop)", LogHeader, e.Message);
}
Shutdown();
}
public void EnqueuePresenceUpdate(UUID id, byte[] update)
{
lock (stats)
queuedUpdates++;
// Enqueue is thread safe
m_outQ.Enqueue(id, update);
}
void EventManager_OnChatFromClient(object sender, OSChatMessage chat)
{
OSDMap data = new OSDMap(5);
data["channel"] = OSD.FromInteger(chat.Channel);
data["msg"] = OSD.FromString(chat.Message);
data["pos"] = OSD.FromVector3(chat.Position);
data["name"] = OSD.FromString(chat.From);
data["id"] = OSD.FromUUID(chat.SenderUUID);
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.ChatFromClient, OSDParser.SerializeJsonString(data)));
}
// Get a message from the RegionSyncClient
private RegionSyncMessage GetMessage()
{
// Get a RegionSyncMessager from the incoming stream
RegionSyncMessage msg = new RegionSyncMessage(m_tcpclient.GetStream());
//m_log.WarnFormat("{0} Received {1}", LogHeader, msg.ToString());
return msg;
}
HashSet<string> exceptions = new HashSet<string>();
private OSDMap DeserializeMessage(RegionSyncMessage msg)
{
OSDMap data = null;
try
{
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
}
catch(Exception e)
{
lock(exceptions)
// If this is a new message, then print the underlying data that caused it
if(!exceptions.Contains(e.Message))
m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
data = null;
}
return data;
}
// Handle an incoming message
// *** Perhaps this should not be synchronous with the receive
// We could handle messages from an incoming Queue
private void HandleMessage(RegionSyncMessage msg)
{
msgCount++;
//string handlerMessage = "";
switch (msg.Type)
{
case RegionSyncMessage.MsgType.RegionName:
{
m_regionName = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.RegionName, m_scene.RegionInfo.RegionName));
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Syncing to region \"{0}\"", m_regionName));
return;
}
case RegionSyncMessage.MsgType.GetAvatars:
{
m_scene.ForEachScenePresence(delegate(ScenePresence presence)
{
// Let the client managers know about this avatar
OSDMap data = new OSDMap(1);
data["agentID"] = OSD.FromUUID(presence.ControllingClient.AgentId);
data["localID"] = OSD.FromUInteger(presence.LocalId);
data["first"] = OSD.FromString(presence.ControllingClient.FirstName);
data["last"] = OSD.FromString(presence.ControllingClient.LastName);
data["startPos"] = OSD.FromVector3(presence.ControllingClient.StartPos);
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.NewAvatar, OSDParser.SerializeJsonString(data)));
});
RegionSyncMessage.HandleSuccess(LogHeader, msg, "Sent all scene avatars");
return;
}
case RegionSyncMessage.MsgType.AgentAdd:
{
OSDMap data = DeserializeMessage(msg);
if (data != null)
{
UUID agentID = data["agentID"].AsUUID();
string first = data["first"].AsString();
string last = data["last"].AsString();
Vector3 startPos = data["startPos"].AsVector3();
if (agentID != null && first != null && last != null && startPos != null)
{
RegionSyncAvatar av = new RegionSyncAvatar(m_scene, agentID, first, last, startPos, this);
lock (m_syncRoot)
{
if (m_syncedAvatars.ContainsKey(agentID))
{
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Attempted to add duplicate avatar with agentID {0}", agentID));
return;
}
m_syncedAvatars.Add(agentID, av);
}
//m_scene.AddNewClient(av);
m_scene.AddNewClient2(av, true, false);
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Handled AddAgent for UUID {0} at {1}", agentID, startPos.ToString()));
return;
}
}
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
case RegionSyncMessage.MsgType.AgentUpdate:
{
int len = 0;
AgentUpdatePacket.AgentDataBlock agentData = new AgentUpdatePacket.AgentDataBlock();
agentData.FromBytes(msg.Data, ref len);
UUID agentID = agentData.AgentID;
RegionSyncAvatar av;
bool found;
lock (m_syncRoot)
{
found = m_syncedAvatars.TryGetValue(agentData.AgentID, out av);
}
if(!found)
{
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Received agent update for avatar not owned by this client view {0}", agentData.AgentID));
return;
}
AgentUpdateArgs arg = new AgentUpdateArgs();
arg.AgentID = agentData.AgentID;
arg.BodyRotation = agentData.BodyRotation;
arg.CameraAtAxis = agentData.CameraAtAxis;
arg.CameraCenter = agentData.CameraCenter;
arg.CameraLeftAxis = agentData.CameraLeftAxis;
arg.CameraUpAxis = agentData.CameraUpAxis;
arg.ControlFlags = agentData.ControlFlags;
arg.Far = agentData.Far;
arg.Flags = agentData.Flags;
arg.HeadRotation = agentData.HeadRotation;
arg.SessionID = agentData.SessionID;
arg.State = agentData.State;
if( av.AgentUpdate(arg) )
{
//RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Handled AgentUpdate for UUID {0}", agentID));
return;
}
else
{
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Could not handle AgentUpdate UUID {0}", agentID));
return;
}
}
case RegionSyncMessage.MsgType.AgentSameRegionTeleport:
//KittyL: added to support same region teleporting
int lent = 0;
TeleportLocationRequestPacket tpLocReq = new TeleportLocationRequestPacket(msg.Data, ref lent);
RegionSyncAvatar avatar;
bool avFound;
lock (m_syncRoot)
{
avFound = m_syncedAvatars.TryGetValue(tpLocReq.AgentData.AgentID, out avatar);
}
if (!avFound)
{
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Received agent update for avatar not owned by this client view {0}", tpLocReq.AgentData.AgentID));
return;
}
m_scene.RequestTeleportLocation(avatar, m_scene.RegionInfo.RegionHandle, tpLocReq.Info.Position,
tpLocReq.Info.LookAt, 16);
return;
case RegionSyncMessage.MsgType.AgentRemove:
{
// Get the data from message and error check
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
// Get the parameters from data and error check
UUID agentID = data["agentID"].AsUUID();
if (agentID == null || agentID == UUID.Zero)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Missing or invalid JSON data.");
return;
}
lock (m_syncRoot)
{
if (m_syncedAvatars.ContainsKey(agentID))
{
m_syncedAvatars.Remove(agentID);
// Find the presence in the scene
ScenePresence presence;
if (m_scene.TryGetScenePresence(agentID, out presence))
{
string name = presence.Name;
m_scene.SceneGraph.DeleteSceneObject(UUID.Zero, true);
m_scene.RemoveClient(agentID);
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Agent \"{0}\" was removed from scene.", name));
return;
}
else
{
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Agent {0} not found in the scene.", agentID));
return;
}
}
else
{
RegionSyncMessage.HandleWarning(LogHeader, msg, String.Format("Agent {0} not in the list of synced avatars.", agentID));
return;
}
}
}
case RegionSyncMessage.MsgType.AvatarAppearance:
{
m_log.DebugFormat("{0} START of AvatarAppearance handler", LogHeader);
// Get the data from message and error check
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
// Get the parameters from data and error check
UUID agentID = data["id"].AsUUID();
if (agentID == null || agentID == UUID.Zero)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Missing or invalid JSON data.");
return;
}
// Tells the avatar factory to pull an updated appearance from the avatar service
m_scene.AvatarFactory.RefreshAppearance(agentID);
m_log.DebugFormat("{0} END of AvatarAppearance handler", LogHeader);
return;
}
case RegionSyncMessage.MsgType.AgentRequestSit:
{
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
UUID agentID = data["agentID"].AsUUID();
UUID targetID = data["targetID"].AsUUID();
Vector3 offset = data["offset"].AsVector3();
// m_log.DebugFormat("{0} AgentRequestSit for {1}", LogHeader, agentID.ToString());
ScenePresence sp;
m_scene.TryGetScenePresence(agentID, out sp);
if (sp != null)
{
sp.HandleAgentRequestSit(sp.ControllingClient, agentID, targetID, offset);
}
return;
}
case RegionSyncMessage.MsgType.AgentSit:
{
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
UUID agentID = data["agentID"].AsUUID();
// m_log.DebugFormat("{0} AgentSit for {1}", LogHeader, agentID.ToString());
ScenePresence sp;
m_scene.TryGetScenePresence(agentID, out sp);
if (sp != null)
{
sp.HandleAgentSit(sp.ControllingClient, agentID);
}
return;
}
case RegionSyncMessage.MsgType.StartAnim:
{
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
UUID agentID = data["agentID"].AsUUID();
UUID animID = data["id"].AsUUID();
// m_log.DebugFormat("{0} AnimStart for {1}", LogHeader, agentID.ToString());
ScenePresence sp;
m_scene.TryGetScenePresence(agentID, out sp);
if (sp != null)
{
sp.HandleStartAnim(sp.ControllingClient, animID);
}
return;
}
case RegionSyncMessage.MsgType.StopAnim:
{
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
UUID agentID = data["agentID"].AsUUID();
UUID animID = data["id"].AsUUID();
// m_log.DebugFormat("{0} AnimStop for {1}", LogHeader, agentID.ToString());
ScenePresence sp;
m_scene.TryGetScenePresence(agentID, out sp);
if (sp != null)
{
sp.HandleStopAnim(sp.ControllingClient, animID);
}
return;
}
case RegionSyncMessage.MsgType.GrabObject:
{
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
UUID agentID = data["agentID"].AsUUID();
uint localID = data["localID"].AsUInteger();
m_log.DebugFormat("{0} GrabObject for {1}. object={2}",
LogHeader, agentID.ToString(), localID);
Vector3 offsetPos = data["offsetPos"].AsVector3();
OSDArray surfaceArray = (OSDArray)data["surfaceArgs"];
List<SurfaceTouchEventArgs> surfaceArgs = ExtractSurfaceArgList(surfaceArray);
ScenePresence sp;
m_scene.TryGetScenePresence(agentID, out sp);
if (sp != null)
{
m_scene.ProcessObjectGrab(localID, offsetPos, sp.ControllingClient, surfaceArgs);
}
return;
}
case RegionSyncMessage.MsgType.GrabUpdate:
{
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
UUID agentID = data["agentID"].AsUUID();
UUID objectID = data["objectID"].AsUUID();
// m_log.DebugFormat("{0} GrabUpdate for {1}. ObjectID={2}",
// LogHeader, agentID.ToString(), objectID.ToString());
Vector3 offset = data["offset"].AsVector3();
Vector3 pos = data["pos"].AsVector3();
OSDArray surfaceArray = (OSDArray)data["surfaceArgs"];
List<SurfaceTouchEventArgs> surfaceArgs = ExtractSurfaceArgList(surfaceArray);
ScenePresence sp;
m_scene.TryGetScenePresence(agentID, out sp);
if (sp != null)
{
m_scene.ProcessObjectGrabUpdate(objectID, offset, pos, sp.ControllingClient, surfaceArgs);
}
return;
}
case RegionSyncMessage.MsgType.DeGrabObject:
{
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
UUID agentID = data["agentID"].AsUUID();
m_log.DebugFormat("{0} DeGrabUpdate for {1}", LogHeader, agentID.ToString());
uint localID = data["objectID"].AsUInteger();
OSDArray surfaceArray = (OSDArray)data["surfaceArgs"];
List<SurfaceTouchEventArgs> surfaceArgs = ExtractSurfaceArgList(surfaceArray);
ScenePresence sp;
m_scene.TryGetScenePresence(agentID, out sp);
if (sp != null)
{
m_scene.ProcessObjectDeGrab(localID, sp.ControllingClient, surfaceArgs);
}
return;
}
case RegionSyncMessage.MsgType.ChatFromClient:
{
// Get the data from message and error check
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
OSChatMessage args = new OSChatMessage();
args.Channel = data["channel"].AsInteger();
args.Message = data["msg"].AsString();
args.Position = data["pos"].AsVector3();
args.From = data["name"].AsString();
UUID id = data["id"].AsUUID();
args.Scene = m_scene;
args.Type = ChatTypeEnum.Say;
ScenePresence sp;
m_scene.TryGetScenePresence(id, out sp);
if(sp != null)
{
args.Sender = sp.ControllingClient;
args.SenderUUID = id;
m_scene.EventManager.TriggerOnChatFromClient(sp.ControllingClient,args);
}
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Received chat from \"{0}\"", args.From));
return;
}
case RegionSyncMessage.MsgType.RegionStatus:
{
// Get the data from message and error check
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
int t = data["total"].AsInteger();
int l = data["local"].AsInteger();
int r = data["remote"].AsInteger();
lastTotalCount = t;
lastLocalCount = l;
lastRemoteCount = r;
//RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Received stats: {0},{1},{2}", t, l, r));
return;
}
case RegionSyncMessage.MsgType.AvatarTeleportIn:
{
// Get the data from message and error check
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
UUID agentID = data["agentID"].AsUUID();
ScenePresence sp;
m_scene.TryGetScenePresence(agentID, out sp);
if (sp == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Presence is not in scene");
return;
}
if (sp.ControllingClient is RegionSyncAvatar)
{
m_syncedAvatars.Add(agentID, (RegionSyncAvatar)sp.ControllingClient);
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Avatar {0} now owned by region {1}", sp.Name, m_regionName));
return;
}
else
{
RegionSyncMessage.HandleError(LogHeader, msg, "Presence is not a RegionSyncAvatar");
return;
}
}
case RegionSyncMessage.MsgType.AvatarTeleportOut:
{
// Get the data from message and error check
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
UUID agentID = data["agentID"].AsUUID();
ScenePresence sp;
m_scene.TryGetScenePresence(agentID, out sp);
if (sp == null)
{
RegionSyncMessage.HandleError(LogHeader, msg, "Presence is not in scene");
return;
}
if (sp.ControllingClient is RegionSyncAvatar)
{
m_syncedAvatars.Remove(agentID);
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Avatar {0} is no longer owned by region {1}", sp.Name, m_regionName));
return;
}
else
{
RegionSyncMessage.HandleError(LogHeader, msg, "Presence is not a RegionSyncAvatar");
return;
}
}
default:
{
m_log.WarnFormat("{0} Unable to handle unsupported message type: {1}", LogHeader, msg.ToString());
return;
}
}
}
private List<SurfaceTouchEventArgs> ExtractSurfaceArgList(OSDArray args)
{
List<SurfaceTouchEventArgs> surfaceArgs = new List<SurfaceTouchEventArgs>();
for (int ii = 0; ii < args.Count; ii++)
{
SurfaceTouchEventArgs stea = new SurfaceTouchEventArgs();
OSDMap entry = (OSDMap)args[ii];
stea.Binormal = entry["binormal"].AsVector3();
stea.FaceIndex = entry["faceIndex"].AsInteger();
stea.Normal = entry["normal"].AsVector3();
stea.Position = entry["position"].AsVector3();
stea.STCoord = entry["stCoord"].AsVector3();
stea.UVCoord = entry["uvCoord"].AsVector3();
surfaceArgs.Add(stea);
}
return surfaceArgs;
}
private bool HandlerDebug(RegionSyncMessage msg, string handlerMessage)
{
m_log.WarnFormat("{0} DBG ({1}): {2}", LogHeader, msg.ToString(), handlerMessage);
return true;
}
private bool HandlerSuccess(RegionSyncMessage msg, string handlerMessage)
{
m_log.WarnFormat("{0} Handled {1}: {2}", LogHeader, msg.ToString(), handlerMessage);
return true;
}
private bool HandlerFailure(RegionSyncMessage msg, string handlerMessage)
{
m_log.WarnFormat("{0} Unable to handle {1}: {2}", LogHeader, msg.ToString(), handlerMessage);
return false;
}
public void Send(RegionSyncMessage msg)
{
//if (msg.Type == RegionSyncMessage.MsgType.AvatarAppearance)
//m_log.WarnFormat("{0} Sending AvatarAppearance to client manager", LogHeader);
Send(msg.ToBytes());
}
private void Send(byte[] data)
{
if (m_tcpclient.Connected)
{
try
{
lock (stats)
{
msgsOut++;
bytesOut += data.Length;
}
m_tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar =>
{
if(m_tcpclient.Connected)
{
try
{
m_tcpclient.GetStream().EndWrite(ar);
}
catch(Exception)
{}
}
}, null);
}
catch (IOException)
{
m_log.WarnFormat("{0} RegionSyncClient has disconnected.", LogHeader);
}
}
}
public int SyncedAvCount
{
get
{
lock (m_syncRoot)
return m_syncedAvatars.Count;
}
}
public void ReportStatus()
{
int syncedAvCount = SyncedAvCount;
lock (stats)
{
bool localcheck = true;
bool remotecheck = true;
bool totalcheck = true;
if (syncedAvCount != lastLocalCount)
localcheck = false;
if (m_scene.SceneGraph.GetRootAgentCount() != lastTotalCount)
totalcheck = false;
if (m_scene.SceneGraph.GetRootAgentCount() - syncedAvCount != lastRemoteCount)
remotecheck = false;
m_log.ErrorFormat("{0} Syncing {1,4} remote presences. Remote scene reporting {2,4} locals, {3,4} remotes, {4,4} total ({5},{6},{7})",
LogHeader, syncedAvCount, lastLocalCount, lastRemoteCount, lastTotalCount, localcheck ? " " : "!", remotecheck ? " " : "!", totalcheck ? " " : "!");
}
}
public void BalanceClients(int targetLoad, string destinationRegion)
{
OSDMap data = new OSDMap(2);
data["endCount"] = OSD.FromInteger(targetLoad);
data["toRegion"] = OSD.FromString(destinationRegion);
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.BalanceClientLoad, OSDParser.SerializeJsonString(data)));
}
}
}

View File

@ -0,0 +1,262 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Text;
using System.IO;
using OpenMetaverse;
using log4net;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
#region ActorType Enum
public enum ActorType
{
Null,
ClientManager,
ScriptEngine,
PhysicsEngine
}
#endregion
#region ActorStatus Enum
public enum ActorStatus
{
Null,
Idle,
Sync
}
#endregion
/// <summary>
/// A message for synchonization message between scenes
/// </summary>
public class RegionSyncMessage
{
//KittyL: added to help identify different actors
#region MsgType Enum
public enum MsgType
{
Null,
//ConnectSyncClient,
//DisconnectSyncClient,
// CM -> SIM(Scene)
ActorConnect,
AgentAdd,
AgentUpdate,
AgentSameRegionTeleport, //from CM to PSA
AgentRemove,
AgentRequestSit,
AgentSit,
GrabObject,
GrabUpdate,
DeGrabObject,
StartAnim,
StopAnim,
GetTerrain,
GetObjects,
SubscribeObjects,
GetAvatars,
SubscribeAvatars,
ChatFromClient,
AvatarTeleportOut, // An LLClientView (real client) was converted to a RegionSyncAvatar
AvatarTeleportIn, // A RegionSyncAvatar was converted to an LLClientView (real client)
AvatarTeleportSameRegion, //from PSA to PE
// SIM -> CM
//Terrain,
//NewObject, // objects
//UpdatedObject, // objects
//RemovedObject, // objects
NewAvatar, // avatars
UpdatedAvatar, // avatars
AnimateAvatar,
AvatarAppearance,
RemovedAvatar, // avatars
BalanceClientLoad, // Tells CM a client load target and a place to teleport the extras
ChatFromSim,
SitResponse,
SendAnimations,
// BIDIR
EchoRequest,
EchoResponse,
RegionName,
RegionStatus,
//Added by KittyL
// Actor -> Scene
ActorType, //to register the type (e.g. Client Manager or Script Engine) with Scene when sync channel is initialized
SetObjectProperty,
ActorStop,
ResetScene,
OnRezScript,
OnScriptReset,
OnUpdateScript,
// Scene -> Script Engine
NewObjectWithScript,
SceneLocation,
//For load balancing purpose (among script engines)
//Temorarily put here, for easier first round of implemention.
//Script engine --> Scene
ActorStatus, //if the actor is busying syncing with a Scene, or is just idle. Status: {sync, idle}
LoadBalanceRequest,
LoadMigrationListenerInitiated,
//Scene --> Script engine
LoadMigrationNotice,
LoadBalanceResponse,
LoadBalanceRejection,
// Physics Engine -> Scene
PhysTerseUpdate,
PhysOutOfBounds,
PhysCollisionUpdate,
// Scene -> Physics Engine
PhysUpdateAttributes,
}
#endregion
#region Member Data
private MsgType m_type;
private byte[] m_data;
static ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#endregion
#region Constructors
public RegionSyncMessage(MsgType type, byte[] data)
{
m_type = type;
m_data = data;
}
public RegionSyncMessage(MsgType type, string msg)
{
m_type = type;
m_data = System.Text.Encoding.ASCII.GetBytes(msg);
}
public RegionSyncMessage(MsgType type)
{
m_type = type;
m_data = new byte[0];
}
public RegionSyncMessage(Stream stream)
{
//ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//try
{
m_type = (MsgType)Utils.BytesToInt(GetBytesFromStream(stream, 4));
int length = Utils.BytesToInt(GetBytesFromStream(stream, 4));
m_data = GetBytesFromStream(stream, length);
//log.WarnFormat("RegionSyncMessage Constructed {0} ({1} bytes)", m_type.ToString(), length);
}
/*
catch (Exception e)
{
log.WarnFormat("[REGION SYNC MESSAGE] RegionSyncMessage Constructor encountered an exception {0}", e.Message);
}
* */
}
private byte[] GetBytesFromStream(Stream stream, int count)
{
// Loop to receive the message length
byte[] ret = new byte[count];
int i = 0;
while (i < count)
{
i += stream.Read(ret, i, count - i);
}
return ret;
}
#endregion
#region Accessors
public MsgType Type
{
get { return m_type; }
}
public int Length
{
get { return m_data.Length; }
}
public byte[] Data
{
get { return m_data; }
}
#endregion
#region Conversions
public byte[] ToBytes()
{
byte[] buf = new byte[m_data.Length + 8];
Utils.IntToBytes((int)m_type, buf, 0);
Utils.IntToBytes(m_data.Length, buf, 4);
Array.Copy(m_data, 0, buf, 8, m_data.Length);
return buf;
}
public override string ToString()
{
return String.Format("{0} ({1} bytes)", m_type.ToString(), m_data.Length.ToString());
}
public string ToStringFull()
{
return String.Format("{0}:{1})", m_type.ToString(), Encoding.ASCII.GetString(m_data));
}
#endregion
public static void HandleSuccess(string header, RegionSyncMessage msg, string message)
{
m_log.WarnFormat("{0} Handled {1}: {2}", header, msg.ToString(), message);
}
public static void HandleTrivial(string header, RegionSyncMessage msg, string message)
{
m_log.WarnFormat("{0} Issue handling {1}: {2}", header, msg.ToString(), message);
}
public static void HandleWarning(string header, RegionSyncMessage msg, string message)
{
m_log.WarnFormat("{0} Warning handling {1}: {2}", header, msg.ToString(), message);
}
public static void HandleError(string header, RegionSyncMessage msg, string message)
{
m_log.WarnFormat("{0} Error handling {1}: {2}", header, msg.ToString(), message);
}
public static bool HandlerDebug(string header, RegionSyncMessage msg, string message)
{
m_log.WarnFormat("{0} DBG ({1}): {2}", header, msg.ToString(), message);
return true;
}
}
}

View File

@ -0,0 +1,238 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
using OpenMetaverse;
using log4net;
using OpenSim.Region.Framework.Scenes.Serialization;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
// The RegionSyncServer has a listener thread which accepts connections from RegionSyncClients
// and an additional thread to process updates to/from each RegionSyncClient.
public class RegionSyncServer
{
#region RegionSyncServer members
// Set the addr and port for TcpListener
private IPAddress m_addr;
private Int32 m_port;
private int clientCounter;
// The local scene.
private Scene m_scene;
private ILog m_log;
// The listener and the thread which listens for connections from client managers
private TcpListener m_listener;
private Thread m_listenerThread;
private DSGClientManagerLoadBalancer m_ClientBalancer;
// Check if any of the client views are in a connected state
public bool Synced
{
get
{
return (m_ClientBalancer.Count > 0);
}
}
private string LogHeader()
{
return String.Format("[REGION SYNC SERVER ({0})]", m_scene.RegionInfo.RegionName);
}
public void ReportStats(System.IO.TextWriter tw)
{
tw.WriteLine("{0}: {1} TOTAL LOCAL REMOTE TO_SCENE FROM_SCENE", DateTime.Now.ToLongTimeString(), LogHeader());
tw.WriteLine("{0}: {1} MSGS ( /s ) BYTES ( Mbps ) MSGS ( /s ) BYTES ( Mbps ) QUEUE", DateTime.Now.ToLongTimeString(), LogHeader());
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv) {
{
tw.WriteLine("{0}: [{1}] {2}", DateTime.Now.ToLongTimeString(), rscv.Description, rscv.GetStats());
}
});
tw.Flush();
}
public void ReportStatus()
{
int cvcount = m_ClientBalancer.Count;
m_log.ErrorFormat("{0} Connected to {1} remote client managers", LogHeader(), cvcount);
m_log.ErrorFormat("{0} Local scene contains {1} presences", LogHeader(), m_scene.SceneGraph.GetRootAgentCount());
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv){rscv.ReportStatus();});
}
#endregion
// Constructor
public RegionSyncServer(Scene scene, string addr, int port, int maxClientsPerManager)
{
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
m_scene = scene;
m_addr = IPAddress.Parse(addr);
m_port = port;
m_ClientBalancer = new DSGClientManagerLoadBalancer(maxClientsPerManager, scene);
}
// Start the server
public void Start()
{
m_listenerThread = new Thread(new ThreadStart(Listen));
m_listenerThread.Name = "RegionSyncServer Listener";
m_log.WarnFormat("{0} Starting {1} thread", LogHeader(), m_listenerThread.Name);
m_listenerThread.Start();
}
// Stop the server and disconnect all RegionSyncClients
public void Shutdown()
{
// Stop the listener and listening thread so no new clients are accepted
m_listener.Stop();
m_listenerThread.Abort();
m_listenerThread = null;
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv)
{
// Each client view will clean up after itself
rscv.Shutdown();
m_ClientBalancer.RemoveSyncedClient(rscv);
});
}
// Listen for connections from a new RegionSyncClient
// When connected, start the ReceiveLoop for the new client
private void Listen()
{
m_listener = new TcpListener(m_addr, m_port);
try
{
// Start listening for clients
m_listener.Start();
while (true)
{
// *** Move/Add TRY/CATCH to here, but we don't want to spin loop on the same error
m_log.WarnFormat("{0} Listening for new connections on {1}:{2}...", LogHeader(), m_addr.ToString(), m_port.ToString());
TcpClient tcpclient = m_listener.AcceptTcpClient();
IPAddress addr = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Address;
int port = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Port;
// Add the RegionSyncClientView to the list of clients
// *** Need to work on the timing order of starting the client view and adding to the server list
// so that messages coming from the scene do not get lost before the client view is added but
// not sent before it is ready to process them.
RegionSyncClientView rscv = new RegionSyncClientView(++clientCounter, m_scene, tcpclient);
m_log.WarnFormat("{0} New connection from {1}", LogHeader(), rscv.Description);
m_ClientBalancer.AddSyncedClient(rscv);
}
}
catch (SocketException e)
{
m_log.WarnFormat("{0} [Listen] SocketException: {1}", LogHeader(), e);
}
}
// Broadcast a message to all connected RegionSyncClients
public void Broadcast(RegionSyncMessage msg)
{
List<RegionSyncClientView> closed = null;
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv)
{
// If connected, send the message.
if (rscv.Connected)
{
rscv.Send(msg);
}
// Else, remove the client view from the list
else
{
if (closed == null)
closed = new List<RegionSyncClientView>();
closed.Add(rscv);
}
});
if (closed != null)
{
foreach (RegionSyncClientView rscv in closed)
m_ClientBalancer.RemoveSyncedClient(rscv);
}
}
// Broadcast a message to all connected RegionSyncClients
public void EnqueuePresenceUpdate(UUID id, byte[] update)
{
List<RegionSyncClientView> closed = null;
m_ClientBalancer.ForEachClientManager(delegate(RegionSyncClientView rscv)
{
// If connected, send the message.
if (rscv.Connected)
{
rscv.EnqueuePresenceUpdate(id, update);
}
// Else, remove the client view from the list
else
{
if (closed == null)
closed = new List<RegionSyncClientView>();
closed.Add(rscv);
}
});
if (closed != null)
{
foreach (RegionSyncClientView rscv in closed)
m_ClientBalancer.RemoveSyncedClient(rscv);
}
}
public void BalanceClients()
{
m_ClientBalancer.BalanceLoad();
}
//KittyL:
public void BroadcastToCM(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
{
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
//m_log.Debug("SOG " + sog.UUID);
RegionSyncMessage rsm = new RegionSyncMessage(msgType, sogxml);
Broadcast(rsm);
}
}
}

View File

@ -0,0 +1,559 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using log4net;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
public class RegionSyncServerModule : IRegionModule, IRegionSyncServerModule, ICommandableModule
{
private static int DefaultPort = 13000;
public static string ActorID = "XX";
private static int PortUnknown = -1;
private static string IPAddrUnknown = "";
#region IRegionModule Members
public void Initialise(Scene scene, IConfigSource config)
{
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// If no syncConfig, do not start up server mode
IConfig syncConfig = config.Configs["RegionSyncModule"];
if (syncConfig == null)
{
scene.RegionSyncEnabled = false;
m_active = false;
m_log.Warn("[REGION SYNC SERVER MODULE] No RegionSyncModule config section found. Shutting down.");
return;
}
// If syncConfig does not indicate "enabled", do not start up server mode
bool enabled = syncConfig.GetBoolean("Enabled", true);
if(!enabled)
{
scene.RegionSyncEnabled = false;
m_active = false;
m_log.Warn("[REGION SYNC SERVER MODULE] RegionSyncModule is not enabled. Shutting down.");
return;
}
// get identifying actor ID whether in client or server mode
ActorID = syncConfig.GetString("ActorID", "ZZ");
// If syncConfig does not indicate "server", do not start up server mode
//string mode = syncConfig.GetString("Mode", "server").ToLower();
string mode = syncConfig.GetString("Mode", "").ToLower();
if(mode != "server")
{
//scene.RegionSyncEnabled = false;
m_active = false;
m_log.WarnFormat("[REGION SYNC SERVER MODULE] RegionSyncModule is in {0} mode. Shutting down.", mode);
return;
}
// Enable region sync in server mode on the scene and module
scene.RegionSyncEnabled = true;
scene.RegionSyncMode = mode;
m_active = true;
// Init the sync statistics log file
string syncstats = "syncstats" + "_" + scene.RegionInfo.RegionName + ".txt";
m_statsWriter = File.AppendText(syncstats);
//Get sync server info for Client Manager actors
//string serverAddr = scene.RegionInfo.RegionName + "_ServerIPAddress";
//m_serveraddr = syncConfig.GetString(serverAddr, IPAddrUnknown);
//string serverPort = scene.RegionInfo.RegionName + "_ServerPort";
//m_serverport = syncConfig.GetInt(serverPort, PortUnknown);
// Client manager load balancing
m_maxClientsPerManager = syncConfig.GetInt("MaxClientsPerManager", 100);
DefaultPort++;
//Get sync server info for Script Engine actors
string seServerAddr = scene.RegionInfo.RegionName + "_SceneToSESyncServerIP";
m_seSyncServeraddr = syncConfig.GetString(seServerAddr, IPAddrUnknown);
string seServerPort = scene.RegionInfo.RegionName + "_SceneToSESyncServerPort";
m_seSyncServerport = syncConfig.GetInt(seServerPort, PortUnknown);
DefaultPort++;
//Get sync server info for Physics Engine actors
string peServerAddr = scene.RegionInfo.RegionName + "_SceneToPESyncServerIP";
m_peSyncServeraddr = syncConfig.GetString(peServerAddr, "127.0.0.1");
string peServerPort = scene.RegionInfo.RegionName + "_SceneToPESyncServerPort";
m_peSyncServerport = syncConfig.GetInt(peServerPort, DefaultPort);
DefaultPort++;
m_scene = scene;
m_scene.RegisterModuleInterface<IRegionSyncServerModule>(this);
// Setup the command line interface
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
InstallInterfaces();
//m_log.Warn("[REGION SYNC SERVER MODULE] Initialised");
}
public void PostInitialise()
{
if (!m_active)
return;
//m_scene.EventManager.OnObjectBeingRemovedFromScene += new EventManager.ObjectBeingRemovedFromScene(EventManager_OnObjectBeingRemovedFromScene);
//m_scene.EventManager.OnAvatarEnteringNewParcel += new EventManager.AvatarEnteringNewParcel(EventManager_OnAvatarEnteringNewParcel);
//m_scene.EventManager.OnClientMovement += new EventManager.ClientMovement(EventManager_OnClientMovement);
//m_scene.EventManager.OnLandObjectAdded += new EventManager.LandObjectAdded(EventManager_OnLandObjectAdded);
//m_scene.EventManager.OnLandObjectRemoved += new EventManager.LandObjectRemoved(EventManager_OnLandObjectRemoved);
m_scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
//m_scene.EventManager.OnNewPresence += new EventManager.OnNewPresenceDelegate(EventManager_OnNewPresence);
m_scene.EventManager.OnRemovePresence += new EventManager.OnRemovePresenceDelegate(EventManager_OnRemovePresence);
// Start the server and listen for RegionSyncClients
m_serveraddr = m_scene.RegionInfo.AvatarSyncServerAddress;
m_serverport = m_scene.RegionInfo.AvatarSyncServerPort;
m_log.Debug("[REGION SYNC SERVER MODULE] to start server on " + m_serveraddr + ":" + m_serverport);
if (!m_serveraddr.Equals(IPAddrUnknown) && m_serverport != PortUnknown)
{
m_log.Warn("[REGION SYNC SERVER MODULE] Starting RegionSyncServer");
m_server = new RegionSyncServer(m_scene, m_serveraddr, m_serverport, m_maxClientsPerManager);
m_server.Start();
m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed);
m_statsTimer.Start();
}
m_peSyncServeraddr = m_scene.RegionInfo.PhysicsSyncServerAddress;
m_peSyncServerport = m_scene.RegionInfo.PhysicsSyncServerPort;
if (!m_peSyncServeraddr.Equals(IPAddrUnknown) && m_peSyncServerport != PortUnknown)
{
m_log.Warn("[REGION SYNC SERVER MODULE] Starting SceneToPhysEngineSyncServer");
//Start the sync server for physics engines
m_sceneToPESyncServer = new SceneToPhysEngineSyncServer(m_scene, m_peSyncServeraddr, m_peSyncServerport);
m_sceneToPESyncServer.Start();
}
//m_log.Warn("[REGION SYNC SERVER MODULE] Post-Initialised");
}
private void StatsTimerElapsed(object source, System.Timers.ElapsedEventArgs e)
{
if (Synced)
m_server.ReportStats(m_statsWriter);
}
void IRegionModule.Close()
{
m_scene = null;
}
public string Name
{
get { return "RegionSyncModule"; }
}
public bool IsSharedModule
{
get { return false; }
}
//KittyL added
//Later, should make quarkIDs the argument to the function call
//public void SendResetScene()
//{
// m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.ResetScene, "reset"));
//}
#endregion
#region ICommandableModule Members
private readonly Commander m_commander = new Commander("sync");
public ICommander CommandInterface
{
get { return m_commander; }
}
#endregion
#region IRegionSyncServerModule members
// Lock is used to synchronize access to the update status and both update queues
private object m_updateLock = new object();
private int m_sendingUpdates;
//private Dictionary<UUID, SceneObjectGroup> m_primUpdates = new Dictionary<UUID, SceneObjectGroup>();
private Dictionary<UUID, ScenePresence> m_presenceUpdates = new Dictionary<UUID, ScenePresence>();
private System.Timers.Timer m_statsTimer = new System.Timers.Timer(1000);
//private TextWriter m_statsWriter = File.AppendText("syncstats.txt");
private TextWriter m_statsWriter;
public void QueuePresenceForTerseUpdate(ScenePresence presence)
{
if (!Active || !Synced)
return;
lock (m_updateLock)
{
m_presenceUpdates[presence.UUID] = presence;
}
//m_log.DebugFormat("[REGION SYNC SERVER MODULE] QueuePresenceForUpdate: {0}", presence.UUID.ToString());
}
/// <summary>
/// Send a teleport message out. This should only be called when teleporting within the same region.
/// </summary>
/// <param name="presence"></param>
public void SendTeleportUpdate(ScenePresence presence)
{
if (!Active || !Synced)
return;
System.Threading.ThreadPool.QueueUserWorkItem(delegate
{
OSDMap data = new OSDMap(10);
data["id"] = OSD.FromUUID(presence.UUID);
// Do not include offset for appearance height. That will be handled by RegionSyncClient before sending to viewers
if (presence.AbsolutePosition.IsFinite())
data["pos"] = OSD.FromVector3(presence.AbsolutePosition);
else
data["pos"] = OSD.FromVector3(Vector3.Zero);
/*
if (presence.Velocity.IsFinite())
data["vel"] = OSD.FromVector3(presence.Velocity);
else
data["vel"] = OSD.FromVector3(Vector3.Zero);
if (System.Single.IsNaN(presence.Rotation.X))
data["rot"] = OSD.FromQuaternion(Quaternion.Identity);
else
data["rot"] = OSD.FromQuaternion(presence.Rotation);
data["fly"] = OSD.FromBoolean(presence.Flying);
data["flags"] = OSD.FromUInteger((uint)presence.AgentControlFlags);
data["anim"] = OSD.FromString(presence.Animator.CurrentMovementAnimation);
// needed for a full update
if (presence.ParentID != presence.lastSentParentID)
{
data["coll"] = OSD.FromVector4(presence.CollisionPlane);
data["off"] = OSD.FromVector3(presence.OffsetPosition);
data["pID"] = OSD.FromUInteger(presence.ParentID);
presence.lastSentParentID = presence.ParentID;
}
* */
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.AvatarTeleportSameRegion, OSDParser.SerializeJsonString(data));
m_server.Broadcast(rsm);
});
}
public void SendUpdates()
{
if (!Active || !Synced)
return;
// Existing value of 1 indicates that updates are currently being sent so skip updates this pass
if (Interlocked.Exchange(ref m_sendingUpdates, 1) == 1)
{
m_log.DebugFormat("[REGION SYNC SERVER MODULE] SendUpdates(): An update thread is already running.");
return;
}
List<SceneObjectGroup> primUpdates;
List<ScenePresence> presenceUpdates;
lock (m_updateLock)
{
//primUpdates = new List<SceneObjectGroup>(m_primUpdates.Values);
presenceUpdates = new List<ScenePresence>(m_presenceUpdates.Values);
//m_primUpdates.Clear();
m_presenceUpdates.Clear();
}
// This could be another thread for sending outgoing messages or just have the Queue functions
// create and queue the messages directly into the outgoing server thread.
System.Threading.ThreadPool.QueueUserWorkItem(delegate
{
// Sending the message when it's first queued would yield lower latency but much higher load on the simulator
// as parts may be updated many many times very quickly. Need to implement a higher resolution send in heartbeat
foreach (ScenePresence presence in presenceUpdates)
{
try
{
if (!presence.IsDeleted)
{
OSDMap data = new OSDMap(10);
data["id"] = OSD.FromUUID(presence.UUID);
// Do not include offset for appearance height. That will be handled by RegionSyncClient before sending to viewers
if(presence.AbsolutePosition.IsFinite())
data["pos"] = OSD.FromVector3(presence.AbsolutePosition);
else
data["pos"] = OSD.FromVector3(Vector3.Zero);
if(presence.Velocity.IsFinite())
data["vel"] = OSD.FromVector3(presence.Velocity);
else
data["vel"] = OSD.FromVector3(Vector3.Zero);
if(System.Single.IsNaN(presence.Rotation.X))
data["rot"] = OSD.FromQuaternion(Quaternion.Identity);
else
data["rot"] = OSD.FromQuaternion(presence.Rotation);
data["fly"] = OSD.FromBoolean(presence.Flying);
data["flags"] = OSD.FromUInteger((uint)presence.AgentControlFlags);
data["anim"] = OSD.FromString(presence.Animator.CurrentMovementAnimation);
// needed for a full update
if (presence.ParentID != presence.lastSentParentID)
{
data["coll"] = OSD.FromVector4(presence.CollisionPlane);
data["off"] = OSD.FromVector3(presence.OffsetPosition);
data["pID"] = OSD.FromUInteger(presence.ParentID);
presence.lastSentParentID = presence.ParentID;
}
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.UpdatedAvatar, OSDParser.SerializeJsonString(data));
m_server.EnqueuePresenceUpdate(presence.UUID, rsm.ToBytes());
}
}
catch (Exception e)
{
m_log.ErrorFormat("[REGION SYNC SERVER MODULE] Caught exception sending presence updates for {0}: {1}", presence.Name, e.Message);
}
}
// Indicate that the current batch of updates has been completed
Interlocked.Exchange(ref m_sendingUpdates, 0);
});
}
private Dictionary<UUID, System.Threading.Timer> m_appearanceTimers = new Dictionary<UUID, Timer>();
public void SendAppearance(UUID agentID)
{
OSDMap data = new OSDMap(1);
data["id"] = OSDUUID.FromUUID(agentID);
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.AvatarAppearance, OSDParser.SerializeJsonString(data)));
}
public void SendAnimations(UUID agentID, UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
{
OSDMap data = new OSDMap();
data["agentID"] = OSD.FromUUID(agentID);
OSDArray animatA = new OSDArray();
foreach (UUID uu in animations) animatA.Add(OSD.FromUUID(uu));
data["animations"] = animatA;
OSDArray seqsA = new OSDArray();
foreach (int ss in seqs) seqsA.Add(OSD.FromInteger(ss));
data["seqs"] = seqsA;
data["sourceAgentID"] = OSD.FromUUID(sourceAgentId);
OSDArray obIDA = new OSDArray();
foreach (UUID ii in objectIDs) obIDA.Add(OSD.FromUUID(ii));
data["objectIDs"] = obIDA;
// m_log.DebugFormat("[REGION SYNC SERVER MODULE] Broadcast animations for {0}", agentID.ToString());
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.SendAnimations, OSDParser.SerializeJsonString(data));
m_server.Broadcast(rsm);
// m_clientView.Send(rsm);
}
public bool Active
{
get { return m_active; }
}
// Check if the sync server module is connected to any clients (KittyL: edited for testing if connected to any actors)
public bool Synced
{
get
{
if (m_server == null || !m_server.Synced)
//if((m_server == null || !m_server.Synced) && (m_sceneToSESyncServer==null || !m_sceneToSESyncServer.Synced))
return false;
return true;
}
}
/*
public void SendLoadWorldMap(ITerrainChannel heightMap)
{
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString());
if(m_server!=null)
m_server.Broadcast(msg);
}
* */
#endregion
#region RegionSyncServerModule members
private bool m_active = true;
private string m_serveraddr;
private int m_serverport;
private int m_maxClientsPerManager;
private Scene m_scene;
//private IClientAPI m_clientAggregator;
private ILog m_log;
//private int m_moveCounter = 0;
private RegionSyncServer m_server = null;
//Sync-server for script engines
private string m_seSyncServeraddr;
private int m_seSyncServerport;
//private SceneToScriptEngineSyncServer m_sceneToSESyncServer = null;
//Sync-server for physics engines
private string m_peSyncServeraddr;
private int m_peSyncServerport;
private SceneToPhysEngineSyncServer m_sceneToPESyncServer = null;
//a boolean variable to indicate in symmetric sync is configured
//private bool m_symsync = false;
#endregion
#region Event Handlers
// A ficticious event
public void Scene_AddNewPrim(SceneObjectGroup sog)
{
if (!Synced)
return;
}
private void EventManager_OnNewPresence(ScenePresence presence)
{
if (!Synced)
return;
m_log.WarnFormat("[REGION SYNC SERVER MODULE] (OneNewPresence) \"{0}\"", presence.Name);
}
private void EventManager_OnNewClient(IClientAPI client)
{
if (!Synced)
return;
m_log.WarnFormat("[REGION SYNC SERVER MODULE] Agent \"{0}\" {1} has joined the scene", client.FirstName + " " + client.LastName, client.AgentId.ToString());
// Let the client managers know that a new agent has connected
OSDMap data = new OSDMap(1);
data["agentID"] = OSD.FromUUID(client.AgentId);
data["localID"] = OSD.FromUInteger(m_scene.GetScenePresence(client.AgentId).LocalId);
data["first"] = OSD.FromString(client.FirstName);
data["last"] = OSD.FromString(client.LastName);
data["startPos"] = OSD.FromVector3(client.StartPos);
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.NewAvatar, OSDParser.SerializeJsonString(data)));
}
private void EventManager_OnRemovePresence(UUID agentID)
{
if (!Synced)
return;
/*
ScenePresence avatar;
if (m_scene.TryGetScenePresence(agentID, out avatar))
{
m_log.WarnFormat("[REGION SYNC SERVER MODULE] Avatar \"{0}\" {1} {2} has left the scene", avatar.Firstname + " " + avatar.Lastname, agentID.ToString(), avatar.UUID.ToString());
}
else
{
m_log.WarnFormat("[REGION SYNC SERVER MODULE] Avatar \"unknown\" has left the scene");
}
* */
OSDMap data = new OSDMap();
data["agentID"] = OSD.FromUUID(agentID);
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.RemovedAvatar, OSDParser.SerializeJsonString(data)));
}
#endregion
#region Console Command Interface
private void InstallInterfaces()
{
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Reports current status of the RegionSyncServer.");
Command cmdBalanceClients = new Command("balance", CommandIntentions.COMMAND_HAZARDOUS, BalanceClients, "Balance client load across available client managers.");
m_commander.RegisterCommand("status", cmdSyncStatus);
m_commander.RegisterCommand("balance", cmdBalanceClients);
lock (m_scene)
{
// Add this to our scene so scripts can call these functions
m_scene.RegisterModuleCommander(m_commander);
}
}
/// <summary>
/// Processes commandline input. Do not call directly.
/// </summary>
/// <param name="args">Commandline arguments</param>
private void EventManager_OnPluginConsole(string[] args)
{
if (args[0] == "sync")
{
if (args.Length == 1)
{
m_commander.ProcessConsoleCommand("help", new string[0]);
return;
}
string[] tmpArgs = new string[args.Length - 2];
int i;
for (i = 2; i < args.Length; i++)
tmpArgs[i - 2] = args[i];
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
}
}
private void SyncStatus(Object[] args)
{
if (Synced)
m_server.ReportStatus();
else
m_log.Error("No RegionSyncClients connected");
}
private void BalanceClients(Object[] args)
{
if (Synced)
m_server.BalanceClients();
else
m_log.Error("No RegionSyncClients connected");
}
#endregion
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using OpenMetaverse.StructuredData;
using log4net;
using OpenSim.Framework;
using OpenMetaverse;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
class RegionSyncUtil
{
// The logfile
private static ILog m_log;
//HashSet<string> exceptions = new HashSet<string>();
public static OSDMap DeserializeMessage(RegionSyncMessage msg, string logHeader)
{
OSDMap data = null;
try
{
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
}
catch (Exception e)
{
m_log.Error(logHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
data = null;
}
return data;
}
}
}

View File

@ -0,0 +1,535 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Physics.Manager;
using log4net;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
//KittyL: NOTE -- We need to define an interface for all actors to connect into the Scene,
// e.g. IActorConnector, that runs on the Scene side, processes messages from actors,
// and apply Scene/Object operations.
// The SceneToPhysEngineConnector acts as a thread on the RegionSyncServer to handle incoming
// messages from PhysEngineToSceneConnectors that run on Physics Engines. It connects the
// authoratative Scene with remote script engines.
public class SceneToPhysEngineConnector : ISyncStatistics
{
#region SceneToPhysEngineConnector members
object stats = new object();
private DateTime lastStatTime;
private long msgsIn;
private long msgsOut;
private long bytesIn;
private long bytesOut;
private long pollBlocks;
private int msgCount = 0;
// The TcpClient this view uses to communicate with its RegionSyncClient
private TcpClient m_tcpclient;
// Set the addr and port for TcpListener
private IPAddress m_addr;
private Int32 m_port;
private static int m_connection_number = 0;
private Scene m_scene;
object m_syncRoot = new object();
Dictionary<UUID, RegionSyncAvatar> m_syncedAvatars = new Dictionary<UUID, RegionSyncAvatar>();
// A queue for incoming and outgoing traffic
private OpenMetaverse.BlockingQueue<RegionSyncMessage> inbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
private OpenMetaverse.BlockingQueue<RegionSyncMessage> outbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
private ILog m_log;
private Thread m_receive_loop;
private string m_regionName;
private SceneToPhysEngineSyncServer m_syncServer = null;
// A string of the format [REGION SYNC SCRIPT API (regionname)] for use in log headers
private string LogHeader
{
get
{
if (m_regionName == null)
return String.Format("[SceneToPhysEngineConnector #{0}]", m_connection_number);
return String.Format("[SceneToPhysEngineConnector #{0} ({1:10})]", m_connection_number, m_regionName);
}
}
// A string of the format "RegionSyncClientView #X" for use in describing the object itself
public string Description
{
get
{
if (m_regionName == null)
return String.Format("RegionSyncPhysAPI #{0}", m_connection_number);
return String.Format("RegionSyncPhysAPI #{0} ({1:10})", m_connection_number, m_regionName);
}
}
public int ConnectionNum
{
get { return m_connection_number; }
}
public string StatisticIdentifier()
{
return "SceneToPhysEngineConnector" + ConnectionNum.ToString();
}
public string StatisticLine(bool clearFlag)
{
string ret = "";
lock (stats)
{
double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds;
lastStatTime = DateTime.Now;
ret = String.Format("{0},{1},{2},{3},{4}",
msgsIn, msgsOut, bytesIn, bytesOut, pollBlocks
);
if (clearFlag)
msgsIn = msgsOut = bytesIn = bytesOut = pollBlocks = 0;
}
return ret;
}
public string StatisticTitle()
{
return "msgsIn,msgsOut,bytesIn,bytesOut,pollBlocks";
}
// Check if the client is connected
public bool Connected
{ get { return m_tcpclient.Connected; } }
#endregion
// Constructor
public SceneToPhysEngineConnector(int num, Scene scene, TcpClient client, SceneToPhysEngineSyncServer syncServer)
{
m_connection_number = num;
m_scene = scene;
m_tcpclient = client;
m_addr = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
m_port = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
m_syncServer = syncServer;
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//m_log.WarnFormat("{0} Constructed", LogHeader);
//Register for events from Scene.EventManager
//m_scene.EventManager.OnRezScript += SEConnectorOnRezScript;
//m_scene.EventManager.OnScriptReset += SEConnectorOnScriptReset;
//m_scene.EventManager.OnUpdateScript += SEConnectorOnUpdateScript;
// Create a thread for the receive loop
m_receive_loop = new Thread(new ThreadStart(delegate() { ReceiveLoop(); }));
m_receive_loop.Name = Description;
//m_log.WarnFormat("{0} Started thread: {1}", LogHeader, m_receive_loop.Name);
m_receive_loop.Start();
SyncStatisticCollector.Register(this);
//tell the remote script engine about the locX, locY of this authoritative scene
// SendSceneLoc();
m_log.DebugFormat("{0}: SceneToPhysEngineConnector initialized", LogHeader);
}
// Stop the listening thread, disconnecting the RegionSyncPhysEngine
public void Shutdown()
{
m_syncServer.RemoveSyncedPhysEngine(this);
// m_scene.EventManager.OnChatFromClient -= EventManager_OnChatFromClient;
// Abort ReceiveLoop Thread, close Socket and TcpClient
m_receive_loop.Abort();
m_tcpclient.Client.Close();
m_tcpclient.Close();
//m_scene.EventManager.OnRezScript -= SEConnectorOnRezScript;
//m_scene.EventManager.OnScriptReset -= SEConnectorOnScriptReset;
//m_scene.EventManager.OnUpdateScript -= SEConnectorOnUpdateScript;
}
#region Send/Receive messages to/from the remote Physics Engine
// Listen for messages from a RegionSyncClient
// *** This is the main thread loop for each connected client
private void ReceiveLoop()
{
//m_scene.EventManager.OnChatFromClient += new EventManager.ChatFromClientEvent(EventManager_OnChatFromClient);
// Reset stats and time
lastStatTime = DateTime.Now;
msgsIn = msgsOut = bytesIn = bytesOut = 0;
try
{
while (true)
{
RegionSyncMessage msg = GetMessage();
lock (stats)
{
msgsIn++;
bytesIn += msg.Length;
}
lock (m_syncRoot)
HandleMessage(msg);
}
}
catch (Exception e)
{
m_log.WarnFormat("{0}: has disconnected: {1}", LogHeader, e.Message);
}
Shutdown();
}
// Get a message from the RegionSyncClient
private RegionSyncMessage GetMessage()
{
// Get a RegionSyncMessager from the incoming stream
RegionSyncMessage msg = new RegionSyncMessage(m_tcpclient.GetStream());
//m_log.WarnFormat("{0} Received {1}", LogHeader, msg.ToString());
return msg;
}
// Handle an incoming message
// *** Perhaps this should not be synchronous with the receive
// We could handle messages from an incoming Queue
private void HandleMessage(RegionSyncMessage msg)
{
SceneToPhysEngineSyncServer.PhysLogMessage(true, msg);
msgCount++;
//string handlerMessage = "";
switch (msg.Type)
{
case RegionSyncMessage.MsgType.ActorStop:
{
Shutdown();
}
return;
/*
case RegionSyncMessage.MsgType.LoadBalanceRequest:
{
m_syncServer.HandleLoadBalanceRequest(this);
return;
}
case RegionSyncMessage.MsgType.ActorStatus:
{
string status = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
ActorStatus actorStatus = (ActorStatus)Convert.ToInt32(status);
if (actorStatus == ActorStatus.Sync)
{
m_log.Debug(LogHeader + ": received ActorStatus " + actorStatus.ToString());
m_syncServer.AddSyncedPhysEngine(this);
}
else
{
m_log.Warn(LogHeader + ": not supposed to received RegionSyncMessage.MsgType.ActorStatus==" + status.ToString());
}
return;
}
*/
case RegionSyncMessage.MsgType.PhysTerseUpdate:
{
HandlePhysTerseUpdate(msg);
return;
}
case RegionSyncMessage.MsgType.PhysOutOfBounds:
{
HandlePhysOutOfBounds(msg);
return;
}
case RegionSyncMessage.MsgType.PhysCollisionUpdate:
{
HandlePhysCollisionUpdate(msg);
return;
}
case RegionSyncMessage.MsgType.PhysUpdateAttributes:
{
HandlePhysUpdateAttributes(msg);
return;
}
default:
{
m_log.WarnFormat("{0} Unable to handle unsupported message type", LogHeader);
return;
}
}
}
private void HandlePhysTerseUpdate(RegionSyncMessage msg)
{
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
try
{
UUID uuid = data["uuid"].AsUUID();
// m_log.DebugFormat("{0}: received PhysUpdateAttributes for {1}", LogHeader, uuid);
PhysicsActor pa = FindPhysicsActor(uuid);
if (pa != null)
{
pa.RequestPhysicsterseUpdate();
}
else
{
m_log.WarnFormat("{0}: terse update for unknown uuid {1}", LogHeader, uuid);
return;
}
}
catch (Exception e)
{
m_log.WarnFormat("{0}: EXCEPTION processing PhysTerseUpdate: {1}", LogHeader, e);
return;
}
return;
}
private void HandlePhysOutOfBounds(RegionSyncMessage msg)
{
// TODO:
return;
}
private void HandlePhysCollisionUpdate(RegionSyncMessage msg)
{
// TODO:
return;
}
/// <summary>
/// The physics engine has some updates to the attributes. Unpack the parameters, find the
/// correct PhysicsActor and plug in the new values;
/// </summary>
/// <param name="msg"></param>
private void HandlePhysUpdateAttributes(RegionSyncMessage msg)
{
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
try
{
UUID uuid = data["uuid"].AsUUID();
string actorID = data["actorID"].AsString();
// m_log.DebugFormat("{0}: received PhysUpdateAttributes for {1}", LogHeader, uuid);
PhysicsActor pa = FindPhysicsActor(uuid);
if (pa != null)
{
if (pa.PhysicsActorType == (int)ActorTypes.Prim)
{
m_log.WarnFormat("{0}: HandlePhysUpdateAttributes for an prim: {1}", LogHeader, pa.UUID);
}
pa.Size = data["size"].AsVector3();
pa.Position = data["position"].AsVector3();
pa.Force = data["force"].AsVector3();
pa.Velocity = data["velocity"].AsVector3();
pa.RotationalVelocity = data["rotationalVelocity"].AsVector3();
pa.Acceleration = data["acceleration"].AsVector3();
pa.Torque = data["torque"].AsVector3();
pa.Orientation = data["orientation"].AsQuaternion();
pa.IsPhysical = data["isPhysical"].AsBoolean(); // receive??
pa.Flying = data["flying"].AsBoolean(); // receive??
pa.Kinematic = data["kinematic"].AsBoolean(); // receive??
pa.Buoyancy = (float)(data["buoyancy"].AsReal());
pa.CollidingGround = data["isCollidingGround"].AsBoolean();
pa.IsColliding = data["isColliding"].AsBoolean();
pa.ChangingActorID = actorID;
pa.RequestPhysicsterseUpdate(); // tell the system the values have changed
}
else
{
m_log.WarnFormat("{0}: attribute update for unknown uuid {1}", LogHeader, uuid);
return;
}
}
catch (Exception e)
{
m_log.WarnFormat("{0}: EXCEPTION processing UpdateAttributes: {1}", LogHeader, e);
return;
}
return;
}
// Find the physics actor whether it is an object or a scene presence
private PhysicsActor FindPhysicsActor(UUID uuid)
{
SceneObjectPart sop = m_scene.GetSceneObjectPart(uuid);
if (sop != null)
{
return sop.PhysActor;
}
ScenePresence sp = m_scene.GetScenePresence(uuid);
if (sp != null)
{
return sp.PhysicsActor;
}
return null;
}
public void SendPhysUpdateAttributes(PhysicsActor pa)
{
// m_log.DebugFormat("{0}: sending PhysUpdateAttributes for {1}", LogHeader, pa.UUID);
if (pa.PhysicsActorType == (int)ActorTypes.Prim)
{
m_log.WarnFormat("{0}: SendPhysUpdateAttributes for an prim: {1}", LogHeader, pa.UUID);
}
OSDMap data = new OSDMap(15);
data["time"] = OSD.FromString(DateTime.Now.ToString("yyyyMMddHHmmssfff"));
data["localID"] = OSD.FromUInteger(pa.LocalID);
data["uuid"] = OSD.FromUUID(pa.UUID);
data["actorID"] = OSD.FromString(RegionSyncServerModule.ActorID);
data["size"] = OSD.FromVector3(pa.Size);
data["position"] = OSD.FromVector3(pa.Position);
data["force"] = OSD.FromVector3(pa.Force);
data["velocity"] = OSD.FromVector3(pa.Velocity);
data["rotationalVelocity"] = OSD.FromVector3(pa.RotationalVelocity);
data["acceleration"] = OSD.FromVector3(pa.Acceleration);
data["torque"] = OSD.FromVector3(pa.Torque);
data["orientation"] = OSD.FromQuaternion(pa.Orientation);
data["isPhysical"] = OSD.FromBoolean(pa.IsPhysical);
data["flying"] = OSD.FromBoolean(pa.Flying);
data["buoyancy"] = OSD.FromReal(pa.Buoyancy);
data["isColliding"] = OSD.FromBoolean(pa.IsColliding);
data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround);
//m_log.DebugFormat("SendPhysUpdateAttributes, ChangingActorID = {0}, with PA at pos {1}, data.position={2}", pa.ChangingActorID, pa.Position, data["position"].AsVector3().ToString());
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,
OSDParser.SerializeJsonString(data));
Send(rsm);
return;
}
private RegionSyncMessage PrepareObjectUpdateMessage(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
{
OSDMap data = new OSDMap(3);
data["locX"] = OSD.FromUInteger(m_scene.RegionInfo.RegionLocX);
data["locY"] = OSD.FromUInteger(m_scene.RegionInfo.RegionLocY);
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
data["sogXml"] = OSD.FromString(sogxml);
RegionSyncMessage rsm = new RegionSyncMessage(msgType, OSDParser.SerializeJsonString(data));
return rsm;
}
private void SendSceneLoc()
{
uint locX = m_scene.RegionInfo.RegionLocX;
uint locY = m_scene.RegionInfo.RegionLocY;
OSDMap data = new OSDMap(2);
data["locX"] = OSD.FromUInteger(locX);
data["locY"] = OSD.FromUInteger(locY);
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.SceneLocation, OSDParser.SerializeJsonString(data)));
}
public void Send(RegionSyncMessage msg)
{
if (msg.Type == RegionSyncMessage.MsgType.AvatarAppearance)
m_log.WarnFormat("{0} Sending AvatarAppearance to client manager", LogHeader);
Send(msg.ToBytes());
}
private void Send(byte[] data)
{
if (m_tcpclient.Connected)
{
try
{
lock (stats)
{
msgsOut++;
bytesOut += data.Length;
}
m_tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar =>
{
if (m_tcpclient.Connected)
{
try
{
m_tcpclient.GetStream().EndWrite(ar);
}
catch (Exception)
{
m_log.WarnFormat("{0} Write to output stream failed", LogHeader);
}
}
}, null);
}
catch (IOException)
{
m_log.WarnFormat("{0} Physics Engine has disconnected.", LogHeader);
}
}
else
{
m_log.DebugFormat("{0} Attempt to send with no connection", LogHeader);
}
}
public void SendObjectUpdate(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
{
Send(PrepareObjectUpdateMessage(msgType, sog));
}
#endregion Send/Receive messages to/from the remote Physics Engine
#region Load balancing functions
/*
public void SendLoadBalanceRejection(string response)
{
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.LoadBalanceRejection, response);
Send(msg);
}
*/
#endregion
}
}

View File

@ -0,0 +1,749 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using OpenSim.Framework;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
using log4net;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
//Information of a registered idle physics engine.
//Note, this is a temporary solution to inlcude idle physics engines here.
//In the future, there might be a independent load balaner that keeps track
//of available idle hardware.
public class IdlePhysEngineInfo
{
public TcpClient TClient;
//public IPAddress PhysEngineIPAddr;
//public int PhysEnginePort;
public string ID;
//Will be used to store the overloaded PE that has send LB request and paired with this idle PE
public SceneToPhysEngineConnector AwaitOverloadedSE=null;
public IdlePhysEngineInfo(TcpClient tclient)
{
if(tclient==null) return;
TClient = tclient;
IPAddress ipAddr = ((IPEndPoint)tclient.Client.RemoteEndPoint).Address;
int port = ((IPEndPoint)tclient.Client.RemoteEndPoint).Port;
ID = ipAddr.ToString()+":"+port;
}
}
//Here is the per actor type listening server for physics Engines.
public class SceneToPhysEngineSyncServer : ISceneToPhysEngineServer, ICommandableModule
{
#region SceneToPhysEngineSyncServer members
// Set the addr and port for TcpListener
private IPAddress m_addr;
private Int32 m_port;
//this field is only meaning for the QuarkInfo records on the Scene side
private SceneToPhysEngineConnector m_peConnector=null;
public SceneToPhysEngineConnector PEConnector
{
get { return m_peConnector; }
set { m_peConnector = value; }
}
private int peCounter;
// static counters that are used to compute global configuration state
private static int m_syncServerInitialized = 0;
private static int m_totalConnections = 0;
private static List<Scene> m_allScenes = new List<Scene>();
// The local scene.
private Scene m_scene;
private ILog m_log;
// The listener and the thread which listens for connections from client managers
private TcpListener m_listener;
private Thread m_listenerThread;
private object m_physEngineConnector_lock = new object();
//private Dictionary<string, SceneToPhysEngineConnector> m_physEngineConnectors = new Dictionary<string, SceneToPhysEngineConnector>();
private List<SceneToPhysEngineConnector> m_physEngineConnectors = new List<SceneToPhysEngineConnector>();
// the last connector created
private SceneToPhysEngineConnector m_sceneToPhysEngineConnector = null;
//list of idle physics engines that have registered.
private List<IdlePhysEngineInfo> m_idlePhysEngineList = new List<IdlePhysEngineInfo>();
private string LogHeader = "[SCENE TO PHYS ENGINE SYNC SERVER]";
#region ICommandableModule Members
private readonly Commander m_commander = new Commander("phys");
public ICommander CommandInterface
{
get { return m_commander; }
}
private void InstallInterfaces()
{
// Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer.");
//cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
// Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer.");
//cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
//cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status.");
// m_commander.RegisterCommand("start", cmdSyncStart);
// m_commander.RegisterCommand("stop", cmdSyncStop);
m_commander.RegisterCommand("status", cmdSyncStatus);
lock (m_scene)
{
// Add this to our scene so scripts can call these functions
m_scene.RegisterModuleCommander(m_commander);
}
}
/// <summary>
/// Processes commandline input. Do not call directly.
/// </summary>
/// <param name="args">Commandline arguments</param>
private void EventManager_OnPluginConsole(string[] args)
{
if (args[0] == "phys")
{
if (args.Length == 1)
{
m_commander.ProcessConsoleCommand("help", new string[0]);
return;
}
string[] tmpArgs = new string[args.Length - 2];
int i;
for (i = 2; i < args.Length; i++)
tmpArgs[i - 2] = args[i];
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
}
}
private void SyncStart(Object[] args)
{
return;
}
private void SyncStop(Object[] args)
{
return;
}
private void SyncStatus(Object[] args)
{
lock (m_physEngineConnector_lock)
{
if (m_physEngineConnectors.Count == 0)
{
m_log.Warn(LogHeader + " Not currently synchronized");
return;
}
m_log.Warn(LogHeader + " Synchronized");
foreach (SceneToPhysEngineConnector pec in m_physEngineConnectors)
{
m_log.Warn(pec.StatisticLine(true));
}
}
}
#endregion
// Check if any of the client views are in a connected state
public bool IsPhysEngineScene() { return SceneToPhysEngineSyncServer.IsPhysEngineScene2S(); }
public bool IsActivePhysEngineScene() { return SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S(); }
public bool IsPhysEngineActor() { return SceneToPhysEngineSyncServer.IsPhysEngineActorS; }
public bool Synced
{
get { return (m_physEngineConnectors.Count > 0); }
}
public static bool IsPhysEngineSceneS
{
get { return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0); }
}
public static bool IsPhysEngineScene2S()
{
return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0);
}
public static bool IsActivePhysEngineSceneS
{
get {
System.Console.WriteLine("IsActivePhysEngineScene: si={0} tc={1}",
SceneToPhysEngineSyncServer.m_syncServerInitialized,
SceneToPhysEngineSyncServer.m_totalConnections);
return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0
&& SceneToPhysEngineSyncServer.m_totalConnections > 0);
}
}
public static bool IsActivePhysEngineScene2S()
{
return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0
&& SceneToPhysEngineSyncServer.m_totalConnections > 0);
}
public static bool IsPhysEngineActorS
{
get { return PhysEngineToSceneConnectorModule.IsPhysEngineActorS; }
}
/// <summary>
/// The scene is unknown by ODE so we have to look through the scenes to
/// find the one with this PhysicsActor so we can send the update.
/// </summary>
/// <param name="pa"></param>
public static void RouteUpdate(PhysicsActor pa)
{
SceneObjectPart sop = null;
Scene s = null;
foreach (Scene ss in m_allScenes)
{
try
{
sop = ss.GetSceneObjectPart(pa.UUID);
}
catch
{
sop = null;
}
if (sop != null)
{
s = ss;
break;
}
else
{
ScenePresence sp = ss.GetScenePresence(pa.UUID);
if (sp != null)
{
s = ss;
break;
}
}
}
if (s != null)
{
if (s.SceneToPhysEngineSyncServer != null)
{
s.SceneToPhysEngineSyncServer.SendUpdate(pa);
}
else
{
Console.WriteLine("RouteUpdate: SceneToPhysEngineSyncServer is not available");
}
}
else
{
Console.WriteLine("RouteUpdate: no SOP for update of {0}", pa.UUID);
}
return;
}
public void SendUpdate(PhysicsActor pa)
{
// m_log.DebugFormat("{0}: SendUpdate for {1}", LogHeader, pa.LocalID);
if (m_sceneToPhysEngineConnector != null)
{
this.m_sceneToPhysEngineConnector.SendPhysUpdateAttributes(pa);
}
}
#endregion
// Constructor
public SceneToPhysEngineSyncServer(Scene scene, string addr, int port)
{
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//m_log.Warn(LogHeader + "Constructed");
m_scene = scene;
m_addr = IPAddress.Parse(addr);
m_port = port;
m_scene.RegisterModuleInterface<ISceneToPhysEngineServer>(this);
// remember all the scenes that are configured for connection to physics engine
if (!m_allScenes.Contains(m_scene))
{
m_allScenes.Add(m_scene);
}
SubscribeToEvents();
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
InstallInterfaces();
}
private void SubscribeToEvents()
{
}
private void UnSubscribeToEvents()
{
}
// Start the server
public void Start()
{
SceneToPhysEngineSyncServer.m_syncServerInitialized++;
m_listenerThread = new Thread(new ThreadStart(Listen));
m_listenerThread.Name = "SceneToPhysEngineSyncServer Listener";
m_log.DebugFormat("{0}: Starting {1} thread", LogHeader, m_listenerThread.Name);
m_listenerThread.Start();
// m_log.DebugFormat("{0}: Started", LogHeader);
}
// Stop the server and disconnect all RegionSyncClients
public void Shutdown()
{
m_log.DebugFormat("{0}: Shutdown", LogHeader);
SceneToPhysEngineSyncServer.m_syncServerInitialized--;
// Stop the listener and listening thread so no new clients are accepted
m_listener.Stop();
m_listenerThread.Abort();
m_listenerThread = null;
// Stop all existing SceneTOSEConnectors
//TO FINISH
foreach (SceneToPhysEngineConnector peConnector in m_physEngineConnectors)
{
peConnector.Shutdown();
}
m_physEngineConnectors.Clear();
UnSubscribeToEvents();
}
// Add a connector to a physics engine
public void AddSyncedPhysEngine(SceneToPhysEngineConnector peConnector)
{
lock (m_physEngineConnector_lock)
{
m_physEngineConnectors.Add(peConnector);
m_sceneToPhysEngineConnector = peConnector;
}
}
// Remove the client view from the list and decrement synced client counter
public void RemoveSyncedPhysEngine(SceneToPhysEngineConnector peConnector)
{
lock (m_physEngineConnector_lock)
{
//Dictionary<string, SceneToPhysEngineConnector> currentlist = m_physEngineConnectors;
//Dictionary<string, SceneToPhysEngineConnector> newlist = new Dictionary<string, SceneToPhysEngineConnector>(currentlist);
m_physEngineConnectors.Remove(peConnector);
// Threads holding the previous version of the list can keep using it since
// they will not hold it for long and get a new copy next time they need to iterate
//m_physEngineConnectors = newlist;
}
}
// Listen for connections from a new RegionSyncClient
// When connected, start the ReceiveLoop for the new client
private void Listen()
{
m_listener = new TcpListener(m_addr, m_port);
try
{
// Start listening for clients
m_listener.Start();
while (true)
{
// *** Move/Add TRY/CATCH to here, but we don't want to spin loop on the same error
m_log.WarnFormat(LogHeader + ": Listening for new connections on port {0}...", m_port.ToString());
TcpClient tcpclient = m_listener.AcceptTcpClient();
IPAddress addr = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Address;
int port = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Port;
SceneToPhysEngineSyncServer.m_totalConnections++;
// m_log.DebugFormat("{0}: m_totalConnections = {1}", LogHeader, SceneToPhysEngineSyncServer.m_totalConnections);
ActorStatus actorStatus = GetActorStatus(tcpclient);
switch (actorStatus)
{
case ActorStatus.Sync:
// Add the SceneToPhysEngineConnector to the list
SceneToPhysEngineConnector sceneToPEConnector = new SceneToPhysEngineConnector(++peCounter, m_scene, tcpclient, this);
AddSyncedPhysEngine(sceneToPEConnector);
break;
case ActorStatus.Idle:
IdlePhysEngineInfo idleSE = new IdlePhysEngineInfo(tcpclient);
m_log.DebugFormat("{0}: adding an idle SE ({1}:{2})", LogHeader, addr, port);
m_idlePhysEngineList.Add(idleSE);
break;
default:
m_log.DebugFormat("{0}: Unknown actor status", LogHeader);
break;
}
}
}
catch (SocketException e)
{
m_log.WarnFormat("{0}: [Listen] SocketException: {1}", LogHeader, e);
}
}
/*
public void RegisterSyncedPhysEngine(SceneToPhysEngineConnector sceneToSEConnector)
{
//first, remove it from the idle list
m_idlePhysEngineList.Remove(sceneToSEConnector);
//now, added to the synced SE list
AddSyncedPhysEngine(sceneToSEConnector);
}
* */
// Broadcast a message to all connected RegionSyncClients
public void SendToAllConnectedPE(RegionSyncMessage msg)
{
if (m_physEngineConnectors.Count > 0)
{
m_log.Debug(LogHeader + ": region " + m_scene.RegionInfo.RegionName + " Broadcast to PhysEngine, msg " + msg.Type);
foreach (SceneToPhysEngineConnector peConnector in m_physEngineConnectors)
{
peConnector.Send(msg);
}
}
}
//TO FINISH: Find the right SceneToSEConnector to forward the message
public void SendToPE(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
{
SceneToPhysEngineConnector peConnector = GetSceneToPEConnector(sog);
if (peConnector != null)
{
peConnector.SendObjectUpdate(msgType, sog);
}
}
//This is to send a message, rsm, to phys engine, and the message is about object SOG. E.g. RemovedObject
public void SendToPE(RegionSyncMessage rsm, SceneObjectGroup sog)
{
SceneToPhysEngineConnector peConnector = GetSceneToPEConnector(sog);
if (peConnector != null)
{
peConnector.Send(rsm);
}
}
private SceneToPhysEngineConnector GetSceneToPEConnector(SceneObjectGroup sog)
{
if (m_physEngineConnectors.Count == 0)
return null;
if (sog == null)
{
return m_physEngineConnectors[0];
}
else
{
// TODO: connection of physics engine to quarks. Next line commented out
// SceneToPhysEngineConnector peConnector = m_quarksInScene[quarkID].PEConnector;
if (PEConnector == null)
{
m_log.Warn(LogHeader + sog.AbsolutePosition.ToString() + " not covered by any physics engine");
}
return PEConnector;
}
}
private ActorStatus GetActorStatus(TcpClient tcpclient)
{
m_log.Debug(LogHeader+ ": Get Actor status");
RegionSyncMessage msg = new RegionSyncMessage(tcpclient.GetStream());
ActorStatus actorStatus;
switch (msg.Type)
{
case RegionSyncMessage.MsgType.ActorStatus:
{
string status = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
m_log.Debug(LogHeader + ": recv status: " + status);
actorStatus = (ActorStatus)Convert.ToInt32(status);
break;
}
default:
{
m_log.Error(LogHeader + ": Expect Message Type: ActorStatus");
RegionSyncMessage.HandleError("[REGION SYNC SERVER]", msg, String.Format("{0} Expect Message Type: ActorType", "[REGION SYNC SERVER]"));
return ActorStatus.Null;
}
}
return actorStatus;
}
#region Event Handlers
#endregion Event Handlers
#region Load balancing members and functions
/*
//keep track of idle physics engines that are in the process of load balancing (they are off the idle list, but not a working physics engine yet (not sync'ing with Scene yet)).
private Dictionary<string, IdlePhysEngineInfo> m_loadBalancingIdleSEs = new Dictionary<string,IdlePhysEngineInfo>();
public void HandleLoadBalanceRequest(SceneToPhysEngineConnector seConnctor)
{
//Let's start a thread to do the job, so that we can return quickly and don't block on ReceiveLoop()
Thread partitionThread = new Thread(new ParameterizedThreadStart(TriggerLoadBalanceProcess));
partitionThread.Name = "TriggerLoadBalanceProcess";
partitionThread.Start((object)seConnctor);
}
public void TriggerLoadBalanceProcess(object arg)
{
SceneToPhysEngineConnector seConnctor = (SceneToPhysEngineConnector)arg;
IdlePhysEngineInfo idlePhysEngineInfo = GetIdlePhysEngineConnector();
if (idlePhysEngineInfo != null)
{
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.LoadMigrationNotice);
Send(idlePhysEngineInfo.TClient, msg.ToBytes());
m_log.Debug(LogHeader + ": HandleLoadBalanceRequest from " + seConnctor.Description + ", picked idle SE: " + idlePhysEngineInfo.ID);
//keep track of which overload physics engine is paired up with which idle physics engine
idlePhysEngineInfo.AwaitOverloadedSE = seConnctor;
m_loadBalancingIdleSEs.Add(idlePhysEngineInfo.ID, idlePhysEngineInfo);
m_log.Debug("ToSEConnector portal: local -" +
((IPEndPoint)idlePhysEngineInfo.TClient.Client.LocalEndPoint).Address.ToString() + ":" + ((IPEndPoint)idlePhysEngineInfo.TClient.Client.LocalEndPoint).Port
+ "; remote - " + ((IPEndPoint)idlePhysEngineInfo.TClient.Client.RemoteEndPoint).Address.ToString() + ":"
+ ((IPEndPoint)idlePhysEngineInfo.TClient.Client.RemoteEndPoint).Port);
//Now we expect the idle physics engine to reply back
msg = new RegionSyncMessage(idlePhysEngineInfo.TClient.GetStream());
if (msg.Type != RegionSyncMessage.MsgType.LoadMigrationListenerInitiated)
{
m_log.Warn(LogHeader + ": should receive a message of type LoadMigrationListenerInitiated, but received " + msg.Type.ToString());
}
else
{
//Before the load is migrated from overloaded physics engine to the idle engine, sync with the DB to update the state in DB
List<EntityBase> entities = m_scene.GetEntities();
foreach (EntityBase entity in entities)
{
if (!entity.IsDeleted && entity is SceneObjectGroup && ((SceneObjectGroup)entity).HasGroupChanged)
{
m_scene.ForceSceneObjectBackup((SceneObjectGroup)entity);
}
}
OSDMap data = DeserializeMessage(msg);
if (!data.ContainsKey("ip") || !data.ContainsKey("port") )
{
m_log.Warn(LogHeader + ": parameters missing in SceneLocation message from Scene, need to have ip, port");
return;
}
//echo the information back to the overloaded physics engine
seConnctor.Send(new RegionSyncMessage(RegionSyncMessage.MsgType.LoadBalanceResponse, OSDParser.SerializeJsonString(data)));
m_log.Debug(LogHeader + " now remove physics engine " + idlePhysEngineInfo.ID + " from idle SE list, and create SceneToPhysEngineConnector to it");
//create a SceneToSEConnector for the idle physics engine, who will be sync'ing with this SyncServer soon
SceneToPhysEngineConnector sceneToSEConnector = new SceneToPhysEngineConnector(++peCounter, m_scene, idlePhysEngineInfo.TClient, this);
//Now remove the physics engine from the idle SE list
m_idlePhysEngineList.Remove(idlePhysEngineInfo);
//AddSyncedPhysEngine(sceneToSEConnector);
}
}
else
{
seConnctor.SendLoadBalanceRejection("no idle physics engines");
}
}
*/
HashSet<string> exceptions = new HashSet<string>();
private OSDMap DeserializeMessage(RegionSyncMessage msg)
{
OSDMap data = null;
try
{
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
}
catch (Exception e)
{
lock (exceptions)
// If this is a new message, then print the underlying data that caused it
if (!exceptions.Contains(e.Message))
m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
data = null;
}
return data;
}
private void Send(TcpClient tcpclient, byte[] data)
{
if (tcpclient.Connected)
{
try
{
tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar =>
{
if (tcpclient.Connected)
{
try
{
tcpclient.GetStream().EndWrite(ar);
}
catch (Exception)
{ }
}
}, null);
}
catch (IOException)
{
m_log.WarnFormat("{0} physics Engine has disconnected.", LogHeader);
}
}
}
private IdlePhysEngineInfo GetIdlePhysEngineConnector()
{
if (m_idlePhysEngineList.Count == 0)
return null;
IdlePhysEngineInfo idleSEInfo = m_idlePhysEngineList[0];
m_idlePhysEngineList.Remove(idleSEInfo);
return idleSEInfo;
}
#endregion Load balancing functions
#region Message Logging
public static bool logInput = false;
public static bool logOutput = true;
public static bool logEnabled = false;
private class PhysMsgLogger
{
public DateTime startTime;
public string path = null;
public System.IO.TextWriter Log = null;
}
private static PhysMsgLogger logWriter = null;
private static TimeSpan logMaxFileTime = new TimeSpan(0, 5, 0); // (h,m,s) => 5 minutes
public static string logDir = "/stats/stats";
private static object logLocker = new Object();
public static void PhysLogMessage(bool direction, RegionSyncMessage rsm)
{
if (!logEnabled) return; // save to work of the ToStringFull if not enabled
PhysLogMessage(direction, rsm.ToStringFull());
}
/// <summary>
/// Log a physics bucket message
/// </summary>
/// <param name="direction">True of message originated from the agent</param>
/// <param name="msg">the message to log</param>
public static void PhysLogMessage(bool direction, string msg)
{
if (!logEnabled) return;
lock (logLocker)
{
try
{
DateTime now = DateTime.Now;
if (logWriter == null || (now > logWriter.startTime + logMaxFileTime))
{
if (logWriter != null && logWriter.Log != null)
{
logWriter.Log.Close();
logWriter.Log.Dispose();
logWriter.Log = null;
}
// First log file or time has expired, start writing to a new log file
logWriter = new PhysMsgLogger();
logWriter.startTime = now;
logWriter.path = (logDir.Length > 0 ? logDir + System.IO.Path.DirectorySeparatorChar.ToString() : "")
+ String.Format("physics-{0}.log", now.ToString("yyyyMMddHHmmss"));
logWriter.Log = new StreamWriter(File.Open(logWriter.path, FileMode.Append, FileAccess.Write));
}
if (logWriter != null && logWriter.Log != null)
{
StringBuilder buff = new StringBuilder();
buff.Append(now.ToString("yyyyMMddHHmmssfff"));
buff.Append(" ");
buff.Append(direction ? "A->S:" : "S->A:");
buff.Append(msg);
buff.Append("\r\n");
logWriter.Log.Write(buff.ToString());
}
}
catch (Exception e)
{
// m_log.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
logEnabled = false;
}
}
return;
}
public static void PhysLogMessageClose()
{
if (logWriter != null && logWriter.Log != null)
{
logWriter.Log.Close();
logWriter.Log.Dispose();
logWriter.Log = null;
logWriter = null;
}
logEnabled = false;
}
#endregion Message Logging
}
}

View File

@ -0,0 +1,188 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Mono.Addins;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ClientManagerSyncModule")]
public class ClientManagerSyncModule : INonSharedRegionModule, IDSGActorSyncModule
{
#region INonSharedRegionModule
public void Initialise(IConfigSource config)
{
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
IConfig syncConfig = config.Configs["RegionSyncModule"];
m_active = false;
if (syncConfig == null)
{
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
return;
}
else if (!syncConfig.GetBoolean("Enabled", false))
{
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
return;
}
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
//Read in configuration, if the local actor is configured to be a client manager, load this module.
if (!actorType.Equals("client_manager"))
{
m_log.Warn(LogHeader + ": not configured as Client Manager Actor. Shut down.");
return;
}
m_actorID = syncConfig.GetString("ActorID", "");
if (m_actorID.Equals(""))
{
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
return;
}
m_active = true;
m_log.Warn(LogHeader + " Initialised");
}
//Called after Initialise()
public void AddRegion(Scene scene)
{
if (!m_active)
return;
//connect with scene
m_scene = scene;
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
// Setup the command line interface
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
//InstallInterfaces();
//Register for the OnPostSceneCreation event
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
//Register for Scene/SceneGraph events
m_scene.EventManager.OnSymmetricSyncStop += ClientManager_OnSymmetricSyncStop;
}
//Called after AddRegion() has been called for all region modules of the scene.
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
public void RegionLoaded(Scene scene)
{
if (!m_active)
return;
}
public void RemoveRegion(Scene scene)
{
}
public Type ReplaceableInterface
{
get { return null; }
}
public void Close()
{
m_scene = null;
}
public string Name
{
get { return "ClientManagerSyncModule"; }
}
#endregion //INonSharedRegionModule
#region IDSGActorSyncModule members and functions
private DSGActorTypes m_actorType = DSGActorTypes.ClientManager;
public DSGActorTypes ActorType
{
get { return m_actorType; }
}
private string m_actorID;
public string ActorID
{
get { return m_actorID; }
}
#endregion //IDSGActorSyncModule
#region ClientManagerSyncModule memebers and functions
private ILog m_log;
private bool m_active = false;
public bool Active
{
get { return m_active; }
}
private Scene m_scene;
private string LogHeader = "[ClientManagerSyncModule]";
/// <summary>
/// Client Manager's action upon an object is added to the local scene
/// </summary>
private void ClientManager_OnObjectCreateBySync(EntityBase entity)
{
}
public void ClientManager_OnSymmetricSyncStop()
{
//remove all objects
//m_scene.DeleteAllSceneObjects();
}
#endregion //ScriptEngineSyncModule
}
}

View File

@ -0,0 +1,384 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Net;
using System.Reflection;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using OpenSim.Framework;
using OpenMetaverse;
using log4net;
using Nini.Config;
using Nwc.XmlRpc;
using Mono.Addins;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
//DSG added to support llDialog with distributed script engine and client manager,
//following the same communication pattern as grid_instant_message
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridDialogModule")]
public class GridDialogModule : ISharedRegionModule, IGridDialogModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
//private bool m_Enabled = false;
protected List<Scene> m_Scenes = new List<Scene>();
private IPresenceService m_PresenceService;
protected IPresenceService PresenceService
{
get
{
if (m_PresenceService == null)
m_PresenceService = m_Scenes[0].RequestModuleInterface<IPresenceService>();
return m_PresenceService;
}
}
#region ISharedRegionModule
public virtual void Initialise(IConfigSource config)
{
//m_log.Debug("[GRID DIALOG MODULE]: Initialise");
}
public virtual void AddRegion(Scene scene)
{
lock (m_Scenes)
{
m_log.Debug("[GRID DIALOG MODULE]: Grid Dialog Module active");
scene.RegisterModuleInterface<IGridDialogModule>(this);
m_Scenes.Add(scene);
}
}
public virtual void PostInitialise()
{
//if (!m_Enabled)
// return;
MainServer.Instance.AddXmlRPCHandler(
"grid_dialog", processXMLRPCGridDialog);
}
public virtual void RegionLoaded(Scene scene)
{
}
public virtual void RemoveRegion(Scene scene)
{
//if (!m_Enabled)
// return;
lock (m_Scenes)
{
m_Scenes.Remove(scene);
}
}
public virtual void Close()
{
}
public virtual string Name
{
get { return "GridDialogModule"; }
}
public virtual Type ReplaceableInterface
{
get { return null; }
}
#endregion //ISharedRegionModule
#region GridCommunication
public delegate void GridDialogDelegate(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName,
string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID);
protected virtual void GridDialogCompleted(IAsyncResult iar)
{
GridDialogDelegate icon =
(GridDialogDelegate)iar.AsyncState;
icon.EndInvoke(iar);
}
public void SendGridDialogViaXMLRPC(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName,
string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID)
{
GridDialogDelegate d = SendGridDialogViaXMLRPCAsync;
d.BeginInvoke(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels, prevRegionID,
GridDialogCompleted, d);
}
private void SendGridDialogViaXMLRPCAsync(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName,
string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID)
{
PresenceInfo upd = null;
// Non-cached user agent lookup.
PresenceInfo[] presences = PresenceService.GetAgents(new string[] { avatarID.ToString() });
if (presences != null && presences.Length > 0)
{
foreach (PresenceInfo p in presences)
{
if (p.RegionID != UUID.Zero)
{
upd = p;
break;
}
}
if (upd != null)
{
// check if we've tried this before..
// This is one way to end the recursive loop
//
if (upd.RegionID == prevRegionID)
{
//Dialog content undelivered
m_log.WarnFormat("Couldn't deliver dialog to {0}" + avatarID);
return;
}
}
else
{
//Dialog content undelivered
m_log.WarnFormat("Couldn't deliver dialog to {0}" + avatarID);
return;
}
}
if (upd != null)
{
GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID,
upd.RegionID);
if (reginfo != null)
{
Hashtable msgdata = ConvertGridDialogToXMLRPC(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels);
//= ConvertGridInstantMessageToXMLRPC(im);
// Not actually used anymore, left in for compatibility
// Remove at next interface change
//
msgdata["region_handle"] = 0;
bool imresult = doDialogSending(reginfo, msgdata);
if (!imresult)
{
SendGridDialogViaXMLRPCAsync(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels, prevRegionID);
m_log.WarnFormat("Couldn't deliver dialog to {0}" + avatarID);
return;
}
}
}
}
private Hashtable ConvertGridDialogToXMLRPC(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName,
string message, UUID textureID, int ch, string[] buttonlabels)
{
Hashtable msgdata = new Hashtable();
msgdata["avatarID"] = avatarID.ToString();
msgdata["objectName"] = objectName;
msgdata["objectID"] = objectID.ToString();
msgdata["ownerID"] = ownerID.ToString();
msgdata["ownerFirstName"] = ownerFirstName;
msgdata["ownerLastName"] = ownerLastName;
msgdata["message"] = message;
msgdata["textureID"] = textureID.ToString();
msgdata["ch"] = ch.ToString();
msgdata["buttonlabelsNum"] = buttonlabels.Length.ToString();
for (int i = 0; i < buttonlabels.Length; i++)
{
string key = "buttonlabel_" + i;
msgdata[key] = buttonlabels[i];
}
return msgdata;
}
/// <summary>
/// This actually does the XMLRPC Request
/// </summary>
/// <param name="reginfo">RegionInfo we pull the data out of to send the request to</param>
/// <param name="xmlrpcdata">The Instant Message data Hashtable</param>
/// <returns>Bool if the message was successfully delivered at the other side.</returns>
protected virtual bool doDialogSending(GridRegion reginfo, Hashtable xmlrpcdata)
{
ArrayList SendParams = new ArrayList();
SendParams.Add(xmlrpcdata);
XmlRpcRequest GridReq = new XmlRpcRequest("grid_dialog", SendParams);
try
{
XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, 3000);
Hashtable responseData = (Hashtable)GridResp.Value;
if (responseData.ContainsKey("success"))
{
if ((string)responseData["success"] == "TRUE")
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
catch (WebException e)
{
m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending grid_dialog to {0} the host didn't respond " + e.ToString(), reginfo.ServerURI.ToString());
}
return false;
}
/// <summary>
/// Process a XMLRPC Grid Instant Message
/// </summary>
/// <param name="request">XMLRPC parameters
/// </param>
/// <returns>Nothing much</returns>
protected virtual XmlRpcResponse processXMLRPCGridDialog(XmlRpcRequest request, IPEndPoint remoteClient)
{
bool decodingSuccessful = true;
bool deliverSuccessful = false;
UUID avatarID = UUID.Zero;
UUID objectID = UUID.Zero;
UUID textureID = UUID.Zero;
UUID ownerID = UUID.Zero;
string objectName="", ownerFirstName="", ownerLastName="";
string message="";
int ch=0;
string[] buttonlabels = null;
Hashtable requestData = (Hashtable)request.Params[0];
// Check if it's got all the data
if (requestData.ContainsKey("avatarID")
&& requestData.ContainsKey("objectName") && requestData.ContainsKey("objectID")
&& requestData.ContainsKey("ownerID")
&& requestData.ContainsKey("ownerFirstName") && requestData.ContainsKey("ownerLastName")
&& requestData.ContainsKey("message") && requestData.ContainsKey("textureID")
&& requestData.ContainsKey("ch")
&& requestData.ContainsKey("buttonlabelsNum"))
{
try
{
// Do the easy way of validating the UUIDs
UUID.TryParse((string)requestData["avatarID"], out avatarID);
UUID.TryParse((string)requestData["objectID"], out objectID);
UUID.TryParse((string)requestData["textureID"], out textureID);
UUID.TryParse((string)requestData["ownerID"], out ownerID);
objectName = (string)requestData["objectName"];
ownerFirstName = (string)requestData["ownerFirstName"];
ownerLastName = (string)requestData["ownerLastName"];
ch = Convert.ToInt32((string)requestData["ch"]);
int buttonlabelsNum = Convert.ToInt32((string)requestData["buttonlabelsNum"]);
buttonlabels = new string[buttonlabelsNum];
for (int i = 0; i < buttonlabelsNum; i++)
{
string key = "buttonlabel_" + i;
if (requestData.ContainsKey(key))
{
buttonlabels[i] = (string)requestData[key];
}
else
{
decodingSuccessful = false;
break;
}
}
}
catch (Exception e)
{
m_log.ErrorFormat("Error in processXMLRPCGridDialog: {0}", e.Message);
deliverSuccessful = false;
}
if (decodingSuccessful)
{
//Deliver the dialog to the client
foreach (Scene scene in m_Scenes)
{
if (scene.Entities.ContainsKey(avatarID) &&
scene.Entities[avatarID] is ScenePresence)
{
ScenePresence user =
(ScenePresence)scene.Entities[avatarID];
if (!user.IsChildAgent)
{
user.ControllingClient.SendDialog(objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels);
deliverSuccessful = true;
}
}
}
}
}
//Send response back to region calling if it was successful
// calling region uses this to know when to look up a user's location again.
XmlRpcResponse resp = new XmlRpcResponse();
Hashtable respdata = new Hashtable();
if (deliverSuccessful)
respdata["success"] = "TRUE";
else
respdata["success"] = "FALSE";
resp.Value = respdata;
return resp;
}
#endregion //GridCommunication
}
}

View File

@ -0,0 +1,198 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Mono.Addins;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsEngineSyncModule")]
public class PhysicsEngineSyncModule : INonSharedRegionModule, IDSGActorSyncModule
{
#region INonSharedRegionModule
public void Initialise(IConfigSource config)
{
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
IConfig syncConfig = config.Configs["RegionSyncModule"];
m_active = false;
if (syncConfig == null)
{
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
return;
}
else if (!syncConfig.GetBoolean("Enabled", false))
{
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
return;
}
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
//Read in configuration, if the local actor is configured to be a client manager, load this module.
if (!actorType.Equals("physics_engine"))
{
m_log.Warn(LogHeader + ": not configured as Physics Engine Actor. Shut down.");
return;
}
m_actorID = syncConfig.GetString("ActorID", "");
if (m_actorID.Equals(""))
{
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
return;
}
m_active = true;
m_log.Warn(LogHeader + " Initialised");
}
//Called after Initialise()
public void AddRegion(Scene scene)
{
if (!m_active)
return;
//connect with scene
m_scene = scene;
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
// register actor
if (!scene.GridService.RegisterActor(scene.RegionInfo.RegionID.ToString(),
"physics_engine", scene.RegionInfo.RegionID.ToString()))
{
m_log.ErrorFormat("{0}: Failure registering actor", LogHeader);
}
// Setup the command line interface
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
//InstallInterfaces();
//Register for the OnPostSceneCreation event
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
//Register for Scene/SceneGraph events
m_scene.EventManager.OnSymmetricSyncStop += PhysicsEngine_OnSymmetricSyncStop;
}
//Called after AddRegion() has been called for all region modules of the scene.
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
public void RegionLoaded(Scene scene)
{
if (!m_active)
return;
}
public void RemoveRegion(Scene scene)
{
}
public Type ReplaceableInterface
{
get { return null; }
}
public void Close()
{
m_scene = null;
}
public string Name
{
get { return "PhysicsEngineSyncModule"; }
}
#endregion //INonSharedRegionModule
#region IDSGActorSyncModule members and functions
private DSGActorTypes m_actorType = DSGActorTypes.PhysicsEngine;
public DSGActorTypes ActorType
{
get { return m_actorType; }
}
private string m_actorID;
public string ActorID
{
get { return m_actorID; }
}
#endregion //IDSGActorSyncModule
#region PhysicsEngineSyncModule members and functions
private ILog m_log;
private bool m_active = false;
public bool Active
{
get { return m_active; }
}
private Scene m_scene;
private string LogHeader = "[PhysicsEngineSyncModule]";
/// <summary>
/// Physics Engine's action upon an object is added to the local scene
/// </summary>
private void PhysicsEngine_OnObjectCreateBySync(EntityBase entity)
{
if (entity is SceneObjectGroup)
{
}
}
public void PhysicsEngine_OnSymmetricSyncStop()
{
//remove all objects
m_scene.DeleteAllSceneObjects();
}
#endregion PhysicsEngineSyncModule members and functions
}
}

View File

@ -0,0 +1,226 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Mono.Addins;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScenePersistenceSyncModule")]
public class ScenePersistenceSyncModule : INonSharedRegionModule, IDSGActorSyncModule
{
#region INonSharedRegionModule
public void Initialise(IConfigSource config)
{
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
IConfig syncConfig = config.Configs["RegionSyncModule"];
m_active = false;
if (syncConfig == null)
{
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
return;
}
else if (!syncConfig.GetBoolean("Enabled", false))
{
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
return;
}
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
if (!actorType.Equals("scene_persistence"))
{
m_log.Warn(LogHeader + ": not configured as Scene Persistence Actor. Shutting down.");
return;
}
m_actorID = syncConfig.GetString("ActorID", "");
if (m_actorID.Equals(""))
{
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
return;
}
m_active = true;
m_log.Warn(LogHeader+" Initialised");
}
//Called after Initialise()
public void AddRegion(Scene scene)
{
if (!m_active)
return;
m_log.Warn(LogHeader + " AddRegion() called");
//connect with scene
m_scene = scene;
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
// register actor
if (!scene.GridService.RegisterActor(scene.RegionInfo.RegionID.ToString(),
"scene_persistence", scene.RegionInfo.RegionID.ToString()))
{
m_log.ErrorFormat("{0}: Failure registering actor", LogHeader);
}
// Setup the command line interface
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
//InstallInterfaces();
//Register for the OnPostSceneCreation event
m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
//Register for Scene/SceneGraph events
m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScenePersistence_OnObjectCreate);
//m_scene.SceneGraph.OnObjectCreateBySync += new ObjectCreateBySyncDelegate(ScenePersistence_OnObjectCreateBySync);
}
//Called after AddRegion() has been called for all region modules of the scene.
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
// So to try to access other region modules in RegionLoaded, e.g. RegionSyncModule, is not a good idea.
public void RegionLoaded(Scene scene)
{
if (!m_active)
return;
m_log.Warn(LogHeader + " RegionLoaded() called");
}
public void RemoveRegion(Scene scene)
{
}
public Type ReplaceableInterface
{
get { return null; }
}
public void Close()
{
m_scene = null;
}
public string Name
{
get { return "ScenePersistenceSyncModule"; }
}
#endregion //INonSharedRegionModule
#region IDSGActorSyncModule members and functions
private DSGActorTypes m_actorType = DSGActorTypes.ScenePersistence;
public DSGActorTypes ActorType
{
get { return m_actorType; }
}
private string m_actorID;
public string ActorID
{
get { return m_actorID; }
}
#endregion //IDSGActorSyncModule
#region ScenePersistenceSyncModule memebers and functions
private ILog m_log;
private bool m_active = false;
public bool Active
{
get { return m_active; }
}
private Scene m_scene;
private string LogHeader = "[ScenePersistenceSyncModule]";
public void OnPostSceneCreation(Scene createdScene)
{
//If this is the local scene the actor is working on, do something
if (createdScene == m_scene)
{
m_scene.RequestModuleInterface<ITerrainModule>().SetSyncInfo(DateTime.Now.Ticks, m_scene.GetSyncActorID());
}
}
/// <summary>
/// ScenePersistence's actions upon an object is added to the local scene.
/// </summary>
private void ScenePersistence_OnObjectCreate(EntityBase entity)
{
if (entity is SceneObjectGroup)
{
//m_log.Warn(LogHeader + ":OnObjectCreate -- link to backup for " + entity.UUID);
SceneObjectGroup sog = (SceneObjectGroup)entity;
//probably what we should do here is to set some variable sog.SyncToBackup to true, and sog.ProcessBackup will only run if that value is true,
//then we do not need to worry about where an object is attach-to-backup and modify all those lines.
sog.ToPersistObjectState = true;
sog.AttachToBackup();
}
}
/// <summary>
/// ScenePersistence's actions upon an object is added to the local scene.
/// </summary>
private void ScenePersistence_OnObjectCreateBySync(EntityBase entity)
{
if (entity is SceneObjectGroup)
{
//m_log.Warn(LogHeader + ":OnObjectCreateBySync -- link to backup for " + entity.UUID);
SceneObjectGroup sog = (SceneObjectGroup)entity;
//probably what we should do here is to set some variable sog.SyncToBackup to true, and sog.ProcessBackup will only run if that value is true,
//then we do not need to worry about where an object is attach-to-backup and modify all those lines.
sog.ToPersistObjectState = true;
sog.AttachToBackup();
}
}
#endregion //ScenePersistenceSyncModule
}
}

View File

@ -0,0 +1,263 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Mono.Addins;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")]
public class ScriptEngineSyncModule : INonSharedRegionModule, IDSGActorSyncModule
{
#region INonSharedRegionModule
public void Initialise(IConfigSource config)
{
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
IConfig syncConfig = config.Configs["RegionSyncModule"];
m_active = false;
if (syncConfig == null)
{
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
return;
}
else if (!syncConfig.GetBoolean("Enabled", false))
{
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
return;
}
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
if (!actorType.Equals("script_engine"))
{
m_log.Warn(LogHeader + ": not configured as Scene Persistence Actor. Shut down.");
return;
}
m_actorID = syncConfig.GetString("ActorID", "");
if (m_actorID.Equals(""))
{
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
return;
}
m_active = true;
LogHeader += "-" + m_actorID;
m_log.Warn(LogHeader + " Initialised");
}
//Called after Initialise()
public void AddRegion(Scene scene)
{
if (!m_active)
return;
m_log.Warn(LogHeader + " AddRegion() called");
//connect with scene
m_scene = scene;
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
// Setup the command line interface
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
//InstallInterfaces();
//Register for the OnPostSceneCreation event
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
//Register for Scene/SceneGraph events
//m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScriptEngine_OnObjectCreate);
//Don't subscribe to OnObjectCreate, only subscribe OnObjectCreateBySync.
m_scene.SceneGraph.OnObjectCreateBySync += new ObjectCreateBySyncDelegate(ScriptEngine_OnObjectCreateBySync);
m_scene.EventManager.OnSymmetricSyncStop += ScriptEngine_OnSymmetricSyncStop;
//for local OnUpdateScript, we'll handle it the same way as a remove OnUpdateScript.
//RegionSyncModule will capture a locally initiated OnUpdateScript event and publish it to other actors.
m_scene.EventManager.OnNewScript += ScriptEngine_OnNewScript;
m_scene.EventManager.OnUpdateScript += ScriptEngine_OnUpdateScript;
m_scene.EventManager.OnAggregateScriptEvents += ScriptEngine_OnAggregateScriptEvents;
LogHeader += "-" + m_actorID + "-" + m_scene.RegionInfo.RegionName;
}
//Called after AddRegion() has been called for all region modules of the scene.
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
public void RegionLoaded(Scene scene)
{
if (!m_active)
return;
}
public void RemoveRegion(Scene scene)
{
}
public Type ReplaceableInterface
{
get { return null; }
}
public void Close()
{
m_scene = null;
}
public string Name
{
get { return "ScriptEngineSyncModule"; }
}
#endregion //INonSharedRegionModule
#region IDSGActorSyncModule members and functions
public static string ActorTypeString = DSGActorTypes.ScriptEngine.ToString();
private DSGActorTypes m_actorType = DSGActorTypes.ScriptEngine;
public DSGActorTypes ActorType
{
get { return m_actorType; }
}
private string m_actorID;
public string ActorID
{
get { return m_actorID; }
}
#endregion //IDSGActorSyncModule
#region ScriptEngineSyncModule memebers and functions
private ILog m_log;
private bool m_active = false;
public bool Active
{
get { return m_active; }
}
private Scene m_scene;
private string LogHeader = "[ScriptEngineSyncModule]";
public void OnPostSceneCreation(Scene createdScene)
{
//If this is the local scene the actor is working on, do something
if (createdScene == m_scene)
{
}
}
/// <summary>
/// Script Engine's action upon an object is added to the local scene
/// </summary>
private void ScriptEngine_OnObjectCreateBySync(EntityBase entity)
{
if (entity is SceneObjectGroup)
{
//m_log.DebugFormat("{0}: start script for obj {1}", LogHeader, entity.UUID);
SceneObjectGroup sog = (SceneObjectGroup)entity;
sog.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0);
sog.ResumeScripts();
}
}
public void ScriptEngine_OnSymmetricSyncStop()
{
//Inform script engine to save script states and stop scripts
m_scene.EventManager.TriggerScriptEngineSyncStop();
//remove all objects
m_scene.DeleteAllSceneObjectsBySync();
}
public void ScriptEngine_OnNewScript(UUID agentID, SceneObjectPart part, UUID itemID)
{
m_log.Debug(LogHeader + " ScriptEngine_OnUpdateScript");
ArrayList errors = m_scene.SymSync_OnNewScript(agentID, itemID, part);
//The errors should be sent back to the client's viewer who submitted
//the new script. But for now, let just display it in concole and
//log it.
LogScriptErrors(errors);
}
//Assumption, when this function is triggered, the new script asset has already been saved.
public void ScriptEngine_OnUpdateScript(UUID agentID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
{
m_log.Debug(LogHeader + " ScriptEngine_OnUpdateScript");
ArrayList errors = m_scene.SymSync_OnUpdateScript(agentID, itemID, primID, isScriptRunning, newAssetID);
//The errors should be sent back to the client's viewer who submitted
//the script update. But for now, let just display it in concole and
//log it.
LogScriptErrors(errors);
}
private void LogScriptErrors(ArrayList errors)
{
string errorString = "";
foreach (Object err in errors)
{
errorString += err + "\n";
}
if (errorString != String.Empty)
{
m_log.ErrorFormat("Error in script: {0}", errorString);
}
}
public void ScriptEngine_OnAggregateScriptEvents(SceneObjectPart part)
{
part.aggregateScriptEvents();
}
#endregion //ScriptEngineSyncModule
}
}

View File

@ -0,0 +1,198 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using OpenMetaverse;
using log4net;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
//Initial code in SymmetricSyncMessage copied from RegionSyncMessage.
/// <summary>
/// Types of symmetric sync messages among actors.
/// NOTE:: To enable message subscription, we may need to move the definition of MsgType to, say IRegionSyncModule, so that it can be exposed to other region modules.
/// </summary>
public class SymmetricSyncMessage
{
#region MsgType Enum
public enum MsgType
{
Null,
// Actor -> SIM(Scene)
GetTerrain,
GetObjects,
// SIM <-> CM
Terrain,
NewObject, // objects
UpdatedPrimProperties, //per property sync
//UpdatedObject, // objects
UpdatedBucketProperties, //object properties in one bucket
RemovedObject, // objects
LinkObject,
DelinkObject,
RegionName,
//RegionStatus,
ActorID,
ActorType,
//events
NewScript,
UpdateScript,
ScriptReset,
ChatFromClient,
ChatFromWorld,
ChatBroadcast,
ObjectGrab,
ObjectGrabbing,
ObjectDeGrab,
Attach,
PhysicsCollision,
ScriptCollidingStart,
ScriptColliding,
ScriptCollidingEnd,
ScriptLandCollidingStart,
ScriptLandColliding,
ScriptLandCollidingEnd,
//contorl command
SyncStateReport,
}
#endregion
#region Member Data
private MsgType m_type;
private byte[] m_data;
static ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#endregion
#region Constructors
public SymmetricSyncMessage(MsgType type, byte[] data)
{
m_type = type;
m_data = data;
}
public SymmetricSyncMessage(MsgType type, string msg)
{
m_type = type;
m_data = System.Text.Encoding.ASCII.GetBytes(msg);
}
public SymmetricSyncMessage(MsgType type)
{
m_type = type;
m_data = new byte[0];
}
public SymmetricSyncMessage(Stream stream)
{
//ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//try
{
m_type = (MsgType)Utils.BytesToInt(GetBytesFromStream(stream, 4));
int length = Utils.BytesToInt(GetBytesFromStream(stream, 4));
m_data = GetBytesFromStream(stream, length);
//log.WarnFormat("RegionSyncMessage Constructed {0} ({1} bytes)", m_type.ToString(), length);
}
}
private byte[] GetBytesFromStream(Stream stream, int count)
{
// Loop to receive the message length
byte[] ret = new byte[count];
int i = 0;
while (i < count)
{
i += stream.Read(ret, i, count - i);
}
return ret;
}
#endregion
#region Accessors
public MsgType Type
{
get { return m_type; }
}
public int Length
{
get { return m_data.Length; }
}
public byte[] Data
{
get { return m_data; }
}
#endregion
#region Conversions
public byte[] ToBytes()
{
byte[] buf = new byte[m_data.Length + 8];
Utils.IntToBytes((int)m_type, buf, 0);
Utils.IntToBytes(m_data.Length, buf, 4);
Array.Copy(m_data, 0, buf, 8, m_data.Length);
return buf;
}
public override string ToString()
{
return String.Format("{0} ({1} bytes)", m_type.ToString(), m_data.Length.ToString());
}
#endregion
public static void HandleSuccess(string header, SymmetricSyncMessage msg, string message)
{
m_log.WarnFormat("{0} Handled {1}: {2}", header, msg.ToString(), message);
}
public static void HandleTrivial(string header, SymmetricSyncMessage msg, string message)
{
m_log.WarnFormat("{0} Issue handling {1}: {2}", header, msg.ToString(), message);
}
public static void HandleWarning(string header, SymmetricSyncMessage msg, string message)
{
m_log.WarnFormat("{0} Warning handling {1}: {2}", header, msg.ToString(), message);
}
public static void HandleError(string header, SymmetricSyncMessage msg, string message)
{
m_log.WarnFormat("{0} Error handling {1}: {2}", header, msg.ToString(), message);
}
public static bool HandlerDebug(string header, SymmetricSyncMessage msg, string message)
{
m_log.WarnFormat("{0} DBG ({1}): {2}", header, msg.ToString(), message);
return true;
}
}
}

View File

@ -0,0 +1,383 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using log4net;
using OpenMetaverse;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
public enum SyncConnectorState
{
Idle, //not connected
Initialization, //initializing local copy of Scene
Syncing, //done initialization, in normal process of syncing terrain, objects, etc
}
// For implementations, a lot was copied from RegionSyncClientView, especially the SendLoop/ReceiveLoop.
public class SyncConnector : ISyncStatistics
{
private TcpClient m_tcpConnection = null;
private RegionSyncListenerInfo m_remoteListenerInfo = null;
private Thread m_rcvLoop;
private Thread m_send_loop;
private string LogHeader = "[SYNC CONNECTOR]";
// The logfile
private ILog m_log;
//members for in/out messages queueing
object stats = new object();
private long queuedUpdates=0;
private long dequeuedUpdates=0;
private long msgsIn=0;
private long msgsOut=0;
private long bytesIn=0;
private long bytesOut=0;
private DateTime lastStatTime;
// A queue for outgoing traffic.
private BlockingUpdateQueue m_outQ = new BlockingUpdateQueue();
private RegionSyncModule m_regionSyncModule = null;
//members for keeping track of state of this connector
private SyncConnectorState m_syncState = SyncConnectorState.Idle;
// unique connector number across all regions
private static int m_connectorNum = 0;
public int ConnectorNum
{
get { return m_connectorNum; }
}
//the actorID of the other end of the connection
private string m_syncOtherSideActorID;
public string OtherSideActorID
{
get { return m_syncOtherSideActorID; }
//set { m_syncOtherSideActorID = value; }
}
//The region name of the other side of the connection
private string m_syncOtherSideRegionName="";
public string OtherSideRegionName
{
get { return m_syncOtherSideRegionName; }
}
private string m_syncOtherSideActorType;
public string OtherSideActorType
{
get { return m_syncOtherSideActorType; }
//set { m_syncOtherSideActorID = value; }
}
// Check if the client is connected
public bool Connected
{ get { return (m_tcpConnection !=null && m_tcpConnection.Connected); } }
public string Description
{
get
{
if (m_syncOtherSideRegionName == null)
return String.Format("SyncConnector{0}", m_connectorNum);
return String.Format("SyncConnector{0}({2}/{1:10})",
m_connectorNum, m_syncOtherSideRegionName, m_syncOtherSideActorID);
}
}
/// <summary>
/// The constructor that will be called when a SyncConnector is created passively: a remote SyncConnector has initiated the connection.
/// </summary>
/// <param name="connectorNum"></param>
/// <param name="tcpclient"></param>
public SyncConnector(int connectorNum, TcpClient tcpclient, RegionSyncModule syncModule)
{
m_tcpConnection = tcpclient;
m_connectorNum = connectorNum;
m_regionSyncModule = syncModule;
lastStatTime = DateTime.Now;
SyncStatisticCollector.Register(this);
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
/// <summary>
/// The constructor that will be called when a SyncConnector is created actively: it is created to send connection request to a remote listener
/// </summary>
/// <param name="connectorNum"></param>
/// <param name="listenerInfo"></param>
public SyncConnector(int connectorNum, RegionSyncListenerInfo listenerInfo, RegionSyncModule syncModule)
{
m_remoteListenerInfo = listenerInfo;
m_connectorNum = connectorNum;
m_regionSyncModule = syncModule;
lastStatTime = DateTime.Now;
SyncStatisticCollector.Register(this);
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
//Connect to the remote listener
public bool Connect()
{
m_tcpConnection = new TcpClient();
try
{
m_tcpConnection.Connect(m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port);
}
catch (Exception e)
{
m_log.WarnFormat("{0} [Start] Could not connect to RegionSyncModule at {1}:{2}", LogHeader, m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port);
m_log.Warn(e.Message);
return false;
}
return true;
}
/// <summary>
/// Start both the send and receive threads
/// </summary>
public void StartCommThreads()
{
// Create a thread for the receive loop
m_rcvLoop = new Thread(new ThreadStart(ReceiveLoop));
m_rcvLoop.Name = Description + " (ReceiveLoop)";
m_log.WarnFormat("{0} Starting {1} thread", Description, m_rcvLoop.Name);
m_rcvLoop.Start();
// Create a thread for the send loop
m_send_loop = new Thread(new ThreadStart(delegate() { SendLoop(); }));
m_send_loop.Name = Description + " (SendLoop)";
m_log.WarnFormat("{0} Starting {1} thread", Description, m_send_loop.Name);
m_send_loop.Start();
}
public void Shutdown()
{
m_log.Warn(LogHeader + " shutdown connection");
// Abort receive and send loop
m_rcvLoop.Abort();
m_send_loop.Abort();
// Close the connection
m_tcpConnection.Client.Close();
m_tcpConnection.Close();
}
///////////////////////////////////////////////////////////
// Sending messages out to the other side of the connection
///////////////////////////////////////////////////////////
// Send messages from the update Q as fast as we can DeQueue them
// *** This is the main send loop thread for each connected client
private void SendLoop()
{
try
{
while (true)
{
// Dequeue is thread safe
byte[] update = m_outQ.Dequeue();
lock (stats)
dequeuedUpdates++;
Send(update);
}
}
catch (Exception e)
{
m_log.ErrorFormat("{0} has disconnected: {1} (SendLoop)", Description, e.Message);
}
Shutdown();
}
/// <summary>
/// Enqueue update of an object/avatar into the outgoing queue, and return right away
/// </summary>
/// <param name="id">UUID of the object/avatar</param>
/// <param name="update">the update infomation in byte format</param>
public void EnqueueOutgoingUpdate(UUID id, byte[] update)
{
lock (stats)
queuedUpdates++;
// Enqueue is thread safe
m_outQ.Enqueue(id, update);
}
//Send out a messge directly. This should only by called for short messages that are not sent frequently.
//Don't call this function for sending out updates. Call EnqueueOutgoingUpdate instead
public void Send(SymmetricSyncMessage msg)
{
Send(msg.ToBytes());
}
private void Send(byte[] data)
{
if (m_tcpConnection.Connected)
{
try
{
lock (stats)
{
msgsOut++;
bytesOut += data.Length;
}
m_tcpConnection.GetStream().BeginWrite(data, 0, data.Length, ar =>
{
if (m_tcpConnection.Connected)
{
try
{
m_tcpConnection.GetStream().EndWrite(ar);
}
catch (Exception)
{ }
}
}, null);
}
catch (Exception e)
{
m_log.WarnFormat("{0}:Error in Send() {1} has disconnected -- error message: {2}.", Description, m_connectorNum, e.Message);
}
}
}
///////////////////////////////////////////////////////////
// Receiving messages from the other side ofthe connection
///////////////////////////////////////////////////////////
private void ReceiveLoop()
{
m_log.WarnFormat("{0} Thread running: {1}", LogHeader, m_rcvLoop.Name);
while (true && m_tcpConnection.Connected)
{
SymmetricSyncMessage msg;
// Try to get the message from the network stream
try
{
msg = new SymmetricSyncMessage(m_tcpConnection.GetStream());
//m_log.WarnFormat("{0} Received: {1}", LogHeader, msg.ToString());
}
// If there is a problem reading from the client, shut 'er down.
catch (Exception e)
{
//ShutdownClient();
m_log.WarnFormat("{0}: ReceiveLoop error {1} has disconnected -- error message {2}.", Description, m_connectorNum, e.Message);
Shutdown();
return;
}
// Try handling the message
try
{
HandleMessage(msg);
}
catch (Exception e)
{
m_log.WarnFormat("{0} Encountered an exception: {1} (MSGTYPE = {2})", Description, e.Message, msg.ToString());
}
}
}
private void HandleMessage(SymmetricSyncMessage msg)
{
msgsIn++;
bytesIn += msg.Data.Length;
switch (msg.Type)
{
case SymmetricSyncMessage.MsgType.RegionName:
{
m_syncOtherSideRegionName = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
if (m_regionSyncModule.IsSyncRelay)
{
SymmetricSyncMessage outMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.RegionName, m_regionSyncModule.LocalScene.RegionInfo.RegionName);
Send(outMsg);
}
m_log.DebugFormat("Syncing to region \"{0}\"", m_syncOtherSideRegionName);
return;
}
case SymmetricSyncMessage.MsgType.ActorID:
{
m_syncOtherSideActorID = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
if (m_regionSyncModule.IsSyncRelay)
{
SymmetricSyncMessage outMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.ActorID, m_regionSyncModule.ActorID);
Send(outMsg);
}
m_log.DebugFormat("Syncing to actor \"{0}\"", m_syncOtherSideActorID);
return;
}
case SymmetricSyncMessage.MsgType.ActorType:
{
m_syncOtherSideActorType = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
if (m_regionSyncModule.IsSyncRelay)
{
SymmetricSyncMessage outMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.ActorType, m_regionSyncModule.LocalScene.RegionSyncActorType );
Send(outMsg);
}
m_log.DebugFormat("Syncing to actor type \"{0}\"", m_syncOtherSideActorType);
return;
}
default:
break;
}
//For any other messages, we simply deliver the message to RegionSyncModule for now.
//Later on, we may deliver messages to different modules, say sync message to RegionSyncModule and event message to ActorSyncModule.
m_regionSyncModule.HandleIncomingMessage(msg, m_syncOtherSideActorID, this);
}
public string StatisticIdentifier()
{
return this.Description;
}
public string StatisticLine(bool clearFlag)
{
string statLine = "";
lock (stats)
{
double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds;
lastStatTime = DateTime.Now;
statLine = String.Format("{0},{1},{2},{3},{4},{5},{6}",
msgsIn, msgsOut, bytesIn, bytesOut, m_outQ.Count,
8 * (bytesIn / secondsSinceLastStats / 1000000),
8 * (bytesOut / secondsSinceLastStats / 1000000) );
if (clearFlag)
msgsIn = msgsOut = bytesIn = bytesOut = 0;
}
return statLine;
}
public string StatisticTitle()
{
return "msgsIn,msgsOut,bytesIn,bytesOut,queueSize,Mbps In,Mbps Out";
}
}
}

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Timers;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
public interface ISyncStatistics
{
// return an identifier for this statistics source
string StatisticIdentifier();
// a line of comma separated values
string StatisticLine(bool clearFlag);
// a line of comma separated field descriptions (describes what StatisticLine returns)
string StatisticTitle();
}
public class SyncStatisticCollector
{
public static bool LogEnabled = false;
public static string LogDirectory = ".";
public static int LogInterval = 5000;
public static int LogMaxFileTimeMin = 5; // 5 minutes
public static string LogFileHeader = "stats-";
private static List<ISyncStatistics> s_staters = new List<ISyncStatistics>();
private static object s_statersLock = new object();
private static Timer s_timer = null;
static SyncStatisticCollector()
{
}
public SyncStatisticCollector()
{
}
/// <summary>
/// Any implementor of ISyncStatistics will call Register to put themselves in
/// the list of routines to collect statistics from. This will run periodically
/// and suck statistics from the registered routines.
/// </summary>
/// <param name="stat"></param>
public static void Register(ISyncStatistics stat)
{
if (!LogEnabled) return;
lock (SyncStatisticCollector.s_statersLock)
{
// set up logging timer
if (SyncStatisticCollector.s_timer == null)
{
SyncStatisticCollector.s_timer = new Timer();
SyncStatisticCollector.s_timer.Interval = LogInterval;
SyncStatisticCollector.s_timer.Enabled = true;
SyncStatisticCollector.s_timer.Elapsed += Tick;
}
SyncStatisticCollector.s_staters.Add(stat);
}
return;
}
public static void Close()
{
lock (SyncStatisticCollector.s_statersLock)
{
SyncStatisticCollector.LogEnabled = false;
if (SyncStatisticCollector.s_timer != null)
{
SyncStatisticCollector.s_timer.Enabled = false;
SyncStatisticCollector.s_timer.Dispose();
SyncStatisticCollector.s_timer = null;
}
if (SyncStatisticCollector.LogFile != null)
{
SyncStatisticCollector.LogFile.Close();
SyncStatisticCollector.LogFile.Dispose();
SyncStatisticCollector.LogFile = null;
}
}
}
private static void Tick(object sender, EventArgs e)
{
if (!LogEnabled) return;
lock (SyncStatisticCollector.s_statersLock)
{
foreach (ISyncStatistics iss in s_staters)
{
LogWriter(iss.StatisticIdentifier() + "," + iss.StatisticLine(true));
}
}
return;
}
private static DateTime LogStartTime;
private static System.IO.TextWriter LogFile = null;
private static void LogWriter(string line)
{
try
{
DateTime now = DateTime.Now;
if (LogFile == null || (now > (LogStartTime + new TimeSpan(0, LogMaxFileTimeMin, 0))))
{
if (LogFile != null)
{
LogFile.Close();
LogFile.Dispose();
LogFile = null;
}
// First log file or time has expired, start writing to a new log file
LogStartTime = now;
string path = (LogDirectory.Length > 0 ? LogDirectory
+ System.IO.Path.DirectorySeparatorChar.ToString() : "")
+ String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
LogFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
}
if (LogFile != null)
{
StringBuilder buff = new StringBuilder();
// buff.Append(now.ToString("yyyyMMddHHmmssfff"));
buff.Append(now.ToString("yyyyMMddHHmmss"));
buff.Append(",");
buff.Append(line);
buff.Append("\r\n");
LogFile.Write(buff.ToString());
}
}
catch (Exception e)
{
// m_log.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
LogEnabled = false;
}
return;
}
}
}

View File

@ -34,8 +34,8 @@ using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
// using log4net;
// using System.Reflection;
//using log4net;
//using System.Reflection;
/*****************************************************
@ -98,6 +98,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
private int m_saydistance = 30;
private int m_shoutdistance = 100;
//private ILog m_log;
#region IRegionModule Members
public void Initialise(Scene scene, IConfigSource config)
@ -125,6 +127,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
m_scene.EventManager.OnChatFromClient += DeliverClientMessage;
m_scene.EventManager.OnChatBroadcast += DeliverClientMessage;
//DSG SYNC
//m_scene.EventManager.OnChatFromWorld += DeliverClientMessage;
//Kitty: temp debug
//m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
//end DSG SYNC
m_pendingQ = new Queue();
m_pending = Queue.Synchronized(m_pendingQ);
}
@ -241,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
/// <param name="msg">msg to sent</param>
public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position)
{
// m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
//m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
// type, channel, name, id, msg);
// Determine which listen event filters match the given set of arguments, this results

View File

@ -260,5 +260,33 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
MainConsole.Instance.Output(caps.ToString());
}
#region SYNC SERVER
// Stubs for actor and quark management. Only implementation is in SimianGridService
public bool RegisterEndpoint(GridEndpointInfo gei)
{
return m_GridService.RegisterEndpoint(gei);
}
public bool RegisterActor(string actorID, string actorType, string syncServerID)
{
return m_GridService.RegisterActor(actorID, actorType, syncServerID);
}
public bool RegisterQuark(string syncServerID, uint locX, uint locY)
{
return m_GridService.RegisterQuark(syncServerID, locX, locY);
}
public List<GridEndpointInfo> LookupQuark(uint locX, uint locY)
{
return m_GridService.LookupQuark(locX, locY);
}
public List<GridEndpointInfo> LookupQuark(uint locX, uint locY, string actorType)
{
return m_GridService.LookupQuark(locX, locY, actorType);
}
public bool CleanUpEndpoint(string syncServerID)
{
return m_GridService.CleanUpEndpoint(syncServerID);
}
#endregion SYNC SERVER
}
}

View File

@ -318,5 +318,33 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
return flags;
}
#endregion
#region SYNC SERVER
// Stubs for actor and quark management. Only implementation is in SimianGridService
public bool RegisterEndpoint(GridEndpointInfo gei)
{
return m_RemoteGridService.RegisterEndpoint(gei);
}
public bool RegisterActor(string actorID, string actorType, string syncServerID)
{
return m_RemoteGridService.RegisterActor(actorID, actorType, syncServerID);
}
public bool RegisterQuark(string syncServerID, uint locX, uint locY)
{
return m_RemoteGridService.RegisterQuark(syncServerID, locX, locY);
}
public List<GridEndpointInfo> LookupQuark(uint locX, uint locY)
{
return m_RemoteGridService.LookupQuark(locX, locY);
}
public List<GridEndpointInfo> LookupQuark(uint locX, uint locY, string actorType)
{
return m_RemoteGridService.LookupQuark(locX, locY, actorType);
}
public bool CleanUpEndpoint(string syncServerID)
{
return m_RemoteGridService.CleanUpEndpoint(syncServerID);
}
#endregion SYNC SERVER
}
}

View File

@ -200,6 +200,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData)
{
return false;
if (destination == null)
return false;

View File

@ -251,8 +251,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
UpdateMediaUrl(part, UUID.Zero);
SetPartMediaFlags(part, face, me != null);
//part.ScheduleFullUpdate();
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.MediaUrl, SceneObjectPartSyncProperties.Shape});
part.ScheduleFullUpdate();
part.TriggerScriptChangedEvent(Changed.MEDIA);
}
@ -457,7 +458,8 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
UpdateMediaUrl(part, agentId);
// Arguably, we could avoid sending a full update to the avatar that just changed the texture.
part.ScheduleFullUpdate();
//part.ScheduleFullUpdate();
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Shape, SceneObjectPartSyncProperties.MediaUrl});
part.TriggerScriptChangedEvent(Changed.MEDIA);
@ -535,7 +537,8 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
UpdateMediaUrl(part, agentId);
part.ScheduleFullUpdate();
//part.ScheduleFullUpdate();
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.MediaUrl});
part.TriggerScriptChangedEvent(Changed.MEDIA);

View File

@ -148,7 +148,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
part.GetProperties(remoteClient);
part.TriggerScriptChangedEvent(Changed.OWNER);
group.ResumeScripts();
part.ScheduleFullUpdate();
//part.ScheduleFullUpdate();
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.FullUpdate }); //quite some properties changed, let's just force all to be synchronized
break;

View File

@ -584,6 +584,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
m_scene.SaveTerrain();
//DSG SYNC
//Terrain has been modified, send out sync message if needed
//if (m_scene.RegionSyncModule != null)
//{
//m_log.DebugFormat("EventManager_OnTerrainTick: To call SendTerrainUpdates with TS {0} and actorID {1}", m_lastUpdateTimeStamp, m_lastUpdateActorID);
//m_scene.RegionSyncModule.SendTerrainUpdates(m_lastUpdateTimeStamp, m_lastUpdateActorID);
//}
//end of DSG SYNC
// Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
//m_scene.CreateTerrainTexture(true);
}
@ -624,6 +633,83 @@ namespace OpenSim.Region.CoreModules.World.Terrain
client.OnUnackedTerrain += client_OnUnackedTerrain;
}
//DSG SYNC
private long m_lastUpdateTimeStamp = DateTime.Now.Ticks;
public long LastUpdateTimeStamp
{
get { return m_lastUpdateTimeStamp; }
set { m_lastUpdateTimeStamp = value; }
}
private string m_lastUpdateActorID;
public string LastUpdateActorID
{
get { return m_lastUpdateActorID; }
set { m_lastUpdateActorID = value; }
}
private void SyncInfoUpdate(long timeStamp, string actorID)
{
m_lastUpdateTimeStamp = timeStamp;
m_lastUpdateActorID = actorID;
// m_log.DebugFormat("TerrainModule: updated syncinfo -- TS {0}, actorID {1}", m_lastUpdateTimeStamp, m_lastUpdateActorID);
}
/// <summary>
/// Invoked by receiving a terrain sync message. First, check if the
/// timestamp is more advance than the local copy. If so, update the
/// local terrain copy, update the sync info (timestamp and actorID).
/// <param name="timeStamp"></param>
/// <param name="actorID"></param>
/// <param name="terrainData"></param>
/// <returns></returns>
public bool UpdateTerrianBySync(long timeStamp, string actorID, string terrainData)
{
if (timeStamp > m_lastUpdateTimeStamp)
{
if (actorID.Equals(m_lastUpdateActorID) && actorID.Equals(m_scene.GetSyncActorID()))
{
m_log.WarnFormat("TerrainModule: Received a Terrain sync message with a more recent timestamp, HOWEVER, actorID on the update is the same with local acotrID ({0})",
actorID);
}
//SyncInfoUpdate(timeStamp, actorID);
//m_log.DebugFormat("TerrainModule: to copy new terrain data with TS {0}, actorID {1}", timeStamp, actorID);
m_scene.Heightmap.LoadFromXmlString(terrainData);
CheckForTerrainUpdates(false, timeStamp, actorID);
return true;
}
else if ((timeStamp == m_lastUpdateTimeStamp) && !actorID.Equals(m_lastUpdateActorID))
{
m_log.WarnFormat("TerrainModule: actors {0} and {1} have edited terrain with the same timestamp, TO DE DONE: need to pick a winner.",
actorID, m_lastUpdateActorID);
}
return false;
}
public bool TerrianModifiedLocally(string localActorID)
{
if (localActorID == m_lastUpdateActorID)
return true;
return false;
}
public void GetSyncInfo(out long lastUpdateTimeStamp, out string lastUpdateActorID)
{
lastUpdateTimeStamp = m_lastUpdateTimeStamp;
lastUpdateActorID = m_lastUpdateActorID;
}
public void SetSyncInfo(long lastUpdateTimeStamp, string lastUpdateActorID)
{
m_lastUpdateTimeStamp = lastUpdateTimeStamp;
m_lastUpdateActorID = lastUpdateActorID;
}
//end of DSG SYNC
/// <summary>
/// Checks to see if the terrain has been modified since last check
/// but won't attempt to limit those changes to the limits specified in the estate settings
@ -631,7 +717,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// </summary>
private void CheckForTerrainUpdates()
{
CheckForTerrainUpdates(false);
//DSG SYNC
m_log.DebugFormat("CheckForTerrainUpdates() called");
//Assumption: Thus function is only called when the terrain is updated by the local actor.
// Updating terrain during receiving sync messages from another actor will call CheckForTerrainUpdates.
//Update the timestamp to the current time tick, and set the LastUpdateActorID to be self
long currentTimeTick = DateTime.Now.Ticks;
string localActorID = m_scene.GetSyncActorID();
//SyncInfoUpdate(currentTimeTick, localActorID);
//Check if the terrain has been modified and send out sync message if modified.
CheckForTerrainUpdates(false, currentTimeTick, localActorID);
//end of DSG SYNC
//CheckForTerrainUpdates(false);
}
/// <summary>
@ -642,7 +742,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// currently invoked by client_OnModifyTerrain only and not the Commander interfaces
/// <param name="respectEstateSettings">should height map deltas be limited to the estate settings limits</param>
/// </summary>
private void CheckForTerrainUpdates(bool respectEstateSettings)
//private void CheckForTerrainUpdates(bool respectEstateSettings)
//DSG SYNC: Change the interface, to input the right sync information for the most recent update
private void CheckForTerrainUpdates(bool respectEstateSettings, long lastUpdateTimeStamp, string lastUpdateActorID)
//end of DSG SYNC
{
bool shouldTaint = false;
float[] serialised = m_channel.GetFloatsSerialised();
@ -671,6 +774,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
if (shouldTaint)
{
m_tainted = true;
//DSG SYNC
//Terrain has been modified, updated the sync info
if (m_scene.RegionSyncModule != null)
{
SyncInfoUpdate(lastUpdateTimeStamp, lastUpdateActorID);
m_scene.RegionSyncModule.SendTerrainUpdates(lastUpdateTimeStamp, lastUpdateActorID);
}
//end of DSG SYNC
}
}
@ -783,7 +894,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_painteffects[(StandardTerrainEffects) action].PaintEffect(
m_channel, allowMask, west, south, height, size, seconds);
CheckForTerrainUpdates(!god); //revert changes outside estate limits
//CheckForTerrainUpdates(!god); //revert changes outside estate limits
//DSG SYNC
CheckForTerrainUpdates(!god, DateTime.Now.Ticks, m_scene.GetSyncActorID());
//end of DSG SYNC
}
}
else
@ -824,7 +938,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_floodeffects[(StandardTerrainEffects) action].FloodEffect(
m_channel, fillArea, size);
CheckForTerrainUpdates(!god); //revert changes outside estate limits
//CheckForTerrainUpdates(!god); //revert changes outside estate limits
//DSG SYNC
CheckForTerrainUpdates(!god, DateTime.Now.Ticks, m_scene.GetSyncActorID());
//end of DSG SYNC
}
}
else

View File

@ -56,6 +56,7 @@ namespace OpenSim.Region.Examples.SimpleModule
public event ImprovedInstantMessage OnInstantMessage;
public event ChatMessage OnChatFromClient;
public event ChatMessageRaw OnChatFromClientRaw;
public event TextureRequest OnRequestTexture;
public event RezObject OnRezObject;
public event ModifyTerrain OnModifyTerrain;
@ -75,6 +76,9 @@ namespace OpenSim.Region.Examples.SimpleModule
public event RequestMapBlocks OnRequestMapBlocks;
public event RequestMapName OnMapNameRequest;
public event TeleportLocationRequest OnTeleportLocationRequest;
//DSG:
public event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
//end of DSG
public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
public event DisconnectUser OnDisconnectUser;
public event RequestAvatarProperties OnRequestAvatarProperties;
@ -86,6 +90,7 @@ namespace OpenSim.Region.Examples.SimpleModule
public event GenericCall1 OnCompleteMovementToRegion;
public event UpdateAgent OnPreAgentUpdate;
public event UpdateAgent OnAgentUpdate;
public event UpdateAgentRaw OnAgentUpdateRaw;
public event AgentRequestSit OnAgentRequestSit;
public event AgentSit OnAgentSit;
public event AvatarPickerRequest OnAvatarPickerRequest;
@ -400,6 +405,11 @@ namespace OpenSim.Region.Examples.SimpleModule
set { }
}
public uint MaxCoarseLocations
{
get { return 0; }
}
public virtual void ActivateGesture(UUID assetId, UUID gestureId)
{
}

View File

@ -35,5 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces
bool ValidateBakedTextureCache(IClientAPI client);
void QueueAppearanceSend(UUID agentid);
void QueueAppearanceSave(UUID agentid);
void RefreshAppearance(UUID agentid);
void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams);
}
}

View File

@ -86,6 +86,10 @@ namespace OpenSim.Region.Framework.Interfaces
ArrayList GetScriptErrors(UUID itemID);
void ResumeScripts();
#region REGION SYNC
void SuspendScripts();
#endregion REGION SYNC
/// <summary>
/// Stop all the scripts in this entity.
/// </summary>
@ -229,5 +233,8 @@ namespace OpenSim.Region.Framework.Interfaces
/// A <see cref="Dictionary`2"/>
/// </returns>
Dictionary<UUID, string> GetScriptStates();
//DSG
bool UpdateInventoryItemBySync(TaskInventoryItem item);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenSim.Framework;
using OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
using log4net;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IGridDialogModule
{
void SendGridDialogViaXMLRPC(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName,
string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID);
}
}

View File

@ -37,5 +37,8 @@ namespace OpenSim.Region.Framework.Interfaces
event UndeliveredMessage OnUndeliveredMessage;
void SendInstantMessage(GridInstantMessage im, MessageResultNotification result);
//DSG: add this to the interface to enable outsiders to call it
void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result);
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//KittyL: Added to support running script engine actor
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
//the interface for Scene to sync with Script Engine
public interface IPhysEngineToSceneConnector
{
// TODO:
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//KittyL: Added to support running script engine actor
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Framework.Interfaces
{
//the interface for Scene to sync with Script Engine
public interface IPhysEngineToSceneConnectorModule
{
bool IsPhysEngineScene();
bool IsActivePhysEngineScene();
bool IsPhysEngineActor();
bool DebugWithViewer { get; }
void SendUpdate(PhysicsActor pa);
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IRegionSyncClientModule
{
bool Active { get; }
bool Synced { get; }
void SendCoarseLocations();
void SendAppearanceToScene(UUID agentID);
void IncomingLoadBalanceConnection(ScenePresence presence);
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//KittyL: Added to support running script engine actor
using System;
using System.Collections.Generic;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
public enum DSGActorTypes
{
Unknown,
ScenePersistence, //the Scene (data store), which is now considered as a persistence actor
ClientManager,
ScriptEngine,
PhysicsEngine
}
/////////////////////////////////////////////////////////////////////////////////////
//Interface for SceneGraph to call into RegionSyncModule
/////////////////////////////////////////////////////////////////////////////////////
public interface IRegionSyncModule
{
bool Active { get; } //if true, this RegionSyncModule is connected into the synchronization overlay
string ActorID { get; } //might be phased out soon
string SyncID { get; }
//DSGActorTypes DSGActorType { get; set; }
bool IsSyncRelay { get; }
void ProcessAndEnqueuePrimUpdatesByLocal(SceneObjectPart part, List<SceneObjectPartSyncProperties> updatedProperties);
void SyncOutPrimUpdates();
//New functions for per property sync'ing
void SyncNewObject(SceneObjectGroup sog);
void SyncDeleteObject(SceneObjectGroup sog, bool softDelete);
void SyncLinkObject(SceneObjectGroup linkedGroup, SceneObjectPart root, List<SceneObjectPart> children);
void SyncDeLinkObject(List<SceneObjectPart> prims, List<SceneObjectGroup> beforeDelinkGroups, List<SceneObjectGroup> afterDelinkGroups);
void SendTerrainUpdates(long updateTimeStamp, string lastUpdateActorID);
//For propogating scene events to other actors
void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs);
//TODO LIST:
//Special API for handling avatars
//void QueuePresenceForTerseUpdate(ScenePresence presence)
//void SendAvatarUpdates();
//Debug purpose, mainly for debugging properties updated by LSL scripts
void Debug(String debugMsg);
}
/// <summary>
/// Interface for invoking DSGActor specific functions or accessing members whose values depend on the actor's type.
/// </summary>
public interface IDSGActorSyncModule
{
DSGActorTypes ActorType { get; }
string ActorID { get; }
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IRegionSyncServerModule
{
//void Scene_AddNewPrim(SceneObjectGroup sog);
bool Active { get; }
bool Synced { get; }
void QueuePresenceForTerseUpdate(ScenePresence presence);
void SendUpdates();
void SendAppearance(UUID agentID);
void SendAnimations(UUID agentID, UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
void SendTeleportUpdate(ScenePresence presence);
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//KittyL: Added to support running script engine actor
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
//the interface for Scene to sync with Script Engine
public interface ISceneToPhysEngineConnector
{
// TODO:
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//KittyL: Added to support running script engine actor
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Framework.Interfaces
{
//the interface for Scene to sync with Script Engine
public interface ISceneToPhysEngineServer
{
bool IsPhysEngineScene();
bool IsActivePhysEngineScene();
bool IsPhysEngineActor();
void SendUpdate(PhysicsActor pa);
}
}

View File

@ -34,7 +34,8 @@ namespace OpenSim.Region.Framework.Interfaces
{
void Reset();
void Close();
void QueuePartForUpdate(SceneObjectPart part);
//void QueuePartForUpdate(SceneObjectPart part);
void QueuePartForUpdate(SceneObjectPartBase part);
void SendPrimUpdates();
int GetPendingObjectsCount();
}

View File

@ -62,6 +62,9 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="regionUUID">the Region UUID</param>
/// <returns>List of loaded groups</returns>
List<SceneObjectGroup> LoadObjects(UUID regionUUID);
#region REGION SYNC
List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY);
#endregion REGION SYNC
/// <summary>
/// Store a terrain revision in region storage

View File

@ -73,6 +73,9 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="regionUUID">the Region UUID</param>
/// <returns>List of loaded groups</returns>
List<SceneObjectGroup> LoadObjects(UUID regionUUID);
#region REGION SYNC
List<SceneObjectGroup> LoadObjectsInGivenSpace(UUID regionID, float lowerX, float lowerY, float upperX, float upperY);
#endregion REGION SYNC
/// <summary>
/// Store a terrain revision in region storage

View File

@ -64,5 +64,38 @@ namespace OpenSim.Region.Framework.Interfaces
void InstallPlugin(string name, ITerrainEffect plug);
void UndoTerrain(ITerrainChannel channel);
//DSG SYNC
/// <summary>
/// Invoked by receiving a terrain sync message. First, check if the
/// timestamp is more advance than the local copy. If so, update the
/// local terrain copy.
/// </summary>
/// <param name="timeStamp">The time that the updated terrain was
/// created</param>
/// <param name="actorID">The actor who created the update.</param>
/// <param name="terrainData">The updated terrain</param>
bool UpdateTerrianBySync(long timeStamp, string actorID, string terrainData);
/// <summary>
/// Return true if the most recent update on terrain is done locally (i.e. not by receiving a terrain-sync message).
/// </summary>
/// <param name="localActorID"></param>
/// <returns></returns>
bool TerrianModifiedLocally(string localActorID);
/// <summary>
/// Obtain the timestemp and actorID information for the most recent update on terrain.
/// </summary>
/// <param name="lastUpdateTimeStamp"></param>
/// <param name="lastUpdateActorID"></param>
void GetSyncInfo(out long lastUpdateTimeStamp, out string lastUpdateActorID);
/// <summary>
/// This is only supposed to be called by Persistence actor, which will
/// set the timestamp and actorID values for terrain upon initialization time.
/// </summary>
/// <param name="lastUpdateTimeStamp"></param>
/// <param name="lastUpdateActorID"></param>
void SetSyncInfo(long lastUpdateTimeStamp, string lastUpdateActorID);
//end of DSG SYNC
}
}

View File

@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
public string CurrentMovementAnimation
{
get { return m_movementAnimation; }
set { m_movementAnimation = value; }
}
protected string m_movementAnimation = "DEFAULT";
@ -404,6 +405,13 @@ namespace OpenSim.Region.Framework.Scenes.Animation
{
if (m_scenePresence.IsChildAgent)
return;
if (m_scenePresence.Scene.IsSyncedServer())
{
m_scenePresence.Scene.RegionSyncServerModule.SendAnimations(
m_scenePresence.ControllingClient.AgentId, animations, seqs,
m_scenePresence.ControllingClient.AgentId, objectIDs);
return;
}
m_scenePresence.Scene.ForEachClient(
delegate(IClientAPI client)

View File

@ -38,10 +38,361 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
namespace OpenSim.Region.Framework.Scenes
{
//DSG SYNC: Rename the original EventManager as EventManagerBase, and implement a new EventManager that inherits from EventManagerBase
/// <summary>
/// A class for triggering remote scene events.
/// A wrapper class to implement handle event differently depending on if they are initiated locally or remotelly (i.e. by another actor)
/// </summary>
public class EventManager
public class EventManager: EventManagerBase
{
private Scene m_scene;
//the events that we'll handle specially in sym-sync
public enum EventNames
{
NewScript,
UpdateScript,
ScriptReset,
ChatFromClient, //chats from avatars
ChatFromWorld, //chats from objects
ChatBroadcast, //broadcast
ObjectGrab,
ObjectGrabbing,
ObjectDeGrab,
Attach, //attaching object to avatar
PhysicsCollision,
ScriptCollidingStart,
ScriptColliding,
ScriptCollidingEnd,
ScriptLandCollidingStart,
ScriptLandColliding,
ScriptLandCollidingEnd
}
public EventManager(Scene scene)
{
m_scene = scene;
}
#region NewScript
//triggered by client.OnRezScript
public override void TriggerNewScript(UUID clientID, SceneObjectPart part, UUID itemID)
{
//publish the event to other actors who are intersted in it
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[3];
eventArgs[0] = (Object)clientID;
eventArgs[1] = (Object)part;
eventArgs[2] = (Object)itemID;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.NewScript, eventArgs);
}
//trigger event locally,
TriggerNewScriptLocally(clientID, part, itemID);
}
//public void TriggerNewScriptLocally(UUID clientID, UUID itemId, UUID primId, UUID newAssetID)
public void TriggerNewScriptLocally(UUID clientID, SceneObjectPart part, UUID itemID)
{
base.TriggerNewScript(clientID, part, itemID);
}
#endregion //UpdateScript
#region UpdateScript
public override void TriggerUpdateScript(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
{
//publish the event to other actors who are intersted in it
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[5];
eventArgs[0] = (Object) clientId;
eventArgs[1] = (Object)itemId;
eventArgs[2] = (Object)primId;
eventArgs[3] = (Object)isScriptRunning;
eventArgs[4] = (Object)newAssetID;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.UpdateScript, eventArgs);
}
//trigger event locally,
TriggerUpdateScriptLocally(clientId, itemId, primId, isScriptRunning, newAssetID);
}
public void TriggerUpdateScriptLocally(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
{
base.TriggerUpdateScript(clientId, itemId, primId, isScriptRunning, newAssetID);
}
#endregion //UpdateScript
#region ScriptReset
public override void TriggerScriptReset(uint localID, UUID itemID)
{
//publish the event to other actors who are intersted in it
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[2];
eventArgs[0] = (Object)localID;
eventArgs[1] = (Object)itemID;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptReset, eventArgs);
}
//trigger event locally, as the legacy code does
TriggerScriptResetLocally(localID, itemID);
}
public void TriggerScriptResetLocally(uint localID, UUID itemID)
{
base.TriggerScriptReset(localID, itemID);
}
#endregion //UpdateScript
#region ChatFromClient
public override void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[2];
eventArgs[0] = sender;
eventArgs[1] = (Object)chat;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ChatFromClient, eventArgs);
}
TriggerOnChatFromClientLocally(sender, chat);
}
public void TriggerOnChatFromClientLocally(Object sender, OSChatMessage chat)
{
base.TriggerOnChatFromClient(sender, chat);
}
#endregion //ChatFromClient
#region ChatBroadcast
public override void TriggerOnChatBroadcast(Object sender, OSChatMessage chat)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[2];
eventArgs[0] = sender;
eventArgs[1] = (Object)chat;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ChatBroadcast, eventArgs);
}
TriggerOnChatBroadcastLocally(sender, chat);
}
public void TriggerOnChatBroadcastLocally(Object sender, OSChatMessage chat)
{
base.TriggerOnChatBroadcast(sender, chat);
}
#endregion
#region ChatFromWorld
public override void TriggerOnChatFromWorld(Object sender, OSChatMessage chat)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[2];
eventArgs[0] = sender;
eventArgs[1] = (Object)chat;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ChatFromWorld, eventArgs);
}
TriggerOnChatFromWorldLocally(sender, chat);
}
public void TriggerOnChatFromWorldLocally(Object sender, OSChatMessage chat)
{
base.TriggerOnChatFromWorld(sender, chat);
}
#endregion //ChatFromWorld
#region ObjectGrab, ObjectGrabbing, ObjectDeGrab
public override void TriggerObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[5];
eventArgs[0] = (Object)localID;
eventArgs[1] = (Object)originalID;
eventArgs[2] = (Object)offsetPos;
eventArgs[3] = (Object)remoteClient;
eventArgs[4] = (Object)surfaceArgs;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ObjectGrab, eventArgs);
}
TriggerObjectGrabLocally(localID, originalID, offsetPos, remoteClient, surfaceArgs);
}
public void TriggerObjectGrabLocally(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
base.TriggerObjectGrab(localID, originalID, offsetPos, remoteClient, surfaceArgs);
}
public override void TriggerObjectGrabbing(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[5];
eventArgs[0] = (Object)localID;
eventArgs[1] = (Object)originalID;
eventArgs[2] = (Object)offsetPos;
eventArgs[3] = (Object)remoteClient;
eventArgs[4] = (Object)surfaceArgs;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ObjectGrabbing, eventArgs);
}
TriggerObjectGrabbingLocally(localID, originalID, offsetPos, remoteClient, surfaceArgs);
}
public void TriggerObjectGrabbingLocally(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
base.TriggerObjectGrabbing(localID, originalID, offsetPos, remoteClient, surfaceArgs);
}
public override void TriggerObjectDeGrab(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[4];
eventArgs[0] = (Object)localID;
eventArgs[1] = (Object)originalID;
eventArgs[2] = (Object)remoteClient;
eventArgs[3] = (Object)surfaceArgs;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ObjectDeGrab, eventArgs);
}
TriggerObjectDeGrabLocally(localID, originalID, remoteClient, surfaceArgs);
}
public void TriggerObjectDeGrabLocally(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
base.TriggerObjectDeGrab(localID, originalID, remoteClient, surfaceArgs);
}
public override void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[4];
eventArgs[0] = (Object)localID;
eventArgs[1] = (Object)itemID;
eventArgs[2] = (Object)avatarID;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.Attach, eventArgs);
}
TriggerOnAttachLocally(localID, itemID, avatarID);
}
public void TriggerOnAttachLocally(uint localID, UUID itemID, UUID avatarID)
{
base.TriggerOnAttach(localID, itemID, avatarID);
}
#endregion //GrabObject
#region collisions
public override void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[4];
eventArgs[0] = (Object)localId;
eventArgs[1] = (Object)colliders;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptCollidingStart, eventArgs);
}
TriggerScriptCollidingStartLocally(localId, colliders);
}
public void TriggerScriptCollidingStartLocally(uint localId, ColliderArgs colliders)
{
base.TriggerScriptCollidingStart(localId, colliders);
}
public override void TriggerScriptColliding(uint localId, ColliderArgs colliders)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[4];
eventArgs[0] = (Object)localId;
eventArgs[1] = (Object)colliders;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptColliding, eventArgs);
}
TriggerScriptCollidingLocally(localId, colliders);
}
public void TriggerScriptCollidingLocally(uint localId, ColliderArgs colliders)
{
base.TriggerScriptColliding(localId, colliders);
}
public override void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[4];
eventArgs[0] = (Object)localId;
eventArgs[1] = (Object)colliders;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptCollidingEnd, eventArgs);
}
TriggerScriptCollidingEndLocally(localId, colliders);
}
public void TriggerScriptCollidingEndLocally(uint localId, ColliderArgs colliders)
{
base.TriggerScriptCollidingEnd(localId, colliders);
}
public override void TriggerScriptLandCollidingStart(uint localId, ColliderArgs colliders)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[4];
eventArgs[0] = (Object)localId;
eventArgs[1] = (Object)colliders;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptLandCollidingStart, eventArgs);
}
TriggerScriptLandCollidingStartLocally(localId, colliders);
}
public void TriggerScriptLandCollidingStartLocally(uint localId, ColliderArgs colliders)
{
base.TriggerScriptLandCollidingStart(localId, colliders);
}
public override void TriggerScriptLandColliding(uint localId, ColliderArgs colliders)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[4];
eventArgs[0] = (Object)localId;
eventArgs[1] = (Object)colliders;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptLandColliding, eventArgs);
}
TriggerScriptLandCollidingLocally(localId, colliders);
}
public void TriggerScriptLandCollidingLocally(uint localId, ColliderArgs colliders)
{
base.TriggerScriptLandColliding(localId, colliders);
}
public override void TriggerScriptLandCollidingEnd(uint localId, ColliderArgs colliders)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[4];
eventArgs[0] = (Object)localId;
eventArgs[1] = (Object)colliders;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptLandCollidingEnd, eventArgs);
}
TriggerScriptLandCollidingEndLocally(localId, colliders);
}
public void TriggerScriptLandCollidingEndLocally(uint localId, ColliderArgs colliders)
{
base.TriggerScriptLandCollidingEnd(localId, colliders);
}
#endregion
}
/// <summary>
/// A class for triggering scene events.
/// </summary>
public class EventManagerBase
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -461,7 +812,8 @@ namespace OpenSim.Region.Framework.Scenes
public event LandBuy OnLandBuy;
public event LandBuy OnValidateLandBuy;
public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
//public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
public virtual void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
{
Attach handlerOnAttach = OnAttach;
if (handlerOnAttach != null)
@ -882,7 +1234,9 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
//DSG SYNC: overridden at new EventManager class
//public void TriggerObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
public virtual void TriggerObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
ObjectGrabDelegate handlerObjectGrab = OnObjectGrab;
if (handlerObjectGrab != null)
@ -903,7 +1257,9 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerObjectGrabbing(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
//DSG SYNC: overridden at new EventManager class
//public void TriggerObjectGrabbing(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
public virtual void TriggerObjectGrabbing(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
ObjectGrabDelegate handlerObjectGrabbing = OnObjectGrabbing;
if (handlerObjectGrabbing != null)
@ -924,7 +1280,9 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerObjectDeGrab(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
//DSG SYNC: overridden at new EventManager class
//public void TriggerObjectDeGrab(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
public virtual void TriggerObjectDeGrab(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
ObjectDeGrabDelegate handlerObjectDeGrab = OnObjectDeGrab;
if (handlerObjectDeGrab != null)
@ -945,7 +1303,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerScriptReset(uint localID, UUID itemID)
//public void TriggerScriptReset(uint localID, UUID itemID)
public virtual void TriggerScriptReset(uint localID, UUID itemID)
{
ScriptResetDelegate handlerScriptReset = OnScriptReset;
if (handlerScriptReset != null)
@ -1613,7 +1972,9 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerOnChatFromWorld(Object sender, OSChatMessage chat)
//DSG SYNC: the function is overridden in new EventManager
//public void TriggerOnChatFromWorld(Object sender, OSChatMessage chat)
public virtual void TriggerOnChatFromWorld(Object sender, OSChatMessage chat)
{
ChatFromWorldEvent handlerChatFromWorld = OnChatFromWorld;
if (handlerChatFromWorld != null)
@ -1634,7 +1995,9 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
//DSG SYNC: overiding this in the inherited class
//public void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
public virtual void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
{
ChatFromClientEvent handlerChatFromClient = OnChatFromClient;
if (handlerChatFromClient != null)
@ -1679,7 +2042,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerOnChatBroadcast(Object sender, OSChatMessage chat)
//public void TriggerOnChatBroadcast(Object sender, OSChatMessage chat)
public virtual void TriggerOnChatBroadcast(Object sender, OSChatMessage chat)
{
ChatBroadcastEvent handlerChatBroadcast = OnChatBroadcast;
if (handlerChatBroadcast != null)
@ -1951,7 +2315,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
//public void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
public virtual void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
{
ScriptColliding handlerCollidingStart = OnScriptColliderStart;
if (handlerCollidingStart != null)
@ -1972,7 +2337,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerScriptColliding(uint localId, ColliderArgs colliders)
//public void TriggerScriptColliding(uint localId, ColliderArgs colliders)
public virtual void TriggerScriptColliding(uint localId, ColliderArgs colliders)
{
ScriptColliding handlerColliding = OnScriptColliding;
if (handlerColliding != null)
@ -1993,7 +2359,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
//public void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
public virtual void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
{
ScriptColliding handlerCollidingEnd = OnScriptCollidingEnd;
if (handlerCollidingEnd != null)
@ -2014,7 +2381,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerScriptLandCollidingStart(uint localId, ColliderArgs colliders)
//public void TriggerScriptLandCollidingStart(uint localId, ColliderArgs colliders)
public virtual void TriggerScriptLandCollidingStart(uint localId, ColliderArgs colliders)
{
ScriptColliding handlerLandCollidingStart = OnScriptLandColliderStart;
if (handlerLandCollidingStart != null)
@ -2035,7 +2403,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerScriptLandColliding(uint localId, ColliderArgs colliders)
//public void TriggerScriptLandColliding(uint localId, ColliderArgs colliders)
public virtual void TriggerScriptLandColliding(uint localId, ColliderArgs colliders)
{
ScriptColliding handlerLandColliding = OnScriptLandColliding;
if (handlerLandColliding != null)
@ -2056,7 +2425,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerScriptLandCollidingEnd(uint localId, ColliderArgs colliders)
//public void TriggerScriptLandCollidingEnd(uint localId, ColliderArgs colliders)
public virtual void TriggerScriptLandCollidingEnd(uint localId, ColliderArgs colliders)
{
ScriptColliding handlerLandCollidingEnd = OnScriptLandColliderEnd;
if (handlerLandCollidingEnd != null)
@ -2266,5 +2636,179 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
//REGION SYNC
#region REGION SYNC RELATED EVENTS
//OnScriptEngineSyncStop: triggered when user types "sync stop" on the script engine's console
public delegate void ScriptEngineSyncStop();
public event ScriptEngineSyncStop OnScriptEngineSyncStop;
public void TriggerScriptEngineSyncStop()
{
ScriptEngineSyncStop handlerScriptEngineSyncStop = OnScriptEngineSyncStop;
if (handlerScriptEngineSyncStop != null)
{
foreach (ScriptEngineSyncStop d in handlerScriptEngineSyncStop.GetInvocationList())
{
try
{
d();
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerScriptEngineSyncStop failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
public delegate void NewScript(UUID clientID, SceneObjectPart part, UUID itemID);
public event NewScript OnNewScript;
public virtual void TriggerNewScript(UUID clientID, SceneObjectPart part, UUID itemID)
{
NewScript handlerNewScript = OnNewScript;
if (handlerNewScript != null)
{
foreach (NewScript d in handlerNewScript.GetInvocationList())
{
try
{
d(clientID, part, itemID);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerNewScript failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
//TriggerUpdateScript: triggered after Scene receives client's upload of updated script and stores it as asset
public delegate void UpdateScript(UUID clientID, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID);
public event UpdateScript OnUpdateScript;
public virtual void TriggerUpdateScript(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
{
UpdateScript handlerUpdateScript = OnUpdateScript;
if (handlerUpdateScript != null)
{
foreach (UpdateScript d in handlerUpdateScript.GetInvocationList())
{
try
{
d(clientId, itemId, primId, isScriptRunning, newAssetID);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerUpdateScript failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
//OnPopulateLocalSceneList: Triggered by OpenSim to the valid local scene, should only happen in script engine
public delegate void PopulateLocalSceneList(List<Scene> localScenes);
public event PopulateLocalSceneList OnPopulateLocalSceneList;
public void TriggerPopulateLocalSceneList(List<Scene> localScenes)
//public delegate void PopulateLocalSceneList(List<Scene> localScenes, string[] cmdparams);
//public event PopulateLocalSceneList OnPopulateLocalSceneList;
//public void TriggerPopulateLocalSceneList(List<Scene> localScenes, string[] cmdparams)
{
PopulateLocalSceneList handlerPopulateLocalSceneList = OnPopulateLocalSceneList;
if (handlerPopulateLocalSceneList != null)
{
foreach (PopulateLocalSceneList d in handlerPopulateLocalSceneList.GetInvocationList())
{
try
{
d(localScenes);
//d(localScenes, cmdparams);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerPopulateLocalSceneList failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
#endregion
//DSG SYNC
public event PostSceneCreation OnPostSceneCreation;
public delegate void PostSceneCreation(Scene createdScene);
public void TriggerOnPostSceneCreation(Scene createdScene)
{
PostSceneCreation handler = OnPostSceneCreation;
if (handler != null)
{
foreach (PostSceneCreation d in handler.GetInvocationList())
{
try
{
d(createdScene);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerOnPostSceneCreation failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
public delegate void SymmetricSyncStop();
public event SymmetricSyncStop OnSymmetricSyncStop;
public void TriggerOnSymmetricSyncStop()
{
SymmetricSyncStop handlerSymmetricSyncStop = OnSymmetricSyncStop;
if (handlerSymmetricSyncStop != null)
{
foreach (SymmetricSyncStop d in handlerSymmetricSyncStop.GetInvocationList())
{
try
{
d();
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerOnSymmetricSyncStop failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
public delegate void AggregateScriptEvents(SceneObjectPart part);
public event AggregateScriptEvents OnAggregateScriptEvents;
public void TriggerAggregateScriptEvents(SceneObjectPart part)
{
AggregateScriptEvents handlerAggregateScriptEvents = OnAggregateScriptEvents;
if (handlerAggregateScriptEvents != null)
{
foreach (AggregateScriptEvents d in handlerAggregateScriptEvents.GetInvocationList())
{
try
{
d(part);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerAggregateScriptEvents failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
//end of DSG SYNC
}
}

View File

@ -204,6 +204,11 @@ namespace OpenSim.Region.Framework.Scenes
return UUID.Zero;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//REGION SYNC
//Scene does permission checking, asset creation and storing, then informs Script Engine to
//update the script.
////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Capability originating call to update the asset of a script in a prim's (task's) inventory
/// </summary>
@ -250,10 +255,17 @@ namespace OpenSim.Region.Framework.Scenes
AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data, remoteClient.AgentId);
AssetService.Store(asset);
//REGION SYNC: if RegionSyncEnabled, move script related operations to be after update inventory item
//DSG SYNC: commenting out old REGION SYNC code, the RemoveScriptInstance would be handled by ScriptEngineSyncModule
/*
if (!RegionSyncEnabled)
{
if (isScriptRunning)
{
part.Inventory.RemoveScriptInstance(item.ItemID, false);
}
}
* */
// Update item with new asset
item.AssetID = asset.FullID;
@ -262,6 +274,13 @@ namespace OpenSim.Region.Framework.Scenes
part.GetProperties(remoteClient);
////REGION SYNC
//DSG SYNC: commenting out old REGION SYNC code, the RemoveScriptInstance would be handled by ScriptEngineSyncModule
/*
if (!RegionSyncEnabled)
{
//Original OpenSim code below
// Trigger rerunning of script (use TriggerRezScript event, see RezScript)
ArrayList errors = new ArrayList();
@ -279,6 +298,156 @@ namespace OpenSim.Region.Framework.Scenes
part.ParentGroup.ResumeScripts();
return errors;
}
else
{
//Distributed Scene Graph is in place, trigger event OnUpdateScript to
//let SceneToSEConnector to contact remote script engine for script update
m_log.Debug("Scene.Inventory: to call EventManager.TriggerUpdateTaskInventoryScriptAsset, agentID: " + remoteClient.AgentId);
EventManager.TriggerUpdateScript(remoteClient.AgentId, itemId, primId, isScriptRunning, item.AssetID);
//For now, we simple tell client that script saved while waiting for remote script engine to re-rez the script.
//Later will change the BaseHttpServer's code to return error list to client.
remoteClient.SendAgentAlertMessage("Script saved", false);
ArrayList errors = new ArrayList();
return errors;
}
* */
//DSG SYNC: Distributed Scene Graph implementation
m_log.Debug("Scene.Inventory: to call EventManager.TriggerUpdateScript, agentID: " + remoteClient.AgentId);
//Trigger OnUpdateScript event.
EventManager.TriggerUpdateScript(remoteClient.AgentId, itemId, primId, isScriptRunning, item.AssetID);
//For now, we simple tell client that script saved while waiting for remote script engine to re-rez the script.
//Later will change the BaseHttpServer's code to return error list to client.
//remoteClient.SendAgentAlertMessage("Script saved", false);
ArrayList errors = new ArrayList();
return errors;
}
#region REGION SYNC
////////////////////////////////////////////////////////////////////////////////////////////////
//REGION SYNC
//Scene does permission checking, asset creation and storing, then informs Script Engine to
//update the script.
////////////////////////////////////////////////////////////////////////////////////////////////
//Only should be called when this is the local Scene of script engine
public ArrayList OnUpdateScript(UUID avatarID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
{
ArrayList errors = new ArrayList();
//In the old async model, this function is supposed to be executed only on a remote script engine, not an authorative Scene
/*
if (RegionSyncModule==null && !IsSyncedScriptEngine())
{
m_log.Warn("This is not the script engine. Should not have received OnUpdateScript event.");
return errors;
}
* */
SceneObjectPart part = GetSceneObjectPart(primID);
SceneObjectGroup group = part.ParentGroup;
if (isScriptRunning)
{
m_log.Debug("To RemoveScriptInstance");
part.Inventory.RemoveScriptInstance(itemID, false);
}
// Retrieve item
TaskInventoryItem item = group.GetInventoryItem(part.LocalId, itemID);
// Update item with new asset
item.AssetID = newAssetID;
group.UpdateInventoryItemBySync(item);
m_log.Debug("UpdateInventoryItem on object "+group.UUID);
if (isScriptRunning)
{
// Needs to determine which engine was running it and use that
m_log.Debug("To CreateScriptInstance");
part.Inventory.CreateScriptInstance(itemID, 0, false, DefaultScriptEngine, 0);
errors = part.Inventory.GetScriptErrors(itemID);
}
part.ParentGroup.ResumeScripts();
return errors;
}
#endregion
#region DSG SYNC
public ArrayList SymSync_OnNewScript(UUID avatarID, UUID itemID, SceneObjectPart part)
{
TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID);
part.Inventory.CreateScriptInstance(item, 0, false, DefaultScriptEngine, 0);
part.ParentGroup.ResumeScripts();
ArrayList errors = part.Inventory.GetScriptErrors(itemID);
return errors;
}
//only a script engine actor is supposed to call this function
public ArrayList SymSync_OnUpdateScript(UUID avatarID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
{
ArrayList errors = new ArrayList();
SceneObjectPart part = GetSceneObjectPart(primID);
SceneObjectGroup group = part.ParentGroup;
if (null == group)
{
m_log.ErrorFormat(
"[PRIM INVENTORY]: " +
"Prim inventory update requested for item ID {0} in prim ID {1} but this prim does not exist",
itemID, primID);
return new ArrayList();
}
if (isScriptRunning)
{
m_log.Debug("To RemoveScriptInstance");
part.Inventory.RemoveScriptInstance(itemID, false);
}
// Retrieve item
TaskInventoryItem item = group.GetInventoryItem(part.LocalId, itemID);
if (null == item)
{
m_log.ErrorFormat(
"[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for caps script update "
+ " but the item does not exist in this inventory",
itemID, part.Name, part.UUID);
return new ArrayList();
}
// Update item with new asset.
// The actor that initiate the UpdateScript event should also send out
// a sync message for the updated task inventory. In case that sync message is
// not here year, we retrieve and update the task item -- w/o marking that
// the taskinventory is modified here, so that when the sync message is here,
// the actor and timestamp info will be copied.
item.AssetID = newAssetID;
group.UpdateInventoryItemBySync(item);
m_log.Debug("UpdateInventoryItem on object "+group.UUID);
if (isScriptRunning)
{
// Needs to determine which engine was running it and use that
m_log.Debug("To CreateScriptInstance");
part.Inventory.CreateScriptInstance(itemID, 0, false, DefaultScriptEngine, 0);
errors = part.Inventory.GetScriptErrors(itemID);
}
part.ParentGroup.ResumeScripts();
return errors;
}
#endregion //DSG SYNC
/// <summary>
/// <see>CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[])</see>
@ -290,6 +459,8 @@ namespace OpenSim.Region.Framework.Scenes
if (TryGetScenePresence(avatarId, out avatar))
{
//REGION SYNC LOG
m_log.Debug("Scene.Inventory: Avatar " + avatarId + ", triggers UpdateTaskInventoryScriptAsset");
return CapsUpdateTaskInventoryScriptAsset(
avatar.ControllingClient, itemId, primId, isScriptRunning, data);
}
@ -1561,6 +1732,10 @@ namespace OpenSim.Region.Framework.Scenes
return;
part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID);
part.GetProperties(remoteClient);
//DSG SYNC
/* Original OpenSim code, commented out
// TODO: switch to posting on_rez here when scripts
// have state in inventory
part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0);
@ -1568,8 +1743,26 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.InfoFormat("[PRIMINVENTORY]: " +
// "Rezzed script {0} into prim local ID {1} for user {2}",
// item.inventoryName, localID, remoteClient.Name);
part.GetProperties(remoteClient);
//part.GetProperties(remoteClient);
part.ParentGroup.ResumeScripts();
* */
if (RegionSyncModule != null)
{
//part.SyncInfoUpdate();
EventManager.TriggerNewScript(remoteClient.AgentId, part, copyID);
}
else
{
part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0);
// m_log.InfoFormat("[PRIMINVENTORY]: " +
// "Rezzed script {0} into prim local ID {1} for user {2}",
// item.inventoryName, localID, remoteClient.Name);
//part.GetProperties(remoteClient);
part.ParentGroup.ResumeScripts();
}
//end of DSG SYNC
}
else
{
@ -1628,9 +1821,26 @@ namespace OpenSim.Region.Framework.Scenes
part.Inventory.AddInventoryItem(taskItem, false);
part.GetProperties(remoteClient);
//DSG SYNC
//part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0);
//part.ParentGroup.ResumeScripts();
if (RegionSyncModule != null)
{
//part.SyncInfoUpdate();
EventManager.TriggerNewScript(remoteClient.AgentId, part, taskItem.ItemID);
}
else
{
part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0);
// m_log.InfoFormat("[PRIMINVENTORY]: " +
// "Rezzed script {0} into prim local ID {1} for user {2}",
// item.inventoryName, localID, remoteClient.Name);
//part.GetProperties(remoteClient);
part.ParentGroup.ResumeScripts();
}
//end of DSG SYNC
}
}
/// <summary>
@ -2047,13 +2257,35 @@ namespace OpenSim.Region.Framework.Scenes
sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
}
AddNewSceneObject(group, true, pos, rot, vel);
//AddNewSceneObject(group, true, pos, rot, vel);
//DSG SYNC
bool triggerSyncNewObject = false;
AddNewSceneObjectByRez(group, true, true, triggerSyncNewObject);
group.AbsolutePosition = pos;
group.Velocity = vel;
if (rot != null)
group.UpdateGroupRotationR((Quaternion)rot);
// TODO: This needs to be refactored with the similar code in
// SceneGraph.AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel)
// possibly by allowing this method to take a null rotation.
if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero)
group.RootPart.ApplyImpulse((vel * group.GetMass()), false);
// We can only call this after adding the scene object, since the scene object references the scene
// to find out if scripts should be activated at all.
group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
group.ScheduleGroupForFullUpdate();
//group.ScheduleGroupForFullUpdate();
group.ScheduleGroupForFullUpdate(null); //new object, all properties have new value
//DSG SYNC: now all properties have been set, sending NewObject message,
if (RegionSyncModule != null)
{
RegionSyncModule.SyncNewObject(group);
}
return group;
}
@ -2118,7 +2350,8 @@ namespace OpenSim.Region.Framework.Scenes
{
sog.SetOwnerId(ownerID);
sog.SetGroup(groupID, remoteClient);
sog.ScheduleGroupForFullUpdate();
//sog.ScheduleGroupForFullUpdate();
sog.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.OwnerID, SceneObjectPartSyncProperties.GroupID});
SceneObjectPart[] partList = sog.Parts;
@ -2182,6 +2415,9 @@ namespace OpenSim.Region.Framework.Scenes
List<SceneObjectPart> children = new List<SceneObjectPart>();
SceneObjectPart root = GetSceneObjectPart(parentPrimId);
//DSG DEBUG
m_log.Debug("Scene.LinkObjects -- ROOT: " + root.DebugObjectPartProperties());
if (root == null)
{
m_log.DebugFormat("[LINK]: Can't find linkset root prim {0}", parentPrimId);
@ -2201,6 +2437,9 @@ namespace OpenSim.Region.Framework.Scenes
if (part == null)
continue;
//DSG DEBUG
m_log.Debug("Scene.LinkObjects -- child to link: " + part.DebugObjectPartProperties());
if (!owners.Contains(part.OwnerID))
owners.Add(part.OwnerID);

View File

@ -212,7 +212,8 @@ namespace OpenSim.Region.Framework.Scenes
if (part.ParentGroup.IsAttachment)
isAttachment = true;
else
part.ParentGroup.ScheduleGroupForFullUpdate();
//part.ParentGroup.ScheduleGroupForFullUpdate();
part.ParentGroup.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate});
// If it's not an attachment, and we are allowed to move it,
// then we might have done so. If we moved across a parcel

File diff suppressed because it is too large Load Diff

View File

@ -469,6 +469,8 @@ namespace OpenSim.Region.Framework.Scenes
/// Shows various details about the sim based on the parameters supplied by the console command in openSimMain.
/// </summary>
/// <param name="showParams">What to show</param>
///
/*
public virtual void Show(string[] showParams)
{
switch (showParams[0])
@ -484,7 +486,7 @@ namespace OpenSim.Region.Framework.Scenes
}
break;
}
}
}*/
/// <summary>
/// Call this from a region module to add a command to the OpenSim console.

View File

@ -47,6 +47,11 @@ namespace OpenSim.Region.Framework.Scenes
public delegate void ObjectDeleteDelegate(EntityBase obj);
//DSG SYNC
public delegate void ObjectCreateBySyncDelegate(EntityBase obj);
//end of DSG SYNC
/// <summary>
/// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
/// should be migrated out over time.
@ -64,6 +69,10 @@ namespace OpenSim.Region.Framework.Scenes
public event ObjectCreateDelegate OnObjectCreate;
public event ObjectDeleteDelegate OnObjectRemove;
//DSG SYNC
public event ObjectCreateBySyncDelegate OnObjectCreateBySync;
//end of DSG SYNC
#endregion
#region Fields
@ -279,7 +288,7 @@ namespace OpenSim.Region.Framework.Scenes
sceneObject.HasGroupChanged = true;
}
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates, true);
}
/// <summary>
@ -301,7 +310,8 @@ namespace OpenSim.Region.Framework.Scenes
if (attachToBackup)
sceneObject.HasGroupChanged = true;
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
//DSG SYNC: passing true to trigger SyncNewObject
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates, true);
}
/// <summary>
@ -338,6 +348,11 @@ namespace OpenSim.Region.Framework.Scenes
sceneObject.Velocity = vel;
}
//DSG SYNC
//Moving AddNewSceneObject to the end of this function, so that
//all object properties are set when AddNewSceneObject is called.
AddNewSceneObject(sceneObject, true, false);
return true;
}
@ -360,7 +375,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns>
/// true if the object was added, false if an object with the same uuid was already in the scene
/// </returns>
protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates, bool triggerSyncNewObject)
{
if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero)
return false;
@ -368,9 +383,9 @@ namespace OpenSim.Region.Framework.Scenes
if (Entities.ContainsKey(sceneObject.UUID))
return false;
// m_log.DebugFormat(
// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
// m_log.DebugFormat(
// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
SceneObjectPart[] children = sceneObject.Parts;
@ -388,16 +403,14 @@ namespace OpenSim.Region.Framework.Scenes
if (scale.Z > m_parentScene.m_maxNonphys)
scale.Z = m_parentScene.m_maxNonphys;
part.Shape.Scale = scale;
//part.Shape.Scale = scale;
part.Scale = scale;
}
}
m_numPrim += children.Length;
sceneObject.AttachToScene(m_parentScene);
if (sendClientUpdates)
sceneObject.ScheduleGroupForFullUpdate();
Entities.Add(sceneObject);
if (attachToBackup)
@ -423,6 +436,16 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
}
if (sendClientUpdates)
//sceneObject.ScheduleGroupForFullUpdate();
sceneObject.ScheduleGroupForFullUpdate(null);
//DSG SYNC: sending NewObject event,
if (m_parentScene.RegionSyncModule != null && triggerSyncNewObject)
{
m_parentScene.RegionSyncModule.SyncNewObject(sceneObject);
}
return true;
}
@ -483,7 +506,10 @@ namespace OpenSim.Region.Framework.Scenes
protected internal void AddToUpdateList(SceneObjectGroup obj)
{
lock (m_updateList)
{
m_updateList[obj.UUID] = obj;
//m_log.Debug("added " + obj.Name+","+ obj.UUID + " to m_updateList");
}
}
/// <summary>
@ -502,6 +528,15 @@ namespace OpenSim.Region.Framework.Scenes
lock (m_updateList)
{
updates = new List<SceneObjectGroup>(m_updateList.Values);
if (updates.Count > 0)
{
//m_log.Debug("SceneGraph.UpdateObjectGroups: " + updates.Count + " objects to send updates for");
}
m_updateList.Clear();
}
@ -923,7 +958,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
/// <param name="fullID"></param>
/// <returns>null if no scene object group containing that prim is found</returns>
private SceneObjectGroup GetGroupByPrim(UUID fullID)
public SceneObjectGroup GetGroupByPrim(UUID fullID)
{
SceneObjectGroup sog;
lock (SceneObjectGroupsByFullPartID)
@ -1653,8 +1688,12 @@ namespace OpenSim.Region.Framework.Scenes
return; // parent is null so not in this region
}
foreach (SceneObjectGroup child in childGroups)
{
m_log.Debug("linking child " + child.UUID + " to parentGroup " + parentGroup.UUID);
parentGroup.LinkToGroup(child);
// this is here so physics gets updated!
@ -1662,12 +1701,25 @@ namespace OpenSim.Region.Framework.Scenes
child.AbsolutePosition = child.AbsolutePosition;
}
// We need to explicitly resend the newly link prim's object properties since no other actions
// occur on link to invoke this elsewhere (such as object selection)
parentGroup.RootPart.CreateSelected = true;
parentGroup.TriggerScriptChangedEvent(Changed.LINK);
parentGroup.HasGroupChanged = true;
parentGroup.ScheduleGroupForFullUpdate();
//DSG SYNC
//Send out LinkObject sync messages.
if (m_parentScene.RegionSyncModule != null)
{
//Tell other actors to link the SceneObjectParts together as a new group.
//m_parentScene.RegionSyncModule.SendLinkObject(parentGroup, root, children);
m_parentScene.RegionSyncModule.SyncLinkObject(parentGroup, root, children);
}
//Schedule updates as in legacy OpenSim code, to send updates to viewers connected to this actor (at least needed for client managers).
//But timestamp won't be changed, so that when other actors get the update, they's simple ignore the updates since they already get them
//via the LinkObject message sent above.
parentGroup.ScheduleGroupForFullUpdate(null);
//end of DSG SYNC
}
finally
@ -1688,6 +1740,11 @@ namespace OpenSim.Region.Framework.Scenes
List<SceneObjectPart> childParts = new List<SceneObjectPart>();
List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
//DSG SYNC, record the new object groups after the delink operation
List<SceneObjectGroup> beforeDelinkGroups = new List<SceneObjectGroup>();
List<SceneObjectGroup> afterDelinkGroups = new List<SceneObjectGroup>();
// Look them all up in one go, since that is comparatively expensive
//
foreach (SceneObjectPart part in prims)
@ -1703,7 +1760,11 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectGroup group = part.ParentGroup;
if (!affectedGroups.Contains(group))
{
affectedGroups.Add(group);
//DSG SYNC
beforeDelinkGroups.Add(group);
}
}
}
}
@ -1717,7 +1778,10 @@ namespace OpenSim.Region.Framework.Scenes
// These are not in affected groups and will not be
// handled further. Do the honors here.
child.ParentGroup.HasGroupChanged = true;
child.ParentGroup.ScheduleGroupForFullUpdate();
//DSG SYNC, delay ScheduleGroupForFullUpdate till the end of the delink operations.
//child.ParentGroup.ScheduleGroupForFullUpdate();
afterDelinkGroups.Add(child.ParentGroup);
}
foreach (SceneObjectPart root in rootParts)
@ -1786,8 +1850,25 @@ namespace OpenSim.Region.Framework.Scenes
{
g.TriggerScriptChangedEvent(Changed.LINK);
g.HasGroupChanged = true; // Persist
g.ScheduleGroupForFullUpdate();
//DSG SYNC, delay ScheduleGroupForFullUpdate till the end of the delink operations.
//g.ScheduleGroupForFullUpdate();
afterDelinkGroups.Add(g);
}
//DSG SYNC
//Send out DelinkObject message to other actors to sychronize their object list
if (m_parentScene.RegionSyncModule != null)
{
m_parentScene.RegionSyncModule.SyncDeLinkObject(prims, beforeDelinkGroups, afterDelinkGroups);
}
//Schedule updates as in legacy OpenSim code, to send updates
//to viewers connected to this actor (at least needed for client managers).
foreach (SceneObjectGroup sog in afterDelinkGroups)
{
sog.ScheduleGroupForFullUpdate(null);
}
//end of DSG SYNC
}
finally
{
@ -1947,7 +2028,8 @@ namespace OpenSim.Region.Framework.Scenes
copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
copy.HasGroupChanged = true;
copy.ScheduleGroupForFullUpdate();
//copy.ScheduleGroupForFullUpdate();
copy.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate}); //new object, all property values are new
copy.ResumeScripts();
// required for physics to update it's position
@ -1985,6 +2067,514 @@ namespace OpenSim.Region.Framework.Scenes
#endregion
#region DSG SYNC
/*
public Scene.ObjectUpdateResult UpdateObjectBySynchronization(SceneObjectGroup updatedSog)
{
UUID sogID = updatedSog.UUID;
Scene.ObjectUpdateResult updateResult = Scene.ObjectUpdateResult.Unchanged;
if (Entities.ContainsKey(sogID))
{
//update the object
EntityBase entity = Entities[sogID];
if (entity is SceneObjectGroup)
{
SceneObjectGroup localSog = (SceneObjectGroup)entity;
updateResult = localSog.UpdateObjectGroupBySync(updatedSog);
}
else
{
m_log.WarnFormat("{0}: Entity with {1} is not of type SceneObjectGroup: {2}",
"[SCENE GRAPH]", sogID, entity.GetType().ToString());
//return false;
updateResult = Scene.ObjectUpdateResult.Error;
}
}
else
{
//An object no longer in Entity list, probably linked to other objects, or handed over to another quark.
m_log.WarnFormat("[SCENE GRAPH] UpdateObjectBySynchronization: received update for an object {0}, {1} no longer in local Entity list. Ignore update.", updatedSog.Name, updatedSog.UUID);
}
return updateResult;
}
*/
//This is called when an object is added due to receiving a state synchronization message from Scene or an actor. Do similar things as the original AddSceneObject(),
//but call ScheduleGroupForFullUpdate_TimeStampUnchanged() instead, so as not to modify the timestamp or actorID, since the object was not created locally.
/*
public Scene.ObjectUpdateResult AddNewSceneObjectBySync(SceneObjectGroup sceneObject)
{
Scene.ObjectUpdateResult updateResult = Scene.ObjectUpdateResult.New;
if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero)
return Scene.ObjectUpdateResult.Error;
if (Entities.ContainsKey(sceneObject.UUID))
{
m_log.WarnFormat("[SCENE GRAPH] AddNewSceneObjectBySync: Already has object {0}, {1} in local Entity list.", sceneObject.Name, sceneObject.UUID);
return Scene.ObjectUpdateResult.Error;
}
SceneObjectPart[] children = sceneObject.Parts;
// Clamp child prim sizes and add child prims to the m_numPrim count
if (m_parentScene.m_clampPrimSize)
{
foreach (SceneObjectPart part in children)
{
SceneObjectPartBase partBase = (SceneObjectPartBase)part;
Vector3 scale = partBase.Scale;
if (scale.X > m_parentScene.m_maxNonphys)
scale.X = m_parentScene.m_maxNonphys;
if (scale.Y > m_parentScene.m_maxNonphys)
scale.Y = m_parentScene.m_maxNonphys;
if (scale.Z > m_parentScene.m_maxNonphys)
scale.Z = m_parentScene.m_maxNonphys;
part.Scale = scale;
}
}
m_numPrim += children.Length;
sceneObject.AttachToScene(m_parentScene);
//Take some special care of the case of this object being an attachment,
//since localID of attachedAvatar is different in different sync node's
//Scene copies.
sceneObject.RootPart.SetAttachmentPoint(sceneObject.RootPart.AttachmentPoint);
if (sceneObject.IsAttachment)
{
ScenePresence avatar = m_parentScene.GetScenePresence(sceneObject.RootPart.AttachedAvatar);
//It is possible that the avatar has not been fully
//created locally when attachment objects are sync'ed.
//So we need to check if the avatar already exists.
//If not, handling of NewAvatar will evetually trigger
//calling of SetParentLocalId.
if(avatar!=null)
sceneObject.RootPart.SetParentLocalId(avatar.LocalId);
}
sceneObject.HasGroupChanged = true;
//NewObject is sent via a specific sync message, not through updates;
//hence not passing any property list here
sceneObject.ScheduleGroupForFullUpdate(null);
Entities.Add(sceneObject);
//ScenePersistenceSyncModule will attach the object to backup when it catches the OnObjectCreate event.
//if (attachToBackup)
// sceneObject.AttachToBackup();
//if (OnObjectCreate != null)
// OnObjectCreate(sceneObject);
if (OnObjectCreateBySync != null)
OnObjectCreateBySync(sceneObject);
lock (SceneObjectGroupsByFullID)
SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
lock (SceneObjectGroupsByFullPartID)
{
SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject;
foreach (SceneObjectPart part in children)
SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
}
lock (SceneObjectGroupsByLocalPartID)
{
SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject;
foreach (SceneObjectPart part in children)
SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
}
return updateResult;
}
* */
public void AddNewSceneObjectPart(SceneObjectPart newPart, SceneObjectGroup parentGroup)
{
SceneObjectPart[] children = parentGroup.Parts;
lock (SceneObjectGroupsByFullID)
{
SceneObjectGroupsByFullID[parentGroup.UUID] = parentGroup;
foreach (SceneObjectPart part in children)
SceneObjectGroupsByFullID[newPart.UUID] = parentGroup;
}
lock (SceneObjectGroupsByLocalPartID)
{
SceneObjectGroupsByLocalPartID[parentGroup.LocalId] = parentGroup;
foreach (SceneObjectPart part in children)
SceneObjectGroupsByLocalPartID[newPart.LocalId] = parentGroup;
}
}
public void LinkObjectsBySync(SceneObjectPart root, List<SceneObjectPart> children)
{
Monitor.Enter(m_updateLock);
try
{
SceneObjectGroup parentGroup = root.ParentGroup;
List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
if (parentGroup != null)
{
// We do this in reverse to get the link order of the prims correct
for (int i = children.Count - 1; i >= 0; i--)
{
SceneObjectGroup child = children[i].ParentGroup;
if (child != null)
{
// Make sure no child prim is set for sale
// So that, on delink, no prims are unwittingly
// left for sale and sold off
child.RootPart.ObjectSaleType = 0;
child.RootPart.SalePrice = 10;
childGroups.Add(child);
}
}
}
else
{
return; // parent is null so not in this region
}
foreach (SceneObjectGroup child in childGroups)
{
parentGroup.LinkToGroupBySync(child);
// this is here so physics gets updated!
// Don't remove! Bad juju! Stay away! or fix physics!
child.AbsolutePosition = child.AbsolutePosition;
}
// We need to explicitly resend the newly link prim's object properties since no other actions
// occur on link to invoke this elsewhere (such as object selection)
parentGroup.RootPart.CreateSelected = true;
parentGroup.TriggerScriptChangedEvent(Changed.LINK);
parentGroup.HasGroupChanged = true;
//Do not change the timestamp and actorID values
parentGroup.ScheduleGroupForFullUpdate(null);
}
finally
{
Monitor.Exit(m_updateLock);
}
}
/// <summary>
/// Delink the prims as indicated in localPrimIDs, and regroup them as the object-groups indicated in incomingAfterDelinkGroups.
/// </summary>
/// <param name="localPrims"></param>
/// <param name="beforeDelinkGroupIDs"></param>
/// <param name="incomingAfterDelinkGroups"></param>
public void DelinkObjectsBySync(List<UUID> delinkPrimIDs, List<UUID> beforeDelinkGroupIDs, List<SceneObjectGroup> incomingAfterDelinkGroups)
{
Dictionary<UUID, SceneObjectGroup> localBeforeDelinkGroups = new Dictionary<UUID, SceneObjectGroup>();
List<SceneObjectGroup> localAfterDelinkGroups = new List<SceneObjectGroup>();
Dictionary<UUID, SceneObjectPart> delinkPrims = new Dictionary<UUID, SceneObjectPart>();
bool beforeStateConsistent = true;
bool afterStateConsistent = true;
Monitor.Enter(m_updateLock);
try
{
//get the before-delink-groups, and all the prims to delink
foreach (UUID primID in delinkPrimIDs)
{
SceneObjectPart localPart = GetSceneObjectPart(primID);
if (!delinkPrims.ContainsKey(primID))
{
delinkPrims.Add(primID, localPart);
}
SceneObjectGroup localGroup = localPart.ParentGroup;
if (!localBeforeDelinkGroups.ContainsKey(localGroup.UUID))
{
localBeforeDelinkGroups.Add(localGroup.UUID, localGroup);
}
}
//Next, do some sanity check to see if the local copy agrees with remote copy on the before-link state.
//TODO:: Actions to be taken after detecting conflicts. For now, we just assume the chance that conflict will happen is almost 0.
//First, check if the groups match
if (beforeDelinkGroupIDs.Count != localBeforeDelinkGroups.Count)
{
//detected conflict on editing object groups
m_log.Warn("DelinkObjectsBySync: the # of groups in before-delink-groups is different from the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
beforeStateConsistent = false;
//TODO: further actions
}
else
{
foreach (UUID beforeGroupID in beforeDelinkGroupIDs)
{
if (!localBeforeDelinkGroups.ContainsKey(beforeGroupID))
{
m_log.Warn("DelinkObjectsBySync: the local state of before-delink-groups is different from the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
beforeStateConsistent = false;
break;
}
}
//TODO: further actions
}
if(beforeStateConsistent){
//Second, check if the prims match
List<SceneObjectPart> allPrimsInLocalGroups = new List<SceneObjectPart>();
foreach (KeyValuePair<UUID, SceneObjectGroup> pair in localBeforeDelinkGroups)
{
foreach (SceneObjectPart part in pair.Value.Parts)
{
allPrimsInLocalGroups.Add(part);
}
}
if (allPrimsInLocalGroups.Count != delinkPrims.Count)
{
m_log.Warn("DelinkObjectsBySync: the # of prims of before-delink-groups is different from the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
beforeStateConsistent = false;
//TODO: further action
}else{
foreach (SceneObjectPart part in allPrimsInLocalGroups)
{
if (!delinkPrims.ContainsKey(part.UUID))
{
m_log.Warn("DelinkObjectsBySync: some local prims in before-delink-groups not exist in the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
beforeStateConsistent = false;
break;
//TODO: further action
}
}
}
}
//end of sanity checking
if(!beforeStateConsistent){
m_log.Warn("DelinkObjectsBySync: before-delink state not consistent in local copy and the incoming copy. Return without further operations.");
}else{
//Next, apply the delink operation locally.
localAfterDelinkGroups = DelinkObjectsBySync(new List<SceneObjectPart>(delinkPrims.Values));
//Check if local after-state agrees with that in the remote copy, and update the groups' properties
if (localAfterDelinkGroups.Count != incomingAfterDelinkGroups.Count)
{
m_log.Warn("DelinkObjectsBySync: local state after delink does not agree with the incoming delink message (# of groups are different). NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
afterStateConsistent = false;
}
else
{
Dictionary<UUID, SceneObjectGroup> incomingAfterDelinkGroupsDictionary = new Dictionary<UUID,SceneObjectGroup>();
foreach (SceneObjectGroup incomingGroup in incomingAfterDelinkGroups){
incomingAfterDelinkGroupsDictionary.Add(incomingGroup.UUID, incomingGroup);
}
foreach (SceneObjectGroup localAfterGroup in localAfterDelinkGroups)
{
if (!incomingAfterDelinkGroupsDictionary.ContainsKey(localAfterGroup.UUID))
{
m_log.Warn("DelinkObjectsBySync: local state after delink does not agree with the incoming delink message. NEED BETTER CONCURRENCY CONTROL IMPLEMENTATION!!!");
afterStateConsistent = false;
}
else
{
//No longer calling update prim's properties here, caller will do that
//localAfterGroup.UpdateObjectGroupBySync(incomingAfterDelinkGroupsDictionary[localAfterGroup.UUID]);
}
}
}
}
foreach (SceneObjectGroup sog in localAfterDelinkGroups)
{
sog.ScheduleGroupForFullUpdate(null);
}
}
finally
{
Monitor.Exit(m_updateLock);
}
if(beforeStateConsistent && afterStateConsistent){
m_log.Debug("DelinkObjectsBySync successful");
}
}
//Similar to DelinkObjects(), but calling DelinkFromGroupBySync instead
private List<SceneObjectGroup> DelinkObjectsBySync(List<SceneObjectPart> prims)
{
//!!!Caller of this function should already lock on m_updateLock, so no locking here !!!
List<SceneObjectGroup> afterDelinkGroups = new List<SceneObjectGroup>();
List<SceneObjectPart> childParts = new List<SceneObjectPart>();
List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
foreach (SceneObjectPart part in prims)
{
if (part != null)
{
if (part.ParentGroup.PrimCount != 1) // Skip single
{
if (part.LinkNum < 2) // Root
rootParts.Add(part);
else
childParts.Add(part);
SceneObjectGroup group = part.ParentGroup;
if (!affectedGroups.Contains(group))
{
affectedGroups.Add(group);
}
}
}
}
foreach (SceneObjectPart child in childParts)
{
// Unlink all child parts from their groups, w/o triggering unwanted events or syncinfo updates
child.ParentGroup.DelinkFromGroupBySync(child, true);
// These are not in affected groups and will not be
// handled further. Do the honors here.
child.ParentGroup.HasGroupChanged = true;
//record the after-delink-groups
afterDelinkGroups.Add(child.ParentGroup);
}
foreach (SceneObjectPart root in rootParts)
{
// In most cases, this will run only one time, and the prim
// will be a solo prim
// However, editing linked parts and unlinking may be different
//
SceneObjectGroup group = root.ParentGroup;
List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
int numChildren = newSet.Count;
// If there are prims left in a link set, but the root is
// slated for unlink, we need to do this
//
if (numChildren != 1)
{
// Unlink the remaining set
//
bool sendEventsToRemainder = true;
if (numChildren > 1)
sendEventsToRemainder = false;
foreach (SceneObjectPart p in newSet)
{
if (p != group.RootPart)
group.DelinkFromGroupBySync(p, sendEventsToRemainder);
}
// If there is more than one prim remaining, we
// need to re-link
//
if (numChildren > 2)
{
// Remove old root
//
if (newSet.Contains(root))
newSet.Remove(root);
// Preserve link ordering
//
newSet.Sort(delegate(SceneObjectPart a, SceneObjectPart b)
{
return a.LinkNum.CompareTo(b.LinkNum);
});
// Determine new root
//
SceneObjectPart newRoot = newSet[0];
newSet.RemoveAt(0);
foreach (SceneObjectPart newChild in newSet)
newChild.UpdateFlag = 0;
LinkObjectsBySync(newRoot, newSet);
if (!affectedGroups.Contains(newRoot.ParentGroup))
affectedGroups.Add(newRoot.ParentGroup);
}
}
}
foreach (SceneObjectGroup g in affectedGroups)
{
g.TriggerScriptChangedEvent(Changed.LINK);
g.HasGroupChanged = true; // Persist
afterDelinkGroups.Add(g);
}
return afterDelinkGroups;
}
protected internal bool AddNewSceneObjectByDelink(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
{
// Ensure that we persist this new scene object if it's not an
// attachment
if (attachToBackup)
sceneObject.HasGroupChanged = true;
bool triggerSyncNewObject = false;
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates, triggerSyncNewObject);
}
protected internal bool AddNewSceneObjectByRez(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates, bool triggerSyncNewObject)
{
// Ensure that we persist this new scene object if it's not an
// attachment
if (attachToBackup)
sceneObject.HasGroupChanged = true;
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates, triggerSyncNewObject);
}
protected internal bool AddNewSceneObjectBySync(SceneObjectGroup sceneObject)
{
sceneObject.HasGroupChanged = true;
bool triggerSyncNewObject = false;
if (AddSceneObject(sceneObject, true, true, triggerSyncNewObject))
{
//Take some special care of the case of this object being an attachment,
//since localID of attachedAvatar is different in different sync node's
//Scene copies.
sceneObject.RootPart.SetAttachmentPoint(sceneObject.RootPart.AttachmentPoint);
if (sceneObject.IsAttachment)
{
ScenePresence avatar = m_parentScene.GetScenePresence(sceneObject.RootPart.AttachedAvatar);
//It is possible that the avatar has not been fully
//created locally when attachment objects are sync'ed.
//So we need to check if the avatar already exists.
//If not, handling of NewAvatar will evetually trigger
//calling of SetParentLocalId.
if (avatar != null)
sceneObject.RootPart.SetParentLocalId(avatar.LocalId);
}
sceneObject.HasGroupChanged = true;
sceneObject.ScheduleGroupForFullUpdate(null);
if (OnObjectCreateBySync != null)
OnObjectCreateBySync(sceneObject);
return true;
}
return false;
}
#endregion //DSG SYNC
}
}

View File

@ -389,5 +389,42 @@ namespace OpenSim.Region.Framework.Scenes
for (int i = 0; i < parts.Length; i++)
parts[i].Inventory.ResumeScripts();
}
#region REGION SYNC
public void SuspendScripts()
{
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
parts[i].Inventory.SuspendScripts();
}
#endregion REGION SYNC
#region DSG SYNC
/// <summary>
/// Update an existing inventory item.
/// </summary>
/// <param name="item">The updated item. An item with the same id must already exist
/// in this prim's inventory</param>
/// <returns>false if the item did not exist, true if the update occurred succesfully</returns>
public bool UpdateInventoryItemBySync(TaskInventoryItem item)
{
SceneObjectPart part = GetChildPart(item.ParentPartID);
if (part != null)
{
part.Inventory.UpdateInventoryItemBySync(item);
return true;
}
else
{
m_log.ErrorFormat(
"[PRIM INVENTORY]: " +
"Couldn't find prim ID {0} to update item {1}, {2}",
item.ParentPartID, item.Name, item.ItemID);
}
return false;
}
#endregion
}
}

View File

@ -334,6 +334,8 @@ namespace OpenSim.Region.Framework.Scenes
|| Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
&& !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
{
//DSG DEBUG
m_log.DebugFormat("Object {0},{1} at pos {2}, to call CrossPrimGroupIntoNewRegion.", Name, UUID, val);
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
}
}
@ -508,6 +510,20 @@ namespace OpenSim.Region.Framework.Scenes
#region Constructors
//DSG SYNC
public SceneObjectGroup(SceneObjectPart part, bool newGroupBySync)
{
if (!newGroupBySync)
{
SetRootPart(part);
}
else
{
SetRootPartBySync(part);
}
}
/// <summary>
/// Constructor
/// </summary>
@ -975,7 +991,10 @@ namespace OpenSim.Region.Framework.Scenes
RootPart.RemFlag(PrimFlags.TemporaryOnRez);
AttachToBackup();
m_scene.EventManager.TriggerParcelPrimCountTainted();
m_rootPart.ScheduleFullUpdate();
//m_rootPart.ScheduleFullUpdate();
//m_rootPart.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.GroupPosition, SceneObjectPartSyncProperties.AttachmentPoint,
m_rootPart.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition, SceneObjectPartSyncProperties.AttachmentPoint,
SceneObjectPartSyncProperties.AttachedAvatar, SceneObjectPartSyncProperties.Flags}); //Physics properties, such as Position, OffsetPosition, etc, should be tainted in ApplyPhysics()
m_rootPart.ClearUndoState();
}
@ -1002,13 +1021,17 @@ namespace OpenSim.Region.Framework.Scenes
//m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
//AttachToBackup();
//m_rootPart.ScheduleFullUpdate();
//m_rootPart.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.GroupPosition, SceneObjectPartSyncProperties.AttachmentPoint,
m_rootPart.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition, SceneObjectPartSyncProperties.AttachmentPoint,
SceneObjectPartSyncProperties.AttachedAvatar, SceneObjectPartSyncProperties.Flags});
}
/// <summary>
///
/// </summary>
/// <param name="part"></param>
private void SetPartAsNonRoot(SceneObjectPart part)
public void SetPartAsNonRoot(SceneObjectPart part)
{
part.ParentID = m_rootPart.LocalId;
part.ClearUndoState();
@ -1174,6 +1197,17 @@ namespace OpenSim.Region.Framework.Scenes
{
SceneObjectPart part = parts[i];
//DSG SYNC: object remove should be handled through RegionSyncModule
/*
// REGION SYNC
if (Scene.IsSyncedServer())
{
Scene.RegionSyncServerModule.DeleteObject(part.RegionHandle, part.LocalId, part);
//return;
}
* */
//end of DSG SYNC
Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
if (avatar.ParentID == LocalId)
@ -1241,7 +1275,9 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.RemoveGroupTarget(this);
}
ScheduleGroupForFullUpdate();
//ScheduleGroupForFullUpdate();
ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){ SceneObjectPartSyncProperties.Flags, SceneObjectPartSyncProperties.LocalFlags,
SceneObjectPartSyncProperties.AggregateScriptEvents}); //do we also need to synchronize SOG properties such as m_scriptListens_atRotTarget? (does any acotr other than script engine care about it?)
}
public void SetText(string text, Vector3 color, double alpha)
@ -1253,7 +1289,8 @@ namespace OpenSim.Region.Framework.Scenes
Text = text;
HasGroupChanged = true;
m_rootPart.ScheduleFullUpdate();
//m_rootPart.ScheduleFullUpdate();
m_rootPart.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() {SceneObjectPartSyncProperties.Text, SceneObjectPartSyncProperties.Color});
}
/// <summary>
@ -1315,6 +1352,14 @@ namespace OpenSim.Region.Framework.Scenes
return;
}
//DSG SYNC
//if we are doing sync across different sync nodes, and are not told to persist the state, don't do anything (only persistence actor will do it)
if (m_scene.RegionSyncModule != null && !ToPersistObjectState)
{
return;
}
//end of DSG SYNC
// Since this is the top of the section of call stack for backing up a particular scene object, don't let
// any exception propogate upwards.
try
@ -1483,6 +1528,7 @@ namespace OpenSim.Region.Framework.Scenes
part.PhysActor.IsPhysical,
newPart.LocalId);
newPart.PhysActor.UUID = part.UUID;
newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
}
}
@ -1493,7 +1539,8 @@ namespace OpenSim.Region.Framework.Scenes
dupe.HasGroupChanged = true;
dupe.AttachToBackup();
ScheduleGroupForFullUpdate();
//ScheduleGroupForFullUpdate();
ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.FullUpdate});
}
return dupe;
@ -1746,7 +1793,8 @@ namespace OpenSim.Region.Framework.Scenes
ApplyNextOwnerPermissions();
}
part.ScheduleFullUpdate();
//part.ScheduleFullUpdate();
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() {SceneObjectPartSyncProperties.OwnerID, SceneObjectPartSyncProperties.GroupID, SceneObjectPartSyncProperties.LastOwnerID});
}
/// <summary>
@ -1873,33 +1921,54 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary>
/// Schedule a full update for this scene object
/// </summary>
public void ScheduleGroupForFullUpdate()
//public void ScheduleGroupForFullUpdate()
public void ScheduleGroupForFullUpdate(List<SceneObjectPartSyncProperties> updatedProperties)
{
// if (IsAttachment)
// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
checkAtTargets();
RootPart.ScheduleFullUpdate();
//RootPart.ScheduleFullUpdate();
RootPart.ScheduleFullUpdate(updatedProperties);
//For group properties, we only need to send it once per SOG,
//hence remove them from the updatedProperties for other parts
List<SceneObjectPartSyncProperties> otherPartsUpdatedProperties = updatedProperties;
if (updatedProperties!=null)
{
HashSet<SceneObjectPartSyncProperties> hashedList = new HashSet<SceneObjectPartSyncProperties>(updatedProperties);
foreach (SceneObjectPartSyncProperties groupProperty in SceneObjectPart.GetGroupProperties())
{
if (updatedProperties.Contains(groupProperty))
{
hashedList.Remove(groupProperty);
}
}
otherPartsUpdatedProperties = new List<SceneObjectPartSyncProperties>(hashedList);
}
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
{
SceneObjectPart part = parts[i];
if (part != RootPart)
part.ScheduleFullUpdate();
//part.ScheduleFullUpdate();
part.ScheduleFullUpdate(otherPartsUpdatedProperties);
}
}
/// <summary>
/// Schedule a terse update for this scene object
/// </summary>
public void ScheduleGroupForTerseUpdate()
//public void ScheduleGroupForTerseUpdate()
public void ScheduleGroupForTerseUpdate(List<SceneObjectPartSyncProperties> updatedProperties)
{
// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID);
// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID);
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
parts[i].ScheduleTerseUpdate();
//parts[i].ScheduleTerseUpdate();
parts[i].ScheduleTerseUpdate(updatedProperties);
}
/// <summary>
@ -2057,9 +2126,9 @@ namespace OpenSim.Region.Framework.Scenes
// objectGroup.RootPart.SendScheduledUpdates();
//}
// m_log.DebugFormat(
// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
//m_log.DebugFormat(
// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
SceneObjectPart linkPart = objectGroup.m_rootPart;
@ -2130,7 +2199,7 @@ namespace OpenSim.Region.Framework.Scenes
objectGroup.m_parts.Clear();
// Can't do this yet since backup still makes use of the root part without any synchronization
// objectGroup.m_rootPart = null;
// objectGroup.m_rootPart = null;
AttachToBackup();
@ -2141,6 +2210,13 @@ namespace OpenSim.Region.Framework.Scenes
//HasGroupChanged = true;
//ScheduleGroupForFullUpdate();
//DSG SYNC
//The DeleteObject message will be enqueued to be sent out by another thread, and the call will return quickly.
//if (m_scene.RegionSyncModule != null)
// m_scene.RegionSyncModule.SendDeleteObject(objectGroup, true);
//end of DSG SYNC
}
/// <summary>
@ -2242,7 +2318,11 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
m_scene.AddNewSceneObject(objectGroup, true);
//m_scene.AddNewSceneObject(objectGroup, true);
//DSG SYNC: calling AddNewSceneObjectByDelink, so that later on we know
//the "new" object is added by delink operation, no need to send sync
//message of NewObject
m_scene.AddNewSceneObjectByDelink(objectGroup, true, true);
if (sendEvents)
linkPart.TriggerScriptChangedEvent(Changed.LINK);
@ -2803,7 +2883,14 @@ namespace OpenSim.Region.Framework.Scenes
//we need to do a terse update even if the move wasn't allowed
// so that the position is reset in the client (the object snaps back)
ScheduleGroupForTerseUpdate();
//ScheduleGroupForTerseUpdate();
//List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.GroupPosition };
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition };
if (IsAttachment)
{
updatedProperties.Add(SceneObjectPartSyncProperties.AttachedPos);
}
ScheduleGroupForTerseUpdate(updatedProperties);
}
/// <summary>
@ -2876,7 +2963,9 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = newPos;
HasGroupChanged = true;
ScheduleGroupForTerseUpdate();
//ScheduleGroupForTerseUpdate();
//ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Position, SceneObjectPartSyncProperties.OffsetPosition});
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition, SceneObjectPartSyncProperties.OffsetPosition });
}
public void OffsetForNewRegion(Vector3 offset)
@ -2913,7 +3002,18 @@ namespace OpenSim.Region.Framework.Scenes
}
HasGroupChanged = true;
ScheduleGroupForTerseUpdate();
//ScheduleGroupForTerseUpdate();
//DSG SYNC
//Above actions only update m_rootPart's RotationOffset, and m_rootPart.UpdateRotation will taint RotationOffset as updated
if (actor != null)
{
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() {SceneObjectPartSyncProperties.RotationOffset, SceneObjectPartSyncProperties.Orientation });
}
else
{
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.RotationOffset });
}
//end DSG SYNC
}
/// <summary>
@ -2945,7 +3045,19 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = pos;
HasGroupChanged = true;
ScheduleGroupForTerseUpdate();
//DSG SYNC
if (actor != null)
{
//RotationOffset is only updated for m_rootPart, and m_rootPart.UpdateRotation should already taint RotationOffset as updated
//ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.Position, SceneObjectPartSyncProperties.Orientation });
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition, SceneObjectPartSyncProperties.Orientation });
}
else
{
//ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.Position });
ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AbsolutePosition});
}
//ScheduleGroupForTerseUpdate();
RootPart.IgnoreUndoUpdate = false;
}
@ -3047,7 +3159,8 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion newRot = primsRot * oldParentRot;
newRot *= Quaternion.Inverse(axRot);
prim.RotationOffset = newRot;
prim.ScheduleTerseUpdate();
prim.ScheduleTerseUpdate(new List<SceneObjectPartSyncProperties>(){ SceneObjectPartSyncProperties.RotationOffset, SceneObjectPartSyncProperties.OffsetPosition});
//prim.ScheduleTerseUpdate();
prim.IgnoreUndoUpdate = false;
}
}
@ -3062,7 +3175,8 @@ namespace OpenSim.Region.Framework.Scenes
// }
// }
m_rootPart.ScheduleTerseUpdate();
m_rootPart.ScheduleTerseUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.RotationOffset});
//m_rootPart.ScheduleTerseUpdate();
// m_log.DebugFormat(
// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@ -3390,6 +3504,460 @@ namespace OpenSim.Region.Framework.Scenes
SetFromItemID(uuid);
}
#endregion
#region DSG SYNC
private bool m_toPersistObjectState = false;
public bool ToPersistObjectState
{
get { return m_toPersistObjectState; }
set { m_toPersistObjectState = value; }
}
//update the existing copy of the object with updated properties in 'updatedSog'
//NOTE: updates on script content are handled seperately (e.g. user edited the script and saved it) -- SESyncServerOnUpdateScript(), a handler of EventManager.OnUpdateScript
//public void UpdateObjectProperties(SceneObjectGroup updatedSog)
/*
/// <summary>
/// Update the existing copy of the object with updated properties in 'updatedSog'. For now we update
/// all properties. Later on this should be edited to allow only updating a bucket of properties.
/// </summary>
/// <param name="updatedSog"></param>
/// <returns></returns>
public Scene.ObjectUpdateResult UpdateObjectGroupBySync(SceneObjectGroup updatedSog)
{
//This GroupID check should be done by the actor who initiates the object update
//if (!this.GroupID.Equals(updatedSog.GroupID))
// return Scene.ObjectUpdateResult.Error;
////////////////////////////////////////////////////////////////////////////////////////////////////
//NOTE!!!
//We do not want to simply call SceneObjectGroup.Copy here to clone the object:
//the prims (SceneObjectParts) in updatedSog are different instances than those in the local copy,
//and we want to preserve the references to the prims in this local copy, especially for scripts
//of each prim, where the scripts have references to the local copy. If the local copy is replaced,
//the prims (parts) will be replaces and we need to update all the references that were pointing to
//the previous prims.
////////////////////////////////////////////////////////////////////////////////////////////////////
Scene.ObjectUpdateResult groupUpdateResult = Scene.ObjectUpdateResult.Unchanged;
Dictionary<UUID, SceneObjectPart> updatedParts = new Dictionary<UUID, SceneObjectPart>();
lock (m_parts.SyncRoot)
{
//foreach (KeyValuePair<UUID, SceneObjectPart> pair in updatedSog.Parts)
Dictionary<UUID, SceneObjectPart> remainedParts = new Dictionary<UUID, SceneObjectPart>();
Dictionary<UUID, SceneObjectPart> removedParts = new Dictionary<UUID, SceneObjectPart>();
Dictionary<UUID, SceneObjectPart> newParts = new Dictionary<UUID, SceneObjectPart>();
//Compare the parts in updatedSog and sort them into remained/removed/newParts groups
foreach (SceneObjectPart updatedPart in updatedSog.Parts)
{
UUID partUUID = updatedPart.UUID;
if (ContainsPart(partUUID))
{
SceneObjectPart localPart = GetChildPart(partUUID);
remainedParts.Add(partUUID, localPart);
}
else
{
//in case the part is in the SceneGraph already (e.g. LinkObject event)
SceneObjectPart localPart = m_scene.GetSceneObjectPart(partUUID);
if (localPart != null)
{
//newParts.Add(partUUID, localPart);
//we should simply add the part into the object, sync-protocol should send another messge to soft-delete the previous group the part was in
AddPart(localPart);
//SceneGraph.GetGroupByPrim will corrent the mapping of <part,group> once it is called.
}
else
{
//This shall not happen, but wired synchronization timing might lead here
newParts.Add(partUUID, updatedPart);
}
}
}
foreach (SceneObjectPart localPart in this.Parts)
{
if (!remainedParts.ContainsKey(localPart.UUID))
removedParts.Add(localPart.UUID, localPart);
}
//For new parts or removed parts, they should be empty except maybe in some wired timing conditions (TO BE VALIDATED)
//Add in new parts
foreach (SceneObjectPart newPart in newParts.Values)
{
//AddPart(newPart);
m_log.Warn("UpdateObjectGroupBySync: prim " + newPart.UUID + " a brand new part, not in any SceneObjectGroup yet:: not supposed to happen. Checking on sync message time!!!!!");
AddNewPart(newPart);
}
//remove parts that are no longer in the group -- !!!!! need to further test how to do correct book-keeping and synchornized with other actors !!!!!!!!
foreach (SceneObjectPart rmPart in removedParts.Values)
{
//m_log.Warn("UpdateObjectGroupBySync: prim " + rmPart.UUID + " no longer in SceneObjectGroup " + this.UUID + ":: not supposed to happen. Checking on sync message time!!!!!");
//If we send out DelinkObject message right after the delink operation at the initiating actor and before any updates of the objects involved
//have been sent out, this shall not happen. Let's worry about this later if it does appear occasionally.
DelinkFromGroupBySync(rmPart, true);
}
if (newParts.Count > 0 || removedParts.Count > 0)
{
groupUpdateResult = Scene.ObjectUpdateResult.Updated;
}
//now update properties of the parts
foreach (SceneObjectPart part in this.Parts)
{
Scene.ObjectUpdateResult partUpdateResult = Scene.ObjectUpdateResult.Unchanged;
SceneObjectPart updatedPart = updatedSog.GetChildPart(part.UUID);
partUpdateResult = part.UpdateAllProperties(updatedPart);
if (partUpdateResult != Scene.ObjectUpdateResult.Unchanged)
{
groupUpdateResult = partUpdateResult;
}
}
//Just to make sure the parts each has the right localID of the rootpart
UpdateParentIDs();
}
//Schedule updates to be sent out, if the local copy has just been updated
//(1) if we are debugging the actor with a viewer attaching to it,
//we need to schedule updates to be sent to the viewer.
//(2) or if we are a relaying node to relay updates, we need to forward the updates.
//NOTE: LastUpdateTimeStamp and LastUpdateActorID should be kept the same as in the received copy of the object.
if (groupUpdateResult == Scene.ObjectUpdateResult.Updated)
{
ScheduleGroupForFullUpdate_SyncInfoUnchanged();
}
//debug the update result
if (groupUpdateResult == Scene.ObjectUpdateResult.Updated)
{
DebugObjectUpdateResult();
}
return groupUpdateResult;
}
*/
public string DebugObjectUpdateResult()
{
//m_log.Debug("ObjectGroup " + UUID + " updated. Rootpart: " +m_rootPart.DebugObjectPartProperties());
string sogDebug = "ObjectGroup " + UUID + ".\n Rootpart: " + m_rootPart.DebugObjectPartProperties();
int partNum = 1;
foreach (SceneObjectPart part in Parts)
{
if (part.UUID != m_rootPart.UUID)
{
//m_log.Debug("part " + partNum + ", " + part.DebugObjectPartProperties());
sogDebug += "\n"+part.DebugObjectPartProperties();
partNum++;
}
}
return sogDebug;
}
private void AddNewPart(SceneObjectPart newPart)
{
//set the parent relationship
AddPart(newPart);
m_scene.AddNewSceneObjectPartBySync(newPart, this);
}
//Similar actions with DelinkFromGroup, except that m_scene.AddNewSceneObjectBySync is called
public SceneObjectGroup DelinkFromGroupBySync(SceneObjectPart delinkPart, bool sendEvents)
{
m_log.DebugFormat(
"[SCENE OBJECT GROUP]: Delinking part {0}, {1}, {4} from group with root part {2}, {3}",
delinkPart.Name, delinkPart.UUID, RootPart.Name, RootPart.UUID, delinkPart.LocalId);
SceneObjectPartBase linkPart = (SceneObjectPartBase)delinkPart;
linkPart.ClearUndoState();
Quaternion worldRot = linkPart.GetWorldRotation();
// Remove the part from this object
lock (m_parts.SyncRoot)
{
m_parts.Remove(linkPart.UUID);
SceneObjectPart[] parts = m_parts.GetArray();
if (parts.Length == 1 && RootPart != null)
{
// Single prim left
RootPart.LinkNum = 0;
}
else
{
for (int i = 0; i < parts.Length; i++)
{
SceneObjectPartBase part = (SceneObjectPartBase)parts[i];
if (part.LinkNum > linkPart.LinkNum)
{
part.LinkNum--;
}
}
}
}
linkPart.ParentID = 0; //ParentID is a value set only locally and ignored in synchronization, so no need to set its value
linkPart.LinkNum = 0;
if (linkPart.PhysActor != null)
{
m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
}
// We need to reset the child part's position
// ready for life as a separate object after being a part of another object
Quaternion parentRot = m_rootPart.RotationOffset;
Vector3 axPos = linkPart.OffsetPosition;
axPos *= parentRot;
linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z);
linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
linkPart.OffsetPosition = new Vector3(0, 0, 0);
linkPart.RotationOffset = worldRot;
//SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
bool newGroupBySync = true;
SceneObjectGroup objectGroup = new SceneObjectGroup(delinkPart, newGroupBySync);
m_scene.AddNewSceneObjectBySync(objectGroup);
if (sendEvents)
linkPart.TriggerScriptChangedEvent(Changed.LINK);
linkPart.Rezzed = RootPart.Rezzed;
// When we delete a group, we currently have to force persist to the database if the object id has changed
// (since delete works by deleting all rows which have a given object id)
objectGroup.HasGroupChangedDueToDelink = true;
return objectGroup;
}
/// <summary>
/// Set a part to act as the root part for this scene object, in which SetProperty("LinkNum",) is called instead of "LinkNum=".
/// </summary>
/// <param name="part"></param>
public void SetRootPartBySync(SceneObjectPart part)
{
if (part == null)
throw new ArgumentNullException("Cannot give SceneObjectGroup a null root SceneObjectPart");
part.SetParent(this);
m_rootPart = part;
if (!IsAttachment)
part.ParentID = 0;
// part.SetProperty("LinkNum", 0);
((SceneObjectPartBase)part).LinkNum = 0;
m_parts.Add(m_rootPart.UUID, m_rootPart);
}
public void ScheduleGroupForFullUpdate_SyncInfoUnchanged()
{
//if (IsAttachment)
// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
checkAtTargets();
RootPart.ScheduleFullUpdate_SyncInfoUnchanged();
lock (m_parts)
{
foreach (SceneObjectPart part in this.Parts)
{
if (part != RootPart)
part.ScheduleFullUpdate_SyncInfoUnchanged();
}
}
}
//Similar to LinkToGroup(), except that not calling RegionSyncModule.SendDeleteObject
public void LinkToGroupBySync(SceneObjectGroup objectGroup)
{
SceneObjectPartBase linkPart = (SceneObjectPartBase)objectGroup.m_rootPart;
Vector3 oldGroupPosition = linkPart.GroupPosition;
Quaternion oldRootRotation = linkPart.RotationOffset;
linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
linkPart.GroupPosition = AbsolutePosition;
Vector3 axPos = linkPart.OffsetPosition;
Quaternion parentRot = m_rootPart.RotationOffset;
axPos *= Quaternion.Inverse(parentRot);
linkPart.OffsetPosition = axPos;
Quaternion oldRot = linkPart.RotationOffset;
Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
linkPart.RotationOffset = newRot;
//ParentID is only valid locally, so remote value is ignored and no syncinfo will be modified
linkPart.ParentID = m_rootPart.LocalId;
if (m_rootPart.LinkNum == 0)
((SceneObjectPartBase)m_rootPart).LinkNum = 1;
//m_rootPart.SetProperty("LinkNum",1);
lock (m_parts.SyncRoot)
{
m_parts.Add(linkPart.UUID, (SceneObjectPart) linkPart);
// Insert in terms of link numbers, the new links
// before the current ones (with the exception of
// the root prim. Shuffle the old ones up
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
{
SceneObjectPartBase part = (SceneObjectPartBase)parts[i];
if (part.LinkNum != 1)
{
// Don't update root prim link number
part.LinkNum += objectGroup.PrimCount;
}
}
linkPart.LinkNum = 2;
linkPart.SetParent(this);
linkPart.CreateSelected = true;
//if (linkPart.PhysActor != null)
//{
// m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
//linkPart.PhysActor = null;
//}
//TODO: rest of parts
int linkNum = 3;
SceneObjectPart[] ogParts = objectGroup.Parts;
for (int i = 0; i < ogParts.Length; i++)
{
SceneObjectPart part = ogParts[i];
if (part.UUID != objectGroup.m_rootPart.UUID)
LinkNonRootPartBySync(part, oldGroupPosition, oldRootRotation, linkNum++);
part.ClearUndoState();
}
}
m_scene.UnlinkSceneObject(objectGroup, true);
objectGroup.m_isDeleted = true;
objectGroup.m_parts.Clear();
// Can't do this yet since backup still makes use of the root part without any synchronization
// objectGroup.m_rootPart = null;
AttachToBackup();
// Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
// position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
// unmoved prims!
ResetChildPrimPhysicsPositions();
}
private void LinkNonRootPartBySync(SceneObjectPart linkPart, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum)
{
Quaternion parentRot = oldGroupRotation;
Quaternion oldRot = linkPart.RotationOffset;
Quaternion worldRot = parentRot * oldRot;
parentRot = oldGroupRotation;
Vector3 axPos = linkPart.OffsetPosition;
SceneObjectPartBase part = (SceneObjectPartBase)linkPart;
axPos *= parentRot;
part.OffsetPosition = axPos;
part.GroupPosition = oldGroupPosition + part.OffsetPosition;
part.OffsetPosition = Vector3.Zero;
part.RotationOffset = worldRot;
part.SetParent(this);
part.ParentID = m_rootPart.LocalId;
m_parts.Add(part.UUID, linkPart);
part.LinkNum = linkNum;
part.OffsetPosition = part.GroupPosition - AbsolutePosition;
Quaternion rootRotation = m_rootPart.RotationOffset;
Vector3 pos = part.OffsetPosition;
pos *= Quaternion.Inverse(rootRotation);
part.OffsetPosition = pos;
parentRot = m_rootPart.RotationOffset;
oldRot = part.RotationOffset;
Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
part.RotationOffset = newRot;
}
public void UpdatePrimFlagsBySync(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVolumeDetect)
{
SceneObjectPart selectionPart = GetChildPart(localID);
if (IsTemporary)
{
DetachFromBackup();
// Remove from database and parcel prim count
//
m_scene.DeleteFromStorage(UUID);
m_scene.EventManager.TriggerParcelPrimCountTainted();
}
if (selectionPart != null)
{
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
{
SceneObjectPart part = parts[i];
if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
part.Scale.Z > m_scene.RegionInfo.PhysPrimMax)
{
UsePhysics = false; // Reset physics
break;
}
}
for (int i = 0; i < parts.Length; i++)
parts[i].UpdatePrimFlagsBySync(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
}
}
public void ScriptSetVolumeDetectBySync(bool SetVD)
{
//m_log.DebugFormat("ScriptSetVolumeDetectBySync called for SOG {0}", Name);
bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
UpdatePrimFlagsBySync(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, SetVD);
}
///////////////////////////////////////////////////////////////////////
// Per SOP property based sync
///////////////////////////////////////////////////////////////////////
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,7 @@ using OpenSim.Region.Framework.Scenes.Serialization;
namespace OpenSim.Region.Framework.Scenes
{
public class SceneObjectPartInventory : IEntityInventory
//public class SceneObjectPartInventoryBase : IEntityInventory
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -53,6 +54,7 @@ namespace OpenSim.Region.Framework.Scenes
/// The part to which the inventory belongs.
/// </value>
private SceneObjectPart m_part;
//private SceneObjectPartBase m_part;
/// <summary>
/// Serial count for inventory file , used to tell if inventory has changed
@ -99,6 +101,7 @@ namespace OpenSim.Region.Framework.Scenes
/// A <see cref="SceneObjectPart"/>
/// </param>
public SceneObjectPartInventory(SceneObjectPart part)
//public SceneObjectPartInventoryBase(SceneObjectPartBase part)
{
m_part = part;
}
@ -291,7 +294,7 @@ namespace OpenSim.Region.Framework.Scenes
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
m_part.ParentGroup.AddActiveScriptCount(1);
m_part.ScheduleFullUpdate();
m_part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Flags, SceneObjectPartSyncProperties.TaskInventory});
return;
}
@ -319,7 +322,7 @@ namespace OpenSim.Region.Framework.Scenes
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
m_part.ParentGroup.AddActiveScriptCount(1);
m_part.ScheduleFullUpdate();
m_part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Flags, SceneObjectPartSyncProperties.TaskInventory});
}
}
}
@ -541,6 +544,9 @@ namespace OpenSim.Region.Framework.Scenes
//m_inventorySerial += 2;
HasInventoryChanged = true;
m_part.ParentGroup.HasGroupChanged = true;
//DSG SYNC: add ScheduleFullUpdate to enable synchronization across actors
m_part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.TaskInventory, SceneObjectPartSyncProperties.InventorySerial});
}
/// <summary>
@ -689,7 +695,8 @@ namespace OpenSim.Region.Framework.Scenes
return UpdateInventoryItem(item, fireScriptEvents, true);
}
public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
//public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
public virtual bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
{
TaskInventoryItem it = GetInventoryItem(item.ItemID);
if (it != null)
@ -720,6 +727,9 @@ namespace OpenSim.Region.Framework.Scenes
{
HasInventoryChanged = true;
m_part.ParentGroup.HasGroupChanged = true;
//DSG
m_part.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.TaskInventory});
}
return true;
@ -763,7 +773,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!ContainsScripts())
m_part.RemFlag(PrimFlags.Scripted);
m_part.ScheduleFullUpdate();
m_part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.TaskInventory});
return type;
@ -1146,5 +1156,130 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
#region REGION SYNC
public void SuspendScripts()
{
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
if (engines == null)
return;
lock (m_items)
{
foreach (TaskInventoryItem item in m_items.Values)
{
if (item.InvType == (int)InventoryType.LSL)
{
foreach (IScriptModule engine in engines)
{
if (engine != null)
{
if (item.OwnerChanged)
engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
item.OwnerChanged = false;
engine.SuspendScript(item.ItemID);
}
}
}
}
}
}
#endregion REGION SYNC
#region DSG SYNC
/// <summary>
/// Update an existing inventory item.
/// </summary>
/// <param name="item">The updated item. An item with the same id must already exist
/// in this prim's inventory.</param>
/// <returns>false if the item did not exist, true if the update occurred successfully</returns>
public bool UpdateInventoryItemBySync(TaskInventoryItem item)
{
return UpdateInventoryItemBySync(item, true, true);
}
//Similar to UpdateInventoryItem except that ScheduleSyncUpdate is not triggered
private bool UpdateInventoryItemBySync(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
{
TaskInventoryItem it = GetInventoryItem(item.ItemID);
if (it != null)
{
// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
item.ParentID = m_part.UUID;
item.ParentPartID = m_part.UUID;
// If group permissions have been set on, check that the groupID is up to date in case it has
// changed since permissions were last set.
if (item.GroupPermissions != (uint)PermissionMask.None)
item.GroupID = m_part.GroupID;
if (item.AssetID == UUID.Zero)
item.AssetID = it.AssetID;
lock (m_items)
{
m_items[item.ItemID] = item;
m_inventorySerial++;
}
if (fireScriptEvents)
m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
if (considerChanged)
{
HasInventoryChanged = true;
m_part.ParentGroup.HasGroupChanged = true;
}
return true;
}
else
{
m_log.ErrorFormat(
"[PRIM INVENTORY]: " +
"Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
item.ItemID, m_part.Name, m_part.UUID,
m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
}
return false;
}
#endregion DSG SYNC
}
/*
#region DSG SYNC
public class SceneObjectPartInventory : SceneObjectPartInventoryBase
{
private SceneObjectPart m_part;
public SceneObjectPartInventory(SceneObjectPart part):base((SceneObjectPartBase) part)
{
m_part = part;
}
new protected internal uint Serial
{
get { return base.Serial; }
set
{
base.Serial = value;
}
}
public override bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
{
if (base.UpdateInventoryItem(item, fireScriptEvents, considerChanged))
{
m_part.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.TaskInventory, SceneObjectPartSyncProperties.InventorySerial });
return true;
}
else
return false;
}
}
#endregion
* */
}

View File

@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes
{
// ~ScenePresence()
// {
// m_log.Debug("[ScenePresence] Destructor called");
// m_log.Debug("[SCENE PRESENCE] Destructor called");
// }
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -125,6 +125,9 @@ namespace OpenSim.Region.Framework.Scenes
private Vector3 m_lastPosition;
private Quaternion m_lastRotation;
private Vector3 m_lastVelocity;
// RA: following kludge lets us remember if we need to send a full update
// Used in RegionSyncServerModule
public uint lastSentParentID;
//private int m_lastTerseSent;
private bool m_updateflag;
@ -390,6 +393,18 @@ namespace OpenSim.Region.Framework.Scenes
set { m_allowMovement = value; }
}
// Added for region sync module.
// Should not rely on a physics actor like so many of these params seem to
public bool Flying
{
get
{
if (PhysicsActor != null)
return PhysicsActor.Flying;
return false;
}
}
public bool SetAlwaysRun
{
get
@ -438,6 +453,7 @@ namespace OpenSim.Region.Framework.Scenes
public IClientAPI ControllingClient
{
get { return m_controllingClient; }
set { m_controllingClient = value; }
}
public IClientCore ClientView
@ -505,7 +521,7 @@ namespace OpenSim.Region.Framework.Scenes
}
catch (Exception e)
{
m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message);
m_log.Error("[SCENE PRESENCE]: ABSOLUTE POSITION " + e.Message);
}
}
@ -542,10 +558,12 @@ namespace OpenSim.Region.Framework.Scenes
{
lock (m_scene.SyncRoot)
actor.Velocity = value;
m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
}
catch (Exception e)
{
m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message);
m_log.Error("[SCENE PRESENCE]: VELOCITY " + e.Message);
}
}
@ -592,6 +610,20 @@ namespace OpenSim.Region.Framework.Scenes
set { m_health = value; }
}
private bool m_isSyncedAvatar;
public bool IsSyncedAvatar
{
get { return m_isSyncedAvatar; }
set { m_isSyncedAvatar = value; }
}
private bool m_isBalancing;
public bool IsBalancing
{
get { return m_isBalancing; }
set { m_isBalancing = value; }
}
/// <summary>
/// These are the region handles known by the avatar.
/// </summary>
@ -770,14 +802,25 @@ namespace OpenSim.Region.Framework.Scenes
public void RegisterToEvents()
{
m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
//m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
// REGION SYNC
// if (m_scene.IsSyncedServer() || m_scene.RegionSyncEnabled == false)
if (m_scene.IsSyncedServer())
{
// These client messages will not be handled by client managers but instead
// they are caught by the RegionSyncClient module and passed up to the auth sim
m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
//m_controllingClient.OnSetAppearance += SetAppearance;
m_log.DebugFormat("[SCENE PRESENCE]: Setting local handler for HandleAgentRequestSit"); //RA
m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
m_controllingClient.OnAgentSit += HandleAgentSit;
m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
m_controllingClient.OnStartAnim += HandleStartAnim;
m_controllingClient.OnStopAnim += HandleStopAnim;
}
m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
//m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
m_controllingClient.OnAutoPilotGo += DoAutoPilot;
m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
@ -1003,7 +1046,7 @@ namespace OpenSim.Region.Framework.Scenes
Animator.ResetAnimations();
// m_log.DebugFormat(
// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
// Name, UUID, m_scene.RegionInfo.RegionName);
// Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
@ -1056,6 +1099,11 @@ namespace OpenSim.Region.Framework.Scenes
}
SendTerseUpdateToAllClients();
//This should only happen on PSA and when the teleport is within the same region.
//If teleport is to a remote region, CM will handle it and PSA should be
//executing inside this function.
SendTeleportUpdate();
}
public void TeleportWithMomentum(Vector3 pos)
@ -1183,14 +1231,18 @@ namespace OpenSim.Region.Framework.Scenes
m_callbackURI = null;
}
//m_log.DebugFormat("Completed movement");
m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
SendInitialData();
// Create child agents in neighbouring regions
if (!m_isChildAgent)
//if (!m_isChildAgent && !m_scene.IsAuthoritativeScene())
if (!m_isChildAgent && !IsSyncedAvatar)
{
m_log.DebugFormat("[SCENE PRESENCE]: Requesting neighbouring children. cagent={0}",
m_isChildAgent.ToString());
IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
if (m_agentTransfer != null)
m_agentTransfer.EnableChildAgents(this);
@ -1249,6 +1301,39 @@ namespace OpenSim.Region.Framework.Scenes
}
}
// Move the avatar to a specific position, velocity and rotation and mark it as changed
// Mostly copied from HandleAgentUpdate
public void MoveTo(Vector3 pos, Vector3 vel, Quaternion rot)
{
++m_movementUpdateCount;
if (m_movementUpdateCount < 1)
m_movementUpdateCount = 1;
#region Sanity Checking
// This is irritating. Really.
if (!AbsolutePosition.IsFinite())
{
RemoveFromPhysicalScene();
m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
m_pos = m_LastFinitePos;
if (!m_pos.IsFinite())
{
m_pos.X = 127f;
m_pos.Y = 127f;
m_pos.Z = 127f;
m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
}
AddToPhysicalScene(false);
}
else
{
m_LastFinitePos = m_pos;
}
#endregion Sanity Checking
}
/// <summary>
/// This is the event handler for client movement. If a client is moving, this event is triggering.
/// </summary>
@ -1569,7 +1654,7 @@ namespace OpenSim.Region.Framework.Scenes
catch (Exception e)
{
//Avoid system crash, can be slower but...
m_log.DebugFormat("Crash! {0}", e.ToString());
m_log.DebugFormat("[SCENE PRESENCE] Crash! {0}", e.ToString());
}
}
}
@ -1605,7 +1690,7 @@ namespace OpenSim.Region.Framework.Scenes
{
// m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
// m_log.DebugFormat(
// "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
// "[SCENE PRESENCE] In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
AddNewMovement(agent_control_v3, q);
@ -1674,7 +1759,7 @@ namespace OpenSim.Region.Framework.Scenes
catch (Exception ex)
{
//Why did I get this error?
m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex);
m_log.Error("[SCENE PRESENCE]: DoMoveToPosition" + ex);
}
}
@ -2266,13 +2351,13 @@ namespace OpenSim.Region.Framework.Scenes
/// Rotate the avatar to the given rotation and apply a movement in the given relative vector
/// </summary>
/// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
/// <param name="rotation">The direction in which this avatar should now face.
/// <param name="rotation">The direction in which this avatar should now face.</param>
public void AddNewMovement(Vector3 vec, Quaternion rotation)
{
if (m_isChildAgent)
{
// WHAT???
m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!");
m_log.Debug("[SCENE PRESENCE]: AddNewMovement() called on child agent, making root agent!");
return;
}
@ -2388,7 +2473,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 pos = m_pos;
pos.Z += m_appearance.HipOffset;
//m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
//m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
remoteClient.SendPrimUpdate(
this,
@ -2411,6 +2496,16 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void SendTerseUpdateToAllClients()
{
// m_log.DebugFormat("[SCENE PRESENCE]: TerseUpdate: UUID={0}, pos={1}", m_physicsActor.UUID.ToString(), m_physicsActor.Position.ToString());
// REGION SYNC
if (m_scene.IsSyncedServer())
{
m_scene.RegionSyncServerModule.QueuePresenceForTerseUpdate(this);
// this.PhysicsRequestingTerseUpdate();
// m_scene.RegionSyncModule.QueueSceneObjectPartForUpdate(this);
return;
}
int currentTick = Util.EnvironmentTickCount();
// Decrease update frequency when avatar is moving but velocity is
@ -2475,6 +2570,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
private void SendInitialData()
{
m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID);
// Moved this into CompleteMovement to ensure that m_appearance is initialized before
// the inventory arrives
// m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
@ -2489,7 +2585,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
m_log.WarnFormat("[SCENEPRESENCE]: AvatarFactory not set for {0}", Name);
m_log.WarnFormat("[SCENE PRESENCE]: AvatarFactory not set for {0}", Name);
}
// If we aren't using a cached appearance, then clear out the baked textures
@ -2515,7 +2611,7 @@ namespace OpenSim.Region.Framework.Scenes
// If the avatars baked textures are all in the cache, then we have a
// complete appearance... send it out, if not, then we'll send it when
// the avatar finishes updating its appearance
SendAppearanceToAllOtherAgents();
m_scene.AvatarFactory.QueueAppearanceSend(UUID);
}
}
@ -2525,10 +2621,19 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void SendAvatarDataToAllAgents()
{
m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID);
// REGION SYNC
// The server sends appearance to all client managers since there are no local clients
if (m_scene.IsSyncedServer())
{
m_scene.RegionSyncServerModule.SendAppearance(UUID);
return;
}
// only send update from root agents to other clients; children are only "listening posts"
if (IsChildAgent)
{
m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent");
m_log.Warn("[SCENE PRESENCE] attempt to send avatar data from a child agent");
return;
}
@ -2551,6 +2656,10 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void SendOtherAgentsAvatarDataToMe()
{
// REGION SYNC
// The server should not be doing anything via the ForEachScenePresence method
if (m_scene.IsSyncedServer())
return;
m_perfMonMS = Util.EnvironmentTickCount();
int count = 0;
@ -2578,7 +2687,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="avatar"></param>
public void SendAvatarDataToAgent(ScenePresence avatar)
{
// m_log.WarnFormat("[SP] Send avatar data from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId);
m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
avatar.ControllingClient.SendAvatarDataImmediate(this);
if (Animator != null)
@ -2591,10 +2700,18 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void SendAppearanceToAllOtherAgents()
{
m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} ({1})", Name, UUID);
// REGION SYNC
// The server should not be doing anything via the ForEachScenePresence method
if (m_scene.IsSyncedServer())
{
m_scene.RegionSyncServerModule.SendAppearance(UUID);
return;
}
// only send update from root agents to other clients; children are only "listening posts"
if (IsChildAgent)
{
m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent");
m_log.Warn("[SCENE PRESENCE] attempt to send avatar data from a child agent");
return;
}
@ -2620,6 +2737,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void SendOtherAgentsAppearanceToMe()
{
m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} ({1})", Name, UUID);
m_perfMonMS = Util.EnvironmentTickCount();
int count = 0;
@ -2636,7 +2754,6 @@ namespace OpenSim.Region.Framework.Scenes
scenePresence.SendAppearanceToAgent(this);
count++;
});
m_scene.StatsReporter.AddAgentUpdates(count);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
}
@ -2647,7 +2764,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="avatar"></param>
public void SendAppearanceToAgent(ScenePresence avatar)
{
// m_log.WarnFormat("[SP] Send appearance from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId);
m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
avatar.ControllingClient.SendAppearance(
m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes());
@ -2731,7 +2848,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <remarks>
/// Also removes the avatar from the physical scene if transit has started.
/// </remarks>
protected void CheckForBorderCrossing()
public void CheckForBorderCrossing()
{
if (IsChildAgent)
return;
@ -3297,11 +3414,12 @@ namespace OpenSim.Region.Framework.Scenes
new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
scene.AddPhysicsActorTaint(m_physicsActor);
//m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
m_physicsActor.SubscribeEvents(500);
m_physicsActor.LocalID = LocalId;
m_physicsActor.UUID = this.UUID;
}
private void OutOfBoundsCall(Vector3 pos)
@ -3784,7 +3902,7 @@ namespace OpenSim.Region.Framework.Scenes
m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID);
return;
}
m_log.DebugFormat("[ATTACHMENT]: Rezzing attachments for scene presence {0} ({1})", Name, UUID);
List<AvatarAttachment> attachments = m_appearance.GetAttachments();
foreach (AvatarAttachment attach in attachments)
{
@ -3861,5 +3979,20 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
#region REGION SYNC
public void SendTeleportUpdate()
{
// m_log.DebugFormat("[SCENE PRESENCE]: TerseUpdate: UUID={0}, pos={1}", m_physicsActor.UUID.ToString(), m_physicsActor.Position.ToString());
// REGION SYNC
if (m_scene.IsSyncedServer())
{
m_scene.RegionSyncServerModule.SendTeleportUpdate(this);
// this.PhysicsRequestingTerseUpdate();
// m_scene.RegionSyncModule.QueueSceneObjectPartForUpdate(this);
return;
}
}
#endregion //REGION SYNC
}
}

View File

@ -57,11 +57,12 @@ namespace OpenSim.Region.Framework.Scenes
/// Add the part to the queue of parts for which we need to send an update to the client
/// </summary>
/// <param name="part"></param>
public void QueuePartForUpdate(SceneObjectPart part)
//public void QueuePartForUpdate(SceneObjectPart part)
public void QueuePartForUpdate(SceneObjectPartBase part)
{
lock (m_partsUpdateQueue)
{
m_partsUpdateQueue.Enqueue(part);
m_partsUpdateQueue.Enqueue((SceneObjectPart)part);
}
}

View File

@ -494,26 +494,31 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
private static void ProcessGroupPosition(SceneObjectPart obj, XmlTextReader reader)
{
obj.GroupPosition = Util.ReadVector(reader, "GroupPosition");
//obj.SetGroupPosition(Util.ReadVector(reader, "GroupPosition"));
}
private static void ProcessOffsetPosition(SceneObjectPart obj, XmlTextReader reader)
{
obj.OffsetPosition = Util.ReadVector(reader, "OffsetPosition"); ;
//obj.SetOffsetPosition(Util.ReadVector(reader, "OffsetPosition"));
}
private static void ProcessRotationOffset(SceneObjectPart obj, XmlTextReader reader)
{
obj.RotationOffset = Util.ReadQuaternion(reader, "RotationOffset");
//obj.SetRotationOffset(Util.ReadQuaternion(reader, "RotationOffset"));
}
private static void ProcessVelocity(SceneObjectPart obj, XmlTextReader reader)
{
obj.Velocity = Util.ReadVector(reader, "Velocity");
//obj.SetVelocity(Util.ReadVector(reader, "Velocity"));
}
private static void ProcessAngularVelocity(SceneObjectPart obj, XmlTextReader reader)
{
obj.AngularVelocity = Util.ReadVector(reader, "AngularVelocity");
//obj.SetVelocity(Util.ReadVector(reader, "AngularVelocity"));
}
private static void ProcessAcceleration(SceneObjectPart obj, XmlTextReader reader)
@ -1109,7 +1114,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
////////// Write /////////
public static void SOGToXml2(XmlTextWriter writer, SceneObjectGroup sog, Dictionary<string, object>options)
public static void SOGToXml2(XmlTextWriter writer, SceneObjectGroup sog, Dictionary<string, object> options)
{
writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
SOPToXml2(writer, sog.RootPart, options);
@ -1267,7 +1272,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString(name, flagsStr.Replace(",", ""));
}
static void WriteTaskInventory(XmlTextWriter writer, TaskInventoryDictionary tinv, Dictionary<string, object> options, Scene scene)
//DSG SYNC: make it a public function, so that we can call serialization of TaskInventory from other places
//static void WriteTaskInventory(XmlTextWriter writer, TaskInventoryDictionary tinv, Dictionary<string, object> options, Scene scene)
public static void WriteTaskInventory(XmlTextWriter writer, TaskInventoryDictionary tinv, Dictionary<string, object> options, Scene scene)
{
if (tinv.Count > 0) // otherwise skip this
{
@ -1321,7 +1328,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
}
}
static void WriteShape(XmlTextWriter writer, PrimitiveBaseShape shp, Dictionary<string, object> options)
//DSG SYNC: make it a public function, so that we can call serialization of Shape from other places
//static void WriteShape(XmlTextWriter writer, PrimitiveBaseShape shp, Dictionary<string, object> options)
public static void WriteShape(XmlTextWriter writer, PrimitiveBaseShape shp, Dictionary<string, object> options)
{
if (shp != null)
{
@ -1365,6 +1374,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("ProfileBegin", shp.ProfileBegin.ToString());
writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
//DSG SYNC: added serialization of Scale
WriteVector(writer, "Scale", shp.Scale);
//end of DSG SYNC
writer.WriteElementString("State", shp.State.ToString());
WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
@ -1496,7 +1508,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
return obj;
}
static TaskInventoryDictionary ReadTaskInventory(XmlTextReader reader, string name)
//DSG SYNC: make it public to be called outside
//static TaskInventoryDictionary ReadTaskInventory(XmlTextReader reader, string name)
public static TaskInventoryDictionary ReadTaskInventory(XmlTextReader reader, string name)
{
TaskInventoryDictionary tinv = new TaskInventoryDictionary();
@ -1542,7 +1556,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
/// <param name="name">The name of the xml element containing the shape</param>
/// <param name="errors">true if any errors were encountered during parsing, false otherwise</param>
/// <returns>The shape parsed</returns>
static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors)
//DSG SYNC: make it public to be called outside
//static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors)
public static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors)
{
errors = false;

View File

@ -31,6 +31,8 @@ using log4net;
using OpenMetaverse;
using OpenSim.Region.Framework.Interfaces;
using System.Collections.Generic;
namespace OpenSim.Region.Framework.Scenes
{
public class UndoState
@ -154,7 +156,13 @@ namespace OpenSim.Region.Framework.Scenes
part.Resize(Scale);
}
part.ParentGroup.ScheduleGroupForTerseUpdate();
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>();
updatedProperties.Add(SceneObjectPartSyncProperties.RotationOffset);
updatedProperties.Add(SceneObjectPartSyncProperties.OffsetPosition);
updatedProperties.Add(SceneObjectPartSyncProperties.Scale);
updatedProperties.Add(SceneObjectPartSyncProperties.AbsolutePosition);
part.ParentGroup.ScheduleGroupForTerseUpdate(updatedProperties);
//part.ParentGroup.ScheduleGroupForTerseUpdate();
}
else
{
@ -182,7 +190,13 @@ namespace OpenSim.Region.Framework.Scenes
part.Resize(Scale);
}
part.ScheduleTerseUpdate();
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>();
updatedProperties.Add(SceneObjectPartSyncProperties.RotationOffset);
updatedProperties.Add(SceneObjectPartSyncProperties.OffsetPosition);
updatedProperties.Add(SceneObjectPartSyncProperties.Scale);
updatedProperties.Add(SceneObjectPartSyncProperties.AbsolutePosition);
part.ScheduleTerseUpdate(updatedProperties);
//part.ScheduleTerseUpdate();
}
part.Undoing = false;
@ -208,7 +222,13 @@ namespace OpenSim.Region.Framework.Scenes
part.Resize(Scale);
}
part.ParentGroup.ScheduleGroupForTerseUpdate();
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>();
updatedProperties.Add(SceneObjectPartSyncProperties.RotationOffset);
updatedProperties.Add(SceneObjectPartSyncProperties.OffsetPosition);
updatedProperties.Add(SceneObjectPartSyncProperties.Scale);
updatedProperties.Add(SceneObjectPartSyncProperties.AbsolutePosition);
part.ParentGroup.ScheduleGroupForTerseUpdate(updatedProperties);
//part.ParentGroup.ScheduleGroupForTerseUpdate();
}
else
{
@ -221,7 +241,13 @@ namespace OpenSim.Region.Framework.Scenes
if (Scale != Vector3.Zero)
part.Resize(Scale);
part.ScheduleTerseUpdate();
List<SceneObjectPartSyncProperties> updatedProperties = new List<SceneObjectPartSyncProperties>();
updatedProperties.Add(SceneObjectPartSyncProperties.RotationOffset);
updatedProperties.Add(SceneObjectPartSyncProperties.OffsetPosition);
updatedProperties.Add(SceneObjectPartSyncProperties.Scale);
updatedProperties.Add(SceneObjectPartSyncProperties.AbsolutePosition);
part.ScheduleTerseUpdate(updatedProperties);
//part.ScheduleTerseUpdate();
}
part.Undoing = false;

View File

@ -636,6 +636,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
set { }
}
public uint MaxCoarseLocations
{
get { return 0; }
}
public uint CircuitCode
{
get { return (uint)Util.RandomClass.Next(0,int.MaxValue); }
@ -650,6 +655,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public event GenericMessage OnGenericMessage;
public event ImprovedInstantMessage OnInstantMessage;
public event ChatMessage OnChatFromClient;
public event ChatMessageRaw OnChatFromClientRaw;
public event TextureRequest OnRequestTexture;
public event RezObject OnRezObject;
public event ModifyTerrain OnModifyTerrain;
@ -670,6 +676,9 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public event RequestMapBlocks OnRequestMapBlocks;
public event RequestMapName OnMapNameRequest;
public event TeleportLocationRequest OnTeleportLocationRequest;
//DSG:
public event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
//end of DSG
public event DisconnectUser OnDisconnectUser;
public event RequestAvatarProperties OnRequestAvatarProperties;
public event SetAlwaysRun OnSetAlwaysRun;
@ -680,6 +689,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public event GenericCall1 OnCompleteMovementToRegion;
public event UpdateAgent OnPreAgentUpdate;
public event UpdateAgent OnAgentUpdate;
public event UpdateAgentRaw OnAgentUpdateRaw;
public event AgentRequestSit OnAgentRequestSit;
public event AgentSit OnAgentSit;
public event AvatarPickerRequest OnAvatarPickerRequest;

View File

@ -131,6 +131,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
set { }
}
public uint MaxCoarseLocations { get { return 0; } }
#region Internal Functions
private void SendOnChatFromClient(string message, ChatTypeEnum chatType)
@ -163,6 +165,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event GenericMessage OnGenericMessage;
public event ImprovedInstantMessage OnInstantMessage;
public event ChatMessage OnChatFromClient;
public event ChatMessageRaw OnChatFromClientRaw;
public event TextureRequest OnRequestTexture;
public event RezObject OnRezObject;
public event ModifyTerrain OnModifyTerrain;
@ -181,6 +184,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event RequestMapBlocks OnRequestMapBlocks;
public event RequestMapName OnMapNameRequest;
public event TeleportLocationRequest OnTeleportLocationRequest;
//DSG:
public event SameRegionTeleportlRequest OnSameRegionTeleportlRequest;
//end of DSG
public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
public event DisconnectUser OnDisconnectUser;
public event RequestAvatarProperties OnRequestAvatarProperties;
@ -192,6 +198,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event GenericCall1 OnCompleteMovementToRegion;
public event UpdateAgent OnPreAgentUpdate;
public event UpdateAgent OnAgentUpdate;
public event UpdateAgentRaw OnAgentUpdateRaw;
public event AgentRequestSit OnAgentRequestSit;
public event AgentSit OnAgentSit;
public event AvatarPickerRequest OnAvatarPickerRequest;

View File

@ -640,7 +640,8 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
{
s_tree.Scale += copse.m_rate;
s_tree.ParentGroup.HasGroupChanged = true;
s_tree.ScheduleFullUpdate();
//s_tree.ScheduleFullUpdate();
s_tree.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Scale});
}
}
else

View File

@ -27,7 +27,9 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
@ -36,6 +38,8 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
{
public class BasicScene : PhysicsScene
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List<BasicActor> _actors = new List<BasicActor>();
private float[] _heightMap;
@ -123,7 +127,16 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
actorPosition.X = ((int)Constants.RegionSize - 0.1f);
}
float height = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z;
float height = 25.0F;
try
{
height = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z;
}
catch (OverflowException)
{
m_log.WarnFormat("[BASICPHYSICS]: Actor out of range: {0}", actor.SOPName, actor.Position.ToString());
}
if (actor.Flying)
{
if (actor.Position.Z + (actor.Velocity.Z*timeStep) <

View File

@ -115,6 +115,49 @@ namespace OpenSim.Region.Physics.Manager
}
}
/// <summary>
/// Structure to hold previous values of the PhysicsActor. This is used to see
/// if the values changed before sending updates to the Physics Engine.
/// </summary>
public struct PhysActorLastValues
{
public uint updateTime;
public uint localID;
public Vector3 size;
public Vector3 position;
public Vector3 force;
public Vector3 velocity;
public Vector3 rotationalVelocity;
public Vector3 torque;
public Quaternion orientation;
public Boolean isPhysical;
public Boolean flying;
public double buoyancy;
public bool Changed(PhysicsActor pa)
{
bool ret = false;
if (localID != pa.LocalID) { localID = pa.LocalID; ret = true; }
if (size != pa.Size) { size = pa.Size; ret = true; }
if (!AlmostEqual(position, pa.Position)) { position = pa.Position; ret = true; }
if (!AlmostEqual(force, pa.Force)) { force = pa.Force; ret = true; }
if (!AlmostEqual(velocity, pa.Velocity)) { velocity = pa.Velocity; ret = true; }
if (!AlmostEqual(rotationalVelocity, pa.RotationalVelocity)) { rotationalVelocity = pa.RotationalVelocity; ret = true; }
if (!AlmostEqual(torque, pa.Torque)) { torque = pa.Torque; ret = true; }
if (orientation != pa.Orientation) { orientation = pa.Orientation; ret = true; }
if (isPhysical != pa.IsPhysical) { isPhysical = pa.IsPhysical; ret = true; }
if (flying != pa.Flying) { flying = pa.Flying; ret = true; }
if (buoyancy != pa.Buoyancy) { buoyancy = pa.Buoyancy; ret = true; }
return ret;
}
private bool AlmostEqual(Vector3 a, Vector3 b)
{
if (Math.Abs(a.X - b.X) > 0.01) return false;
if (Math.Abs(a.Y - b.Y) > 0.01) return false;
if (Math.Abs(a.Z - b.Z) > 0.01) return false;
return true;
}
}
public abstract class PhysicsActor
{
public delegate void RequestTerseUpdate();
@ -142,12 +185,24 @@ namespace OpenSim.Region.Physics.Manager
public abstract PrimitiveBaseShape Shape { set; }
// RA: used to be abstract but changed to allow 'get' without changing all the phys engines
uint m_baseLocalID;
public virtual uint LocalID
{
set { m_baseLocalID = value; }
get { return m_baseLocalID; }
}
public UUID m_UUID;
public virtual UUID UUID
{
set { m_UUID = value; }
get { return m_UUID; }
}
public PhysActorLastValues lastValues;
// ID of actor which last updated the values. Send if I did the change.
public string ChangingActorID = "YY";
// set to true of prim is updated
public bool SyncUpdated;
public abstract bool Grabbed { set; }
@ -222,7 +277,12 @@ namespace OpenSim.Region.Physics.Manager
public abstract Vector3 Velocity { get; set; }
public abstract Vector3 Torque { get; set; }
public abstract float CollisionScore { get; set;}
public abstract Vector3 Acceleration { get; }
// RA: used to be abstract but made virtual so 'set' does not need to be added to all phys engines
private Vector3 _acceleration;
public virtual Vector3 Acceleration {
get { return _acceleration; }
set { _acceleration = value; }
}
public abstract Quaternion Orientation { get; set; }
public abstract int PhysicsActorType { get; set; }
public abstract bool IsPhysical { get; set; }
@ -285,6 +345,7 @@ namespace OpenSim.Region.Physics.Manager
public override uint LocalID
{
set { return; }
get { return 0; }
}
public override bool Grabbed
@ -419,6 +480,7 @@ namespace OpenSim.Region.Physics.Manager
public override Vector3 Acceleration
{
get { return Vector3.Zero; }
set { }
}
public override bool IsPhysical

View File

@ -32,6 +32,7 @@ using OpenMetaverse;
using Ode.NET;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
using log4net;
namespace OpenSim.Region.Physics.OdePlugin
@ -202,6 +203,25 @@ namespace OpenSim.Region.Physics.OdePlugin
m_name = avName;
}
public override void RequestPhysicsterseUpdate()
{
if (PhysEngineToSceneConnectorModule.IsPhysEngineActorS)
{
// if the values have changed and it was I who changed them, send an update
// if (this.lastValues.Changed(this) && ChangingActorID == RegionSyncServerModule.ActorID)
if (ChangingActorID == RegionSyncServerModule.ActorID)
{
// m_log.DebugFormat("[ODE CHARACTER]: Sending terse update for {0}", LocalID);
ChangingActorID = "XXX"; // it's been sent. I am not changing it.
PhysEngineToSceneConnectorModule.RouteUpdate(this);
}
}
else
{
base.RequestPhysicsterseUpdate();
}
}
public override int PhysicsActorType
{
get { return (int) ActorTypes.Agent; }
@ -220,6 +240,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public override uint LocalID
{
set { m_localID = value; }
get { return m_localID; }
}
public override bool Grabbed
@ -408,6 +429,7 @@ namespace OpenSim.Region.Physics.OdePlugin
get { return _position; }
set
{
base.ChangingActorID = RegionSyncServerModule.ActorID;
if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
{
if (value.IsFinite())
@ -453,6 +475,7 @@ namespace OpenSim.Region.Physics.OdePlugin
get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
set
{
base.ChangingActorID = RegionSyncServerModule.ActorID;
if (value.IsFinite())
{
m_pidControllerActive = true;
@ -774,6 +797,13 @@ namespace OpenSim.Region.Physics.OdePlugin
{
m_pidControllerActive = true;
_target_velocity = value;
if (_target_velocity.X == 0 && _target_velocity.Y == 0 && _target_velocity.Z == 0)
{
// if stopping, force real velocity to zero
_velocity = Vector3.Zero;
// m_log.DebugFormat("{0}: Set velocity {1}", "[PHYSICS]", _target_velocity); // RADEBUG
}
base.ChangingActorID = RegionSyncServerModule.ActorID;
}
else
{
@ -813,6 +843,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public override Vector3 Acceleration
{
get { return _acceleration; }
set { _acceleration = value; }
}
public void SetAcceleration(Vector3 accel)
@ -830,6 +861,7 @@ namespace OpenSim.Region.Physics.OdePlugin
{
if (force.IsFinite())
{
base.ChangingActorID = RegionSyncServerModule.ActorID;
if (pushforce)
{
m_pidControllerActive = false;
@ -906,10 +938,9 @@ namespace OpenSim.Region.Physics.OdePlugin
d.Vector3 localpos = d.BodyGetPosition(Body);
Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);
if (!localPos.IsFinite())
if (!localPos.IsFinite() || localpos.X < 0.0 || localpos.X > 256.0 || localpos.Y < 0.0 || localpos.Y > 256.0 || localpos.Z < 0.0)
{
m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
m_log.Warn("[PHYSICS]: Avatar Position is non-finite or out of bounds!");
defects.Add(this);
// _parent_scene.RemoveCharacter(this);
@ -960,10 +991,12 @@ namespace OpenSim.Region.Physics.OdePlugin
if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
{
// keep track of where we stopped. No more slippin' & slidin'
// m_log.DebugFormat("[PHYSICS]: Move setting zero. zeroFlag={0}, pidControllerActive={1}", _zeroFlag, m_pidControllerActive); // RADEBUG
if (!_zeroFlag)
{
_zeroFlag = true;
_zeroPosition = d.BodyGetPosition(Body);
_velocity = _target_velocity;
}
if (m_pidControllerActive)
{
@ -1141,13 +1174,15 @@ namespace OpenSim.Region.Physics.OdePlugin
_velocity.Y = 0.0f;
_velocity.Z = 0.0f;
/*
// Did we send out the 'stopped' message?
if (!m_lastUpdateSent)
{
m_lastUpdateSent = true;
//base.RequestPhysicsterseUpdate();
this.RequestPhysicsterseUpdate();
}
*/
}
else
{
@ -1183,6 +1218,12 @@ namespace OpenSim.Region.Physics.OdePlugin
m_hackSentFall = false;
}
}
if (!m_lastUpdateSent)
{
m_lastUpdateSent = true;
ChangingActorID = RegionSyncServerModule.ActorID;
this.RequestPhysicsterseUpdate();
}
}
/// <summary>
@ -1349,7 +1390,8 @@ namespace OpenSim.Region.Physics.OdePlugin
_position.Z = m_taintPosition.Z;
}
}
ChangingActorID = RegionSyncServerModule.ActorID;
this.RequestPhysicsterseUpdate();
}
internal void AddCollisionFrameTime(int p)

View File

@ -50,7 +50,9 @@ using log4net;
using OpenMetaverse;
using Ode.NET;
using OpenSim.Framework;
using OpenSim.Region.Framework;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
namespace OpenSim.Region.Physics.OdePlugin
{
@ -253,6 +255,8 @@ namespace OpenSim.Region.Physics.OdePlugin
m_taintadd = true;
_parent_scene.AddPhysicsActorTaint(this);
// don't do .add() here; old geoms get recycled with the same hash
// m_log.DebugFormat("[PHYSICS] Created ODEPrim: n={0}, m={1}, pbs={2}, phys={3}",
// primName, mesh == null ? "NULL" : "DEFINED", pbs == null ? "NULL" : "DEFINED", pisPhysical);
}
public override int PhysicsActorType
@ -272,6 +276,7 @@ namespace OpenSim.Region.Physics.OdePlugin
set {
//m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
m_localID = value; }
get { return m_localID; }
}
public override bool Grabbed
@ -2467,6 +2472,7 @@ Console.WriteLine("changeshape not need meshing");
public override Vector3 Acceleration
{
get { return _acceleration; }
set { _acceleration = value; }
}
@ -2622,7 +2628,7 @@ Console.WriteLine("changeshape not need meshing");
_position = l_position;
//_parent_scene.remActivePrim(this);
if (_parent == null)
base.RequestPhysicsterseUpdate();
this.RequestPhysicsterseUpdate();
return;
}
else
@ -2657,7 +2663,7 @@ Console.WriteLine("changeshape not need meshing");
m_rotationalVelocity.Z = 0;
if (_parent == null)
base.RequestPhysicsterseUpdate();
this.RequestPhysicsterseUpdate();
m_throttleUpdates = false;
throttleCounter = 0;
@ -2710,7 +2716,7 @@ Console.WriteLine("changeshape not need meshing");
if (_parent == null)
{
base.RequestPhysicsterseUpdate();
this.RequestPhysicsterseUpdate();
}
m_lastUpdateSent = true;
@ -2722,7 +2728,7 @@ Console.WriteLine("changeshape not need meshing");
{
if (_parent == null)
{
base.RequestPhysicsterseUpdate();
this.RequestPhysicsterseUpdate();
}
}
@ -2757,7 +2763,7 @@ Console.WriteLine("changeshape not need meshing");
{
if (_parent == null)
{
base.RequestPhysicsterseUpdate();
this.RequestPhysicsterseUpdate();
}
}
else

View File

@ -0,0 +1,313 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
namespace OpenSim.Region.Physics.PEPlugin
{
public class PECharacter : PhysicsActor
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private bool _stopped;
private Vector3 _size;
private PrimitiveBaseShape _pbs;
private uint _localID = 0;
private bool _grabbed;
private bool _selected;
private Vector3 _position;
private float _mass = 80f;
public float _density = 60f;
public float CAPSULE_RADIUS = 0.37f;
public float CAPSULE_LENGTH = 2.140599f;
private Vector3 _force;
private Vector3 _velocity;
private Vector3 _torque;
private float _collisionScore;
private Vector3 _acceleration;
private Quaternion _orientation;
private int _physicsActorType;
private bool _isPhysical;
private bool _flying;
private bool _setAlwaysRun;
private bool _throttleUpdates;
private bool _isColliding;
private bool _collidingGround;
private bool _collidingObj;
private bool _floatOnWater;
private Vector3 _rotationalVelocity;
private bool _kinematic;
private float _buoyancy;
private Vector3 _PIDTarget;
private bool _usePID;
private float _PIDTau;
private bool _useHoverPID;
private float _PIDHoverHeight;
private PIDHoverType _PIDHoverType;
private float _PIDHoverTao;
public PECharacter(String avName, PEScene parent_scene, Vector3 pos,
CollisionLocker dode, Vector3 size, float pid_d, float pid_p,
float capsule_radius, float tensor, float density, float height_fudge_factor,
float walk_divisor, float rundivisor)
{
_position = pos;
_size = size;
_density = density;
base.ChangingActorID = RegionSyncServerModule.ActorID;
return;
}
public override void RequestPhysicsterseUpdate()
{
if (PhysEngineToSceneConnectorModule.IsPhysEngineActorS)
{
// if the values have changed and it was I who changed them, send an update
if (this.lastValues.Changed(this) && ChangingActorID == RegionSyncServerModule.ActorID)
{
// m_log.DebugFormat("[ODE CHARACTER]: Sending terse update for {0}", LocalID);
PhysEngineToSceneConnectorModule.RouteUpdate(this);
}
}
else
{
base.RequestPhysicsterseUpdate();
}
}
public override bool Stopped {
get { return _stopped; }
}
public override Vector3 Size {
get { return _size; }
set { _size = value;
}
}
public override PrimitiveBaseShape Shape {
set { _pbs = value;
}
}
public override uint LocalID {
set { _localID = value;
}
get { return _localID; }
}
public override bool Grabbed {
set { _grabbed = value;
// m_log.Debug("[RPE] PEChar set Grabbed");
}
}
public override bool Selected {
set { _selected = value;
// m_log.Debug("[RPE] PEChar set Selected");
}
}
public override void CrossingFailure() { return; }
public override void link(PhysicsActor obj) { return; }
public override void delink() { return; }
public override void LockAngularMotion(Vector3 axis) { return; }
public override Vector3 Position {
get { return _position; }
set { _position = value;
base.ChangingActorID = RegionSyncServerModule.ActorID;
}
}
public override float Mass {
get {
float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH);
_mass = _density*AVvolume;
return _mass;
}
}
public override Vector3 Force {
get { return _force; }
set { _force = value;
base.ChangingActorID = RegionSyncServerModule.ActorID;
}
}
public override int VehicleType {
get { return 0; }
set { return; }
}
public override void VehicleFloatParam(int param, float value) { }
public override void VehicleVectorParam(int param, Vector3 value) {}
public override void VehicleRotationParam(int param, Quaternion rotation) { }
public override void VehicleFlags(int param, bool remove) { }
// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
public override void SetVolumeDetect(int param) { return; }
public override Vector3 GeometricCenter { get { return Vector3.Zero; } }
public override Vector3 CenterOfMass { get { return Vector3.Zero; } }
public override Vector3 Velocity {
get { return _velocity; }
set { _velocity = value;
base.ChangingActorID = RegionSyncServerModule.ActorID;
}
}
public override Vector3 Torque {
get { return _torque; }
set { _torque = value;
}
}
public override float CollisionScore {
get { return _collisionScore; }
set { _collisionScore = value;
}
}
public override Vector3 Acceleration {
get { return _acceleration; }
}
public override Quaternion Orientation {
get { return _orientation; }
set { _orientation = value;
base.ChangingActorID = RegionSyncServerModule.ActorID;
}
}
public override int PhysicsActorType {
get { return _physicsActorType; }
set { _physicsActorType = value;
}
}
public override bool IsPhysical {
get { return _isPhysical; }
set { _isPhysical = value;
}
}
public override bool Flying {
get { return _flying; }
set { _flying = value;
}
}
public override bool
SetAlwaysRun {
get { return _setAlwaysRun; }
set { _setAlwaysRun = value; }
}
public override bool ThrottleUpdates {
get { return _throttleUpdates; }
set { _throttleUpdates = value; }
}
public override bool IsColliding {
get { return _isColliding; }
set { _isColliding = value; }
}
public override bool CollidingGround {
get { return _collidingGround; }
set { _collidingGround = value; }
}
public override bool CollidingObj {
get { return _collidingObj; }
set { _collidingObj = value; }
}
public override bool FloatOnWater {
set { _floatOnWater = value; }
}
public override Vector3 RotationalVelocity {
get { return _rotationalVelocity; }
set { _rotationalVelocity = value; }
}
public override bool Kinematic {
get { return _kinematic; }
set { _kinematic = value; }
}
public override float Buoyancy {
get { return _buoyancy; }
set { _buoyancy = value; }
}
// Used for MoveTo
public override Vector3 PIDTarget {
set { _PIDTarget = value; }
}
public override bool PIDActive {
set { _usePID = value; }
}
public override float PIDTau {
set { _PIDTau = value; }
}
// Used for llSetHoverHeight and maybe vehicle height
// Hover Height will override MoveTo target's Z
public override bool PIDHoverActive {
set { _useHoverPID = value; }
}
public override float PIDHoverHeight {
set { _PIDHoverHeight = value; }
}
public override PIDHoverType PIDHoverType {
set { _PIDHoverType = value; }
}
public override float PIDHoverTau {
set { _PIDHoverTao = value; }
}
// For RotLookAt
public override Quaternion APIDTarget { set { return; } }
public override bool APIDActive { set { return; } }
public override float APIDStrength { set { return; } }
public override float APIDDamping { set { return; } }
public override void AddForce(Vector3 force, bool pushforce) {
if (force.IsFinite())
{
// base.ChangingActorID = RegionSyncServerModule.ActorID;
_velocity.X += force.X;
_velocity.Y += force.Y;
_velocity.Z += force.Z;
}
else
{
m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
}
//m_lastUpdateSent = false;
}
public override void AddAngularForce(Vector3 force, bool pushforce) {
}
public override void SetMomentum(Vector3 momentum) {
}
public override void SubscribeEvents(int ms) {
}
public override void UnSubscribeEvents() {
}
public override bool SubscribedEvents() {
return false;
}
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenMetaverse;
namespace OpenSim.Region.Physics.PEPlugin
{
public class PEPlugin : IPhysicsPlugin
{
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private PEScene _mScene;
public PEPlugin()
{
}
public bool Init()
{
return true;
}
public PhysicsScene GetScene(String sceneIdentifier)
{
if (_mScene == null)
{
_mScene = new PEScene(sceneIdentifier);
}
return (_mScene);
}
public string GetName()
{
return ("RemotePhysicsEngine");
}
public void Dispose()
{
}
}
}

View File

@ -0,0 +1,287 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Xml;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
namespace OpenSim.Region.Physics.PEPlugin
{
[Serializable]
public sealed class PEPrim : PhysicsActor
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private bool _stopped;
private Vector3 _size;
private PrimitiveBaseShape _pbs;
private uint _localID = 0;
private bool _grabbed;
private bool _selected;
private Vector3 _position;
private float _mass;
private Vector3 _force;
private Vector3 _velocity;
private Vector3 _torque;
private float _collisionScore;
private Vector3 _acceleration;
private Quaternion _orientation;
private int _physicsActorType;
private bool _isPhysical;
private bool _flying;
private bool _setAlwaysRun;
private bool _throttleUpdates;
private bool _isColliding;
private bool _collidingGround;
private bool _collidingObj;
private bool _floatOnWater;
private Vector3 _rotationalVelocity;
private bool _kinematic;
private float _buoyancy;
private Vector3 _PIDTarget;
private bool _usePID;
private float _PIDTau;
private bool _useHoverPID;
private float _PIDHoverHeight;
private PIDHoverType _PIDHoverType;
private float _PIDHoverTao;
public PEPrim(String primName, PEScene parent_scene, Vector3 pos, Vector3 size,
Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
{
_position = pos;
_size = size;
_orientation = rotation;
// m_log.DebugFormat("[REMOTE PRIM ENGINE] PEPrim creation of {0}", primName);
}
public override bool Stopped {
get { return _stopped; }
}
public override Vector3 Size {
get { return _size; }
set { _size = value;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Size");
// SyncUpdated = true;
}
}
public override PrimitiveBaseShape Shape {
set { _pbs = value;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Shape");
// SyncUpdated = true;
}
}
public override uint LocalID {
set { _localID = value;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set LocalID");
// SyncUpdated = true;
}
get { return _localID; }
}
public override bool Grabbed {
set { _grabbed = value;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Grabbed");
}
}
public override bool Selected {
set { _selected = value;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Selected");
}
}
public override void CrossingFailure() { return; }
public override void link(PhysicsActor obj) { return; }
public override void delink() { return; }
public override void LockAngularMotion(Vector3 axis) { return; }
public override Vector3 Position {
get { return _position; }
set { _position = value;
// SyncUpdated = true;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Position");
}
}
public override float Mass {
get { return _mass; }
}
public override Vector3 Force {
get { return _force; }
set { _force = value;
// SyncUpdated = true;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Force");
}
}
public override int VehicleType {
get { return 0; }
set { return; }
}
public override void VehicleFloatParam(int param, float value) { }
public override void VehicleVectorParam(int param, Vector3 value) {}
public override void VehicleRotationParam(int param, Quaternion rotation) { }
public override void VehicleFlags(int param, bool remove) { }
// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
public override void SetVolumeDetect(int param) { return; }
public override Vector3 GeometricCenter { get { return Vector3.Zero; } }
public override Vector3 CenterOfMass { get { return Vector3.Zero; } }
public override Vector3 Velocity {
get { return _velocity; }
set { _velocity = value;
// SyncUpdated = true;
}
}
public override Vector3 Torque {
get { return _torque; }
set { _torque = value;
// SyncUpdated = true;
}
}
public override float CollisionScore {
get { return _collisionScore; }
set { _collisionScore = value;
// SyncUpdated = true;
}
}
public override Vector3 Acceleration {
get { return _acceleration; }
}
public override Quaternion Orientation {
get { return _orientation; }
set { _orientation = value;
// SyncUpdated = true;
}
}
public override int PhysicsActorType {
get { return _physicsActorType; }
set { _physicsActorType = value;
// SyncUpdated = true;
}
}
public override bool IsPhysical {
get { return _isPhysical; }
set { _isPhysical = value;
// SyncUpdated = true;
}
}
public override bool Flying {
get { return _flying; }
set { _flying = value;
// SyncUpdated = true;
}
}
public override bool
SetAlwaysRun {
get { return _setAlwaysRun; }
set { _setAlwaysRun = value; }
}
public override bool ThrottleUpdates {
get { return _throttleUpdates; }
set { _throttleUpdates = value; }
}
public override bool IsColliding {
get { return _isColliding; }
set { _isColliding = value; }
}
public override bool CollidingGround {
get { return _collidingGround; }
set { _collidingGround = value; }
}
public override bool CollidingObj {
get { return _collidingObj; }
set { _collidingObj = value; }
}
public override bool FloatOnWater {
set { _floatOnWater = value; }
}
public override Vector3 RotationalVelocity {
get { return _rotationalVelocity; }
set { _rotationalVelocity = value; }
}
public override bool Kinematic {
get { return _kinematic; }
set { _kinematic = value; }
}
public override float Buoyancy {
get { return _buoyancy; }
set { _buoyancy = value; }
}
// Used for MoveTo
public override Vector3 PIDTarget {
set { _PIDTarget = value; }
}
public override bool PIDActive {
set { _usePID = value; }
}
public override float PIDTau {
set { _PIDTau = value; }
}
// Used for llSetHoverHeight and maybe vehicle height
// Hover Height will override MoveTo target's Z
public override bool PIDHoverActive {
set { _useHoverPID = value; }
}
public override float PIDHoverHeight {
set { _PIDHoverHeight = value; }
}
public override PIDHoverType PIDHoverType {
set { _PIDHoverType = value; }
}
public override float PIDHoverTau {
set { _PIDHoverTao = value; }
}
// For RotLookAt
public override Quaternion APIDTarget { set { return; } }
public override bool APIDActive { set { return; } }
public override float APIDStrength { set { return; } }
public override float APIDDamping { set { return; } }
public override void AddForce(Vector3 force, bool pushforce) {
}
public override void AddAngularForce(Vector3 force, bool pushforce) {
}
public override void SetMomentum(Vector3 momentum) {
}
public override void SubscribeEvents(int ms) {
}
public override void UnSubscribeEvents() {
}
public override bool SubscribedEvents() {
return false;
}
}
}

View File

@ -0,0 +1,210 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using Nini.Config;
using log4net;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenMetaverse;
using OpenSim.Region.Framework;
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
namespace OpenSim.Region.Physics.PEPlugin
{
public class PEScene : PhysicsScene
{
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private List<PECharacter> m_avatars = new List<PECharacter>();
private List<PEPrim> m_prims = new List<PEPrim>();
private float[] m_heightMap;
public PEScene(string identifier)
{
}
public override void Initialise(IMesher meshmerizer, IConfigSource config)
{
}
public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
{
PECharacter actor = new PECharacter(avName, this, position, null, size, 0f, 0f, .5f, 1f,
1f, 1f, .5f, .5f);
lock (m_avatars) m_avatars.Add(actor);
return actor;
}
public override void RemoveAvatar(PhysicsActor actor)
{
try
{
lock (m_avatars) m_avatars.Remove((PECharacter)actor);
}
catch (Exception e)
{
m_log.WarnFormat("[RPE]: Attempt to remove avatar that is not in physics scene: {0}", e);
}
}
public override void RemovePrim(PhysicsActor prim)
{
try
{
lock (m_prims) m_prims.Remove((PEPrim)prim);
}
catch (Exception e)
{
m_log.WarnFormat("[RPE]: Attempt to remove prim that is not in physics scene: {0}", e);
}
}
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
Vector3 size, Quaternion rotation, bool isPhysical, uint localID)
{
PEPrim prim = new PEPrim(primName, this, position, size, rotation, null, pbs, isPhysical, null);
prim.LocalID = localID;
lock (m_prims) m_prims.Add(prim);
return prim;
}
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
public override float Simulate(float timeStep)
{
// if we are a physics engine server, send update information
if (SceneToPhysEngineSyncServer.IsPhysEngineScene2S())
{
if (SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S())
{
// m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count);
/*
lock (m_prims)
{
foreach (PEPrim prim in m_prims)
{
// if the values have changed and it was I who changed them, send an update
if (prim.ChangingActorID == RegionSyncServerModule.ActorID && prim.lastValues.Changed(prim))
{
SceneToPhysEngineSyncServer.RouteUpdate(prim);
}
}
}
*/
lock (m_avatars)
{
foreach (PECharacter actor in m_avatars)
{
// m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count);
// if the values have changed and it was I who changed them, send an update
if (actor.ChangingActorID == RegionSyncServerModule.ActorID && actor.lastValues.Changed(actor))
{
SceneToPhysEngineSyncServer.RouteUpdate(actor);
actor.ChangingActorID = "YY";
}
}
}
}
return 60f;
}
/*
// code borrowed from BasicPhysics to do just avatar movement
foreach (PECharacter actor in m_avatars)
{
Vector3 actorPosition = actor.Position;
Vector3 actorVelocity = actor.Velocity;
actorPosition.X += actor.Velocity.X*timeStep;
actorPosition.Y += actor.Velocity.Y*timeStep;
actorPosition.Y = Math.Max(actorPosition.Y, 0.1f);
actorPosition.Y = Math.Min(actorPosition.Y, Constants.RegionSize - 0.1f);
actorPosition.X = Math.Max(actorPosition.X, 0.1f);
actorPosition.X = Math.Min(actorPosition.X, Constants.RegionSize - 0.1f);
float height = 25.0F;
try
{
height = m_heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z;
}
catch (OverflowException)
{
m_log.WarnFormat("[RPE]: Actor out of range: {0}", actor.SOPName, actor.Position.ToString());
}
if (actor.Flying)
{
if (actor.Position.Z + (actor.Velocity.Z*timeStep) <
m_heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + 2)
{
actorPosition.Z = height;
actorVelocity.Z = 0;
actor.IsColliding = true;
}
else
{
actorPosition.Z += actor.Velocity.Z*timeStep;
actor.IsColliding = false;
}
}
else
{
actorPosition.Z = height;
actorVelocity.Z = 0;
actor.IsColliding = true;
}
actor.Position = actorPosition;
actor.Velocity = actorVelocity;
}
*/
return 60f; // returns frames per second
}
public override void GetResults() { }
public override void SetTerrain(float[] heightMap) {
m_heightMap = heightMap;
}
public override void SetWaterLevel(float baseheight) { }
public override void DeleteTerrain() { }
public override void Dispose() { }
public override Dictionary<uint, float> GetTopColliders()
{
return new Dictionary<uint, float>();
}
public override bool IsThreaded { get { return false; } }
}
}

View File

@ -368,6 +368,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
#region LSL Util functions
// convert a LSL_Rotation to a Quaternion
protected Quaternion Rot2Quaternion(LSL_Rotation r)
{
@ -773,6 +775,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return rotBetween;
}
#endregion //of LSL Util functions
public void llWhisper(int channelID, string text)
{
m_host.AddScriptLPS(1);
@ -1170,6 +1174,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return wind;
}
#region REGION SYNC
//REGION SYNC TOUCHED -- set via sync'ing with remote Scene
public void llSetStatus(int status, int value)
{
m_host.AddScriptLPS(1);
@ -1381,6 +1388,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
tmp.Z = (float)scale.z;
part.Scale = tmp;
part.SendFullUpdateToAllClients();
//DSG SYNC
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.Scale });
}
public LSL_Vector llGetScale()
@ -1394,7 +1404,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
m_host.ClickAction = (byte)action;
if (m_host.ParentGroup != null) m_host.ParentGroup.HasGroupChanged = true;
m_host.ScheduleFullUpdate();
//m_host.ScheduleFullUpdate();
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.ClickAction});
return;
}
@ -1646,7 +1657,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
part.ParentGroup.HasGroupChanged = true;
part.ScheduleFullUpdate();
//part.ScheduleFullUpdate();
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Shape});
}
/// <summary>
@ -1681,7 +1693,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
part.ParentGroup.HasGroupChanged = true;
part.ScheduleFullUpdate();
//part.ScheduleFullUpdate();
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Shape});
}
public LSL_Vector llGetColor(int face)
@ -1913,6 +1926,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
//REGION SYNC TOUCHED -- set via sync'ing with remote Scene -- SetPos is modified.
public void llSetPos(LSL_Vector pos)
{
m_host.AddScriptLPS(1);
@ -1932,6 +1946,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return end;
}
//REGION SYNC TOUCHED -- set via sync'ing with remote Scene
protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
{
// Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
@ -1954,7 +1969,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z);
SceneObjectGroup parent = part.ParentGroup;
parent.HasGroupChanged = true;
parent.ScheduleGroupForTerseUpdate();
//parent.ScheduleGroupForTerseUpdate();
parent.ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.OffsetPosition});
}
}
@ -2313,7 +2329,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.SoundFlags = 1; // looping
m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
m_host.ScheduleFullUpdate();
//m_host.ScheduleFullUpdate();
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Sound});
m_host.SendFullUpdateToAllClients();
}
@ -2333,7 +2350,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
prim.SoundFlags = 1; // looping
prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
prim.ScheduleFullUpdate();
//prim.ScheduleFullUpdate();
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Sound});
prim.SendFullUpdateToAllClients();
}
}
@ -2345,7 +2363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.SoundFlags = 1; // looping
m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
m_host.ScheduleFullUpdate();
//m_host.ScheduleFullUpdate();
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Sound});
m_host.SendFullUpdateToAllClients();
}
@ -2387,7 +2406,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.SoundGain = 0;
part.SoundFlags = 0;
part.SoundRadius = 0;
part.ScheduleFullUpdate();
//part.ScheduleFullUpdate();
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Sound});
part.SendFullUpdateToAllClients();
}
m_host.ParentGroup.LoopSoundMasterPrim = null;
@ -2399,7 +2419,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.SoundGain = 0;
m_host.SoundFlags = 0;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
//m_host.ScheduleFullUpdate();
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Sound});
m_host.SendFullUpdateToAllClients();
}
}
@ -2409,7 +2430,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.SoundGain = 0;
m_host.SoundFlags = 0;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
//m_host.ScheduleFullUpdate();
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Sound});
m_host.SendFullUpdateToAllClients();
}
}
@ -2796,6 +2818,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
llSay(0, "Could not find object " + inventory);
}
public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
{
llRezAtRoot(inventory, pos, vel, rot, param);
@ -3314,7 +3337,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
m_host.AngularVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
m_host.ScheduleTerseUpdate();
//m_host.ScheduleTerseUpdate();
m_host.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.AngularVelocity });
m_host.SendTerseUpdateToAllClients();
m_host.ParentGroup.HasGroupChanged = true;
}
@ -3344,8 +3368,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
item = m_host.TaskInventory[invItemID];
}
if (agentID == UUID.Zero || perm == 0) // Releasing permissions
{
//if (agentID == UUID.Zero || perm == 0) // Releasing permissions
//{
llReleaseControls();
item.PermsGranter = UUID.Zero;
@ -3357,7 +3381,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
new DetectParams[0]));
return;
}
//}
if (item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
llReleaseControls();
@ -3567,6 +3591,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; // Fail silently if attached
SceneObjectGroup parentPrim = null, childPrim = null;
//SYEMMETRIC SYNC
List<SceneObjectPart> children = new List<SceneObjectPart>();
if (targetPart != null)
{
if (parent != 0) {
@ -3578,6 +3605,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parentPrim = targetPart.ParentGroup;
childPrim = m_host.ParentGroup;
}
children.Add(childPrim.RootPart);
// byte uf = childPrim.RootPart.UpdateFlag;
childPrim.RootPart.UpdateFlag = 0;
parentPrim.LinkToGroup(childPrim);
@ -3588,7 +3617,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
parentPrim.RootPart.CreateSelected = true;
parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate();
//parentPrim.ScheduleGroupForFullUpdate();
//DSG SYNC
//Schedule a LinkObject message for synchronization purpose. This will lead to enqueue a LinkObject message in SyncConnector's outgoingQueue,
//so should return quickly.
if (World.RegionSyncModule != null)
{
//Tell other actors to link the SceneObjectParts together as a new group.
//parentGroup.SyncInfoUpdate();
//World.RegionSyncModule.SendLinkObject(parentPrim, parentPrim.RootPart, children);
World.RegionSyncModule.SyncLinkObject(parentPrim, parentPrim.RootPart, children);
}
m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.None }); //SyncLinkObject above will synchronize the link operation, no need to taint updates here
//end of DSG SYNC
if (client != null)
parentPrim.GetProperties(client);
@ -3646,15 +3687,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (linknum == ScriptBaseClass.LINK_ROOT)
{
//DSG SYNC
List<SceneObjectGroup> beforeDelinkGroups = new List<SceneObjectGroup>();
beforeDelinkGroups.Add(parentPrim);
List<SceneObjectGroup> afterDelinkGroups = new List<SceneObjectGroup>();
//end of DSG SYNC
// Restructuring Multiple Prims.
List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
parts.Remove(parentPrim.RootPart);
foreach (SceneObjectPart part in parts)
{
parentPrim.DelinkFromGroup(part.LocalId, true);
//DSG SYNC
afterDelinkGroups.Add(part.ParentGroup);
}
parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate();
//parentPrim.ScheduleGroupForFullUpdate();
//DSG SYNC
//Send out DelinkObject message to other actors to sychronize their object list
if (World.RegionSyncModule != null)
{
World.RegionSyncModule.SyncDeLinkObject(parts, beforeDelinkGroups, afterDelinkGroups);
}
parentPrim.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.None});
//end of DSG SYNC
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
if (parts.Count > 0)
@ -3667,7 +3724,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
}
newRoot.ParentGroup.HasGroupChanged = true;
newRoot.ParentGroup.ScheduleGroupForFullUpdate();
//newRoot.ParentGroup.ScheduleGroupForFullUpdate();
//DSG SYNC
if (World.RegionSyncModule != null)
{
//World.RegionSyncModule.SendLinkObject(newRoot.ParentGroup, newRoot, new List<SceneObjectPart>(newRoot.ParentGroup.Parts));
World.RegionSyncModule.SyncLinkObject(newRoot.ParentGroup, newRoot, new List<SceneObjectPart>(newRoot.ParentGroup.Parts));
}
newRoot.ParentGroup.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.None});
//end of DSG SYNC
}
}
else
@ -3677,7 +3743,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parentPrim.DelinkFromGroup(childPrim.LocalId, true);
parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate();
//parentPrim.ScheduleGroupForFullUpdate();
//DSG SYNC
//Send out DelinkObject message to other actors to sychronize their object list
if (World.RegionSyncModule != null)
{
List<SceneObjectGroup> beforeDelinkGroups = new List<SceneObjectGroup>();
beforeDelinkGroups.Add(parentPrim);
List<SceneObjectGroup> afterDelinkGroups = new List<SceneObjectGroup>();
afterDelinkGroups.Add(childPrim.ParentGroup);
World.RegionSyncModule.SyncDeLinkObject(new List<SceneObjectPart>(parentPrim.Parts), beforeDelinkGroups, afterDelinkGroups);
}
//end of DSG SYNC
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
}
}
@ -3689,6 +3767,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (parentPrim.RootPart.AttachmentPoint != 0)
return; // Fail silently if attached
//DSG SYNC
List<SceneObjectGroup> beforeDelinkGroups = new List<SceneObjectGroup>();
beforeDelinkGroups.Add(parentPrim);
List<SceneObjectGroup> afterDelinkGroups = new List<SceneObjectGroup>();
SceneObjectPart rootPart = parentPrim.RootPart;
//end of DSG SYNC
List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
parts.Remove(parentPrim.RootPart);
@ -3696,9 +3781,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
parentPrim.DelinkFromGroup(part.LocalId, true);
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
//DSG SYNC
afterDelinkGroups.Add(part.ParentGroup);
}
parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate();
//parentPrim.ScheduleGroupForFullUpdate();
//SYMMETRIC SYNCF
if (World.RegionSyncModule != null)
{
parts.Add(rootPart);
afterDelinkGroups.Add(rootPart.ParentGroup);
World.RegionSyncModule.SyncDeLinkObject(parts, beforeDelinkGroups, afterDelinkGroups);
}
parentPrim.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.None});
//end of DSG SYNC
}
public LSL_String llGetLinkKey(int linknum)
@ -3950,7 +4046,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
Util.Clip((float)color.z, 0.0f, 1.0f));
m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
m_host.ParentGroup.HasGroupChanged = true;
m_host.ParentGroup.ScheduleGroupForFullUpdate();
//m_host.ParentGroup.ScheduleGroupForFullUpdate();
m_host.ParentGroup.ScheduleGroupForFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Text});
}
public LSL_Float llWater(LSL_Vector offset)
@ -5343,6 +5440,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
m_host.Name = name!=null?name:String.Empty;
//DSG SYNC
//m_host.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.Name });
m_host.ScheduleSyncUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.Name });
}
public LSL_String llGetDate()
@ -5606,6 +5707,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.AddTextureAnimation(pTexAnim);
part.SendFullUpdateToAllClients();
part.ParentGroup.HasGroupChanged = true;
//DSG SYNC
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.TextureAnimation });
}
public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east,
@ -6118,6 +6222,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.ParentGroup.HasGroupChanged = true;
}
part.SendFullUpdateToAllClients();
//DSG SYNC
part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { SceneObjectPartSyncProperties.ParticleSystem });
}
public void llGroundRepel(double height, int water, double tau)
@ -6587,6 +6694,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return Util.SHA1Hash(src).ToLower();
}
#endregion REGION SYNC
protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
{
ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();

View File

@ -2346,7 +2346,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
obj.ParentGroup.HasGroupChanged = true;
obj.ScheduleFullUpdate();
//obj.ScheduleFullUpdate();
obj.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Shape});
}

View File

@ -51,6 +51,8 @@ using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.Region.ScriptEngine.Shared.CodeTools;
using OpenSim.Region.ScriptEngine.Interfaces;
using log4net;
namespace OpenSim.Region.ScriptEngine.Shared.Instance
{
public class ScriptInstance : MarshalByRefObject, IScriptInstance
@ -214,12 +216,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
get { return m_thisScriptTask; }
}
private ILog m_log;
public ScriptInstance(IScriptEngine engine, SceneObjectPart part,
UUID itemID, UUID assetID, string assembly,
AppDomain dom, string primName, string scriptName,
int startParam, bool postOnRez, StateSource stateSource,
int maxScriptQueue)
{
//Kitty: temp debug
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
m_Engine = engine;
m_LocalID = part.LocalId;
@ -647,6 +654,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
if (m_Suspended)
return 0;
lock (m_Script)
{
EventParams data = null;
@ -667,6 +675,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
return 0;
}
//m_log.DebugFormat("[Script] processing event {2} in state {3} to {0}.{1}, localID-{4}", m_PrimName, m_ScriptName, data.EventName, m_State, m_LocalID);
if (data.EventName == "timer")
m_TimerQueued = false;
if (data.EventName == "control")
@ -705,8 +716,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
{
SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
m_LocalID);
// m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
// m_PrimName, m_ScriptName, data.EventName, m_State);
try
{
@ -732,7 +741,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
}
catch (Exception e)
{
// m_log.DebugFormat("[SCRIPT] Exception: {0}", e.Message);
m_log.DebugFormat("[SCRIPT] Exception: {0}", e.Message);
m_InEvent = false;
m_CurrentEvent = String.Empty;
@ -779,6 +788,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
}
}
//m_log.DebugFormat("[Script] processing event {2} in state {3} to {0}.{1}, localID -{4}; to trigger QueueEventHandler", m_PrimName, m_ScriptName, data.EventName, m_State, m_LocalID);
lock (m_EventQueue)
{
if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown))

View File

@ -328,6 +328,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
m_Scene.EventManager.OnGetScriptRunning += OnGetScriptRunning;
m_Scene.EventManager.OnShutdown += OnShutdown;
//REGION SYNC events
m_Scene.EventManager.OnScriptEngineSyncStop += OnScriptEngineSyncStop;
//end REGION SYNC
if (m_SleepTime > 0)
{
m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance),
@ -591,7 +595,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
if (part == null)
{
m_log.Error("[Script] SceneObjectPart unavailable. Script NOT started.");
m_log.Error("[Script] SceneObjectPart unavailable. Script NOT started."+" localID = "+localID);
m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n";
m_ScriptFailCount++;
return false;
@ -1620,5 +1624,57 @@ namespace OpenSim.Region.ScriptEngine.XEngine
instance.Resume();
}
#region REGION SYNC functions
//eventually triggered when user typed "sync stop" at the script engine's console
public void OnScriptEngineSyncStop()
{
//DoBackup();
//save the script states, stop script instances, and clear records
//similar to RemoveRegion(), except that still keep the engine in
//m_scriptEngines.
lock (m_Scripts)
{
foreach (IScriptInstance instance in m_Scripts.Values)
{
// Force a final state save
//
if (m_Assemblies.ContainsKey(instance.AssetID))
{
string assembly = m_Assemblies[instance.AssetID];
instance.SaveState(assembly);
}
// Clear the event queue and abort the instance thread
//
instance.ClearQueue();
instance.Stop(0);
// Release events, timer, etc
//
instance.DestroyScriptInstance();
// Unload scripts and app domains
// Must be done explicitly because they have infinite
// lifetime
//
m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
if (m_DomainScripts[instance.AppDomain].Count == 0)
{
m_DomainScripts.Remove(instance.AppDomain);
UnloadAppDomain(instance.AppDomain);
}
}
m_Scripts.Clear();
m_PrimObjects.Clear();
m_Assemblies.Clear();
m_DomainScripts.Clear();
}
}
#endregion
}
}

Some files were not shown because too many files have changed in this diff Show More